import { Router } from "express"; import type { Request, Response } from "express"; import { storage } from "../storage"; import { AppointmentUncheckedCreateInputObjectSchema, PatientUncheckedCreateInputObjectSchema, } from "@repo/db/usedSchemas"; import { z } from "zod"; const router = Router(); //creating types out of schema auto generated. type Appointment = z.infer; const insertAppointmentSchema = ( AppointmentUncheckedCreateInputObjectSchema as unknown as z.ZodObject ).omit({ id: true, createdAt: true, }); type InsertAppointment = z.infer; const updateAppointmentSchema = ( AppointmentUncheckedCreateInputObjectSchema as unknown as z.ZodObject ) .omit({ id: true, createdAt: true, }) .partial(); type UpdateAppointment = z.infer; const PatientSchema = ( PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject ).omit({ appointments: true, }); type Patient = z.infer; const insertPatientSchema = ( PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject ).omit({ id: true, createdAt: true, }); type InsertPatient = z.infer; const updatePatientSchema = ( PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject ) .omit({ id: true, createdAt: true, userId: true, }) .partial(); type UpdatePatient = z.infer; // Patient Routes // Get all patients for the logged-in user router.get("/", async (req, res) => { try { const patients = await storage.getPatientsByUserId(req.user!.id); res.json(patients); } catch (error) { res.status(500).json({ message: "Failed to retrieve patients" }); } }); // Get a single patient by ID router.get( "/:id", async (req: Request, res: Response): Promise => { try { const patientIdParam = req.params.id; // Ensure that patientIdParam exists and is a valid number if (!patientIdParam) { return res.status(400).json({ message: "Patient ID is required" }); } const patientId = parseInt(patientIdParam); const patient = await storage.getPatient(patientId); if (!patient) { return res.status(404).json({ message: "Patient not found" }); } // Ensure the patient belongs to the logged-in user if (patient.userId !== req.user!.id) { return res.status(403).json({ message: "Forbidden" }); } res.json(patient); } catch (error) { res.status(500).json({ message: "Failed to retrieve patient" }); } } ); // Create a new patient router.post("/", async (req: Request, res: Response): Promise => { try { // Validate request body const patientData = insertPatientSchema.parse({ ...req.body, userId: req.user!.id, }); // Create patient const patient = await storage.createPatient(patientData); res.status(201).json(patient); } catch (error) { if (error instanceof z.ZodError) { return res.status(400).json({ message: "Validation error", errors: error.format(), }); } res.status(500).json({ message: "Failed to create patient" }); } }); // Update an existing patient router.put( "/:id", async (req: Request, res: Response): Promise => { try { const patientIdParam = req.params.id; // Ensure that patientIdParam exists and is a valid number if (!patientIdParam) { return res.status(400).json({ message: "Patient ID is required" }); } const patientId = parseInt(patientIdParam); // Check if patient exists and belongs to user const existingPatient = await storage.getPatient(patientId); if (!existingPatient) { return res.status(404).json({ message: "Patient not found" }); } if (existingPatient.userId !== req.user!.id) { return res.status(403).json({ message: "Forbidden" }); } // Validate request body const patientData = updatePatientSchema.parse(req.body); // Update patient const updatedPatient = await storage.updatePatient( patientId, patientData ); res.json(updatedPatient); } catch (error) { if (error instanceof z.ZodError) { return res.status(400).json({ message: "Validation error", errors: error.format(), }); } res.status(500).json({ message: "Failed to update patient" }); } } ); // Delete a patient router.delete( "/:id", async (req: Request, res: Response): Promise => { try { const patientIdParam = req.params.id; // Ensure that patientIdParam exists and is a valid number if (!patientIdParam) { return res.status(400).json({ message: "Patient ID is required" }); } const patientId = parseInt(patientIdParam); // Check if patient exists and belongs to user const existingPatient = await storage.getPatient(patientId); if (!existingPatient) { return res.status(404).json({ message: "Patient not found" }); } if (existingPatient.userId !== req.user!.id) { console.warn( `User ${req.user!.id} tried to delete patient ${patientId} owned by ${existingPatient.userId}` ); return res .status(403) .json({ message: "Forbidden: Patient belongs to a different user" }); } // Delete patient await storage.deletePatient(patientId); res.status(204).send(); } catch (error:any) { console.error("Delete patient error:", error); res.status(500).json({ message: "Failed to delete patient" }); } } ); // Appointment Routes // Get all appointments for the logged-in user router.get("/appointments", async (req, res) => { try { const appointments = await storage.getAppointmentsByUserId(req.user!.id); res.json(appointments); } catch (error) { res.status(500).json({ message: "Failed to retrieve appointments" }); } }); // Get appointments for a specific patient router.get( "/:patientId/appointments", async (req: Request, res: Response): Promise => { try { const patientIdParam = req.params.id; // Ensure that patientIdParam exists and is a valid number if (!patientIdParam) { return res.status(400).json({ message: "Patient ID is required" }); } const patientId = parseInt(patientIdParam); // Check if patient exists and belongs to user const patient = await storage.getPatient(patientId); if (!patient) { return res.status(404).json({ message: "Patient not found" }); } if (patient.userId !== req.user!.id) { return res.status(403).json({ message: "Forbidden" }); } const appointments = await storage.getAppointmentsByPatientId(patientId); res.json(appointments); } catch (error) { res.status(500).json({ message: "Failed to retrieve appointments" }); } } ); export default router;