111 lines
3.2 KiB
Go
111 lines
3.2 KiB
Go
|
|
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)
|
||
|
|
}
|
||
|
|
}
|