package handler import ( "accounting-app/internal/models" "accounting-app/internal/service" "accounting-app/pkg/api" "net/http" "strconv" "github.com/gin-gonic/gin" ) type NotificationHandler struct { service *service.NotificationService } func NewNotificationHandler(service *service.NotificationService) *NotificationHandler { return &NotificationHandler{service: service} } // GetNotifications returns a list of notifications for the user func (h *NotificationHandler) GetNotifications(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { api.Unauthorized(c, "User not authenticated") return } page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10")) var isRead *bool if val, ok := c.GetQuery("is_read"); ok { parsedVal, err := strconv.ParseBool(val) if err == nil { isRead = &parsedVal } } notifications, total, err := h.service.GetNotifications(userID.(uint), page, limit, isRead) if err != nil { api.Error(c, http.StatusInternalServerError, "FETCH_ERROR", "Failed to fetch notifications") return } api.Success(c, gin.H{ "notifications": notifications, "total": total, "page": page, "limit": limit, }) } // GetUnreadCount returns the number of unread notifications func (h *NotificationHandler) GetUnreadCount(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { api.Unauthorized(c, "User not authenticated") return } count, err := h.service.GetUnreadCount(userID.(uint)) if err != nil { api.Error(c, http.StatusInternalServerError, "FETCH_ERROR", "Failed to count unread notifications") return } api.Success(c, gin.H{ "count": count, }) } // MarkAsRead marks a specific notification as read func (h *NotificationHandler) MarkAsRead(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { api.Unauthorized(c, "User not authenticated") return } id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { api.Error(c, http.StatusBadRequest, "INVALID_ID", "Invalid notification ID") return } if err := h.service.MarkAsRead(uint(id), userID.(uint)); err != nil { api.Error(c, http.StatusInternalServerError, "UPDATE_ERROR", "Failed to mark as read") return } api.Success(c, gin.H{"message": "Marked as read"}) } // MarkAllAsRead marks all notifications as read func (h *NotificationHandler) MarkAllAsRead(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { api.Unauthorized(c, "User not authenticated") return } if err := h.service.MarkAllAsRead(userID.(uint)); err != nil { api.Error(c, http.StatusInternalServerError, "UPDATE_ERROR", "Failed to mark all as read") return } api.Success(c, gin.H{"message": "All marked as read"}) } // CreateNotificationRequest represents the request body for creating a notification (internal/admin use primarily) type CreateNotificationRequest struct { Title string `json:"title" binding:"required"` Content string `json:"content" binding:"required"` Type string `json:"type" binding:"required"` Link string `json:"link"` } // CreateNotification creates a new notification (For testing/admin purposes) func (h *NotificationHandler) CreateNotification(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { api.Unauthorized(c, "User not authenticated") return } var req CreateNotificationRequest if err := c.ShouldBindJSON(&req); err != nil { api.Error(c, http.StatusBadRequest, "INVALID_REQUEST", "Invalid request") return } err := h.service.CreateNotification( userID.(uint), req.Title, req.Content, models.NotificationType(req.Type), req.Link, ) if err != nil { api.Error(c, http.StatusInternalServerError, "CREATE_ERROR", "Failed to create notification") return } api.Success(c, gin.H{"message": "Notification created"}) } // RegisterRoutes registers the notification routes func (h *NotificationHandler) RegisterRoutes(r *gin.RouterGroup) { notifications := r.Group("/notifications") { notifications.GET("", h.GetNotifications) notifications.GET("/unread-count", h.GetUnreadCount) notifications.PUT("/:id/read", h.MarkAsRead) notifications.PUT("/read-all", h.MarkAllAsRead) notifications.POST("", h.CreateNotification) // Admin/Internal use } }