Add Today action lists and clickable KPI links (Phase 3).

Show upcoming appointments for the rest of today and link each KPI card to its relevant dashboard tab.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-11 00:48:35 +03:30
parent 394aa98314
commit 3f2b332bd3
10 changed files with 203 additions and 5 deletions

View File

@@ -30,6 +30,7 @@ export interface TodayKpiDefinition {
icon: LucideIcon;
color: KpiCardColor;
orgTypes: OrgTypeName[];
href: string;
isVisible: (org: Organization | null) => boolean;
formatValue: (widgets: TodaySummaryWidgets) => string | null;
formatSubtitle?: (widgets: TodaySummaryWidgets) => string | null;
@@ -65,6 +66,7 @@ export const TODAY_KPI_DEFINITIONS: TodayKpiDefinition[] = [
icon: CalendarDays,
color: 'blue',
orgTypes: ['CLINIC'],
href: '/appointments',
isVisible: (org) => canAccessAppointmentsSection(org),
formatValue: (widgets) => {
const count = countWidget(widgets, 'appointmentsToday');
@@ -77,6 +79,7 @@ export const TODAY_KPI_DEFINITIONS: TodayKpiDefinition[] = [
icon: Users,
color: 'green',
orgTypes: ['CLINIC'],
href: '/patients',
isVisible: (org) => canViewPatients(org) || canAccessAppointmentsSection(org),
formatValue: (widgets) => {
const count = countWidget(widgets, 'patientsToday');
@@ -89,6 +92,7 @@ export const TODAY_KPI_DEFINITIONS: TodayKpiDefinition[] = [
icon: Stethoscope,
color: 'purple',
orgTypes: ['CLINIC'],
href: '/treatment',
isVisible: (org) => canViewTreatment(org),
formatValue: (widgets) => {
const count = countWidget(widgets, 'treatmentsToday');
@@ -101,6 +105,7 @@ export const TODAY_KPI_DEFINITIONS: TodayKpiDefinition[] = [
icon: ClipboardList,
color: 'yellow',
orgTypes: ['CLINIC'],
href: '/treatment',
isVisible: (org) => canViewTreatment(org),
formatValue: (widgets) => {
const count = countWidget(widgets, 'draftTreatments');
@@ -113,6 +118,7 @@ export const TODAY_KPI_DEFINITIONS: TodayKpiDefinition[] = [
icon: FlaskConical,
color: 'red',
orgTypes: ['CLINIC'],
href: '/treatment',
isVisible: (org) => canViewTreatment(org),
formatValue: (widgets) => {
const count = countWidget(widgets, 'labCasesPendingSend');
@@ -125,6 +131,7 @@ export const TODAY_KPI_DEFINITIONS: TodayKpiDefinition[] = [
icon: FlaskConical,
color: 'blue',
orgTypes: ['LAB'],
href: '/cases',
isVisible: (org) => canViewCases(org),
formatValue: (widgets) => {
const count = countWidget(widgets, 'casesReceivedToday');
@@ -137,6 +144,7 @@ export const TODAY_KPI_DEFINITIONS: TodayKpiDefinition[] = [
icon: ClipboardList,
color: 'yellow',
orgTypes: ['LAB'],
href: '/tasks',
isVisible: (org) => canViewTasks(org),
formatValue: (widgets) => {
const count = countWidget(widgets, 'tasksInProgress');
@@ -149,6 +157,7 @@ export const TODAY_KPI_DEFINITIONS: TodayKpiDefinition[] = [
icon: AlertCircle,
color: 'red',
orgTypes: ['LAB'],
href: '/tasks',
isVisible: (org) => canViewTasks(org),
formatValue: (widgets) => {
const count = countWidget(widgets, 'importantTasks');
@@ -161,6 +170,7 @@ export const TODAY_KPI_DEFINITIONS: TodayKpiDefinition[] = [
icon: Link2,
color: 'yellow',
orgTypes: ['CLINIC', 'LAB'],
href: '/organizations',
isVisible: (org) => canManageOrganizations(org),
formatValue: (widgets) => {
const count = countWidget(widgets, 'pendingConnections');
@@ -173,6 +183,7 @@ export const TODAY_KPI_DEFINITIONS: TodayKpiDefinition[] = [
icon: UserCog,
color: 'default',
orgTypes: ['CLINIC', 'LAB'],
href: '/staff',
isVisible: (org) => canViewStaff(org),
formatValue: (widgets) => {
const seats = widgets.seats;
@@ -192,6 +203,7 @@ export const TODAY_KPI_DEFINITIONS: TodayKpiDefinition[] = [
icon: UserCog,
color: 'purple',
orgTypes: ['CLINIC', 'LAB'],
href: '/staff',
isVisible: (org) => canEditStaff(org) || Boolean(org?.isOwner),
formatValue: (widgets) => {
const count = countWidget(widgets, 'pendingStaffInvites');