Files
cally/components/pages/calendar/EventCalendar.tsx
2024-10-20 16:03:46 +02:00

147 lines
4.4 KiB
TypeScript

import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {Calendar} from "react-native-big-calendar";
import {ActivityIndicator, StyleSheet, View} from "react-native";
import {useGetEvents} from "@/hooks/firebase/useGetEvents";
import {useAtom, useSetAtom} from "jotai";
import {
editVisibleAtom,
eventForEditAtom,
modeAtom,
selectedDateAtom,
selectedNewEventDateAtom
} from "@/components/pages/calendar/atoms";
import {useAuthContext} from "@/contexts/AuthContext";
import {CalendarEvent} from "@/components/pages/calendar/interfaces";
interface EventCalendarProps {
calendarHeight: number;
// WAS USED FOR SCROLLABLE CALENDARS, PERFORMANCE WAS NOT OPTIMAL
calendarWidth: number;
}
const getTotalMinutes = () => {
const date = new Date();
return Math.abs(date.getUTCHours() * 60 + date.getUTCMinutes() - 200);
}
export const EventCalendar: React.FC<EventCalendarProps> = React.memo(({calendarHeight}) => {
const {data: events, isLoading} = useGetEvents();
const {profileData} = useAuthContext();
const [selectedDate, setSelectedDate] = useAtom(selectedDateAtom);
const [mode, setMode] = useAtom(modeAtom);
const setEditVisible = useSetAtom(editVisibleAtom);
const setEventForEdit = useSetAtom(eventForEditAtom);
const setSelectedNewEndDate = useSetAtom(selectedNewEventDateAtom);
const [isRendering, setIsRendering] = useState(true);
const [offsetMinutes, setOffsetMinutes] = useState(getTotalMinutes())
useEffect(() => {
if (events && mode) {
setIsRendering(true);
const timeout = setTimeout(() => {
setIsRendering(false);
}, 300);
return () => clearTimeout(timeout);
}
}, [events, mode]);
const handlePressEvent = useCallback((event: CalendarEvent) => {
if (mode === "day") {
setEditVisible(true);
console.log({event})
setEventForEdit(event);
} else {
setMode("day")
setSelectedDate(event.start);
}
}, [setEditVisible, setEventForEdit, mode]);
const handlePressCell = useCallback(
(date: Date) => {
if (mode === "day") {
setSelectedNewEndDate(date);
} else {
setMode("day")
setSelectedDate(date);
}
},
[mode, setSelectedNewEndDate, setSelectedDate]
);
const handleSwipeEnd = useCallback((date: Date) => {
setSelectedDate(date);
}, [setSelectedDate]);
const memoizedEventCellStyle = useCallback(
(event: CalendarEvent) => ({backgroundColor: event.eventColor}),
[]
);
const memoizedWeekStartsOn = useMemo(
() => (profileData?.firstDayOfWeek === "Mondays" ? 1 : 0),
[profileData]
);
const memoizedHeaderContentStyle = useMemo(
() => (mode === "day" ? styles.dayModeHeader : {}),
[mode]
);
const memoizedEvents = useMemo(() => events ?? [], [events]);
useEffect(() => {
setOffsetMinutes(getTotalMinutes())
}, [events, mode]);
if (isLoading || isRendering) {
return (
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color="#0000ff"/>
</View>
);
}
return (
<Calendar
bodyContainerStyle={styles.calHeader}
swipeEnabled
enableEnrichedEvents
mode={mode}
events={memoizedEvents}
eventCellStyle={memoizedEventCellStyle}
onPressEvent={handlePressEvent}
weekStartsOn={memoizedWeekStartsOn}
height={calendarHeight}
activeDate={selectedDate}
date={selectedDate}
onPressCell={handlePressCell}
headerContentStyle={memoizedHeaderContentStyle}
onSwipeEnd={handleSwipeEnd}
scrollOffsetMinutes={offsetMinutes}
/>
);
});
const styles = StyleSheet.create({
segmentslblStyle: {
fontSize: 12,
fontFamily: "Manrope_600SemiBold",
},
calHeader: {
borderWidth: 0,
},
dayModeHeader: {
alignSelf: "flex-start",
justifyContent: "space-between",
alignContent: "center",
width: 38,
right: 42,
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});