Get Events fix

This commit is contained in:
Milan Paunovic
2024-10-20 12:41:33 +02:00
parent 3275e64479
commit a9c02e880f
13 changed files with 486 additions and 669 deletions

View File

@ -30,6 +30,7 @@ export default function TabLayout() {
return ( return (
<Drawer <Drawer
initialRouteName={"index"} initialRouteName={"index"}
detachInactiveScreens
screenOptions={{ screenOptions={{
headerShown: true, headerShown: true,
drawerStyle: { drawerStyle: {

View File

@ -1,11 +1,8 @@
import React from "react"; import React from "react";
import CalendarPage from "@/components/pages/calendar/CalendarPage"; import CalendarPage from "@/components/pages/calendar/CalendarPage";
import {SettingsContextProvider} from "@/contexts/SettingsContext";
export default function Screen() { export default function Screen() {
return ( return (
<SettingsContextProvider>
<CalendarPage/> <CalendarPage/>
</SettingsContextProvider>
); );
} }

View File

@ -1,11 +1,8 @@
import SettingsPage from "@/components/pages/settings/SettingsPage"; import SettingsPage from "@/components/pages/settings/SettingsPage";
import {SettingsContextProvider} from "@/contexts/SettingsContext";
import React from "react"; import React from "react";
export default function Screen() { export default function Screen() {
return ( return (
<SettingsContextProvider>
<SettingsPage/> <SettingsPage/>
</SettingsContextProvider>
); );
} }

View File

@ -54,6 +54,9 @@ import {QueryClient, QueryClientProvider} from "react-query";
import {TextProps, ThemeManager, Toast, Typography,} from "react-native-ui-lib"; import {TextProps, ThemeManager, Toast, Typography,} from "react-native-ui-lib";
import {Platform} from 'react-native'; import {Platform} from 'react-native';
import KeyboardManager from 'react-native-keyboard-manager'; import KeyboardManager from 'react-native-keyboard-manager';
import {enableScreens} from 'react-native-screens';
enableScreens(true)
SplashScreen.preventAutoHideAsync(); SplashScreen.preventAutoHideAsync();

View File

@ -6,26 +6,25 @@ import {StyleSheet} from "react-native";
import {useAtom} from "jotai"; import {useAtom} from "jotai";
import {modeAtom, selectedDateAtom} from "@/components/pages/calendar/atoms"; import {modeAtom, selectedDateAtom} from "@/components/pages/calendar/atoms";
export const CalendarHeader = memo(() => { export const CalendarHeader = memo(() => {
const [selectedDate, setSelectedDate] = useAtom(selectedDateAtom) const [selectedDate, setSelectedDate] = useAtom(selectedDateAtom);
const [mode, setMode] = useAtom(modeAtom) const [mode, setMode] = useAtom(modeAtom);
const handleSegmentChange = (index: number) => { const handleSegmentChange = (index: number) => {
const selectedMode = modeMap.get(index); const selectedMode = modeMap.get(index);
if (selectedMode) { if (selectedMode) {
setTimeout(() => {
setMode(selectedMode as "day" | "week" | "month"); setMode(selectedMode as "day" | "week" | "month");
}, 150);
} }
}; };
const handleMonthChange = (month: string) => { const handleMonthChange = (month: string) => {
const currentDay = selectedDate.getDate(); const currentDay = selectedDate.getDate();
const currentYear = selectedDate.getFullYear(); const currentYear = selectedDate.getFullYear();
const newMonthIndex = months.indexOf(month); const newMonthIndex = months.indexOf(month);
const updatedDate = new Date(currentYear, newMonthIndex, currentDay); const updatedDate = new Date(currentYear, newMonthIndex, currentDay);
setSelectedDate(updatedDate); setSelectedDate(updatedDate);
}; };
@ -89,14 +88,4 @@ const styles = StyleSheet.create({
fontSize: 12, fontSize: 12,
fontFamily: "Manrope_600SemiBold", fontFamily: "Manrope_600SemiBold",
}, },
calHeader: {
borderWidth: 0,
},
dayModeHeader: {
alignSelf: "flex-start",
justifyContent: "space-between",
alignContent: "center",
width: 38,
right: 42,
},
}); });

View File

@ -1,4 +1,4 @@
import React, {memo} from 'react'; import React, {useCallback, useMemo} from 'react';
import {Calendar} from "react-native-big-calendar"; import {Calendar} from "react-native-big-calendar";
import {StyleSheet} from "react-native"; import {StyleSheet} from "react-native";
import {useGetEvents} from "@/hooks/firebase/useGetEvents"; import {useGetEvents} from "@/hooks/firebase/useGetEvents";
@ -11,44 +11,71 @@ import {
selectedNewEventDateAtom selectedNewEventDateAtom
} from "@/components/pages/calendar/atoms"; } from "@/components/pages/calendar/atoms";
import {useAuthContext} from "@/contexts/AuthContext"; import {useAuthContext} from "@/contexts/AuthContext";
import {CalendarEvent} from "@/components/pages/calendar/interfaces";
interface EventCalendarProps { interface EventCalendarProps {
calendarHeight: number; calendarHeight: number;
} }
export const EventCalendar: React.FC<EventCalendarProps> = memo(({calendarHeight}) => { export const EventCalendar: React.FC<EventCalendarProps> = React.memo(({calendarHeight}) => {
const {data: events} = useGetEvents(); const {data: events} = useGetEvents();
const {profileData} = useAuthContext() const {profileData} = useAuthContext();
const [selectedDate, setSelectedDate] = useAtom(selectedDateAtom) const [selectedDate, setSelectedDate] = useAtom(selectedDateAtom);
const [mode, setMode] = useAtom(modeAtom) const mode = useAtomValue(modeAtom);
const setEditVisible = useSetAtom(editVisibleAtom) const setEditVisible = useSetAtom(editVisibleAtom);
const setEventForEdit = useSetAtom(eventForEditAtom) const setEventForEdit = useSetAtom(eventForEditAtom);
const setSelectedNewEndDate = useSetAtom(selectedNewEventDateAtom) const setSelectedNewEndDate = useSetAtom(selectedNewEventDateAtom);
console.log("Events: ", events) const handlePressEvent = useCallback((event: CalendarEvent) => {
setEditVisible(true);
setEventForEdit(event);
}, [setEditVisible, setEventForEdit]);
const handlePressCell = useCallback(
(date: Date) => {
if (mode === "day") {
setSelectedNewEndDate(date);
} else {
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]
);
return ( return (
<Calendar <Calendar
bodyContainerStyle={styles.calHeader} bodyContainerStyle={styles.calHeader}
swipeEnabled
mode={mode} mode={mode}
events={events ?? []} events={events ?? []}
eventCellStyle={(event) => ({backgroundColor: event.eventColor})} eventCellStyle={memoizedEventCellStyle}
onPressEvent={(event) => { onPressEvent={handlePressEvent}
setEditVisible(true); weekStartsOn={memoizedWeekStartsOn}
setEventForEdit(event);
}}
weekStartsOn={profileData?.firstDayOfWeek === "Mondays" ? 1 : 0}
height={calendarHeight} height={calendarHeight}
activeDate={selectedDate} activeDate={selectedDate}
date={selectedDate} date={selectedDate}
onPressCell={mode === "day" ? setSelectedNewEndDate: (date) => { onPressCell={handlePressCell}
setSelectedDate(date) headerContentStyle={memoizedHeaderContentStyle}
setMode("day") onSwipeEnd={handleSwipeEnd}
}}
headerContentStyle={mode === "day" ? styles.dayModeHeader : {}}
onSwipeEnd={(date) => {
setSelectedDate(date);
}}
/> />
); );
}); });

View File

@ -2,7 +2,6 @@ import {AntDesign, Ionicons} from "@expo/vector-icons";
import React, {useCallback, useEffect, useState} from "react"; import React, {useCallback, useEffect, useState} from "react";
import {Button, Checkbox, Text, View} from "react-native-ui-lib"; import {Button, Checkbox, Text, View} from "react-native-ui-lib";
import {ActivityIndicator, ScrollView, StyleSheet} from "react-native"; import {ActivityIndicator, ScrollView, StyleSheet} from "react-native";
import {colorMap} from "@/contexts/SettingsContext";
import {TouchableOpacity} from "react-native-gesture-handler"; import {TouchableOpacity} from "react-native-gesture-handler";
import {useAuthContext} from "@/contexts/AuthContext"; import {useAuthContext} from "@/contexts/AuthContext";
import {useUpdateUserData} from "@/hooks/firebase/useUpdateUserData"; import {useUpdateUserData} from "@/hooks/firebase/useUpdateUserData";
@ -19,6 +18,7 @@ import {useFetchAndSaveOutlookEvents} from "@/hooks/useFetchAndSaveOutlookEvents
import {useFetchAndSaveAppleEvents} from "@/hooks/useFetchAndSaveAppleEvents"; import {useFetchAndSaveAppleEvents} from "@/hooks/useFetchAndSaveAppleEvents";
import * as AppleAuthentication from 'expo-apple-authentication'; import * as AppleAuthentication from 'expo-apple-authentication';
import ExpoLocalization from "expo-localization/src/ExpoLocalization"; import ExpoLocalization from "expo-localization/src/ExpoLocalization";
import {colorMap} from "@/constants/colorMap";
const googleConfig = { const googleConfig = {
androidClientId: androidClientId:

7
constants/colorMap.ts Normal file
View File

@ -0,0 +1,7 @@
export const colorMap = {
pink: "#ea156c",
orange: "#e28800",
green: "#46a80a",
teal: "#05a8b6",
purple: "#7305d4",
};

View File

@ -1,53 +0,0 @@
import { createContext, FC, ReactNode, useContext, useState } from "react";
import { useAuthContext } from "./AuthContext";
export const colorMap = {
pink: "#ea156c",
orange: "#e28800",
green: "#46a80a",
teal: "#05a8b6",
purple: "#7305d4",
};
interface IUserDetails {
email: string | undefined;
firstName: string;
lastName: string;
}
interface ISettingsContext {
calendarColor: string;
userDetails: IUserDetails;
editUserDetails: (details: Partial<IUserDetails>) => void;
setCalendarColor: (color: string) => void;
}
const SettingsContext = createContext<ISettingsContext>(undefined!);
export const SettingsContextProvider: FC<{ children: ReactNode }> = ({
children,
}) => {
const { user } = useAuthContext();
const [userDetails, setUserDetails] = useState<IUserDetails>({
email: user?.email?.toString(),
firstName: "",
lastName: "",
});
const [calendarColor, setCalendarColor] = useState<string>(colorMap.pink);
const editUserDetails = (details: Partial<IUserDetails>) => {
setUserDetails((prevDetails) => ({
...prevDetails,
...details,
}));
};
return (
<SettingsContext.Provider
value={{ calendarColor, setCalendarColor, userDetails, editUserDetails }}
>
{children}
</SettingsContext.Provider>
);
};
export const useSettingsContext = () => useContext(SettingsContext)!;

View File

@ -1,29 +1,39 @@
import {useQuery} from "react-query"; import {useQuery} from "react-query";
import firestore from "@react-native-firebase/firestore"; import firestore from "@react-native-firebase/firestore";
import {useAuthContext} from "@/contexts/AuthContext"; import {useAuthContext} from "@/contexts/AuthContext";
import {colorMap} from "@/contexts/SettingsContext";
import {useAtomValue} from "jotai"; import {useAtomValue} from "jotai";
import {isFamilyViewAtom} from "@/components/pages/calendar/atoms"; import {isFamilyViewAtom} from "@/components/pages/calendar/atoms";
import {colorMap} from "@/constants/colorMap";
export const useGetEvents = () => { export const useGetEvents = () => {
const {user, profileData} = useAuthContext(); const {user, profileData} = useAuthContext();
const isFamilyView = useAtomValue(isFamilyViewAtom) const isFamilyView = useAtomValue(isFamilyViewAtom);
return useQuery({ return useQuery({
queryKey: ["events", user?.uid, isFamilyView], queryKey: ["events", user?.uid, isFamilyView],
queryFn: async () => { queryFn: async () => {
const db = firestore(); const db = firestore();
const userId = user?.uid; // Assuming user is defined const userId = user?.uid;
const familyId = profileData?.familyId; // Assuming profileData is defined const familyId = profileData?.familyId;
let allEvents = []; let allEvents = [];
if (isFamilyView) { if (isFamilyView) {
const familyQuery = db.collection("Events").where("familyID", "==", familyId); const familyQuery = db.collection("Events").where("familyID", "==", familyId);
const familySnapshot = await familyQuery.get(); const creatorQuery = db.collection("Events").where("creatorId", "==", userId);
const familyEvents = familySnapshot.docs.map(doc => doc.data()); const attendeeQuery = db.collection("Events").where("attendees", "array-contains", userId);
allEvents = [...familyEvents]; const [familySnapshot, creatorSnapshot, attendeeSnapshot] = await Promise.all([
familyQuery.get(),
creatorQuery.get(),
attendeeQuery.get(),
]);
const familyEvents = familySnapshot.docs.map(doc => doc.data());
const creatorEvents = creatorSnapshot.docs.map(doc => doc.data());
const attendeeEvents = attendeeSnapshot.docs.map(doc => doc.data());
allEvents = [...familyEvents, ...creatorEvents, ...attendeeEvents];
} else { } else {
const creatorQuery = db.collection("Events").where("creatorId", "==", userId); const creatorQuery = db.collection("Events").where("creatorId", "==", userId);
const attendeeQuery = db.collection("Events").where("attendees", "array-contains", userId); const attendeeQuery = db.collection("Events").where("attendees", "array-contains", userId);
@ -51,7 +61,7 @@ export const useGetEvents = () => {
.get(); .get();
const profileData = profileSnapshot.data(); const profileData = profileSnapshot.data();
const eventColor = profileData?.eventColor || colorMap.pink; // Default color if not found const eventColor = profileData?.eventColor || colorMap.pink;
return { return {
id: event.id, id: event.id,
@ -65,6 +75,6 @@ export const useGetEvents = () => {
); );
}, },
staleTime: Infinity, staleTime: Infinity,
cacheTime: Infinity cacheTime: Infinity,
}); });
}; };

View File

@ -14,7 +14,7 @@ install! 'cocoapods',
prepare_react_native_project! prepare_react_native_project!
target 'cally' do target 'cally' do
# pod 'IQKeyboardManagerSwift', :git => 'https://github.com/douglasjunior/IQKeyboardManager.git', :branch => 'react-native-keyboard-manager' pod 'IQKeyboardManagerSwift', :git => 'https://github.com/douglasjunior/IQKeyboardManager.git', :branch => 'react-native-keyboard-manager'
use_expo_modules! use_expo_modules!
config = use_native_modules! config = use_native_modules!

View File

@ -562,7 +562,10 @@
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\""; LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "$(inherited) "; OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
USE_HERMES = true; USE_HERMES = true;
@ -631,7 +634,10 @@
); );
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\""; LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
OTHER_LDFLAGS = "$(inherited) "; OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
USE_HERMES = true; USE_HERMES = true;

941
yarn.lock

File diff suppressed because it is too large Load Diff