fix: setup wizard role guard, Doctor.clinic removal, dial sends agent config

Defect 1: Setup wizard (/setup) now guarded by AdminSetupGuard —
CC agents and other non-admin roles are redirected to / instead of
seeing the setup wizard they can't complete.

Defect 3: Removed all references to Doctor.clinic (relation was
replaced by DoctorVisitSlot entity). Updated queries.ts,
appointments.tsx, transforms.ts, doctors.tsx, appointment-form.tsx.

Defect 6 (frontend side): Dial request now sends agentId and
campaignName from localStorage agent config so the sidecar dials
with the correct per-agent credentials, not global defaults.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-10 14:29:32 +05:30
parent 72012f099c
commit fb92da113e
7 changed files with 27 additions and 13 deletions

View File

@@ -58,7 +58,7 @@ const QUERY = `{ appointments(first: 100, orderBy: [{ scheduledAt: DescNullsLast
id scheduledAt durationMin appointmentType status
doctorName department reasonForVisit
patient { id fullName { firstName lastName } phones { primaryPhoneNumber } }
doctor { clinic { clinicName } }
doctor { id }
} } } }`;
const formatDate = (iso: string): string => formatDateOnly(iso);
@@ -103,7 +103,7 @@ export const AppointmentsPage = () => {
const phone = a.patient?.phones?.primaryPhoneNumber ?? '';
const doctor = (a.doctorName ?? '').toLowerCase();
const dept = (a.department ?? '').toLowerCase();
const branch = (a.doctor?.clinic?.clinicName ?? '').toLowerCase();
const branch = (a.department ?? '').toLowerCase();
return patientName.includes(q) || phone.includes(q) || doctor.includes(q) || dept.includes(q) || branch.includes(q);
});
}
@@ -177,7 +177,7 @@ export const AppointmentsPage = () => {
? `${appt.patient.fullName?.firstName ?? ''} ${appt.patient.fullName?.lastName ?? ''}`.trim() || 'Unknown'
: 'Unknown';
const phone = appt.patient?.phones?.primaryPhoneNumber ?? '';
const branch = appt.doctor?.clinic?.clinicName ?? '—';
const branch = appt.department ?? '—';
const statusLabel = STATUS_LABELS[appt.status ?? ''] ?? appt.status ?? '—';
const statusColor = STATUS_COLORS[appt.status ?? ''] ?? 'gray';

View File

@@ -133,7 +133,7 @@ const toFormValues = (doctor: DoctorNode): DoctorFormValues => ({
doctor.doctorVisitSlots?.edges.map(
(e): DoctorVisitSlotEntry => ({
id: e.node.id,
clinicId: e.node.clinicId ?? e.node.clinic?.id ?? '',
clinicId: e.node.clinicId ?? e.node.clinicId ?? '',
dayOfWeek: e.node.dayOfWeek ?? '',
startTime: e.node.startTime ?? null,
endTime: e.node.endTime ?? null,
@@ -156,7 +156,7 @@ const summariseVisitSlots = (
if (edges.length === 0) return 'No slots';
const byClinic = new Map<string, DayOfWeek[]>();
for (const e of edges) {
const cid = e.node.clinicId ?? e.node.clinic?.id;
const cid = e.node.clinicId ?? e.node.clinicId;
if (!cid || !e.node.dayOfWeek) continue;
if (!byClinic.has(cid)) byClinic.set(cid, []);
byClinic.get(cid)!.push(e.node.dayOfWeek);