From bbcaf9826c2bca17e5184d63d9a6524ba0f20763 Mon Sep 17 00:00:00 2001 From: Fanrouver Date: Fri, 10 Jul 2026 11:14:36 +0700 Subject: [PATCH] update skill dan docs --- .agents/AGENTS.md | 304 ++++++++++++++++++ .../web-antrean-coding-standards/SKILL.md | 173 ++++++++++ docs/DEVLOG.md | 81 ++++- docs/DEVPLAN.md | 37 ++- docs/PRD.md | 15 +- 5 files changed, 584 insertions(+), 26 deletions(-) create mode 100644 .agents/AGENTS.md create mode 100644 .agents/skills/web-antrean-coding-standards/SKILL.md diff --git a/.agents/AGENTS.md b/.agents/AGENTS.md new file mode 100644 index 0000000..7b9c0ef --- /dev/null +++ b/.agents/AGENTS.md @@ -0,0 +1,304 @@ +# πŸ“‹ Project Knowledge β€” Web Antrean (Sistem Antrian Rumah Sakit) + +> Dokumen ini berisi knowledge base lengkap, aturan pengkodean, dan workflow wajib untuk project **web-antrean**. +> **WAJIB DIBACA** sebelum melakukan task apapun. + +--- + +## 🚨 ATURAN WAJIB (MANDATORY RULES) + +### Rule 1: Selalu Buat Implementation Plan Sebelum Eksekusi +- **SEBELUM** menulis kode apapun, buat implementation plan di `docs/DEVPLAN.md` atau artifact +- Plan harus mencakup: file yang akan diubah, perubahan spesifik, dan alasan +- Tunggu persetujuan user sebelum eksekusi (kecuali fix minor/typo) + +### Rule 2: Selalu Tambahkan Komentar di Setiap Fungsi +- Setiap **function**, **method**, **computed**, dan **watcher** HARUS punya komentar JSDoc/TSDoc +- Format minimum: `/** Deskripsi singkat fungsi ini */` +- Untuk fungsi kompleks, tambahkan `@param`, `@returns`, `@example` +- Komentar inline untuk logika yang tidak obvious + +```javascript +// βœ… BENAR +/** + * Mengambil data pasien dari API berdasarkan ID loket + * @param {string} loketId - ID loket yang akan di-fetch + * @returns {Promise} Daftar pasien dalam antrian + */ +const fetchPatientsForLoket = async (loketId) => { ... } + +// ❌ SALAH β€” tanpa komentar +const fetchPatientsForLoket = async (loketId) => { ... } +``` + +### Rule 3: Selalu Update Dokumentasi Setelah Perubahan +- **DEVLOG.md**: Tambahkan entry untuk setiap perubahan signifikan +- **DEVPLAN.md**: Update status task yang sudah selesai +- **PRD.md**: Update jika ada perubahan requirements/API/arsitektur +- **AGENTS.md**: Update jika ada knowledge baru yang penting + +### Rule 4: Selalu Baca AGENTS.md dan Skills Sebelum Eksekusi +- Baca file ini SEBELUM mulai task apapun +- Baca skill `web-antrean-coding-standards` untuk konvensi kode +- Jangan mengulang kesalahan yang sudah tercatat di bagian Gotchas + +### Rule 5: Jangan Mengulang Kesalahan yang Sudah Diketahui +- Cek bagian **⚠️ Gotchas & Known Issues** sebelum debug +- Cek **DEVLOG.md** untuk masalah serupa yang pernah diselesaikan +- Jika menemukan masalah baru, catat di DEVLOG dan Gotchas + +--- + +## πŸ—οΈ Arsitektur & Tech Stack + +| Layer | Teknologi | +|---|---| +| **Framework** | Nuxt 3 (`^3.17.7`) dengan SSR | +| **UI Library** | Vuetify 3 (`^3.9.3`) + Material Design Icons (`@mdi/font`) | +| **State Management** | Pinia (`^3.0.3`) + `pinia-plugin-persistedstate` | +| **Styling** | SCSS (`sass-embedded`), design tokens di `assets/scss/` | +| **Auth** | Keycloak OAuth2 (custom server-side implementation, bukan nuxt-auth) | +| **Database (Server)** | SQLite via `better-sqlite3` β€” untuk konfigurasi device & user sync | +| **Charting** | Chart.js + vue-chartjs + nuxt-charts | +| **QR Code** | `html5-qrcode` (scanner) + `qrcode.vue` / `nuxt-qrcode` (generator) | +| **WebSocket** | Custom composable (`useWebSocket.ts`) ke backend Go | +| **Deployment** | Docker + docker-compose | +| **Testing** | Vitest (unit) + Cypress (E2E) | +| **Font** | Google Fonts (Inter 400-700) | + +--- + +## πŸ“ Struktur Direktori + +``` +web-antrean/ +β”œβ”€β”€ app.vue # Entry point β€” store schema migration + loading overlay +β”œβ”€β”€ nuxt.config.ts # Konfigurasi Nuxt, Vuetify, runtime config, proxy +β”œβ”€β”€ .env # Environment variables (API URLs, auth, proxy) +β”œβ”€β”€ docker-compose.yml # Docker deployment config +β”‚ +β”œβ”€β”€ .agents/ # Agent rules & skills +β”‚ β”œβ”€β”€ AGENTS.md # FILE INI β€” rules & knowledge base +β”‚ └── skills/ # Coding standards & workflow skills +β”‚ +β”œβ”€β”€ docs/ # Dokumentasi project +β”‚ β”œβ”€β”€ DEVLOG.md # Development log (kronologis) +β”‚ β”œβ”€β”€ DEVPLAN.md # Development plan (task breakdown) +β”‚ └── PRD.md # Product Requirements Document +β”‚ +β”œβ”€β”€ assets/scss/ # Design system +β”‚ β”œβ”€β”€ _colors.scss # Color tokens (CSS variables) +β”‚ β”œβ”€β”€ _variables.scss # Spacing, breakpoints, etc. +β”‚ β”œβ”€β”€ _typography.scss # Font styles +β”‚ └── main.scss # Global imports +β”‚ +β”œβ”€β”€ components/ +β”‚ β”œβ”€β”€ common/ # Shared: PageHeader, Avatar, AppSnackbar, SelectionDialog +β”‚ β”œβ”€β”€ layout/ # SideBar, ProfileMenu, ProfilePopup +β”‚ β”œβ”€β”€ features/ # Feature-specific (antrean, master, monitoring, queue) +β”‚ β”œβ”€β”€ AdminKlinik/ # Komponen admin klinik eksekutif +β”‚ β”œβ”€β”€ GrandPaviliun/ # Komponen Grand Paviliun (Gp*) +β”‚ β”œβ”€β”€ HakAkses/ # Komponen manajemen hak akses +β”‚ β”œβ”€β”€ MonitorPasien/ # Komponen monitoring pasien +β”‚ β”œβ”€β”€ checkin/ # Komponen check-in +β”‚ β”œβ”€β”€ verification/ # Komponen verifikasi akun +β”‚ └── preview/ # Komponen preview +β”‚ +β”œβ”€β”€ composables/ +β”‚ β”œβ”€β”€ useAuth.ts # Auth state & session management +β”‚ β”œβ”€β”€ useWebSocket.ts # WebSocket client dengan auto-reconnect +β”‚ β”œβ”€β”€ useQueueAPI.ts # API wrapper untuk antrian (verificationApiBaseUrl) +β”‚ β”œβ”€β”€ useVisitAPI.ts # API wrapper untuk visit (externalApiBaseUrl) +β”‚ β”œβ”€β”€ useQueueSync.ts # Sinkronisasi antrian antar client +β”‚ β”œβ”€β”€ useCheckIn.ts # Logika check-in pasien +β”‚ β”œβ”€β”€ useCheckInHistory.ts # Riwayat check-in +β”‚ β”œβ”€β”€ useClinicAPI.ts # API wrapper klinik +β”‚ β”œβ”€β”€ useGrandPaviliun.ts # Logika Grand Paviliun +β”‚ β”œβ”€β”€ useHakAkses.ts # Manajemen hak akses +β”‚ β”œβ”€β”€ usePermissions.ts # Permission check helper +β”‚ β”œβ”€β”€ useQRGenerator.ts # QR code generation +β”‚ β”œβ”€β”€ useQRScanner.ts # QR code scanning (html5-qrcode) +β”‚ β”œβ”€β”€ useThermalPrint.ts # Thermal printer (tiket antrian) +β”‚ β”œβ”€β”€ useSnackbar.ts # Toast notification +β”‚ └── useInfiniteScroll.ts # Infinite scroll pagination +β”‚ +β”œβ”€β”€ layouts/ +β”‚ β”œβ”€β”€ default.vue # Main layout β€” SideBar + middleware auth + checkPageAccess +β”‚ └── empty.vue # Empty layout (untuk halaman tanpa sidebar) +β”‚ +β”œβ”€β”€ middleware/ +β”‚ β”œβ”€β”€ auth.ts # Auth check β†’ redirect ke /LoginPage jika belum login +β”‚ β”œβ”€β”€ guest.ts # Untuk halaman publik +β”‚ β”œβ”€β”€ checkPageAccess.ts # Cek akses halaman berdasarkan hak akses +β”‚ └── permissions.ts # Auto-sync permissions dari backend (DISABLED) +β”‚ +β”œβ”€β”€ pages/ # Semua halaman (lihat detail di PRD.md section 8.1) +β”‚ β”œβ”€β”€ AdminKlinikRuang/ # [kodeKlinik].vue (~111KB) +β”‚ β”œβ”€β”€ AdminLoket/ # [id].vue (~58KB) +β”‚ β”œβ”€β”€ CheckInPasien/ # checkIn.vue (~230KB, LARGEST) +β”‚ β”œβ”€β”€ Anjungan/ # Display anjungan (kiosk) +β”‚ β”œβ”€β”€ Setting/ # Master data & konfigurasi +β”‚ └── ... +β”‚ +β”œβ”€β”€ server/ +β”‚ β”œβ”€β”€ api/auth/ # Auth endpoints (Keycloak OAuth flow) +β”‚ β”œβ”€β”€ api/users/ # User management (SQLite-backed) +β”‚ β”œβ”€β”€ api/config/ # Device configuration (SQLite-backed) +β”‚ β”œβ”€β”€ api/hak-akses/ # Hak akses management +β”‚ └── utils/ # configDb.ts, sessionStore.ts, userSync.ts +β”‚ +β”œβ”€β”€ stores/ # Pinia stores (Single Source of Truth) +β”‚ β”œβ”€β”€ clinicStore.js # Master data klinik (~1007 lines) +β”‚ β”œβ”€β”€ queueStore.ts # Antrian pasien (~3302 lines, LARGEST) +β”‚ β”œβ”€β”€ loketStore.js # Data loket (~549 lines) +β”‚ β”œβ”€β”€ ruangStore.js # Data ruang klinik (~558 lines) +β”‚ β”œβ”€β”€ masterStore.js # BACKWARD COMPAT LAYER (jangan tulis langsung!) +β”‚ β”œβ”€β”€ penunjangStore.js # Data penunjang medis +β”‚ β”œβ”€β”€ doctorStore.js # Data dokter (fetched from API) +β”‚ └── ... # anjunganStore, screenStore, navItems1, dll +β”‚ +β”œβ”€β”€ types/ # TypeScript interfaces & types +β”‚ β”œβ”€β”€ auth.ts, queue.ts, checkin.ts, setting.ts +β”‚ +└── data/ + └── users.db # SQLite database (user sync + device config) +``` + +--- + +## πŸ”Œ API Endpoints & External Services + +### Environment Variables (`.env`) + +| Variable | Deskripsi | Value (Juli 2026) | +|---|---|---| +| `ANTRIAN_API_URL` | API antrian utama (Go backend) | `http://10.10.150.131:8089/api/v1` | +| `VERIFICATION_API_BASE_URL` | Alias untuk ANTRIAN_API_URL | (same) | +| `VISIT_API_URL` | API visit/kunjungan pasien | `http://10.10.123.135:8084/api/v1` | +| `WS_API_URL` | WebSocket URL | `ws://10.10.123.135:8084/api/v1/ws` | +| `EXTERNAL_API_BASE_URL` | External API (JWT validation) | `http://10.10.123.135:8084` | +| `KEYCLOAK_ISSUER` | Keycloak realm URL | `https://auth.rssa.top/realms/sandbox` | +| `AUTH_ORIGIN` | Aplikasi origin URL | `http://10.10.150.175:3000` | +| `HOST` | Dev server host | `http://10.10.150.175:3000` | + +### Runtime Config (`nuxt.config.ts`) + +``` +runtimeConfig.public.verificationApiBaseUrl β†’ ANTRIAN_API_URL (antrian API) +runtimeConfig.public.externalApiBaseUrl β†’ VISIT_API_URL (visit API) +runtimeConfig.public.wsBaseUrl β†’ WS_API_URL (WebSocket) +``` + +### External Backend APIs + +1. **Antrian API** (`verificationApiBaseUrl`) β€” Go backend + - `GET /klinik/reguler` β€” Fetch daftar klinik reguler + - `GET /loket/ruang` β€” Fetch daftar ruangan per klinik + - `GET /loket/{id}` β€” Fetch pasien per loket + - `GET /dokter/{id}` β€” Fetch data dokter per klinik + - `POST /tiket/generate` β€” Generate tiket antrian + - `POST /tiket/checkin` β€” Check-in pasien + - `GET /permission` β€” Fetch permission/hak akses + +2. **Visit API** (`externalApiBaseUrl`) β€” Visit/kunjungan + - `GET /visit?klinik_id={id}` β€” Fetch data pasien per klinik + - `POST /external/validate-token` β€” Validate JWT token + +3. **WebSocket** (`wsBaseUrl`) + - Real-time queue updates, connected via `useWebSocket.ts` + +> **PENTING**: Semua kode menggunakan `config.public.verificationApiBaseUrl` dengan fallback hardcoded. Saat ganti IP, ubah di `.env` lalu **restart dev server**. Nuxt hanya membaca `.env` saat startup! + +--- + +## πŸ—„οΈ Store Architecture + +### Hirarki Store + +``` +masterStore (BACKWARD COMPAT LAYER β€” JANGAN TULIS LANGSUNG) + β”œβ”€β”€ clinicStore β†’ Single source of truth untuk data KLINIK + β”œβ”€β”€ loketStore β†’ Data LOKET (counter antrian) + β”œβ”€β”€ ruangStore β†’ Data RUANG per klinik + └── penunjangStore β†’ Data PENUNJANG medis + +queueStore β†’ Data ANTRIAN PASIEN (terbesar, 136KB) +doctorStore β†’ Data DOKTER (fetched per klinik) +anjunganStore β†’ Config ANJUNGAN (kiosk) +screenStore β†’ Config SCREEN display +antreanMasukScreenStore β†’ Config screen antrian masuk +navItems1 β†’ Navigation items + hak akses filter +permissionStore β†’ Permission data +verificationStore β†’ Verifikasi akun +``` + +### Store Schema Migration +- `app.vue` manages `STORE_SCHEMA_VERSION` (currently `3`) +- Saat versi tidak cocok, semua localStorage Pinia di-clear +- **Naikkan versi** saat ada perubahan struktur state + +--- + +## πŸ” Authentication Flow + +1. **Login**: User klik login β†’ `keycloak-login.ts` β†’ redirect ke Keycloak +2. **Callback**: Keycloak redirect back β†’ `keycloak-callback.get.ts` β†’ exchange code for token β†’ create session cookie +3. **Session**: `session.get.ts` validates cookie β†’ returns user data +4. **Middleware**: `auth.ts` checks session on every protected route +5. **User Sync**: `userSync.ts` syncs Keycloak users to local SQLite DB + +--- + +## ⚠️ Gotchas & Known Issues (HARUS DIBACA SEBELUM DEBUG) + +1. **ENV reload**: Nuxt hanya membaca `.env` saat startup. Setelah ubah `.env`, HARUS restart dev server (`Ctrl+C` β†’ `npm run dev`). + +2. **Hardcoded fallback IPs**: Banyak file masih punya fallback IP lama. Saat ganti IP, ubah `.env` + restart server. JANGAN cuma ubah satu file. + +3. **`totalQuota === 0` filter di ruangStore**: Klinik dengan `totalQuota: 0` diskip dari Admin Klinik Ruang. Ini menyembunyikan klinik yang valid tapi belum dikonfigurasi kuotanya. Trade-off yang disengaja. + +4. **masterStore adalah proxy**: Jangan langsung tulis data ke masterStore. Selalu gunakan store yang sesuai (clinicStore, loketStore, ruangStore, penunjangStore). + +5. **File besar** (hati-hati saat edit): + - `CheckInPasien/checkIn.vue` (~230KB) + - `queueStore.ts` (~136KB) + - `AdminKlinikRuang/[kodeKlinik].vue` (~111KB) + +6. **SQLite DB path**: `data/users.db` β€” digunakan untuk konfigurasi device & user sync. Di Docker, di-mount sebagai volume. + +7. **WebSocket auto-upgrade**: `useWebSocket.ts` otomatis upgrade `ws://` ke `wss://` jika halaman diakses via HTTPS. + +8. **Pinia persist `paths` type mismatch**: Gunakan `// @ts-ignore` untuk properti `paths` karena kompatibel runtime tapi melanggar validasi tipe. + +--- + +## πŸ”— Key File Quick Reference + +| Kebutuhan | File | +|---|---| +| Ganti API URL | `.env` β†’ restart dev server | +| Auth flow | `server/api/auth/` | +| Konfigurasi Nuxt | `nuxt.config.ts` | +| Data klinik | `stores/clinicStore.js` | +| Data antrian | `stores/queueStore.ts` | +| Data ruang | `stores/ruangStore.js` | +| Data loket | `stores/loketStore.js` | +| Sidebar/Navigation | `stores/navItems1.ts` + `components/layout/SideBar.vue` | +| Design tokens | `assets/scss/_colors.scss`, `_variables.scss` | +| Database schema | `server/utils/configDb.ts` | +| User management | `server/api/users/` + `server/utils/userSync.ts` | +| WebSocket | `composables/useWebSocket.ts` | +| Thermal print | `composables/useThermalPrint.ts` | + +--- + +## πŸš€ Development Commands + +```bash +npm run dev # Start dev server +npm run dev:https # Start with HTTPS + host 0.0.0.0 +npm run build # Production build +npm run preview # Preview production build +npm run test # Run Vitest +docker compose up -d # Deploy production +``` diff --git a/.agents/skills/web-antrean-coding-standards/SKILL.md b/.agents/skills/web-antrean-coding-standards/SKILL.md new file mode 100644 index 0000000..e7ed4e3 --- /dev/null +++ b/.agents/skills/web-antrean-coding-standards/SKILL.md @@ -0,0 +1,173 @@ +--- +name: web-antrean-coding-standards +description: Aturan dasar pengkodean dan konvensi untuk project web-antrean berbasis Nuxt 3, Vue 3, TypeScript, Pinia, dan Vuetify. +--- + +# πŸ“œ Web Antrean Coding Standards + +Skill ini berisi standar pengkodean wajib yang harus diikuti saat memodifikasi atau membuat kode baru di project `web-antrean`. + +## 1. Komentar & Dokumentasi (WAJIB) +- **Tiap Fungsi/Method/Computed/Watcher HARUS dikomentari.** +- Gunakan JSDoc (`/** ... */`) untuk mendeskripsikan tujuan fungsi. +- Jika fungsi kompleks atau memiliki parameter spesifik, gunakan tag `@param`, `@returns`. +- Berikan komentar singkat (`//`) di dalam body fungsi jika ada logika yang tidak langsung jelas (non-obvious). + +```typescript +// βœ… CONTOH BENAR +/** + * Menghitung total antrean aktif untuk loket tertentu. + * @param {string} loketId - ID unik dari loket. + * @returns {number} Jumlah antrean berstatus 'menunggu'. + */ +const countActiveQueue = (loketId: string): number => { + // Hanya hitung pasien yang belum dipanggil atau di-skip + return allPatients.value.filter(p => p.loketId === loketId && p.status === 'menunggu').length; +}; +``` + +## 2. Struktur Komponen (Vue 3 / Nuxt 3) +- Gunakan `