refactor(dateTime): streamline slot handling and improve session management

This commit is contained in:
hamed
2026-07-15 19:16:24 +03:30
parent 07d6526f74
commit d5845bf84d
4 changed files with 55 additions and 51 deletions
+3 -4
View File
@@ -1,8 +1,8 @@
import { Button } from "@mui/material"; import { Button } from "@mui/material";
import React from "react"; import React from "react";
function List({ appo, hour, setHour, value }) { function List({ slots, hour, setHour }) {
const list = appo && appo[value ? "evening" : "morning"]; const list = slots;
const checkHour = (item) => JSON.stringify(item) === JSON.stringify(hour); const checkHour = (item) => JSON.stringify(item) === JSON.stringify(hour);
const isSelectable = (item) => const isSelectable = (item) =>
item.is_available && !(item?.start && item.start * 1000 < Date.now()); item.is_available && !(item?.start && item.start * 1000 < Date.now());
@@ -30,8 +30,7 @@ function List({ appo, hour, setHour, value }) {
} else { } else {
return ( return (
<p className="text-[#525252] text-[14px] md:text-[16px] font-medium py-[56px]"> <p className="text-[#525252] text-[14px] md:text-[16px] font-medium py-[56px]">
در حال حاضر، نوبتی برای ساعتهای {[value ? "بعد از ظهر" : "صبح"]} موجود در حال حاضر، نوبتی برای این شیفت موجود نمیباشد.
نمیباشد.
</p> </p>
); );
} }
+2 -2
View File
@@ -1,7 +1,7 @@
import List from "./List"; import List from "./List";
import Loading from "./Loading"; import Loading from "./Loading";
function Hours({ appo, doctor, hour, setHour, value, nameHours, locationAddress }) { function Hours({ appo, slots, hour, setHour, locationAddress }) {
if (appo === "loading") { if (appo === "loading") {
return <Loading />; return <Loading />;
} else if (typeof appo === "string") { } else if (typeof appo === "string") {
@@ -13,7 +13,7 @@ function Hours({ appo, doctor, hour, setHour, value, nameHours, locationAddress
} else { } else {
return ( return (
<> <>
<List appo={appo} hour={hour} value={value} setHour={setHour} /> <List slots={slots} hour={hour} setHour={setHour} />
{locationAddress && ( {locationAddress && (
<div className="mt-4 p-3 bg-[#F5F5F5] dark:bg-[#2A2A2A] rounded-lg"> <div className="mt-4 p-3 bg-[#F5F5F5] dark:bg-[#2A2A2A] rounded-lg">
<p className="text-[#616161] dark:text-[#A1A1A1] text-[14px] font-medium mb-1"> <p className="text-[#616161] dark:text-[#A1A1A1] text-[14px] font-medium mb-1">
+39 -32
View File
@@ -8,14 +8,15 @@ import { request } from "@/services/response";
import SendAppo from "./SendAppo"; import SendAppo from "./SendAppo";
import { adaptSlots, hasAvailable } from "@/lib/appointmentSlots"; import { adaptSlots, hasAvailable } from "@/lib/appointmentSlots";
const listTab = ["صبح", "بعد از ظهر"];
const nameHours = ["hours_morning", "hours_afternoon"];
function DateTime({ date, doctor, setStep, setSelectedSlot, setSelectedDate }) { 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 sessions = Array.isArray(appo) ? appo : [];
const listTab = sessions.map((s) => s.label);
const currentSlots = sessions[value]?.slots ?? [];
const handleChange = (event, newValue) => { const handleChange = (event, newValue) => {
setHour(); setHour();
setValue(newValue); setValue(newValue);
@@ -33,9 +34,15 @@ function DateTime({ date, doctor, setStep, setSelectedSlot, setSelectedDate }) {
request request
.getAppointmentSlots(doctor.uuid, dateStr) .getAppointmentSlots(doctor.uuid, dateStr)
.then((res) => { .then((res) => {
const slots = adaptSlots(res); const parsed = adaptSlots(res);
setAppo(slots); if (!parsed.length) {
setValue(hasAvailable(slots.morning) || !hasAvailable(slots.evening) ? 0 : 1); setAppo("در حال حاضر، نوبتی برای این روز موجود نمی‌باشد.");
setValue(0);
return;
}
setAppo(parsed);
const firstAvailable = parsed.findIndex((s) => hasAvailable(s.slots));
setValue(firstAvailable >= 0 ? firstAvailable : 0);
}) })
.catch(() => { .catch(() => {
setAppo("در حال حاضر، نوبتی برای این روز موجود نمی‌باشد."); setAppo("در حال حاضر، نوبتی برای این روز موجود نمی‌باشد.");
@@ -46,36 +53,36 @@ function DateTime({ date, doctor, setStep, setSelectedSlot, setSelectedDate }) {
return ( return (
<div className="w-full"> <div className="w-full">
<Tabs {sessions.length > 1 && (
isSm={true} <Tabs
style={{ isSm={sessions.length === 2}
".MuiTabs-indicator": { style={{
height: "4px", ".MuiTabs-indicator": {
borderRadius: "8px", height: "4px",
background: "#F17732", borderRadius: "8px",
}, background: "#F17732",
"& .MuiTabs-flexContainer": { },
borderBottom: "2px solid #EFEFEF", "& .MuiTabs-flexContainer": {
marginBottom: "1px", borderBottom: "2px solid #EFEFEF",
}, marginBottom: "1px",
"& .mui-11pdt05-MuiButtonBase-root-MuiTab-root.Mui-selected": { },
color: "#F17732 !important", "& .mui-11pdt05-MuiButtonBase-root-MuiTab-root.Mui-selected": {
}, color: "#F17732 !important",
"& .MuiButtonBase-root.Mui-selected": { },
color: "#F17732 !important", "& .MuiButtonBase-root.Mui-selected": {
}, color: "#F17732 !important",
}} },
value={value} }}
listTab={listTab} value={value}
handleChange={handleChange} listTab={listTab}
/> handleChange={handleChange}
/>
)}
<Hours <Hours
appo={appo} appo={appo}
slots={currentSlots}
hour={hour} hour={hour}
value={value}
doctor={doctor}
setHour={setHour} setHour={setHour}
nameHours={nameHours}
locationAddress={locationAddress} locationAddress={locationAddress}
/> />
<SendAppo <SendAppo
+11 -13
View File
@@ -1,19 +1,17 @@
const MORNING_END = "12:00";
export function adaptSlots(slotsResponse) { export function adaptSlots(slotsResponse) {
const sessions = slotsResponse?.data?.sessions ?? slotsResponse?.sessions ?? []; const sessions = slotsResponse?.data?.sessions ?? slotsResponse?.sessions ?? [];
const morning = []; // Group slots by the shifts the backend already returns; the front does not
const evening = []; // decide shift boundaries (no hard-coded morning/evening split). Each session
// becomes one tab labelled with its own time range.
sessions.forEach((session) => { return sessions
(session.slots ?? []).forEach((slot) => { .filter((session) => Array.isArray(session.slots) && session.slots.length > 0)
const target = slot.start_time < MORNING_END ? morning : evening; .map((session) => ({
target.push(slot); start_time: session.start_time,
}); end_time: session.end_time,
}); label: `${session.start_time} - ${session.end_time}`,
slots: session.slots,
return { morning, evening }; }));
} }
export function hasAvailable(slots) { export function hasAvailable(slots) {