Add Today dashboard foundation with permission-aware KPI summary API.
Replace hardcoded Today cards with a backend summary endpoint and composable frontend widgets filtered by org type and tab permissions. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
51
frontend/src/components/today/TodayKpiGrid.tsx
Normal file
51
frontend/src/components/today/TodayKpiGrid.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
'use client';
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useAuth } from '@/lib/hooks/useAuth';
|
||||
import { KpiCard } from '@/components/today/KpiCard';
|
||||
import { getEligibleTodayKpis, getVisibleTodayKpis } from '@/components/today/widget-registry';
|
||||
import type { TodaySummaryWidgets } from '@/types/today';
|
||||
|
||||
interface TodayKpiGridProps {
|
||||
widgets: TodaySummaryWidgets;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
export function TodayKpiGrid({ widgets, loading = false }: TodayKpiGridProps) {
|
||||
const t = useTranslations('today');
|
||||
const { currentOrganization } = useAuth();
|
||||
const definitions = loading
|
||||
? getEligibleTodayKpis(currentOrganization)
|
||||
: getVisibleTodayKpis(currentOrganization, widgets);
|
||||
|
||||
if (!loading && definitions.length === 0) {
|
||||
return (
|
||||
<p className="text-sm text-text-muted">{t('noWidgets')}</p>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4">
|
||||
{definitions.map((definition) => {
|
||||
const value = definition.formatValue(widgets) ?? '—';
|
||||
const subtitleKey = definition.formatSubtitle?.(widgets);
|
||||
const subtitle =
|
||||
subtitleKey === 'unlimited'
|
||||
? t('seatsUnlimited')
|
||||
: definition.formatSubtitle?.(widgets);
|
||||
|
||||
return (
|
||||
<KpiCard
|
||||
key={definition.key}
|
||||
title={t(definition.titleKey)}
|
||||
value={value}
|
||||
subtitle={subtitle}
|
||||
icon={definition.icon}
|
||||
color={definition.color}
|
||||
loading={loading}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user