# Setrip — Admin User Management Roadmap (ARCHIVED — DELIVERED 2026-05-18, fully done) Admin perlu bisa cari user dan **suspend** akun yang melakukan abuse (scam, harassment, fake review). > **Skenario nyata:** organizer scam berkali-kali bikin trip palsu pakai alias berbeda. Peserta lapor harassment dari user lain di grup WA trip. --- ## Status delivery | Phase | Status | Catatan | |---|---|---| | Phase 1 — User List & Detail | ✅ Delivered | Search by email/name, filter tab (ALL/ACTIVE/SUSPENDED), stats (trip dibuat, booking, total spent). | | Phase 2 — User Suspension | ✅ Delivered | Schema baru `User.suspended`, auth gate sign-in + helper `requireActiveUser` di mutating actions, trip public list otomatis sembunyikan organizer suspended. | | Phase 3 — User Analytics | ✅ Delivered | Page `/admin/users/stats` dengan stats card (total/suspended/verified-organizer/active-organizer-30d/paid-participant-30d) + bar chart signup per minggu (8 minggu terakhir, inline SVG-free). | --- ## Phase 1 — User List & Detail ✅ | # | Item | Status | File | |---|---|---|---| | 1.1 | `userRepo.searchForAdmin({ q?, suspended? })` | ✅ | [server/repositories/user.repo.ts](../../server/repositories/user.repo.ts) | | 1.2 | Page `/admin/users` — list + search + tab filter (ALL/ACTIVE/SUSPENDED) | ✅ | [app/admin/users/page.tsx](../../app/admin/users/page.tsx) | | 1.3 | Page `/admin/users/[id]` — detail dengan trip dibuat + booking history + profile + verification | ✅ | [app/admin/users/[id]/page.tsx](../../app/admin/users/[id]/page.tsx) | | 1.4 | Stats cards: trip dibuat, booking aktif, total spent (PAID) | ✅ | [app/admin/users/[id]/page.tsx](../../app/admin/users/[id]/page.tsx) | | 1.5 | Link "Users" di admin navbar | ✅ | [components/admin/admin-sidebar.tsx](../../components/admin/admin-sidebar.tsx) | --- ## Phase 2 — User Suspension ✅ | # | Item | Status | File | |---|---|---|---| | 2.1 | Migration: `suspended Boolean`, `suspendedAt`, `suspendedReason`, `suspendedById` (FK User SET NULL) | ✅ | `prisma/migrations/20260518160000_add_user_suspension/` | | 2.2 | `userService.suspendUser` + `unsuspendUser` (idempotent + cek tidak suspend diri sendiri + reason min 10 char) | ✅ | [server/services/user.service.ts](../../server/services/user.service.ts) | | 2.3 | Block sign-in di NextAuth `signIn` callback (email-based, jalan untuk Credentials + OAuth) | ✅ | [lib/auth.ts](../../lib/auth.ts) | | 2.4 | Helper `requireActiveUser(userId)` — lookup fresh dari DB | ✅ | [lib/auth-guards.ts](../../lib/auth-guards.ts) | | 2.5 | Wire `requireActiveUser` di `createTripAction` + `joinTripAction` | ✅ | [features/trip/actions.ts](../../features/trip/actions.ts) | | 2.6 | Filter trip public list: `organizer: { suspended: false }` di `findOpen` | ✅ | [server/repositories/trip.repo.ts](../../server/repositories/trip.repo.ts) | | 2.7 | UI: tombol Suspend/Unsuspend di `/admin/users/[id]` dengan modal reason wajib | ✅ | [features/admin/components/suspend-user-button.tsx](../../features/admin/components/suspend-user-button.tsx) | | 2.8 | Badge "SUSPENDED" di user list + detail header (red border accent) | ✅ | list & detail pages | | 2.9 | Server actions `suspendUserAction` + `unsuspendUserAction` (guard isAdmin) | ✅ | [features/admin/actions.ts](../../features/admin/actions.ts) | **Tindakan manual ops:** 1. Apply migration: `npx prisma migrate deploy`. 2. Brief admin: kriteria suspend (scam, harassment, repeated TOS violation). Reason wajib min 10 char. 3. Wire `requireActiveUser` ke action mutating lain saat dibuat (`createReviewAction`, dst). 4. Pertimbangkan: bikin halaman info "Akun ditangguhkan" untuk UX saat suspended user coba login. --- ## Phase 3 — User Analytics ✅ | # | Item | Status | File | |---|---|---|---| | 3.1 | Stats: total users, suspended, verified organizers, active organizer 30d (bikin trip), paid participant 30d | ✅ | [app/admin/users/stats/page.tsx](../../app/admin/users/stats/page.tsx) | | 3.2 | Bar chart signup per minggu (8 minggu terakhir, pakai inline div height % — no chart library) | ✅ | [app/admin/users/stats/page.tsx](../../app/admin/users/stats/page.tsx) | | 3.3 | Link "📊 Stats" di header `/admin/users` | ✅ | [app/admin/users/page.tsx](../../app/admin/users/page.tsx) |