feat(desa): Kalender Event Budaya — fitur admin/public, seeder, pagination, fix duplicate options

- Tambah fitur Kalender Event Budaya di admin CMS (list, detail, edit, hapus)
- Tambah state Valtio (create, findMany, findUnique, edit, delete, findUpcoming)
- Tambah endpoint API /find-upcoming untuk event mendatang
- Tambah halaman public /darmasaba/desa/event-budaya dengan pagination 5 data/halaman
- Switch public page dari findUpcoming ke findMany agar pagination berjalan
- Tambah menu "Kalender Event Budaya" di navbar (id: 2.9)
- Perluas seeder event budaya: 8 → 34 events mencakup 2025-2026
- Fix: deduplikasi kategoriOptions di kegiatan-desa public page (Mantine Select error)
- Hapus STRUKTUR.md yang sudah tidak relevan

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-21 16:28:13 +08:00
parent 0a3dc1dc43
commit e9e7c17ee3
12 changed files with 648 additions and 906 deletions

View File

@@ -0,0 +1,67 @@
# Summary: Event Budaya — Seeder, Pagination & Fix Duplicate Options
**Tanggal:** 2026-05-21
**Branch:** `tasks/event-budaya/feat-seeder-pagination-fix-duplicate/20260521`
**Scope:** Fitur Kalender Event Budaya (admin + public) + fix bug + seeder
---
## Perubahan yang Dilakukan
### 1. Fix Bug: Duplicate Options di Halaman Kegiatan Desa (Public)
**File:** `src/app/darmasaba/(pages)/desa/kegiatan-desa/_lib/layoutTabs.tsx`
- **Masalah:** Mantine `<Select>` error `Duplicate options are not supported` untuk value "Sosial" karena data kategori di DB memiliki nama duplikat.
- **Fix:** Deduplikasi `kategoriOptions` menggunakan `Map` sebelum data masuk ke `<Select>`.
- **Root cause:** Data duplikat di tabel kategori kegiatan desa — perlu dibersihkan dari sisi DB.
### 2. Fitur Kalender Event Budaya (Admin CMS)
**Files:**
- `src/app/admin/(dashboard)/desa/event-budaya/page.tsx` — List event dengan table, aksi edit/hapus/lihat
- `src/app/admin/(dashboard)/desa/event-budaya/[id]/page.tsx` — Detail & edit event
- `src/app/admin/(dashboard)/desa/event-budaya/layout.tsx` — Layout wrapper admin
- `src/app/admin/(dashboard)/_state/desa/eventBudaya.ts` — State Valtio: create, findMany, findUnique, edit, delete, findUpcoming
- `src/app/api/[[...slugs]]/_lib/desa/event-budaya/index.ts` — Elysia router: tambah endpoint `/find-upcoming`
- `src/app/api/[[...slugs]]/_lib/desa/event-budaya/find-upcoming.ts` — Query event mendatang (tanggal >= hari ini, max 20)
### 3. Fitur Kalender Event Budaya (Public)
**File:** `src/app/darmasaba/(pages)/desa/event-budaya/page.tsx`
- Menampilkan list event budaya dengan pagination **5 data per halaman**
- Menggunakan `eventBudayaState.findMany` (bukan `findUpcoming`) agar pagination berjalan
- Komponen `Pagination` dari Mantine di bawah list
- Skeleton loading saat data belum tersedia
### 4. Navigasi Navbar
**File:** `src/con/navbar-list-menu.ts`
- Tambah menu **"Kalender Event Budaya"** (id: 2.9) di bawah "Kegiatan Desa" dengan href `/darmasaba/desa/event-budaya`
### 5. Seeder: Data Event Budaya
**Files:**
- `prisma/data/desa/event-budaya/event-budaya.json` — Diperluas dari **8 → 34 events**
- `prisma/_seeder_list/desa/event-budaya/seed_event_budaya.ts` — Tidak diubah (sudah kompatibel)
**Cakupan seeder (20252026):**
- Hari Raya Hindu Bali: Galungan (×5), Kuningan (×5), Nyepi, Melasti, Saraswati, Pagerwesi
- Tumpek: Landep, Uduh, Krulut
- Upacara desa: Ngusaba Desa, Pujawali Pura Puseh, Melaspas
- Event nasional: HUT RI ke-80 & ke-81, Hari Kesaktian Pancasila
- Event budaya: Festival Budaya Desa, Parade Ogoh-Ogoh, Pementasan Wayang Kulit
---
## Arsitektur yang Diikuti
- **State management:** Valtio proxy di `_state/desa/eventBudaya.ts`
- **API:** Elysia.js endpoint di `/api/desa/eventbudaya/*`
- **Pagination:** Server-side via `findMany` (skip/take Prisma), state sudah punya `page`, `totalPages`, `total`
- **Seeder:** JSON data + `upsert` Prisma (aman dijalankan berulang)
---
## Catatan
- `STRUKTUR.md` dihapus (file lama tidak relevan)
- Seeder bisa dijalankan dengan `bun run prisma/seed.ts`
- Bug duplicate kategori di DB belum dibersihkan dari sisi data — hanya di-guard di UI