Initial commit

This commit is contained in:
sas.fajri
2026-04-30 14:27:01 +07:00
commit e29e943c27
70 changed files with 8909 additions and 0 deletions

View File

@@ -0,0 +1,74 @@
package progress
import (
"cpone-dashboard/menu/auth"
"cpone-dashboard/menu/projects"
"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
Search string
Status string
Rows []ProgressRow
FilteredRows []ProgressRow
Summary ProgressSummary
ValidatedPct int
PublishedPct int
}
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
}
rows, err := GetProgressRows(mcuID)
if err != nil {
http.Error(w, "query error", http.StatusInternalServerError)
return
}
summary := BuildProgressSummary(rows)
search := r.URL.Query().Get("search")
status := r.URL.Query().Get("status")
filteredRows := FilterProgressRows(rows, search, status)
t := tmpl
if t == nil {
http.Error(w, "template not ready", http.StatusInternalServerError)
return
}
if err := t.ExecuteTemplate(w, "base", pageData{
Username: username,
CurrentProject: project,
Search: search,
Status: status,
Rows: rows,
FilteredRows: filteredRows,
Summary: summary,
ValidatedPct: Pct(summary.Validated, summary.Total),
PublishedPct: Pct(summary.Published, summary.Total),
}); err != nil {
http.Error(w, "template error", http.StatusInternalServerError)
}
}

View File

@@ -0,0 +1,120 @@
package progress
import (
"cpone-dashboard/db"
"strings"
)
type ProgressRow struct {
PreregisterID int
NIP string
Name string
Posisi string
ResumeStatus string
Validated string
Published string
}
type ProgressSummary struct {
Total int
Validated int
Published int
}
func GetProgressRows(mcuID int) ([]ProgressRow, error) {
rows, err := db.DB.Query(`
SELECT
mp.Mcu_PatientPreregisterID,
COALESCE(NULLIF(TRIM(mp.Mcu_PatientNIP), ''), '-') AS nip,
COALESCE(NULLIF(TRIM(mp.Mcu_PatientName), ''), '-') AS name,
COALESCE(
NULLIF(TRIM(mp.Mcu_PatientDepartment), ''),
NULLIF(TRIM(mp.Mcu_PatientDivision), ''),
NULLIF(TRIM(mp.Mcu_PatientPosisi), ''),
'-'
) AS posisi,
COALESCE(rs.Mcu_PatientResumeStatusStatus, '') AS resume_status,
COALESCE(rs.Mcu_PatientResumeStatusValidated, 'N') AS validated,
COALESCE(rs.Mcu_PatientResumeStatusPublished, 'N') AS published
FROM mcu_patient mp
LEFT JOIN mcu_patient_resume_status rs
ON rs.Mcu_PatientResumeStatusPreregisterID = mp.Mcu_PatientPreregisterID
AND rs.Mcu_PatientResumeStatusMcuID = ?
WHERE mp.Mcu_PatientMcuID = ?
AND mp.Mcu_PatientIsActive = 'Y'
ORDER BY
rs.Mcu_PatientResumeStatusValidated DESC,
mp.Mcu_PatientName ASC
`, mcuID, mcuID)
if err != nil {
return nil, err
}
defer rows.Close()
var result []ProgressRow
for rows.Next() {
var r ProgressRow
if err := rows.Scan(&r.PreregisterID, &r.NIP, &r.Name, &r.Posisi, &r.ResumeStatus, &r.Validated, &r.Published); err != nil {
continue
}
result = append(result, r)
}
return result, nil
}
func BuildProgressSummary(rows []ProgressRow) ProgressSummary {
s := ProgressSummary{Total: len(rows)}
for _, r := range rows {
if r.Validated == "Y" {
s.Validated++
}
if r.Published == "Y" {
s.Published++
}
}
return s
}
func FilterProgressRows(rows []ProgressRow, search, status string) []ProgressRow {
search = strings.ToLower(strings.TrimSpace(search))
status = strings.TrimSpace(status)
if search == "" && status == "" {
return rows
}
out := make([]ProgressRow, 0, len(rows))
for _, r := range rows {
switch status {
case "validated":
if r.Validated != "Y" {
continue
}
case "published":
if r.Published != "Y" {
continue
}
case "not_validated":
if r.Validated == "Y" {
continue
}
case "not_published":
if r.Published == "Y" {
continue
}
}
if search != "" {
hay := strings.ToLower(r.Name + " " + r.NIP + " " + r.Posisi)
if !strings.Contains(hay, search) {
continue
}
}
out = append(out, r)
}
return out
}
func Pct(num, total int) int {
if total == 0 {
return 0
}
return num * 100 / total
}

View File

@@ -0,0 +1,7 @@
package progress
import "github.com/go-chi/chi/v5"
func Routes(r chi.Router) {
r.Get("/", Index)
}