diff --git a/internal/domain/messages/domain.go b/internal/domain/messages/domain.go index 2ae6554..2a61bed 100644 --- a/internal/domain/messages/domain.go +++ b/internal/domain/messages/domain.go @@ -19,8 +19,7 @@ type MessageService interface { GetByID(userID, id int64) (*Message, error) Create(userID int64, in CreateMessageInput) (int64, error) Archive(userID, id int64) error - //Restore() - //ToDo: implement Unarchive(userID, id int64) error - //MarkRead(userID, id int64) error + MarkRead(userID, id int64) error + //MarkUnread(userID, id int64) error } diff --git a/internal/handlers/account/messages/read.go b/internal/handlers/account/messages/read.go index 6c9ef0c..87da355 100644 --- a/internal/handlers/account/messages/read.go +++ b/internal/handlers/account/messages/read.go @@ -7,6 +7,7 @@ package accountMessageHandler import ( "bytes" + "database/sql" "net/http" "strconv" @@ -137,3 +138,36 @@ func (h *AccountMessageHandlers) ReadGet(c *gin.Context) { } c.Data(http.StatusOK, "text/html; charset=utf-8", buf.Bytes()) } + +func (h *AccountMessageHandlers) MarkReadPost(c *gin.Context) { + app := c.MustGet("app").(*bootstrap.App) + sm := app.SessionManager + userID := mustUserID(c) + + idStr := c.PostForm("id") + id, err := strconv.ParseInt(idStr, 10, 64) + if err != nil || id <= 0 { + sm.Put(c.Request.Context(), "flash", "Invalid message id.") + c.Redirect(http.StatusSeeOther, c.Request.Referer()) // back to where they came from + return + } + + if err := h.Svc.MarkRead(userID, id); err != nil { + logging.Info("❌ MarkRead error: %v", err) + if err == sql.ErrNoRows { + sm.Put(c.Request.Context(), "flash", "Message not found or not permitted.") + } else { + sm.Put(c.Request.Context(), "flash", "Could not mark message as read.") + } + c.Redirect(http.StatusSeeOther, "/account/messages") + return + } + + sm.Put(c.Request.Context(), "flash", "Message marked as read.") + // Redirect back to referer when possible so UX is smooth. + if ref := c.Request.Referer(); ref != "" { + c.Redirect(http.StatusSeeOther, ref) + } else { + c.Redirect(http.StatusSeeOther, "/account/messages") + } +} diff --git a/internal/http/routes/accountroutes.go b/internal/http/routes/accountroutes.go index 8f2c6bf..9fd9e96 100644 --- a/internal/http/routes/accountroutes.go +++ b/internal/http/routes/accountroutes.go @@ -72,6 +72,7 @@ func RegisterAccountRoutes(app *bootstrap.App) { messages.GET("/archive", msgH.ArchivedList) // view archived messages messages.POST("/archive", msgH.ArchivePost) // archive a message messages.POST("/restore", msgH.RestoreArchived) + messages.POST("/mark-read", msgH.MarkReadPost) } // Notifications (auth-required) diff --git a/internal/platform/services/messages/service.go b/internal/platform/services/messages/service.go index e784562..558c4b5 100644 --- a/internal/platform/services/messages/service.go +++ b/internal/platform/services/messages/service.go @@ -277,3 +277,25 @@ func (s *Service) Unarchive(userID, id int64) error { } return nil } + +func (s *Service) MarkRead(userID, id int64) error { + ctx, cancel := context.WithTimeout(context.Background(), s.Timeout) + defer cancel() + + q := ` + UPDATE user_messages + SET is_read = 1 + WHERE id = ? AND recipientId = ? + ` + q = s.bind(q) + + res, err := s.DB.ExecContext(ctx, q, id, userID) + if err != nil { + return err + } + n, _ := res.RowsAffected() + if n == 0 { + return sql.ErrNoRows + } + return nil +} diff --git a/web/templates/account/messages/index.html b/web/templates/account/messages/index.html index 3a8e1a4..f8e5e9c 100644 --- a/web/templates/account/messages/index.html +++ b/web/templates/account/messages/index.html @@ -5,16 +5,33 @@ {{ if .Messages }}
{{ .Message.Body }}
- +