import type { LucideIcon } from 'lucide-react'; import { AlertCircle, CalendarDays, ClipboardList, FlaskConical, Link2, Stethoscope, UserCog, Users, } from 'lucide-react'; import type { Organization } from '@/types/organization'; import { canEditStaff, canViewAppointmentsTab, canViewCases, canViewStaff, canViewTasks, canViewTreatment, hasPermission, type OrgTypeName, } from '@/components/shared/permissions'; import type { TodaySummaryWidgets, TodayWidgetKey } from '@/types/today'; export type KpiCardColor = 'blue' | 'yellow' | 'green' | 'red' | 'purple' | 'default'; export interface TodayKpiDefinition { key: TodayWidgetKey; titleKey: string; icon: LucideIcon; color: KpiCardColor; orgTypes: OrgTypeName[]; href: string; isVisible: (org: Organization | null) => boolean; formatValue: (widgets: TodaySummaryWidgets) => string | null; formatSubtitle?: (widgets: TodaySummaryWidgets) => string | null; } function countWidget( widgets: TodaySummaryWidgets, key: TodayWidgetKey, ): number | null { const value = widgets[key]; if (!value || !('count' in value)) return null; return value.count; } function canManageOrganizations(org: Organization | null): boolean { if (!org) return false; if (org.isOwner) return true; return hasPermission(org, 'TAB_ORGANIZATIONS_EDIT'); } function canViewPatients(org: Organization | null): boolean { if (!org) return false; return ( hasPermission(org, 'TAB_PATIENTS_READ') || hasPermission(org, 'TAB_PATIENTS_EDIT') ); } export const TODAY_KPI_DEFINITIONS: TodayKpiDefinition[] = [ { key: 'appointmentsToday', titleKey: 'widgetAppointmentsToday', icon: CalendarDays, color: 'blue', orgTypes: ['CLINIC'], href: '/appointments', isVisible: (org) => canViewAppointmentsTab(org), formatValue: (widgets) => { const count = countWidget(widgets, 'appointmentsToday'); return count === null ? null : String(count); }, }, { key: 'patientsToday', titleKey: 'widgetPatientsToday', icon: Users, color: 'green', orgTypes: ['CLINIC'], href: '/patients', isVisible: (org) => canViewPatients(org) || canViewAppointmentsTab(org), formatValue: (widgets) => { const count = countWidget(widgets, 'patientsToday'); return count === null ? null : String(count); }, }, { key: 'treatmentsToday', titleKey: 'widgetTreatmentsToday', icon: Stethoscope, color: 'purple', orgTypes: ['CLINIC'], href: '/treatment', isVisible: (org) => canViewTreatment(org), formatValue: (widgets) => { const count = countWidget(widgets, 'treatmentsToday'); return count === null ? null : String(count); }, }, { key: 'labCasesPendingSend', titleKey: 'widgetLabCasesPendingSend', icon: FlaskConical, color: 'red', orgTypes: ['CLINIC'], href: '/treatment', isVisible: (org) => canViewTreatment(org), formatValue: (widgets) => { const count = countWidget(widgets, 'labCasesPendingSend'); return count === null ? null : String(count); }, }, { key: 'providersWithoutWorkingHours', titleKey: 'widgetProvidersWithoutWorkingHours', icon: UserCog, color: 'yellow', orgTypes: ['CLINIC'], href: '/staff', isVisible: (org) => canViewStaff(org), formatValue: (widgets) => { const count = countWidget(widgets, 'providersWithoutWorkingHours'); return count === null ? null : String(count); }, }, { key: 'casesReceivedToday', titleKey: 'widgetCasesReceivedToday', icon: FlaskConical, color: 'blue', orgTypes: ['LAB'], href: '/cases', isVisible: (org) => canViewCases(org), formatValue: (widgets) => { const count = countWidget(widgets, 'casesReceivedToday'); return count === null ? null : String(count); }, }, { key: 'casesInProgress', titleKey: 'widgetCasesInProgress', icon: FlaskConical, color: 'yellow', orgTypes: ['LAB'], href: '/cases', isVisible: (org) => canViewCases(org), formatValue: (widgets) => { const count = countWidget(widgets, 'casesInProgress'); return count === null ? null : String(count); }, }, { key: 'tasksInProgress', titleKey: 'widgetTasksInProgress', icon: ClipboardList, color: 'yellow', orgTypes: ['LAB'], href: '/tasks', isVisible: (org) => canViewTasks(org), formatValue: (widgets) => { const count = countWidget(widgets, 'tasksInProgress'); return count === null ? null : String(count); }, }, { key: 'importantTasks', titleKey: 'widgetImportantTasks', icon: AlertCircle, color: 'red', orgTypes: ['LAB'], href: '/tasks', isVisible: (org) => canViewTasks(org), formatValue: (widgets) => { const count = countWidget(widgets, 'importantTasks'); return count === null ? null : String(count); }, }, { key: 'pendingConnections', titleKey: 'widgetPendingConnections', icon: Link2, color: 'yellow', orgTypes: ['CLINIC', 'LAB'], href: '/organizations', isVisible: (org) => canManageOrganizations(org), formatValue: (widgets) => { const count = countWidget(widgets, 'pendingConnections'); return count === null ? null : String(count); }, }, { key: 'pendingStaffInvites', titleKey: 'widgetPendingStaffInvites', icon: UserCog, color: 'purple', orgTypes: ['CLINIC', 'LAB'], href: '/staff', isVisible: (org) => canEditStaff(org) || Boolean(org?.isOwner), formatValue: (widgets) => { const count = countWidget(widgets, 'pendingStaffInvites'); return count === null ? null : String(count); }, }, ]; export function getEligibleTodayKpis(org: Organization | null): TodayKpiDefinition[] { if (!org) return []; return TODAY_KPI_DEFINITIONS.filter((definition) => { if (!definition.orgTypes.includes(org.type)) return false; return definition.isVisible(org); }); } export function getVisibleTodayKpis( org: Organization | null, widgets: TodaySummaryWidgets, ): TodayKpiDefinition[] { return getEligibleTodayKpis(org).filter( (definition) => definition.formatValue(widgets) !== null, ); }