feat: ticket system base implementation
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user