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) } }