Files
helix-engage/docs/defect-fixing-plan.md
2026-03-31 11:45:04 +05:30

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 triggers
  • src/components/call-desk/appointment-form.tsx — wrap in Modal/ModalOverlay from src/components/application/modals/modal
  • src/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:

  1. Check sidecar logs for the actual Ozonetel API response when Break/Training is selected
  2. Verify Ozonetel API docs for valid pauseReason values (may need BREAK, TRAINING, or numeric codes)
  3. Check if the agent must be in Ready state before transitioning to Pause

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:

  1. Sidecar /api/worklist not returning data — check endpoint response
  2. Calls created via Ozonetel disposition lack leadId linkage — can't match to worklist
  3. Call records created but callStatus not set correctly (need MISSED for missed tab) Action: Check sidecar logs and /api/worklist response 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