feat(appointment): add city_id to appointment payload and update ProvinceProvider for city context
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# ارسال city_id دامنهی جاری هنگام رزرو نوبت
|
||||
|
||||
## پروژه
|
||||
|
||||
`nobat724_front` (سایت عمومی). **cross-repo**: پرامپت همتا `clinicpro/.claude/prompt/representation-domain-guard-dashboard-settlement.md` است که **اول** اجرا میشود (backend فیلد `city_id` را در `POST /api/v1/appointment` میپذیرد و نمایندهی شهر را برای گاردِ پورسانت ذخیره میکند). این پرامپت front را بعد از آن اجرا کن.
|
||||
|
||||
## زمینه
|
||||
|
||||
هر شهر دامنهی جداگانه دارد و از `data/city.json` تشخیص داده میشود (`getStateInfo().matchedCity` سرور، `ProvinceProvider`/`window.location.hostname` کلاینت). هر شهر `id` دارد (مثلاً اراک `129`) و فیلد `representation_id`. نماینده در backend به همان `city_id` خورده است.
|
||||
|
||||
برای اینکه backend بتواند تشخیص دهد نوبت از **دامنهی نماینده** ثبت شده (شرط لازم برای محاسبهی پورسانت)، سایت باید `city_id` دامنهی جاری را در payload رزرو بفرستد.
|
||||
|
||||
## مشکل / هدف
|
||||
|
||||
در حال حاضر `appointmentPayload` در `components/appointment/detail/SubmitData.js` فیلد `city_id` ندارد. باید `matchedCity.id` دامنهی جاری به آن اضافه شود.
|
||||
|
||||
## فایلهای مرتبط
|
||||
|
||||
| فایل | نقش |
|
||||
|------|-----|
|
||||
| `nobat724_front/components/appointment/detail/SubmitData.js` | ساخت `appointmentPayload` و فراخوانی `postAppointment` |
|
||||
| `nobat724_front/context/ProvinceProvider.js` | منبع client-side شهر جاری (`useProvince`) |
|
||||
| `nobat724_front/lib/getStateInfo.js` | منبع server-side شهر (`matchedCity.id`) |
|
||||
| `nobat724_front/data/city.json` | `id` و `domain` هر شهر |
|
||||
| `nobat724_front/services/response.js` | `postAppointment` (بدون تغییر؛ فقط payload عوض میشود) |
|
||||
|
||||
## وضعیت فعلی
|
||||
|
||||
`components/appointment/detail/SubmitData.js` (پس از تغییرِ قبلیِ national_code/gender):
|
||||
```js
|
||||
const appointmentPayload = {
|
||||
doctor_uuid: doctor.uuid,
|
||||
slot_start: selectedSlot.start,
|
||||
slot_end: selectedSlot.end,
|
||||
for_self: !isForAnother,
|
||||
note: data?.patient_reason?.value || "",
|
||||
patient_national_code: data?.national_code?.value || "",
|
||||
patient_gender: data?.gender?.value?.id || data?.gender?.value || "",
|
||||
...(isForAnother ? { patient_name: ..., patient_mobile: ..., patient_reason: ... } : {}),
|
||||
};
|
||||
const res = await request.postAppointment(appointmentPayload);
|
||||
```
|
||||
|
||||
`ProvinceProvider` (client) شهر را از `window.location.hostname` تشخیص میدهد. باید بررسی شود چه چیزی expose میکند — اگر فقط `isProvinceInclude` دارد، یک getter برای `matchedCity` (یا حداقل `matchedCity.id`) به آن اضافه شود تا کامپوننت کلاینت به `city.id` دسترسی داشته باشد.
|
||||
|
||||
## وظایف
|
||||
|
||||
### ۱. در دسترس قرار دادن city.id در کلاینت
|
||||
|
||||
اگر `useProvince()` فقط `isProvinceInclude` میدهد، آن را گسترش بده تا `matchedCity` (یا `cityId`) هم برگرداند. منطق تطبیق همان `getStateInfo` است: `subdomain = hostname.split('.')[0]`، سپس `citiesData.find(c => c.domain.split('.')[0] === subdomain)`. (در dev، `HOST=yazd-nobat.localhost` ⇒ subdomain = `yazd-nobat`.)
|
||||
|
||||
### ۲. افزودن city_id به payload رزرو
|
||||
|
||||
در `SubmitData.js`:
|
||||
```js
|
||||
import { useProvince } from "@/context/ProvinceProvider";
|
||||
// ...
|
||||
const { matchedCity } = useProvince(); // یا cityId مستقیم
|
||||
|
||||
const appointmentPayload = {
|
||||
doctor_uuid: doctor.uuid,
|
||||
slot_start: selectedSlot.start,
|
||||
slot_end: selectedSlot.end,
|
||||
for_self: !isForAnother,
|
||||
note: data?.patient_reason?.value || "",
|
||||
patient_national_code: data?.national_code?.value || "",
|
||||
patient_gender: data?.gender?.value?.id || data?.gender?.value || "",
|
||||
city_id: matchedCity?.id ?? null, // ← جدید
|
||||
...(isForAnother ? { ... } : {}),
|
||||
};
|
||||
```
|
||||
|
||||
## نکات مهم
|
||||
|
||||
- `city_id` همان `matchedCity.id` از `city.json` است (نه `representation_id` که ممکن است null باشد). backend خودش نمایندهی آن شهر را پیدا میکند.
|
||||
- اگر شهر تشخیص داده نشد یا نماینده نداشت، `city_id` خالی/null ⇒ backend پورسانت محاسبه نمیکند. این رفتار مطلوب است؛ خطا نده.
|
||||
- مبلغ پرداختیِ کاربر تغییر نمیکند؛ این فقط متادیتای رزرو است.
|
||||
- App Router + کامپوننت کلاینت: `useProvince` فقط در client component کار میکند؛ `SubmitData` کلاینت است.
|
||||
- بعد از تغییر: `npm run build` برای صحت. قرارداد `POST /api/v1/appointment` در `clinicpro/docs/api/appointment.md` (سمت backend) بهروز است؛ فقط مطمئن شو نام فیلد `city_id` با backend یکی است.
|
||||
@@ -5,9 +5,11 @@ import ArrowLeftB from "@/components/icons/ArrowLeftB";
|
||||
import { request } from "@/services/response";
|
||||
import Cookies from "js-cookie";
|
||||
import { setAccessToken } from "@/lib/tokenStore";
|
||||
import { useProvince } from "@/context/ProvinceProvider";
|
||||
|
||||
function SubmitData({ setStep, data, prevData, setErrors, doctor, isForAnother, selectedSlot, selectedDate, setAppointmentId, setAppointmentExpiresAt }) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { cityId } = useProvince();
|
||||
const newStep = () => setStep((prev) => prev + 1);
|
||||
|
||||
const refreshAccessToken = async () => {
|
||||
@@ -142,6 +144,8 @@ function SubmitData({ setStep, data, prevData, setErrors, doctor, isForAnother,
|
||||
// کد ملی و جنسیت در هر دو حالت (خودِ بیمار / شخص دیگر) الزامی است.
|
||||
patient_national_code: data?.national_code?.value || "",
|
||||
patient_gender: data?.gender?.value?.id || data?.gender?.value || "",
|
||||
// شناسهی شهرِ دامنهی جاری؛ backend برای گاردِ پورسانت نماینده استفاده میکند.
|
||||
city_id: cityId ?? null,
|
||||
...(isForAnother
|
||||
? {
|
||||
patient_name: [data?.name?.value, data?.family?.value].filter(Boolean).join(" ").trim(),
|
||||
|
||||
@@ -18,7 +18,7 @@ export const ProvinceProvider = ({ children }) => {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<ProvinceContext.Provider value={{ isProvinceInclude }}>
|
||||
<ProvinceContext.Provider value={{ isProvinceInclude, cityId: isProvinceInclude?.id ?? null }}>
|
||||
{children}
|
||||
</ProvinceContext.Provider>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user