Ticketing updates

This commit is contained in:
Stephanos A
2026-07-22 12:54:21 +03:00
parent e0dc60361a
commit 44b4779ca6
6 changed files with 98 additions and 2 deletions

View File

@@ -98,6 +98,21 @@ export default function TicketsPage() {
queryFn: () => apiClient.get('/fleet/coaches'),
});
const [generateMissingResult, setGenerateMissingResult] = useState<any>(null);
const generateMissingMutation = useMutation({
mutationFn: () => ticketsApi.generateMissing(),
onSuccess: (result: any) => {
queryClient.invalidateQueries({ queryKey: ['tickets'] });
setGenerateMissingResult(result);
setSuccessMessage(`Generated ${result.generated} ticket(s) for ${result.processed} booking(s)${result.failed ? ` (${result.failed} failed)` : ''}`);
setTimeout(() => setSuccessMessage(''), 6000);
},
onError: (error: any) => {
alert(error?.response?.data?.message || error?.message || 'Failed to generate missing tickets');
},
});
const boardMutation = useMutation({
mutationFn: ({ ticketId, leg }: { ticketId: string; leg?: 'outbound' | 'inbound' }) =>
ticketsApi.validate(ticketId, { status: 'USED', boardedAt: new Date().toISOString(), leg: leg === 'inbound' ? 'RETURN' : 'OUTBOUND' }),
@@ -546,7 +561,17 @@ export default function TicketsPage() {
<h1 className="text-2xl font-bold text-foreground">Tickets</h1>
<p className="text-muted-foreground">Manage tickets and validations</p>
</div>
<ActionButton icon={Download} variant="export" onClick={() => setExportModalOpen(true)}>Export</ActionButton>
<div className="flex items-center gap-2">
<ActionButton
icon={Download}
variant="secondary"
loading={generateMissingMutation.isPending}
onClick={() => generateMissingMutation.mutate()}
>
Generate Missing
</ActionButton>
<ActionButton icon={Download} variant="export" onClick={() => setExportModalOpen(true)}>Export</ActionButton>
</div>
</div>
{/* Filters */}

View File

@@ -224,6 +224,7 @@ export const ticketsApi = {
return Array.isArray(response) ? { items: response } : response;
},
getById: (id: string) => apiClient.get<any>(`/tickets/${id}`),
generateMissing: () => apiClient.post<any>('/tickets/generate-missing', {}),
validate: (ticketId: string, data: any) => apiClient.post<any>(`/tickets/${ticketId}/validate`, data),
scanAndBoard: (qrCodeOrRef: string, data: any) => apiClient.post<any>(`/tickets/scan-board/${encodeURIComponent(qrCodeOrRef)}`, data),
regenerate: (ticketId: string) => apiClient.post<any>(`/tickets/${ticketId}/regenerate`),