
3D Extruded Buildings & Urban Footprints
Real-world 3D building extrusions with dynamic sunlight shadows, terrain DEM elevations, and pitch/bearing camera controls.
Biometric vitals monitoring dashboard with multi-day trends, threshold bands, device sync status, 7-day vitals table with risk indicators, clinician alert limits, and quick-entry logging dialog.
Also available for Vue ->$pnpm dlx shadcn@latest add https://uipkge.dev/r/react/vitals-tracker-chart.json$npx shadcn@latest add https://uipkge.dev/r/react/vitals-tracker-chart.json$yarn dlx shadcn@latest add https://uipkge.dev/r/react/vitals-tracker-chart.json$bunx shadcn@latest add https://uipkge.dev/r/react/vitals-tracker-chart.jsonnpx shadcn@latest add @uipkge-react/vitals-tracker-chartInstalls to:components/blocks/Type aliases exported from this item's source. Use these to shape the data you pass in.
DailyVitalLoginterface DailyVitalLog {
id: string
date: string
isToday?: boolean
morningBP: string
morningPulse: number
eveningBP: string
eveningPulse: number
avgBP: string
systolicVal: number
diastolicVal: number
fastingGlucose: number
glucoseStatus: 'optimal' | 'normal' | 'elevated'
spo2: number
riskStatus: 'optimal' | 'normal' | 'elevated'
riskLabel: string
notes?: string
}'use client'
import * as React from 'react'
import {
Activity,
Heart,
TrendingDown,
Minus,
CheckCircle2,
Plus,
Sliders,
Droplets,
Wind,
RefreshCw,
Bell,
ShieldCheck,
Stethoscope,
} from 'lucide-react'
import { cn } from '@/lib/utils'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from '@/components/ui/card'
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@/components/ui/dialog'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Progress } from '@/components/ui/progress'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import { Separator } from '@/components/ui/separator'
import { Switch } from '@/components/ui/switch'
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
import { Textarea } from '@/components/ui/textarea'
interface DailyVitalLog {
id: string
date: string
isToday?: boolean
morningBP: string
morningPulse: number
eveningBP: string
eveningPulse: number
avgBP: string
systolicVal: number
diastolicVal: number
fastingGlucose: number
glucoseStatus: 'optimal' | 'normal' | 'elevated'
spo2: number
riskStatus: 'optimal' | 'normal' | 'elevated'
riskLabel: string
notes?: string
}
const initialLogs: DailyVitalLog[] = [
{
id: 'vital-1',
date: 'Aug 21 (Today)',
isToday: true,
morningBP: '120/76',
morningPulse: 66,
eveningBP: '122/78',
eveningPulse: 68,
avgBP: '121/77',
systolicVal: 121,
diastolicVal: 77,
fastingGlucose: 94,
glucoseStatus: 'optimal',
spo2: 99,
riskStatus: 'optimal',
riskLabel: 'Optimal',
notes: 'Resting morning reading taken pre-breakfast.',
},
{
id: 'vital-2',
date: 'Aug 20',
morningBP: '124/80',
morningPulse: 70,
eveningBP: '122/79',
eveningPulse: 69,
avgBP: '123/80',
systolicVal: 123,
diastolicVal: 80,
fastingGlucose: 94,
glucoseStatus: 'optimal',
spo2: 98,
riskStatus: 'normal',
riskLabel: 'Normal',
},
{
id: 'vital-3',
date: 'Aug 19',
morningBP: '126/82',
morningPulse: 71,
eveningBP: '125/80',
eveningPulse: 70,
avgBP: '126/81',
systolicVal: 126,
diastolicVal: 81,
fastingGlucose: 97,
glucoseStatus: 'normal',
spo2: 99,
riskStatus: 'normal',
riskLabel: 'Normal',
},
{
id: 'vital-4',
date: 'Aug 18',
morningBP: '132/84',
morningPulse: 74,
eveningBP: '130/82',
eveningPulse: 73,
avgBP: '131/83',
systolicVal: 131,
diastolicVal: 83,
fastingGlucose: 101,
glucoseStatus: 'elevated',
spo2: 98,
riskStatus: 'elevated',
riskLabel: 'Elevated',
notes: 'Mild post-work stress reported by patient.',
},
{
id: 'vital-5',
date: 'Aug 17',
morningBP: '128/82',
morningPulse: 72,
eveningBP: '126/80',
eveningPulse: 71,
avgBP: '127/81',
systolicVal: 127,
diastolicVal: 81,
fastingGlucose: 98,
glucoseStatus: 'normal',
spo2: 99,
riskStatus: 'normal',
riskLabel: 'Normal',
},
{
id: 'vital-6',
date: 'Aug 16',
morningBP: '122/78',
morningPulse: 69,
eveningBP: '124/80',
eveningPulse: 70,
avgBP: '123/79',
systolicVal: 123,
diastolicVal: 79,
fastingGlucose: 95,
glucoseStatus: 'optimal',
spo2: 99,
riskStatus: 'optimal',
riskLabel: 'Optimal',
},
{
id: 'vital-7',
date: 'Aug 15',
morningBP: '120/78',
morningPulse: 68,
eveningBP: '121/77',
eveningPulse: 67,
avgBP: '121/78',
systolicVal: 121,
diastolicVal: 78,
fastingGlucose: 96,
glucoseStatus: 'optimal',
spo2: 99,
riskStatus: 'optimal',
riskLabel: 'Optimal',
},
]
const bpHistory = [121, 123, 126, 131, 127, 123, 121]
const hrHistory = [68, 70, 71, 74, 72, 69, 68]
const glucoseHistory = [96, 95, 98, 101, 97, 94, 94]
function getSparkline(history: number[]) {
const min = Math.min(...history)
const max = Math.max(...history)
const range = max - min || 1
const height = 26
const padding = 3
const points = history.map((val, idx) => {
const x = (idx / (history.length - 1)) * 100
const y = height - ((val - min) / range) * (height - padding * 2) - padding
return { x, y }
})
let path = `M ${points[0].x},${points[0].y}`
for (let i = 1; i < points.length; i++) {
const prev = points[i - 1]
const curr = points[i]
const cx = (prev.x + curr.x) / 2
path += ` C ${cx},${prev.y} ${cx},${curr.y} ${curr.x},${curr.y}`
}
const lastPoint = points[points.length - 1]
const area = `${path} L 100,32 L 0,32 Z`
return { path, area, lastPoint }
}
export function VitalsTrackerChart({ className }: { className?: string }) {
const [timeframe, setTimeframe] = React.useState<'7d' | '30d' | '90d'>('7d')
const [isSyncing, setIsSyncing] = React.useState(false)
const [lastSyncText, setLastSyncText] = React.useState('4m ago')
const [isLogDialogOpen, setIsLogDialogOpen] = React.useState(false)
const [showSuccessNotification, setShowSuccessNotification] = React.useState(false)
// Configurable Thresholds State
const [systolicLimit, setSystolicLimit] = React.useState('140')
const [diastolicLimit, setDiastolicLimit] = React.useState('90')
const [hrAlertRange, setHrAlertRange] = React.useState('50-100')
const [glucoseAlertLimit, setGlucoseAlertLimit] = React.useState('130')
const [spo2AlertLimit] = React.useState('95')
// Alert Toggles
const [clinicianSmsAlert, setClinicianSmsAlert] = React.useState(true)
const [ehrAutoSync, setEhrAutoSync] = React.useState(true)
// New Entry Form State
const [formDate, setFormDate] = React.useState('2026-08-21T08:30')
const [formPeriod, setFormPeriod] = React.useState('morning')
const [formSystolic, setFormSystolic] = React.useState('120')
const [formDiastolic, setFormDiastolic] = React.useState('78')
const [formPulse, setFormPulse] = React.useState('68')
const [formGlucose, setFormGlucose] = React.useState('94')
const [formSpo2, setFormSpo2] = React.useState('99')
const [formDevice, setFormDevice] = React.useState('withings')
const [formNotes, setFormNotes] = React.useState('')
const [dailyLogs, setDailyLogs] = React.useState<DailyVitalLog[]>(initialLogs)
const handleSyncRefresh = () => {
setIsSyncing(true)
setTimeout(() => {
setIsSyncing(false)
setLastSyncText('just now')
}, 600)
}
const handleLogSubmit = () => {
const systolic = parseInt(formSystolic, 10) || 120
const diastolic = parseInt(formDiastolic, 10) || 80
const pulse = parseInt(formPulse, 10) || 68
const glucose = parseInt(formGlucose, 10) || 94
const spo2 = parseInt(formSpo2, 10) || 99
let riskStatus: 'optimal' | 'normal' | 'elevated' = 'normal'
let riskLabel = 'Normal'
if (systolic >= 130 || diastolic >= 85 || glucose >= 100) {
riskStatus = 'elevated'
riskLabel = 'Elevated'
} else if (systolic <= 120 && diastolic <= 80 && glucose < 95) {
riskStatus = 'optimal'
riskLabel = 'Optimal'
}
const newLog: DailyVitalLog = {
id: `vital-${Date.now()}`,
date: 'Aug 21 (Manual)',
isToday: true,
morningBP: `${systolic}/${diastolic}`,
morningPulse: pulse,
eveningBP: `${systolic}/${diastolic}`,
eveningPulse: pulse,
avgBP: `${systolic}/${diastolic}`,
systolicVal: systolic,
diastolicVal: diastolic,
fastingGlucose: glucose,
glucoseStatus: glucose < 95 ? 'optimal' : glucose <= 99 ? 'normal' : 'elevated',
spo2,
riskStatus,
riskLabel,
notes: formNotes.trim() || undefined,
}
setDailyLogs([newLog, ...dailyLogs.slice(0, 6)])
setIsLogDialogOpen(false)
setShowSuccessNotification(true)
setTimeout(() => {
setShowSuccessNotification(false)
}, 4000)
}
return (
<div data-slot="vitals-tracker-chart" className={cn('mx-auto w-full max-w-6xl space-y-6', className)}>
{/* Header Section */}
<div className="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div className="space-y-1">
<div className="flex flex-wrap items-center gap-2.5">
<h1 className="text-foreground text-2xl font-bold tracking-tight sm:text-3xl">
Patient Biometrics & Vitals Telemetry
</h1>
<Badge wrap variant="outline" className="gap-1.5 text-xs font-normal">
<span className="bg-success size-1.5 rounded-full" />
<span className="tabular-nums">MRN-84920</span>
</Badge>
</div>
<p className="text-muted-foreground text-sm">
Continuous physiological telemetry stream · Eleanor Vance (DOB: 1984-06-12) · Care Lead: Dr. M. Vance, MD
</p>
</div>
<div className="flex flex-wrap items-center gap-2.5">
{/* Device Sync Telemetry Badge */}
<div className="bg-muted/50 border-border/80 text-card-foreground flex items-center gap-2 rounded-lg border px-3 py-1.5 text-xs shadow-xs">
<span className="relative flex size-2 shrink-0">
<span className="bg-success absolute inline-flex h-full w-full rounded-full opacity-75" />
<span className="bg-success relative inline-flex size-2 rounded-full" />
</span>
<span className="text-muted-foreground">Apple Health / Withings Connected · Last sync</span>
<span className="text-foreground font-medium tabular-nums">{lastSyncText}</span>
<Button
variant="ghost"
size="icon-sm"
className="text-muted-foreground hover:text-foreground size-6 rounded-md p-0"
aria-label="Sync vitals telemetry"
onClick={handleSyncRefresh}
>
<RefreshCw className={cn('size-3.5', isSyncing && 'animate-spin')} />
</Button>
</div>
{/* Timeframe Selector */}
<div className="bg-muted border-border/60 flex items-center rounded-lg border p-0.5 text-xs">
<button
type="button"
className={cn(
'rounded-md px-2.5 py-1 font-medium transition-colors',
timeframe === '7d'
? 'bg-background text-foreground shadow-xs'
: 'text-muted-foreground hover:text-foreground',
)}
onClick={() => setTimeframe('7d')}
>
7 Days
</button>
<button
type="button"
className={cn(
'rounded-md px-2.5 py-1 font-medium transition-colors',
timeframe === '30d'
? 'bg-background text-foreground shadow-xs'
: 'text-muted-foreground hover:text-foreground',
)}
onClick={() => setTimeframe('30d')}
>
30 Days
</button>
<button
type="button"
className={cn(
'rounded-md px-2.5 py-1 font-medium transition-colors',
timeframe === '90d'
? 'bg-background text-foreground shadow-xs'
: 'text-muted-foreground hover:text-foreground',
)}
onClick={() => setTimeframe('90d')}
>
90 Days
</button>
</div>
{/* Log Vitals Entry Dialog */}
<Dialog open={isLogDialogOpen} onOpenChange={setIsLogDialogOpen}>
<DialogTrigger asChild>
<Button size="sm" className="gap-1.5 shadow-xs">
<Plus className="size-4" />
<span>Log Vitals Entry</span>
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-xl">
<DialogHeader>
<DialogTitle>Log Biometric Vitals Entry</DialogTitle>
<DialogDescription>
Record manual cuff, glucometer, or pulse oximeter measurements into the clinical telemetry stream.
</DialogDescription>
</DialogHeader>
<div className="grid grid-cols-1 gap-4 py-2 sm:grid-cols-2">
<div className="space-y-1.5 sm:col-span-2">
<Label htmlFor="vital-timestamp-react" className="text-xs">
Measurement Timestamp
</Label>
<Input
id="vital-timestamp-react"
value={formDate}
onChange={(e) => setFormDate(e.target.value)}
type="datetime-local"
className="h-9 text-xs"
/>
</div>
<div className="space-y-1.5">
<Label htmlFor="vital-period-react" className="text-xs">
Context / Reading Period
</Label>
<Select value={formPeriod} onValueChange={setFormPeriod}>
<SelectTrigger id="vital-period-react" className="h-9 text-xs">
<SelectValue placeholder="Select period" />
</SelectTrigger>
<SelectContent>
<SelectItem value="morning">Morning (Fasting)</SelectItem>
<SelectItem value="midday">Midday (Pre-lunch)</SelectItem>
<SelectItem value="evening">Evening (Post-dinner)</SelectItem>
<SelectItem value="bedtime">Bedtime (Resting)</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-1.5">
<Label htmlFor="vital-device-react" className="text-xs">
Telemetry Source Device
</Label>
<Select value={formDevice} onValueChange={setFormDevice}>
<SelectTrigger id="vital-device-react" className="h-9 text-xs">
<SelectValue placeholder="Select device" />
</SelectTrigger>
<SelectContent>
<SelectItem value="withings">Withings BPM Core</SelectItem>
<SelectItem value="apple-watch">Apple Watch Series 9</SelectItem>
<SelectItem value="omron">Omron Platinum Cuff</SelectItem>
<SelectItem value="dexcom">Dexcom G7 CGM</SelectItem>
<SelectItem value="manual">Manual Clinical Station</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-1.5">
<Label htmlFor="systolic-input-react" className="text-xs">
Systolic Pressure (mmHg)
</Label>
<Input
id="systolic-input-react"
value={formSystolic}
onChange={(e) => setFormSystolic(e.target.value)}
type="number"
placeholder="120"
className="h-9 text-xs tabular-nums"
/>
</div>
<div className="space-y-1.5">
<Label htmlFor="diastolic-input-react" className="text-xs">
Diastolic Pressure (mmHg)
</Label>
<Input
id="diastolic-input-react"
value={formDiastolic}
onChange={(e) => setFormDiastolic(e.target.value)}
type="number"
placeholder="80"
className="h-9 text-xs tabular-nums"
/>
</div>
<div className="space-y-1.5">
<Label htmlFor="pulse-input-react" className="text-xs">
Resting Heart Rate (bpm)
</Label>
<Input
id="pulse-input-react"
value={formPulse}
onChange={(e) => setFormPulse(e.target.value)}
type="number"
placeholder="68"
className="h-9 text-xs tabular-nums"
/>
</div>
<div className="space-y-1.5">
<Label htmlFor="glucose-input-react" className="text-xs">
Blood Glucose (mg/dL)
</Label>
<Input
id="glucose-input-react"
value={formGlucose}
onChange={(e) => setFormGlucose(e.target.value)}
type="number"
placeholder="94"
className="h-9 text-xs tabular-nums"
/>
</div>
<div className="space-y-1.5 sm:col-span-2">
<Label htmlFor="spo2-input-react" className="text-xs">
Blood Oxygen SpO2 (%)
</Label>
<Input
id="spo2-input-react"
value={formSpo2}
onChange={(e) => setFormSpo2(e.target.value)}
type="number"
placeholder="99"
className="h-9 text-xs tabular-nums"
/>
</div>
<div className="space-y-1.5 sm:col-span-2">
<Label htmlFor="vital-notes-react" className="text-xs">
Clinical Notes & Symptoms (Optional)
</Label>
<Textarea
id="vital-notes-react"
value={formNotes}
onValueChange={setFormNotes}
placeholder="e.g. Patient rested seated for 5 minutes prior to measurement. No palpitations or dyspnea."
rows={2}
className="text-xs"
/>
</div>
</div>
<DialogFooter className="gap-2 sm:gap-0">
<Button variant="outline" size="sm" onClick={() => setIsLogDialogOpen(false)}>
Cancel
</Button>
<Button size="sm" onClick={handleLogSubmit}>
Save Reading
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
</div>
{/* Success Toast Notification */}
{showSuccessNotification && (
<div
className="border-success/30 bg-success/10 text-foreground dark:text-foreground flex items-center justify-between gap-x-2 rounded-lg border p-3 text-xs shadow-xs"
role="status"
>
<div className="flex items-center gap-2">
<CheckCircle2 className="text-success size-4 shrink-0" />
<span className="font-medium">Vitals telemetry entry successfully appended to EHR clinical chart.</span>
</div>
<Button
aria-label="Dismiss notification"
variant="ghost"
size="icon-sm"
className="text-success size-6"
onClick={() => setShowSuccessNotification(false)}
>
<span className="text-xs">✕</span>
</Button>
</div>
)}
{/* 4 Primary Vitals Overview Cards */}
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
{/* 1. Blood Pressure */}
<Card className="flex flex-col justify-between">
<CardHeader className="pb-2">
<div className="flex items-center justify-between gap-2">
<div className="flex min-w-0 items-center gap-2.5">
<div
className="bg-muted text-muted-foreground border-border flex size-8 shrink-0 items-center justify-center rounded-lg border shadow-xs"
aria-hidden="true"
>
<Activity className="text-success size-4" />
</div>
<CardTitle className="truncate text-sm font-medium">Blood Pressure</CardTitle>
</div>
<Badge wrap variant="success" className="shrink-0 text-xs">
Normal
</Badge>
</div>
</CardHeader>
<CardContent className="space-y-3 pt-1">
<div>
<div className="mb-1 flex flex-wrap items-baseline justify-between gap-x-2 gap-y-0.5">
<div className="flex items-baseline gap-1.5">
<span className="text-foreground text-3xl font-bold tracking-tight tabular-nums">122/78</span>
<span className="text-muted-foreground text-xs">mmHg</span>
</div>
<span className="text-muted-foreground text-xs tabular-nums">MAP 92 mmHg</span>
</div>
{/* Mini Sparkline for BP Trend */}
<div className="h-7 w-full overflow-hidden pt-1" aria-label="7-day systolic blood pressure trend">
<svg className="h-full w-full overflow-visible" viewBox="0 0 100 28" preserveAspectRatio="none">
<defs>
<linearGradient id="grad-bp-react" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor="var(--color-emerald-500, #10b981)" stopOpacity="0.25" />
<stop offset="100%" stopColor="var(--color-emerald-500, #10b981)" stopOpacity="0.0" />
</linearGradient>
</defs>
<path d={getSparkline(bpHistory).area} fill="url(#grad-bp-react)" />
<path
d={getSparkline(bpHistory).path}
fill="none"
stroke="var(--color-emerald-500, #10b981)"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<circle
cx={getSparkline(bpHistory).lastPoint.x}
cy={getSparkline(bpHistory).lastPoint.y}
r="2.5"
className="fill-success"
/>
</svg>
</div>
</div>
<div className="border-border/60 border-t pt-2.5 text-xs">
<div className="flex items-center justify-between gap-x-2">
<span className="text-muted-foreground">7-Day Mean:</span>
<span className="text-foreground font-medium tabular-nums">124/80 mmHg</span>
</div>
<p className="text-muted-foreground mt-0.5 text-xs">Target < 120/80 mmHg · Controlled</p>
</div>
</CardContent>
</Card>
{/* 2. Resting Heart Rate */}
<Card className="flex flex-col justify-between">
<CardHeader className="pb-2">
<div className="flex items-center justify-between gap-2">
<div className="flex min-w-0 items-center gap-2.5">
<div
className="bg-muted text-muted-foreground border-border flex size-8 shrink-0 items-center justify-center rounded-lg border shadow-xs"
aria-hidden="true"
>
<Heart className="text-destructive size-4" />
</div>
<CardTitle className="truncate text-sm font-medium">Resting Heart Rate</CardTitle>
</div>
<Badge wrap variant="success" className="shrink-0 text-xs">
Healthy
</Badge>
</div>
</CardHeader>
<CardContent className="space-y-3 pt-1">
<div>
<div className="mb-1 flex flex-wrap items-baseline justify-between gap-x-2 gap-y-0.5">
<div className="flex items-baseline gap-1.5">
<span className="text-foreground text-3xl font-bold tracking-tight tabular-nums">68</span>
<span className="text-muted-foreground text-xs">bpm</span>
</div>
<div className="text-success flex items-center gap-1 text-xs font-medium tabular-nums">
<TrendingDown className="size-3" />
<span>-2 bpm</span>
</div>
</div>
{/* Mini Sparkline for HR Trend */}
<div className="h-7 w-full overflow-hidden pt-1" aria-label="7-day resting heart rate trend">
<svg className="h-full w-full overflow-visible" viewBox="0 0 100 28" preserveAspectRatio="none">
<defs>
<linearGradient id="grad-hr-react" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor="var(--color-rose-500, #f43f5e)" stopOpacity="0.25" />
<stop offset="100%" stopColor="var(--color-rose-500, #f43f5e)" stopOpacity="0.0" />
</linearGradient>
</defs>
<path d={getSparkline(hrHistory).area} fill="url(#grad-hr-react)" />
<path
d={getSparkline(hrHistory).path}
fill="none"
stroke="var(--color-rose-500, #f43f5e)"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<circle
cx={getSparkline(hrHistory).lastPoint.x}
cy={getSparkline(hrHistory).lastPoint.y}
r="2.5"
className="fill-destructive"
/>
</svg>
</div>
</div>
<div className="border-border/60 border-t pt-2.5 text-xs">
<div className="flex items-center justify-between gap-x-2">
<span className="text-muted-foreground">Normal Range:</span>
<span className="text-foreground font-medium tabular-nums">60 – 100 bpm</span>
</div>
<p className="text-muted-foreground mt-0.5 text-xs">Sinus Rhythm · HRV 58 ms</p>
</div>
</CardContent>
</Card>
{/* 3. Blood Glucose / Fasting */}
<Card className="flex flex-col justify-between">
<CardHeader className="pb-2">
<div className="flex items-center justify-between gap-2">
<div className="flex min-w-0 items-center gap-2.5">
<div
className="bg-muted text-muted-foreground border-border flex size-8 shrink-0 items-center justify-center rounded-lg border shadow-xs"
aria-hidden="true"
>
<Droplets className="text-info size-4" />
</div>
<CardTitle className="truncate text-sm font-medium">Blood Glucose</CardTitle>
</div>
<Badge wrap variant="success" className="shrink-0 text-xs">
Fasting < 100
</Badge>
</div>
</CardHeader>
<CardContent className="space-y-3 pt-1">
<div>
<div className="mb-1 flex flex-wrap items-baseline justify-between gap-x-2 gap-y-0.5">
<div className="flex items-baseline gap-1.5">
<span className="text-foreground text-3xl font-bold tracking-tight tabular-nums">94</span>
<span className="text-muted-foreground text-xs">mg/dL</span>
</div>
<div className="text-muted-foreground flex items-center gap-1 text-xs font-medium tabular-nums">
<Minus className="size-3" />
<span>Stable</span>
</div>
</div>
{/* Mini Sparkline for Glucose Trend */}
<div className="h-7 w-full overflow-hidden pt-1" aria-label="7-day blood glucose trend">
<svg className="h-full w-full overflow-visible" viewBox="0 0 100 28" preserveAspectRatio="none">
<defs>
<linearGradient id="grad-glu-react" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor="var(--color-sky-500, #0ea5e9)" stopOpacity="0.25" />
<stop offset="100%" stopColor="var(--color-sky-500, #0ea5e9)" stopOpacity="0.0" />
</linearGradient>
</defs>
<path d={getSparkline(glucoseHistory).area} fill="url(#grad-glu-react)" />
<path
d={getSparkline(glucoseHistory).path}
fill="none"
stroke="var(--color-sky-500, #0ea5e9)"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<circle
cx={getSparkline(glucoseHistory).lastPoint.x}
cy={getSparkline(glucoseHistory).lastPoint.y}
r="2.5"
className="fill-info"
/>
</svg>
</div>
</div>
<div className="border-border/60 border-t pt-2.5 text-xs">
<div className="flex items-center justify-between gap-x-2">
<span className="text-muted-foreground">Fasting Window:</span>
<span className="text-foreground font-medium tabular-nums">12 hrs</span>
</div>
<p className="text-muted-foreground mt-0.5 text-xs">Estimated HbA1c: 5.4%</p>
</div>
</CardContent>
</Card>
{/* 4. Blood Oxygen SpO2 */}
<Card className="flex flex-col justify-between">
<CardHeader className="pb-2">
<div className="flex items-center justify-between gap-2">
<div className="flex min-w-0 items-center gap-2.5">
<div
className="bg-muted text-muted-foreground border-border flex size-8 shrink-0 items-center justify-center rounded-lg border shadow-xs"
aria-hidden="true"
>
<Wind className="size-4 text-teal-500" />
</div>
<CardTitle className="truncate text-sm font-medium">Blood Oxygen SpO2</CardTitle>
</div>
<Badge wrap variant="success" className="shrink-0 text-xs">
≥ 95% Normal
</Badge>
</div>
</CardHeader>
<CardContent className="space-y-3 pt-1">
<div>
<div className="mb-1 flex flex-wrap items-baseline justify-between gap-x-2 gap-y-0.5">
<div className="flex items-baseline gap-1.5">
<span className="text-foreground text-3xl font-bold tracking-tight tabular-nums">99%</span>
<span className="text-muted-foreground text-xs">SpO2</span>
</div>
<span className="text-success text-xs font-medium">0 drops detected</span>
</div>
<Progress value={99} className="h-2 [&_[data-slot=progress-indicator]]:bg-teal-500" />
<div className="mt-1.5 flex items-center justify-between gap-x-2 text-xs">
<span className="text-muted-foreground">Pulse Oximeter</span>
<span className="text-muted-foreground tabular-nums">Target ≥ 95%</span>
</div>
</div>
<div className="border-border/60 border-t pt-2.5 text-xs">
<div className="flex items-center justify-between gap-x-2">
<span className="text-muted-foreground">Sleep O2 Baseline:</span>
<span className="text-foreground font-medium tabular-nums">98.4%</span>
</div>
<p className="text-muted-foreground mt-0.5 text-xs">Continuous Plethysmography</p>
</div>
</CardContent>
</Card>
</div>
{/* 7-Day Vitals Trend Grid & Daily Telemetry Table */}
<Card>
<CardHeader>
<div className="flex flex-col gap-1 sm:flex-row sm:items-center sm:justify-between">
<div>
<CardTitle>7-Day Vitals Trend & Daily Telemetry Logs</CardTitle>
<CardDescription>
Comprehensive morning & evening multi-parameter biometrics with systolic range markers and risk
stratification.
</CardDescription>
</div>
<div className="flex items-center gap-2">
<Badge wrap variant="outline" className="w-fit text-xs font-normal tabular-nums">
{dailyLogs.length} readings logged
</Badge>
</div>
</div>
</CardHeader>
<CardContent className="p-0 sm:p-6 sm:pt-0">
<div className="overflow-x-auto">
<Table>
<TableHeader>
<TableRow>
<TableHead className="min-w-[120px]">Date</TableHead>
<TableHead className="min-w-[150px]">Morning Reading</TableHead>
<TableHead className="min-w-[150px]">Evening Reading</TableHead>
<TableHead className="min-w-[110px]">Daily Mean BP</TableHead>
<TableHead className="min-w-[120px]">Fasting Glucose</TableHead>
<TableHead className="min-w-[80px]">SpO2</TableHead>
<TableHead className="min-w-[160px]">Systolic Band Indicator</TableHead>
<TableHead className="text-right">Risk Status</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{dailyLogs.map((log) => (
<TableRow key={log.id} className={log.isToday ? 'bg-muted/25 font-medium' : undefined}>
<TableCell className="text-foreground text-xs whitespace-nowrap">
<div className="flex items-center gap-1.5">
<span className="tabular-nums">{log.date}</span>
{log.isToday && (
<Badge wrap variant="secondary" className="h-4.5 px-1.5 text-xs font-normal">
Now
</Badge>
)}
</div>
</TableCell>
<TableCell className="text-xs whitespace-nowrap">
<span className="text-foreground font-medium tabular-nums">{log.morningBP}</span>
<span className="text-muted-foreground text-xs"> mmHg · </span>
<span className="text-muted-foreground tabular-nums">{log.morningPulse} bpm</span>
</TableCell>
<TableCell className="text-xs whitespace-nowrap">
<span className="text-foreground font-medium tabular-nums">{log.eveningBP}</span>
<span className="text-muted-foreground text-xs"> mmHg · </span>
<span className="text-muted-foreground tabular-nums">{log.eveningPulse} bpm</span>
</TableCell>
<TableCell className="text-foreground text-xs font-semibold whitespace-nowrap tabular-nums">
{log.avgBP}
<span className="text-muted-foreground text-xs font-normal"> mmHg</span>
</TableCell>
<TableCell className="text-xs whitespace-nowrap">
<span className="text-foreground font-medium tabular-nums">{log.fastingGlucose}</span>
<span className="text-muted-foreground text-xs"> mg/dL</span>
</TableCell>
<TableCell className="text-foreground text-xs font-medium whitespace-nowrap tabular-nums">
{log.spo2}%
</TableCell>
<TableCell className="text-xs">
{/* Visual Horizontal Range Pill */}
<div className="w-36 space-y-1">
<div className="bg-muted border-border/70 relative h-3 w-full overflow-hidden rounded-full border">
{/* Normal Zone (110 - 129) */}
<div className="bg-success/20 absolute inset-y-0 right-[50%] left-[16%]" />
{/* Elevated Zone (130 - 139) */}
<div className="bg-warning/25 absolute inset-y-0 right-[33%] left-[50%]" />
{/* High Zone (>= 140) */}
<div className="bg-destructive/25 absolute inset-y-0 right-0 left-[67%]" />
{/* Reading Dot Marker */}
<div
className={cn(
'absolute top-1/2 size-2 -translate-y-1/2 rounded-full shadow-xs',
log.systolicVal < 130
? 'bg-success ring-success/30 ring-2'
: log.systolicVal < 140
? 'bg-warning ring-warning/30 ring-2'
: 'bg-destructive ring-destructive/30 ring-2',
)}
style={{
left: `${Math.min(96, Math.max(4, ((log.systolicVal - 100) / 60) * 100))}%`,
}}
/>
</div>
<div className="text-muted-foreground flex justify-between text-xs tabular-nums">
<span>100</span>
<span className="text-success font-medium">120</span>
<span>140+</span>
</div>
</div>
</TableCell>
<TableCell className="text-right">
<Badge
wrap
variant={
log.riskStatus === 'optimal' ? 'success' : log.riskStatus === 'normal' ? 'success' : 'warning'
}
className="text-xs capitalize"
>
{log.riskLabel}
</Badge>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
</CardContent>
</Card>
{/* Threshold & Alert Limits Card */}
<div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
<Card>
<CardHeader>
<div className="flex items-center justify-between gap-x-2">
<div className="flex items-center gap-2">
<Sliders className="text-primary size-4" />
<CardTitle>Configurable Clinical Thresholds</CardTitle>
</div>
<Badge wrap variant="outline" className="text-xs font-normal">
AHA / ACC Standards
</Badge>
</div>
<CardDescription>
Custom warning & critical breach boundaries tailored to this patient's clinical care plan.
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
<div className="space-y-1.5">
<Label className="text-xs">Systolic Alert Limit</Label>
<Select value={systolicLimit} onValueChange={setSystolicLimit}>
<SelectTrigger className="h-9 text-xs">
<SelectValue placeholder="Select limit" />
</SelectTrigger>
<SelectContent>
<SelectItem value="130">> 130 mmHg (Elevated)</SelectItem>
<SelectItem value="140">> 140 mmHg (Stage 2 Alert)</SelectItem>
<SelectItem value="160">> 160 mmHg (Critical Crisis)</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-1.5">
<Label className="text-xs">Diastolic Alert Limit</Label>
<Select value={diastolicLimit} onValueChange={setDiastolicLimit}>
<SelectTrigger className="h-9 text-xs">
<SelectValue placeholder="Select limit" />
</SelectTrigger>
<SelectContent>
<SelectItem value="85">> 85 mmHg (Elevated)</SelectItem>
<SelectItem value="90">> 90 mmHg (Stage 2 Alert)</SelectItem>
<SelectItem value="100">> 100 mmHg (Crisis)</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-1.5">
<Label className="text-xs">Heart Rate Alert Range</Label>
<Select value={hrAlertRange} onValueChange={setHrAlertRange}>
<SelectTrigger className="h-9 text-xs">
<SelectValue placeholder="Select range" />
</SelectTrigger>
<SelectContent>
<SelectItem value="50-100">< 50 or > 100 bpm</SelectItem>
<SelectItem value="55-110">< 55 or > 110 bpm</SelectItem>
<SelectItem value="45-120">< 45 or > 120 bpm (Wide)</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-1.5">
<Label className="text-xs">Fasting Glucose Warning</Label>
<Select value={glucoseAlertLimit} onValueChange={setGlucoseAlertLimit}>
<SelectTrigger className="h-9 text-xs">
<SelectValue placeholder="Select limit" />
</SelectTrigger>
<SelectContent>
<SelectItem value="120">> 120 mg/dL (Pre-diabetic)</SelectItem>
<SelectItem value="130">> 130 mg/dL (Clinical Alert)</SelectItem>
<SelectItem value="150">> 150 mg/dL (High Trigger)</SelectItem>
</SelectContent>
</Select>
</div>
</div>
<Separator />
<div className="border-border bg-muted/40 flex items-center justify-between gap-x-2 rounded-lg border p-3">
<div className="space-y-0.5">
<p className="text-foreground text-xs font-medium">Oxygen Desaturation Limit</p>
<p className="text-muted-foreground text-xs">Triggers hypoxemia alert if SpO2 drops below bound.</p>
</div>
<Badge wrap variant="outline" className="text-xs font-medium tabular-nums">
< {spo2AlertLimit}% SpO2
</Badge>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<div className="flex items-center justify-between gap-x-2">
<div className="flex items-center gap-2">
<Bell className="text-primary size-4" />
<CardTitle>Automated Clinical Alert Protocol</CardTitle>
</div>
<Badge wrap variant="success" className="gap-1 text-xs">
<ShieldCheck className="size-3" />
<span>Active Sentinel</span>
</Badge>
</div>
<CardDescription>
Instant escalation rules and clinician notification triggers for threshold violations.
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-start justify-between gap-4">
<div className="space-y-0.5">
<Label className="text-foreground text-xs font-medium">Clinician Urgent SMS Alert</Label>
<p className="text-muted-foreground text-xs leading-relaxed">
Immediately dispatch SMS alert to on-call cardiologist when 2 consecutive readings exceed threshold.
</p>
</div>
<Switch
checked={clinicianSmsAlert}
onCheckedChange={setClinicianSmsAlert}
aria-label="Toggle clinician SMS alert"
/>
</div>
<Separator />
<div className="flex items-start justify-between gap-4">
<div className="space-y-0.5">
<Label className="text-foreground text-xs font-medium">EHR Auto-Sync (FHIR R4 Stream)</Label>
<p className="text-muted-foreground text-xs leading-relaxed">
Stream verified biometric readings directly to patient's electronic health record chart.
</p>
</div>
<Switch checked={ehrAutoSync} onCheckedChange={setEhrAutoSync} aria-label="Toggle EHR auto sync" />
</div>
<Separator />
<div className="bg-muted/40 border-border space-y-2 rounded-lg border p-3 text-xs">
<div className="flex items-center justify-between gap-x-2">
<div className="flex items-center gap-2">
<Stethoscope className="text-primary size-3.5" />
<span className="text-foreground font-semibold">On-Call Clinical Lead:</span>
</div>
<span className="text-foreground font-medium">Dr. Sarah Chen, MD (Cardiology)</span>
</div>
<div className="text-muted-foreground flex items-center justify-between gap-x-2">
<span>Pager: #4920 · Priority SLA:</span>
<span className="text-success font-medium">< 15 min triage</span>
</div>
</div>
</CardContent>
</Card>
</div>
</div>
)
}
Raw manifest:https://uipkge.dev/r/react/vitals-tracker-chart.json