mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-11 18:28:15 +00:00
docs: CSV lead import spec + defect fixing plan
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
212
docs/defect-fixing-plan.md
Normal file
212
docs/defect-fixing-plan.md
Normal file
@@ -0,0 +1,212 @@
|
||||
# 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
|
||||
```
|
||||
Reference in New Issue
Block a user