cmc-sales/go-app/internal/cmc/handlers/quotes.go

111 lines
3.2 KiB
Go
Raw Normal View History

2025-07-14 06:26:26 -07:00
package handlers
import (
"net/http"
"strconv"
"strings"
"time"
"code.springupsoftware.com/cmc/cmc-sales/internal/cmc/db"
"code.springupsoftware.com/cmc/cmc-sales/internal/cmc/templates"
)
type QuotesHandler struct {
queries *db.Queries
tmpl *templates.TemplateManager
}
func ExpiringQuotesHandler(queries *db.Queries, tmpl *templates.TemplateManager) *QuotesHandler {
return &QuotesHandler{
queries: queries,
tmpl: tmpl,
}
}
func (h *QuotesHandler) ExpiringQuotesView(w http.ResponseWriter, r *http.Request) {
days := int32(14)
recentlyExpiredQuotes, err := h.queries.GetRecentlyExpiredQuotes(r.Context(), days)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
expiringSoonQuotes, err := h.queries.GetExpiringSoonQuotes(r.Context(), days)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
calcExpiryInfo := func(validUntil time.Time) (string, int, int) {
now := time.Now()
daysUntil := int(validUntil.Sub(now).Hours() / 24)
daysSince := int(now.Sub(validUntil).Hours() / 24)
var relative string
if validUntil.After(now) {
if daysUntil == 0 {
relative = "expires today"
} else if daysUntil == 1 {
relative = "in 1 day"
} else {
relative = "in " + strconv.Itoa(daysUntil) + " days"
}
} else {
if daysSince == 0 {
relative = "expired today"
} else if daysSince == 1 {
relative = "expired 1 day ago"
} else {
relative = "expired " + strconv.Itoa(daysSince) + " days ago"
}
}
return relative, daysUntil, daysSince
}
formatQuote := func(q db.GetRecentlyExpiredQuotesRow) map[string]interface{} {
relative, daysUntil, daysSince := calcExpiryInfo(q.ValidUntil)
return map[string]interface{}{
"ID": q.ID,
"Username": strings.Title(q.Username),
"EnquiryID": q.ID_2,
"EnquiryTitle": q.Title,
"DateIssued": q.DateIssued.Format("2006-01-02"),
"ValidUntil": q.ValidUntil.Format("2006-01-02"),
"ValidUntilRelative": relative,
"DaysUntilExpiry": daysUntil,
"DaysSinceExpiry": daysSince,
}
}
formatSoonQuote := func(q db.GetExpiringSoonQuotesRow) map[string]interface{} {
relative, daysUntil, daysSince := calcExpiryInfo(q.ValidUntil)
return map[string]interface{}{
"ID": q.ID,
"Username": strings.ToUpper(q.Username),
"EnquiryID": q.ID_2,
"EnquiryTitle": q.Title,
"DateIssued": q.DateIssued.Format("2006-01-02"),
"ValidUntil": q.ValidUntil.Format("2006-01-02"),
"ValidUntilRelative": relative,
"DaysUntilExpiry": daysUntil,
"DaysSinceExpiry": daysSince,
}
}
var expiredRows []map[string]interface{}
for _, q := range recentlyExpiredQuotes {
expiredRows = append(expiredRows, formatQuote(q))
}
var soonRows []map[string]interface{}
for _, q := range expiringSoonQuotes {
soonRows = append(soonRows, formatSoonQuote(q))
}
data := map[string]interface{}{
"RecentlyExpiredQuotes": expiredRows,
"ExpiringSoonQuotes": soonRows,
}
if err := h.tmpl.Render(w, "quotes/index.html", data); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}