fix(appointments): preload clinic + keep saved time on edit
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

The appointment-edit form opened with clinic/time blank even for
well-formed appointments because the pipeline never carried clinicId
end-to-end. Four-layer audit + fix:

1. APPOINTMENTS_QUERY now fetches clinicId + clinic { id clinicName }
   + doctor.fullName (was only doctor.id).
2. transformAppointments populates real clinicId + clinicName from the
   relation instead of faking clinicName=department.
3. Appointment type gets clinicId: string | null.
4. context-panel passes clinicId through to AppointmentForm's
   existingAppointment prop; form initial-states clinic from it.

Also on edit: if the saved timeSlot isn't in the fresh slot list
(past-slot filter, schedule change, clinic mismatch) we inject it as
"HH:MM (current)" so the dropdown displays the existing value instead
of looking cleared.

Historical appointments with clinicId=null on the platform still fall
through to the auto-select-from-slot logic; a maint backfill for those
is a separate task.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-15 11:56:51 +05:30
parent d3cbf4d2bb
commit 72cb192447
5 changed files with 53 additions and 21 deletions

View File

@@ -158,22 +158,31 @@ export function transformCalls(data: any): Call[] {
}
export function transformAppointments(data: any): Appointment[] {
return extractEdges(data, 'appointments').map((n) => ({
id: n.id,
createdAt: n.createdAt,
scheduledAt: n.scheduledAt,
durationMinutes: n.durationMin ?? 30,
appointmentType: n.appointmentType,
appointmentStatus: n.status,
doctorName: n.doctorName,
doctorId: n.doctor?.id ?? null,
department: n.department,
reasonForVisit: n.reasonForVisit,
patientId: n.patient?.id ?? null,
patientName: n.patient?.fullName ? `${n.patient.fullName.firstName} ${n.patient.fullName.lastName}`.trim() : null,
patientPhone: n.patient?.phones?.primaryPhoneNumber ?? null,
clinicName: n.department ?? null,
}));
return extractEdges(data, 'appointments').map((n) => {
// Doctor name: prefer the relation's fullName (authoritative — pulled
// from the Doctor entity). Fall back to the denormalized doctorName
// field for legacy rows that predate the doctor relation being fetched.
const doctorFullName = n.doctor?.fullName
? `${n.doctor.fullName.firstName ?? ''} ${n.doctor.fullName.lastName ?? ''}`.trim()
: '';
return {
id: n.id,
createdAt: n.createdAt,
scheduledAt: n.scheduledAt,
durationMinutes: n.durationMin ?? 30,
appointmentType: n.appointmentType,
appointmentStatus: n.status,
doctorName: doctorFullName || n.doctorName || null,
doctorId: n.doctor?.id ?? null,
department: n.department,
reasonForVisit: n.reasonForVisit,
patientId: n.patient?.id ?? null,
patientName: n.patient?.fullName ? `${n.patient.fullName.firstName} ${n.patient.fullName.lastName}`.trim() : null,
patientPhone: n.patient?.phones?.primaryPhoneNumber ?? null,
clinicId: n.clinicId ?? n.clinic?.id ?? null,
clinicName: n.clinic?.clinicName ?? null,
};
});
}
export function transformPatients(data: any): Patient[] {