Files
helix-engage/docs/superpowers/plans/2026-03-18-call-desk-redesign.md
saridsa2 526ad18159 feat: call desk redesign — 2-panel layout, collapsible sidebar, inline AI, ringtone
- Collapsible sidebar with Jotai atom (icon-only mode, persisted to localStorage)
- 2-panel call desk: worklist (60%) + context panel (40%) with AI + Lead 360 tabs
- Inline AI call prep card — known lead summary or unknown caller script
- Active call card with compact Answer/Decline buttons
- Worklist panel with human-readable labels, priority badges, click-to-select
- Context panel auto-switches to Lead 360 when lead selected or call incoming
- Browser ringtone via Web Audio API on incoming calls
- Sonner + Untitled UI IconNotification for toast system
- apiClient pattern: centralized post/get/graphql with auto-toast on errors
- Remove duplicate avatar from top bar, hide floating widget on call desk
- Fix Link routing in collapsed sidebar (was using <a> causing full page reload)
- Fix GraphQL field names: adStatus→status, platformUrl needs subfield selection
- Silent mode for DataProvider queries to prevent toast spam

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 18:33:36 +05:30

12 KiB

Call Desk Redesign + Ozonetel Dial API

For agentic workers: REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Rebuild the call desk into a 2-panel layout with collapsible sidebar, inline AI assistant, and Ozonetel outbound dial integration.

Architecture: The call desk becomes the agent's cockpit — a 2-panel layout (main 60% + context 40%) with the worklist always visible. The left nav sidebar becomes collapsible (icon-only mode) to maximize workspace. AI is inline within the call flow, not a separate tab. Outbound calls go through Ozonetel REST API (dialCustomer → agent SIP ring → bridge to customer).

Tech Stack: React 19, Jotai atoms, Untitled UI components, FontAwesome Pro Duotone icons, NestJS sidecar, Ozonetel CloudAgent REST API


File Structure

Sidecar (helix-engage-server)

  • src/ozonetel/ozonetel-agent.service.ts — ALREADY DONE: dialCustomer() method added
  • src/ozonetel/ozonetel-agent.controller.ts — ALREADY DONE: POST /api/ozonetel/dial endpoint added

Frontend (helix-engage)

Modified files:

  • src/components/layout/sidebar.tsx — Add collapse/expand toggle, icon-only mode
  • src/components/layout/app-shell.tsx — Pass collapse state to sidebar, adjust main content margin
  • src/pages/call-desk.tsx — Complete rewrite: 2-panel layout with worklist + context panel
  • src/components/call-desk/ai-chat-panel.tsx — Move to context panel, full-height, always visible
  • src/components/call-desk/incoming-call-card.tsx — Simplify for inline use (no idle/waiting states)
  • src/components/call-desk/click-to-call-button.tsx — ALREADY DONE: Uses Ozonetel dial API

New files:

  • src/state/sidebar-state.ts — Jotai atom for sidebar collapsed state (persisted to localStorage)
  • src/components/call-desk/worklist-panel.tsx — Worklist section: missed calls, follow-ups, assigned leads
  • src/components/call-desk/context-panel.tsx — Right panel: AI chat + lead 360 tabs
  • src/components/call-desk/call-prep-card.tsx — Inline AI prep card (known lead summary / unknown caller script)
  • src/components/call-desk/active-call-card.tsx — Compact caller info + controls during active call

Task 1: Collapsible Sidebar

Files:

  • Create: src/state/sidebar-state.ts

  • Modify: src/components/layout/sidebar.tsx

  • Modify: src/components/layout/app-shell.tsx

  • Step 1: Create sidebar Jotai atom

// src/state/sidebar-state.ts
import { atom } from 'jotai';

const stored = localStorage.getItem('helix_sidebar_collapsed');
export const sidebarCollapsedAtom = atom<boolean>(stored === 'true');
  • Step 2: Add collapse toggle to sidebar

