import React, { useRef, useMemo, useState } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { useAuth0 } from '@auth0/auth0-react'; import { isAxiosError } from 'axios'; import { Card } from '../../../shared-minimal/components/Card'; import { Button } from '../../../shared-minimal/components/Button'; import { useDocument } from '../hooks/useDocuments'; import { useUploadWithProgress } from '../hooks/useUploadWithProgress'; import { documentsApi } from '../api/documents.api'; import { DocumentPreview } from '../components/DocumentPreview'; import { EditDocumentDialog } from '../components/EditDocumentDialog'; import { ExpirationBadge } from '../components/ExpirationBadge'; import { DocumentCardMetadata } from '../components/DocumentCardMetadata'; import { useVehicle, useVehicles } from '../../vehicles/hooks/useVehicles'; import { getVehicleLabel } from '../utils/vehicleLabel'; export const DocumentDetailPage: React.FC = () => { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); const { isAuthenticated, isLoading: authLoading, loginWithRedirect } = useAuth0(); const { data: doc, isLoading, error, refetch } = useDocument(id); const { data: vehicle } = useVehicle(doc?.vehicleId || ''); const { data: vehicles } = useVehicles(); const inputRef = useRef(null); const upload = useUploadWithProgress(id!); const [isEditOpen, setIsEditOpen] = useState(false); const vehiclesMap = useMemo(() => new Map(vehicles?.map(v => [v.id, v]) || []), [vehicles]); // Check if document has displayable metadata const hasDisplayableMetadata = useMemo(() => { if (!doc) return false; const details = doc.details || {}; if (doc.documentType === 'insurance') { return !!(doc.expirationDate || details.policyNumber || details.insuranceCompany || doc.issuedDate || details.bodilyInjuryPerson || details.bodilyInjuryIncident || details.propertyDamage || details.premium); } if (doc.documentType === 'registration') { return !!(doc.expirationDate || details.licensePlate || details.cost); } if (doc.documentType === 'manual') { return !!(doc.issuedDate || doc.notes); } return false; }, [doc]); const handleDownload = async () => { if (!id) return; const blob = await documentsApi.download(id); const url = URL.createObjectURL(blob); window.open(url, '_blank'); }; const handleUpload = () => { if (!inputRef.current) return; inputRef.current.onchange = () => { const file = inputRef.current?.files?.[0]; if (file && id) { const allowed = new Set(['application/pdf', 'image/jpeg', 'image/png']); if (!file.type || !allowed.has(file.type)) { alert('Unsupported file type. Allowed: PDF, JPG/JPEG, PNG.'); return; } upload.mutate(file); } }; inputRef.current.click(); }; // Show loading while auth is initializing if (authLoading) { return (
Checking authentication...
); } // Show login prompt when not authenticated if (!isAuthenticated) { return (

Authentication Required

Please log in to view this document

); } // Check for authentication error (401) const isAuthError = error && isAxiosError(error) && error.response?.status === 401; if (isAuthError) { return (

Session Expired

Your session has expired. Please log in again to continue.

); } if (isLoading) return
Loading document...
; if (error && !isAuthError) { return (

Document Not Found

The document you're looking for could not be found.

); } if (!doc) { return (

Document Not Found

The document you're looking for does not exist.

); } return (
{/* Mobile Layout: Stacked */}
{/* Header Card - Mobile */}

{doc.title}

{doc.documentType} |
{hasDisplayableMetadata && }
{/* Preview Card - Mobile */}
{/* Actions Card - Mobile */}
{upload.isPending && (
Uploading... {upload.progress}%
)} {upload.isError && (
{((upload.error as any)?.response?.status === 415) ? 'Unsupported file type. Allowed: PDF, JPG/JPEG, PNG.' : 'Failed to upload file. Please try again.'}
)}
{/* Desktop Layout: Side by Side */}
{/* Left Panel: Document Preview (60%) */}
{/* Right Panel: Metadata (40%) */}
{/* Title and Badge */}

{doc.title}

{/* Document Type */}
Type
{doc.documentType}
{/* Vehicle */}
Vehicle
{/* Shared Vehicles */} {doc.sharedVehicleIds.length > 0 && (
Shared with
    {doc.sharedVehicleIds.map((vehicleId) => { const sharedVehicle = vehiclesMap.get(vehicleId); return (
  • ); })}
)} {/* Type-specific Metadata - only show if there's data */} {hasDisplayableMetadata && (
Details
)} {/* Actions */}
{upload.isPending && (
Uploading... {upload.progress}%
)} {upload.isError && (
{((upload.error as any)?.response?.status === 415) ? 'Unsupported file type. Allowed: PDF, JPG/JPEG, PNG.' : 'Failed to upload file. Please try again.'}
)}
{doc && ( { setIsEditOpen(false); refetch(); }} document={doc} /> )}
); }; export default DocumentDetailPage;