Files
cpone_dashboard/cpone-dashboard/menu/arrival/handler.go
2026-04-30 14:27:01 +07:00

129 lines
3.5 KiB
Go

package arrival
import (
"cpone-dashboard/menu/auth"
"cpone-dashboard/menu/projects"
"encoding/json"
"html/template"
"net/http"
)
var tmpl *template.Template
var basePath string
func SetTemplates(t *template.Template) { tmpl = t }
func SetBasePath(p string) { basePath = p }
type pageData struct {
Username string
CurrentProject projects.ProjectItem
Date string
AvailableDates []string
Search string
Department string
Rows []ArrivalRow
FilteredRows []ArrivalRow
Summary ArrivalSummary
Departments []DepartmentStat
DepartmentOptions []string
OverviewJSON template.JS
DepartmentJSON template.JS
}
func toJS(v interface{}) template.JS {
b, _ := json.Marshal(v)
return template.JS(b)
}
func Index(w http.ResponseWriter, r *http.Request) {
username := auth.Username(r)
mcuID := auth.SelectedProjectID(r)
if mcuID == 0 {
http.Redirect(w, r, basePath+"/projects", http.StatusSeeOther)
return
}
project, ok, err := projects.GetUserProject(username, mcuID)
if err != nil {
http.Error(w, "query error", http.StatusInternalServerError)
return
}
if !ok {
http.Redirect(w, r, basePath+"/projects", http.StatusSeeOther)
return
}
dates, err := GetArrivalDates(mcuID)
if err != nil {
http.Error(w, "query error", http.StatusInternalServerError)
return
}
selectedDate := activeDateOrLatest(dates, r.URL.Query().Get("date"), project.StartDate)
rows, err := GetArrivalRows(mcuID, selectedDate)
if err != nil {
http.Error(w, "query error", http.StatusInternalServerError)
return
}
summary, deptStats := BuildArrivalStats(rows)
filteredRows := FilterArrivalRows(rows, r.URL.Query().Get("search"), r.URL.Query().Get("dept"))
deptOptions := UniqueDepartments(rows)
stationMap, err := GetStationProgress(mcuID, selectedDate)
if err != nil {
http.Error(w, "query error", http.StatusInternalServerError)
return
}
for i := range filteredRows {
filteredRows[i].Stations = stationMap[filteredRows[i].PreregisterID]
}
// Chart 1: double donut — inner: checked-in vs pending, outer: total per posisi/dept
outerDepts := []map[string]any{}
for _, d := range deptStats {
if d.Total > 0 {
outerDepts = append(outerDepts, map[string]any{"name": d.Name, "value": d.Total})
}
}
overview := map[string]any{
"checkedIn": summary.CheckedIn,
"pending": summary.Pending,
"depts": outerDepts,
}
// Chart 2: per-station patient count bar chart
stationStats := BuildStationChart(stationMap)
stationLabels := make([]string, len(stationStats))
stationCounts := make([]int, len(stationStats))
for i, s := range stationStats {
stationLabels[i] = s.Name
stationCounts[i] = s.Count
}
stationChart := map[string]any{
"labels": stationLabels,
"counts": stationCounts,
}
t := tmpl
if t == nil {
http.Error(w, "template not ready", http.StatusInternalServerError)
return
}
data := pageData{
Username: username,
CurrentProject: project,
Date: selectedDate,
AvailableDates: dates,
Search: r.URL.Query().Get("search"),
Department: r.URL.Query().Get("dept"),
Rows: rows,
FilteredRows: filteredRows,
Summary: summary,
Departments: deptStats,
DepartmentOptions: deptOptions,
OverviewJSON: toJS(overview),
DepartmentJSON: toJS(stationChart),
}
if err := t.ExecuteTemplate(w, "base", data); err != nil {
http.Error(w, "template error", http.StatusInternalServerError)
}
}