This commit is contained in:
TuanVT
2026-05-31 09:38:10 +07:00
parent 56e2733d8f
commit 62ca6dd0f9
32 changed files with 1785 additions and 381 deletions
@@ -22,13 +22,17 @@ import patientServices, {
import { QUERY_KEY } from "@/constant/config/enum";
import CustomButton from "@/components/customs/custom-button";
import { useRouter } from "next/navigation";
import { useRouter, useSearchParams } from "next/navigation";
import InputForm from "@/components/utils/FormCustom/components/InputForm";
import GridColumn from "@/components/layouts/GridColumn";
import { toastWarn } from "@/common/funcs/toast";
import specialtyServices, { SpecialtyItem } from "@/services/specialtyServices";
import SelectMany from "@/components/utils/FormCustom/components/SelectMany";
const CreateConsultation = () => {
const router = useRouter();
const searchParams = useSearchParams();
const patientId = searchParams.get("patientId");
const queryClient = useQueryClient();
const [form, setForm] = useState<{
@@ -36,17 +40,13 @@ const CreateConsultation = () => {
chiefComplaint: string;
symptomsText: string;
vitalSigns: string;
diagnosis: string;
treatmentPlan: string;
doctorNotes: string;
specialtyIds: string[];
}>({
patientId: "",
patientId: patientId || "",
chiefComplaint: "",
symptomsText: "",
vitalSigns: "",
diagnosis: "",
treatmentPlan: "",
doctorNotes: "",
specialtyIds: [],
});
/* =========================
@@ -80,6 +80,24 @@ const CreateConsultation = () => {
},
});
/* =========================
GET LIST SPECIALTY
========================= */
const specialtyQuery = useQuery<SpecialtyItem[]>({
queryKey: [QUERY_KEY.table_list_specialty],
queryFn: async () => {
const res = await httpRequest<SpecialtyItem[]>({
showMessageFailed: true,
http: specialtyServices.getSpecialty(),
});
return res || [];
},
});
const specialties: SpecialtyItem[] = specialtyQuery.data || [];
/* =========================
OPTIONS SELECT
========================= */
@@ -99,6 +117,10 @@ const CreateConsultation = () => {
http: consultationServices.createConsultations({
patientId: form.patientId,
chiefComplaint: form.chiefComplaint,
symptomsText: form.symptomsText,
vitalSigns: form.vitalSigns,
specialtyIds: form.specialtyIds,
}),
});
},
@@ -123,7 +145,6 @@ const CreateConsultation = () => {
<div
className="
max-w-[95vw]
h-[485px]
border
rounded-lg
bg-white
@@ -158,6 +179,7 @@ const CreateConsultation = () => {
<span className="text-red-500">*</span>
</span>
}
readOnly={!!patientId}
placeholder="Chọn bệnh nhân"
value={form.patientId}
options={patientOptions}
@@ -180,6 +202,63 @@ const CreateConsultation = () => {
getOptionValue={(item: PatientItem) => item.id}
/>
</div>
<div className="space-y-5 mb-2">
<GridColumn col={3}>
<InputForm
label="Lý do khám"
name="chiefComplaint"
type="text"
value={form.chiefComplaint}
placeholder="Nhập lý do khám"
isRequired
onChangeValue={(v) =>
setForm((prev) => ({ ...prev, chiefComplaint: String(v) }))
}
/>
<InputForm
type="text"
label="Triệu chứng"
name="symptomsText"
placeholder="Nhập triệu chứng"
isRequired
value={form.symptomsText}
onChangeValue={(v) =>
setForm((prev) => ({ ...prev, symptomsText: String(v) }))
}
/>
<InputForm
type="text"
label="Chỉ số huyết áp, chỉ số mạch"
name="vitalSigns"
placeholder="Nhập chỉ số huyết áp, chỉ số mạch"
value={form.vitalSigns}
isRequired
onChangeValue={(v) =>
setForm((prev) => ({ ...prev, vitalSigns: String(v) }))
}
/>
</GridColumn>
</div>
<div className="space-y-5 mb2">
<SelectMany<SpecialtyItem>
label="Chuyên khoa"
text="chuyên khoa"
title="Chọn chuyên khoa"
placeholder="Chọn nhiều chuyên khoa..."
options={specialties}
selectedItems={form.specialtyIds}
setSelectedItems={(value) =>
setForm((prev) => ({
...prev,
specialtyIds: value as string[],
}))
}
showSelectedItems="default"
getOptionLabel={(item) => item.name}
getOptionValue={(item) => item.id}
/>
</div>
</div>
{/* FOOTER */}
@@ -207,12 +286,10 @@ const CreateConsultation = () => {
<CustomButton
disabled={
!form.patientId ||
// !form.chiefComplaint ||
// !form.diagnosis ||
// !form.doctorNotes ||
// !form.symptomsText ||
// !form.treatmentPlan ||
// !form.vitalSigns ||
!form.chiefComplaint ||
!form.symptomsText ||
!form.vitalSigns ||
!form.specialtyIds ||
createConsultationMutation.isPending
}
variant="midnightBlue"
@@ -134,10 +134,10 @@ const DetailConsultation = () => {
</p>
</div>
{/* DẤU HIỆU SINH TỒN */}
{/* CHỈ SỐ HUYẾT ÁP, CHỈ SỐ MẠCH */}
<div className="space-y-1">
<p className="text-[14px] font-medium text-[#697586]">
DẤU HIỆU SINH TỒN
CHỈ SỐ HUYẾT ÁP, CHỈ SỐ MẠCH
</p>
<p className="text-[15px] font-medium text-[#202939]">
@@ -189,6 +189,32 @@ const DetailConsultation = () => {
</p>
</div>
<div className="space-y-1">
<p className="text-[14px] font-medium text-[#697586]">
CÁC CHUYÊN KHOA ĐANG CHỜ KHÁM
</p>
<p className="text-[15px] font-medium text-[#202939]">
{consultation.specialtyClinics
?.filter((specialty) => specialty.specialtyStatus === 1)
.map((specialty) => specialty.specialtyName)
.join(", ") || "---"}
</p>
</div>
<div className="space-y-1">
<p className="text-[14px] font-medium text-[#697586]">
CÁC CHUYÊN KHOA ĐÃ KHÁM
</p>
<p className="text-[15px] font-medium text-[#202939]">
{consultation.specialtyClinics
?.filter((specialty) => specialty.specialtyStatus === 3)
.map((specialty) => specialty.specialtyName)
.join(", ") || "---"}
</p>
</div>
{/* TRẠNG THÁI */}
<div className="space-y-1">
<p className="text-[14px] font-medium text-[#697586]">
@@ -200,29 +226,44 @@ const DetailConsultation = () => {
listState={[
{
state: TYPE_STATUS.Draft,
text: "Đang chờ",
textColor: "#000",
backgroundColor: "#FFE4C4",
text: "Đang chờ khám",
textColor: "#92400E",
backgroundColor: "#FEF3C7",
},
{
state: TYPE_STATUS.InProgress,
text: "Đang thực hiện",
textColor: "#000",
backgroundColor: "#ff3300",
text: "Đang khám tổng quát",
textColor: "#1E3A8A",
backgroundColor: "#DBEAFE",
},
{
state: TYPE_STATUS.ToSpecialty,
text: "Chờ khám chuyên khoa",
textColor: "#6B21A8",
backgroundColor: "#E9D5FF",
},
{
state: TYPE_STATUS.PendingPrescription,
text: "Chờ nhận thuốc/kính",
textColor: "#9A3412",
backgroundColor: "#FED7AA",
},
{
state: TYPE_STATUS.Completed,
text: "Hoàn thành",
textColor: "#000",
backgroundColor: "#3d69eb",
textColor: "#166534",
backgroundColor: "#DCFCE7",
},
{
state: TYPE_STATUS.Cancelled,
text: "Đã hủy",
textColor: "#000",
backgroundColor: "#cccc",
textColor: "#991B1B",
backgroundColor: "#FEE2E2",
},
]}
/>
@@ -2,7 +2,6 @@
import CustomButton from "@/components/customs/custom-button";
import CustomDialog from "@/components/customs/custom-dialog";
import CustomPopup from "@/components/customs/custom-popup";
import DataWrapper from "@/components/customs/DataWrapper";
import Search from "@/components/customs/custom-search";
import StateActive from "@/components/customs/StateActive";
@@ -27,8 +26,11 @@ import { usePathname, useRouter, useSearchParams } from "next/navigation";
import React, { useMemo, useState } from "react";
import { PATH } from "@/constant/config";
import Pagination from "@/components/customs/custom-pagination";
import moment from "moment";
import specialtyServices, { SpecialtyItem } from "@/services/specialtyServices";
import FilterCustom from "@/components/customs/FilterCustom";
const MainPageConsultation = () => {
const router = useRouter();
@@ -49,6 +51,10 @@ const MainPageConsultation = () => {
const _keyword = searchParams.get("_keyword");
const _status = searchParams.get("_status");
const _specialtyId = searchParams.get("_specialtyId");
/* =========================
STATE
========================= */
@@ -78,7 +84,7 @@ const MainPageConsultation = () => {
Search: _keyword || "",
SortBy: "id",
SortBy: _specialtyId || undefined,
Desc: true,
}),
@@ -100,9 +106,35 @@ const MainPageConsultation = () => {
DATA
========================= */
const specialtyQuery = useQuery({
queryKey: [QUERY_KEY.list_specialty_lookup],
queryFn: async () => {
const res = await httpRequest<SpecialtyItem[]>({
http: specialtyServices.getSpecialty(),
showMessageFailed: true,
});
return res || [];
},
});
const consultationData = useMemo(() => {
return consultationQuery.data?.items || [];
}, [consultationQuery.data]);
let data = consultationQuery.data?.items || [];
if (_status) {
data = data.filter((item) => item.status === Number(_status));
}
if (_specialtyId) {
data = data.filter((item) =>
item.specialtyClinics?.some(
(specialty) => specialty.specialtyId === _specialtyId,
),
);
}
return data;
}, [consultationQuery.data, _status, _specialtyId]);
/* =========================
UPDATE QUERY
@@ -114,13 +146,18 @@ const MainPageConsultation = () => {
const updateQuery = (key: string, value: string | number) => {
const params = new URLSearchParams(searchParams.toString());
if (!value || value === "" || (key === "_page" && value === 1)) {
if (!value || value === "") {
params.delete(key);
} else {
params.set(key, String(value));
}
if (key === "_pageSize") {
if (
key === "_pageSize" ||
key === "_keyword" ||
key === "_status" ||
key === "_specialtyId"
) {
params.delete("_page");
}
@@ -259,6 +296,51 @@ const MainPageConsultation = () => {
placeholder="Tìm kiếm phiên khám..."
/>
</div>
<FilterCustom<string | null>
name="Chuyên khoa"
value={_specialtyId}
onChange={(value) => updateQuery("_specialtyId", value ?? "")}
listOption={useMemo(() => {
return (
specialtyQuery.data?.map((item) => ({
uuid: item.id,
name: item.name,
})) || []
);
}, [specialtyQuery.data])}
/>
<FilterCustom<number | null>
name="Trạng thái"
value={_status ? Number(_status) : null}
onChange={(value) => updateQuery("_status", value ?? "")}
listOption={[
{
uuid: TYPE_STATUS.Draft,
name: "Đang chờ khám",
},
{
uuid: TYPE_STATUS.InProgress,
name: "Đang khám tổng quát",
},
{
uuid: TYPE_STATUS.ToSpecialty,
name: "Chờ khám chuyên khoa",
},
{
uuid: TYPE_STATUS.PendingPrescription,
name: "Chờ nhận thuốc/kính",
},
{
uuid: TYPE_STATUS.Completed,
name: "Hoàn thành",
},
{
uuid: TYPE_STATUS.Cancelled,
name: "Đã hủy",
},
]}
/>
</div>
{/* TABLE */}
@@ -295,8 +377,13 @@ const MainPageConsultation = () => {
{
title: "NGÀY KHÁM",
render: (item: ConsultationItem) => <span>{item.visitDate}</span>,
render: (item: ConsultationItem) => (
<span>
{item.visitDate
? moment(item.visitDate).format("DD/MM/YYYY")
: "---"}
</span>
),
},
{
@@ -330,7 +417,30 @@ const MainPageConsultation = () => {
<span>{item.doctorNotes || "---"}</span>
),
},
{
title: "CÁC CHUYÊN KHOA ĐANG CHỜ KHÁM",
render: (item: ConsultationItem) => {
const waitingSpecialties = item.specialtyClinics
?.filter((specialty) => specialty.specialtyStatus === 1)
.map((specialty) => specialty.specialtyName)
.join(", ");
return <span>{waitingSpecialties || "---"}</span>;
},
},
{
title: "CÁC CHUYÊN KHOA ĐÃ KHÁM",
render: (item: ConsultationItem) => {
const completedSpecialties = item.specialtyClinics
?.filter((specialty) => specialty.specialtyStatus === 3)
.map((specialty) => specialty.specialtyName)
.join(", ");
return <span>{completedSpecialties || "---"}</span>;
},
},
{
title: "TRẠNG THÁI",
@@ -340,29 +450,44 @@ const MainPageConsultation = () => {
listState={[
{
state: TYPE_STATUS.Draft,
text: "Đang chờ",
textColor: "#000",
backgroundColor: "#FFE4C4",
text: "Đang chờ khám",
textColor: "#92400E",
backgroundColor: "#FEF3C7",
},
{
state: TYPE_STATUS.InProgress,
text: "Đang thực hiện",
textColor: "#000",
backgroundColor: "#ff3300",
text: "Đang khám tổng quát",
textColor: "#1E3A8A",
backgroundColor: "#DBEAFE",
},
{
state: TYPE_STATUS.ToSpecialty,
text: "Chờ khám chuyên khoa",
textColor: "#6B21A8",
backgroundColor: "#E9D5FF",
},
{
state: TYPE_STATUS.PendingPrescription,
text: "Chờ nhận thuốc/kính",
textColor: "#9A3412",
backgroundColor: "#FED7AA",
},
{
state: TYPE_STATUS.Completed,
text: "Hoàn thành",
textColor: "#000",
backgroundColor: "#3d69eb",
textColor: "#166534",
backgroundColor: "#DCFCE7",
},
{
state: TYPE_STATUS.Cancelled,
text: "Đã hủy",
textColor: "#000",
backgroundColor: "#cccc",
textColor: "#991B1B",
backgroundColor: "#FEE2E2",
},
]}
/>
@@ -381,15 +506,32 @@ const MainPageConsultation = () => {
const isDisabled = isCancelled || isCompleted;
// Tìm chuyên khoa có specialtyStatus = 1
const specialtyClinicActive = item.specialtyClinics?.find(
(specialty) => specialty.specialtyStatus === 1,
);
return (
<div className="flex items-center gap-2">
{/* UPDATE */}
<CustomButton
size="sm"
disabled={isDisabled}
icon={<Pencil className="text-blue-400" />}
href={`/consultation/update?_id=${item?.id}`}
/>
icon={
specialtyClinicActive ? undefined : (
<Pencil className="text-blue-400" />
)
}
href={
specialtyClinicActive
? `/consultation/update-specialty?_id=${item.id}&specialtyClinicId=${specialtyClinicActive.id}`
: `/consultation/update?_id=${item.id}`
}
>
{specialtyClinicActive
? `Cập nhật ${specialtyClinicActive.specialtyName}`
: undefined}
</CustomButton>
{/* CANCEL */}
<CustomButton
@@ -423,7 +565,7 @@ const MainPageConsultation = () => {
pageSize={pageSize}
onSetPage={(value) => updateQuery("_page", value)}
onSetPageSize={(value) => updateQuery("_pageSize", value)}
dependencies={[_pageSize, _keyword]}
dependencies={[_pageSize, _keyword, _specialtyId, _status]}
/>
{/* CANCEL DIALOG */}
@@ -18,6 +18,7 @@ import Table from "@/components/customs/custom-table";
import StateActive from "@/components/customs/StateActive";
import Pagination from "@/components/customs/custom-pagination";
import Search from "@/components/customs/custom-search";
import moment from "moment";
const TableHistoryPatient = () => {
const searchParams = useSearchParams();
@@ -129,7 +130,13 @@ const TableHistoryPatient = () => {
},
{
title: "NGÀY KHÁM",
render: (item: ConsultationItem) => <span>{item.visitDate}</span>,
render: (item: ConsultationItem) => (
<span>
{item.visitDate
? moment(item.visitDate).format("DD/MM/YYYY")
: "---"}
</span>
),
},
{
title: "DẤU HIỆU",
@@ -151,27 +158,44 @@ const TableHistoryPatient = () => {
listState={[
{
state: TYPE_STATUS.Draft,
text: "Đang chờ",
textColor: "#000",
backgroundColor: "#FFE4C4",
text: "Đang chờ khám",
textColor: "#92400E",
backgroundColor: "#FEF3C7",
},
{
state: TYPE_STATUS.InProgress,
text: "Đang thực hiện",
textColor: "#000",
backgroundColor: "#ff3300",
text: "Đang khám tổng quát",
textColor: "#1E3A8A",
backgroundColor: "#DBEAFE",
},
{
state: TYPE_STATUS.ToSpecialty,
text: "Chờ khám chuyên khoa",
textColor: "#6B21A8",
backgroundColor: "#E9D5FF",
},
{
state: TYPE_STATUS.PendingPrescription,
text: "Chờ nhận thuốc/kính",
textColor: "#9A3412",
backgroundColor: "#FED7AA",
},
{
state: TYPE_STATUS.Completed,
text: "Hoàn thành",
textColor: "#000",
backgroundColor: "#3d69eb",
textColor: "#166534",
backgroundColor: "#DCFCE7",
},
{
state: TYPE_STATUS.Cancelled,
text: "Đã hủy",
textColor: "#000",
backgroundColor: "#cccccc",
textColor: "#991B1B",
backgroundColor: "#FEE2E2",
},
]}
/>
@@ -27,6 +27,7 @@ interface IUpdateConsul {
diagnosis: string;
treatmentPlan: string;
doctorNotes: string;
isGlassesDelivered: boolean;
}
/* =========================
@@ -39,6 +40,7 @@ const defaultForm: IUpdateConsul = {
diagnosis: "",
treatmentPlan: "",
doctorNotes: "",
isGlassesDelivered: false,
};
/* =========================
@@ -103,6 +105,7 @@ const UpdateConsultation = () => {
diagnosis: consul.diagnosis || "",
treatmentPlan: consul.treatmentPlan || "",
doctorNotes: consul.doctorNotes || "",
isGlassesDelivered: consul.isGlassesDelivered,
});
}, [consulDetailQuery.data]);
@@ -126,6 +129,7 @@ const UpdateConsultation = () => {
diagnosis: form.diagnosis,
treatmentPlan: form.treatmentPlan,
doctorNotes: form.doctorNotes,
isGlassesDelivered: form?.isGlassesDelivered,
}),
});
},
@@ -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 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 }))
}
/>
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;
@@ -0,0 +1 @@
export { default } from "./UpdateSpecialtyClinicId";