Files
cpone_dashboard/docs/superpowers/specs/2026-04-30-result-menu-design.md
2026-04-30 14:27:01 +07:00

3.7 KiB

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

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:

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:

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.