import type { CreateEventCategoryDto, EventCategoryResponseDto } from '@/api/generated/models' import { createServiceError, errorResult, handleServiceError, type ServiceCallOptions, type ServiceResult, shouldBubbleErrorToParent, successResult, } from '@/services/errorHandler' import { unwrapApiData } from '@/services/apiResponse' import { getAdminEventCategories } from '@/api/generated/admin-event-categories/admin-event-categories' import { getEventCategories } from '@/api/generated/event-categories/event-categories' import { texts } from '@/texts' export type EventCategory = EventCategoryResponseDto export type EventCategoryPayload = CreateEventCategoryDto const eventCategoriesApi = getEventCategories() const adminEventCategoriesApi = getAdminEventCategories() /** * Public, unpaginated flat list of *active* categories — `GET /event-categories` * (see backend/src/modules/event-categories/event-categories.controller.ts). * Used by the consumer app's categories tab; unlike GET_CATEGORY_CHILDREN * below, this returns every active category in one call (parentId included * per row), so the caller builds the tree client-side instead of fetching * level-by-level. */ export const LIST_PUBLIC_CATEGORIES = async (options?: ServiceCallOptions): Promise> => { try { const res = await eventCategoriesApi.eventCategoriesControllerList() const payload = res.data if (!payload.success) { throw createServiceError(payload.message || texts.events.categoriesListFailed) } const items = unwrapApiData(payload) return successResult({ items: items ?? [] }) } catch (error) { const normalizedError = handleServiceError(error, options) if (shouldBubbleErrorToParent(options)) { throw normalizedError } return errorResult(normalizedError) } } /** * One "level" of the category tree: every direct child of `parentId` * (or every root category, when `parentId` is null). Page size is fixed * at the backend's max (100) — there's no pagination UI within a tree * level; if an organizer ever needs more than 100 siblings under one * parent, that's a real product problem, not something to paginate away. */ export const GET_CATEGORY_CHILDREN = async ( parentId: number | null, options?: ServiceCallOptions ): Promise> => { try { const res = await adminEventCategoriesApi.adminEventCategoriesControllerList({ pageSize: 100, filters: { parentId: parentId === null ? 'null' : String(parentId) }, }) const payload = res.data if (!payload.success) { throw createServiceError(payload.message || texts.events.categoriesListFailed) } const list = unwrapApiData(payload) return successResult(list?.items ?? []) } catch (error) { const normalizedError = handleServiceError(error, options) if (shouldBubbleErrorToParent(options)) { throw normalizedError } return errorResult(normalizedError) } } export const CREATE_CATEGORY = async ( payload: EventCategoryPayload, options?: ServiceCallOptions ): Promise> => { try { const res = await adminEventCategoriesApi.adminEventCategoriesControllerCreate(payload) const body = res.data if (!body.success) { throw createServiceError(body.message || texts.events.categoryCreateFailed) } const category = unwrapApiData(body) if (!category?.id) { throw createServiceError(texts.common.invalidServerResponse) } return successResult(category) } catch (error) { const normalizedError = handleServiceError(error, options) if (shouldBubbleErrorToParent(options)) { throw normalizedError } return errorResult(normalizedError) } } export const UPDATE_CATEGORY = async ( id: number, payload: Omit, options?: ServiceCallOptions ): Promise> => { try { const res = await adminEventCategoriesApi.adminEventCategoriesControllerUpdate(id, payload) const body = res.data if (!body.success) { throw createServiceError(body.message || texts.events.categoryUpdateFailed) } const category = unwrapApiData(body) if (!category?.id) { throw createServiceError(texts.common.invalidServerResponse) } return successResult(category) } catch (error) { const normalizedError = handleServiceError(error, options) if (shouldBubbleErrorToParent(options)) { throw normalizedError } return errorResult(normalizedError) } } export const DELETE_CATEGORY = async (id: number, options?: ServiceCallOptions): Promise> => { try { const res = await adminEventCategoriesApi.adminEventCategoriesControllerRemove(id) const body = res.data if (!body.success) { throw createServiceError(body.message || texts.events.categoryDeleteFailed) } return successResult(unwrapApiData(body) ?? { success: true }) } catch (error) { const normalizedError = handleServiceError(error, options) if (shouldBubbleErrorToParent(options)) { throw normalizedError } return errorResult(normalizedError) } }