refactor: enhance date selection logic in DatePicker and update appointment request parameters

This commit is contained in:
hamed
2025-11-17 14:18:15 +03:30
parent 63d968be1e
commit 1e510a84b1
5 changed files with 79 additions and 23 deletions
+43
View File
@@ -5,6 +5,7 @@ import FirstDatePicker from "./date/FirstDatePicker";
import SecondDatePicker from "./date/SecondDatePicker"; import SecondDatePicker from "./date/SecondDatePicker";
import { dateToTimestamp } from "@/helper"; import { dateToTimestamp } from "@/helper";
import moment from "moment-jalaali"; import moment from "moment-jalaali";
import "moment-timezone";
function DatePicker({ setDate, disabledDates = [] }) { function DatePicker({ setDate, disabledDates = [] }) {
const nextIconDatePickerF = useRef(); const nextIconDatePickerF = useRef();
@@ -15,6 +16,7 @@ function DatePicker({ setDate, disabledDates = [] }) {
const [startDate, setStartDate] = useState(null); const [startDate, setStartDate] = useState(null);
const [endDate, setEndDate] = useState(); const [endDate, setEndDate] = useState();
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [autoSelected, setAutoSelected] = useState(false);
const handleStartDateChange = (date, e) => { const handleStartDateChange = (date, e) => {
if (date) { if (date) {
@@ -59,6 +61,47 @@ function DatePicker({ setDate, disabledDates = [] }) {
} }
}, [nextIconDatePickerS, disabledDates]); }, [nextIconDatePickerS, disabledDates]);
// انتخاب خودکار امروز یا نزدیک‌ترین روز قابل انتخاب
useEffect(() => {
if (!loading && !autoSelected && disabledDates) {
const today = moment().tz("Asia/Tehran");
const todayTimestamp = moment().tz("Asia/Tehran").startOf("day").unix();
// بررسی اینکه امروز قابل انتخاب است یا نه
const isTodayDisabled = disabledDates.some((ts) =>
moment.unix(ts).startOf("day").isSame(today.startOf("day"))
);
if (!isTodayDisabled) {
// امروز قابل انتخاب است
setStartDate(today);
setDate(todayTimestamp);
setAutoSelected(true);
} else {
// پیدا کردن نزدیک‌ترین روز قابل انتخاب
let nearestDate = null;
let daysToCheck = 30; // بررسی 30 روز آینده
for (let i = 1; i <= daysToCheck; i++) {
const futureDate = moment().tz("Asia/Tehran").add(i, "days");
const futureDateTimestamp = futureDate.clone().startOf("day").unix();
const isFutureDateDisabled = disabledDates.some((ts) =>
moment.unix(ts).startOf("day").isSame(futureDate.startOf("day"))
);
if (!isFutureDateDisabled) {
nearestDate = futureDate;
setStartDate(futureDate);
setDate(futureDateTimestamp);
setAutoSelected(true);
break;
}
}
}
}
}, [loading, disabledDates, autoSelected, setDate]);
return ( return (
<div className="datePickerApt flex items-start custom-datepicker justify-evenly w-full"> <div className="datePickerApt flex items-start custom-datepicker justify-evenly w-full">
<FirstDatePicker <FirstDatePicker
+1 -1
View File
@@ -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.status !== "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] " : ""}
+22 -9
View File
@@ -4,15 +4,12 @@ import { useEffect, useState } from "react";
import Hours from "./hours"; import Hours from "./hours";
import Tabs from "../../Tabs"; import Tabs from "../../Tabs";
import { request } from "@/services/response"; import { request } from "@/services/response";
import { useParams } from "next/navigation";
import SendAppo from "./SendAppo"; import SendAppo from "./SendAppo";
const listTab = ["صبح", "بعد از ظهر"]; const listTab = ["صبح", "بعد از ظهر"];
const nameHours = ["hours_morning", "hours_afternoon"]; const nameHours = ["hours_morning", "hours_afternoon"];
function DateTime({ date, doctor, setStep }) { function DateTime({ date, doctor, setStep }) {
const params = useParams();
const doctorId = params.doctorId;
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("تاریخ مورد نظرتان را انتخاب کنید.");
@@ -23,22 +20,38 @@ function DateTime({ date, doctor, setStep }) {
}; };
useEffect(() => { useEffect(() => {
if (date) { if (date && doctor?.id) {
setAppo("loading"); setAppo("loading");
setHour(); setHour();
request request
.getAppointment(doctorId, date) .getAppointment(doctor.id, date)
.then((res) => { .then((res) => {
setAppo(res); setAppo(res);
if (res.morning?.length && res.evening?.length) setValue(0);
else if (res.morning?.length && value !== 0) setValue(0); // بررسی وجود اسلات‌های available در صبح و عصر
else if (res.evening?.length && value !== 1) setValue(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((err) => {
setAppo("در حال حاضر، نوبتی برای ساعت‌های صبح موجود نمی‌باشد."); setAppo("در حال حاضر، نوبتی برای ساعت‌های صبح موجود نمی‌باشد.");
// در صورت خطا هم عصر را نمایش بده
setValue(1);
}); });
} }
}, [date]); }, [date, doctor?.id]);
return ( return (
<div className="w-full"> <div className="w-full">
+12 -12
View File
@@ -1,6 +1,7 @@
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import Cookies from "js-cookie"; import Cookies from "js-cookie";
import moment from "moment-jalaali"; import moment from "moment-jalaali";
import "moment-timezone";
// Data // Data
import specialties from "@/data/specialties.json"; import specialties from "@/data/specialties.json";
@@ -153,9 +154,9 @@ export function clearFilterParams(router, listRemove) {
router.push(newUrl); router.push(newUrl);
} }
export function clearDoctorClinicParams(router,slug){ export function clearDoctorClinicParams(router, slug) {
const clinicslug=slug; const clinicslug = slug;
const newUrl = `/clinic/${clinicslug}`; const newUrl = `/clinic/${clinicslug}`;
router.push(newUrl) router.push(newUrl)
} }
@@ -249,12 +250,11 @@ export const removeTokenHead = {
}; };
export const dateToTimestamp = (date) => { export const dateToTimestamp = (date) => {
const gregorianMoment = date.clone().locale("fa"); // تنظیم timezone به تهران
const tehranMoment = date.clone().tz("Asia/Tehran").startOf("day");
// Get the Unix timestamp in milliseconds // Get the Unix timestamp in seconds
const unixTimestamp = gregorianMoment.valueOf(); const inSeconde = tehranMoment.unix();
const inSeconde = unixTimestamp / 1000;
return inSeconde; return inSeconde;
}; };
@@ -322,8 +322,8 @@ export const QueryForDoctorsFilter = (newFilter) => {
return query; return query;
}; };
export const QueryForClinicDoctorFilter=(newFilter)=>{ export const QueryForClinicDoctorFilter = (newFilter) => {
const query = {}; const query = {};
// 🔹 active => only when value === 1 // 🔹 active => only when value === 1
if (newFilter.active === 1) { if (newFilter.active === 1) {
@@ -405,8 +405,8 @@ export const QueryForDoctorsReq = (newFilter) => {
return params; return params;
}; };
export const QueryForDoctorsClinicReq=(newFilter)=>{ export const QueryForDoctorsClinicReq = (newFilter) => {
const params = {}; const params = {};
if (newFilter.active === 1) params.active = 1; if (newFilter.active === 1) params.active = 1;
+1 -1
View File
@@ -68,7 +68,7 @@ export const request = {
api.delete(`api/v1/appointment-settings/weekly-schedule/${uuid}`), api.delete(`api/v1/appointment-settings/weekly-schedule/${uuid}`),
getAppointment: (doctor_id, date) => getAppointment: (doctor_id, date) =>
api.get( api.get(
`api/v1/appointment-slots?doctor_id=${doctor_id}&date=${date}`, `api/v1/appointment-slots?date=${date}&doctor_id=${doctor_id}`,
removeTokenHead removeTokenHead
), ),
postAppointment: (data) => api.post(`api/v1/appointment`, data), postAppointment: (data) => api.post(`api/v1/appointment`, data),