# Setrip — Admin Trip Operations Roadmap (ARCHIVED — DELIVERED 2026-05-18) Admin perlu visibilitas penuh atas trip dan bisa intervensi (cancel + auto-refund) saat organizer unreachable atau ada masalah safety. > **Skenario nyata:** peserta lapor trip berjalan tidak sesuai itinerary. Organizer tidak responsif. Hari berikutnya peserta minta refund. Saat ini admin harus refund satu-satu manual via `/admin/refunds` tanpa konteks trip atau cara cancel trip-nya. --- ## Status delivery | Phase | Status | Catatan | |---|---|---| | Phase 1 — List + Detail View | ✅ Delivered | Filter dasar `status` + search `q`. Filter advanced (date range, organizer dropdown, kategori) belum dipakai — bisa ditambah di iterasi berikut kalau ada kebutuhan konkret. | | Phase 2 — Admin Force-Cancel | ✅ Delivered | `tripService.closeTrip` di-refactor terima actor union (ORGANIZER \| ADMIN). Migration menambah `Trip.cancelledByAdminId` + `cancelledReason`. | | Phase 3 — Trip Edit Override | ⏳ Deferred | Opsional, skip MVP. Evaluasi ulang kalau ada keluhan konkret. | --- ## Phase 1 — Trip List + Detail View ✅ | # | Item | Status | File | |---|---|---|---| | 1.1 | `tripRepo.searchForAdmin({ q?, status? })` | ✅ | [server/repositories/trip.repo.ts](../../server/repositories/trip.repo.ts) | | 1.2 | Page `/admin/trips` — list + tab status (ALL/OPEN/FULL/CLOSED/COMPLETED) + search bar | ✅ | [app/admin/trips/page.tsx](../../app/admin/trips/page.tsx) | | 1.3 | Filter: tanggal range, organizer dropdown, kategori | ⏳ | Deferred — search `q` sudah cover sebagian (search organizer name/email). | | 1.4 | Page `/admin/trips/[id]` — full detail (trip core + itinerary items + participants) | ✅ | [app/admin/trips/[id]/page.tsx](../../app/admin/trips/[id]/page.tsx) | | 1.5 | Stat cards: kapasitas, confirmed, pending, cancelled | ✅ | [app/admin/trips/[id]/page.tsx](../../app/admin/trips/[id]/page.tsx) | | 1.6 | Link "Trips" di admin navbar | ✅ | [components/admin/admin-sidebar.tsx](../../components/admin/admin-sidebar.tsx) | --- ## Phase 2 — Admin Force-Cancel Trip ✅ | # | Item | Status | File | |---|---|---|---| | 2.1 | Migration: `cancelledByAdminId` (FK User, ON DELETE SET NULL) + `cancelledReason` | ✅ | `prisma/migrations/20260518150000_add_trip_admin_cancel/` | | 2.2 | Refactor `tripService.closeTrip` terima `actor: { type: "ORGANIZER" \| "ADMIN", ... }` | ✅ | [server/services/trip.service.ts](../../server/services/trip.service.ts) | | 2.3 | Server action `adminCancelTripAction(tripId, reason)` — guard isAdmin, reason min 10 char | ✅ | [features/trip/actions.ts](../../features/trip/actions.ts) | | 2.4 | UI: tombol "Cancel Trip (Admin)" di `/admin/trips/[id]` dengan modal reason wajib + summary impact | ✅ | [features/trip/components/admin-cancel-trip-button.tsx](../../features/trip/components/admin-cancel-trip-button.tsx) | | 2.5 | Badge "Dibatalkan admin" + reason di public trip detail | ⏳ | Deferred — kolom DB sudah ada, tinggal tambah UI saat ada kebutuhan transparansi. | **Tindakan manual yang sudah dilakukan:** none — admin tinggal pakai. **Tindakan manual yang masih perlu dilakukan ops:** 1. Jalankan migration di production: `npx prisma migrate deploy`. 2. Brief admin: kriteria reason yang valid (organizer unreachable >7 hari, dispute peserta tidak terselesaikan, safety issue). Reason wajib min 10 karakter untuk audit. --- ## Phase 3 — Trip Edit Override ⏳ (deferred) Skip MVP. Lihat versi awal di [ADMIN_ROADMAP.md](../../ADMIN_ROADMAP.md) kalau perlu re-open.