diff --git a/handlers/messages.go b/handlers/messages.go index 3726239..5e5ecd2 100644 --- a/handlers/messages.go +++ b/handlers/messages.go @@ -72,3 +72,67 @@ func ArchiveMessageHandler(db *sql.DB) http.HandlerFunc { http.Redirect(w, r, "/account/messages", http.StatusSeeOther) } } + +func ArchivedMessagesHandler(db *sql.DB) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + userID, ok := helpers.GetCurrentUserID(r) + if !ok { + helpers.RenderError(w, r, 403) + return + } + + page := helpers.Atoi(r.URL.Query().Get("page")) + if page < 1 { + page = 1 + } + perPage := 10 + + messages := storage.GetArchivedMessages(db, userID, page, perPage) + hasMore := len(messages) == perPage + + data := BuildTemplateData(db, w, r) + context := helpers.TemplateContext(w, r, data) + context["Messages"] = messages + context["Page"] = page + context["HasMore"] = hasMore + + tmpl := helpers.LoadTemplateFiles("archived.html", "templates/account/messages/archived.html") + tmpl.ExecuteTemplate(w, "layout", context) + } +} + +func SendMessageHandler(db *sql.DB) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case http.MethodGet: + // Display the form + data := BuildTemplateData(db, w, r) + context := helpers.TemplateContext(w, r, data) + tmpl := helpers.LoadTemplateFiles("send-message.html", "templates/account/messages/send.html") + + if err := tmpl.ExecuteTemplate(w, "layout", context); err != nil { + helpers.RenderError(w, r, 500) + } + case http.MethodPost: + // Handle form submission + senderID, ok := helpers.GetCurrentUserID(r) + if !ok { + helpers.RenderError(w, r, 403) + return + } + + recipientID := helpers.Atoi(r.FormValue("recipient_id")) + subject := r.FormValue("subject") + body := r.FormValue("message") + + if err := storage.SendMessage(db, senderID, recipientID, subject, body); err != nil { + helpers.SetFlash(w, r, "Failed to send message.") + } else { + helpers.SetFlash(w, r, "Message sent.") + } + http.Redirect(w, r, "/account/messages", http.StatusSeeOther) + default: + helpers.RenderError(w, r, 405) + } + } +} diff --git a/main.go b/main.go index 978253d..39c35ea 100644 --- a/main.go +++ b/main.go @@ -71,6 +71,8 @@ func setupAccountRoutes(mux *http.ServeMux, db *sql.DB) { mux.HandleFunc("/account/messages", middleware.Auth(true)(handlers.MessagesInboxHandler(db))) mux.HandleFunc("/account/messages/read", middleware.Auth(true)(handlers.ReadMessageHandler(db))) mux.HandleFunc("/account/messages/archive", middleware.Auth(true)(handlers.ArchiveMessageHandler(db))) + mux.HandleFunc("/account/messages/archived", middleware.Auth(true)(handlers.ArchivedMessagesHandler(db))) + mux.HandleFunc("/account/messages/send", middleware.Auth(true)(handlers.SendMessageHandler(db))) mux.HandleFunc("/account/notifications", middleware.Auth(true)(handlers.NotificationsHandler(db))) mux.HandleFunc("/account/notifications/read", middleware.Auth(true)(handlers.MarkNotificationReadHandler(db))) } diff --git a/models/user.go b/models/user.go index 2ffaf9d..b05faab 100644 --- a/models/user.go +++ b/models/user.go @@ -30,6 +30,7 @@ type Message struct { Message string IsRead bool CreatedAt time.Time + ArchivedAt *time.Time } var db *sql.DB diff --git a/storage/messages.go b/storage/messages.go index 9e68b96..4bebf36 100644 --- a/storage/messages.go +++ b/storage/messages.go @@ -85,8 +85,45 @@ func MarkMessageAsRead(db *sql.DB, messageID, userID int) error { func ArchiveMessage(db *sql.DB, userID, messageID int) error { _, err := db.Exec(` UPDATE users_messages - SET is_archived = TRUE + SET is_archived = TRUE, archived_at = CURRENT_TIMESTAMP WHERE id = ? AND recipientId = ? `, messageID, userID) return err } + +func SendMessage(db *sql.DB, senderID, recipientID int, subject, message string) error { + _, err := db.Exec(` + INSERT INTO users_messages (senderId, recipientId, subject, message) + VALUES (?, ?, ?, ?) + `, senderID, recipientID, subject, message) + return err +} + +func GetArchivedMessages(db *sql.DB, userID int, page, perPage int) []models.Message { + offset := (page - 1) * perPage + rows, err := db.Query(` + SELECT id, senderId, recipientId, subject, message, is_read, created_at, archived_at + FROM users_messages + WHERE recipientId = ? AND is_archived = TRUE + ORDER BY archived_at DESC + LIMIT ? OFFSET ? + `, userID, perPage, offset) + if err != nil { + return nil + } + defer rows.Close() + + var messages []models.Message + for rows.Next() { + var m models.Message + err := rows.Scan( + &m.ID, &m.SenderId, &m.RecipientId, + &m.Subject, &m.Message, &m.IsRead, + &m.CreatedAt, &m.ArchivedAt, + ) + if err == nil { + messages = append(messages, m) + } + } + return messages +} diff --git a/storage/schema.go b/storage/schema.go index 77523a9..a5177c0 100644 --- a/storage/schema.go +++ b/storage/schema.go @@ -115,12 +115,13 @@ const SchemaUsersMessages = ` CREATE TABLE IF NOT EXISTS users_messages ( id INTEGER PRIMARY KEY AUTOINCREMENT, senderId INTEGER NOT NULL REFERENCES users(id), - recipientId int, + recipientId INTEGER NOT NULL REFERENCES users(id), subject TEXT NOT NULL, message TEXT, is_read BOOLEAN DEFAULT FALSE, is_archived BOOLEAN DEFAULT FALSE, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + archived_at TIMESTAMP );` const SchemaUsersNotifications = ` diff --git a/templates/account/messages/achived.html b/templates/account/messages/achived.html new file mode 100644 index 0000000..16b8456 --- /dev/null +++ b/templates/account/messages/achived.html @@ -0,0 +1,39 @@ +{{ define "content" }} +
{{ .Message }}
++ Archived: {{ .ArchivedAt.Format "02 Jan 2006 15:04" }} +
+