diff --git a/client/src/components/ClearanceSummaryCard.jsx b/client/src/components/ClearanceSummaryCard.jsx new file mode 100644 index 0000000..708cfcf --- /dev/null +++ b/client/src/components/ClearanceSummaryCard.jsx @@ -0,0 +1,126 @@ +import { useEffect, useState } from 'react' +import { ShieldCheck, ShieldAlert, ShieldX, Clock, AlertTriangle, Plus } from 'lucide-react' +import axios from 'axios' + +const STATUS_CONFIG = { + pass: { icon: ShieldCheck, color: 'var(--success)', label: 'Clear', bg: 'rgba(52,199,89,0.1)' }, + expiring_soon: { icon: Clock, color: 'var(--warning)', label: 'Expiring Soon', bg: 'rgba(255,159,10,0.1)' }, + expired: { icon: ShieldX, color: 'var(--danger)', label: 'Expired', bg: 'rgba(255,59,48,0.1)' }, + missing: { icon: ShieldAlert, color: 'var(--text-muted)', label: 'Missing', bg: 'var(--bg-primary)' }, +} + +const GROUP_LABELS = { hip: 'Hips', elbow: 'Elbows', heart: 'Heart', eye: 'Eyes' } + +function ClearanceChip({ group, status, record }) { + const cfg = STATUS_CONFIG[status] || STATUS_CONFIG.missing + const Icon = cfg.icon + const tip = record + ? `OFA #${record.ofa_number || '-'} - ${record.ofa_result || record.result || ''}` + : 'No record on file' + return ( +
+ +
+
+ {GROUP_LABELS[group]} +
+
+ {cfg.label} +
+
+
+ ) +} + +export default function ClearanceSummaryCard({ dogId, onAddRecord }) { + const [data, setData] = useState(null) + const [error, setError] = useState(null) + + useEffect(() => { + axios.get(`/api/health/dog/${dogId}/clearance-summary`) + .then(r => setData(r.data)) + .catch(() => setError(true)) + }, [dogId]) + + if (error || !data) return null + + const { summary, grca_eligible, age_eligible, chic_number } = data + const hasMissing = Object.values(summary).some(s => s.status === 'missing') + const hasExpiring = Object.values(summary).some(s => s.status === 'expiring_soon') + + return ( +
+ {/* Header row */} +
+

+ OFA Clearances +

+
+ {grca_eligible && ( + GRCA Eligible + )} + {!age_eligible && ( + Under 24mo + )} + {chic_number && ( + CHIC #{chic_number} + )} +
+
+ + {/* Clearance chips */} +
+ {Object.entries(summary).map(([group, { status, record }]) => ( + + ))} +
+ + {/* Expiry warning */} + {hasExpiring && ( +
+ + One or more clearances expire within 90 days. Schedule re-testing. +
+ )} + + {/* CTA */} + {(hasMissing || onAddRecord) && ( + + )} +
+ ) +}