Some functionality added to dashboard gadgets.
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
||||
canViewAppointmentsTab,
|
||||
canViewCases,
|
||||
canViewLabCasesOrTasks,
|
||||
canViewMyAppointmentsWeekChart,
|
||||
canViewTasks,
|
||||
canViewTreatment,
|
||||
} from '@/components/shared/permissions';
|
||||
@@ -15,15 +16,17 @@ import { ChartCard } from '@/components/today/ChartCard';
|
||||
import { TodayAreaChart } from '@/components/today/TodayAreaChart';
|
||||
import { TodayBarChart } from '@/components/today/TodayBarChart';
|
||||
import {
|
||||
formatTodayChartDayLabel,
|
||||
mapWeekChartBuckets,
|
||||
useTodayDayLabelFormatter,
|
||||
} from '@/components/today/chart-day-labels';
|
||||
import { TodayDashboardGrid } from '@/components/today/TodayDashboardGrid';
|
||||
import { TodayDonutChart } from '@/components/today/TodayDonutChart';
|
||||
import { TodayDonutChart, TodayDonutChartLegend } from '@/components/today/TodayDonutChart';
|
||||
import { TodayHorizontalBarChart } from '@/components/today/TodayHorizontalBarChart';
|
||||
import { TodayCaseCompletionKpiCard } from '@/components/today/TodayCaseCompletionKpiCard';
|
||||
import { TodayStackedBarChart } from '@/components/today/TodayStackedBarChart';
|
||||
import {
|
||||
mapLabTaskActivityChartData,
|
||||
TodayLabTaskActivityChart,
|
||||
} from '@/components/today/TodayLabTaskActivityChart';
|
||||
import { TodaySubscriptionKpiCard } from '@/components/today/TodaySubscriptionKpiCard';
|
||||
import { TodayUpcomingAppointments } from '@/components/today/TodayUpcomingAppointments';
|
||||
import {
|
||||
@@ -36,7 +39,7 @@ import {
|
||||
type TodayDashboardCell,
|
||||
} from '@/components/today/today-dashboard-layout';
|
||||
import { getEligibleTodayKpis, getVisibleTodayKpis } from '@/components/today/widget-registry';
|
||||
import { prosthesisTypeColor, prosthesisTypeSwatchStyle } from '@/components/ui/treatment/prosthesisTypeDisplay';
|
||||
import { prosthesisTypeColor } from '@/components/ui/treatment/prosthesisTypeDisplay';
|
||||
import { treatmentTypeColor } from '@/components/ui/treatment/treatmentTypeDisplay';
|
||||
import type {
|
||||
TodaySubscriptionSnapshot,
|
||||
@@ -71,7 +74,9 @@ export function TodayDashboard({
|
||||
const isOwner = Boolean(currentOrganization?.isOwner);
|
||||
|
||||
const showUpcoming =
|
||||
orgType === 'CLINIC' && currentOrganization && canViewTreatment(currentOrganization);
|
||||
orgType === 'CLINIC' &&
|
||||
currentOrganization &&
|
||||
canViewMyAppointmentsWeekChart(currentOrganization);
|
||||
|
||||
const showCharts = useMemo(() => {
|
||||
if (!orgType || !currentOrganization) return false;
|
||||
@@ -109,6 +114,10 @@ export function TodayDashboard({
|
||||
showCharts,
|
||||
orgType,
|
||||
isOwner,
|
||||
showMyAppointmentsWeekChart: Boolean(
|
||||
currentOrganization &&
|
||||
canViewMyAppointmentsWeekChart(currentOrganization),
|
||||
),
|
||||
charts,
|
||||
});
|
||||
}
|
||||
@@ -171,12 +180,18 @@ function buildSkeletonCells(options: {
|
||||
showCharts: boolean;
|
||||
orgType?: 'CLINIC' | 'LAB';
|
||||
isOwner: boolean;
|
||||
showMyAppointmentsWeekChart: boolean;
|
||||
charts: TodaySummaryCharts;
|
||||
}): TodayDashboardCell[] {
|
||||
const cells: TodayDashboardCell[] = [];
|
||||
|
||||
if (options.showCharts) {
|
||||
const chartCount = countVisibleCharts(options.charts, options.orgType, options.isOwner);
|
||||
const chartCount = countVisibleCharts(
|
||||
options.charts,
|
||||
options.orgType,
|
||||
options.isOwner,
|
||||
options.showMyAppointmentsWeekChart,
|
||||
);
|
||||
for (let index = 0; index < Math.min(chartCount, 4); index += 1) {
|
||||
cells.push({
|
||||
id: `chart-skeleton-${index}`,
|
||||
@@ -250,8 +265,6 @@ function buildDashboardCells(options: {
|
||||
currentOrganization: ReturnType<typeof useAuth>['currentOrganization'];
|
||||
}): TodayDashboardCell[] {
|
||||
const cells: TodayDashboardCell[] = [];
|
||||
const formatDayLabel = (code: string) =>
|
||||
formatTodayChartDayLabel(code, options.dayLabelFormatter);
|
||||
|
||||
if (options.showCharts) {
|
||||
cells.push(
|
||||
@@ -260,7 +273,10 @@ function buildDashboardCells(options: {
|
||||
charts: options.charts,
|
||||
orgType: options.orgType,
|
||||
isOwner: options.isOwner,
|
||||
formatDayLabel,
|
||||
showMyAppointmentsWeekChart: Boolean(
|
||||
options.currentOrganization &&
|
||||
canViewMyAppointmentsWeekChart(options.currentOrganization),
|
||||
),
|
||||
dayLabelFormatter: options.dayLabelFormatter,
|
||||
}),
|
||||
);
|
||||
@@ -328,13 +344,13 @@ function buildChartCells(options: {
|
||||
charts: TodaySummaryCharts;
|
||||
orgType?: 'CLINIC' | 'LAB';
|
||||
isOwner: boolean;
|
||||
formatDayLabel: (code: string) => string;
|
||||
showMyAppointmentsWeekChart: boolean;
|
||||
dayLabelFormatter: ReturnType<typeof useTodayDayLabelFormatter>;
|
||||
}): TodayDashboardCell[] {
|
||||
const { t, charts, orgType, isOwner } = options;
|
||||
const { t, charts, orgType, isOwner, showMyAppointmentsWeekChart } = options;
|
||||
const cells: TodayDashboardCell[] = [];
|
||||
const tallChart = TODAY_DASHBOARD_LAYOUT.chart;
|
||||
const mediumChart = TODAY_DASHBOARD_LAYOUT.chartMedium;
|
||||
const areaChart = TODAY_DASHBOARD_LAYOUT.chartArea;
|
||||
const barChart = TODAY_DASHBOARD_LAYOUT.chartBar;
|
||||
|
||||
const appointmentsWeekAllData = mapWeekChartBuckets(
|
||||
charts.appointmentsWeekAll ?? [],
|
||||
@@ -348,11 +364,12 @@ function buildChartCells(options: {
|
||||
charts.labTaskActivityWeek ?? [],
|
||||
options.dayLabelFormatter,
|
||||
);
|
||||
const labTaskActivityChartData = mapLabTaskActivityChartData(labTaskActivityData);
|
||||
|
||||
if (orgType === 'CLINIC' && charts.appointmentsWeekAll !== undefined) {
|
||||
cells.push({
|
||||
id: 'chart-appointments-week-all',
|
||||
layout: tallChart,
|
||||
layout: areaChart,
|
||||
content: (
|
||||
<ChartCard
|
||||
title={t('chartAppointmentsWeekAllTitle')}
|
||||
@@ -366,10 +383,14 @@ function buildChartCells(options: {
|
||||
});
|
||||
}
|
||||
|
||||
if (orgType === 'CLINIC' && charts.appointmentsWeekMine !== undefined) {
|
||||
if (
|
||||
orgType === 'CLINIC' &&
|
||||
showMyAppointmentsWeekChart &&
|
||||
charts.appointmentsWeekMine !== undefined
|
||||
) {
|
||||
cells.push({
|
||||
id: 'chart-appointments-week-mine',
|
||||
layout: tallChart,
|
||||
layout: areaChart,
|
||||
content: (
|
||||
<ChartCard
|
||||
title={t('chartAppointmentsWeekMineTitle')}
|
||||
@@ -386,7 +407,7 @@ function buildChartCells(options: {
|
||||
if (orgType === 'LAB' && charts.labTaskActivityWeek !== undefined) {
|
||||
cells.push({
|
||||
id: 'chart-lab-task-activity',
|
||||
layout: tallChart,
|
||||
layout: areaChart,
|
||||
content: (
|
||||
<ChartCard
|
||||
title={t('chartLabTaskActivityTitle')}
|
||||
@@ -396,38 +417,10 @@ function buildChartCells(options: {
|
||||
)}
|
||||
emptyMessage={t('chartEmpty')}
|
||||
>
|
||||
<TodayStackedBarChart
|
||||
data={labTaskActivityData}
|
||||
<TodayLabTaskActivityChart
|
||||
data={labTaskActivityChartData}
|
||||
completedLabel={t('chartLabTaskCompletedLegend')}
|
||||
receivedLabel={t('chartLabTaskReceivedLegend')}
|
||||
formatDayLabel={options.formatDayLabel}
|
||||
/>
|
||||
</ChartCard>
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
const prosthesisData = charts.inProgressTasksByProsthesis ?? [];
|
||||
if (orgType === 'LAB' && charts.inProgressTasksByProsthesis !== undefined) {
|
||||
cells.push({
|
||||
id: 'chart-prosthesis-mix',
|
||||
layout: tallChart,
|
||||
content: (
|
||||
<ChartCard
|
||||
title={t('chartProsthesisMixTitle')}
|
||||
subtitle={t('chartProsthesisMixSubtitle')}
|
||||
isEmpty={prosthesisData.length === 0}
|
||||
emptyMessage={t('chartEmpty')}
|
||||
>
|
||||
<TodayDonutChart
|
||||
data={prosthesisData}
|
||||
labelForCode={(code) =>
|
||||
prosthesisData.find((row) => row.code === code)?.label ?? code
|
||||
}
|
||||
colorForCode={(code, index) => prosthesisTypeColor(code, index)}
|
||||
swatchStyleForCode={(code, index) => prosthesisTypeSwatchStyle(code, index)}
|
||||
variant="pie"
|
||||
sideLegend
|
||||
/>
|
||||
</ChartCard>
|
||||
),
|
||||
@@ -442,7 +435,7 @@ function buildChartCells(options: {
|
||||
) {
|
||||
cells.push({
|
||||
id: 'chart-efficiency-report',
|
||||
layout: tallChart,
|
||||
layout: areaChart,
|
||||
content: (
|
||||
<ChartCard
|
||||
title={t('chartEfficiencyReportTitle')}
|
||||
@@ -453,14 +446,22 @@ function buildChartCells(options: {
|
||||
}
|
||||
isEmpty={efficiencyReportData.every((row) => row.count === 0)}
|
||||
emptyMessage={t('chartEmpty')}
|
||||
sidePanelLayout
|
||||
chartPanel={
|
||||
<TodayDonutChart
|
||||
data={efficiencyReportData}
|
||||
labelForCode={(code) =>
|
||||
efficiencyReportData.find((row) => row.code === code)?.label ?? code
|
||||
}
|
||||
variant="pie"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<TodayDonutChart
|
||||
<TodayDonutChartLegend
|
||||
data={efficiencyReportData}
|
||||
labelForCode={(code) =>
|
||||
efficiencyReportData.find((row) => row.code === code)?.label ?? code
|
||||
}
|
||||
variant="pie"
|
||||
sideLegend
|
||||
/>
|
||||
</ChartCard>
|
||||
),
|
||||
@@ -471,7 +472,7 @@ function buildChartCells(options: {
|
||||
if (orgType === 'CLINIC' && charts.appointmentsByProvider !== undefined) {
|
||||
cells.push({
|
||||
id: 'chart-appointments-by-provider',
|
||||
layout: mediumChart,
|
||||
layout: barChart,
|
||||
content: (
|
||||
<ChartCard
|
||||
title={t('chartAppointmentsByProviderTitle')}
|
||||
@@ -489,7 +490,7 @@ function buildChartCells(options: {
|
||||
if (orgType === 'CLINIC' && charts.treatmentMixWeek !== undefined) {
|
||||
cells.push({
|
||||
id: 'chart-treatment-mix',
|
||||
layout: mediumChart,
|
||||
layout: barChart,
|
||||
content: (
|
||||
<ChartCard
|
||||
title={t('chartTreatmentMixTitle')}
|
||||
@@ -506,19 +507,22 @@ function buildChartCells(options: {
|
||||
});
|
||||
}
|
||||
|
||||
const tasksData = charts.tasksByWorkflowStep ?? [];
|
||||
if (orgType === 'LAB' && charts.tasksByWorkflowStep !== undefined) {
|
||||
const tasksByProsthesisData = charts.tasksByProsthesis ?? [];
|
||||
if (orgType === 'LAB' && charts.tasksByProsthesis !== undefined) {
|
||||
cells.push({
|
||||
id: 'chart-tasks-by-step',
|
||||
layout: mediumChart,
|
||||
id: 'chart-tasks-by-prosthesis',
|
||||
layout: barChart,
|
||||
content: (
|
||||
<ChartCard
|
||||
title={t('chartTasksByStepTitle')}
|
||||
subtitle={t('chartTasksByStepSubtitle')}
|
||||
isEmpty={tasksData.length === 0}
|
||||
title={t('chartTasksByProsthesisTitle')}
|
||||
subtitle={t('chartTasksByProsthesisSubtitle')}
|
||||
isEmpty={tasksByProsthesisData.length === 0}
|
||||
emptyMessage={t('chartEmpty')}
|
||||
>
|
||||
<TodayBarChart data={tasksData} />
|
||||
<TodayBarChart
|
||||
data={tasksByProsthesisData}
|
||||
colorForCode={(code, index) => prosthesisTypeColor(code, index)}
|
||||
/>
|
||||
</ChartCard>
|
||||
),
|
||||
});
|
||||
@@ -531,18 +535,19 @@ function countVisibleCharts(
|
||||
charts: TodaySummaryCharts,
|
||||
orgType?: 'CLINIC' | 'LAB',
|
||||
isOwner = false,
|
||||
showMyAppointmentsWeekChart = false,
|
||||
): number {
|
||||
let count = 0;
|
||||
if (orgType === 'CLINIC') {
|
||||
count += charts.appointmentsWeekAll !== undefined ? 1 : 0;
|
||||
count += charts.appointmentsWeekMine !== undefined ? 1 : 0;
|
||||
count +=
|
||||
showMyAppointmentsWeekChart && charts.appointmentsWeekMine !== undefined ? 1 : 0;
|
||||
count += charts.appointmentsByProvider !== undefined ? 1 : 0;
|
||||
count += charts.treatmentMixWeek !== undefined ? 1 : 0;
|
||||
}
|
||||
if (orgType === 'LAB') {
|
||||
count += charts.labTaskActivityWeek !== undefined ? 1 : 0;
|
||||
count += charts.inProgressTasksByProsthesis !== undefined ? 1 : 0;
|
||||
count += charts.tasksByWorkflowStep !== undefined ? 1 : 0;
|
||||
count += charts.tasksByProsthesis !== undefined ? 1 : 0;
|
||||
}
|
||||
if (
|
||||
isOwner &&
|
||||
|
||||
Reference in New Issue
Block a user