2025-04-30 17:28:58 +01:00

207 lines
7.7 KiB
TypeScript

import {type PatientData, SORT_SYMBOLS, type WardInfo, WardTypes} from "~/utils/models.ts";
import {ActionIcon, Group, Table, Text} from "@mantine/core";
import {useEffect, useMemo, useState} from "react";
import {apiGetWardPatients, apiTransferWard, apiGetWardList} from "~/utils/hms_api.ts";
import {getUserDisplayFullName, showErrorMessage, showInfoMessage} from "~/utils/utils.ts";
import {confirmCheckWardPatients, confirmDeleteWard, confirmEditOrCreateWard} from "~/components/subs/confirms.tsx";
import EyeIcon from "mdi-react/EyeIcon";
import {iconMStyle} from "~/styles.ts";
import PencilIcon from "mdi-react/PencilIcon";
import DeleteIcon from "mdi-react/DeleteIcon";
import SwapHorizontalIcon from "mdi-react/SwapHorizontalIcon";
import {modals} from "@mantine/modals";
import {Button, Select, Stack} from "@mantine/core";
import {useForm} from "@mantine/form";
import { ResponsiveTableContainer } from "./ResponsiveTableContainer";
function ConfirmTransferWard({patientId, currentWardId, onSuccess}: {patientId: number, currentWardId: number, onSuccess: () => void}) {
const [loading, setLoading] = useState(false);
const [wards, setWards] = useState<WardInfo[]>([]);
const [loadingWards, setLoadingWards] = useState(true);
const form = useForm({
initialValues: {
patient_id: patientId,
target_ward_id: '',
},
validate: {
target_ward_id: (value) => (!value ? 'Please select a ward' : null),
},
});
useEffect(() => {
// Load wards for selection
apiGetWardList(1, true).then(res => {
if (res.success) {
setWards(res.data.wards);
} else {
showErrorMessage(res.message, "Failed to load wards");
}
})
.catch(err => {
showErrorMessage("Failed to load wards", "Error");
})
.finally(() => {
setLoadingWards(false);
});
}, []);
const wardOptions = useMemo(() => {
return wards
.filter(ward => ward.id !== currentWardId && ward.current_occupancy < ward.total_capacity) // Exclude current ward and show only those with available capacity
.map(ward => ({
value: ward.id.toString(),
label: `${ward.name} (${ward.current_occupancy}/${ward.total_capacity}) - ${WardTypes[ward.type]}`
}));
}, [wards, currentWardId]);
const handleFormSubmit = (values: typeof form.values) => {
setLoading(true);
apiTransferWard(
values.patient_id,
parseInt(values.target_ward_id)
).then(res => {
if (res.success) {
showInfoMessage("Patient transferred successfully", "Success");
modals.closeAll();
onSuccess();
} else {
showErrorMessage(res.message, "Failed to transfer patient");
}
})
.catch(err => {
showErrorMessage("Failed to transfer patient", "Error");
})
.finally(() => {
setLoading(false);
});
};
return (
<form onSubmit={form.onSubmit(handleFormSubmit)}>
<Stack>
<Select
withAsterisk
label="Select Target Ward"
placeholder="Choose a ward to transfer patient to"
data={wardOptions}
searchable
nothingFoundMessage={wardOptions.length === 0 ? "No available wards with capacity" : "No matching wards found"}
disabled={loadingWards || wardOptions.length === 0}
{...form.getInputProps('target_ward_id')}
onChange={(value) => {
if (!value) return;
form.setFieldValue('target_ward_id', value);
}}
/>
{wardOptions.length === 0 && !loadingWards && (
<Text c="red" size="sm">
No available wards with capacity. Please free up space in a ward first.
</Text>
)}
<Group mt="md" justify="flex-end">
<Button variant="outline" onClick={() => modals.closeAll()}>
Cancel
</Button>
<Button
type="submit"
loading={loading || loadingWards}
disabled={wardOptions.length === 0}
color="blue"
>
Transfer Patient
</Button>
</Group>
</Stack>
</form>
);
}
export default function WardPatients ({ward_id, onChanged}: {ward_id: number, onChanged: () => void}) {
const [wardPatients, setWardPatients] = useState<PatientData[]>([])
useEffect(() => {
refreshWardPatients()
}, []);
const refreshWardPatients = () => {
apiGetWardPatients(ward_id).then((result) => {
if (result.success) {
setWardPatients(result.data.patients)
}
else {
showErrorMessage(result.message, "Failed to get ward patients")
}
}).catch((err => { showErrorMessage(err.toString(), "Failed to get ward patients") }) )
}
const handleTransferWard = (patientId: number) => {
modals.open({
title: "Transfer Patient",
centered: true,
size: "md",
children: (
<ConfirmTransferWard
patientId={patientId}
currentWardId={ward_id}
onSuccess={() => {
refreshWardPatients()
onChanged()
}}
/>
)
});
};
const rows = wardPatients.map((patient) => (
<Table.Tr key={patient.id}>
<Table.Td>{`${patient.title} ${patient.name}`}</Table.Td>
<Table.Td>{patient.gender}</Table.Td>
<Table.Td>{patient.birth_date}</Table.Td>
<Table.Td>{patient.email}</Table.Td>
<Table.Td>{patient.phone}</Table.Td>
<Table.Td>
<Group>
<ActionIcon onClick={() => handleTransferWard(patient.id)} title="Transfer to another ward">
<SwapHorizontalIcon style={iconMStyle}/>
</ActionIcon>
</Group>
</Table.Td>
</Table.Tr>
))
return (
<>
<ResponsiveTableContainer minWidth={600}>
<Table striped highlightOnHover withColumnBorders withTableBorder>
<Table.Thead>
<Table.Tr>
<Table.Th>
Name
</Table.Th>
<Table.Th>
Gender
</Table.Th>
<Table.Th>
Date of Birth
</Table.Th>
<Table.Th>
Email
</Table.Th>
<Table.Th>
Phone
</Table.Th>
<Table.Th>
Operations
</Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
</Table>
</ResponsiveTableContainer>
</>
)
}