andrei 01a27978e6 refactor: Перенос AppointmentViewModal в папку Dummies
Перемещены компоненты и хуки для AppointmentViewModal.
Обновлены импорты в HomePage и AppointmentsPage.

Добавлено вывод на печать результатов приема
2025-06-06 19:40:59 +05:00

238 lines
8.7 KiB
JavaScript
Raw 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 { useDispatch, useSelector } from "react-redux";
import { setSelectedAppointment } from "../../../Redux/Slices/appointmentsSlice.js";
import dayjs from "dayjs";
import { useState } from "react";
import { useGetAppointmentFilesQuery, useDeleteAppointmentFileMutation } from "../../../Api/appointmentFilesApi.js";
import { baseQueryWithAuth } from "../../../Api/baseQuery.js";
import { notification } from "antd";
const useAppointmentView = () => {
const dispatch = useDispatch();
const { selectedAppointment } = useSelector((state) => state.appointmentsUI);
const { data: files = [], isLoading: isFilesLoading } = useGetAppointmentFilesQuery(
selectedAppointment?.id,
{ skip: !selectedAppointment?.id }
);
const [deleteAppointmentFile, { isLoading: isDeletingFile }] = useDeleteAppointmentFileMutation();
const [downloadingFiles, setDownloadingFiles] = useState({});
const [deletingFiles, setDeletingFiles] = useState({});
const modalWidth = 700;
const blockStyle = { marginBottom: 16 };
const footerRowStyle = { marginTop: 16 };
const footerButtonStyle = { marginRight: 8 };
const labels = {
title: "Просмотр приема",
patient: "Пациент:",
birthday: "Дата рождения:",
email: "Email:",
phone: "Телефон:",
type: "Тип приема:",
appointmentTime: "Время приема:",
daysUntilNext: "Дней до следующего приема:",
results: "Результаты приема:",
closeButton: "Закрыть",
notSpecified: "Не указан",
resultsNotSpecified: "Не указаны",
files: "Файлы:",
noFiles: "Файлы отсутствуют",
download: "Скачать",
downloading: "Загрузка...",
delete: "Удалить",
deleting: "Удаление...",
confirmDelete: "Вы уверены, что хотите удалить файл?",
printResults: "Печать результатов",
};
const visible = !!selectedAppointment;
const getDateString = (date) => {
return date ? new Date(date).toLocaleDateString("ru-RU") : labels.notSpecified;
};
const getAppointmentTime = (datetime) => {
return datetime
? dayjs(datetime).format("DD.MM.YYYY HH:mm")
: labels.notSpecified;
};
const getPatientName = (patient) => {
return patient
? `${patient.last_name} ${patient.first_name}`
: labels.notSpecified;
};
const getPatientField = (field) => {
return field || labels.notSpecified;
};
const getResults = (results) => {
return results || labels.resultsNotSpecified;
};
const onCancel = () => {
dispatch(setSelectedAppointment(null));
};
const downloadFile = async (fileId, fileName) => {
try {
setDownloadingFiles((prev) => ({ ...prev, [fileId]: true }));
const { url, ...options } = await baseQueryWithAuth(
{
url: `/appointment_files/${fileId}/file/`,
method: 'GET',
credentials: 'include',
},
{},
{}
);
const response = await fetch(url, {
...options,
method: 'GET',
credentials: 'include',
});
if (!response.ok) {
notification.error({
message: "Ошибка при скачивании файла",
description: "Не удалось загрузить файл.",
placement: "topRight",
});
}
const blob = await response.blob();
const downloadUrl = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = downloadUrl;
link.setAttribute("download", fileName || "file");
document.body.appendChild(link);
link.click();
link.remove();
window.URL.revokeObjectURL(downloadUrl);
} catch (error) {
console.error("Error downloading file:", error);
notification.error({
message: "Ошибка при скачивании файлов",
description: "Не удалось загрузить файл.",
placement: "topRight",
});
} finally {
setDownloadingFiles((prev) => ({ ...prev, [fileId]: false }));
}
};
const deleteFile = async (fileId, fileName) => {
try {
setDeletingFiles((prev) => ({ ...prev, [fileId]: true }));
await deleteAppointmentFile(fileId).unwrap();
notification.success({
message: "Файл удален",
description: `Файл ${fileName || "неизвестный"} успешно удален.`,
placement: "topRight",
});
} catch (error) {
console.error("Error deleting file:", error);
notification.error({
message: "Ошибка при удалении файла",
description: `Не удалось удалить файл ${fileName || "неизвестный"}: ${error.data?.detail || error.message}`,
placement: "topRight",
});
} finally {
setDeletingFiles((prev) => ({ ...prev, [fileId]: false }));
}
};
const printResults = () => {
if (!selectedAppointment?.results || selectedAppointment.results === labels.resultsNotSpecified) {
notification.error({
message: "Ошибка печати",
description: "Результаты приема отсутствуют.",
placement: "topRight",
});
return;
}
try {
const results = getResults(selectedAppointment.results);
const patientName = getPatientName(selectedAppointment.patient);
const appointmentTime = getAppointmentTime(selectedAppointment.appointment_datetime);
const printWindow = window.open('', '_blank', 'width=800,height=600');
if (!printWindow) {
notification.error({
message: "Ошибка печати",
description: "Не удалось открыть окно для печати. Проверьте настройки блокировки всплывающих окон.",
placement: "topRight",
});
return;
}
printWindow.document.write(`
<html>
<head>
<title>Результаты приема - ${patientName}</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
h1 { font-size: 24px; }
h2 { font-size: 18px; margin-bottom: 10px; }
.results { font-size: 16px; line-height: 1.5; }
</style>
</head>
<body>
<h1>Результаты приема</h1>
<h2>Пациент: ${patientName}</h2>
<h2>Дата и время приема: ${appointmentTime}</h2>
<div class="results">${results}</div>
</body>
</html>
`);
printWindow.document.close();
printWindow.onload = () => {
printWindow.focus();
printWindow.print();
setTimeout(() => {
printWindow.close();
}, 500);
};
} catch (error) {
console.error("Error printing results:", error);
notification.error({
message: "Ошибка печати",
description: "Не удалось выполнить печать. Попробуйте снова.",
placement: "topRight",
});
}
};
return {
modalWidth,
blockStyle,
footerRowStyle,
footerButtonStyle,
labels,
selectedAppointment,
visible,
getDateString,
getAppointmentTime,
getPatientName,
getPatientField,
getResults,
onCancel,
files,
isFilesLoading,
downloadingFiles,
downloadFile,
deletingFiles,
deleteFile,
isDeletingFile,
printResults,
};
};
export default useAppointmentView;