diff --git a/packages/ui/src/components/ui/horizontal-calendar.tsx b/packages/ui/src/components/ui/horizontal-calendar.tsx index 13f6f63..de39d87 100644 --- a/packages/ui/src/components/ui/horizontal-calendar.tsx +++ b/packages/ui/src/components/ui/horizontal-calendar.tsx @@ -2,115 +2,61 @@ import { cn } from '../../lib/utils'; import { Button } from '../ui/button'; -import { addDays, format, isSameDay, subDays } from 'date-fns'; +import { + addMonths, + eachDayOfInterval, + endOfMonth, + format, + isSameDay, + startOfMonth, +} from 'date-fns'; import { ru } from 'date-fns/locale'; import { ChevronLeft, ChevronRight } from 'lucide-react'; -import { useEffect, useMemo, useRef, useState } from 'react'; +import { useMemo, useRef, useState } from 'react'; type HorizontalCalendarProps = { readonly className?: string; - readonly numberOfDays?: number; - readonly numberOfDaysBefore?: number; readonly onDateChange: (date: Date) => void; readonly selectedDate: Date; }; export function HorizontalCalendar({ className, - numberOfDays = 14, - numberOfDaysBefore = 7, onDateChange, selectedDate, }: HorizontalCalendarProps) { const scrollRef = useRef(null); - const [baseDate, setBaseDate] = useState(addDays(new Date(), -numberOfDaysBefore)); - const [currentMonthDate, setCurrentMonthDate] = useState(new Date()); + const [currentMonthDate, setCurrentMonthDate] = useState(startOfMonth(new Date())); + // Получаем список всех дней текущего месяца const dates = useMemo(() => { - return Array.from({ length: numberOfDays }, (_, index) => { - return addDays(baseDate, index); + return eachDayOfInterval({ + end: endOfMonth(currentMonthDate), + start: startOfMonth(currentMonthDate), }); - }, [baseDate, numberOfDays]); + }, [currentMonthDate]); - const updateCurrentMonth = (newBaseDate: Date) => { - setBaseDate(newBaseDate); - setCurrentMonthDate(newBaseDate); - setTimeout(() => { - if (scrollRef.current) { - scrollRef.current.scrollLeft = 0; - } - }, 0); + const scrollToStart = () => { + if (scrollRef.current) { + scrollRef.current.scrollTo({ + behavior: 'smooth', + left: 0, + }); + } }; const scrollPrevious = () => { - const newDate = subDays(baseDate, numberOfDays); - updateCurrentMonth(newDate); + const newDate = addMonths(currentMonthDate, -1); + setCurrentMonthDate(newDate); + setTimeout(scrollToStart, 0); }; const scrollNext = () => { - const newDate = addDays(baseDate, numberOfDays); - updateCurrentMonth(newDate); + const newDate = addMonths(currentMonthDate, 1); + setCurrentMonthDate(newDate); + setTimeout(scrollToStart, 0); }; - // Обработчик scroll — вычисляет дату ближайшую к левому краю - const handleScroll = () => { - const container = scrollRef.current; - if (!container) return; - - const children = Array.from(container.children) as HTMLElement[]; - - let closestChild: HTMLElement | null = null; - let minOffset = Infinity; - - for (const child of children) { - const offset = Math.abs(child.offsetLeft - container.scrollLeft); - if (offset < minOffset) { - minOffset = offset; - closestChild = child; - } - } - - if (closestChild) { - const dateString = closestChild.dataset.date; - if (dateString) { - const date = new Date(dateString); - setCurrentMonthDate(date); - } - } - }; - - useEffect(() => { - const scrollElement = scrollRef.current; - if (scrollElement) { - scrollElement.addEventListener('scroll', handleScroll, { passive: true }); - } - - return () => { - if (scrollElement) { - scrollElement.removeEventListener('scroll', handleScroll); - } - }; - }, []); - - useEffect(() => { - const container = scrollRef.current; - if (!container) return; - - const selectedChild = container.querySelector( - `[data-date="${selectedDate.toISOString()}"]`, - ) as HTMLElement; - if (selectedChild) { - // Прокрутка так, чтобы элемент оказался в центре - const offsetLeft = selectedChild.offsetLeft; - const centerOffset = offsetLeft - container.clientWidth / 2 + selectedChild.clientWidth / 2; - - container.scrollTo({ - behavior: 'auto', // можно 'smooth', если хочешь плавно - left: centerOffset, - }); - } - }, []); // <- только при монтировании - return (
@@ -131,6 +77,7 @@ export function HorizontalCalendar({
+
{dates.map((date) => (