admin/services/events.ts
alisaza 82593dc18c refactor(events): update event management components and remove unused files
- Replaced `LIST_PUBLIC_CATEGORIES` with `LIST_ADMIN_CATEGORIES_FLAT` in `ArticleFormModal.tsx`.
- Removed the "Add Event" button from the dashboard page.
- Simplified the `EventsPage` by removing the button and adjusting the layout.
- Cleaned up the `AdminEventEditPage` by removing unnecessary props.
- Deleted unused layout and page files related to event creation.
- Updated `AdminAuthContent` to use `useAdminCitiesQuery` instead of `useDiscoveryCitiesQuery`.
- Refactored `EventGuestListAccessPanel` to remove the `accessMode` prop and adjust API calls accordingly.
- Removed several unused components and tests related to event creation, enhancing project maintainability.
2026-09-07 18:09:55 +03:30

215 lines
7.9 KiB
TypeScript

import type {
CreateEventDto,
CreateEventFaqDto,
CreateEventMediaDto,
EventCategoryResponseDto,
EventResponseDto,
} 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 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<EventCategory[]> {
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
}
/** Admin approval is one half of the two-key publication workflow. */
export async function approveEventAsAdmin(eventId: string): Promise<CreatedEvent> {
const response = await adminEventsApi.adminEventsControllerApprove(eventId)
return unwrapApiPayload<CreatedEvent>(response.data)
}
/** Force-publish bypass: skips the request/approve flow entirely. */
export async function publishEventAsAdmin(eventId: string): Promise<CreatedEvent> {
const response = await adminEventsApi.adminEventsControllerPublish(eventId)
return unwrapApiPayload<CreatedEvent>(response.data)
}
export async function rejectEventAsAdmin(eventId: string, rejectionReason: string): Promise<CreatedEvent> {
const response = await adminEventsApi.adminEventsControllerReject(eventId, { rejectionReason })
return unwrapApiPayload<CreatedEvent>(response.data)
}
export async function cancelEventAsAdmin(eventId: string): Promise<CreatedEvent> {
const response = await adminEventsApi.adminEventsControllerCancel(eventId)
return unwrapApiPayload<CreatedEvent>(response.data)
}
export async function completeEventAsAdmin(eventId: string): Promise<CreatedEvent> {
const response = await adminEventsApi.adminEventsControllerComplete(eventId)
return unwrapApiPayload<CreatedEvent>(response.data)
}
export async function deleteEventAsAdmin(eventId: string): Promise<CreatedEvent> {
const response = await axiosInstance.delete(API_ROUTES.EVENTS.ADMIN_DELETE(eventId))
return unwrapApiPayload<CreatedEvent>(response.data)
}
export async function updateEventReservedCapacity(eventId: string, reservedCapacity: number): Promise<CreatedEvent> {
const response = await axiosInstance.patch(API_ROUTES.EVENTS.ADMIN_RESERVED_CAPACITY(eventId), { reservedCapacity })
return unwrapApiPayload<CreatedEvent>(response.data)
}
/** Admin can edit any organizer's event (same field locks as host). */
export async function updateEventAsAdmin(eventId: string, payload: Partial<CreateEventPayload>): Promise<CreatedEvent> {
const response = await axiosInstance.patch(API_ROUTES.EVENTS.ADMIN_DETAIL(eventId), payload)
return unwrapApiPayload<CreatedEvent>(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<CreatedEvent> {
const response = await axiosInstance.patch(API_ROUTES.EVENTS.ADMIN_COMMISSION(eventId), { commissionPercent })
return unwrapApiPayload<CreatedEvent>(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<CreatedEvent> {
const response = await axiosInstance.get(API_ROUTES.EVENTS.FOR_EDIT(eventId))
return unwrapApiPayload<CreatedEvent>(response.data)
}
/** Admin detail including bookmarkCount + organizer contact. */
export async function fetchAdminEventDetail(eventId: string): Promise<CreatedEvent> {
const response = await axiosInstance.get(API_ROUTES.EVENTS.ADMIN_DETAIL(eventId))
return unwrapApiPayload<CreatedEvent>(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<void> {
await eventExtrasApi.eventMediaControllerCreate(eventId, payload)
}
export async function updateEventMedia(eventId: string, mediaId: string, payload: Partial<CreateEventMediaPayload>): Promise<void> {
await eventExtrasApi.eventMediaControllerUpdate(eventId, mediaId, payload)
}
export async function deleteEventMedia(eventId: string, mediaId: string): Promise<void> {
await eventExtrasApi.eventMediaControllerRemove(eventId, mediaId)
}
export async function createEventFaq(eventId: string, payload: CreateEventFaqPayload): Promise<void> {
await eventExtrasApi.eventFaqsControllerCreate(eventId, payload)
}
export async function updateEventFaq(eventId: string, faqId: string, payload: Partial<CreateEventFaqPayload>): Promise<void> {
await eventExtrasApi.eventFaqsControllerUpdate(eventId, faqId, payload)
}
export async function deleteEventFaq(eventId: string, faqId: string): Promise<void> {
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<string, unknown>
createdBy: string
reviewedBy: string | null
rejectionReason: string | null
submittedAt: string
decidedAt: string | null
}
export async function fetchAdminPendingEventRevision(eventId: string): Promise<EventRevision | null> {
try {
const response = await axiosInstance.get(API_ROUTES.EVENTS.ADMIN_REVISION_PENDING(eventId))
return unwrapApiPayload<EventRevision>(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<CreatedEvent> {
const response = await axiosInstance.patch(API_ROUTES.EVENTS.ADMIN_REVISION_APPROVE(eventId, revisionId))
return unwrapApiPayload<CreatedEvent>(response.data)
}
export async function rejectEventRevisionAsAdmin(eventId: string, revisionId: string, rejectionReason: string): Promise<EventRevision> {
const response = await axiosInstance.patch(API_ROUTES.EVENTS.ADMIN_REVISION_REJECT(eventId, revisionId), {
rejectionReason,
})
return unwrapApiPayload<EventRevision>(response.data)
}