# 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<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**

```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"
```
