first commit

This commit is contained in:
2026-07-17 13:02:59 -04:00
commit 8ffd50b7cc
15 changed files with 13518 additions and 0 deletions
+148
View File
@@ -0,0 +1,148 @@
import React from 'react'
// ── Stat card data ────────────────────────────────────────────────────────────
const STATS = [
{
id: 'pre-travel',
icon: '♥',
value: '24',
label: 'In Pre-Travel',
delta: '+3',
deltaType: 'up',
accent: 'violet',
},
{
id: 'in-transit',
icon: '◷',
value: '8',
label: 'In Transit',
delta: null,
accent: 'blue',
},
{
id: 'at-risk',
icon: '⌛',
value: '11',
label: 'At Risk',
delta: '+2',
deltaType: 'up',
accent: 'amber',
},
{
id: 'post-travel',
icon: '✓',
value: '47',
label: 'In Post-Travel',
delta: '+12%',
deltaType: 'up',
accent: 'teal',
},
]
// ── Placeholder patient journey rows ─────────────────────────────────────────
const PATIENTS = [
{ id: 'P-001', name: 'Maria Santos', departure: '2026-07-14', arrival: '2026-07-19', status: 'in-transit', email: 'name@example.com' },
{ id: 'P-002', name: 'James Owusu', departure: '2026-07-12', arrival: '2026-07-20', status: 'at-risk', email: 'name@example.com' },
{ id: 'P-003', name: 'Anya Kowalski', departure: '2026-07-12', arrival: '2026-07-21', status: 'in-transit', email: 'name@example.com' },
{ id: 'P-004', name: 'Carlos Mendoza', departure: '2026-07-19', arrival: '2026-07-22', status: 'at-risk', email: 'name@example.com' },
{ id: 'P-005', name: 'Priya Nair', departure: '2026-07-02', arrival: '2026-07-13', status: 'post-travel', email: 'name@example.com' },
{ id: 'P-006', name: 'David Okonkwo', departure: '2026-07-19', arrival: '2026-07-24', status: 'pre-travel', email: 'name@example.com' },
]
const STATUS_META = {
'in-transit': { label: 'In Transit', className: 'status-in-transit' },
'at-risk': { label: 'At Risk', className: 'status-at-risk' },
'post-travel': { label: 'Post-Travel', className: 'status-post-travel' },
'pre-travel': { label: 'Pre-Travel', className: 'status-pre-travel' },
}
function getGreeting() {
const h = new Date().getHours()
if (h < 12) return 'Good morning'
if (h < 17) return 'Good afternoon'
return 'Good evening'
}
/**
* Dashboard — main content viewport for CTM Concierge.
* Shows real-time stat cards and a patient journey table.
*/
export default function Dashboard() {
const today = new Date().toLocaleDateString('en-US', {
weekday: 'long', year: 'numeric', month: 'long', day: 'numeric',
})
return (
<section className="dashboard" aria-label="Dashboard">
{/* ── Header ─────────────────────────────────────────────────────────── */}
<header className="dashboard-header">
<p className="dashboard-greeting">{getGreeting()}</p>
<h1 className="dashboard-title">Patient Trip Overview</h1>
<p className="dashboard-subtitle">{today}</p>
</header>
{/* ── Stat Cards ─────────────────────────────────────────────────────── */}
<div className="stat-grid" role="list" aria-label="Today's statistics">
{STATS.map((stat) => (
<article
key={stat.id}
id={`stat-${stat.id}`}
className={`stat-card accent-${stat.accent}`}
role="listitem"
>
<span className="stat-card-icon" aria-hidden="true">{stat.icon}</span>
<div className="stat-card-value">{stat.value}</div>
<div className="stat-card-label">{stat.label}</div>
{stat.delta && (
<span className={`stat-card-delta delta-${stat.deltaType}`} aria-label={`Change: ${stat.delta}`}>
{stat.delta}
</span>
)}
</article>
))}
</div>
{/* ── Patient Journey Table ───────────────────────────────────────────── */}
<div className="section-heading">
<h2 className="section-title">Live Patient Board</h2>
<span className="section-action" role="button" tabIndex={0}>View all </span>
</div>
<div className="journey-panel">
<table className="journey-table" aria-label="Live patient journey board">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Departure</th>
<th scope="col">Arrival</th>
<th scope="col">Status</th>
</tr>
</thead>
<tbody>
{PATIENTS.map((p) => {
const meta = STATUS_META[p.status]
return (
<tr key={p.id} id={`patient-row-${p.id}`}>
<td>{p.id}</td>
<td className="patient-name">{p.name}</td>
<td>{p.email}</td>
<td>{p.departure}</td>
<td>{p.arrival}</td>
<td>
<span className={`status-pill ${meta.className}`}>
{meta.label}
</span>
</td>
</tr>
)
})}
</tbody>
</table>
</div>
</section>
)
}