fix(appointment): render real slot structure in time picker
The slots API returns data.sessions[].slots[] with start_time (HH:MM), is_available, and start/end unix timestamps — not the morning/evening + time/status shape the UI assumed. Add lib/appointmentSlots.js to flatten sessions into morning/evening by start_time, fetch with doctor.uuid, and read item.start_time / item.is_available in the slot grid. Derive the clinic address from the already-loaded doctor.address by location_id instead of a separate auth-required call. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -12,7 +12,7 @@ function List({ appo, hour, setHour, value }) {
|
|||||||
<li key={idx}>
|
<li key={idx}>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => setHour(item)}
|
onClick={() => setHour(item)}
|
||||||
disabled={item.status !== "available"}
|
disabled={!item.is_available}
|
||||||
className={`
|
className={`
|
||||||
!w-full !rounded-[8px] !bg-[#EFEFEF] !flex !justify-center !items-center !py-[10px] !px-[14px] !h-[40px] md:!h-[42px] lg:!h-[44px]
|
!w-full !rounded-[8px] !bg-[#EFEFEF] !flex !justify-center !items-center !py-[10px] !px-[14px] !h-[40px] md:!h-[42px] lg:!h-[44px]
|
||||||
${checkHour(item) ? "!bg-[#F79463] " : ""}
|
${checkHour(item) ? "!bg-[#F79463] " : ""}
|
||||||
@@ -21,11 +21,11 @@ function List({ appo, hour, setHour, value }) {
|
|||||||
<p
|
<p
|
||||||
className={`
|
className={`
|
||||||
text-[16px] font-semibold text-[#525252]
|
text-[16px] font-semibold text-[#525252]
|
||||||
${item.status === "available" ? "text-[#525252]" : "text-[#D7D7D7]"}
|
${item.is_available ? "text-[#525252]" : "text-[#D7D7D7]"}
|
||||||
${checkHour(item) ? "!text-[#FAFAFA] " : ""}
|
${checkHour(item) ? "!text-[#FAFAFA] " : ""}
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
{item.time}
|
{item.start_time}
|
||||||
</p>
|
</p>
|
||||||
</Button>
|
</Button>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import Hours from "./hours";
|
|||||||
import Tabs from "../../Tabs";
|
import Tabs from "../../Tabs";
|
||||||
import { request } from "@/services/response";
|
import { request } from "@/services/response";
|
||||||
import SendAppo from "./SendAppo";
|
import SendAppo from "./SendAppo";
|
||||||
|
import { adaptSlots, hasAvailable } from "@/lib/appointmentSlots";
|
||||||
|
|
||||||
const listTab = ["صبح", "بعد از ظهر"];
|
const listTab = ["صبح", "بعد از ظهر"];
|
||||||
const nameHours = ["hours_morning", "hours_afternoon"];
|
const nameHours = ["hours_morning", "hours_afternoon"];
|
||||||
@@ -13,63 +14,33 @@ function DateTime({ date, doctor, setStep, setSelectedSlot, setSelectedDate }) {
|
|||||||
const [value, setValue] = useState(0);
|
const [value, setValue] = useState(0);
|
||||||
const [hour, setHour] = useState();
|
const [hour, setHour] = useState();
|
||||||
const [appo, setAppo] = useState("تاریخ مورد نظرتان را انتخاب کنید.");
|
const [appo, setAppo] = useState("تاریخ مورد نظرتان را انتخاب کنید.");
|
||||||
const [locationAddress, setLocationAddress] = useState(null);
|
|
||||||
|
|
||||||
const handleChange = (event, newValue) => {
|
const handleChange = (event, newValue) => {
|
||||||
setHour();
|
setHour();
|
||||||
setValue(newValue);
|
setValue(newValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
// دریافت آدرس بر اساس location_id وقتی ساعت انتخاب میشود
|
const locationAddress = hour?.location_id
|
||||||
useEffect(() => {
|
? doctor?.address?.find((a) => String(a.id) === String(hour.location_id))?.address ?? null
|
||||||
if (hour && hour.location_id) {
|
: null;
|
||||||
request
|
|
||||||
.getDoctorAddress(hour.location_id)
|
|
||||||
.then((res) => {
|
|
||||||
setLocationAddress(res.address);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error("Error fetching address:", err);
|
|
||||||
setLocationAddress(null);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setLocationAddress(null);
|
|
||||||
}
|
|
||||||
}, [hour]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (date && doctor?.id) {
|
if (date && doctor?.uuid) {
|
||||||
setAppo("loading");
|
setAppo("loading");
|
||||||
setHour();
|
setHour();
|
||||||
request
|
request
|
||||||
.getAppointment(doctor.id, date)
|
.getAppointmentSlots(doctor.uuid, date)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setAppo(res);
|
const slots = adaptSlots(res);
|
||||||
|
setAppo(slots);
|
||||||
// بررسی وجود اسلاتهای available در صبح و عصر
|
setValue(hasAvailable(slots.morning) || !hasAvailable(slots.evening) ? 0 : 1);
|
||||||
const hasAvailableMorning = res.morning?.some(slot => slot.status === "available");
|
|
||||||
const hasAvailableEvening = res.evening?.some(slot => slot.status === "available");
|
|
||||||
|
|
||||||
// اگر هر دو صبح و عصر اسلات available داشته باشند، صبح را نمایش بده
|
|
||||||
if (hasAvailableMorning && hasAvailableEvening) {
|
|
||||||
setValue(0);
|
|
||||||
}
|
|
||||||
// اگر فقط صبح اسلات available داشته باشد
|
|
||||||
else if (hasAvailableMorning && !hasAvailableEvening) {
|
|
||||||
setValue(0);
|
|
||||||
}
|
|
||||||
// اگر فقط عصر اسلات available داشته باشد یا هیچ کدام available نداشته باشند، عصر را نمایش بده
|
|
||||||
else {
|
|
||||||
setValue(1);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch(() => {
|
||||||
setAppo("در حال حاضر، نوبتی برای ساعتهای صبح موجود نمیباشد.");
|
setAppo("در حال حاضر، نوبتی برای این روز موجود نمیباشد.");
|
||||||
// در صورت خطا هم عصر را نمایش بده
|
setValue(0);
|
||||||
setValue(1);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [date, doctor?.id]);
|
}, [date, doctor?.uuid]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
const MORNING_END = "12:00";
|
||||||
|
|
||||||
|
export function adaptSlots(slotsResponse) {
|
||||||
|
const sessions = slotsResponse?.data?.sessions ?? slotsResponse?.sessions ?? [];
|
||||||
|
|
||||||
|
const morning = [];
|
||||||
|
const evening = [];
|
||||||
|
|
||||||
|
sessions.forEach((session) => {
|
||||||
|
(session.slots ?? []).forEach((slot) => {
|
||||||
|
const target = slot.start_time < MORNING_END ? morning : evening;
|
||||||
|
target.push(slot);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return { morning, evening };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hasAvailable(slots) {
|
||||||
|
return Array.isArray(slots) && slots.some((slot) => slot.is_available);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user