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;
}