"use client"; import * as React from 'react'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { Link, useNavigate } from '@/lib/router'; import type { EventListItemSchema } from '@/lib/types'; import { api } from '@/lib/api'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { ScrollArea } from '@/components/ui/scroll-area'; import ProgressiveImage from '@/components/ProgressiveImage'; import { useToast } from '@/hooks/use-toast'; import { formatJalali, formatToman, getEventCardImageUrl, resolveErrorMessage, toPersianDigits } from '@/lib/utils'; const EVENTS_PAGE_SIZE = 30; const eventStatusOptions = [ { value: 'all', label: 'همه وضعیت‌ها' }, { value: 'draft', label: 'پیش‌نویس' }, { value: 'published', label: 'منتشر شده' }, { value: 'cancelled', label: 'لغو شده' }, { value: 'completed', label: 'برگزار شده' }, ]; const statusConfig: Record< EventListItemSchema['status'], { label: string; variant: 'outline' | 'default' | 'destructive' | 'secondary' } > = { draft: { label: 'پیش‌نویس', variant: 'outline' }, published: { label: 'منتشر شده', variant: 'default' }, cancelled: { label: 'لغو شده', variant: 'destructive' }, completed: { label: 'برگزار شده', variant: 'secondary' }, }; const eventSortOptions = [ { value: 'newest', label: 'جدیدترین شروع' }, { value: 'oldest', label: 'قدیمی‌ترین شروع' }, { value: 'priceAsc', label: 'قیمت صعودی' }, { value: 'priceDesc', label: 'قیمت نزولی' }, ]; const AdminEventsPage: React.FC = () => { const { toast } = useToast(); const queryClient = useQueryClient(); const navigate = useNavigate(); const [filters, setFilters] = React.useState({ search: '', status: 'all' as 'all' | EventListItemSchema['status'], type: 'all' as 'all' | EventListItemSchema['event_type'], sort: 'newest' as (typeof eventSortOptions)[number]['value'], }); const eventsQuery = useQuery({ queryKey: ['admin', 'events', filters], queryFn: () => api.getEvents({ statuses: filters.status === 'all' ? undefined : [filters.status as EventListItemSchema['status']], event_type: filters.type === 'all' ? undefined : (filters.type as EventListItemSchema['event_type']), search: filters.search || undefined, limit: EVENTS_PAGE_SIZE, }), }); const deleteMutation = useMutation({ mutationFn: (eventId: number) => api.deleteEvent(eventId), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['admin', 'events'] }); toast({ title: 'رویداد حذف شد', variant: 'success' }); }, onError: (error) => { toast({ title: 'خطا', description: resolveErrorMessage(error), variant: 'destructive', }); }, }); const sortedEvents = React.useMemo(() => { const list = (eventsQuery.data ?? []).slice(); switch (filters.sort) { case 'newest': return list.sort((a, b) => new Date(b.start_time).getTime() - new Date(a.start_time).getTime()); case 'oldest': return list.sort((a, b) => new Date(a.start_time).getTime() - new Date(b.start_time).getTime()); case 'priceAsc': return list.sort((a, b) => Number(a.price) - Number(b.price)); case 'priceDesc': return list.sort((a, b) => Number(b.price) - Number(a.price)); default: return list; } }, [eventsQuery.data, filters.sort]); return (

رویدادها

مدیریت رویدادها، ثبت‌نام‌ها و وضعیت انتشار

فیلترها پیدا کردن سریع رویدادها
setFilters((prev) => ({ ...prev, search: event.target.value }))} />
لیست رویدادها وضعیت، ظرفیت و قیمت هر رویداد {eventsQuery.isLoading ? (

در حال بارگذاری...

) : sortedEvents.length === 0 ? (

رویدادی یافت نشد.

) : (
{sortedEvents.map((event) => ( ))}
پوستر عنوان وضعیت تاریخ شروع ثبت‌نام‌ها قیمت (تومان) عملیات
navigate(`/admin/events/${event.id}`)}> {event.title} {statusConfig[event.status].label} {formatJalali(event.start_time)} {toPersianDigits(event.registration_count)} {formatToman(event.price)}
{sortedEvents.map((event) => (
{event.title}
{statusConfig[event.status].label}
تاریخ شروع: {formatJalali(event.start_time)}
ثبت‌نام‌ها: {toPersianDigits(event.registration_count)}
قیمت: {formatToman(event.price)}
))}
)}
); }; export default AdminEventsPage;