feat: integrate operations dashboard summaries
This commit is contained in:
@@ -9,11 +9,14 @@ import {
|
||||
} from "@/modules/core/server/operations";
|
||||
import { hasPermission } from "@/modules/core/server/permissions";
|
||||
import type { BedStatus, Permission } from "@/modules/core/types";
|
||||
import { listCareExecutionData } from "@/modules/care/server/operations";
|
||||
import { DashboardHome, type DashboardMetric } from "@/modules/dashboard/components/DashboardHome";
|
||||
import { listEmergencyIncidentData } from "@/modules/emergency/server/operations";
|
||||
import { listHealthAdminData } from "@/modules/health/server/operations";
|
||||
import { getWorkspaceHref } from "@/modules/shared/lib/workspace-routing";
|
||||
|
||||
const BED_STATUSES: BedStatus[] = ["available", "occupied", "maintenance", "disabled"];
|
||||
const DASHBOARD_PERMISSIONS: Permission[] = ["elder:read", "facility:read", "admission:read", "incident:read"];
|
||||
const DASHBOARD_PERMISSIONS: Permission[] = ["elder:read", "facility:read", "admission:read", "incident:read", "care:read", "health:read"];
|
||||
|
||||
export default async function DashboardPage(): Promise<React.ReactElement> {
|
||||
const context = await getCurrentAuthContext();
|
||||
@@ -27,11 +30,18 @@ export default async function DashboardPage(): Promise<React.ReactElement> {
|
||||
redirect(getWorkspaceHref(context.organization?.slug, "/family"));
|
||||
}
|
||||
|
||||
const [elders, beds, admissions, incidents] = await Promise.all([
|
||||
const canReadCare = hasPermission(context.permissions, "care:read");
|
||||
const canReadHealth = hasPermission(context.permissions, "health:read");
|
||||
const canReadIncidents = hasPermission(context.permissions, "incident:read");
|
||||
|
||||
const [elders, beds, admissions, incidents, careData, healthData, emergencyData] = await Promise.all([
|
||||
listOperationalElders(organizationId),
|
||||
listOperationalBeds(organizationId),
|
||||
listOperationalAdmissions(organizationId),
|
||||
listOperationalIncidents(organizationId),
|
||||
organizationId && canReadCare ? listCareExecutionData(organizationId) : undefined,
|
||||
organizationId && canReadHealth ? listHealthAdminData(organizationId) : undefined,
|
||||
organizationId && canReadIncidents ? listEmergencyIncidentData(organizationId) : undefined,
|
||||
]);
|
||||
|
||||
const activeElders = elders.filter((elder) => elder.status === "active").length;
|
||||
@@ -40,12 +50,20 @@ export default async function DashboardPage(): Promise<React.ReactElement> {
|
||||
const availableBeds = beds.filter((bed) => bed.status === "available").length;
|
||||
const activeAdmissions = admissions.filter((admission) => admission.status === "active").length;
|
||||
const openIncidents = incidents.filter((incident) => incident.status !== "closed").length;
|
||||
const pendingCare = careData?.metrics.pending ?? 0;
|
||||
const inProgressCare = careData?.metrics.inProgress ?? 0;
|
||||
const pendingHealthReviews = healthData?.metrics.pendingReviews ?? 0;
|
||||
const activeChronicConditions = healthData?.metrics.activeChronicConditions ?? 0;
|
||||
const openEmergency = emergencyData?.metrics.open ?? 0;
|
||||
const criticalEmergency = emergencyData?.metrics.critical ?? 0;
|
||||
|
||||
const metrics: DashboardMetric[] = [
|
||||
{ label: "在院老人", value: String(activeElders), trend: `待入住 ${pendingElders}`, icon: "users" },
|
||||
{ label: "床位占用", value: `${occupiedBeds}/${beds.length}`, trend: `空闲 ${availableBeds}`, icon: "beds" },
|
||||
{ label: "护理任务", value: String(pendingCare + inProgressCare), trend: `待处理 ${pendingCare} / 进行中 ${inProgressCare}`, icon: "care" },
|
||||
{ label: "健康复核", value: String(pendingHealthReviews), trend: `慢病管理 ${activeChronicConditions}`, icon: "health" },
|
||||
{ label: "当前入住", value: String(activeAdmissions), trend: `历史 ${admissions.length}`, icon: "admissions" },
|
||||
{ label: "未关闭故障", value: String(openIncidents), trend: `总计 ${incidents.length}`, icon: "incidents" },
|
||||
{ label: "应急事件", value: String(openEmergency), trend: `紧急 ${criticalEmergency} / 未关闭 ${openIncidents}`, icon: "incidents" },
|
||||
];
|
||||
|
||||
const occupancyData = BED_STATUSES.map((status) => ({
|
||||
@@ -73,9 +91,49 @@ export default async function DashboardPage(): Promise<React.ReactElement> {
|
||||
source: incident.source,
|
||||
createdAt: incident.createdAt,
|
||||
}));
|
||||
const careTasks = (careData?.tasks ?? [])
|
||||
.filter((task) => task.status === "pending" || task.status === "in_progress" || task.priority === "urgent" || task.priority === "high")
|
||||
.slice(0, 6)
|
||||
.map((task) => ({
|
||||
id: task.id,
|
||||
assigneeLabel: task.assigneeLabel,
|
||||
elderName: task.elderName,
|
||||
priority: task.priority,
|
||||
scheduledAt: task.scheduledAt,
|
||||
status: task.status,
|
||||
title: task.title,
|
||||
}));
|
||||
const healthReviews = (healthData?.reviews ?? [])
|
||||
.filter((review) => review.status === "pending" || review.severity === "critical")
|
||||
.slice(0, 6)
|
||||
.map((review) => ({
|
||||
id: review.id,
|
||||
elderName: review.elderName,
|
||||
severity: review.severity,
|
||||
status: review.status,
|
||||
title: review.title,
|
||||
}));
|
||||
const emergencyIncidents = (emergencyData?.incidents ?? [])
|
||||
.filter((incident) => incident.status === "open" || incident.status === "acknowledged" || incident.severity === "critical")
|
||||
.slice(0, 6)
|
||||
.map((incident) => ({
|
||||
id: incident.id,
|
||||
severity: incident.severity,
|
||||
status: incident.status,
|
||||
title: incident.title,
|
||||
source: incident.source,
|
||||
createdAt: incident.createdAt,
|
||||
}));
|
||||
|
||||
return (
|
||||
<DashboardHome
|
||||
bedsHref={getWorkspaceHref(context.organization?.slug, "/beds")}
|
||||
careHref={getWorkspaceHref(context.organization?.slug, "/care")}
|
||||
careTasks={careTasks}
|
||||
emergencyHref={getWorkspaceHref(context.organization?.slug, "/emergency")}
|
||||
emergencyIncidents={emergencyIncidents}
|
||||
healthHref={getWorkspaceHref(context.organization?.slug, "/settings/health")}
|
||||
healthReviews={healthReviews}
|
||||
incidents={visibleIncidents}
|
||||
metrics={metrics}
|
||||
occupancyData={occupancyData}
|
||||
|
||||
Reference in New Issue
Block a user