import { useEffect, useState } from 'react'; import { Button, Card, CardBody, Col, Container, Row, Table } from 'react-bootstrap'; import PageBreadcrumb from '@/components/PageBreadcrumb'; import { api } from '@/lib/api'; export default function ReportsPage() { const [patients, setPatients] = useState([]); const [utilization, setUtilization] = useState([]); const [productivity, setProductivity] = useState({ sessionsRun: 0, attendance: 0, possibleAttendance: 0, reassignments: [] }); const [error, setError] = useState(''); useEffect(() => { Promise.all([ api('/api/reports/patients'), api('/api/reports/utilization'), api('/api/reports/productivity'), ]).then(([a, b, c]) => { setPatients(a.items || []); setUtilization(b.items || []); setProductivity(c); }).catch((err) => setError(err.message)); }, []); const download = (type) => { fetch(`/api/reports/export?type=${type}`, { credentials: 'include' }) .then((res) => res.blob()) .then((blob) => { const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = `${type}-report.csv`; link.click(); URL.revokeObjectURL(url); }) .catch((err) => setError(err.message)); }; return ( {error ?
{error}
: null}
Patient progress
{patients.map((item) => ( ))} {!patients.length ? : null}
PatientCohortPRTFirst sessionCompletedAssignedAttendance
{item.name}
{item.diseaseType}
{item.cohort?.name || '—'} {item.prt ? `${item.prt.firstName} ${item.prt.lastName}` : '—'} {item.firstSession || '—'} {item.completed} {item.assigned} {item.completion}
No confirmed patients.
Utilization
{utilization.map((item) => ( ))}
PRTCohortsIdleCancelled
{item.name} {item.used}/{item.max} {item.idle} {item.cancelled}
Productivity

Sessions run: {productivity.sessionsRun}

Attendance: {productivity.attendance}/{productivity.possibleAttendance}

Recent reassignments
{(productivity.reassignments || []).length ? (
    {productivity.reassignments.map((item) => (
  • {item.date}: {item.cohort} {item.from} → {item.to || 'open'} ({item.reason})
  • ))}
) :

None yet.

}
); }