Dental Care

This commit is contained in:
Iliyan Angelov
2025-11-16 14:29:51 +02:00
commit 39077550ef
194 changed files with 43197 additions and 0 deletions

View File

@@ -0,0 +1,122 @@
import { prisma } from "@/lib/types/prisma";
import type { Prisma } from "@prisma/client";
type AppointmentSelect = {
id: string;
patientId: string;
dentistId: string;
serviceId: string;
date: Date;
timeSlot: string;
status: string;
notes: string | null;
cancelReason: string | null;
createdAt: Date;
updatedAt: Date;
};
type AppointmentWithRelations<TInclude extends Prisma.AppointmentInclude | undefined> =
TInclude extends Prisma.AppointmentInclude
? Prisma.AppointmentGetPayload<{ include: TInclude }>[]
: AppointmentSelect[];
/**
* Safely fetch appointments with relations, filtering out orphaned records
* This prevents Prisma errors when appointments reference non-existent users
*/
export async function safeFindManyAppointments<
TInclude extends Prisma.AppointmentInclude | undefined = undefined
>(
args: {
where?: Prisma.AppointmentWhereInput;
include?: TInclude;
orderBy?: Prisma.AppointmentOrderByWithRelationInput | Prisma.AppointmentOrderByWithRelationInput[];
take?: number;
skip?: number;
}
): Promise<AppointmentWithRelations<TInclude>> {
try {
// First, get all appointments without relations
const appointments = await prisma.appointment.findMany({
where: args.where,
select: {
id: true,
patientId: true,
dentistId: true,
serviceId: true,
date: true,
timeSlot: true,
status: true,
notes: true,
cancelReason: true,
createdAt: true,
updatedAt: true,
},
orderBy: args.orderBy,
take: args.take,
skip: args.skip,
});
// Get all unique patient and dentist IDs
const patientIds = [...new Set(appointments.map((apt) => apt.patientId))];
const dentistIds = [...new Set(appointments.map((apt) => apt.dentistId))];
const serviceIds = [...new Set(appointments.map((apt) => apt.serviceId))];
// Verify that all referenced users and services exist
const [patients, dentists, services] = await Promise.all([
prisma.user.findMany({
where: { id: { in: patientIds } },
select: { id: true },
}),
prisma.user.findMany({
where: { id: { in: dentistIds } },
select: { id: true },
}),
prisma.service.findMany({
where: { id: { in: serviceIds } },
select: { id: true },
}),
]);
const validPatientIds = new Set(patients.map((p) => p.id));
const validDentistIds = new Set(dentists.map((d) => d.id));
const validServiceIds = new Set(services.map((s) => s.id));
// Filter out appointments with invalid references
const validAppointments = appointments.filter(
(apt) =>
validPatientIds.has(apt.patientId) &&
validDentistIds.has(apt.dentistId) &&
validServiceIds.has(apt.serviceId)
);
// If no include needed, return early
if (!args.include || validAppointments.length === 0) {
return validAppointments as AppointmentWithRelations<TInclude>;
}
// Now fetch the full appointments with relations for valid ones only
const validAppointmentIds = validAppointments.map((apt) => apt.id);
try {
const fullAppointments = await prisma.appointment.findMany({
where: {
id: { in: validAppointmentIds },
},
include: args.include,
orderBy: args.orderBy,
});
return fullAppointments as AppointmentWithRelations<TInclude>;
} catch (error) {
console.error("[safeFindManyAppointments] Error fetching relations:", error);
// Return appointments without relations if relation fetch fails
return validAppointments as AppointmentWithRelations<TInclude>;
}
} catch (error) {
console.error("[safeFindManyAppointments] Error:", error);
// Return empty array on error instead of crashing
return [] as unknown as AppointmentWithRelations<TInclude>;
}
}