dealspace/lib/notify.go

169 lines
4.7 KiB
Go

package lib
import (
"fmt"
"time"
)
// Broadcast logic — answer published → notify all linked requesters.
// Uses the broadcasts table for idempotency.
// NotifyAnswerPublished broadcasts a published answer to all linked requesters. Stub.
func NotifyAnswerPublished(db *DB, cfg *Config, answerID string) error {
// TODO: implementation steps:
// 1. Query answer_links WHERE answer_id = ? AND status = 'confirmed'
// 2. For each linked request, find the origin_id (buyer)
// 3. Check broadcasts table for idempotency
// 4. Send notification (email, in-app, etc.)
// 5. Record in broadcasts table
return nil
}
// NotifyTaskAssigned notifies a user that a task has been assigned to them. Stub.
func NotifyTaskAssigned(db *DB, cfg *Config, entryID, assigneeID string) error {
// TODO: implement notification
return nil
}
// NotifyChainComplete fires when a routing chain completes back to origin. Stub.
func NotifyChainComplete(db *DB, cfg *Config, entryID string) error {
// TODO: implement chain completion notification
return nil
}
// ---- Email Notification Functions ----
// NotifyInvite sends an invitation email to a new user.
func NotifyInvite(m *Mailer, to, inviterName, inviterOrg, projectName, inviteURL string) error {
if !m.Enabled() {
return nil
}
subject := fmt.Sprintf("You've been invited to join %s on Dealspace", projectName)
data := InviteData{
InviterName: inviterName,
InviterOrg: inviterOrg,
ProjectName: projectName,
InviteURL: inviteURL,
ExpiresIn: "7 days",
}
return m.SendTemplate(to, subject, "invite.html", data)
}
// NotifyTasksAssigned sends an email when new tasks are assigned to a user.
func NotifyTasksAssigned(m *Mailer, to, projectName string, tasks []string) error {
if !m.Enabled() {
return nil
}
count := len(tasks)
var subject string
if count == 1 {
subject = fmt.Sprintf("You have 1 new task on %s", projectName)
} else {
subject = fmt.Sprintf("You have %d new tasks on %s", count, projectName)
}
// Convert task strings to TaskItem (simplified — in real usage, you'd pass full task data)
taskItems := make([]TaskItem, 0, len(tasks))
for _, t := range tasks {
taskItems = append(taskItems, TaskItem{
Title: t,
})
}
data := TasksAssignedData{
ProjectName: projectName,
Count: count,
Tasks: taskItems,
TasksURL: "https://app.muskepo.com/app/tasks",
}
return m.SendTemplate(to, subject, "tasks_assigned.html", data)
}
// NotifyAnswerSubmitted notifies an IB member that a seller submitted an answer.
func NotifyAnswerSubmitted(m *Mailer, to, answererName, requestTitle, wsName, reviewURL string) error {
if !m.Enabled() {
return nil
}
subject := fmt.Sprintf("%s submitted an answer for: %s", answererName, requestTitle)
data := AnswerSubmittedData{
AnswererName: answererName,
RequestTitle: requestTitle,
WorkstreamName: wsName,
ReviewURL: reviewURL,
}
return m.SendTemplate(to, subject, "answer_submitted.html", data)
}
// NotifyAnswerApproved notifies a seller that their answer was approved.
func NotifyAnswerApproved(m *Mailer, to, requestTitle string, published bool) error {
if !m.Enabled() {
return nil
}
subject := "Your answer was approved ✓"
data := AnswerApprovedData{
RequestTitle: requestTitle,
Published: published,
}
return m.SendTemplate(to, subject, "answer_approved.html", data)
}
// NotifyAnswerRejected notifies a seller that their answer was rejected.
func NotifyAnswerRejected(m *Mailer, to, requestTitle, reason, requestURL string) error {
if !m.Enabled() {
return nil
}
subject := "Your answer needs revision"
data := AnswerRejectedData{
RequestTitle: requestTitle,
Reason: reason,
RequestURL: requestURL,
}
return m.SendTemplate(to, subject, "answer_rejected.html", data)
}
// NotifyRequestForwarded notifies a user that a request was forwarded to them.
func NotifyRequestForwarded(m *Mailer, to, senderName, requestTitle, requestURL string, dueAt *time.Time) error {
if !m.Enabled() {
return nil
}
subject := fmt.Sprintf("%s forwarded a request to you: %s", senderName, requestTitle)
data := RequestForwardedData{
SenderName: senderName,
RequestTitle: requestTitle,
RequestURL: requestURL,
HasDueDate: dueAt != nil,
}
if dueAt != nil {
data.DueDate = dueAt.Format("January 2, 2006")
}
return m.SendTemplate(to, subject, "request_forwarded.html", data)
}
// NotifyWelcome sends a welcome email to a new user after accepting an invite.
func NotifyWelcome(m *Mailer, to, name, tasksURL string) error {
if !m.Enabled() {
return nil
}
subject := "Welcome to Dealspace"
data := WelcomeData{
RecipientName: name,
TasksURL: tasksURL,
}
return m.SendTemplate(to, subject, "welcome.html", data)
}