# 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** ```typescript // src/state/sidebar-state.ts import { atom } from 'jotai'; const stored = localStorage.getItem('helix_sidebar_collapsed'); export const sidebarCollapsedAtom = atom(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 `` - 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** ```bash 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: ```typescript 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** ```bash 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: ```typescript interface CallPrepCardProps { lead: Lead | null; callerPhone: string; activities: LeadActivity[]; } ``` - [ ] **Step 3: Commit** ```bash 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** ```bash 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** ```bash 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** ```bash 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** ```bash 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** ```bash git add -A git commit -m "feat: complete call desk redesign — collapsible nav, 2-panel layout, inline AI, Ozonetel dial" ```