From fdce888e0e02b5d5fdcb75152573b4c0799f8a10 Mon Sep 17 00:00:00 2001 From: hamed <15238-genius.ha@users.noreply.drupalcode.org> Date: Sun, 12 Jul 2026 22:00:33 +0330 Subject: [PATCH] feat(patient): edit patient basic info (doctor/clinic/secretary) Add PATCH /api/v1/patient/{uuid} to update User.realName + UserProfile demographic/insurance fields (mobile stays immutable, national_code uniqueness enforced). Expose name/family separately in profile payload. Add edit modal in my-patients. Update patient.md. Co-Authored-By: Claude Opus 4.8 --- assets/admin/pages/MyPatientsPage.tsx | 153 ++++++++++++++++++- assets/admin/types/index.ts | 4 + docs/api/patient.md | 59 +++++++ src/Patient/Controller/PatientController.php | 89 +++++++++++ 4 files changed, 304 insertions(+), 1 deletion(-) diff --git a/assets/admin/pages/MyPatientsPage.tsx b/assets/admin/pages/MyPatientsPage.tsx index e1e7557c..33ef7467 100644 --- a/assets/admin/pages/MyPatientsPage.tsx +++ b/assets/admin/pages/MyPatientsPage.tsx @@ -151,6 +151,15 @@ function MyPatientsPageInner() { const [newPatientName, setNewPatientName] = useState(""); const mobileInputRef = useRef(null); + const EMPTY_EDIT = { + name: "", family: "", national_code: "", gender: "", blood_type: "", + marital_status: "", job: "", home_phone: "", work_phone: "", address: "", + basic_insurance_id: "", supplementary_insurance_id: "", + }; + const [editOpen, setEditOpen] = useState(false); + const [editForm, setEditForm] = useState>(EMPTY_EDIT); + const setEditField = (k: string, v: string) => setEditForm((f) => ({ ...f, [k]: v })); + const servicesTotal = selectedServices.reduce( (sum, s) => sum + s.price_rials, 0, @@ -262,6 +271,60 @@ function MyPatientsPageInner() { } }; + const openEditInfo = () => { + const p = patientProfile; + setEditForm({ + name: p?.name ?? "", + family: p?.family ?? "", + national_code: p?.national_code ?? "", + gender: p?.gender ?? "", + blood_type: p?.blood_type ?? "", + marital_status: p?.marital_status ?? "", + job: p?.job ?? "", + home_phone: p?.home_phone ?? "", + work_phone: p?.work_phone ?? "", + address: p?.address ?? "", + basic_insurance_id: p?.basic_insurance_id != null ? String(p.basic_insurance_id) : "", + supplementary_insurance_id: p?.supplementary_insurance_id != null ? String(p.supplementary_insurance_id) : "", + }); + setEditOpen(true); + }; + + const updatePatientMut = useMutation({ + mutationFn: (body: object) => + api.patch(`/api/v1/patient/${selectedRecord!.uuid}`, body), + onSuccess: () => { + qc.invalidateQueries({ queryKey: ["patient-detail", selectedRecord?.uuid] }); + qc.invalidateQueries({ queryKey: ["patients"] }); + setEditOpen(false); + toast.success("اطلاعات بیمار به‌روزرسانی شد"); + }, + onError: (e: any) => { + toast.error(e?.message || "خطا در به‌روزرسانی اطلاعات بیمار"); + }, + }); + + const submitEditInfo = () => { + if (!editForm.name.trim()) { + toast.error("نام بیمار الزامی است"); + return; + } + updatePatientMut.mutate({ + name: editForm.name.trim(), + family: editForm.family.trim() || null, + national_code: editForm.national_code.trim(), + gender: editForm.gender || null, + blood_type: editForm.blood_type.trim() || null, + marital_status: editForm.marital_status || null, + job: editForm.job.trim() || null, + home_phone: editForm.home_phone.trim() || null, + work_phone: editForm.work_phone.trim() || null, + address: editForm.address.trim() || null, + basic_insurance_id: editForm.basic_insurance_id ? Number(editForm.basic_insurance_id) : null, + supplementary_insurance_id: editForm.supplementary_insurance_id ? Number(editForm.supplementary_insurance_id) : null, + }); + }; + const createSessionMut = useMutation({ mutationFn: (body: object) => api.post(`/api/v1/patient/${selectedRecord!.uuid}/session`, body), @@ -924,7 +987,12 @@ function MyPatientsPageInner() { {detailTab === "info" && patientProfile && (
-
اطلاعات بیمار
+
+
اطلاعات بیمار
+ +
{([ ["نام کامل", patientProfile.full_name], @@ -951,6 +1019,89 @@ function MyPatientsPageInner() {
)} + setEditOpen(false)} + footer={ + <> + + + + } + > +
+
+ + setEditField("name", e.target.value)} /> +
+
+ + setEditField("family", e.target.value)} /> +
+
+ + setEditField("national_code", e.target.value.replace(/\D/g, ""))} /> +
+
+ + +
+
+ + setEditField("blood_type", e.target.value)} /> +
+
+ + +
+
+ + setEditField("job", e.target.value)} /> +
+
+ + setEditField("home_phone", e.target.value)} /> +
+
+ + setEditField("work_phone", e.target.value)} /> +
+
+ + +
+
+ + +
+
+
+ +