import { useEffect, useState } from "react"; import { useMutation, useQuery } from "@tanstack/react-query"; import { TopAppBar } from "@/components/layout/top-app-bar"; import { Sidebar } from "@/components/layout/sidebar"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { Search, Eye, ChevronLeft, ChevronRight, Settings, Trash, Download, } from "lucide-react"; import { useAuth } from "@/hooks/use-auth"; import { cn } from "@/lib/utils"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { ClaimPdfUncheckedCreateInputObjectSchema } from "@repo/db/usedSchemas"; import { z } from "zod"; import "@react-pdf-viewer/core/lib/styles/index.css"; import "@react-pdf-viewer/default-layout/lib/styles/index.css"; import { Viewer, Worker } from "@react-pdf-viewer/core"; import { defaultLayoutPlugin } from "@react-pdf-viewer/default-layout"; import { apiRequest, queryClient } from "@/lib/queryClient"; import { toast } from "@/hooks/use-toast"; import { DeleteConfirmationDialog } from "@/components/ui/deleteDialog"; const ClaimPdfSchema = ClaimPdfUncheckedCreateInputObjectSchema as unknown as z.ZodObject; type ClaimPdf = z.infer; export default function DocumentsPage() { const { user } = useAuth(); const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); const [searchTerm, setSearchTerm] = useState(""); const [searchField, setSearchField] = useState("all"); const [currentPage, setCurrentPage] = useState(1); const itemsPerPage = 5; const [selectedPdfId, setSelectedPdfId] = useState(null); const defaultLayoutPluginInstance = defaultLayoutPlugin(); const [isDeletePdfOpen, setIsDeletePdfOpen] = useState(false); const [currentPdf, setCurrentPdf] = useState(null); const { data: pdfs = [], isLoading } = useQuery({ queryKey: ["/api/documents/claim-pdf/recent"], enabled: !!user, queryFn: async () => { const res = await apiRequest("GET", "/api/documents/claim-pdf/recent"); return res.json(); }, }); const deletePdfMutation = useMutation({ mutationFn: async (id: number) => { await apiRequest("DELETE", `/api/documents/claim-pdf/${id}`); }, onSuccess: () => { setIsDeletePdfOpen(false); setCurrentPdf(null); queryClient.invalidateQueries({ queryKey: ["/api/documents/claim-pdf/recent"], }); toast({ title: "Success", description: "PDF deleted successfully!", variant: "default", }); }, onError: (error: any) => { console.error("Error deleting PDF:", error); toast({ title: "Error", description: `Failed to delete PDF: ${error.message || error}`, variant: "destructive", }); }, }); const formatDate = (dateString: string) => { const date = new Date(dateString); return date.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric", }); }; const getPatientInitials = (first: string, last: string) => `${first[0]}${last[0]}`.toUpperCase(); const [fileBlobUrl, setFileBlobUrl] = useState(null); useEffect(() => { if (!selectedPdfId) return; let url: string | null = null; const fetchPdf = async () => { try { const res = await apiRequest( "GET", `/api/documents/claim-pdf/${selectedPdfId}` ); const arrayBuffer = await res.arrayBuffer(); const blob = new Blob([arrayBuffer], { type: "application/pdf" }); const objectUrl = URL.createObjectURL(blob); setFileBlobUrl(objectUrl); url = objectUrl; } catch (err) { console.error("Failed to load PDF", err); } }; fetchPdf(); return () => { if (url) { URL.revokeObjectURL(url); } }; }, [selectedPdfId]); const toggleMobileMenu = () => setIsMobileMenuOpen((prev) => !prev); const viewPdf = (pdfId: number) => { setSelectedPdfId(pdfId); }; const downloadPdf = async (pdfId: number, filename: string) => { try { const res = await apiRequest("GET", `/api/documents/claim-pdf/${pdfId}`); const arrayBuffer = await res.arrayBuffer(); const blob = new Blob([arrayBuffer], { type: "application/pdf" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } catch (err) { console.error("Failed to download PDF:", err); } }; const handleDeletePdf = (pdf: ClaimPdf) => { setCurrentPdf(pdf); setIsDeletePdfOpen(true); }; const handleConfirmDeletePdf = () => { if (currentPdf) { deletePdfMutation.mutate(currentPdf.id); } else { toast({ title: "Error", description: "No PDF selected for deletion.", variant: "destructive", }); } }; const filteredPdfs = pdfs.filter((pdf) => { const patient = pdf.patient; const searchLower = searchTerm.toLowerCase(); const fullName = `${patient.firstName} ${patient.lastName}`.toLowerCase(); const patientId = `PID-${patient.id.toString().padStart(4, "0")}`; switch (searchField) { case "name": return fullName.includes(searchLower); case "id": return patientId.toLowerCase().includes(searchLower); case "phone": return patient.phone?.toLowerCase().includes(searchLower) || false; case "all": default: return ( fullName.includes(searchLower) || patientId.includes(searchLower) || patient.phone?.toLowerCase().includes(searchLower) || patient.email?.toLowerCase().includes(searchLower) || false ); } }); const totalPages = Math.ceil(filteredPdfs.length / itemsPerPage); const startIndex = (currentPage - 1) * itemsPerPage; const currentPdfs = filteredPdfs.slice(startIndex, startIndex + itemsPerPage); return (

Documents

View and manage recent uploaded claim PDFs

setSearchTerm(e.target.value)} className="pl-10" />
{isLoading ? (
Loading data...
) : currentPdfs.length === 0 ? (
{searchTerm ? "No results matching your search." : "No recent claim PDFs available."}
) : ( <>
Patient
DOB / Gender
Contact
Insurance
Status
Actions
{currentPdfs.map((pdf) => { const patient = pdf.patient; return (
{getPatientInitials( patient.firstName, patient.lastName )}
{patient.firstName} {patient.lastName}
PID-{patient.id.toString().padStart(4, "0")}
{formatDate(patient.dateOfBirth)}
{patient.gender}
{patient.phone || "Not provided"}
{patient.email || "No email"}
{patient.insuranceProvider ? `${patient.insuranceProvider.charAt(0).toUpperCase()}${patient.insuranceProvider.slice(1)}` : "Not specified"}
ID: {patient.insuranceId || "N/A"}
{patient.status === "active" ? "Active" : "Inactive"}
); })} setIsDeletePdfOpen(false)} entityName={`PDF #${currentPdf?.id}`} /> {/* PDF Viewer */} {selectedPdfId && fileBlobUrl && (

Viewing PDF #{selectedPdfId}

)} {/* Pagination */} {totalPages > 1 && (
Showing {startIndex + 1} to{" "} {Math.min( startIndex + itemsPerPage, filteredPdfs.length )}{" "} of {filteredPdfs.length} results
{Array.from( { length: totalPages }, (_, i) => i + 1 ).map((page) => ( ))}
)} )}
); }