mirror of
https://github.com/urosran/cally.git
synced 2025-07-09 22:57:16 +00:00
122 lines
4.4 KiB
TypeScript
122 lines
4.4 KiB
TypeScript
import React, {useCallback, useMemo, useRef, useState} from "react";
|
|
import {View} from "react-native-ui-lib";
|
|
import {DeviceType} from "expo-device";
|
|
import * as Device from "expo-device";
|
|
import {CalendarBody, CalendarContainer, CalendarHeader, CalendarKitHandle} from "@howljs/calendar-kit";
|
|
import {useAtomValue} from "jotai";
|
|
import {selectedUserAtom} from "@/components/pages/calendar/atoms";
|
|
|
|
import {useAuthContext} from "@/contexts/AuthContext";
|
|
import {useGetFamilyMembers} from "@/hooks/firebase/useGetFamilyMembers";
|
|
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 {DetailedCalendarController} from "@/components/pages/calendar/DetailedCalendarController";
|
|
|
|
interface EventCalendarProps {
|
|
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
|
|
} as const;
|
|
|
|
const getContainerProps = (date: Date, customKey: string) => ({
|
|
hourWidth: 70,
|
|
allowPinchToZoom: true,
|
|
useHaptic: true,
|
|
scrollToNow: true,
|
|
initialDate: customKey !== "default" ? customKey : date.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(({
|
|
calendarWidth,
|
|
mode,
|
|
onLoad
|
|
}) => {
|
|
const {profileData} = useAuthContext();
|
|
const {data: familyMembers} = useGetFamilyMembers();
|
|
const {data: events} = useGetEvents();
|
|
const selectedUser = useAtomValue(selectedUserAtom);
|
|
const calendarRef = useRef<CalendarKitHandle>(null);
|
|
const [customKey, setCustomKey] = useState("defaultKey");
|
|
|
|
const memoizedFamilyMembers = useMemo(() => familyMembers || [], [familyMembers]);
|
|
const currentDate = useMemo(() => new Date(), []);
|
|
const containerProps = useMemo(() => getContainerProps(currentDate, customKey), [currentDate, customKey]);
|
|
|
|
const {data: formattedEvents} = useFormattedEvents(events ?? [], currentDate, 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}
|
|
>
|
|
<DetailedCalendarController
|
|
calendarRef={calendarRef}
|
|
setCustomKey={setCustomKey}
|
|
/>
|
|
<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; |