In sidebar.tsx:

  • Add a collapse button (chevron icon) at the top-right of the sidebar

  • When collapsed: sidebar width shrinks from 292px to 64px, show only icons (no labels, no section headers)

  • NavItemBase gets a collapsed prop — renders icon-only with tooltip

  • Account card at bottom: show only avatar when collapsed

  • Logo: show only "H" icon when collapsed

  • Persist state to localStorage via Jotai atom

  • Step 3: Wire AppShell to sidebar collapse state

In app-shell.tsx:

  • Read sidebarCollapsedAtom with useAtom

  • Pass collapsed state to <Sidebar collapsed={collapsed} />

  • Adjust the invisible spacer width from 292px to 64px when collapsed

  • Step 4: Verify sidebar works in both states

Manual test:

  • Click collapse button → sidebar shrinks to icons-only, tooltips show on hover

  • Click expand button → sidebar returns to full width

  • Refresh page → collapsed state persists

  • Step 5: Commit

git add src/state/sidebar-state.ts src/components/layout/sidebar.tsx src/components/layout/app-shell.tsx
git commit -m "feat: add collapsible sidebar with icon-only mode"

Task 2: Worklist Panel Component

Files:

  • Create: src/components/call-desk/worklist-panel.tsx

  • Step 1: Create worklist panel

A vertical list component that renders three sections:

  1. Missed Calls (red border) — from useWorklist().missedCalls
  2. Follow-ups Due (amber/blue border) — from useWorklist().followUps
  3. Assigned Leads (brand border) — from useWorklist().marketingLeads

Each item is a compact card:

  • Lead name, phone number, service interest
  • Priority/SLA badge
  • Click-to-call button (uses Ozonetel dial via existing ClickToCallButton)
  • Clicking the card (not the call button) selects it and loads context in the right panel

Props:

interface WorklistPanelProps {
    onSelectLead: (lead: WorklistLead) => void;
    selectedLeadId: string | null;
}
  • Step 2: Verify worklist renders with seeded data

Manual test: worklist shows Priya, Ravi, Deepa, Vijay with phone numbers and services

  • Step 3: Commit
git add src/components/call-desk/worklist-panel.tsx
git commit -m "feat: add worklist panel component"

Task 3: Call Prep Card (Inline AI)

Files:

  • Create: src/components/call-desk/call-prep-card.tsx

  • Step 1: Create call prep card for known leads

When a call comes in from a known lead, this card shows:

  • Lead name, status, score

  • AI summary (from lead.aiSummary)

  • AI suggested action (from lead.aiSuggestedAction)

  • Recent activity (last 3 activities)

  • Campaign attribution

  • Step 2: Add unknown caller variant

When a call comes in from an unknown number:

  • "Unknown Caller" header with the phone number
  • "No record found" message
  • Suggested script: Ask name, DOB, service interest, how they heard about us, offer to book consultation
  • "Create Lead" button to create a new lead from the call

Props:

interface CallPrepCardProps {
    lead: Lead | null;
    callerPhone: string;
    activities: LeadActivity[];
}
  • Step 3: Commit
git add src/components/call-desk/call-prep-card.tsx
git commit -m "feat: add inline AI call prep card"

Task 4: Context Panel

Files:

  • Create: src/components/call-desk/context-panel.tsx

  • Modify: src/components/call-desk/ai-chat-panel.tsx — remove header, make full-height

  • Step 1: Create context panel with tabs

Right panel (40% width) with two tabs:

  • AI Assistant — The existing AiChatPanel, now full-height with callerContext auto-set from selected lead
  • Lead 360 — Summary of selected lead: profile, appointments, call history, activities

When no lead is selected: show AI Assistant tab by default with quick prompts. When a lead is selected (from worklist click or incoming call): auto-switch to Lead 360 tab, pre-populate AI context.

  • Step 2: Update AiChatPanel for inline use

