Files
helix-engage/docs/superpowers/plans/2026-03-19-data-pages.md
saridsa2 4c6cae9d65 feat: build all data pages — worklist table, call history, patients, dashboard, reports
Worklist (call-desk):
- Upgrade to Untitled UI Table with columns: Priority, Patient, Phone, Type, SLA, Actions
- Filter tabs: All Tasks / Missed Calls / Callbacks / Follow-ups with counts
- Search by name or phone
- SLA timer color-coded: green <15m, amber <30m, red >30m

Call History:
- Full table: Type (direction icon), Patient (matched from leads), Phone, Duration, Outcome, Agent, Recording (play/pause), Time
- Search + All/Inbound/Outbound/Missed filter
- Recording playback via native <audio>

Patients:
- New page with table: Patient (avatar+name+age), Contact, Type, Gender, Status, Actions
- Search + status filter
- Call + View Details actions
- Added patients to DataProvider + transforms + queries
- Route /patients added, sidebar nav updated for cc-agent + executive

Supervisor Dashboard:
- KPI cards: Total Calls, Inbound, Outbound, Missed
- Performance metrics: Avg Response Time, Callback Time, Conversion %
- Agent performance table with per-agent stats
- Missed Call Queue
- AI Assistant section
- Day/Week/Month filter

Reports:
- ECharts bar chart: Call Volume Trend (7-day, Inbound vs Outbound)
- ECharts donut chart: Call Outcomes (Booked, Follow-up, Info, Missed)
- KPI cards with trend indicators (+/-%)
- Route /reports, sidebar Analytics → /reports

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:26:13 +05:30

12 KiB

Data Pages — Table Views, Dashboard, Reports

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: Build all missing data presentation pages using Untitled UI Table component and Apache ECharts. Transform card-based views into proper sortable/filterable tables. Add supervisor dashboard with KPIs and reports with charts.

Architecture: All data comes from the platform via the DataProvider (already wired). Pages use the Untitled UI Table and TableCard components for consistent table presentation. Charts use echarts-for-react. Each page is a separate route — no shared state beyond DataProvider.

Tech Stack: React 19, Untitled UI Table (src/components/application/table/table.tsx), Apache ECharts (echarts-for-react), Jotai, existing DataProvider + apiClient pattern

Deployed at: https://engage.srv1477139.hstgr.cloud Sidecar: https://engage-api.srv1477139.hstgr.cloud Platform: https://fortytwo-dev.srv1477139.hstgr.cloud


Important Context

Untitled UI Table API

import { Table, TableCard } from '@/components/application/table/table';
import { TableBody } from 'react-aria-components';

<TableCard.Root size="sm">
  <TableCard.Header title="Worklist" badge={count} description="..." contentTrailing={<Button>...</Button>} />
  <Table>
    <Table.Header>
      <Table.Head label="PATIENT" />
      <Table.Head label="PHONE" />
    </Table.Header>
    <Table.Body items={data}>
      {(item) => (
        <Table.Row id={item.id}>
          <Table.Cell>{item.name}</Table.Cell>
          <Table.Cell>{item.phone}</Table.Cell>
        </Table.Row>
      )}
    </Table.Body>
  </Table>
</TableCard.Root>

Data Sources (all from DataProvider)

  • leads — Lead[] with contactName, contactPhone, status, source, aiSummary, etc.
  • calls — Call[] with direction, callStatus, durationSeconds, agentName, disposition, startedAt
  • campaigns — Campaign[] with metrics (impressions, clicks, converted, budget)
  • followUps — FollowUp[] with type, status, scheduledAt, priority
  • leadActivities — LeadActivity[] with activityType, summary, occurredAt
  • ads — Ad[] linked to campaigns

Existing Pages (routes in main.tsx)

  • / — RoleRouter (redirects based on role)
  • /leads — AllLeadsPage
  • /campaigns — CampaignsPage
  • /campaigns/:id — CampaignDetailPage
  • /outreach — OutreachPage
  • /follow-ups — FollowUpsPage
  • /call-history — CallHistoryPage
  • /call-desk — CallDeskPage (2-panel with worklist + AI)
  • /team-dashboard — TeamDashboardPage
  • /patient/:id — Patient360Page

Sidebar Navigation (by role)

admin: Team Dashboard, Campaigns, Analytics, Integrations, Settings cc-agent: Call Desk, Follow-ups, Call History executive: Lead Workspace, All Leads, Campaigns, Outreach, Analytics

API Pattern

// All data fetched silently via DataProvider on mount
const { leads, calls, followUps, campaigns, leadActivities, loading } = useData();
// For sidecar-specific data:
const worklist = apiClient.get<WorklistData>('/api/worklist');

Platform Field Mapping (SDK → Platform)

  • Lead: leadSource→source, leadStatus→status, firstContactedAt→firstContacted, lastContactedAt→lastContacted
  • Call: callDirection→direction, durationSeconds→durationSec
  • Campaign: campaignType→typeCustom, campaignStatus→status, impressionCount→impressions
  • FollowUp: followUpType→typeCustom, followUpStatus→status
  • Appointment: appointmentStatus→status, durationMinutes→durationMin

