HMS_Group5/HMS_Frontend/app/components/subs/DoctorInfoDisplay.tsx
2025-04-30 17:28:58 +01:00

173 lines
6.0 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect, useState } from 'react';
import { ActionIcon, Button, Group, Modal, Stack, Text, Loader } from '@mantine/core';
import { showErrorMessage } from '~/utils/utils.ts';
import { apiGetDoctorsList } from '~/utils/hms_api.ts';
import type { DoctorData, DoctorDataWithPermission } from '~/utils/models.ts';
import InfoIcon from 'mdi-react/InfoIcon';
import { iconMStyle } from '~/styles.ts';
import { DoctorGrade } from '~/utils/hms_enums.ts';
// 缓存已加载的医生数据,避免重复请求
const doctorCache = new Map<number, DoctorDataWithPermission>();
interface DoctorInfoDisplayProps {
doctorId: number;
showIcon?: boolean;
}
export function DoctorInfoDisplay({ doctorId, showIcon = true }: DoctorInfoDisplayProps) {
const [doctorInfo, setDoctorInfo] = useState<DoctorDataWithPermission | null>(null);
const [loading, setLoading] = useState(true);
const [modalOpen, setModalOpen] = useState(false);
const [initialLoad, setInitialLoad] = useState(true);
useEffect(() => {
// 如果已经在缓存中,直接使用缓存数据
if (doctorCache.has(doctorId)) {
setDoctorInfo(doctorCache.get(doctorId) || null);
setLoading(false);
setInitialLoad(false);
return;
}
// 否则加载医生数据
fetchDoctorInfo();
}, [doctorId]);
const fetchDoctorInfo = async () => {
try {
setLoading(true);
// 获取所有医生信息,传递-1表示不分页获取所有医生
const response = await apiGetDoctorsList(-1);
if (response.success) {
const doctors = response.data.doctors;
// 将所有医生添加到缓存
doctors.forEach(doctor => {
doctorCache.set(doctor.id, doctor);
});
// 查找当前需要的医生
const doctor = doctors.find(d => d.id === doctorId);
if (doctor) {
setDoctorInfo(doctor);
} else {
console.warn(`Doctor with ID ${doctorId} not found`);
}
} else {
showErrorMessage(response.message, "Failed to load doctor information");
}
} catch (error) {
showErrorMessage("Error loading doctor information", "Error");
console.error("Error fetching doctor information:", error);
} finally {
setLoading(false);
setInitialLoad(false);
}
};
const openModal = () => {
setModalOpen(true);
};
const closeModal = () => {
setModalOpen(false);
};
// 初始加载时显示加载状态
if (initialLoad) {
return <Loader size="xs" />;
}
// 如果无法找到医生信息,显示 ID
if (!doctorInfo) {
return (
<Group gap="xs">
<Text>ID: {doctorId}</Text>
{showIcon && (
<ActionIcon
size="sm"
onClick={fetchDoctorInfo}
loading={loading}
title="Refresh doctor information"
>
<InfoIcon style={iconMStyle} />
</ActionIcon>
)}
</Group>
);
}
return (
<>
<Group gap="xs">
<Text
style={{ cursor: 'pointer' }}
onClick={openModal}
title="Click to view details"
>
{`${doctorInfo.title} ${doctorInfo.name}`}
</Text>
{showIcon && (
<ActionIcon
size="sm"
onClick={openModal}
title="View doctor details"
>
<InfoIcon style={iconMStyle} />
</ActionIcon>
)}
</Group>
<Modal
opened={modalOpen}
onClose={closeModal}
title="Doctor Information"
centered
size="md"
>
<Stack gap="md">
<Group>
<Text fw={500} w={100}>Name:</Text>
<Text>{`${doctorInfo.title} ${doctorInfo.name}`}</Text>
</Group>
<Group>
<Text fw={500} w={100}>Gender:</Text>
<Text>{doctorInfo.gender}</Text>
</Group>
<Group>
<Text fw={500} w={100}>Grade:</Text>
<Text>{DoctorGrade[doctorInfo.grade]}</Text>
</Group>
<Group>
<Text fw={500} w={100}>Birth Date:</Text>
<Text>{doctorInfo.birth_date}</Text>
</Group>
<Group>
<Text fw={500} w={100}>Email:</Text>
<Text>{doctorInfo.email}</Text>
</Group>
<Group>
<Text fw={500} w={100}>Phone:</Text>
<Text>{doctorInfo.phone}</Text>
</Group>
<Group>
<Text fw={500} w={100}>Admin:</Text>
<Text>{doctorInfo.is_admin ? 'Yes' : 'No'}</Text>
</Group>
<Group>
<Text fw={500} w={100}>Status:</Text>
<Text color={doctorInfo.is_resigned ? 'red' : 'green'}>
{doctorInfo.is_resigned ? 'Resigned' : 'Active'}
</Text>
</Group>
<Group justify="flex-end" mt="md">
<Button onClick={closeModal}>Close</Button>
</Group>
</Stack>
</Modal>
</>
);
}