'use client'; import { useState } from 'react'; import { AlertCircle, CalendarDays, CheckCircle2, Clock3, Loader2, Plus, RotateCcw, XCircle, } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { cn } from '@/lib/utils'; import type { TicketExtensionRequest, TicketExtensionRequestsResponse, } from '@/types'; import { formatDate } from '@/utils/date'; import { useTicketExtensionRequestQuery } from '../../../hooks/useTicketQueries'; import { ExtensionRequestHistoryDialog } from './ExtensionRequestHistoryDialog'; import { RequestExtensionForm } from './RequestExtensionForm'; interface DetailRowProps { label: string; value: string; children?: React.ReactNode; className?: string; } function DetailRow({ label, value, children, className }: DetailRowProps) { return (

{label}

{value}

{children}
); } const statusConfig = { pending: { title: 'Request Pending', description: 'This extension request is waiting for manager approval.', icon: Clock3, className: 'border-amber-200 bg-amber-50 text-amber-700 dark:border-amber-900/60 dark:bg-amber-950/30 dark:text-amber-300', }, approved: { title: 'Request Approved', description: 'This extension request was approved by the manager.', icon: CheckCircle2, className: 'border-emerald-200 bg-emerald-50 text-emerald-700 dark:border-emerald-900/60 dark:bg-emerald-950/30 dark:text-emerald-300', }, rejected: { title: 'Request Rejected', description: 'This extension request was rejected by the manager.', icon: AlertCircle, className: 'border-red-200 bg-red-50 text-red-700 dark:border-red-900/60 dark:bg-red-950/30 dark:text-red-300', }, cancelled: { title: 'Request Cancelled', description: 'This extension request was cancelled.', icon: XCircle, className: 'border-border bg-muted/50 text-muted-foreground', }, } satisfies Record< TicketExtensionRequest['status'], { title: string; description: string; icon: typeof Clock3; className: string; } >; export function getLatestRequest(response: TicketExtensionRequestsResponse) { return response.items.reduce( (latest, item) => { if (!latest) return item; return new Date(item.requested_at) > new Date(latest.requested_at) ? item : latest; }, null, ); } function getExtensionDays(request: TicketExtensionRequest) { const difference = new Date(request.requested_due_at).getTime() - new Date(request.current_due_at).getTime(); return Math.max(0, Math.ceil(difference / (24 * 60 * 60 * 1000))); } export function ExtensionRequestDetails({ request, requests, onRequestAnother, }: { request: TicketExtensionRequest; requests: TicketExtensionRequest[]; onRequestAnother?: () => void; }) { const config = statusConfig[request.status]; const StatusIcon = config.icon; const extensionDays = getExtensionDays(request); return (

{config.title}

{config.description}

Request Details

{extensionDays > 0 ? ( +{extensionDays} {extensionDays === 1 ? 'Day' : 'Days'} ) : null}
{request.resolved_at || request.resolved_by ? (

Manager Response

{request.resolved_at ? ( ) : null} {request.resolved_by ? ( ) : null} {request.status === 'approved' ? ( ) : null} {request.decision_note ? ( ) : null}
) : null}

Original Due Date

{request.status !== 'pending' && onRequestAnother ? ( ) : null}
); } export function TicketExtensionRequestPanel({ ticketId, assignmentId, dueAt, canRequest, }: { ticketId: string; assignmentId: number; dueAt: string | null; canRequest: boolean; }) { const [isRequestFormOpen, setIsRequestFormOpen] = useState(false); const extensionRequestQuery = useTicketExtensionRequestQuery( ticketId, assignmentId, ); if (extensionRequestQuery.isLoading) { return (
Loading extension request...
); } if (extensionRequestQuery.isError) { return (

Extension request details could not be loaded.

); } const latestRequest = extensionRequestQuery.data ? getLatestRequest(extensionRequestQuery.data) : null; if (!latestRequest) { if (!canRequest) { return (

No extension request history is available for this ticket lot.

); } return ( ); } if (isRequestFormOpen && latestRequest.status !== 'pending') { return (
); } return ( setIsRequestFormOpen(true) : undefined } /> ); }