The soft reset to 77073ba inadvertently staged deletions of all phase 2
and 3 artifacts. This commit restores them from their source commits so
subsequent task commits build on the complete prior-phase foundation:
- components/mobile/{BottomNav,HeaderBar,KpiCardMobile,MoreDrawer,NeedsAttentionStrip,WorkerStatusRow}
- app/mobile/layout.tsx, dashboard/page.tsx, analyzer/page.tsx
- app/api/mobile/dashboard/route.ts
- All .planning/** files from phases 01-04
- CLAUDE.md, app/layout.tsx, app/styles/brand.css, public/manifest.json
39 lines
1.3 KiB
TypeScript
39 lines
1.3 KiB
TypeScript
'use client';
|
||
|
||
/* KpiCardMobile — phase 03 (DASH-01).
|
||
*
|
||
* Phone-sized KPI card for the 2×2 dashboard grid. Renders a label,
|
||
* a large numeric value, and an optional caption. tone="attention"
|
||
* adds a left-edge destructive border for SLA breaches > 0.
|
||
*
|
||
* Pure presentational — no fetch, no state. Parent provides values. */
|
||
|
||
import { Card, CardContent } from '@/components/ui/card';
|
||
import { cn } from '@/lib/utils';
|
||
|
||
export type KpiTone = 'default' | 'attention';
|
||
|
||
interface KpiCardMobileProps {
|
||
label: string;
|
||
value: number | string;
|
||
caption?: string;
|
||
tone?: KpiTone;
|
||
}
|
||
|
||
const TONE_BORDER: Record<KpiTone, string> = {
|
||
default: 'border-l-transparent',
|
||
attention: 'border-l-destructive',
|
||
};
|
||
|
||
export function KpiCardMobile({ label, value, caption, tone = 'default' }: KpiCardMobileProps) {
|
||
const display = typeof value === 'number' ? value.toLocaleString() : value;
|
||
return (
|
||
<Card className={cn('h-full border-l-2', TONE_BORDER[tone])}>
|
||
<CardContent className="p-4 flex flex-col gap-1">
|
||
<p className="text-[11px] font-semibold text-muted-foreground uppercase tracking-wider">{label}</p>
|
||
<p className="text-3xl font-bold tabular-nums">{display}</p>
|
||
{caption && <p className="text-xs text-muted-foreground">{caption}</p>}
|
||
</CardContent>
|
||
</Card>
|
||
);
|
||
}
|