# 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
```tsx
import { Table, TableCard } from '@/components/application/table/table';
import { TableBody } from 'react-aria-components';
...} />
{(item) => (
{item.name}{item.phone}
)}
```
### 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
```tsx
// All data fetched silently via DataProvider on mount
const { leads, calls, followUps, campaigns, leadActivities, loading } = useData();
// For sidecar-specific data:
const worklist = apiClient.get('/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
```bash
# 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 `