- New EngagementProfileHeader: avatar (photo/initials fallback), name, jobTitle, department, mailto link, last-active relative/absolute label - New EngagementProfileMetricGrid: 2x2 grid of Hours/Billable/Days/Meetings cards - Page updated: imports Header+MetricGrid, placeholder div removed, real components mounted - D-01/D-22 guard rails: EngagementUserRow.tsx and data endpoint untouched
51 lines
2 KiB
TypeScript
51 lines
2 KiB
TypeScript
'use client';
|
||
|
||
/* EngagementProfileMetricGrid — phase 08 (D-11, D-12, D-13).
|
||
* Purpose: 2×2 grid of 4 hero metric cards (Hours worked / Billable hours /
|
||
* Days worked / Meetings attended). Values always render as numbers —
|
||
* never '—' (D-13). Layout mirrors Phase 3 dashboard KPI grid. */
|
||
|
||
import { Card, CardContent } from '@/components/ui/card';
|
||
|
||
export interface EngagementProfileMetricGridProps {
|
||
hoursWorked: number; // already period-scoped by caller
|
||
billableHours: number;
|
||
daysWorked: number;
|
||
meetingsAttended: number;
|
||
}
|
||
|
||
export function EngagementProfileMetricGrid({
|
||
hoursWorked,
|
||
billableHours,
|
||
daysWorked,
|
||
meetingsAttended,
|
||
}: EngagementProfileMetricGridProps) {
|
||
return (
|
||
<div className="grid grid-cols-2 gap-3">
|
||
<Card className="py-0 shadow-none">
|
||
<CardContent className="px-4 py-4">
|
||
<p className="text-2xl font-semibold text-foreground leading-none">{hoursWorked.toFixed(1)}h</p>
|
||
<p className="text-xs text-muted-foreground mt-2">Hours worked</p>
|
||
</CardContent>
|
||
</Card>
|
||
<Card className="py-0 shadow-none">
|
||
<CardContent className="px-4 py-4">
|
||
<p className="text-2xl font-semibold text-foreground leading-none">{billableHours.toFixed(1)}h</p>
|
||
<p className="text-xs text-muted-foreground mt-2">Billable hours</p>
|
||
</CardContent>
|
||
</Card>
|
||
<Card className="py-0 shadow-none">
|
||
<CardContent className="px-4 py-4">
|
||
<p className="text-2xl font-semibold text-foreground leading-none">{daysWorked.toString()}</p>
|
||
<p className="text-xs text-muted-foreground mt-2">Days worked</p>
|
||
</CardContent>
|
||
</Card>
|
||
<Card className="py-0 shadow-none">
|
||
<CardContent className="px-4 py-4">
|
||
<p className="text-2xl font-semibold text-foreground leading-none">{meetingsAttended.toString()}</p>
|
||
<p className="text-xs text-muted-foreground mt-2">Meetings attended</p>
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
);
|
||
}
|