diff --git a/app/component/date/datePicker/index.js b/app/component/date/datePicker/index.js index 3d1ad35..dde70e8 100644 --- a/app/component/date/datePicker/index.js +++ b/app/component/date/datePicker/index.js @@ -1,128 +1,70 @@ "use client"; -import { useEffect, useRef, useState } from "react"; -import FirstDatePicker from "./date/FirstDatePicker"; -import SecondDatePicker from "./date/SecondDatePicker"; -import { dateToTimestamp } from "@/helper"; +import { useEffect, useState } from "react"; import moment from "moment-jalaali"; import "moment-timezone"; +import { dateToTimestamp } from "@/helper"; +import InlineJalaliMonth from "@/components/common/InlineJalaliMonth"; function DatePicker({ setDate, disabledDates = [] }) { - const nextIconDatePickerF = useRef(); - const prevIconDatePickerF = useRef(); - const nextIconDatePickerS = useRef(); - const prevIconDatePickerS = useRef(); - - const [startDate, setStartDate] = useState(null); - const [endDate, setEndDate] = useState(); - const [loading, setLoading] = useState(true); + const [baseMonth, setBaseMonth] = useState(moment().tz("Asia/Tehran")); + const [selectedDate, setSelectedDate] = useState(null); const [autoSelected, setAutoSelected] = useState(false); - const handleStartDateChange = (date, e) => { - if (date) { - setDate(dateToTimestamp(date)); - setEndDate(null); - setStartDate(date); - } + const isDisabled = (date) => { + const day = moment(date).startOf("day"); + if (day.isBefore(moment().startOf("day"))) return true; + return disabledDates.some((ts) => day.isSame(moment.unix(ts).startOf("day"))); }; - const handleEndDateChange = (date) => { - if (date) { - setDate(dateToTimestamp(date)); - setEndDate(date); - setStartDate(null); - } - }; - - - const handleDisableDate = (e) => { - const date = moment(e).startOf("day"); - const today = moment().startOf("day"); - - if (date.isBefore(today)) return true; - - if ( - disabledDates.some((ts) => date.isSame(moment.unix(ts).startOf("day"))) - ) { - return true; - } - - return false; + const selectDay = (date) => { + if (isDisabled(date)) return; + setSelectedDate(date); + setDate(dateToTimestamp(date)); }; useEffect(() => { - // تنظیم loading به false بعد از یک تاخیر کوتاه - setTimeout(() => { - setLoading(false); - }, 1000); + if (autoSelected) return; - if (nextIconDatePickerS.current) { - nextIconDatePickerS.current.click(); - } - }, [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); + const today = moment().tz("Asia/Tehran"); + for (let i = 0; i <= 30; i++) { + const candidate = today.clone().add(i, "days"); + if (!isDisabled(candidate)) { + setSelectedDate(candidate); + setBaseMonth(candidate.clone()); + setDate(candidate.clone().startOf("day").unix()); 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; - } - } + break; } } - }, [loading, disabledDates, autoSelected, setDate]); + }, [disabledDates, autoSelected, setDate]); + + const secondMonth = moment(baseMonth).add(1, "jMonth"); return ( -
- - +
+
+ setBaseMonth(moment(baseMonth).add(1, "jMonth"))} + onPrev={() => setBaseMonth(moment(baseMonth).subtract(1, "jMonth"))} + /> +
+
+ setBaseMonth(moment(baseMonth).subtract(1, "jMonth"))} + onNext={() => setBaseMonth(moment(baseMonth).add(1, "jMonth"))} + /> +
); } diff --git a/components/common/InlineJalaliMonth.js b/components/common/InlineJalaliMonth.js new file mode 100644 index 0000000..439bdb1 --- /dev/null +++ b/components/common/InlineJalaliMonth.js @@ -0,0 +1,118 @@ +"use client"; + +import moment from "moment-jalaali"; + +moment.loadPersian({ dialect: "persian-modern", usePersianDigits: false }); + +const WEEKDAYS = ["شنبه", "۱ شنبه", "۲ شنبه", "۳ شنبه", "۴ شنبه", "۵ شنبه", "جمعه"]; +const MONTHS = [ + "فروردین", + "اردیبهشت", + "خرداد", + "تیر", + "مرداد", + "شهریور", + "مهر", + "آبان", + "آذر", + "دی", + "بهمن", + "اسفند", +]; + +function buildDays(displayDate) { + const year = displayDate.jYear(); + const month = displayDate.jMonth(); + const daysInMonth = moment.jDaysInMonth(year, month); + const firstDayOfMonth = moment(`${year}/${month + 1}/1`, "jYYYY/jM/jD").day(); + const startOffset = (firstDayOfMonth + 1) % 7; + + const days = []; + for (let i = 0; i < startOffset; i++) days.push(null); + for (let day = 1; day <= daysInMonth; day++) days.push(day); + return days; +} + +function InlineJalaliMonth({ + displayDate, + selectedDate, + onSelectDay, + isDisabled, + onPrev, + onNext, + showPrev = true, + showNext = true, +}) { + const days = buildDays(displayDate); + + return ( +
+
+ +

+ {MONTHS[displayDate.jMonth()]} {displayDate.jYear()} +

+ +
+ +
+ {WEEKDAYS.map((label, idx) => ( + + {label} + + ))} +
+ +
+ {days.map((day, index) => { + if (!day) return ; + + const dayDate = moment(displayDate).jDate(day); + const isFriday = dayDate.day() === 5; + const disabled = isDisabled(dayDate); + const selected = + selectedDate && + dayDate.jYear() === selectedDate.jYear() && + dayDate.jMonth() === selectedDate.jMonth() && + dayDate.jDate() === selectedDate.jDate(); + + return ( + + ); + })} +
+
+ ); +} + +export default InlineJalaliMonth;