mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-11 18:28:15 +00:00
fix: disposition returns straight to worklist — no intermediate screens
Disposition is the last step. After submission, handleReset() clears all state and returns to worklist immediately. Removed the "Call Completed" card, post-disposition appointment form, and "Skip" button. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@ import { useState, useRef } from 'react';
|
|||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import {
|
import {
|
||||||
faPhone, faPhoneHangup, faMicrophone, faMicrophoneSlash,
|
faPhone, faPhoneHangup, faMicrophone, faMicrophoneSlash,
|
||||||
faPause, faPlay, faCalendarPlus, faCheckCircle,
|
faPause, faPlay, faCalendarPlus,
|
||||||
faPhoneArrowRight, faRecordVinyl, faClipboardQuestion,
|
faPhoneArrowRight, faRecordVinyl, faClipboardQuestion,
|
||||||
} from '@fortawesome/pro-duotone-svg-icons';
|
} from '@fortawesome/pro-duotone-svg-icons';
|
||||||
import { Button } from '@/components/base/buttons/button';
|
import { Button } from '@/components/base/buttons/button';
|
||||||
@@ -42,7 +42,6 @@ export const ActiveCallCard = ({ lead, callerPhone, missedCallId, onCallComplete
|
|||||||
const setCallerNumber = useSetAtom(sipCallerNumberAtom);
|
const setCallerNumber = useSetAtom(sipCallerNumberAtom);
|
||||||
const setCallUcid = useSetAtom(sipCallUcidAtom);
|
const setCallUcid = useSetAtom(sipCallUcidAtom);
|
||||||
const [postCallStage, setPostCallStage] = useState<PostCallStage | null>(null);
|
const [postCallStage, setPostCallStage] = useState<PostCallStage | null>(null);
|
||||||
const [savedDisposition, setSavedDisposition] = useState<CallDisposition | null>(null);
|
|
||||||
const [appointmentOpen, setAppointmentOpen] = useState(false);
|
const [appointmentOpen, setAppointmentOpen] = useState(false);
|
||||||
const [appointmentBookedDuringCall, setAppointmentBookedDuringCall] = useState(false);
|
const [appointmentBookedDuringCall, setAppointmentBookedDuringCall] = useState(false);
|
||||||
const [transferOpen, setTransferOpen] = useState(false);
|
const [transferOpen, setTransferOpen] = useState(false);
|
||||||
@@ -60,7 +59,6 @@ export const ActiveCallCard = ({ lead, callerPhone, missedCallId, onCallComplete
|
|||||||
const phoneDisplay = phone ? formatPhone(phone) : callerPhone || 'Unknown';
|
const phoneDisplay = phone ? formatPhone(phone) : callerPhone || 'Unknown';
|
||||||
|
|
||||||
const handleDisposition = async (disposition: CallDisposition, notes: string) => {
|
const handleDisposition = async (disposition: CallDisposition, notes: string) => {
|
||||||
setSavedDisposition(disposition);
|
|
||||||
|
|
||||||
// Submit disposition to sidecar — handles Ozonetel ACW release
|
// Submit disposition to sidecar — handles Ozonetel ACW release
|
||||||
if (callUcid) {
|
if (callUcid) {
|
||||||
@@ -76,12 +74,8 @@ export const ActiveCallCard = ({ lead, callerPhone, missedCallId, onCallComplete
|
|||||||
}).catch((err) => console.warn('Disposition failed:', err));
|
}).catch((err) => console.warn('Disposition failed:', err));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disposition === 'APPOINTMENT_BOOKED') {
|
// Side effects per disposition type
|
||||||
setPostCallStage('appointment');
|
if (disposition === 'FOLLOW_UP_SCHEDULED') {
|
||||||
setAppointmentOpen(true);
|
|
||||||
} else if (disposition === 'FOLLOW_UP_SCHEDULED') {
|
|
||||||
setPostCallStage('follow-up');
|
|
||||||
// Create follow-up
|
|
||||||
try {
|
try {
|
||||||
await apiClient.graphql(`mutation($data: FollowUpCreateInput!) { createFollowUp(data: $data) { id } }`, {
|
await apiClient.graphql(`mutation($data: FollowUpCreateInput!) { createFollowUp(data: $data) { id } }`, {
|
||||||
data: {
|
data: {
|
||||||
@@ -97,27 +91,23 @@ export const ActiveCallCard = ({ lead, callerPhone, missedCallId, onCallComplete
|
|||||||
} catch {
|
} catch {
|
||||||
notify.info('Follow-up', 'Could not auto-create follow-up');
|
notify.info('Follow-up', 'Could not auto-create follow-up');
|
||||||
}
|
}
|
||||||
setPostCallStage('done');
|
|
||||||
} else {
|
|
||||||
notify.success('Call Logged', `Disposition: ${disposition.replace(/_/g, ' ').toLowerCase()}`);
|
|
||||||
setPostCallStage('done');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disposition is the last step — return to worklist immediately
|
||||||
|
notify.success('Call Logged', `Disposition: ${disposition.replace(/_/g, ' ').toLowerCase()}`);
|
||||||
|
handleReset();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAppointmentSaved = () => {
|
const handleAppointmentSaved = () => {
|
||||||
setAppointmentOpen(false);
|
setAppointmentOpen(false);
|
||||||
notify.success('Appointment Booked', 'Payment link will be sent to the patient');
|
notify.success('Appointment Booked', 'Payment link will be sent to the patient');
|
||||||
// If booked during active call, don't skip to 'done' — wait for disposition after call ends
|
|
||||||
if (callState === 'active') {
|
if (callState === 'active') {
|
||||||
setAppointmentBookedDuringCall(true);
|
setAppointmentBookedDuringCall(true);
|
||||||
} else {
|
|
||||||
setPostCallStage('done');
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
setPostCallStage(null);
|
setPostCallStage(null);
|
||||||
setSavedDisposition(null);
|
|
||||||
setCallState('idle');
|
setCallState('idle');
|
||||||
setCallerNumber(null);
|
setCallerNumber(null);
|
||||||
setCallUcid(null);
|
setCallUcid(null);
|
||||||
@@ -192,50 +182,6 @@ export const ActiveCallCard = ({ lead, callerPhone, missedCallId, onCallComplete
|
|||||||
|
|
||||||
// Post-call flow takes priority over active state (handles race between hangup + SIP ended event)
|
// Post-call flow takes priority over active state (handles race between hangup + SIP ended event)
|
||||||
if (postCallStage !== null || callState === 'ended' || callState === 'failed') {
|
if (postCallStage !== null || callState === 'ended' || callState === 'failed') {
|
||||||
// Done state
|
|
||||||
if (postCallStage === 'done') {
|
|
||||||
return (
|
|
||||||
<div className="rounded-xl border border-success bg-success-primary p-4 text-center">
|
|
||||||
<FontAwesomeIcon icon={faCheckCircle} className="size-8 text-fg-success-primary mb-2" />
|
|
||||||
<p className="text-sm font-semibold text-success-primary">Call Completed</p>
|
|
||||||
<p className="text-xs text-tertiary mt-1">
|
|
||||||
{savedDisposition ? savedDisposition.replace(/_/g, ' ').toLowerCase() : 'logged'}
|
|
||||||
</p>
|
|
||||||
<Button size="sm" color="secondary" className="mt-3" onClick={handleReset}>
|
|
||||||
Back to Worklist
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Appointment booking after disposition — auto-return when form closes
|
|
||||||
if (postCallStage === 'appointment') {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="rounded-xl border border-brand bg-brand-primary p-4 text-center">
|
|
||||||
<FontAwesomeIcon icon={faCalendarPlus} className="size-6 text-fg-brand-primary mb-2" />
|
|
||||||
<p className="text-sm font-semibold text-brand-secondary">Booking Appointment</p>
|
|
||||||
<p className="text-xs text-tertiary mt-1">for {fullName || phoneDisplay}</p>
|
|
||||||
<Button size="sm" color="secondary" className="mt-2" onClick={() => setPostCallStage('done')}>
|
|
||||||
Skip & Return to Worklist
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<AppointmentForm
|
|
||||||
isOpen={appointmentOpen}
|
|
||||||
onOpenChange={(open) => {
|
|
||||||
setAppointmentOpen(open);
|
|
||||||
if (!open) setPostCallStage('done');
|
|
||||||
}}
|
|
||||||
callerNumber={callerPhone}
|
|
||||||
leadName={fullName || null}
|
|
||||||
leadId={lead?.id ?? null}
|
|
||||||
patientId={(lead as any)?.patientId ?? null}
|
|
||||||
onSaved={handleAppointmentSaved}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disposition form + enquiry access
|
// Disposition form + enquiry access
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
Reference in New Issue
Block a user