import React, {useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react'; import {View} from 'react-native'; import XDate from 'xdate'; import InfiniteList from '../../infinite-list'; import Week from '../week'; import WeekDaysNames from './WeekDaysNames'; import {CalendarListProps} from '../../calendar-list'; import CalendarContext from '../../expandableCalendar/Context'; import styleConstructor from '../style'; import {toMarkingFormat} from '../../interface'; import {extractComponentProps} from '../../componentUpdater'; import constants from '../../commons/constants'; import {UpdateSources} from '../commons'; import {sameWeek} from '../../dateutils'; import {DateData} from '../../types'; export interface WeekCalendarProps extends CalendarListProps { /** whether to have shadow/elevation for the calendar */ allowShadow?: boolean; /** whether to hide the names of the week days */ hideDayNames?: boolean; } const NUMBER_OF_PAGES = 50; const WeekCalendar = (props: WeekCalendarProps) => { const {current, firstDay = 0, markedDates, allowShadow = true, hideDayNames, theme, calendarWidth, testID} = props; const context = useContext(CalendarContext); const {date, updateSource} = context; const style = useRef(styleConstructor(theme)); const list = useRef(); const [items, setItems] = useState(getDatesArray(current || date, firstDay, NUMBER_OF_PAGES)); const extraData = { current, date: context.date, firstDay }; const containerWidth = calendarWidth || constants.screenWidth; const weekStyle = useMemo(() => { return [{width: containerWidth}, props.style]; }, [containerWidth, props.style]); useEffect(() => { if (updateSource !== UpdateSources.WEEK_SCROLL) { const pageIndex = items.findIndex(item => sameWeek(item, date, firstDay)); // @ts-expect-error list.current?.scrollToOffset?.(pageIndex * containerWidth, 0, false); } }, [date]); const onDayPress = useCallback( (dateData: DateData) => { context.setDate?.(dateData.dateString, UpdateSources.DAY_PRESS); props.onDayPress?.(dateData); }, [props.onDayPress] ); const onPageChange = useCallback( (pageIndex: number, _prevPage, {scrolledByUser}) => { if (scrolledByUser) { context?.setDate(items[pageIndex], UpdateSources.WEEK_SCROLL); } }, [items] ); const reloadPages = useCallback( pageIndex => { const date = items[pageIndex]; setItems(getDatesArray(date, firstDay, NUMBER_OF_PAGES)); }, [items] ); const renderItem = useCallback( (_type: any, item: string) => { const {/* style, */ ...others} = extractComponentProps(Week, props); const isSameWeek = sameWeek(item, date, firstDay); return ( ); }, [date, markedDates] ); return ( {!hideDayNames && ( )} ); }; export default WeekCalendar; // function getDate({current, context, firstDay = 0}: WeekCalendarProps, weekIndex: number) { function getDate(date: string, firstDay: number, weekIndex: number) { // const d = new XDate(current || context.date); const d = new XDate(date); // get the first day of the week as date (for the on scroll mark) let dayOfTheWeek = d.getDay(); if (dayOfTheWeek < firstDay && firstDay > 0) { dayOfTheWeek = 7 + dayOfTheWeek; } // leave the current date in the visible week as is const dd = weekIndex === 0 ? d : d.addDays(firstDay - dayOfTheWeek); const newDate = dd.addWeeks(weekIndex); return toMarkingFormat(newDate); } // function getDatesArray(args: WeekCalendarProps, numberOfPages = NUMBER_OF_PAGES) => { function getDatesArray(date: string, firstDay: number, numberOfPages = NUMBER_OF_PAGES) { const array = []; for (let index = -numberOfPages; index <= numberOfPages; index++) { const d = getDate(date, firstDay, index); array.push(d); } return array; }