mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-11 18:28:15 +00:00
fix: pinned header/chat input, numpad dialler, caller matching, appointment FK
- AppShell: h-screen + overflow-hidden for pinned header - AI chat: input pinned to bottom, messages scroll independently - Dialler: numpad grid (1-9,*,0,#) replaces text input - Inbound calls: don't fall back to previously selected lead - Appointment: use lead.patientId instead of leadId for FK - Added .env.production for consistent builds Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,7 +20,7 @@ type ExistingAppointment = {
|
||||
doctorId?: string;
|
||||
department: string;
|
||||
reasonForVisit?: string;
|
||||
appointmentStatus: string;
|
||||
status: string;
|
||||
};
|
||||
|
||||
type AppointmentFormProps = {
|
||||
@@ -29,6 +29,7 @@ type AppointmentFormProps = {
|
||||
callerNumber?: string | null;
|
||||
leadName?: string | null;
|
||||
leadId?: string | null;
|
||||
patientId?: string | null;
|
||||
onSaved?: () => void;
|
||||
existingAppointment?: ExistingAppointment | null;
|
||||
};
|
||||
@@ -70,6 +71,7 @@ export const AppointmentForm = ({
|
||||
callerNumber,
|
||||
leadName,
|
||||
leadId,
|
||||
patientId,
|
||||
onSaved,
|
||||
existingAppointment,
|
||||
}: AppointmentFormProps) => {
|
||||
@@ -141,11 +143,11 @@ export const AppointmentForm = ({
|
||||
`{ appointments(filter: {
|
||||
doctorId: { eq: "${doctor}" },
|
||||
scheduledAt: { gte: "${date}T00:00:00", lte: "${date}T23:59:59" }
|
||||
}) { edges { node { id scheduledAt durationMin appointmentStatus } } } }`,
|
||||
}) { edges { node { id scheduledAt durationMin status } } } }`,
|
||||
).then(data => {
|
||||
// Filter out cancelled/completed appointments client-side
|
||||
const activeAppointments = data.appointments.edges.filter(e => {
|
||||
const status = e.node.appointmentStatus;
|
||||
const status = e.node.status;
|
||||
return status !== 'CANCELLED' && status !== 'COMPLETED' && status !== 'NO_SHOW';
|
||||
});
|
||||
const slots = activeAppointments.map(e => {
|
||||
@@ -223,14 +225,14 @@ export const AppointmentForm = ({
|
||||
notify.success('Appointment Updated');
|
||||
} else {
|
||||
// Double-check slot availability before booking
|
||||
const checkResult = await apiClient.graphql<{ appointments: { edges: Array<{ node: { appointmentStatus: string } }> } }>(
|
||||
const checkResult = await apiClient.graphql<{ appointments: { edges: Array<{ node: { status: string } }> } }>(
|
||||
`{ appointments(filter: {
|
||||
doctorId: { eq: "${doctor}" },
|
||||
scheduledAt: { gte: "${date}T${timeSlot}:00", lte: "${date}T${timeSlot}:00" }
|
||||
}) { edges { node { appointmentStatus } } } }`,
|
||||
}) { edges { node { status } } } }`,
|
||||
);
|
||||
const activeBookings = checkResult.appointments.edges.filter(e =>
|
||||
e.node.appointmentStatus !== 'CANCELLED' && e.node.appointmentStatus !== 'NO_SHOW',
|
||||
e.node.status !== 'CANCELLED' && e.node.status !== 'NO_SHOW',
|
||||
);
|
||||
if (activeBookings.length > 0) {
|
||||
setError('This slot was just booked by someone else. Please select a different time.');
|
||||
@@ -248,12 +250,12 @@ export const AppointmentForm = ({
|
||||
scheduledAt,
|
||||
durationMin: 30,
|
||||
appointmentType: 'CONSULTATION',
|
||||
appointmentStatus: 'SCHEDULED',
|
||||
status: 'SCHEDULED',
|
||||
doctorName: selectedDoctor?.name ?? '',
|
||||
department: selectedDoctor?.department ?? '',
|
||||
doctorId: doctor,
|
||||
reasonForVisit: chiefComplaint || null,
|
||||
...(leadId ? { patientId: leadId } : {}),
|
||||
...(patientId ? { patientId } : {}),
|
||||
},
|
||||
},
|
||||
);
|
||||
@@ -294,7 +296,7 @@ export const AppointmentForm = ({
|
||||
}`,
|
||||
{
|
||||
id: existingAppointment.id,
|
||||
data: { appointmentStatus: 'CANCELLED' },
|
||||
data: { status: 'CANCELLED' },
|
||||
},
|
||||
);
|
||||
notify.success('Appointment Cancelled');
|
||||
|
||||
Reference in New Issue
Block a user