import type { CreateEventDto, CreateEventFaqDto, CreateEventMediaDto, EventCategoryResponseDto, EventResponseDto, AdminCreateEventDto, } from '@/api/generated/models' import { getAdminEventCategories } from '@/api/generated/admin-event-categories/admin-event-categories' import { getAdminEvents } from '@/api/generated/admin-events/admin-events' import { getEventExtras } from '@/api/generated/event-extras/event-extras' import { unwrapApiPayload } from '@/helpers/listResponse' import axiosInstance from '@/config/axios' import { API_ROUTES } from '@/services/config' export type EventCategory = EventCategoryResponseDto export type CreateEventPayload = CreateEventDto export type AdminCreateEventPayload = AdminCreateEventDto export type CreatedEvent = EventResponseDto export type CreateEventMediaPayload = CreateEventMediaDto export type CreateEventFaqPayload = CreateEventFaqDto const adminEventsApi = getAdminEvents() const adminEventCategoriesApi = getAdminEventCategories() const eventExtrasApi = getEventExtras() /** Full category tree for admin edit forms — admin list, not public discovery. */ export async function fetchEventCategories(): Promise { const items: EventCategory[] = [] let page = 1 let totalPages = 1 while (page <= totalPages) { const response = await adminEventCategoriesApi.adminEventCategoriesControllerList({ page, pageSize: 100, sort: 'sortOrder', }) const payload = unwrapApiPayload<{ items?: EventCategory[]; response?: { totalPages?: number } }>(response.data) const batch = Array.isArray(payload.items) ? payload.items : Array.isArray(payload) ? (payload as EventCategory[]) : [] items.push(...batch) totalPages = Number(payload.response?.totalPages ?? 1) page += 1 } return items } /** * Create a pre-approved draft for a verified host. Host still publishes; * backend notifies the host via `event_created_by_admin`. */ export async function createEventAsAdmin(payload: AdminCreateEventPayload): Promise { const response = await adminEventsApi.adminEventsControllerCreate(payload) return unwrapApiPayload(response.data) } /** Admin approval is one half of the two-key publication workflow. */ export async function approveEventAsAdmin(eventId: string): Promise { const response = await adminEventsApi.adminEventsControllerApprove(eventId) return unwrapApiPayload(response.data) } /** Force-publish bypass: skips the request/approve flow entirely. */ export async function publishEventAsAdmin(eventId: string): Promise { const response = await adminEventsApi.adminEventsControllerPublish(eventId) return unwrapApiPayload(response.data) } export async function rejectEventAsAdmin(eventId: string, rejectionReason: string): Promise { const response = await adminEventsApi.adminEventsControllerReject(eventId, { rejectionReason }) return unwrapApiPayload(response.data) } export async function cancelEventAsAdmin(eventId: string): Promise { const response = await adminEventsApi.adminEventsControllerCancel(eventId) return unwrapApiPayload(response.data) } export async function completeEventAsAdmin(eventId: string): Promise { const response = await adminEventsApi.adminEventsControllerComplete(eventId) return unwrapApiPayload(response.data) } export async function deleteEventAsAdmin(eventId: string): Promise { const response = await axiosInstance.delete(API_ROUTES.EVENTS.ADMIN_DELETE(eventId)) return unwrapApiPayload(response.data) } export async function updateEventReservedCapacity(eventId: string, reservedCapacity: number): Promise { const response = await axiosInstance.patch(API_ROUTES.EVENTS.ADMIN_RESERVED_CAPACITY(eventId), { reservedCapacity }) return unwrapApiPayload(response.data) } /** Admin can edit any organizer's event (same field locks as host). */ export async function updateEventAsAdmin(eventId: string, payload: Partial): Promise { const response = await axiosInstance.patch(API_ROUTES.EVENTS.ADMIN_DETAIL(eventId), payload) return unwrapApiPayload(response.data) } /** Admin-only: set (or, with null, clear) this event's platform commission override. */ export async function updateEventCommissionAsAdmin(eventId: string, commissionPercent: number | null): Promise { const response = await axiosInstance.patch(API_ROUTES.EVENTS.ADMIN_COMMISSION(eventId), { commissionPercent }) return unwrapApiPayload(response.data) } /** * Full event for edit forms. Backend authorizes admin (and owner); * admin panel uses this for the edit screen. */ export async function fetchEventForEdit(eventId: string): Promise { const response = await axiosInstance.get(API_ROUTES.EVENTS.FOR_EDIT(eventId)) return unwrapApiPayload(response.data) } /** Admin detail including bookmarkCount + organizer contact. */ export async function fetchAdminEventDetail(eventId: string): Promise { const response = await axiosInstance.get(API_ROUTES.EVENTS.ADMIN_DETAIL(eventId)) return unwrapApiPayload(response.data) } /** * Media/FAQ mutations share `/events/:id/...` extras endpoints; backend * authorizes event owner or admin. No separate admin CRUD routes exist. */ export async function createEventMedia(eventId: string, payload: CreateEventMediaPayload): Promise { await eventExtrasApi.eventMediaControllerCreate(eventId, payload) } export async function updateEventMedia(eventId: string, mediaId: string, payload: Partial): Promise { await eventExtrasApi.eventMediaControllerUpdate(eventId, mediaId, payload) } export async function deleteEventMedia(eventId: string, mediaId: string): Promise { await eventExtrasApi.eventMediaControllerRemove(eventId, mediaId) } export async function createEventFaq(eventId: string, payload: CreateEventFaqPayload): Promise { await eventExtrasApi.eventFaqsControllerCreate(eventId, payload) } export async function updateEventFaq(eventId: string, faqId: string, payload: Partial): Promise { await eventExtrasApi.eventFaqsControllerUpdate(eventId, faqId, payload) } export async function deleteEventFaq(eventId: string, faqId: string): Promise { await eventExtrasApi.eventFaqsControllerRemove(eventId, faqId) } export interface EventRevisionPayload { title?: string slug?: string shortDescription?: string description?: string categoryId?: number startsAt?: string endsAt?: string provinceId?: number cityId?: number address?: string lat?: number lng?: number isFree?: boolean price?: number capacity?: number genderRestriction?: string ageRestriction?: string cancellationFeePercent?: number cancellationFeePercent12To24Hours?: number cancellationFeePercentMoreThan24Hours?: number settings?: CreateEventPayload['settings'] media: CreateEventMediaPayload[] faqs?: CreateEventFaqPayload[] } export interface EventRevision { id: string eventId: string status: string payload: EventRevisionPayload & Record createdBy: string reviewedBy: string | null rejectionReason: string | null submittedAt: string decidedAt: string | null } export async function fetchAdminPendingEventRevision(eventId: string): Promise { try { const response = await axiosInstance.get(API_ROUTES.EVENTS.ADMIN_REVISION_PENDING(eventId)) return unwrapApiPayload(response.data) } catch (error) { const status = (error as { response?: { status?: number } })?.response?.status if (status === 404) return null throw error } } export async function approveEventRevisionAsAdmin(eventId: string, revisionId: string): Promise { const response = await axiosInstance.patch(API_ROUTES.EVENTS.ADMIN_REVISION_APPROVE(eventId, revisionId)) return unwrapApiPayload(response.data) } export async function rejectEventRevisionAsAdmin(eventId: string, revisionId: string, rejectionReason: string): Promise { const response = await axiosInstance.patch(API_ROUTES.EVENTS.ADMIN_REVISION_REJECT(eventId, revisionId), { rejectionReason, }) return unwrapApiPayload(response.data) }