feat: create patient record without prior signup
Extend POST /api/v1/patient to resolve user by uuid or mobile, and create a new ROLE_USER (name + optional national code, no password) when no user exists. Admin modal shows a new-patient form on lookup miss. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -142,6 +142,8 @@ function MyPatientsPageInner() {
|
||||
} | null>(null);
|
||||
const [recordNationalCode, setRecordNationalCode] = useState("");
|
||||
const [searchError, setSearchError] = useState("");
|
||||
const [notFound, setNotFound] = useState(false);
|
||||
const [newPatientName, setNewPatientName] = useState("");
|
||||
const mobileInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const servicesTotal = selectedServices.reduce(
|
||||
@@ -285,22 +287,28 @@ function MyPatientsPageInner() {
|
||||
),
|
||||
onSuccess: (res: any) => {
|
||||
setFoundUser(res?.data);
|
||||
setRecordNationalCode(res?.data?.national_code ?? "");
|
||||
setNotFound(false);
|
||||
setSearchError("");
|
||||
},
|
||||
onError: () => {
|
||||
setFoundUser(null);
|
||||
setSearchError("کاربری با این شماره در سیستم یافت نشد");
|
||||
setNotFound(true);
|
||||
setSearchError("");
|
||||
},
|
||||
});
|
||||
|
||||
const createRecordMut = useMutation({
|
||||
mutationFn: (userUuid: string) =>
|
||||
api.post("/api/v1/patient", { user_uuid: userUuid }),
|
||||
mutationFn: (body: Record<string, unknown>) =>
|
||||
api.post("/api/v1/patient", body),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ["patients"] });
|
||||
setCreateRecordOpen(false);
|
||||
setSearchMobile("");
|
||||
setFoundUser(null);
|
||||
setRecordNationalCode("");
|
||||
setNotFound(false);
|
||||
setNewPatientName("");
|
||||
setSearchError("");
|
||||
toast.success("پرونده بیمار ایجاد شد");
|
||||
},
|
||||
@@ -315,13 +323,32 @@ function MyPatientsPageInner() {
|
||||
}
|
||||
setSearchError("");
|
||||
setFoundUser(null);
|
||||
setNotFound(false);
|
||||
searchUserMut.mutate(digits);
|
||||
};
|
||||
|
||||
const handleCreateRecord = () => {
|
||||
if (foundUser) {
|
||||
createRecordMut.mutate({
|
||||
user_uuid: foundUser.uuid,
|
||||
national_code: recordNationalCode || undefined,
|
||||
});
|
||||
} else if (notFound) {
|
||||
createRecordMut.mutate({
|
||||
mobile: searchMobile.replace(/\D/g, ""),
|
||||
name: newPatientName.trim(),
|
||||
national_code: recordNationalCode || undefined,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleCreateRecordClose = () => {
|
||||
setCreateRecordOpen(false);
|
||||
setSearchMobile("");
|
||||
setFoundUser(null);
|
||||
setRecordNationalCode("");
|
||||
setNotFound(false);
|
||||
setNewPatientName("");
|
||||
setSearchError("");
|
||||
};
|
||||
|
||||
@@ -493,12 +520,11 @@ function MyPatientsPageInner() {
|
||||
<button
|
||||
className="btn primary sm"
|
||||
disabled={
|
||||
!foundUser || createRecordMut.isPending
|
||||
}
|
||||
onClick={() =>
|
||||
foundUser &&
|
||||
createRecordMut.mutate(foundUser.uuid)
|
||||
createRecordMut.isPending ||
|
||||
(!foundUser &&
|
||||
!(notFound && newPatientName.trim()))
|
||||
}
|
||||
onClick={handleCreateRecord}
|
||||
>
|
||||
{createRecordMut.isPending
|
||||
? "در حال ایجاد..."
|
||||
@@ -685,6 +711,80 @@ function MyPatientsPageInner() {
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{notFound && (
|
||||
<div
|
||||
style={{
|
||||
marginTop: 16,
|
||||
padding: 14,
|
||||
border: "1px solid var(--border)",
|
||||
borderRadius: "var(--r)",
|
||||
background: "var(--surface)",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: 12,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
fontSize: 12.5,
|
||||
color: "var(--text-3)",
|
||||
lineHeight: 1.7,
|
||||
}}
|
||||
>
|
||||
کاربری با این شماره یافت نشد. برای ثبت بیمار جدید،
|
||||
نام را وارد کنید.
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: 5,
|
||||
}}
|
||||
>
|
||||
<label
|
||||
style={{ fontSize: 12.5, fontWeight: 600 }}
|
||||
>
|
||||
نام و نام خانوادگی *
|
||||
</label>
|
||||
<input
|
||||
className="input"
|
||||
value={newPatientName}
|
||||
onChange={(e) =>
|
||||
setNewPatientName(e.target.value)
|
||||
}
|
||||
placeholder="مثال: محمد محمدی"
|
||||
autoFocus
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: 5,
|
||||
}}
|
||||
>
|
||||
<label
|
||||
style={{ fontSize: 12.5, fontWeight: 600 }}
|
||||
>
|
||||
کد ملی (اختیاری)
|
||||
</label>
|
||||
<input
|
||||
className="input"
|
||||
dir="ltr"
|
||||
inputMode="numeric"
|
||||
maxLength={10}
|
||||
value={recordNationalCode}
|
||||
onChange={(e) =>
|
||||
setRecordNationalCode(
|
||||
e.target.value.replace(/\D/g, ""),
|
||||
)
|
||||
}
|
||||
placeholder="۱۰ رقم"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user