'use client' import { useEffect, useMemo, useState } from 'react' import { useRouter } from 'next/navigation' import type { PaginationListColumnType } from '@/types' import PaginatedList from '@/components/PaginatedList' import PageNavbar from '@/components/layouts/PageNavbar' import AdminTableViewButton from '@/components/ui/AdminTableViewButton' import StatusChip from '@/components/ui/StatusChip' import axiosInstance from '@/config/axios' import { APP_ROUTES } from '@/constants/routes' import { EVENT_STATUS_FILTER_ITEMS, getBooleanStatus, getEventStatus } from '@/constants/status' import { formatCurrency, formatPersonName, coerceToString } from '@/helpers' import { formatPersianDate } from '@/lib/formatters' import { API_ROUTES } from '@/services/config' interface NamedEntity { id: number | string name: string } interface EventOrganizer { id: string firstName: string | null lastName: string | null } interface EventRow { id: string title: string status: string isDiscoverable: boolean isFree: boolean price: number category?: NamedEntity province?: NamedEntity city?: NamedEntity organizer?: EventOrganizer [key: string]: unknown } interface FilterOption { code: string name: string } const IS_FREE_FILTER_ITEMS: FilterOption[] = [ { code: 'true', name: 'بله' }, { code: 'false', name: 'خیر' }, ] const IS_DISCOVERABLE_FILTER_ITEMS: FilterOption[] = [ { code: 'true', name: 'بله' }, { code: 'false', name: 'خیر' }, ] const toSelectFilterItems = (items: NamedEntity[]): FilterOption[] => items.map((item) => ({ code: String(item.id), name: item.name })) const extractApiList = (raw: unknown): T[] => { if (Array.isArray(raw)) return raw as T[] if (typeof raw === 'object' && raw !== null && 'data' in raw) { const data = raw.data if (Array.isArray(data)) return data as T[] } return [] } const getOrganizer = (row: EventRow): EventOrganizer => { if (row.organizer && typeof row.organizer === 'object') { return row.organizer } return { id: '—', firstName: null, lastName: null } } const EventsPage = () => { const router = useRouter() const [categoryFilterItems, setCategoryFilterItems] = useState([]) const [cityFilterItems, setCityFilterItems] = useState([]) useEffect(() => { const loadFilterOptions = async () => { try { const [categoriesRes, citiesRes] = await Promise.all([ axiosInstance.get(API_ROUTES.EVENT_CATEGORIES.ADMIN_FLAT), axiosInstance.get(API_ROUTES.GEOGRAPHY.ALL_CITIES), ]) setCategoryFilterItems(toSelectFilterItems(extractApiList(categoriesRes.data))) setCityFilterItems(toSelectFilterItems(extractApiList(citiesRes.data))) } catch { setCategoryFilterItems([]) setCityFilterItems([]) } } void loadFilterOptions() }, []) const columns = useMemo( () => [ { field: 'title', label: 'عنوان', filterable: true, type: 'text', sortable: false, }, { field: 'status', label: 'وضعیت', filterable: true, type: 'select', sortable: false, filterItems: EVENT_STATUS_FILTER_ITEMS, }, { field: 'isDiscoverable', label: 'قابل‌جستجو', filterable: true, type: 'select', sortable: false, filterItems: IS_DISCOVERABLE_FILTER_ITEMS, }, { field: 'categoryId', label: 'دسته‌بندی', filterable: true, type: 'select', sortable: false, filterItems: categoryFilterItems, }, { field: 'organizerId', label: 'برگزارکننده', filterable: true, type: 'text', sortable: false, }, // Province-level filtering is disabled here too — see cities/page.tsx's // note for why (city-only admin surface). Only the city filter below // is active. { field: 'cityId', label: 'شهر', filterable: true, type: 'select', sortable: false, filterItems: cityFilterItems, }, { field: 'startsAt', label: 'تاریخ شروع', filterable: true, sortable: true, type: 'dateFromTo', }, { field: 'isFree', label: 'رایگان', filterable: true, type: 'select', sortable: false, filterItems: IS_FREE_FILTER_ITEMS, }, { field: 'price', label: 'قیمت', filterable: true, type: 'inputFromTo', sortable: false, }, { field: 'actions', label: 'عملیات', }, ], [categoryFilterItems, cityFilterItems] ) return (
{ router.push(APP_ROUTES.MANAGE_EVENT_NEW) }} > {{ status: (_row, cellValue) => , isDiscoverable: (_row, cellValue) => , categoryId: (row) => { const event = row as EventRow return event.category?.name ?? '—' }, organizerId: (row) => { const organizer = getOrganizer(row as EventRow) return formatPersonName(organizer.firstName, organizer.lastName) }, cityId: (row) => { const event = row as EventRow return event.city?.name ?? '—' }, startsAt: (_row, cellValue) => formatPersianDate(cellValue), isFree: (_row, cellValue) => , price: (row, cellValue) => { const event = row as EventRow if (event.isFree) return '—' const amount = typeof cellValue === 'number' ? cellValue : Number(cellValue) if (!Number.isFinite(amount)) return '—' return formatCurrency(amount) }, actions: (row) => ( ), }}
) } export default EventsPage