10 KiB
Helix Engage — Defect Fixing Plan
Date: 2026-03-31 Status: Analysis complete, implementation pending
Item 1: Sidebar navigation during ongoing calls
Status: NOT A BUG
Finding: Sidebar is fully functional during calls. No code blocks navigation. Call state persists via Jotai atoms (sipCallStateAtom, sipCallerNumberAtom, sipCallUcidAtom) regardless of which page the agent navigates to. CallWidget in app-shell.tsx (line 80) renders on non-call-desk pages when a call is active, ensuring the agent can return.
Item 2: Appointment form / Enquiry form visibility during calls
Status: APPROVED REDESIGN — Convert to modals
Root Cause: active-call-card.tsx renders AppointmentForm and EnquiryForm inside a max-h-[50vh] overflow-y-auto container (line 292). After the call header + controls take ~100px, the form is squeezed.
Approved approach: Convert both forms to modal dialogs (like TransferDialog already is).
Flow:
Agent clicks "Book Appt" → Modal opens → Log intent to LeadActivity → Agent fills form
→ Save succeeds → setSuggestedDisposition('APPOINTMENT_BOOKED') → Modal closes
→ Save abandoned → No disposition change → Intent logged for supervisor analytics
Same for Enquiry → INFO_PROVIDED on save, intent logged on open.
Files to change:
src/components/call-desk/active-call-card.tsx— replace inline form expansion with modal triggerssrc/components/call-desk/appointment-form.tsx— wrap in Modal/ModalOverlay fromsrc/components/application/modals/modalsrc/components/call-desk/enquiry-form.tsx— wrap in Modal/ModalOverlay
Benefits: Solves Item 2 (form visibility), Item 10a (returning patient checkbox shift), keeps call card clean.
Effort: Medium (3-4h)
Item 3: Enquiry form disposition + modal disposition context
Status: REAL ISSUE (two parts)
3a: Remove disposition from enquiry form
enquiry-form.tsx (lines 19-26, 195-198) has its own disposition field with 6 options (CONVERTED, FOLLOW_UP, GENERAL_QUERY, NO_ANSWER, INVALID_NUMBER, CALL_DROPPED). During an active call, NO_ANSWER and INVALID_NUMBER are nonsensical — the caller is connected.
Fix: Remove disposition field from enquiry form entirely. Disposition is captured in the disposition modal after the call ends. The enquiry form's job is to log the enquiry, not to classify the call outcome.
Files: src/components/call-desk/enquiry-form.tsx — remove disposition Select + validation
3b: Context-aware disposition options in modal
disposition-modal.tsx (lines 15-57) shows all 6 options regardless of call context. During an inbound answered call, "No Answer" and "Wrong Number" don't apply.
Fix: Accept a callContext prop ('inbound-answered' | 'outbound' | 'missed-callback') and filter options accordingly:
- Inbound answered: show APPOINTMENT_BOOKED, FOLLOW_UP_SCHEDULED, INFO_PROVIDED, CALLBACK_REQUESTED
- Outbound: show all
- Missed callback: show all
Files: src/components/call-desk/disposition-modal.tsx, src/components/call-desk/active-call-card.tsx
Effort: Low (2h)
Item 4: Edit future appointment during inbound call
Status: DONE (2026-03-30)
Implementation: Context panel (context-panel.tsx lines 172-197) shows upcoming appointments with Edit button → opens AppointmentForm in edit mode with existingAppointment prop. Appointments fetched via APPOINTMENTS_QUERY in DataProvider.
Item 5: My Performance page
Status: THREE SUB-ISSUES
5a: From/To date range filter
Current: Only Today/Yesterday presets + single date picker in my-performance.tsx (lines 95-135).
Fix: Add two DatePicker components (From/To) or a date range picker. Update API call to accept date range. Update chart/KPI computations to use range.
Effort: Medium (3-4h)
5b: Time Utilisation not displayed
Current: Section renders conditionally at line 263 — only if timeUtilization is not null. If sidecar API returns null (Ozonetel getAgentSummary fails or VPN blocks), section silently disappears.
Fix: Add placeholder/error state when null: "Time utilisation data unavailable — check Ozonetel connection"
Effort: Low (30min)
5c: Data loading slow
Current: Fetches from /api/ozonetel/performance on every date change, no caching.
Fix: Add response caching (memoize by date key), show skeleton loader during fetch, debounce date changes.
Effort: Medium (2h)
Item 6: Break and Training status not working
Status: REAL ISSUE — likely Ozonetel API parameter mismatch
Root Cause: agent-status-toggle.tsx (lines 41-64) calls /api/ozonetel/agent-state with { state: 'Pause', pauseReason: 'Break' } or 'Training'. Ozonetel's changeAgentState API may expect different pause reason enum values. Errors are caught and shown as generic toast — no specific failure reason.
Investigation needed:
- Check sidecar logs for the actual Ozonetel API response when Break/Training is selected
- Verify Ozonetel API docs for valid
pauseReasonvalues (may needBREAK,TRAINING, or numeric codes) - Check if the agent must be in
Readystate before transitioning toPause
Fix: Correct pause reason values, add specific error messages. Effort: Low-Medium (2-3h including investigation)
Item 7: Auto-refresh for Call Desk, Call History, Appointments
Status: REAL ISSUE
| Page | Current | Fix |
|---|---|---|
| Call Desk worklist | YES (30s via use-worklist.ts) |
Working |
| DataProvider (calls, leads, etc.) | NO — useEffect([fetchData]) runs once |
Add setInterval(fetchData, 30000) |
| Call History | NO — uses useData() |
Automatic once DataProvider fixed |
| Appointments | NO — useEffect([]) runs once |
Add interval or move to DataProvider |
Files: src/providers/data-provider.tsx (lines 117-119), src/pages/appointments.tsx (lines 76-81)
Effort: Low (1-2h)
Item 8: Appointments page improvements
Status: THREE SUB-ISSUES
8a: Appointment ID as primary field
Current: No ID column in table. appointments.tsx shows Patient, Date, Time, Doctor, Department, Branch, Status, Chief Complaint.
Fix: Add ID column (first column) showing appointment ID or a short reference number.
Effort: Low (30min)
8b: Edit Appointment option
Current: No edit button on appointments page (only exists in call desk context panel).
Fix: Add per-row Edit button → opens AppointmentForm in edit mode (same component, reuse existingAppointment prop).
Pending: Confirmation from Meghana
Effort: Low (1-2h)
8c: Sort by status
Current: Tabs filter by status but no column-level sorting.
Fix: Add allowsSorting to table headers + sortDescriptor/onSortChange (same pattern as worklist).
Pending: Confirmation from Meghana
Effort: Low (1h)
Item 9: AI Surface enlargement + patient historical data
Status: PARTIALLY DONE
9a: Panel width
Current: Context panel is w-[400px] in call-desk.tsx (line 218).
Fix: Increase to w-[440px] or w-[460px].
Effort: Trivial
9b: Patient historical data
Current: We added calls, follow-ups, and appointments to context panel (2026-03-30). Shows in "Upcoming" and "Recent" sections. Data requires patientId on the lead — populated by caller resolution service.
Verify: Test with real inbound call to confirmed patient. If lead has no patientId, nothing shows.
Effort: Done — verify only
Item 10: Multiple issues
10a: Returning Patient checkbox shifts form upward
Status: WILL BE FIXED by Item 2 (modal conversion). Form in modal has its own layout — checkbox toggle won't affect call card.
10b: Patients page table not scrollable
File: src/pages/patients.tsx
Fix: Add overflow-auto to table container wrapper. Check if outer div has proper min-h-0 for flex overflow.
Effort: Trivial (15min)
10c: Call log data not appearing in worklist tabs
Status: INVESTIGATION NEEDED Possible causes:
- Sidecar
/api/worklistnot returning data — check endpoint response - Calls created via Ozonetel disposition lack
leadIdlinkage — can't match to worklist - Call records created but
callStatusnot set correctly (needMISSEDfor missed tab) Action: Check sidecar logs and/api/worklistresponse payload
10d: Missed calls appearing in wrong sub-tabs (Attempted/Completed/Invalid instead of Pending)
Status: INVESTIGATION NEEDED
Possible cause: callbackstatus field being set to non-null value during call creation. worklist-panel.tsx (line 246) routes to Pending when callbackstatus === 'PENDING_CALLBACK' || !callbackstatus. If the sidecar sets a status during ingestion, it may skip Pending.
Action: Check missed call ingestion code in sidecar — what callbackstatus is set on creation
Item 11: Patient column filter in Call Desk
Status: NOT A BUG
Finding: The PATIENT column has allowsSorting (added 2026-03-30) which shows a sort arrow. This is a sort control, not a filter. The search box at the top of the worklist filters across name + phone. No separate column-level filter exists. Functionally correct.
Priority Matrix
| Priority | Items | Total Effort |
|---|---|---|
| P0 — Do first | #2 (modal conversion — solves 2, 10a), #7 (auto-refresh), #3 (disposition context) | ~7h |
| P1 — Quick wins | #8a (appt ID), #8c (sort), #9a (panel width), #10b (scroll fix), #5b (time util placeholder) | ~3h |
| P2 — Medium | #5a (date range), #5c (loading perf), #6 (break/training debug), #8b (edit appt) | ~8h |
| P3 — Investigation | #10c (call log data), #10d (missed call routing) | ~2h investigation |
| Done | #1, #4, #9b, #11 | — |
Data Seeding (separate from defects)
Patient/Lead seeding
| Name | Phone | Action |
|---|---|---|
| Ganesh Bandi | 8885540404 | Create patient + lead, interestedService: "Back Pain" |
| Meghana | 7702055204 | Update existing "Unknown" patient + lead, interestedService: "Hair Loss" |
CC Agent profiles (completed)
Agent Email Password Ozonetel ID SIP Ext Campaign
-------- ---------------------------- --------- -------------- -------- ----------------------
Rekha S rekha.cc@globalhospital.com Test123$ global 523590 Inbound_918041763265
Ganesh ganesh.cc@globalhospital.com Test123$ globalhealthx 523591 Inbound_918041763265