feat: ticket system base implementation

This commit is contained in:
2026-06-19 01:19:01 +05:30
parent a18fff4d6f
commit 8c3d19a429
19 changed files with 1400 additions and 27 deletions

View File

@@ -1,32 +1,94 @@
'use client';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { useCallback, useMemo, useState } from 'react';
import { useRouter } from 'next/navigation';
import { PageHeader } from '@/components/page-header';
import { Ticket } from 'lucide-react';
import type { TicketListItem, TicketStatus } from '@/types';
import { TicketFilters } from './components/TicketFilters';
import { TicketTable } from './components/TicketTable';
import { useTicketColumns } from './components/TicketColumns';
import { useTenantTicketTableEvents } from './hooks/useTicketEvents';
import { useTicketsQuery } from './hooks/useTicketQueries';
export default function TicketPage() {
return (
<div className="min-h-screen pb-12">
<main>
<div className="mb-10">
<PageHeader
title="Ticket"
description="Uploaded video details will be shown here."
icon={Ticket}
/>
</div>
const router = useRouter();
const [skip, setSkip] = useState(0);
const [limit, setLimit] = useState(10);
const [status, setStatus] = useState<TicketStatus | 'all'>('all');
const [segmentId, setSegmentId] = useState('');
<Card>
<CardHeader>
<CardTitle>Ticket Page</CardTitle>
</CardHeader>
<CardContent>
<p className="text-sm text-muted-foreground">
This is ticket page for now.
</p>
</CardContent>
</Card>
</main>
</div>
useTenantTicketTableEvents();
const ticketsQuery = useTicketsQuery({
skip,
limit,
status,
chainageId: segmentId,
});
const columns = useTicketColumns();
const tickets = ticketsQuery.data?.items ?? [];
const total = ticketsQuery.data?.total ?? 0;
const handleStatusChange = useCallback((nextStatus: TicketStatus | 'all') => {
setStatus(nextStatus);
setSkip(0);
}, []);
const handleSegmentChange = useCallback((nextSegmentId: string) => {
setSegmentId(nextSegmentId);
setSkip(0);
}, []);
const handleView = useCallback(
(ticket: TicketListItem) => {
router.push(`/ticket/${ticket.id}`);
},
[router],
);
const handleShowAnalytics = useCallback(
(ticket: TicketListItem) => {
router.push(`/results/${ticket.video_id}`);
},
[router],
);
const toolbar = useMemo(
() => (
<TicketFilters
status={status}
segmentId={segmentId}
onStatusChange={handleStatusChange}
onSegmentChange={handleSegmentChange}
/>
),
[handleSegmentChange, handleStatusChange, segmentId, status],
);
return (
<main className="relative z-10 space-y-5">
<PageHeader
title="Tickets"
description="Track detection, assignment, repair, review, and closure."
icon={Ticket}
/>
<TicketTable
columns={columns}
tickets={tickets}
isLoading={ticketsQuery.isLoading}
toolbar={toolbar}
skip={skip}
limit={limit}
total={total}
onPageChange={setSkip}
onLimitChange={setLimit}
onView={handleView}
onShowAnalytics={handleShowAnalytics}
/>
</main>
);
}