"use client"; import { FormEvent, useMemo, useState } from "react"; import { CheckCircle2, Clock3, Play, Search, Siren } from "lucide-react"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Dialog } from "@/components/ui/dialog"; import { Input, Textarea } from "@/components/ui/input"; import { Select } from "@/components/ui/select"; import { Table } from "@/components/ui/table"; import type { ApiResult } from "@/modules/core/server/api"; import type { CareExecutionData, CareTask, CareTaskPriority, CareTaskStatus, CareTaskType } from "@/modules/care/types"; import { CARE_TASK_PRIORITY_LABELS, CARE_TASK_STATUS_LABELS, CARE_TASK_TYPE_LABELS } from "@/modules/care/types"; type CareWorkspaceClientProps = { canManage: boolean; initialData: CareExecutionData; }; function formatDateTime(value: string | undefined): string { return value ? new Date(value).toLocaleString("zh-CN") : "-"; } function statusVariant(status: CareTaskStatus): "success" | "secondary" | "warning" { if (status === "completed") { return "success"; } return status === "pending" ? "warning" : "secondary"; } function priorityVariant(priority: CareTaskPriority): "danger" | "secondary" | "warning" { if (priority === "urgent") { return "danger"; } return priority === "high" ? "warning" : "secondary"; } export function CareWorkspaceClient({ canManage, initialData }: CareWorkspaceClientProps): React.ReactElement { const [data, setData] = useState(initialData); const [query, setQuery] = useState(""); const [statusFilter, setStatusFilter] = useState<"all" | CareTaskStatus>("all"); const [priorityFilter, setPriorityFilter] = useState<"all" | CareTaskPriority>("all"); const [typeFilter, setTypeFilter] = useState<"all" | CareTaskType>("all"); const [message, setMessage] = useState(""); const [isPending, setIsPending] = useState(false); const [completeTarget, setCompleteTarget] = useState(); const [executionNotes, setExecutionNotes] = useState(""); const normalizedQuery = query.trim().toLowerCase(); const filteredTasks = useMemo( () => data.tasks.filter((task) => { const matchesQuery = !normalizedQuery || [task.title, task.elderName, task.assigneeLabel, task.executionNotes].join(" ").toLowerCase().includes(normalizedQuery); const matchesStatus = statusFilter === "all" || task.status === statusFilter; const matchesPriority = priorityFilter === "all" || task.priority === priorityFilter; const matchesType = typeFilter === "all" || task.careType === typeFilter; return matchesQuery && matchesStatus && matchesPriority && matchesType; }), [data.tasks, normalizedQuery, priorityFilter, statusFilter, typeFilter], ); async function refreshData(): Promise { const response = await fetch("/api/care/tasks"); const result = (await response.json()) as ApiResult<{ data: CareExecutionData }>; if (result.success) { setData(result.data); } } async function updateTask(task: CareTask, status: CareTaskStatus, notes = task.executionNotes): Promise { if (!canManage) { setMessage("当前角色无权处理护理任务"); return; } setIsPending(true); setMessage(""); const response = await fetch(`/api/care/tasks/${task.id}`, { method: "PATCH", headers: { "content-type": "application/json" }, body: JSON.stringify({ status, executionNotes: notes }), }); const result = (await response.json()) as ApiResult<{ task: CareTask }>; setIsPending(false); setMessage(result.reason); if (result.success) { setCompleteTarget(undefined); setExecutionNotes(""); await refreshData(); } } function openCompleteDialog(task: CareTask): void { setCompleteTarget(task); setExecutionNotes(task.executionNotes); setMessage(""); } function closeCompleteDialog(): void { if (isPending) { return; } setCompleteTarget(undefined); setExecutionNotes(""); } async function submitComplete(event: FormEvent): Promise { event.preventDefault(); if (!completeTarget) { return; } await updateTask(completeTarget, "completed", executionNotes); } return (

护理服务

按老人、任务类型、优先级和执行状态推进每日护理服务。

setPriorityFilter(value as "all" | CareTaskPriority)} options={[ { value: "all", label: "全部优先级" }, ...Object.entries(CARE_TASK_PRIORITY_LABELS).map(([value, label]) => ({ value, label })), ]} value={priorityFilter} />