Adds branded HTML layout matching the admin portal purple palette, updates 000066 seeds, and adds 000067 migration to refresh existing template rows. Co-authored-by: Cursor <cursoragent@cursor.com>
113 lines
3.1 KiB
Go
113 lines
3.1 KiB
Go
package emailtemplates
|
|
|
|
import (
|
|
"Yimaru-Backend/internal/domain"
|
|
"bytes"
|
|
)
|
|
|
|
var defaultTemplates = map[string]domain.EmailTemplate{
|
|
domain.EmailTemplateSlugOTP: {
|
|
Slug: domain.EmailTemplateSlugOTP,
|
|
Name: "One-Time Password",
|
|
Subject: defaultOTPSubject,
|
|
BodyText: defaultOTPText,
|
|
BodyHTML: defaultOTPHTML,
|
|
Variables: []string{"OTP", "FirstName", "ExpiresMinutes"},
|
|
Status: domain.EmailTemplateStatusActive,
|
|
},
|
|
domain.EmailTemplateSlugInvitation: {
|
|
Slug: domain.EmailTemplateSlugInvitation,
|
|
Name: "User Invitation",
|
|
Subject: defaultInvitationSubject,
|
|
BodyText: defaultInvitationText,
|
|
BodyHTML: defaultInvitationHTML,
|
|
Variables: []string{"FirstName", "InviterName", "InviteLink"},
|
|
Status: domain.EmailTemplateStatusActive,
|
|
},
|
|
domain.EmailTemplateSlugPasswordReset: {
|
|
Slug: domain.EmailTemplateSlugPasswordReset,
|
|
Name: "Password Reset",
|
|
Subject: defaultPasswordResetSubject,
|
|
BodyText: defaultPasswordResetText,
|
|
BodyHTML: defaultPasswordResetHTML,
|
|
Variables: []string{"FirstName", "ResetLink", "ExpiresMinutes"},
|
|
Status: domain.EmailTemplateStatusActive,
|
|
},
|
|
domain.EmailTemplateSlugWelcome: {
|
|
Slug: domain.EmailTemplateSlugWelcome,
|
|
Name: "Welcome Email",
|
|
Subject: defaultWelcomeSubject,
|
|
BodyText: defaultWelcomeText,
|
|
BodyHTML: defaultWelcomeHTML,
|
|
Variables: []string{"FirstName", "LoginURL"},
|
|
Status: domain.EmailTemplateStatusActive,
|
|
},
|
|
domain.EmailTemplateSlugCustomMessage: {
|
|
Slug: domain.EmailTemplateSlugCustomMessage,
|
|
Name: "Custom Message",
|
|
Subject: "{{.Subject}}",
|
|
BodyText: "{{.Message}}",
|
|
BodyHTML: defaultCustomMessageHTML,
|
|
Variables: []string{"Subject", "Message"},
|
|
Status: domain.EmailTemplateStatusActive,
|
|
},
|
|
}
|
|
|
|
func defaultTemplate(slug string) (domain.EmailTemplate, bool) {
|
|
tmpl, ok := defaultTemplates[slug]
|
|
return tmpl, ok
|
|
}
|
|
|
|
func renderTemplateFields(tmpl domain.EmailTemplate, data map[string]any) (domain.RenderedEmail, error) {
|
|
if data == nil {
|
|
data = map[string]any{}
|
|
}
|
|
|
|
subject, err := executeTextTemplate("subject:"+tmpl.Slug, tmpl.Subject, data)
|
|
if err != nil {
|
|
return domain.RenderedEmail{}, err
|
|
}
|
|
|
|
text, err := executeTextTemplate("text:"+tmpl.Slug, tmpl.BodyText, data)
|
|
if err != nil {
|
|
return domain.RenderedEmail{}, err
|
|
}
|
|
|
|
html, err := executeHTMLTemplate("html:"+tmpl.Slug, tmpl.BodyHTML, data)
|
|
if err != nil {
|
|
return domain.RenderedEmail{}, err
|
|
}
|
|
|
|
return domain.RenderedEmail{
|
|
Subject: subject,
|
|
Text: text,
|
|
HTML: html,
|
|
}, nil
|
|
}
|
|
|
|
func executeTextTemplate(name, content string, data map[string]any) (string, error) {
|
|
tmpl, err := newTextTemplate(name, content)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
if err := tmpl.Execute(&buf, data); err != nil {
|
|
return "", err
|
|
}
|
|
return buf.String(), nil
|
|
}
|
|
|
|
func executeHTMLTemplate(name, content string, data map[string]any) (string, error) {
|
|
tmpl, err := newHTMLTemplate(name, content)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
if err := tmpl.Execute(&buf, data); err != nil {
|
|
return "", err
|
|
}
|
|
return buf.String(), nil
|
|
}
|