update
This commit is contained in:
@@ -0,0 +1,341 @@
|
||||
"use client";
|
||||
|
||||
import CustomButton from "@/components/customs/custom-button";
|
||||
import GridColumn from "@/components/layouts/GridColumn";
|
||||
import FormCustom from "@/components/utils/FormCustom";
|
||||
import InputForm from "@/components/utils/FormCustom/components/InputForm";
|
||||
import TextArea from "@/components/utils/FormCustom/components/TextArea";
|
||||
import { PATH } from "@/constant/config";
|
||||
import { QUERY_KEY } from "@/constant/config/enum";
|
||||
import { httpRequest } from "@/services";
|
||||
import consultationServices, {
|
||||
ConsultationDetail,
|
||||
} from "@/services/consultationServices";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { useParams, useRouter, useSearchParams } from "next/navigation";
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
const UpdateSpecialtyClinicId = () => {
|
||||
const router = useRouter();
|
||||
const params = useParams();
|
||||
const searchParams = useSearchParams();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const consultationId = searchParams.get("_id") || "";
|
||||
const specialtyClinicId = searchParams.get("specialtyClinicId") || "";
|
||||
|
||||
const [form, setForm] = useState<{
|
||||
specialtyAssignmentId: string;
|
||||
specialtyNotes: string;
|
||||
diagnosis: string;
|
||||
procedureNotes: string;
|
||||
glassRequired: boolean;
|
||||
glassType: string;
|
||||
}>({
|
||||
specialtyAssignmentId: "",
|
||||
specialtyNotes: "",
|
||||
diagnosis: "",
|
||||
procedureNotes: "",
|
||||
glassRequired: false,
|
||||
glassType: "",
|
||||
});
|
||||
|
||||
/* =========================
|
||||
GET DETAIL API
|
||||
========================= */
|
||||
const consulDetailQuery = useQuery<ConsultationDetail>({
|
||||
queryKey: [QUERY_KEY.chi_tiet_phien_kham, consultationId],
|
||||
enabled: !!consultationId,
|
||||
queryFn: async () => {
|
||||
const res = await httpRequest<ConsultationDetail>({
|
||||
showMessageFailed: true,
|
||||
http: consultationServices.detailConsultations(consultationId),
|
||||
});
|
||||
|
||||
return (
|
||||
res || {
|
||||
id: "",
|
||||
patientId: "",
|
||||
sessionCode: "",
|
||||
visitDate: "",
|
||||
status: 1,
|
||||
chiefComplaint: null,
|
||||
symptomsText: null,
|
||||
vitalSigns: null,
|
||||
diagnosis: null,
|
||||
treatmentPlan: null,
|
||||
doctorNotes: null,
|
||||
createdBy: "",
|
||||
isDeleted: false,
|
||||
specialtyClinics: [
|
||||
{
|
||||
id: "",
|
||||
specialtyId: "",
|
||||
specialtyName: "",
|
||||
specialtyNotes: null,
|
||||
diagnosis: null,
|
||||
procedureNotes: null,
|
||||
glassRequired: null,
|
||||
glassType: null,
|
||||
examinerName: "",
|
||||
specialtyStatus: 1,
|
||||
sharedItems: [],
|
||||
},
|
||||
],
|
||||
aggregatedPrescriptionItems: [],
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// Tìm chuyên khoa hiện tại từ data trả về
|
||||
const selectedSpecialtyClinic =
|
||||
consulDetailQuery.data?.specialtyClinics?.find(
|
||||
(item) => item.id === specialtyClinicId,
|
||||
);
|
||||
|
||||
/**
|
||||
* ĐIỀU KIỆN KIỂM TRA KHOA MẮT
|
||||
* Bạn hãy thay đổi điều kiện này tùy thuộc vào database của bạn.
|
||||
* Ví dụ: selectedSpecialtyClinic?.specialtyId === "MẮT" hoặc kiểm tra theo tên.
|
||||
*/
|
||||
const isEyeClinic =
|
||||
selectedSpecialtyClinic?.specialtyName?.toLowerCase().includes("mắt") ||
|
||||
selectedSpecialtyClinic?.specialtyId?.toLowerCase().includes("mat");
|
||||
|
||||
useEffect(() => {
|
||||
const consul = consulDetailQuery.data;
|
||||
if (!consul) return;
|
||||
|
||||
const specialtyClinic = consul.specialtyClinics?.find(
|
||||
(item) => item.id === specialtyClinicId,
|
||||
);
|
||||
|
||||
if (!specialtyClinic) return;
|
||||
|
||||
setForm({
|
||||
specialtyAssignmentId: specialtyClinic.id || "",
|
||||
specialtyNotes: specialtyClinic.specialtyNotes || "",
|
||||
diagnosis: specialtyClinic.diagnosis || "",
|
||||
procedureNotes: specialtyClinic.procedureNotes || "",
|
||||
glassRequired: specialtyClinic.glassRequired || false,
|
||||
glassType: specialtyClinic.glassType || "",
|
||||
});
|
||||
}, [consulDetailQuery.data, specialtyClinicId]);
|
||||
|
||||
/* =========================
|
||||
UPDATE MUTATION
|
||||
========================= */
|
||||
const specialtyResultsMutation = useMutation({
|
||||
mutationFn: async () => {
|
||||
if (!consultationId) {
|
||||
throw new Error("Không tìm thấy ID phiên khám!");
|
||||
}
|
||||
|
||||
return httpRequest({
|
||||
showMessageFailed: true,
|
||||
showMessageSuccess: true,
|
||||
msgSuccess: "Cập nhật phiên khám thành công!",
|
||||
http: consultationServices.specialtyResults(
|
||||
form.specialtyAssignmentId,
|
||||
{
|
||||
specialtyNotes: form.specialtyNotes,
|
||||
diagnosis: form.diagnosis,
|
||||
procedureNotes: form.procedureNotes,
|
||||
// Nếu không phải khoa mắt, gán mặc định false và chuỗi rỗng khi gửi API
|
||||
glassRequired: isEyeClinic ? form.glassRequired : false,
|
||||
glassType: isEyeClinic ? form.glassType : "",
|
||||
},
|
||||
),
|
||||
});
|
||||
},
|
||||
onSuccess(data) {
|
||||
if (!data) return;
|
||||
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [QUERY_KEY.table_list_consultation],
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [QUERY_KEY.chi_tiet_phien_kham, consultationId],
|
||||
});
|
||||
|
||||
router.push(PATH.CONSULTATION || "/consultation");
|
||||
},
|
||||
});
|
||||
|
||||
const handleSubmit = () => {
|
||||
specialtyResultsMutation.mutate();
|
||||
};
|
||||
|
||||
const isLoading =
|
||||
consulDetailQuery.isLoading || specialtyResultsMutation.isPending;
|
||||
|
||||
if (consulDetailQuery.isLoading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center p-10 font-medium text-gray-500">
|
||||
Đang tải dữ liệu phiên khám...
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<FormCustom form={form} setForm={setForm} onSubmit={handleSubmit}>
|
||||
<div className="flex flex-col gap-6 rounded-2xl bg-white p-6 shadow-xl">
|
||||
{/* HEADER */}
|
||||
<div className="flex items-center justify-between border-b pb-5">
|
||||
<div>
|
||||
<h2 className="text-[24px] font-bold text-[#111827]">
|
||||
Phiên khám chuyên khoa
|
||||
</h2>
|
||||
<p className="mt-1 text-sm text-[#697586]">
|
||||
Cập nhật kết quả chi tiết quá trình khám bệnh của bệnh nhân
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* CHUYÊN KHOA INFO */}
|
||||
<InputForm
|
||||
label="Chuyên khoa đảm nhận"
|
||||
name="specialtyAssignmentId"
|
||||
type="text"
|
||||
value={
|
||||
selectedSpecialtyClinic
|
||||
? `${selectedSpecialtyClinic.specialtyName}`
|
||||
: "Chưa có thông tin chuyên khoa"
|
||||
}
|
||||
placeholder="Thông tin chuyên khoa"
|
||||
isRequired
|
||||
readOnly
|
||||
/>
|
||||
|
||||
{/* KHỐI THÔNG TIN KHÁM CHUNG (Luôn cố định 3 cột đẹp mắt) */}
|
||||
<div className="mt-2">
|
||||
<h3 className="mb-4 text-sm font-semibold uppercase tracking-wider text-gray-400">
|
||||
Thông tin khám chung
|
||||
</h3>
|
||||
<GridColumn col={3}>
|
||||
<InputForm
|
||||
label="Ghi chú chuyên khoa"
|
||||
name="specialtyNotes"
|
||||
type="text"
|
||||
value={form.specialtyNotes}
|
||||
placeholder="Nhập ghi chú chuyên khoa"
|
||||
isRequired
|
||||
onChangeValue={(v) =>
|
||||
setForm((prev) => ({ ...prev, specialtyNotes: String(v) }))
|
||||
}
|
||||
/>
|
||||
<InputForm
|
||||
type="text"
|
||||
label="Chuẩn đoán chuyên khoa"
|
||||
name="diagnosis"
|
||||
placeholder="Nhập Chuẩn đoán"
|
||||
isRequired
|
||||
value={form.diagnosis}
|
||||
onChangeValue={(v) =>
|
||||
setForm((prev) => ({ ...prev, diagnosis: String(v) }))
|
||||
}
|
||||
/>
|
||||
<InputForm
|
||||
type="text"
|
||||
label="Ghi chú thủ thuật / can thiệp"
|
||||
name="procedureNotes"
|
||||
placeholder="Nhập ghi chú thủ thuật / can thiệp"
|
||||
value={form.procedureNotes}
|
||||
isRequired
|
||||
onChangeValue={(v) =>
|
||||
setForm((prev) => ({ ...prev, procedureNotes: String(v) }))
|
||||
}
|
||||
/>
|
||||
</GridColumn>
|
||||
</div>
|
||||
|
||||
{/* KHỐI THÔNG TIN KHÁM MẮT (Chỉ hiển thị khi là khoa mắt) */}
|
||||
{isEyeClinic && (
|
||||
<div className="mt-2 rounded-xl border border-blue-100 bg-[#f8fafc] p-5 transition-all">
|
||||
<h3 className="mb-4 text-sm font-bold uppercase tracking-wider text-blue-600">
|
||||
Chỉ định thị lực (Khoa Mắt)
|
||||
</h3>
|
||||
|
||||
<div className="flex flex-col gap-5">
|
||||
{/* Radio Chọn Có/Không */}
|
||||
<div>
|
||||
<label className="text-sm font-medium text-gray-700">
|
||||
Bệnh nhân có chỉ định đeo kính không?
|
||||
</label>
|
||||
<div className="mt-2.5 flex items-center gap-8">
|
||||
<label className="flex cursor-pointer items-center gap-2 text-sm font-medium text-gray-900">
|
||||
<input
|
||||
type="radio"
|
||||
name="glassRequired"
|
||||
className="h-4 w-4 border-gray-300 text-blue-600 focus:ring-blue-500"
|
||||
checked={form.glassRequired === true}
|
||||
onChange={() =>
|
||||
setForm((prev) => ({ ...prev, glassRequired: true }))
|
||||
}
|
||||
/>
|
||||
Có chỉ định
|
||||
</label>
|
||||
|
||||
<label className="flex cursor-pointer items-center gap-2 text-sm font-medium text-gray-900">
|
||||
<input
|
||||
type="radio"
|
||||
name="glassRequired"
|
||||
className="h-4 w-4 border-gray-300 text-blue-600 focus:ring-blue-500"
|
||||
checked={form.glassRequired === false}
|
||||
onChange={() =>
|
||||
setForm((prev) => ({ ...prev, glassRequired: false }))
|
||||
}
|
||||
/>
|
||||
Không chỉ định
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* TextArea Loại Kính (Trải rộng ra 100% dòng tạo cảm giác thoáng đãng) */}
|
||||
{form.glassRequired && (
|
||||
<div className="mt-2 animate-fadeIn ">
|
||||
<TextArea
|
||||
name="glassType"
|
||||
placeholder="Nhập thông số chi tiết loại kính được chỉ định (Cận, viễn, loạn, độ kính...)"
|
||||
label="Thông số / Loại kính chỉ định"
|
||||
value={form.glassType}
|
||||
isRequired
|
||||
isBlur
|
||||
max={5000}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* BUTTON ACTION */}
|
||||
<div className="mt-4 flex items-center justify-end gap-3 border-t pt-5">
|
||||
<CustomButton
|
||||
type="button"
|
||||
variant="grey"
|
||||
rounded="md"
|
||||
onClick={() => router.back()}
|
||||
className="min-w-[120px]"
|
||||
>
|
||||
Hủy bỏ
|
||||
</CustomButton>
|
||||
<CustomButton
|
||||
type="submit"
|
||||
variant="midnightBlue"
|
||||
rounded="md"
|
||||
disabled={isLoading || !consultationId}
|
||||
className="min-w-[140px]"
|
||||
>
|
||||
{specialtyResultsMutation.isPending
|
||||
? "Đang cập nhật..."
|
||||
: "Cập nhật kết quả"}
|
||||
</CustomButton>
|
||||
</div>
|
||||
</div>
|
||||
</FormCustom>
|
||||
);
|
||||
};
|
||||
|
||||
export default UpdateSpecialtyClinicId;
|
||||
Reference in New Issue
Block a user