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 '../../commons/WeekDaysNames'; import { CalendarListProps } from '../../calendar-list'; import CalendarContext from '../../expandableCalendar/Context'; import styleConstructor from '../style'; import { toMarkingFormat } from '../../interface'; import { extractCalendarProps } 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; } const NUMBER_OF_PAGES = 50; const DEFAULT_PAGE_HEIGHT = 48; const WeekCalendar = (props: WeekCalendarProps) => { const { current, firstDay = 0, markedDates, allowShadow = true, hideDayNames, theme, calendarWidth, calendarHeight = DEFAULT_PAGE_HEIGHT, 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( // @ts-ignore (pageIndex: number, _prevPage, { scrolledByUser }) => { if (scrolledByUser) { // @ts-ignore context?.setDate(items[pageIndex], UpdateSources.WEEK_SCROLL); } }, [items] ); const reloadPages = useCallback( (pageIndex: number) => { const date = items[pageIndex]; // @ts-ignore setItems(getDatesArray(date, firstDay, NUMBER_OF_PAGES)); }, [items] ); const renderItem = useCallback( (_type: any, item: string) => { // eslint-disable-next-line @typescript-eslint/no-unused-vars const { allowShadow, ...calendarListProps } = props; const { /* style, */ ...others } = extractCalendarProps(calendarListProps); 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: string[] = []; for (let index = -numberOfPages; index <= numberOfPages; index++) { const d = getDate(date, firstDay, index); array.push(d); } return array; }