claim page done
This commit is contained in:
@@ -183,6 +183,8 @@ router.post(
|
|||||||
});
|
});
|
||||||
|
|
||||||
const userId = req.user!.id;
|
const userId = req.user!.id;
|
||||||
|
const originalStartTime = appointmentData.startTime;
|
||||||
|
const MAX_END_TIME = "18:30";
|
||||||
|
|
||||||
// 1. Verify patient exists and belongs to user
|
// 1. Verify patient exists and belongs to user
|
||||||
const patient = await storage.getPatient(appointmentData.patientId);
|
const patient = await storage.getPatient(appointmentData.patientId);
|
||||||
@@ -196,39 +198,87 @@ router.post(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Check if patient already has an appointment on the same date and time.
|
// 2. Attempt to find the next available slot
|
||||||
const sameDayAppointment = await storage.getPatientAppointmentByDateTime(
|
let [hour, minute] = originalStartTime.split(":").map(Number);
|
||||||
|
|
||||||
|
const pad = (n: number) => n.toString().padStart(2, "0");
|
||||||
|
|
||||||
|
while (`${pad(hour)}:${pad(minute)}` <= MAX_END_TIME) {
|
||||||
|
const currentStartTime = `${pad(hour)}:${pad(minute)}`;
|
||||||
|
|
||||||
|
// Check patient appointment at this time
|
||||||
|
const sameDayAppointment =
|
||||||
|
await storage.getPatientAppointmentByDateTime(
|
||||||
appointmentData.patientId,
|
appointmentData.patientId,
|
||||||
appointmentData.date,
|
appointmentData.date,
|
||||||
appointmentData.startTime
|
currentStartTime
|
||||||
);
|
);
|
||||||
// 3. Check if there's already an appointment at this time slot of Staff.
|
|
||||||
|
// Check staff conflict at this time
|
||||||
const staffConflict = await storage.getStaffAppointmentByDateTime(
|
const staffConflict = await storage.getStaffAppointmentByDateTime(
|
||||||
appointmentData.staffId,
|
appointmentData.staffId,
|
||||||
appointmentData.date,
|
appointmentData.date,
|
||||||
appointmentData.startTime,
|
currentStartTime,
|
||||||
sameDayAppointment?.id
|
sameDayAppointment?.id // Ignore self if updating
|
||||||
);
|
);
|
||||||
|
|
||||||
if (staffConflict) {
|
if (!staffConflict) {
|
||||||
|
const endMinute = minute + 30;
|
||||||
|
let endHour = hour + Math.floor(endMinute / 60);
|
||||||
|
let realEndMinute = endMinute % 60;
|
||||||
|
|
||||||
|
const currentEndTime = `${pad(endHour)}:${pad(realEndMinute)}`;
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
...appointmentData,
|
||||||
|
startTime: currentStartTime,
|
||||||
|
endTime: currentEndTime,
|
||||||
|
};
|
||||||
|
|
||||||
|
let responseData;
|
||||||
|
|
||||||
|
if (sameDayAppointment?.id !== undefined) {
|
||||||
|
const updated = await storage.updateAppointment(
|
||||||
|
sameDayAppointment.id,
|
||||||
|
payload
|
||||||
|
);
|
||||||
|
responseData = {
|
||||||
|
...updated,
|
||||||
|
originalRequestedTime: originalStartTime,
|
||||||
|
finalScheduledTime: currentStartTime,
|
||||||
|
message:
|
||||||
|
originalStartTime !== currentStartTime
|
||||||
|
? `Your requested time (${originalStartTime}) was unavailable. Appointment was updated to ${currentStartTime}.`
|
||||||
|
: `Appointment successfully updated at ${currentStartTime}.`,
|
||||||
|
};
|
||||||
|
return res.status(200).json(responseData);
|
||||||
|
}
|
||||||
|
|
||||||
|
const created = await storage.createAppointment(payload);
|
||||||
|
responseData = {
|
||||||
|
...created,
|
||||||
|
originalRequestedTime: originalStartTime,
|
||||||
|
finalScheduledTime: currentStartTime,
|
||||||
|
message:
|
||||||
|
originalStartTime !== currentStartTime
|
||||||
|
? `Your requested time (${originalStartTime}) was unavailable. Appointment was scheduled at ${currentStartTime}.`
|
||||||
|
: `Appointment successfully scheduled at ${currentStartTime}.`,
|
||||||
|
};
|
||||||
|
return res.status(201).json(responseData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move to next 30-min slot
|
||||||
|
minute += 30;
|
||||||
|
if (minute >= 60) {
|
||||||
|
hour += 1;
|
||||||
|
minute = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return res.status(409).json({
|
return res.status(409).json({
|
||||||
message:
|
message:
|
||||||
"This time slot is already booked for the selected staff. Please choose another time or staff member.",
|
"No available slots remaining until 6:30 PM for this Staff. Please choose another day.",
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// 4. If same-day appointment exists, update it
|
|
||||||
if (sameDayAppointment?.id !== undefined) {
|
|
||||||
const updatedAppointment = await storage.updateAppointment(
|
|
||||||
sameDayAppointment.id,
|
|
||||||
appointmentData
|
|
||||||
);
|
|
||||||
return res.status(200).json(updatedAppointment);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6. Otherwise, create a new appointment
|
|
||||||
const newAppointment = await storage.createAppointment(appointmentData);
|
|
||||||
return res.status(201).json(newAppointment);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error in upsert appointment:", error);
|
console.error("Error in upsert appointment:", error);
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import patientRoutes from './patients';
|
import patientRoutes from './patients';
|
||||||
import appointmentRoutes from './appointements'
|
import appointmentRoutes from './appointments'
|
||||||
import userRoutes from './users'
|
import userRoutes from './users'
|
||||||
import staffRoutes from './staffs'
|
import staffRoutes from './staffs'
|
||||||
import pdfExtractionRoutes from './pdfExtraction';
|
import pdfExtractionRoutes from './pdfExtraction';
|
||||||
|
|||||||
@@ -159,6 +159,29 @@ router.get("/search", async (req: Request, res: Response): Promise<any> => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// get patient by insurance id
|
||||||
|
router.get("/by-insurance-id", async (req: Request, res: Response): Promise<any> => {
|
||||||
|
const insuranceId = req.query.insuranceId?.toString();
|
||||||
|
|
||||||
|
if (!insuranceId) {
|
||||||
|
return res.status(400).json({ error: "Missing insuranceId" });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const patient = await storage.getPatientByInsuranceId(insuranceId);
|
||||||
|
|
||||||
|
if (patient) {
|
||||||
|
return res.status(200).json(patient);
|
||||||
|
} else {
|
||||||
|
return res.status(404).json(null);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Failed to lookup patient:", err);
|
||||||
|
return res.status(500).json({ error: "Internal server error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Get a single patient by ID
|
// Get a single patient by ID
|
||||||
router.get(
|
router.get(
|
||||||
"/:id",
|
"/:id",
|
||||||
|
|||||||
@@ -24,7 +24,11 @@ const PatientSchema = (
|
|||||||
});
|
});
|
||||||
type Patient = z.infer<typeof PatientSchema>;
|
type Patient = z.infer<typeof PatientSchema>;
|
||||||
|
|
||||||
export default function ClaimsOfPatientModal() {
|
interface ClaimsOfPatientModalProps {
|
||||||
|
onNewClaim?: (patientId: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ClaimsOfPatientModal({ onNewClaim }: ClaimsOfPatientModalProps) {
|
||||||
const [selectedPatient, setSelectedPatient] = useState<Patient | null>(null);
|
const [selectedPatient, setSelectedPatient] = useState<Patient | null>(null);
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
const [claimsPage, setClaimsPage] = useState(1);
|
const [claimsPage, setClaimsPage] = useState(1);
|
||||||
@@ -70,13 +74,18 @@ export default function ClaimsOfPatientModal() {
|
|||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Patient Records</CardTitle>
|
<CardTitle>Patient Records</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
View and manage all patient information
|
Select any patient and View all their recent claims.
|
||||||
|
</CardDescription>
|
||||||
|
<CardDescription>
|
||||||
|
Also create new claim for any patients.
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<PatientTable
|
<PatientTable
|
||||||
allowView
|
allowView
|
||||||
allowCheckbox
|
allowCheckbox
|
||||||
|
allowNewClaim
|
||||||
|
onNewClaim={onNewClaim}
|
||||||
onSelectPatient={handleSelectPatient}
|
onSelectPatient={handleSelectPatient}
|
||||||
/>
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
@@ -94,7 +94,6 @@ export default function ClaimsRecentTable({
|
|||||||
patientId,
|
patientId,
|
||||||
}: ClaimsRecentTableProps) {
|
}: ClaimsRecentTableProps) {
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { user } = useAuth();
|
|
||||||
|
|
||||||
const [isViewClaimOpen, setIsViewClaimOpen] = useState(false);
|
const [isViewClaimOpen, setIsViewClaimOpen] = useState(false);
|
||||||
const [isEditClaimOpen, setIsEditClaimOpen] = useState(false);
|
const [isEditClaimOpen, setIsEditClaimOpen] = useState(false);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
TableRow,
|
TableRow,
|
||||||
} from "@/components/ui/table";
|
} from "@/components/ui/table";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Delete, Edit, Eye } from "lucide-react";
|
import { Delete, Edit, Eye, FileCheck } from "lucide-react";
|
||||||
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
|
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
|
||||||
import {
|
import {
|
||||||
Pagination,
|
Pagination,
|
||||||
@@ -69,6 +69,8 @@ interface PatientTableProps {
|
|||||||
allowView?: boolean;
|
allowView?: boolean;
|
||||||
allowDelete?: boolean;
|
allowDelete?: boolean;
|
||||||
allowCheckbox?: boolean;
|
allowCheckbox?: boolean;
|
||||||
|
allowNewClaim?: boolean;
|
||||||
|
onNewClaim?: (patientId: number) => void;
|
||||||
onSelectPatient?: (patient: Patient | null) => void;
|
onSelectPatient?: (patient: Patient | null) => void;
|
||||||
onPageChange?: (page: number) => void;
|
onPageChange?: (page: number) => void;
|
||||||
onSearchChange?: (searchTerm: string) => void;
|
onSearchChange?: (searchTerm: string) => void;
|
||||||
@@ -79,6 +81,8 @@ export function PatientTable({
|
|||||||
allowView,
|
allowView,
|
||||||
allowDelete,
|
allowDelete,
|
||||||
allowCheckbox,
|
allowCheckbox,
|
||||||
|
allowNewClaim,
|
||||||
|
onNewClaim,
|
||||||
onSelectPatient,
|
onSelectPatient,
|
||||||
onPageChange,
|
onPageChange,
|
||||||
onSearchChange,
|
onSearchChange,
|
||||||
@@ -480,6 +484,17 @@ export function PatientTable({
|
|||||||
>
|
>
|
||||||
<Edit className="h-4 w-4" />
|
<Edit className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
|
)}
|
||||||
|
{allowNewClaim && (
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
onClick={() => onNewClaim?.(patient.id)}
|
||||||
|
className="text-green-600 hover:text-green-800 hover:bg-green-50"
|
||||||
|
aria-label="New Claim"
|
||||||
|
>
|
||||||
|
<FileCheck className="h-5 w-5" />
|
||||||
|
</Button>
|
||||||
)}
|
)}
|
||||||
{allowView && (
|
{allowView && (
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -97,39 +97,13 @@ export default function ClaimsPage() {
|
|||||||
setIsMobileMenuOpen(!isMobileMenuOpen);
|
setIsMobileMenuOpen(!isMobileMenuOpen);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fetch patients
|
|
||||||
const { data: patients = [], isLoading: isLoadingPatients } = useQuery<
|
|
||||||
Patient[]
|
|
||||||
>({
|
|
||||||
queryKey: ["/api/patients/"],
|
|
||||||
queryFn: async () => {
|
|
||||||
const res = await apiRequest("GET", "/api/patients/");
|
|
||||||
return res.json();
|
|
||||||
},
|
|
||||||
enabled: !!user,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Fetch appointments
|
|
||||||
const {
|
|
||||||
data: appointments = [] as Appointment[],
|
|
||||||
isLoading: isLoadingAppointments,
|
|
||||||
} = useQuery<Appointment[]>({
|
|
||||||
queryKey: ["/api/appointments/all"],
|
|
||||||
queryFn: async () => {
|
|
||||||
const res = await apiRequest("GET", "/api/appointments/all");
|
|
||||||
return res.json();
|
|
||||||
},
|
|
||||||
enabled: !!user,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add patient mutation
|
// Add patient mutation
|
||||||
const addPatientMutation = useMutation({
|
const addPatientMutation = useMutation({
|
||||||
mutationFn: async (patient: InsertPatient) => {
|
mutationFn: async (patient: InsertPatient) => {
|
||||||
const res = await apiRequest("POST", "/api/patients/", patient);
|
const res = await apiRequest("POST", "/api/patients/", patient);
|
||||||
return res.json();
|
return res.json();
|
||||||
},
|
},
|
||||||
onSuccess: (newPatient) => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ["/api/patients/"] });
|
|
||||||
toast({
|
toast({
|
||||||
title: "Success",
|
title: "Success",
|
||||||
description: "Patient added successfully!",
|
description: "Patient added successfully!",
|
||||||
@@ -158,7 +132,6 @@ export default function ClaimsPage() {
|
|||||||
return res.json();
|
return res.json();
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ["/api/patients/"] });
|
|
||||||
toast({
|
toast({
|
||||||
title: "Success",
|
title: "Success",
|
||||||
description: "Patient updated successfully!",
|
description: "Patient updated successfully!",
|
||||||
@@ -184,14 +157,11 @@ export default function ClaimsPage() {
|
|||||||
);
|
);
|
||||||
return await res.json();
|
return await res.json();
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: (appointment) => {
|
||||||
toast({
|
toast({
|
||||||
title: "Success",
|
title: "Appointment Scheduled",
|
||||||
description: "Appointment created successfully.",
|
description: appointment.message || "Appointment created successfully.",
|
||||||
});
|
});
|
||||||
// Invalidate both appointments and patients queries
|
|
||||||
queryClient.invalidateQueries({ queryKey: ["/api/appointments/all"] });
|
|
||||||
queryClient.invalidateQueries({ queryKey: ["/api/patients/"] });
|
|
||||||
},
|
},
|
||||||
onError: (error: Error) => {
|
onError: (error: Error) => {
|
||||||
toast({
|
toast({
|
||||||
@@ -209,6 +179,11 @@ export default function ClaimsPage() {
|
|||||||
return res.json();
|
return res.json();
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: ["claims-recent"],
|
||||||
|
exact: false,
|
||||||
|
});
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: "Claim created successfully",
|
title: "Claim created successfully",
|
||||||
variant: "default",
|
variant: "default",
|
||||||
@@ -223,8 +198,17 @@ export default function ClaimsPage() {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// workflow starts from there - this params are set by pdf extraction/patient page.
|
// helper
|
||||||
// the fields are either send by pdfExtraction or by selecting patients.
|
const getPatientByInsuranceId = async (insuranceId: string) => {
|
||||||
|
const res = await apiRequest(
|
||||||
|
"GET",
|
||||||
|
`/api/patients/by-insurance-id?insuranceId=${encodeURIComponent(insuranceId)}`
|
||||||
|
);
|
||||||
|
if (!res.ok) throw new Error("Failed to fetch patient by insuranceId");
|
||||||
|
return res.json(); // returns patient object or null
|
||||||
|
};
|
||||||
|
|
||||||
|
// workflow starts from there - this params are set by pdf extraction/patient page. then used in claim page here.
|
||||||
const [location] = useLocation();
|
const [location] = useLocation();
|
||||||
const { name, memberId, dob } = useMemo(() => {
|
const { name, memberId, dob } = useMemo(() => {
|
||||||
const search = window.location.search;
|
const search = window.location.search;
|
||||||
@@ -279,7 +263,7 @@ export default function ClaimsPage() {
|
|||||||
};
|
};
|
||||||
fetchMatchingPatient();
|
fetchMatchingPatient();
|
||||||
}
|
}
|
||||||
}, [memberId, dob]);
|
}, [memberId]);
|
||||||
|
|
||||||
// 1. upsert appointment.
|
// 1. upsert appointment.
|
||||||
const handleAppointmentSubmit = async (
|
const handleAppointmentSubmit = async (
|
||||||
@@ -468,53 +452,6 @@ export default function ClaimsPage() {
|
|||||||
window.history.replaceState({}, document.title, url.toString());
|
window.history.replaceState({}, document.title, url.toString());
|
||||||
};
|
};
|
||||||
|
|
||||||
// helper func for frontend
|
|
||||||
const getDisplayProvider = (provider: string) => {
|
|
||||||
const insuranceMap: Record<string, string> = {
|
|
||||||
delta: "Delta Dental",
|
|
||||||
metlife: "MetLife",
|
|
||||||
cigna: "Cigna",
|
|
||||||
aetna: "Aetna",
|
|
||||||
};
|
|
||||||
return insuranceMap[provider?.toLowerCase()] || provider;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get unique patients with appointments - might not needed now, can shift this to the recent patients table
|
|
||||||
const patientsWithAppointments = patients.reduce(
|
|
||||||
(acc, patient) => {
|
|
||||||
const patientAppointments = appointments
|
|
||||||
.filter((appt) => appt.patientId === patient.id)
|
|
||||||
.sort(
|
|
||||||
(a, b) =>
|
|
||||||
parseLocalDate(b.date).getTime() - parseLocalDate(a.date).getTime()
|
|
||||||
); // Sort descending by date
|
|
||||||
|
|
||||||
if (patientAppointments.length > 0) {
|
|
||||||
const latestAppointment = patientAppointments[0];
|
|
||||||
acc.push({
|
|
||||||
patientId: patient.id,
|
|
||||||
patientName: `${patient.firstName} ${patient.lastName}`,
|
|
||||||
appointmentId: latestAppointment!.id,
|
|
||||||
insuranceProvider: patient.insuranceProvider || "N/A",
|
|
||||||
insuranceId: patient.insuranceId || "N/A",
|
|
||||||
lastAppointment: formatLocalDate(
|
|
||||||
parseLocalDate(latestAppointment!.date)
|
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
[] as Array<{
|
|
||||||
patientId: number;
|
|
||||||
patientName: string;
|
|
||||||
appointmentId: number;
|
|
||||||
insuranceProvider: string;
|
|
||||||
insuranceId: string;
|
|
||||||
lastAppointment: string;
|
|
||||||
}>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-screen overflow-hidden bg-gray-100">
|
<div className="flex h-screen overflow-hidden bg-gray-100">
|
||||||
<Sidebar
|
<Sidebar
|
||||||
@@ -546,92 +483,8 @@ export default function ClaimsPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* New Claims Section */}
|
{/* Recent Claims by Patients also handles new claims */}
|
||||||
<div className="mb-8 mt-8">
|
<ClaimsOfPatientModal onNewClaim={handleNewClaim} />
|
||||||
<div className="flex items-center justify-between mb-4">
|
|
||||||
<div
|
|
||||||
className="flex items-center cursor-pointer group"
|
|
||||||
onClick={() => {
|
|
||||||
if (patientsWithAppointments.length > 0) {
|
|
||||||
const firstPatient = patientsWithAppointments[0];
|
|
||||||
handleNewClaim(Number(firstPatient?.patientId));
|
|
||||||
} else {
|
|
||||||
toast({
|
|
||||||
title: "No patients available",
|
|
||||||
description:
|
|
||||||
"There are no patients with appointments to create a claim",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<h2 className="text-xl font-medium text-gray-800 group-hover:text-primary">
|
|
||||||
New Claims
|
|
||||||
</h2>
|
|
||||||
<div className="ml-2 text-primary">
|
|
||||||
<FileCheck className="h-5 w-5" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Card>
|
|
||||||
<CardHeader className="pb-2">
|
|
||||||
<CardTitle>Recent Patients for Claims</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
{isLoadingPatients || isLoadingAppointments ? (
|
|
||||||
<div className="text-center py-4">
|
|
||||||
Loading patients data...
|
|
||||||
</div>
|
|
||||||
) : patientsWithAppointments.length > 0 ? (
|
|
||||||
<div className="divide-y">
|
|
||||||
{patientsWithAppointments.map(
|
|
||||||
(item: (typeof patientsWithAppointments)[number]) => (
|
|
||||||
<div
|
|
||||||
key={item.patientId}
|
|
||||||
className="py-4 flex items-center justify-between cursor-pointer hover:bg-gray-50"
|
|
||||||
onClick={() => handleNewClaim(item.patientId)}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<h3 className="font-medium">{item.patientName}</h3>
|
|
||||||
<div className="text-sm text-gray-500">
|
|
||||||
<span>
|
|
||||||
Insurance:{" "}
|
|
||||||
{getDisplayProvider(item.insuranceProvider)}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span className="mx-2">•</span>
|
|
||||||
<span>ID: {item.insuranceId}</span>
|
|
||||||
<span className="mx-2">•</span>
|
|
||||||
<span>
|
|
||||||
Last Visit:{" "}
|
|
||||||
{parseLocalDate(
|
|
||||||
item.lastAppointment
|
|
||||||
).toLocaleDateString("en-CA")}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="text-primary">
|
|
||||||
<FileCheck className="h-5 w-5" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="text-center py-8">
|
|
||||||
<FileCheck className="h-12 w-12 mx-auto text-gray-400 mb-3" />
|
|
||||||
<h3 className="text-lg font-medium">
|
|
||||||
No eligible patients for claims
|
|
||||||
</h3>
|
|
||||||
<p className="text-gray-500 mt-1">
|
|
||||||
Patients with appointments will appear here for insurance
|
|
||||||
claim processing
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Recent Claims Section */}
|
{/* Recent Claims Section */}
|
||||||
<Card>
|
<Card>
|
||||||
@@ -649,9 +502,6 @@ export default function ClaimsPage() {
|
|||||||
/>
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* Recent Claims by Patients */}
|
|
||||||
<ClaimsOfPatientModal />
|
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user