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

108 lines
3.7 KiB
TypeScript

import React from 'react';
import { StyleSheet, View, ActivityIndicator } from 'react-native';
import { Text } from 'react-native-ui-lib';
import Animated, {
withTiming,
useAnimatedStyle,
FadeOut,
useSharedValue,
runOnJS
} from 'react-native-reanimated';
import { useGetEvents } from '@/hooks/firebase/useGetEvents';
import { useCalSync } from '@/hooks/useCalSync';
import { useSyncEvents } from '@/hooks/useSyncOnScroll';
import { useAtom } from 'jotai';
import { modeAtom } from './atoms';
import { MonthCalendar } from "@/components/pages/calendar/MonthCalendar";
import DetailedCalendar from "@/components/pages/calendar/DetailedCalendar";
import * as Device from "expo-device";
export type CalendarMode = 'month' | 'day' | '3days' | 'week';
interface EventCalendarProps {
calendarHeight: number;
calendarWidth: number;
}
export const EventCalendar: React.FC<EventCalendarProps> = React.memo((props) => {
const { isLoading } = useGetEvents();
const [mode] = useAtom<CalendarMode>(modeAtom);
const { isSyncing } = useSyncEvents();
const isTablet = Device.deviceType === Device.DeviceType.TABLET;
const isCalendarReady = useSharedValue(false);
useCalSync();
const handleRenderComplete = React.useCallback(() => {
isCalendarReady.value = true;
}, []);
const containerStyle = useAnimatedStyle(() => ({
opacity: withTiming(isCalendarReady.value ? 1 : 0, { duration: 500 }),
flex: 1,
}));
const monthStyle = useAnimatedStyle(() => ({
opacity: withTiming(mode === 'month' ? 1 : 0, { duration: 300 }),
position: 'absolute',
width: '100%',
height: '100%',
}));
const detailedDayStyle = useAnimatedStyle(() => ({
opacity: withTiming(mode === 'day' ? 1 : 0, { duration: 300 }),
position: 'absolute',
width: '100%',
height: '100%',
}));
const detailedMultiStyle = useAnimatedStyle(() => ({
opacity: withTiming(mode === (isTablet ? 'week' : '3days') ? 1 : 0, { duration: 300 }),
position: 'absolute',
width: '100%',
height: '100%',
}));
return (
<View style={styles.root}>
{(isLoading || isSyncing) && mode !== 'month' && (
<Animated.View
exiting={FadeOut.duration(300)}
style={styles.loadingContainer}
>
{isSyncing && <Text>Syncing...</Text>}
<ActivityIndicator size="large" color="#0000ff"/>
</Animated.View>
)}
<Animated.View style={containerStyle}>
<Animated.View style={monthStyle} pointerEvents={mode === 'month' ? 'auto' : 'none'}>
<MonthCalendar {...props} />
</Animated.View>
<Animated.View style={detailedDayStyle} pointerEvents={mode === 'day' ? 'auto' : 'none'}>
<DetailedCalendar mode="day" {...props} />
</Animated.View>
<Animated.View style={detailedMultiStyle} pointerEvents={mode === (isTablet ? 'week' : '3days') ? 'auto' : 'none'}>
{!isLoading && (
<DetailedCalendar onLoad={handleRenderComplete} mode={isTablet ? 'week' : '3days'} {...props} />
)}
</Animated.View>
</Animated.View>
</View>
);
});
const styles = StyleSheet.create({
root: {
flex: 1,
},
loadingContainer: {
position: 'absolute',
width: '100%',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
zIndex: 100,
backgroundColor: 'rgba(255, 255, 255, 0.9)',
},
});
export default EventCalendar;