Files
cally/components/pages/calendar/DetailedCalendar.tsx
Milan Paunovic 580104d052 Month cal changes
2025-01-23 02:16:07 +01:00

134 lines
4.5 KiB
TypeScript

import React, {useCallback, useEffect, useMemo, useRef, useState} from "react";
import {useAuthContext} from "@/contexts/AuthContext";
import {useAtomValue} from "jotai";
import {modeAtom, selectedDateAtom, selectedUserAtom} from "@/components/pages/calendar/atoms";
import {useGetFamilyMembers} from "@/hooks/firebase/useGetFamilyMembers";
import {CalendarBody, CalendarContainer, CalendarHeader, CalendarKitHandle} from "@howljs/calendar-kit";
import {useGetEvents} from "@/hooks/firebase/useGetEvents";
import {useFormattedEvents} from "@/components/pages/calendar/useFormattedEvents";
import {useCalendarControls} from "@/components/pages/calendar/useCalendarControls";
import {EventCell} from "@/components/pages/calendar/EventCell";
import {isToday} from "date-fns";
import {View} from "react-native-ui-lib";
import {DeviceType} from "expo-device";
import * as Device from "expo-device"
import {useAtomCallback} from 'jotai/utils'
interface EventCalendarProps {
calendarHeight: number;
calendarWidth: number;
mode: "week" | "month" | "day" | "3days";
onLoad?: () => void;
}
const HEADER_PROPS = {
dayBarHeight: 60,
headerBottomHeight: 20,
};
const BODY_PROPS = {
showNowIndicator: true,
hourFormat: "h:mm a"
};
const MODE_TO_DAYS = {
'week': 7,
'3days': 3,
'day': 1,
'month': 1
};
const getContainerProps = (selectedDate: Date) => ({
hourWidth: 70,
allowPinchToZoom: true,
useHaptic: true,
scrollToNow: true,
initialDate: selectedDate.toISOString(),
});
const MemoizedEventCell = React.memo(EventCell, (prev, next) => {
return prev.event.id === next.event.id &&
prev.event.lastModified === next.event.lastModified;
});
export const DetailedCalendar: React.FC<EventCalendarProps> = React.memo((
{
calendarHeight,
calendarWidth,
mode,
onLoad
}) => {
const {profileData} = useAuthContext();
const selectedDate = useAtomValue(selectedDateAtom);
const {data: familyMembers} = useGetFamilyMembers();
const calendarRef = useRef<CalendarKitHandle>(null);
const {data: events} = useGetEvents();
const selectedUser = useAtomValue(selectedUserAtom);
const [customKey, setCustomKey] = useState("defaultKey");
const memoizedFamilyMembers = useMemo(() => familyMembers || [], [familyMembers]);
const containerProps = useMemo(() => getContainerProps(selectedDate), [selectedDate]);
const checkModeAndGoToDate = useAtomCallback(useCallback((get) => {
const currentMode = get(modeAtom);
if ((selectedDate && isToday(selectedDate)) || currentMode === "month") {
calendarRef?.current?.goToDate({date: selectedDate});
setCustomKey(selectedDate.toISOString())
}
}, [selectedDate]));
useEffect(() => {
checkModeAndGoToDate();
}, [selectedDate, checkModeAndGoToDate]);
const {data: formattedEvents} = useFormattedEvents(events ?? [], selectedDate, selectedUser);
const {
handlePressEvent,
handlePressCell,
debouncedOnDateChanged
} = useCalendarControls(events ?? []);
const getAttendees = useCallback((event: any) => {
return memoizedFamilyMembers.filter(member => event?.attendees?.includes(member?.uid!));
}, [memoizedFamilyMembers]);
const renderEvent = useCallback((event: any) => {
const attendees = getAttendees(event);
return (
<MemoizedEventCell
event={event}
onPress={handlePressEvent}
attendees={attendees}
/>
);
}, [getAttendees, handlePressEvent]);
return (
<CalendarContainer
ref={calendarRef}
{...containerProps}
numberOfDays={MODE_TO_DAYS[mode]}
calendarWidth={calendarWidth}
onDateChanged={debouncedOnDateChanged}
firstDay={profileData?.firstDayOfWeek === "Mondays" ? 1 : 0}
events={formattedEvents ?? []}
onPressEvent={handlePressEvent}
onPressBackground={handlePressCell}
onLoad={onLoad}
key={customKey}
>
<CalendarHeader {...HEADER_PROPS} />
<CalendarBody
{...BODY_PROPS}
renderEvent={renderEvent}
/>
{Device.deviceType === DeviceType.TABLET && (
<View style={{backgroundColor: 'white', height: '9%', width: '100%'}}/>
)}
</CalendarContainer>
);
});
DetailedCalendar.displayName = 'DetailedCalendar';
export default DetailedCalendar;