import { Appointment, InsertAppointment, Patient, UpdateAppointment, } from "@repo/db/types"; import { prisma as db } from "@repo/db/client"; export interface IStorage { getAppointment(id: number): Promise; getAllAppointments(): Promise; getAppointmentsByUserId(userId: number): Promise; getAppointmentsByPatientId(patientId: number): Promise; getPatientFromAppointmentId( appointmentId: number ): Promise; getRecentAppointments(limit: number, offset: number): Promise; getAppointmentsOnRange(start: Date, end: Date): Promise; createAppointment(appointment: InsertAppointment): Promise; updateAppointment( id: number, appointment: UpdateAppointment ): Promise; deleteAppointment(id: number): Promise; getPatientAppointmentByDateTime( patientId: number, date: Date, startTime: string ): Promise; getStaffAppointmentByDateTime( staffId: number, date: Date, startTime: string, excludeId?: number ): Promise; getPatientConflictAppointment( patientId: number, date: Date, startTime: string, excludeId: number ): Promise; getStaffConflictAppointment( staffId: number, date: Date, startTime: string, excludeId: number ): Promise; getAppointmentsByDateForUser(dateStr: string, userId: number): Promise; } export const appointmentsStorage: IStorage = { async getAppointment(id: number): Promise { const appointment = await db.appointment.findUnique({ where: { id } }); return appointment ?? undefined; }, async getAllAppointments(): Promise { return await db.appointment.findMany(); }, async getAppointmentsByUserId(userId: number): Promise { return await db.appointment.findMany({ where: { userId } }); }, async getAppointmentsByPatientId(patientId: number): Promise { return await db.appointment.findMany({ where: { patientId } }); }, async getPatientFromAppointmentId( appointmentId: number ): Promise { const appointment = await db.appointment.findUnique({ where: { id: appointmentId }, include: { patient: true }, }); return appointment?.patient ?? undefined; }, async getAppointmentsOnRange(start: Date, end: Date): Promise { return db.appointment.findMany({ where: { date: { gte: start, lte: end, }, }, orderBy: { date: "asc" }, }); }, async getRecentAppointments( limit: number, offset: number ): Promise { return db.appointment.findMany({ skip: offset, take: limit, orderBy: { date: "desc" }, }); }, async createAppointment( appointment: InsertAppointment ): Promise { return await db.appointment.create({ data: appointment as Appointment }); }, async updateAppointment( id: number, updateData: UpdateAppointment ): Promise { try { return await db.appointment.update({ where: { id }, data: updateData, }); } catch (err) { throw new Error(`Appointment with ID ${id} not found`); } }, async deleteAppointment(id: number): Promise { try { await db.appointment.delete({ where: { id } }); } catch (err) { throw new Error(`Appointment with ID ${id} not found`); } }, async getPatientAppointmentByDateTime( patientId: number, date: Date, startTime: string ): Promise { return ( (await db.appointment.findFirst({ where: { patientId, date, startTime, }, })) ?? undefined ); }, async getStaffAppointmentByDateTime( staffId: number, date: Date, startTime: string, excludeId?: number ): Promise { return ( (await db.appointment.findFirst({ where: { staffId, date, startTime, NOT: excludeId ? { id: excludeId } : undefined, }, })) ?? undefined ); }, async getPatientConflictAppointment( patientId: number, date: Date, startTime: string, excludeId: number ): Promise { return ( (await db.appointment.findFirst({ where: { patientId, date, startTime, NOT: { id: excludeId }, }, })) ?? undefined ); }, async getStaffConflictAppointment( staffId: number, date: Date, startTime: string, excludeId: number ): Promise { return ( (await db.appointment.findFirst({ where: { staffId, date, startTime, NOT: { id: excludeId }, }, })) ?? undefined ); }, /** * getAppointmentsByDateForUser * dateStr expected as "YYYY-MM-DD" (same string your frontend sends) * returns appointments for that date (local midnight-to-midnight) filtered by userId */ async getAppointmentsByDateForUser(dateStr: string, userId: number): Promise { // defensive parsing — if invalid, throw so caller can handle const start = new Date(dateStr); if (Number.isNaN(start.getTime())) { throw new Error(`Invalid date string passed to getAppointmentsByDateForUser: ${dateStr}`); } // create exclusive end (next day midnight) const end = new Date(start); end.setDate(start.getDate() + 1); return db.appointment.findMany({ where: { userId, date: { gte: start, lt: end, }, }, orderBy: { startTime: "asc" }, }); } };