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