Remove the standalone header (it's now inside the context panel tab). Make it flex-1 to fill available height. Auto-send a prep message when callerContext changes (e.g., "Tell me about the patient on the line").

  • Step 3: Commit
git add src/components/call-desk/context-panel.tsx src/components/call-desk/ai-chat-panel.tsx
git commit -m "feat: add context panel with AI + Lead 360 tabs"

Task 5: Active Call Card

Files:

  • Create: src/components/call-desk/active-call-card.tsx

  • Step 1: Create compact active call card

Replaces the worklist section when a call is active. Shows:

  • Caller name/number
  • Call duration timer
  • Call controls: Mute, Hold, Hangup
  • Answer/Reject buttons (during ringing)
  • Disposition form (after call ends)

Uses Jotai SIP atoms for call state.

  • Step 2: Commit
git add src/components/call-desk/active-call-card.tsx
git commit -m "feat: add compact active call card"

Task 6: Call Desk Page Rewrite

Files:

  • Modify: src/pages/call-desk.tsx — Complete rewrite

  • Step 1: Rewrite call desk with 2-panel layout

┌──────────────────────────────────┬─────────────────────────────┐
│  MAIN (60%)                      │  CONTEXT (40%)              │
│                                  │                             │
│  ┌─ Status Bar ───────────────┐  │  Context Panel              │
│  │ ● Ready · Rekha · 4 items │  │  (AI Chat | Lead 360)       │
│  └────────────────────────────┘  │                             │
│                                  │                             │
│  When IDLE:                      │                             │
│  ┌─ Worklist Panel ───────────┐  │                             │
│  │ (missed calls, follow-ups, │  │                             │
│  │  assigned leads)           │  │                             │
│  └────────────────────────────┘  │                             │
│                                  │                             │
│  When CALL ACTIVE:               │                             │
│  ┌─ Active Call Card ─────────┐  │                             │
│  │ (caller info, controls)    │  │                             │
│  └────────────────────────────┘  │                             │
│  ┌─ Call Prep Card ───────────┐  │                             │
│  │ (AI summary, suggested     │  │                             │
│  │  action, recent activity)  │  │                             │
│  └────────────────────────────┘  │                             │
│                                  │                             │
│  ┌─ Today's Calls ────────────┐  │                             │
│  │ (call log, always visible) │  │                             │
│  └────────────────────────────┘  │                             │
└──────────────────────────────────┴─────────────────────────────┘

Key behaviors:

  • Clicking a worklist item selects it → context panel shows lead 360 + AI context

  • Incoming call → active call card replaces worklist, call prep card appears inline, context panel auto-loads lead data

  • Unknown caller → call prep shows script for new caller

  • After disposition → returns to worklist view

  • Step 2: Remove old sidebar tab (Stats/AI) from call desk

Stats move into a collapsible section at the top of the main panel or into the top bar. AI is now always in the context panel.

  • Step 3: Wire SIP call events to call desk state

When SIP ringing-in fires:

  1. Look up caller by phone number (from worklist data or platform query)
  2. If found → set active lead, show call prep with AI summary
  3. If not found → show unknown caller prep card
  4. Context panel auto-switches to lead 360 (if found) or AI assistant (if unknown)
  • Step 4: Verify end-to-end flow

Manual test:

  1. Login as Rekha → call desk shows worklist with 4 leads
  2. Click Priya → context panel shows her lead 360 with AI summary
  3. Click "Call" on Priya → Ozonetel dials, SIP rings agent
  4. Call from unknown number → unknown caller prep card appears
  • Step 5: Commit
git add src/pages/call-desk.tsx
git commit -m "feat: redesign call desk — 2-panel layout with inline AI"

Task 7: Final Integration Test

  • Step 1: Run the AI flow test harness
cd helix-engage && npx tsx scripts/test-ai-flow.ts

Expected: ALL TESTS PASSED (steps 1-9)

  • Step 2: Manual smoke test
  1. Login as Rekha (rekha.cc@globalhospital.com / Global@123)
  2. Sidebar collapses and expands correctly
  3. Call desk shows worklist with real platform data (4 assigned leads)
  4. Clicking a lead loads context panel with lead details
  5. AI assistant responds to queries with real platform data
  6. Click-to-call triggers Ozonetel dial API (SIP rings agent)
  7. Phone shows "Ready" status
  • Step 3: Commit all remaining changes
git add -A
git commit -m "feat: complete call desk redesign — collapsible nav, 2-panel layout, inline AI, Ozonetel dial"