Deploy Pattern

# Build frontend
cd helix-engage
VITE_API_URL=https://engage-api.srv1477139.hstgr.cloud \
VITE_SIP_URI=sip:523590@blr-pub-rtc4.ozonetel.com \
VITE_SIP_PASSWORD=Test123$ \
VITE_SIP_WS_SERVER=wss://blr-pub-rtc4.ozonetel.com:444 \
npm run build

# Upload to VPS
scp -r -i /Users/satyasumansaridae/Downloads/fortytwoai_hostinger \
  dist/* root@148.230.67.184:/opt/fortytwo/helix-engage-frontend/

# Build + push sidecar (if sidecar changes)
cd helix-engage-server && npm run build
docker build --platform linux/amd64 -t 043728036361.dkr.ecr.ap-south-1.amazonaws.com/fortytwo-eap/helix-engage-sidecar:alpha .
docker save 043728036361.dkr.ecr.ap-south-1.amazonaws.com/fortytwo-eap/helix-engage-sidecar:alpha | \
  ssh -i /Users/satyasumansaridae/Downloads/fortytwoai_hostinger root@148.230.67.184 "docker load"
ssh -i /Users/satyasumansaridae/Downloads/fortytwoai_hostinger root@148.230.67.184 \
  "cd /opt/fortytwo && docker compose up -d --force-recreate sidecar"

Task 1: Worklist Table Page

Files:

  • Modify: src/pages/call-desk.tsx — keep the 2-panel layout but upgrade worklist to table
  • Modify: src/components/call-desk/worklist-panel.tsx — replace card list with Table component

The call desk's left panel worklist should use the Table component. Columns:

  • Priority (color badge: HIGH/MEDIUM/LOW/URGENT)
  • Patient name + age (e.g. "Priya Sharma · 1h ago")
  • Phone
  • Direction (icon: inbound/outbound)
  • Type (Missed Call / Callback / Follow-up / Lead)
  • Reason (truncated summary)
  • SLA timer (computed: time since created, color-coded green/amber/red)
  • Task State (PENDING/ATTEMPTED/SCHEDULED)
  • Actions (Call button + dismiss)

Filter tabs: All Tasks | Missed Calls | Callbacks | Follow-ups (with counts) Filter toggle: All / Inbound / Outbound Search: by patient name or phone

Data source: useWorklist() hook (sidecar /api/worklist)

  • Step 1: Rewrite worklist-panel.tsx using Table + TableCard components
  • Step 2: Add filter tabs and search
  • Step 3: Add SLA timer computation (minutes since created, color thresholds: <15m green, <30m amber, >30m red)
  • Step 4: Type check and verify
  • Step 5: Commit

Task 2: Call History Table Page

Files:

  • Rewrite: src/pages/call-history.tsx
  • Modify: src/lib/queries.ts — add CALLS query if not already fetching all fields

Full call history table. Columns:

  • Type (inbound/outbound icon)
  • Patient (matched lead name or "Unknown")
  • Phone
  • Duration (formatted: 5m 12s)
  • Outcome (disposition badge: Appointment Booked, Follow-up Scheduled, Info Provided, Missed, No Answer)
  • Agent
  • Recording (Play button — uses recordingUrl from webhook data)
  • Time (formatted datetime)
  • Actions (View Details link)

Features:

  • Search by patient name or phone
  • Filter dropdown: All Calls / Inbound / Outbound / Missed
  • Sort by time (default: newest first)

Data source: useData().calls from DataProvider

  • Step 1: Rewrite call-history.tsx with Table component
  • Step 2: Add search + filter dropdown
  • Step 3: Add recording playback (native <audio> element in a popover or inline)
  • Step 4: Type check and verify
  • Step 5: Commit

Task 3: Patients Listing Page

Files:

  • Create: src/pages/patients.tsx
  • Modify: src/lib/queries.ts — add PATIENTS_QUERY to DataProvider if not fetched
  • Modify: src/providers/data-provider.tsx — fetch patients
  • Modify: src/main.tsx — add /patients route

Patient table. Columns:

  • Patient (name + age/gender)
  • Contact (phone + email)
  • Location (from address field if available)
  • Last Visit (from appointments — most recent completed)
  • Next Appt (from appointments — next scheduled)
  • Status (active/inactive badge)
  • Actions (Call button + View Details link to /patient/:id)

Features:

  • Search by name or phone
  • Filter by status (active/inactive)
  • "Add Patient" button (opens modal or navigates to form)

Data source: Need to add patients to DataProvider. Query: { patients(first: 50) { edges { node { id name fullName phones emails dateOfBirth gender patientType } } } }

  • Step 1: Add patients to DataProvider + queries + transforms
  • Step 2: Create patients.tsx page with Table
  • Step 3: Add search + filter
  • Step 4: Add route to main.tsx and sidebar nav
  • Step 5: Type check and verify
  • Step 6: Commit

Task 4: Supervisor Dashboard

Files:

  • Rewrite: src/pages/team-dashboard.tsx

This is the admin/supervisor view. Sections:

4a. KPI Cards (top row)

  • Total Calls (count from calls array)
  • Inbound (filtered count)
  • Outbound (filtered count)
  • Missed (filtered count)

4b. Performance Metrics (second row)

  • Avg Lead Response Time (computed from lead firstContacted - createdAt)
  • Missed Callback Time (avg time since missed calls)
  • Call → Appointment % (calls with disposition APPOINTMENT_BOOKED / total)
  • Lead → Appointment % (leads with status APPOINTMENT_SET or CONVERTED / total)

4c. Agent Performance Table Columns: Agent, Calls (In/Out/Missed), Avg Handle Time, Conversion %, Active/Idle

Data: Aggregate calls by agentName, compute per-agent metrics

4d. Missed Call Queue List of recent missed calls with phone, age, priority

4e. Supervisor AI Assistant Reuse existing AiChatPanel with supervisor-specific quick prompts:

  • "Which agents have the highest conversions?"
  • "How many leads are pending contact?"
  • "Top missed callback risks?"

Data source: useData().calls, useData().leads, computed aggregations

  • Step 1: Build KPI card component (reusable)
  • Step 2: Build agent performance table
  • Step 3: Build missed call queue section
  • Step 4: Add AI assistant section
  • Step 5: Wire Day/Week/Month filter (client-side date filtering)
  • Step 6: Type check and verify
  • Step 7: Commit

Task 5: Reports Page

Files:

  • Create: src/pages/reports.tsx
  • Modify: src/main.tsx — add /reports route (or reuse /analytics)

Charts page using Apache ECharts.

5a. KPI Cards (top row)

  • Total Calls (with +X% trend vs previous period)
  • Inbound
  • Outbound
  • Conversion %

5b. Call Volume Trend (bar chart)

  • X axis: days of week (Mon-Sun) or last 7/30 days
  • Y axis: call count
  • Two series: Inbound (gray) + Outbound (blue)
  • Use echarts-for-react with bar chart type

5c. Call Outcomes (donut chart)

  • Segments: Booked, Follow-up, Info Only, Missed
  • Computed from call dispositions
  • Center label: total count

Data source: useData().calls aggregated by date and disposition

ECharts pattern:

import ReactECharts from 'echarts-for-react';

const option = {
  xAxis: { type: 'category', data: ['Mon', 'Tue', ...] },
  yAxis: { type: 'value' },
  series: [
    { name: 'Inbound', type: 'bar', data: [...] },
    { name: 'Outbound', type: 'bar', data: [...] },
  ],
};

<ReactECharts option={option} style={{ height: 400 }} />
  • Step 1: Build KPI cards with trend indicators
  • Step 2: Build Call Volume Trend bar chart
  • Step 3: Build Call Outcomes donut chart
  • Step 4: Wire date range filter
  • Step 5: Add route to main.tsx and sidebar nav
  • Step 6: Type check and verify
  • Step 7: Commit

Task 6: Live Call Monitoring (Supervisor)

Files:

  • Create: src/components/dashboard/live-calls-panel.tsx
  • Modify: src/pages/team-dashboard.tsx — add live calls section

This requires real-time data from Ozonetel. Two approaches:

Option A: Polling — hit Ozonetel's agent status API every 10 seconds Option B: WebSocket — if Ozonetel exposes real-time WebSocket feeds

For MVP, use polling via the sidecar:

  • New sidecar endpoint: GET /api/agents/live — queries Ozonetel for current agent states
  • Returns: [{ agentId, name, status, currentCall: { phone, duration, direction } }]

The live calls panel shows:

  • Agent name + phone number + Inbound/Outbound badge
  • Call duration (live timer)
  • Whisper button (joins call silently — needs Ozonetel conference API)
  • Barge-in button (joins call audibly — needs Ozonetel conference API)

NOTE: Whisper/Barge-in require Ozonetel's conference/monitor APIs which may have the same auth issue as the dial API. Research needed.

  • Step 1: Research Ozonetel live agent status API
  • Step 2: Create sidecar endpoint GET /api/agents/live
  • Step 3: Build live-calls-panel.tsx with polling
  • Step 4: Add to supervisor dashboard
  • Step 5: Research whisper/barge-in APIs
  • Step 6: Implement whisper/barge-in buttons (if API available)
  • Step 7: Commit

Task 7: Deploy and Verify

  • Step 1: Build frontend with production env vars
  • Step 2: Upload to VPS
  • Step 3: Rebuild sidecar if changed, push to VPS
  • Step 4: Test all pages as each role (admin, cc-agent, executive)
  • Step 5: Commit all changes