'use client'; import { useState, useEffect } from 'react'; import { useLanguage } from '@/context/LanguageContext'; import { ticketsApi, eventsApi, Ticket, Event } from '@/lib/api'; import { parseDate } from '@/lib/utils'; import Card from '@/components/ui/Card'; import Button from '@/components/ui/Button'; import Input from '@/components/ui/Input'; import { BottomSheet, MoreMenu, DropdownItem, AdminMobileStyles } from '@/components/admin/MobileComponents'; import { CheckCircleIcon, XCircleIcon, PlusIcon, FunnelIcon, XMarkIcon } from '@heroicons/react/24/outline'; import toast from 'react-hot-toast'; import clsx from 'clsx'; export default function AdminTicketsPage() { const { t, locale } = useLanguage(); const [tickets, setTickets] = useState([]); const [events, setEvents] = useState([]); const [loading, setLoading] = useState(true); const [selectedEvent, setSelectedEvent] = useState(''); const [statusFilter, setStatusFilter] = useState(''); const [mobileFilterOpen, setMobileFilterOpen] = useState(false); const [showCreateForm, setShowCreateForm] = useState(false); const [creating, setCreating] = useState(false); const [createForm, setCreateForm] = useState({ eventId: '', firstName: '', lastName: '', email: '', phone: '', preferredLanguage: 'en' as 'en' | 'es', autoCheckin: false, adminNote: '', }); useEffect(() => { Promise.all([ticketsApi.getAll(), eventsApi.getAll()]) .then(([ticketsRes, eventsRes]) => { setTickets(ticketsRes.tickets); setEvents(eventsRes.events); }) .catch(console.error) .finally(() => setLoading(false)); }, []); const loadTickets = async () => { try { const params: any = {}; if (selectedEvent) params.eventId = selectedEvent; if (statusFilter) params.status = statusFilter; const { tickets } = await ticketsApi.getAll(params); setTickets(tickets); } catch (error) { toast.error('Failed to load tickets'); } }; useEffect(() => { if (!loading) loadTickets(); }, [selectedEvent, statusFilter]); const handleCheckin = async (id: string) => { try { await ticketsApi.checkin(id); toast.success('Check-in successful'); loadTickets(); } catch (error: any) { toast.error(error.message || 'Check-in failed'); } }; const handleCancel = async (id: string) => { if (!confirm('Are you sure you want to cancel this ticket?')) return; try { await ticketsApi.cancel(id); toast.success('Ticket cancelled'); loadTickets(); } catch (error) { toast.error('Failed to cancel ticket'); } }; const handleConfirm = async (id: string) => { try { await ticketsApi.updateStatus(id, 'confirmed'); toast.success('Ticket confirmed'); loadTickets(); } catch (error) { toast.error('Failed to confirm ticket'); } }; const handleCreateTicket = async (e: React.FormEvent) => { e.preventDefault(); if (!createForm.eventId) { toast.error('Please select an event'); return; } setCreating(true); try { await ticketsApi.adminCreate({ eventId: createForm.eventId, firstName: createForm.firstName, lastName: createForm.lastName || undefined, email: createForm.email, phone: createForm.phone, preferredLanguage: createForm.preferredLanguage, autoCheckin: createForm.autoCheckin, adminNote: createForm.adminNote || undefined, }); toast.success('Ticket created successfully'); setShowCreateForm(false); setCreateForm({ eventId: '', firstName: '', lastName: '', email: '', phone: '', preferredLanguage: 'en', autoCheckin: false, adminNote: '' }); loadTickets(); } catch (error: any) { toast.error(error.message || 'Failed to create ticket'); } finally { setCreating(false); } }; const formatDate = (dateStr: string) => { return parseDate(dateStr).toLocaleDateString(locale === 'es' ? 'es-ES' : 'en-US', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', timeZone: 'America/Asuncion', }); }; const getStatusBadge = (status: string) => { const styles: Record = { pending: 'badge-warning', confirmed: 'badge-success', cancelled: 'badge-danger', checked_in: 'badge-info', }; const labels: Record = { pending: t('admin.tickets.status.pending'), confirmed: t('admin.tickets.status.confirmed'), cancelled: t('admin.tickets.status.cancelled'), checked_in: t('admin.tickets.status.checkedIn'), }; return {labels[status] || status}; }; const getEventName = (eventId: string) => events.find(e => e.id === eventId)?.title || 'Unknown Event'; const hasActiveFilters = selectedEvent || statusFilter; const getPrimaryAction = (ticket: Ticket) => { if (ticket.status === 'pending') return { label: 'Confirm', onClick: () => handleConfirm(ticket.id) }; if (ticket.status === 'confirmed') return { label: t('admin.tickets.checkin'), onClick: () => handleCheckin(ticket.id) }; return null; }; if (loading) { return (
); } return (

{t('admin.tickets.title')}

{/* Create Ticket Modal */} {showCreateForm && (

Create Ticket Manually

setCreateForm({ ...createForm, firstName: e.target.value })} required placeholder="First name" /> setCreateForm({ ...createForm, lastName: e.target.value })} placeholder="Last name" />
setCreateForm({ ...createForm, email: e.target.value })} placeholder="attendee@email.com" /> setCreateForm({ ...createForm, phone: e.target.value })} placeholder="+595 XXX XXX XXX" />