166 lines
5.7 KiB
TypeScript
166 lines
5.7 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
||
import { ActionIcon, Button, Group, Modal, Stack, Text, Loader } from '@mantine/core';
|
||
import { showErrorMessage } from '~/utils/utils.ts';
|
||
import { apiGetPatientsList } from '~/utils/hms_api.ts';
|
||
import type { PatientData } from '~/utils/models.ts';
|
||
import InfoIcon from 'mdi-react/InfoIcon';
|
||
import { iconMStyle } from '~/styles.ts';
|
||
|
||
// 缓存已加载的患者数据,避免重复请求
|
||
const patientCache = new Map<number, PatientData>();
|
||
|
||
interface PatientInfoDisplayProps {
|
||
patientId: number;
|
||
showIcon?: boolean;
|
||
}
|
||
|
||
export function PatientInfoDisplay({ patientId, showIcon = true }: PatientInfoDisplayProps) {
|
||
const [patientInfo, setPatientInfo] = useState<PatientData | null>(null);
|
||
const [loading, setLoading] = useState(true);
|
||
const [modalOpen, setModalOpen] = useState(false);
|
||
const [initialLoad, setInitialLoad] = useState(true);
|
||
|
||
useEffect(() => {
|
||
// 如果已经在缓存中,直接使用缓存数据
|
||
if (patientCache.has(patientId)) {
|
||
setPatientInfo(patientCache.get(patientId) || null);
|
||
setLoading(false);
|
||
setInitialLoad(false);
|
||
return;
|
||
}
|
||
|
||
// 否则加载患者数据
|
||
fetchPatientInfo();
|
||
}, [patientId]);
|
||
|
||
const fetchPatientInfo = async () => {
|
||
try {
|
||
setLoading(true);
|
||
// 获取所有患者信息,传递-1表示不分页,获取所有患者
|
||
const response = await apiGetPatientsList(-1);
|
||
|
||
if (response.success) {
|
||
const patients = response.data.patients;
|
||
// 将所有患者添加到缓存
|
||
patients.forEach(patient => {
|
||
patientCache.set(patient.id, patient);
|
||
});
|
||
|
||
// 查找当前需要的患者
|
||
const patient = patients.find(p => p.id === patientId);
|
||
|
||
if (patient) {
|
||
setPatientInfo(patient);
|
||
} else {
|
||
console.warn(`Patient with ID ${patientId} not found`);
|
||
}
|
||
} else {
|
||
showErrorMessage(response.message, "Failed to load patient information");
|
||
}
|
||
} catch (error) {
|
||
showErrorMessage("Error loading patient information", "Error");
|
||
console.error("Error fetching patient information:", error);
|
||
} finally {
|
||
setLoading(false);
|
||
setInitialLoad(false);
|
||
}
|
||
};
|
||
|
||
const openModal = () => {
|
||
setModalOpen(true);
|
||
};
|
||
|
||
const closeModal = () => {
|
||
setModalOpen(false);
|
||
};
|
||
|
||
// 初始加载时显示加载状态
|
||
if (initialLoad) {
|
||
return <Loader size="xs" />;
|
||
}
|
||
|
||
// 如果无法找到患者信息,显示 ID
|
||
if (!patientInfo) {
|
||
return (
|
||
<Group gap="xs">
|
||
<Text>ID: {patientId}</Text>
|
||
{showIcon && (
|
||
<ActionIcon
|
||
size="sm"
|
||
onClick={fetchPatientInfo}
|
||
loading={loading}
|
||
title="Refresh patient information"
|
||
>
|
||
<InfoIcon style={iconMStyle} />
|
||
</ActionIcon>
|
||
)}
|
||
</Group>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<>
|
||
<Group gap="xs">
|
||
<Text
|
||
style={{ cursor: 'pointer' }}
|
||
onClick={openModal}
|
||
title="Click to view details"
|
||
>
|
||
{`${patientInfo.title} ${patientInfo.name}`}
|
||
</Text>
|
||
{showIcon && (
|
||
<ActionIcon
|
||
size="sm"
|
||
onClick={openModal}
|
||
title="View patient details"
|
||
>
|
||
<InfoIcon style={iconMStyle} />
|
||
</ActionIcon>
|
||
)}
|
||
</Group>
|
||
|
||
<Modal
|
||
opened={modalOpen}
|
||
onClose={closeModal}
|
||
title="Patient Information"
|
||
centered
|
||
size="md"
|
||
>
|
||
<Stack gap="md">
|
||
<Group>
|
||
<Text fw={500} w={100}>Name:</Text>
|
||
<Text>{`${patientInfo.title} ${patientInfo.name}`}</Text>
|
||
</Group>
|
||
<Group>
|
||
<Text fw={500} w={100}>Gender:</Text>
|
||
<Text>{patientInfo.gender}</Text>
|
||
</Group>
|
||
<Group>
|
||
<Text fw={500} w={100}>Birth Date:</Text>
|
||
<Text>{patientInfo.birth_date}</Text>
|
||
</Group>
|
||
<Group>
|
||
<Text fw={500} w={100}>Email:</Text>
|
||
<Text>{patientInfo.email}</Text>
|
||
</Group>
|
||
<Group>
|
||
<Text fw={500} w={100}>Phone:</Text>
|
||
<Text>{patientInfo.phone}</Text>
|
||
</Group>
|
||
<Group>
|
||
<Text fw={500} w={100}>Address:</Text>
|
||
<Text>{patientInfo.address}</Text>
|
||
</Group>
|
||
<Group>
|
||
<Text fw={500} w={100}>Postcode:</Text>
|
||
<Text>{patientInfo.postcode}</Text>
|
||
</Group>
|
||
|
||
<Group justify="flex-end" mt="md">
|
||
<Button onClick={closeModal}>Close</Button>
|
||
</Group>
|
||
</Stack>
|
||
</Modal>
|
||
</>
|
||
);
|
||
}
|