fixing claimsPage
This commit is contained in:
@@ -1,30 +1,67 @@
|
|||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, ResponsiveContainer, Tooltip } from "recharts";
|
import {
|
||||||
|
BarChart,
|
||||||
|
Bar,
|
||||||
|
XAxis,
|
||||||
|
YAxis,
|
||||||
|
CartesianGrid,
|
||||||
|
ResponsiveContainer,
|
||||||
|
Tooltip,
|
||||||
|
} from "recharts";
|
||||||
|
|
||||||
interface AppointmentsByDayProps {
|
interface AppointmentsByDayProps {
|
||||||
appointments: any[];
|
appointments: any[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AppointmentsByDay({ appointments }: AppointmentsByDayProps) {
|
export function AppointmentsByDay({ appointments }: AppointmentsByDayProps) {
|
||||||
// Data processing for appointments by day
|
|
||||||
const daysOfWeek = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
const daysOfWeek = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
||||||
|
const countsByDay = daysOfWeek.map((day) => ({ day, count: 0 }));
|
||||||
|
|
||||||
// Initialize counts for each day
|
// Get current date and set time to start of day (midnight)
|
||||||
const countsByDay = daysOfWeek.map(day => ({ day, count: 0 }));
|
const now = new Date();
|
||||||
|
now.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
// Count appointments by day of week
|
// Calculate Monday of the current week
|
||||||
appointments.forEach(appointment => {
|
const day = now.getDay(); // 0 = Sunday, 1 = Monday, ...
|
||||||
|
const diffToMonday = day === 0 ? -6 : 1 - day; // adjust if Sunday
|
||||||
|
const monday = new Date(now);
|
||||||
|
monday.setDate(now.getDate() + diffToMonday);
|
||||||
|
|
||||||
|
// Sunday of the current week
|
||||||
|
const sunday = new Date(monday);
|
||||||
|
sunday.setDate(monday.getDate() + 6);
|
||||||
|
|
||||||
|
// Filter appointments only from this week (Monday to Sunday)
|
||||||
|
const appointmentsThisWeek = appointments.filter((appointment) => {
|
||||||
|
if (!appointment.date) return false;
|
||||||
|
|
||||||
|
const date = new Date(appointment.date);
|
||||||
|
// Reset time to compare just the date
|
||||||
|
date.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
|
return date >= monday && date <= sunday;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Count appointments by day for current week
|
||||||
|
appointmentsThisWeek.forEach((appointment) => {
|
||||||
const date = new Date(appointment.date);
|
const date = new Date(appointment.date);
|
||||||
const dayOfWeek = date.getDay(); // 0 = Sunday, 1 = Monday, ...
|
const dayOfWeek = date.getDay(); // 0 = Sunday, 1 = Monday, ...
|
||||||
const dayIndex = dayOfWeek === 0 ? 6 : dayOfWeek - 1; // Adjust to make Monday first
|
const dayIndex = dayOfWeek === 0 ? 6 : dayOfWeek - 1; // Monday=0, Sunday=6
|
||||||
countsByDay[dayIndex].count += 1;
|
if (countsByDay[dayIndex]) {
|
||||||
|
countsByDay[dayIndex].count += 1;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="shadow-sm">
|
<Card className="shadow-sm">
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
<CardTitle className="text-base font-medium">Appointments by Day</CardTitle>
|
<CardTitle className="text-base font-medium">
|
||||||
<p className="text-xs text-muted-foreground">Distribution of appointments throughout the week</p>
|
Appointments by Day
|
||||||
|
</CardTitle>
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
|
Distribution of appointments throughout the week
|
||||||
|
</p>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="h-[200px]">
|
<div className="h-[200px]">
|
||||||
@@ -34,7 +71,12 @@ export function AppointmentsByDay({ appointments }: AppointmentsByDayProps) {
|
|||||||
margin={{ top: 5, right: 5, left: 0, bottom: 5 }}
|
margin={{ top: 5, right: 5, left: 0, bottom: 5 }}
|
||||||
>
|
>
|
||||||
<CartesianGrid strokeDasharray="3 3" vertical={false} />
|
<CartesianGrid strokeDasharray="3 3" vertical={false} />
|
||||||
<XAxis dataKey="day" fontSize={12} tickLine={false} axisLine={false} />
|
<XAxis
|
||||||
|
dataKey="day"
|
||||||
|
fontSize={12}
|
||||||
|
tickLine={false}
|
||||||
|
axisLine={false}
|
||||||
|
/>
|
||||||
<YAxis fontSize={12} tickLine={false} axisLine={false} />
|
<YAxis fontSize={12} tickLine={false} axisLine={false} />
|
||||||
<Tooltip
|
<Tooltip
|
||||||
formatter={(value) => [`${value} appointments`, "Count"]}
|
formatter={(value) => [`${value} appointments`, "Count"]}
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ export function NewPatients({ patients }: NewPatientsProps) {
|
|||||||
patients.forEach(patient => {
|
patients.forEach(patient => {
|
||||||
const createdDate = new Date(patient.createdAt);
|
const createdDate = new Date(patient.createdAt);
|
||||||
const monthIndex = createdDate.getMonth();
|
const monthIndex = createdDate.getMonth();
|
||||||
patientsByMonth[monthIndex].count += 1;
|
if (patientsByMonth[monthIndex]) {
|
||||||
|
patientsByMonth[monthIndex].count += 1;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add some sample data for visual effect if no patients
|
// Add some sample data for visual effect if no patients
|
||||||
@@ -24,9 +26,10 @@ export function NewPatients({ patients }: NewPatientsProps) {
|
|||||||
// Sample data pattern similar to the screenshot
|
// Sample data pattern similar to the screenshot
|
||||||
const sampleData = [17, 12, 22, 16, 15, 17, 22, 28, 20, 16];
|
const sampleData = [17, 12, 22, 16, 15, 17, 22, 28, 20, 16];
|
||||||
sampleData.forEach((value, index) => {
|
sampleData.forEach((value, index) => {
|
||||||
if (index < patientsByMonth.length) {
|
if (index < patientsByMonth.length ) {
|
||||||
|
if (patientsByMonth[index]) {
|
||||||
patientsByMonth[index].count = value;
|
patientsByMonth[index].count = value;
|
||||||
}
|
}}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,60 @@ import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
|
|||||||
import { ClaimForm } from "@/components/claims/claim-form";
|
import { ClaimForm } from "@/components/claims/claim-form";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
// import { Patient, Appointment } from "@shared/schema";
|
import { PatientUncheckedCreateInputObjectSchema, AppointmentUncheckedCreateInputObjectSchema } from "@repo/db/usedSchemas";
|
||||||
import { PatientUncheckedCreateInputObjectSchema, AppointmentUncheckedCreateInputObjectSchema } from "@repo/db/shared/schemas";
|
|
||||||
import { Plus, FileCheck, CheckCircle, Clock, AlertCircle } from "lucide-react";
|
import { Plus, FileCheck, CheckCircle, Clock, AlertCircle } from "lucide-react";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
|
import {z} from "zod";
|
||||||
|
import { apiRequest } from "@/lib/queryClient";
|
||||||
|
|
||||||
|
//creating types out of schema auto generated.
|
||||||
|
type Appointment = z.infer<typeof AppointmentUncheckedCreateInputObjectSchema>;
|
||||||
|
|
||||||
|
const insertAppointmentSchema = (
|
||||||
|
AppointmentUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
||||||
|
).omit({
|
||||||
|
id: true,
|
||||||
|
createdAt: true,
|
||||||
|
});
|
||||||
|
type InsertAppointment = z.infer<typeof insertAppointmentSchema>;
|
||||||
|
|
||||||
|
const updateAppointmentSchema = (
|
||||||
|
AppointmentUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
||||||
|
)
|
||||||
|
.omit({
|
||||||
|
id: true,
|
||||||
|
createdAt: true,
|
||||||
|
})
|
||||||
|
.partial();
|
||||||
|
type UpdateAppointment = z.infer<typeof updateAppointmentSchema>;
|
||||||
|
|
||||||
|
const PatientSchema = (
|
||||||
|
PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
||||||
|
).omit({
|
||||||
|
appointments: true,
|
||||||
|
});
|
||||||
|
type Patient = z.infer<typeof PatientSchema>;
|
||||||
|
|
||||||
|
const insertPatientSchema = (
|
||||||
|
PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
||||||
|
).omit({
|
||||||
|
id: true,
|
||||||
|
createdAt: true,
|
||||||
|
});
|
||||||
|
type InsertPatient = z.infer<typeof insertPatientSchema>;
|
||||||
|
|
||||||
|
const updatePatientSchema = (
|
||||||
|
PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
|
||||||
|
)
|
||||||
|
.omit({
|
||||||
|
id: true,
|
||||||
|
createdAt: true,
|
||||||
|
userId: true,
|
||||||
|
})
|
||||||
|
.partial();
|
||||||
|
|
||||||
|
type UpdatePatient = z.infer<typeof updatePatientSchema>;
|
||||||
|
|
||||||
|
|
||||||
export default function ClaimsPage() {
|
export default function ClaimsPage() {
|
||||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
||||||
@@ -21,19 +71,29 @@ export default function ClaimsPage() {
|
|||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
|
|
||||||
// Fetch patients
|
// Fetch patients
|
||||||
const { data: patients = [], isLoading: isLoadingPatients } = useQuery<Patient[]>({
|
const { data: patients = [], isLoading: isLoadingPatients } = useQuery<
|
||||||
queryKey: ["/api/patients"],
|
Patient[]
|
||||||
enabled: !!user,
|
>({
|
||||||
});
|
queryKey: ["/api/patients/"],
|
||||||
|
queryFn: async () => {
|
||||||
|
const res = await apiRequest("GET", "/api/patients/");
|
||||||
|
return res.json();
|
||||||
|
},
|
||||||
|
enabled: !!user,
|
||||||
|
});
|
||||||
|
|
||||||
// Fetch appointments
|
// Fetch appointments
|
||||||
const {
|
const {
|
||||||
data: appointments = [] as Appointment[],
|
data: appointments = [] as Appointment[],
|
||||||
isLoading: isLoadingAppointments
|
isLoading: isLoadingAppointments,
|
||||||
} = useQuery<Appointment[]>({
|
} = useQuery<Appointment[]>({
|
||||||
queryKey: ["/api/appointments"],
|
queryKey: ["/api/appointments/all"],
|
||||||
enabled: !!user,
|
queryFn: async () => {
|
||||||
});
|
const res = await apiRequest("GET", "/api/appointments/all");
|
||||||
|
return res.json();
|
||||||
|
},
|
||||||
|
enabled: !!user,
|
||||||
|
});
|
||||||
|
|
||||||
const toggleMobileMenu = () => {
|
const toggleMobileMenu = () => {
|
||||||
setIsMobileMenuOpen(!isMobileMenuOpen);
|
setIsMobileMenuOpen(!isMobileMenuOpen);
|
||||||
@@ -59,10 +119,10 @@ export default function ClaimsPage() {
|
|||||||
acc.push({
|
acc.push({
|
||||||
patientId: patient.id,
|
patientId: patient.id,
|
||||||
patientName: `${patient.firstName} ${patient.lastName}`,
|
patientName: `${patient.firstName} ${patient.lastName}`,
|
||||||
appointmentId: appointment.id,
|
appointmentId: Number(appointment.id),
|
||||||
insuranceProvider: patient.insuranceProvider || 'N/A',
|
insuranceProvider: patient.insuranceProvider || 'N/A',
|
||||||
insuranceId: patient.insuranceId || 'N/A',
|
insuranceId: patient.insuranceId || 'N/A',
|
||||||
lastAppointment: appointment.date
|
lastAppointment: String(appointment.date)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,7 +158,7 @@ export default function ClaimsPage() {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (patientsWithAppointments.length > 0) {
|
if (patientsWithAppointments.length > 0) {
|
||||||
const firstPatient = patientsWithAppointments[0];
|
const firstPatient = patientsWithAppointments[0];
|
||||||
handleNewClaim(firstPatient.patientId, firstPatient.appointmentId);
|
handleNewClaim(Number(firstPatient?.patientId), Number(firstPatient?.appointmentId));
|
||||||
} else {
|
} else {
|
||||||
toast({
|
toast({
|
||||||
title: "No patients available",
|
title: "No patients available",
|
||||||
|
|||||||
Reference in New Issue
Block a user