# Result Menu — Design Spec Date: 2026-04-30 ## Overview Halaman `/result` menampilkan daftar peserta MCU beserta tombol "View PDF" untuk membuka laporan hasil konsolidasi. Data diambil sepenuhnya dari `cpone_dashboard` (zero dependency ke `cpone`). ## Data Sources Semua tabel ada di `cpone_dashboard`: - `mcu_patient` — data peserta (NIP, nama, posisi/dept, order ID) - `published_mcu_dashboard_sync` — file URL PDF per peserta Join key: `mcu_patient.Mcu_PatientOrderID = published_mcu_dashboard_sync.Published_McuDasboardT_OrderHeaderID` ## Config / Env Tambah key baru ke `.env`, `.env.example`, dan `config/config.go`: ``` PDF_BASE_URL=http://devcpone.aplikasi.web.id/dashboard-files/ ``` Field `PDFBaseURL string` ditambah ke struct `Config`. Nilai ini di-passing ke `result` handler saat setup di `main.go`. ## Backend — `menu/result/` ### query.go ```go type ResultRow struct { NIP string Name string Posisi string FileUrl string // kosong jika belum ada PDF ReportDate string // Published_McuDasboardLastUpdated } type ResultSummary struct { Total int HasPDF int } ``` Query: ```sql SELECT 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(p.Published_McuDasboardFileUrl, '') AS file_url, CASE WHEN p.Published_McuDasboardFileUrl IS NOT NULL AND p.Published_McuDasboardFileUrl != '' THEN COALESCE(p.Published_McuDasboardLastUpdated, '') ELSE '' END AS report_date FROM mcu_patient mp LEFT JOIN published_mcu_dashboard_sync p ON p.Published_McuDasboardT_OrderHeaderID = mp.Mcu_PatientOrderID WHERE mp.Mcu_PatientMcuID = ? AND mp.Mcu_PatientIsActive = 'Y' ORDER BY (p.Published_McuDasboardFileUrl IS NOT NULL AND p.Published_McuDasboardFileUrl != '') DESC, mp.Mcu_PatientName ASC ``` Helper functions: - `BuildResultSummary(rows []ResultRow) ResultSummary` - `FilterResultRows(rows []ResultRow, search, filter string) []ResultRow` - filter values: `""` (all), `"has_pdf"`, `"no_pdf"` ### handler.go `pageData` struct: ```go type pageData struct { Username string CurrentProject projects.ProjectItem Search string Filter string Rows []ResultRow FilteredRows []ResultRow Summary ResultSummary PDFBaseURL string } ``` Handler `Index` mengikuti pola progress: redirect ke `/projects` jika belum pilih project, fetch rows, build summary, apply filter, render template. `PDFBaseURL` di-inject saat `SetTemplates` — tambah fungsi `SetPDFBaseURL(url string)` di package result. ### route.go Tidak berubah — sudah ada `r.Get("/", Index)`. ## Template — `templates/result/index.html` **Section 1 — Current project card** Sama persis dengan progress/arrival: nama project, nomor, tombol "Ganti project". **Section 2 — Summary cards (2 cards)** - Total Patients - Has PDF (count `FileUrl != ""`) **Section 3 — Filter form** - Search input (nama atau NIP) - Dropdown: All / Has PDF / No PDF - Tombol Filter **Section 4 — Patient list** - Desktop: table dengan kolom NIP, Nama, Posisi/Dept, Report Date, Action - Mobile: card stack - Action: tombol `View PDF` (buka tab baru) jika `FileUrl != ""`, teks `—` jika kosong - PDF full URL: `PDFBaseURL + FileUrl` ## Referensi Visual `/PLAN/draft-cpone/06-result.html` — warna dan layout mengikuti color scheme brand yang ada (`brand-500`, `slate-*`), bukan warna `diagnos-*` dari draft.