Rancang admin campaign sebagai pekerjaan bertahap: otorisasi, validasi, server action, UI, dan verifikasi constraint. Jangan menyamakan halaman tersembunyi dengan admin yang aman.
40m bacaanKuis WajibMicro Badge Lesson
Admin: Tambah & Ubah Campaign
Sampai titik ini, campaign berasal dari seed migration. Itu cukup untuk belajar homepage dan detail, tapi platform asli butuh cara membuat dan mengubah campaign.
Di sinilah banyak project AI coding mulai kacau. Prompt seperti ini terlalu besar:
text
buatkan admin campaign lengkap
Agent bisa membuat UI, auth palsu, mutation tanpa guard, status langsung published, atau policy database yang membuka data terlalu luas. Hasilnya mungkin terlihat seperti admin, tapi belum tentu aman.
Admin bukan sekadar halaman yang URL-nya sulit ditebak. Admin berarti mutasi data dibatasi oleh otorisasi yang jelas.
Pisahkan pekerjaan admin menjadi lapis kecil
Untuk admin campaign, pecah menjadi empat lapis:
otorisasi — siapa yang boleh mengelola campaign;
validasi — input apa yang sah;
server action — operasi create/update di server;
UI admin — form dan daftar untuk manusia.
Jangan campur semuanya dalam satu prompt. Kalau migration rusak, kamu ingin tahu sebelum UI ditulis. Kalau validasi salah, kamu ingin memperbaikinya sebelum server action menyimpan data.
Keputusan MVP yang jujur
Starter belum punya halaman login admin penuh. Jadi jangan berpura-pura admin sudah final.
Untuk desain MVP, kamu bisa membuat guard sederhana:
role admin disimpan di metadata user Supabase Auth;
helper database has_role('admin') mengecek role user aktif;
server action admin wajib mengecek role sebelum insert/update;
halaman admin boleh dibuat, tetapi pengujian browser penuh menunggu login/admin session tersedia.
Catatan penting: menyembunyikan link admin di UI tidak cukup. Kalau server action tidak mengecek admin, user yang tahu endpoint/action bisa mencoba mutasi.
Constraint database tetap jadi pagar
Migration awal sudah memberi constraint penting:
campaigns.slug unik;
target_amount > 0;
status hanya draft, published, paused, completed, archived;
public select hanya untuk published.
Admin harus menghormati ini.
Campaign baru sebaiknya mulai sebagai draft. Publish adalah keputusan terpisah, bukan efek otomatis dari create form. Ini mencegah campaign setengah matang muncul ke publik.
Prompt 1: lapis otorisasi
text
Mulai dari AGENTS.md, DESIGN.md, dan docs/README.md.Tugas kecil #1: tambahkan lapis otorisasi admin campaign.Baca:- supabase/migrations/20260829_vertical_slice.sql- docs/project-rules.md- docs/data-contract.mdBuat migration baru:- supabase/migrations/20260910_campaign_admin.sqlIsi migration:1. Function public.has_role(p_role text) yang mengecek role user aktif dari auth.users app_metadata.2. Policy admin untuk campaigns: - admin boleh select semua campaign, - admin boleh insert campaign, - admin boleh update campaign.3. Policy publik existing yang hanya membaca status published tidak boleh diubah.4. Jangan mengubah tabel donations, donors, payments, atau donation flow.Acceptance criteria:- Migration bisa dijalankan.- Policy publik published tetap ada.- Policy admin baru memakai public.has_role('admin').- Draft tetap tidak bisa dibaca publik.Laporkan isi migration dan cara verifikasinya.
Kalau agent mengubah policy publik agar semua authenticated bisa membaca semua campaign, itu salah. Authenticated bukan otomatis admin.
Prompt 2: validasi dan server action
text
Tugas kecil #2: buat validasi dan server action admin campaign.Baca AGENTS.md, docs/README.md, docs/data-contract.md, dan migration campaign admin.Buat:- src/lib/campaigns/validations.ts- src/app/admin/campaigns/actions.tsRequirement validation:- title wajib.- slug hanya huruf kecil, angka, dan tanda hubung.- summary opsional.- description wajib.- target_amount harus angka > 0.- status hanya draft/published/paused/completed/archived.Requirement server action:- createCampaign membaca FormData, validasi input, cek admin, lalu insert campaign.- Campaign baru default draft kecuali ada aksi publish yang eksplisit.- updateCampaign cek admin, validasi input, lalu update campaign berdasarkan id.- Tangkap unique violation 23505 untuk slug duplikat dengan pesan yang bisa dipahami.- Revalidate halaman publik dan halaman admin yang relevan.Jangan membuat UI di langkah ini.Jangan mengubah donation action.Jangan mengubah migration awal.Acceptance criteria:- Non-admin tidak boleh create/update.- Slug invalid ditolak sebelum insert.- target_amount <= 0 ditolak.- Slug duplikat menghasilkan pesan "Slug sudah dipakai" atau sejenisnya.
Kenapa FormData perlu divalidasi? Karena semua nilai dari form datang sebagai string. Jangan percaya input UI. Parse di server.
Prompt 3: UI admin minimal
text
Tugas kecil #3: buat UI admin campaign minimal.Baca AGENTS.md, DESIGN.md, docs/README.md, dan actions admin yang sudah dibuat.Buat halaman:- src/app/admin/campaigns/page.tsx- src/app/admin/campaigns/new/page.tsx- src/app/admin/campaigns/[id]/edit/page.tsxRequirement UI:- daftar semua campaign untuk admin, termasuk draft.- form tambah campaign.- form edit campaign.- tampilkan status campaign dengan badge sederhana.- copy jelas, tidak manipulatif, dan sesuai DESIGN.md.- semua input punya label.Batasan:- Jangan membuat login UI penuh di langkah ini.- Jangan mengubah halaman publik.- Jangan mengubah donation flow.- Jangan memakai gambar manusia/aurat, musik, simbol agama lain, dark pattern, atau copy hiperbolis.Acceptance criteria:- Halaman admin memakai server action yang sudah dibuat.- Form punya label dan error state yang bisa dibaca.- Halaman publik tetap hanya menampilkan published.- npm run lint dan npm run build berhasil.
UI admin minimal tidak harus mewah. Yang penting ia memakai guard dan validasi yang benar.
Verifikasi yang realistis
Beberapa bagian bisa kamu verifikasi tanpa login UI lengkap.
Kalau login UI belum dibuat, tulis statusnya dengan jujur:
text
Admin campaign sudah punya rancangan guard dan server-side check, tetapi browser flow admin penuh menunggu login/admin session tersedia.
Ini bukan kelemahan materi. Ini cara kerja yang sehat. Kamu membedakan mana yang sudah terbukti, mana yang masih butuh gate berikutnya.
Prinsip yang perlu dibawa
Admin feature selalu punya dua lapis:
UI untuk manusia;
authorization di server/database untuk keamanan.
AI sering cepat membuat UI, tapi kamu yang harus memastikan mutasi data tidak terbuka. Karena itu prompt admin harus atomic dan eksplisit menyebut perilaku yang tidak boleh berubah.
Checkpoint
Pekerjaan admin dipecah menjadi otorisasi, validasi, server action, dan UI.
Policy public published tidak dilemahkan.
Server action mengecek admin sebelum mutasi.
Campaign baru tidak otomatis public tanpa keputusan publish.
Constraint slug unique dan target_amount > 0 tetap diuji di database.
Halaman publik dan donation flow tetap jalan.
Status keamanan admin dicatat jujur jika login UI belum tersedia.
Kalau bagian admin ini terasa “kok banyak pagar?”, itu memang intinya. Semakin dekat fitur ke data penting, semakin kecil ruang untuk prompt asal jadi. UI boleh sederhana, tapi otorisasi dan constraint tidak boleh pura-pura.
Checkpoint KuisTarget: 70%
Kuis 03.3 — Admin: Tambah & Ubah Campaign
Kuis ini wajib untuk sertifikat. Kamu tetap bisa lanjut ke pelajaran berikutnya dan mengerjakannya nanti.