package handlers
import (
"fmt"
"html/template"
"net/http"
"strconv"
"go-crm/internal/db"
"go-crm/internal/templates"
"github.com/go-chi/chi/v5"
)
func (a *App) LeadKeywordsPage(w http.ResponseWriter, r *http.Request) {
accountID, ok := a.requireAuth(w, r)
if !ok {
return
}
clientID := a.clientIDForAccount(accountID)
if clientID == 0 {
http.Error(w, "No client found for account", http.StatusBadRequest)
return
}
kws, err := db.ListServiceKeywords(a.DB, clientID)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
statuses, _ := db.ListLeadStatuses(a.DB, clientID)
services := a.serviceNames(clientID)
pendingCount, _ := db.CountLeadsNeedingReview(a.DB, clientID)
buf := templates.BufRender()
fmt.Fprint(buf, templates.PageHeader("Keyword Mapping", "Auto-detect services from WhatsApp messages"))
if pendingCount > 0 {
fmt.Fprintf(buf, `
`, pendingCount)
}
// Service Keywords Section
keywordForm := fmt.Sprintf(`
%s`, buildServiceSelectOptions(services), renderKeywordTable(kws))
fmt.Fprint(buf, templates.SectionCard("Service Keywords", "Add keywords that trigger automatic service detection. Case and accent insensitive.", template.HTML(keywordForm)))
// Statuses Section
statusForm := fmt.Sprintf(`
%s`, renderStatusTable(statuses))
fmt.Fprintf(buf, `%s
`, templates.SectionCard("Lead Statuses", "Manage the status options available for leads.", template.HTML(statusForm)))
w.Header().Set("Content-Type", "text/html; charset=utf-8")
templates.WritePage(w, buf, "Keyword Mapping", "")
}
func (a *App) AddServiceKeyword(w http.ResponseWriter, r *http.Request) {
accountID, ok := a.requireAuth(w, r)
if !ok {
return
}
clientID := a.clientIDForAccount(accountID)
r.ParseForm()
svc := r.FormValue("service_name")
kw := r.FormValue("keyword")
if svc == "" || kw == "" {
http.Error(w, "service_name and keyword required", http.StatusBadRequest)
return
}
db.AddServiceKeyword(a.DB, clientID, svc, kw)
kws, _ := db.ListServiceKeywords(a.DB, clientID)
w.Header().Set("Content-Type", "text/html; charset=utf-8")
fmt.Fprint(w, renderKeywordTable(kws))
}
func (a *App) DeleteServiceKeywordHandler(w http.ResponseWriter, r *http.Request) {
accountID, ok := a.requireAuth(w, r)
if !ok {
return
}
clientID := a.clientIDForAccount(accountID)
kwID, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
db.DeleteServiceKeyword(a.DB, clientID, kwID)
kws, _ := db.ListServiceKeywords(a.DB, clientID)
w.Header().Set("Content-Type", "text/html; charset=utf-8")
fmt.Fprint(w, renderKeywordTable(kws))
}
func (a *App) AddLeadStatusHandler(w http.ResponseWriter, r *http.Request) {
accountID, ok := a.requireAuth(w, r)
if !ok {
return
}
clientID := a.clientIDForAccount(accountID)
r.ParseForm()
statusName := r.FormValue("status_name")
if statusName == "" {
http.Error(w, "status_name required", http.StatusBadRequest)
return
}
db.AddLeadStatus(a.DB, clientID, statusName)
statuses, _ := db.ListLeadStatuses(a.DB, clientID)
w.Header().Set("Content-Type", "text/html; charset=utf-8")
fmt.Fprint(w, renderStatusTable(statuses))
}
func (a *App) DeleteLeadStatusHandler(w http.ResponseWriter, r *http.Request) {
accountID, ok := a.requireAuth(w, r)
if !ok {
return
}
clientID := a.clientIDForAccount(accountID)
statusID, _ := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64)
db.DeleteLeadStatus(a.DB, clientID, statusID)
statuses, _ := db.ListLeadStatuses(a.DB, clientID)
w.Header().Set("Content-Type", "text/html; charset=utf-8")
fmt.Fprint(w, renderStatusTable(statuses))
}
func buildServiceSelectOptions(services []string) string {
out := ""
for _, s := range services {
if s == "Não especificou" {
continue
}
out += fmt.Sprintf(``, htmlEscape(s), htmlEscape(s))
}
return out
}
func renderKeywordTable(kws []db.ServiceKeyword) string {
out := `| Service | Keyword | Actions |
`
if len(kws) == 0 {
out += `| No keywords defined. |
`
}
for _, kw := range kws {
out += fmt.Sprintf(`
| %s |
%s |
|
`, htmlEscape(kw.ServiceName), htmlEscape(kw.Keyword), kw.KeywordID)
}
out += `
`
return out
}
func renderStatusTable(statuses []db.LeadStatus) string {
out := `| Status | Actions |
`
if len(statuses) == 0 {
out += `| No statuses defined. |
`
}
for _, s := range statuses {
out += fmt.Sprintf(`
| %s |
|
`, htmlEscape(s.StatusName), s.StatusID)
}
out += `
`
return out
}
// --- package-level shims ---
func LeadKeywordsPage(w http.ResponseWriter, r *http.Request) {
(&App{DB: DB, WAConnector: WAConnector}).LeadKeywordsPage(w, r)
}
func AddServiceKeyword(w http.ResponseWriter, r *http.Request) {
(&App{DB: DB, WAConnector: WAConnector}).AddServiceKeyword(w, r)
}
func DeleteServiceKeywordHandler(w http.ResponseWriter, r *http.Request) {
(&App{DB: DB, WAConnector: WAConnector}).DeleteServiceKeywordHandler(w, r)
}
func AddLeadStatusHandler(w http.ResponseWriter, r *http.Request) {
(&App{DB: DB, WAConnector: WAConnector}).AddLeadStatusHandler(w, r)
}
func DeleteLeadStatusHandler(w http.ResponseWriter, r *http.Request) {
(&App{DB: DB, WAConnector: WAConnector}).DeleteLeadStatusHandler(w, r)
}