mirror of
https://github.com/urosran/cally.git
synced 2025-11-26 00:24:53 +00:00
Calendar page refactor
This commit is contained in:
@ -1,14 +1,11 @@
|
||||
import React from "react";
|
||||
import { CalendarProvider } from "@/contexts/CalendarContext"; // Import the new CalendarPage component
|
||||
import CalendarPage from "@/components/pages/calendar/CalendarPage";
|
||||
import {SettingsContextProvider} from "@/contexts/SettingsContext";
|
||||
|
||||
export default function Screen() {
|
||||
return (
|
||||
<SettingsContextProvider>
|
||||
<CalendarProvider>
|
||||
<CalendarPage/>
|
||||
</CalendarProvider>
|
||||
</SettingsContextProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import React, {useEffect} from "react";
|
||||
import {DefaultTheme, ThemeProvider} from "@react-navigation/native";
|
||||
import {
|
||||
useFonts,
|
||||
Manrope_200ExtraLight,
|
||||
Manrope_300Light,
|
||||
Manrope_400Regular,
|
||||
@ -9,21 +8,22 @@ import {
|
||||
Manrope_600SemiBold,
|
||||
Manrope_700Bold,
|
||||
Manrope_800ExtraBold,
|
||||
useFonts,
|
||||
} from "@expo-google-fonts/manrope";
|
||||
import {
|
||||
PlusJakartaSans_200ExtraLight,
|
||||
PlusJakartaSans_300Light,
|
||||
PlusJakartaSans_400Regular,
|
||||
PlusJakartaSans_500Medium,
|
||||
PlusJakartaSans_600SemiBold,
|
||||
PlusJakartaSans_700Bold,
|
||||
PlusJakartaSans_800ExtraBold,
|
||||
PlusJakartaSans_200ExtraLight_Italic,
|
||||
PlusJakartaSans_300Light,
|
||||
PlusJakartaSans_300Light_Italic,
|
||||
PlusJakartaSans_400Regular,
|
||||
PlusJakartaSans_400Regular_Italic,
|
||||
PlusJakartaSans_500Medium,
|
||||
PlusJakartaSans_500Medium_Italic,
|
||||
PlusJakartaSans_600SemiBold,
|
||||
PlusJakartaSans_600SemiBold_Italic,
|
||||
PlusJakartaSans_700Bold,
|
||||
PlusJakartaSans_700Bold_Italic,
|
||||
PlusJakartaSans_800ExtraBold,
|
||||
PlusJakartaSans_800ExtraBold_Italic,
|
||||
} from "@expo-google-fonts/plus-jakarta-sans";
|
||||
import {
|
||||
@ -51,24 +51,16 @@ import * as SplashScreen from "expo-splash-screen";
|
||||
import "react-native-reanimated";
|
||||
import {AuthContextProvider} from "@/contexts/AuthContext";
|
||||
import {QueryClient, QueryClientProvider} from "react-query";
|
||||
import {
|
||||
ThemeManager,
|
||||
Typography,
|
||||
Toast,
|
||||
TextProps,
|
||||
} from "react-native-ui-lib";
|
||||
import functions from "@react-native-firebase/functions";
|
||||
import auth from "@react-native-firebase/auth";
|
||||
import firestore from "@react-native-firebase/firestore";
|
||||
import {TextProps, ThemeManager, Toast, Typography,} from "react-native-ui-lib";
|
||||
|
||||
SplashScreen.preventAutoHideAsync();
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
if (__DEV__) {
|
||||
functions().useEmulator("localhost", 5001);
|
||||
firestore().useEmulator("localhost", 5471);
|
||||
auth().useEmulator("http://localhost:9099");
|
||||
// functions().useEmulator("localhost", 5001);
|
||||
// firestore().useEmulator("localhost", 5471);
|
||||
// auth().useEmulator("http://localhost:9099");
|
||||
}
|
||||
|
||||
type TextStyleBase =
|
||||
@ -236,7 +228,7 @@ export default function RootLayout() {
|
||||
|
||||
ThemeManager.setComponentTheme(
|
||||
"Text",
|
||||
(props: ExtendedTextProps, context: unknown) => {
|
||||
(props: ExtendedTextProps) => {
|
||||
const textStyle = (
|
||||
Object.keys(props) as Array<keyof ExtendedTextProps>
|
||||
).find((key) => typographies[key as TextStyle]) as
|
||||
|
||||
@ -1,38 +1,26 @@
|
||||
import React, {useState} from "react";
|
||||
import {
|
||||
AntDesign,
|
||||
Feather,
|
||||
MaterialCommunityIcons,
|
||||
MaterialIcons,
|
||||
} from "@expo/vector-icons";
|
||||
import {
|
||||
Button,
|
||||
ButtonSize,
|
||||
Card,
|
||||
Dialog,
|
||||
PanningProvider,
|
||||
Text,
|
||||
View,
|
||||
} from "react-native-ui-lib";
|
||||
import {MaterialIcons,} from "@expo/vector-icons";
|
||||
import {Button, Card, Dialog, PanningProvider, Text, View,} from "react-native-ui-lib";
|
||||
import {StyleSheet, TouchableOpacity} from "react-native";
|
||||
import { ManuallyAddEventModal } from "@/components/pages/calendar/ManuallyAddEventModal";
|
||||
import AddChoreDialog from "../todos/AddChoreDialog";
|
||||
import {ToDosContextProvider} from "@/contexts/ToDosContext";
|
||||
import UploadImageDialog from "./UploadImageDialog";
|
||||
import CameraIcon from "@/assets/svgs/CameraIcon";
|
||||
import CalendarIcon from "@/assets/svgs/CalendarIcon";
|
||||
import NavToDosIcon from "@/assets/svgs/NavToDosIcon";
|
||||
import {useSetAtom} from "jotai";
|
||||
import {selectedNewEventDateAtom} from "@/components/pages/calendar/atoms";
|
||||
|
||||
export const AddEventDialog = () => {
|
||||
const [show, setShow] = useState(false);
|
||||
const [showManualInputModal, setShowManualInputModal] = useState(false);
|
||||
const [choreDialogVisible, setChoreDialogVisible] = useState<boolean>(false);
|
||||
const [showUploadDialog, setShowUploadDialog] = useState<boolean>(false);
|
||||
const setSelectedNewEndDate = useSetAtom(selectedNewEventDateAtom)
|
||||
|
||||
const handleOpenManualInputModal = () => {
|
||||
setShow(false);
|
||||
setTimeout(() => {
|
||||
setShowManualInputModal(true);
|
||||
setSelectedNewEndDate(new Date());
|
||||
}, 500);
|
||||
};
|
||||
|
||||
@ -147,10 +135,6 @@ export const AddEventDialog = () => {
|
||||
isVisible={choreDialogVisible}
|
||||
setIsVisible={setChoreDialogVisible}
|
||||
/>
|
||||
<ManuallyAddEventModal
|
||||
show={showManualInputModal}
|
||||
close={() => setShowManualInputModal(false)}
|
||||
/>
|
||||
<UploadImageDialog
|
||||
show={showUploadDialog}
|
||||
setShow={setShowUploadDialog}
|
||||
|
||||
102
components/pages/calendar/CalendarHeader.tsx
Normal file
102
components/pages/calendar/CalendarHeader.tsx
Normal file
@ -0,0 +1,102 @@
|
||||
import React, {memo} from 'react';
|
||||
import {Picker, PickerModes, SegmentedControl, Text, View} from "react-native-ui-lib";
|
||||
import {MaterialIcons} from "@expo/vector-icons";
|
||||
import {modeMap, months} from './constants';
|
||||
import {StyleSheet} from "react-native";
|
||||
import {useAtom} from "jotai";
|
||||
import {modeAtom, selectedDateAtom} from "@/components/pages/calendar/atoms";
|
||||
|
||||
|
||||
export const CalendarHeader = memo(() => {
|
||||
const [selectedDate, setSelectedDate] = useAtom(selectedDateAtom)
|
||||
const [mode, setMode] = useAtom(modeAtom)
|
||||
|
||||
const handleSegmentChange = (index: number) => {
|
||||
const selectedMode = modeMap.get(index);
|
||||
if (selectedMode) {
|
||||
setMode(selectedMode as "day" | "week" | "month");
|
||||
}
|
||||
};
|
||||
|
||||
const handleMonthChange = (month: string) => {
|
||||
const currentDay = selectedDate.getDate();
|
||||
const currentYear = selectedDate.getFullYear();
|
||||
|
||||
const newMonthIndex = months.indexOf(month);
|
||||
|
||||
const updatedDate = new Date(currentYear, newMonthIndex, currentDay);
|
||||
|
||||
setSelectedDate(updatedDate);
|
||||
};
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 8,
|
||||
borderRadius: 20,
|
||||
borderBottomLeftRadius: 0,
|
||||
borderBottomRightRadius: 0,
|
||||
backgroundColor: "white",
|
||||
marginBottom: 10,
|
||||
}}
|
||||
>
|
||||
<View row centerV gap-3>
|
||||
<Text style={{fontFamily: "Manrope_500Medium", fontSize: 17}}>
|
||||
{selectedDate.getFullYear()}
|
||||
</Text>
|
||||
<Picker
|
||||
value={months[selectedDate.getMonth()]}
|
||||
placeholder={"Select Month"}
|
||||
style={{fontFamily: "Manrope_500Medium", fontSize: 17}}
|
||||
mode={PickerModes.SINGLE}
|
||||
onChange={(itemValue) => handleMonthChange(itemValue as string)}
|
||||
trailingAccessory={<MaterialIcons name={"keyboard-arrow-down"}/>}
|
||||
topBarProps={{
|
||||
title: selectedDate.getFullYear().toString(),
|
||||
titleStyle: {fontFamily: "Manrope_500Medium", fontSize: 17},
|
||||
}}
|
||||
>
|
||||
{months.map((month) => (
|
||||
<Picker.Item key={month} label={month} value={month}/>
|
||||
))}
|
||||
</Picker>
|
||||
</View>
|
||||
|
||||
<View>
|
||||
<SegmentedControl
|
||||
segments={[{label: "D"}, {label: "W"}, {label: "M"}]}
|
||||
backgroundColor="#ececec"
|
||||
inactiveColor="#919191"
|
||||
activeBackgroundColor="#ea156c"
|
||||
activeColor="white"
|
||||
outlineColor="white"
|
||||
outlineWidth={3}
|
||||
segmentLabelStyle={styles.segmentslblStyle}
|
||||
onChangeIndex={handleSegmentChange}
|
||||
initialIndex={mode === "day" ? 0 : mode === "week" ? 1 : 2}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
});
|
||||
|
||||
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,
|
||||
},
|
||||
});
|
||||
@ -1,100 +1,9 @@
|
||||
import React, { useRef, useState } from "react";
|
||||
import { LayoutChangeEvent, StyleSheet } from "react-native";
|
||||
import { Calendar } from "react-native-big-calendar";
|
||||
import {
|
||||
Picker,
|
||||
PickerModes,
|
||||
SegmentedControl,
|
||||
View,
|
||||
} from "react-native-ui-lib";
|
||||
import { MaterialIcons } from "@expo/vector-icons";
|
||||
import { AddEventDialog } from "@/components/pages/calendar/AddEventDialog";
|
||||
import React from "react";
|
||||
import {View,} from "react-native-ui-lib";
|
||||
import HeaderTemplate from "@/components/shared/HeaderTemplate";
|
||||
import CalendarViewSwitch from "@/components/pages/calendar/CalendarViewSwitch";
|
||||
import { ManuallyAddEventModal } from "@/components/pages/calendar/ManuallyAddEventModal";
|
||||
import { CalendarEvent } from "@/contexts/CalendarContext";
|
||||
import { useSettingsContext } from "@/contexts/SettingsContext";
|
||||
import EditEventDialog from "./EditEventDialog";
|
||||
import { useGetEvents } from "@/hooks/firebase/useGetEvents";
|
||||
import { Text } from "react-native-ui-lib";
|
||||
|
||||
const modeMap = new Map([
|
||||
[0, "day"],
|
||||
[1, "week"],
|
||||
[2, "month"],
|
||||
]);
|
||||
|
||||
const months = [
|
||||
"January",
|
||||
"February",
|
||||
"March",
|
||||
"April",
|
||||
"May",
|
||||
"June",
|
||||
"July",
|
||||
"August",
|
||||
"September",
|
||||
"October",
|
||||
"November",
|
||||
"December",
|
||||
];
|
||||
import {InnerCalendar} from "@/components/pages/calendar/InnerCalendar";
|
||||
|
||||
export default function CalendarPage() {
|
||||
const { calendarColor } = useSettingsContext();
|
||||
const [editVisible, setEditVisible] = useState<boolean>(false);
|
||||
const [eventForEdit, setEventForEdit] = useState<CalendarEvent>();
|
||||
|
||||
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,
|
||||
},
|
||||
});
|
||||
|
||||
const [isFamilyView, setIsFamilyView] = useState<boolean>(false);
|
||||
const [calendarHeight, setCalendarHeight] = useState(0);
|
||||
const [mode, setMode] = useState<"week" | "month" | "day">("week");
|
||||
const [selectedDate, setSelectedDate] = useState<Date>(new Date());
|
||||
const [selectedNewEventDate, setSelectedNewEndDate] = useState<
|
||||
Date | undefined
|
||||
>(undefined);
|
||||
|
||||
const calendarContainerRef = useRef(null);
|
||||
const { data: events } = useGetEvents(isFamilyView);
|
||||
|
||||
const onLayout = (event: LayoutChangeEvent) => {
|
||||
const { height } = event.nativeEvent.layout;
|
||||
setCalendarHeight(height);
|
||||
};
|
||||
|
||||
const handleSegmentChange = (index: number) => {
|
||||
const selectedMode = modeMap.get(index);
|
||||
if (selectedMode) {
|
||||
setMode(selectedMode as "day" | "week" | "month");
|
||||
}
|
||||
};
|
||||
|
||||
const handleMonthChange = (month: string) => {
|
||||
const currentDay = selectedDate.getDate();
|
||||
const currentYear = selectedDate.getFullYear();
|
||||
|
||||
const newMonthIndex = months.indexOf(month);
|
||||
|
||||
const updatedDate = new Date(currentYear, newMonthIndex, currentDay);
|
||||
|
||||
setSelectedDate(updatedDate);
|
||||
};
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{flex: 1, height: "100%", padding: 10}}
|
||||
@ -103,105 +12,9 @@ export default function CalendarPage() {
|
||||
>
|
||||
<HeaderTemplate
|
||||
message={"Let's get your week started!"}
|
||||
isWelcome={true}
|
||||
/>
|
||||
|
||||
<View
|
||||
style={{ flex: 1, backgroundColor: "#fff", borderRadius: 30 }}
|
||||
ref={calendarContainerRef}
|
||||
onLayout={onLayout}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 8,
|
||||
borderRadius: 20,
|
||||
borderBottomLeftRadius: 0,
|
||||
borderBottomRightRadius: 0,
|
||||
backgroundColor: "white",
|
||||
marginBottom: 10,
|
||||
}}
|
||||
>
|
||||
<View row centerV gap-3>
|
||||
<Text style={{ fontFamily: "Manrope_500Medium", fontSize: 17 }}>
|
||||
{selectedDate.getFullYear()}
|
||||
</Text>
|
||||
<Picker
|
||||
value={months[selectedDate.getMonth()]} // Get the month from the date
|
||||
placeholder={"Select Month"}
|
||||
style={{ fontFamily: "Manrope_500Medium", fontSize: 17 }}
|
||||
mode={PickerModes.SINGLE}
|
||||
onChange={(itemValue) => handleMonthChange(itemValue as string)}
|
||||
trailingAccessory={<MaterialIcons name={"keyboard-arrow-down"} />}
|
||||
topBarProps={{
|
||||
title: selectedDate.getFullYear().toString(),
|
||||
titleStyle: { fontFamily: "Manrope_500Medium", fontSize: 17 },
|
||||
}}
|
||||
>
|
||||
{months.map((month) => (
|
||||
<Picker.Item key={month} label={month} value={month} />
|
||||
))}
|
||||
</Picker>
|
||||
</View>
|
||||
|
||||
<View>
|
||||
<SegmentedControl
|
||||
segments={[{ label: "D" }, { label: "W" }, { label: "M" }]}
|
||||
backgroundColor="#ececec"
|
||||
inactiveColor="#919191"
|
||||
activeBackgroundColor="#ea156c"
|
||||
activeColor="white"
|
||||
outlineColor="white"
|
||||
outlineWidth={3}
|
||||
segmentLabelStyle={styles.segmentslblStyle}
|
||||
onChangeIndex={handleSegmentChange}
|
||||
initialIndex={mode === "day" ? 0 : mode === "week" ? 1 : 2}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{calendarHeight > 0 && (
|
||||
<Calendar
|
||||
bodyContainerStyle={styles.calHeader}
|
||||
mode={mode}
|
||||
events={isFamilyView ? events ?? [] : events ?? []}
|
||||
eventCellStyle={(event) => ({ backgroundColor: event.eventColor })}
|
||||
onPressEvent={(event) => {
|
||||
setEditVisible(true);
|
||||
setEventForEdit(event);
|
||||
}}
|
||||
height={calendarHeight}
|
||||
activeDate={selectedDate}
|
||||
date={selectedDate}
|
||||
onPressCell={setSelectedNewEndDate}
|
||||
headerContentStyle={mode === "day" ? styles.dayModeHeader : {}}
|
||||
onSwipeEnd={(date) => {
|
||||
setSelectedDate(date);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
<CalendarViewSwitch viewSwitch={setIsFamilyView} />
|
||||
<AddEventDialog />
|
||||
{eventForEdit && (
|
||||
<EditEventDialog
|
||||
isVisible={editVisible}
|
||||
setIsVisible={() => {
|
||||
setEditVisible(!editVisible);
|
||||
}}
|
||||
event={eventForEdit}
|
||||
/>
|
||||
)}
|
||||
|
||||
<ManuallyAddEventModal
|
||||
key={`${selectedNewEventDate}`}
|
||||
initialDate={selectedNewEventDate}
|
||||
show={!!selectedNewEventDate}
|
||||
close={() => setSelectedNewEndDate(undefined)}
|
||||
isWelcome
|
||||
/>
|
||||
<InnerCalendar/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { View, Text, Button, TouchableOpacity } from "react-native-ui-lib";
|
||||
import {Text, TouchableOpacity, View} from "react-native-ui-lib";
|
||||
import React, {useState} from "react";
|
||||
import { MaterialIcons } from "@expo/vector-icons";
|
||||
import {StyleSheet} from "react-native";
|
||||
import {useSetAtom} from "jotai";
|
||||
import {isFamilyViewAtom} from "@/components/pages/calendar/atoms";
|
||||
|
||||
interface ICalendarViewProps {
|
||||
viewSwitch: (value: boolean) => void;
|
||||
}
|
||||
const CalendarViewSwitch = (calendarViewProps: ICalendarViewProps) => {
|
||||
|
||||
const CalendarViewSwitch = () => {
|
||||
const [calView, setCalView] = useState<boolean>(false);
|
||||
const viewSwitch = useSetAtom(isFamilyViewAtom)
|
||||
|
||||
return (
|
||||
<View
|
||||
@ -34,7 +34,7 @@ const CalendarViewSwitch = (calendarViewProps: ICalendarViewProps) => {
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
setCalView(true);
|
||||
calendarViewProps.viewSwitch(true);
|
||||
viewSwitch(true);
|
||||
}}
|
||||
>
|
||||
<View
|
||||
@ -53,7 +53,7 @@ const CalendarViewSwitch = (calendarViewProps: ICalendarViewProps) => {
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
setCalView(false);
|
||||
calendarViewProps.viewSwitch(false);
|
||||
viewSwitch(false);
|
||||
}}
|
||||
>
|
||||
<View
|
||||
|
||||
@ -1,42 +1,31 @@
|
||||
import { View, Text, Button, Switch } from "react-native-ui-lib";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Feather, AntDesign, Ionicons } from "@expo/vector-icons";
|
||||
import {
|
||||
Dialog,
|
||||
TextField,
|
||||
DateTimePicker,
|
||||
Picker,
|
||||
ButtonSize,
|
||||
} from "react-native-ui-lib";
|
||||
import {Button, ButtonSize, DateTimePicker, Dialog, Switch, Text, TextField, View} from "react-native-ui-lib";
|
||||
import React from "react";
|
||||
import {AntDesign, Feather, Ionicons} from "@expo/vector-icons";
|
||||
import {PanningDirectionsEnum} from "react-native-ui-lib/src/incubator/panView";
|
||||
import {StyleSheet} from "react-native";
|
||||
import DropModalIcon from "@/assets/svgs/DropModalIcon";
|
||||
import { CalendarEvent } from "@/contexts/CalendarContext";
|
||||
import ClockIcon from "@/assets/svgs/ClockIcon";
|
||||
import LockIcon from "@/assets/svgs/LockIcon";
|
||||
import MenuIcon from "@/assets/svgs/MenuIcon";
|
||||
import {useUpdateEvent} from "@/hooks/firebase/useUpdateEvent";
|
||||
import {editVisibleAtom, eventForEditAtom} from "@/components/pages/calendar/atoms";
|
||||
import {useAtom} from "jotai";
|
||||
|
||||
interface IEditEventDialog {
|
||||
event: CalendarEvent;
|
||||
isVisible: boolean;
|
||||
setIsVisible: (value: boolean) => void;
|
||||
}
|
||||
const EditEventDialog = (editEventProps: IEditEventDialog) => {
|
||||
const [event, setEvent] = useState<CalendarEvent>(editEventProps.event);
|
||||
|
||||
const EditEventDialog = () => {
|
||||
const [isVisible, setIsVisible] = useAtom(editVisibleAtom)
|
||||
const [event, setEvent] = useAtom(eventForEditAtom)
|
||||
|
||||
const {mutateAsync: updateEvent} = useUpdateEvent();
|
||||
|
||||
useEffect(() => {
|
||||
setEvent(editEventProps.event);
|
||||
}, [editEventProps.isVisible]);
|
||||
if (!event) return null
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
bottom={true}
|
||||
height={"90%"}
|
||||
panDirection={PanningDirectionsEnum.DOWN}
|
||||
onDismiss={() => editEventProps.setIsVisible(false)}
|
||||
onDismiss={() => setIsVisible(false)}
|
||||
containerStyle={{
|
||||
borderRadius: 10,
|
||||
backgroundColor: "white",
|
||||
@ -46,7 +35,7 @@ const EditEventDialog = (editEventProps: IEditEventDialog) => {
|
||||
paddingTop: 4,
|
||||
margin: 0,
|
||||
}}
|
||||
visible={editEventProps.isVisible}
|
||||
visible={isVisible}
|
||||
>
|
||||
<View row spread>
|
||||
<Button
|
||||
@ -54,13 +43,13 @@ const EditEventDialog = (editEventProps: IEditEventDialog) => {
|
||||
style={styles.topBtn}
|
||||
label="Cancel"
|
||||
onPress={() => {
|
||||
editEventProps.setIsVisible(false);
|
||||
setIsVisible(false);
|
||||
}}
|
||||
/>
|
||||
<View marginT-12>
|
||||
<DropModalIcon
|
||||
onPress={() => {
|
||||
editEventProps.setIsVisible(false);
|
||||
setIsVisible(false);
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
@ -71,7 +60,7 @@ const EditEventDialog = (editEventProps: IEditEventDialog) => {
|
||||
onPress={() => {
|
||||
try {
|
||||
if (event.id) {
|
||||
updateEvent(event).then(() => editEventProps.setIsVisible(false));
|
||||
updateEvent(event).then(() => setIsVisible(false));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
@ -85,7 +74,7 @@ const EditEventDialog = (editEventProps: IEditEventDialog) => {
|
||||
value={event.title}
|
||||
onChangeText={(text) => {
|
||||
setEvent((prevEvent) => ({
|
||||
...prevEvent,
|
||||
...prevEvent!,
|
||||
title: text,
|
||||
}));
|
||||
}}
|
||||
@ -110,7 +99,7 @@ const EditEventDialog = (editEventProps: IEditEventDialog) => {
|
||||
marginL-10
|
||||
value={event.allDay}
|
||||
onValueChange={(value) =>
|
||||
setEvent((prev) => ({ ...prev, allDay: value }))
|
||||
setEvent((prev) => ({...prev!, allDay: value}))
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
@ -125,7 +114,7 @@ const EditEventDialog = (editEventProps: IEditEventDialog) => {
|
||||
marginL-8
|
||||
maximumDate={event.end}
|
||||
onChange={(date) => {
|
||||
setEvent((prev) => ({ ...prev, start: date }));
|
||||
setEvent((prev) => ({...prev!, start: date}));
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
@ -133,11 +122,12 @@ const EditEventDialog = (editEventProps: IEditEventDialog) => {
|
||||
text70
|
||||
value={event.start}
|
||||
onChange={(date) => {
|
||||
setEvent((prev) => ({ ...prev, start: date }));
|
||||
setEvent((prev) => ({...prev!, start: date}));
|
||||
}}
|
||||
maximumDate={event.end}
|
||||
dateTimeFormatter={(date, mode) => date.toLocaleTimeString("en-us",
|
||||
{ hour: "numeric",
|
||||
dateTimeFormatter={(date) => date.toLocaleTimeString("en-us",
|
||||
{
|
||||
hour: "numeric",
|
||||
minute: "numeric"
|
||||
})}
|
||||
mode="time"
|
||||
@ -155,7 +145,7 @@ const EditEventDialog = (editEventProps: IEditEventDialog) => {
|
||||
text70
|
||||
marginL-8
|
||||
onChange={(date) => {
|
||||
setEvent((prev) => ({ ...prev, end: date }));
|
||||
setEvent((prev) => ({...prev!, end: date}));
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
@ -164,10 +154,11 @@ const EditEventDialog = (editEventProps: IEditEventDialog) => {
|
||||
value={event.end}
|
||||
minimumDate={event.start}
|
||||
onChange={(date) => {
|
||||
setEvent((prev) => ({ ...prev, end: date }));
|
||||
setEvent((prev) => ({...prev!, end: date}));
|
||||
}}
|
||||
dateTimeFormatter={(date, mode) => date.toLocaleTimeString("en-us",
|
||||
{ hour: "numeric",
|
||||
dateTimeFormatter={(date) => date.toLocaleTimeString("en-us",
|
||||
{
|
||||
hour: "numeric",
|
||||
minute: "numeric"
|
||||
})}
|
||||
mode="time"
|
||||
@ -262,7 +253,7 @@ const EditEventDialog = (editEventProps: IEditEventDialog) => {
|
||||
marginL-10
|
||||
value={event.private}
|
||||
onValueChange={(value) =>
|
||||
setEvent((prev) => ({ ...prev, private: value }))
|
||||
setEvent((prev) => ({...prev!, private: value}))
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
|
||||
63
components/pages/calendar/EventCalendar.tsx
Normal file
63
components/pages/calendar/EventCalendar.tsx
Normal file
@ -0,0 +1,63 @@
|
||||
import React, {memo} from 'react';
|
||||
import {Calendar} from "react-native-big-calendar";
|
||||
import {StyleSheet} from "react-native";
|
||||
import {useGetEvents} from "@/hooks/firebase/useGetEvents";
|
||||
import {useAtom, useAtomValue, useSetAtom} from "jotai";
|
||||
import {
|
||||
editVisibleAtom,
|
||||
eventForEditAtom,
|
||||
modeAtom,
|
||||
selectedDateAtom,
|
||||
selectedNewEventDateAtom
|
||||
} from "@/components/pages/calendar/atoms";
|
||||
|
||||
interface EventCalendarProps {
|
||||
calendarHeight: number;
|
||||
}
|
||||
|
||||
export const EventCalendar: React.FC<EventCalendarProps> = memo(({calendarHeight}) => {
|
||||
const {data: events} = useGetEvents();
|
||||
const [selectedDate, setSelectedDate] = useAtom(selectedDateAtom)
|
||||
const mode = useAtomValue(modeAtom)
|
||||
const setEditVisible = useSetAtom(editVisibleAtom)
|
||||
const setEventForEdit = useSetAtom(eventForEditAtom)
|
||||
const setSelectedNewEndDate = useSetAtom(selectedNewEventDateAtom)
|
||||
|
||||
return (
|
||||
<Calendar
|
||||
bodyContainerStyle={styles.calHeader}
|
||||
mode={mode}
|
||||
events={events ?? []}
|
||||
eventCellStyle={(event) => ({backgroundColor: event.eventColor})}
|
||||
onPressEvent={(event) => {
|
||||
setEditVisible(true);
|
||||
setEventForEdit(event);
|
||||
}}
|
||||
height={calendarHeight}
|
||||
activeDate={selectedDate}
|
||||
date={selectedDate}
|
||||
onPressCell={setSelectedNewEndDate}
|
||||
headerContentStyle={mode === "day" ? styles.dayModeHeader : {}}
|
||||
onSwipeEnd={(date) => {
|
||||
setSelectedDate(date);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
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,
|
||||
},
|
||||
});
|
||||
41
components/pages/calendar/InnerCalendar.tsx
Normal file
41
components/pages/calendar/InnerCalendar.tsx
Normal file
@ -0,0 +1,41 @@
|
||||
import {View} from "react-native-ui-lib";
|
||||
import React, {useRef, useState} from "react";
|
||||
import {LayoutChangeEvent} from "react-native";
|
||||
import CalendarViewSwitch from "@/components/pages/calendar/CalendarViewSwitch";
|
||||
import {AddEventDialog} from "@/components/pages/calendar/AddEventDialog";
|
||||
import EditEventDialog from "@/components/pages/calendar/EditEventDialog";
|
||||
import {ManuallyAddEventModal} from "@/components/pages/calendar/ManuallyAddEventModal";
|
||||
import {CalendarHeader} from "@/components/pages/calendar/CalendarHeader";
|
||||
import {EventCalendar} from "@/components/pages/calendar/EventCalendar";
|
||||
|
||||
export const InnerCalendar = () => {
|
||||
const [calendarHeight, setCalendarHeight] = useState(0);
|
||||
const calendarContainerRef = useRef(null);
|
||||
|
||||
const onLayout = (event: LayoutChangeEvent) => {
|
||||
const {height} = event.nativeEvent.layout;
|
||||
setCalendarHeight(height);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<View
|
||||
style={{flex: 1, backgroundColor: "#fff", borderRadius: 30}}
|
||||
ref={calendarContainerRef}
|
||||
onLayout={onLayout}
|
||||
>
|
||||
<CalendarHeader/>
|
||||
{calendarHeight > 0 && (
|
||||
<EventCalendar
|
||||
calendarHeight={calendarHeight}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
<CalendarViewSwitch/>
|
||||
|
||||
<AddEventDialog/>
|
||||
<EditEventDialog/>
|
||||
<ManuallyAddEventModal/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@ -1,12 +1,10 @@
|
||||
import {
|
||||
Avatar,
|
||||
Button,
|
||||
ButtonSize,
|
||||
Colors,
|
||||
DateTimePicker,
|
||||
LoaderScreen,
|
||||
Modal,
|
||||
Picker,
|
||||
Switch,
|
||||
Text,
|
||||
TextField,
|
||||
@ -16,26 +14,20 @@ import {
|
||||
import {ScrollView} from "react-native-gesture-handler";
|
||||
import {useSafeAreaInsets} from "react-native-safe-area-context";
|
||||
import {useState} from "react";
|
||||
import {
|
||||
AntDesign,
|
||||
Feather,
|
||||
Ionicons,
|
||||
MaterialIcons,
|
||||
} from "@expo/vector-icons";
|
||||
import {AntDesign, Feather, Ionicons,} from "@expo/vector-icons";
|
||||
import {PickerMultiValue} from "react-native-ui-lib/src/components/picker/types";
|
||||
import { useAuthContext } from "@/contexts/AuthContext";
|
||||
import {useCreateEvent} from "@/hooks/firebase/useCreateEvent";
|
||||
import {EventData} from "@/hooks/firebase/types/eventData";
|
||||
import { addHours, setDate } from "date-fns";
|
||||
import {addHours} from "date-fns";
|
||||
import DropModalIcon from "@/assets/svgs/DropModalIcon";
|
||||
import { CalendarEvent, useCalendarContext } from "@/contexts/CalendarContext";
|
||||
import { repeatOptions } from "@/contexts/ToDosContext";
|
||||
import { ImageBackground, StyleSheet } from "react-native";
|
||||
import {StyleSheet} from "react-native";
|
||||
import ClockIcon from "@/assets/svgs/ClockIcon";
|
||||
import LockIcon from "@/assets/svgs/LockIcon";
|
||||
import MenuIcon from "@/assets/svgs/MenuIcon";
|
||||
import CameraIcon from "@/assets/svgs/CameraIcon";
|
||||
import AssigneesDisplay from "@/components/shared/AssigneesDisplay";
|
||||
import {useAtom} from "jotai";
|
||||
import {selectedNewEventDateAtom} from "@/components/pages/calendar/atoms";
|
||||
|
||||
const daysOfWeek = [
|
||||
{label: "Monday", value: "monday"},
|
||||
@ -47,19 +39,17 @@ const daysOfWeek = [
|
||||
{label: "Sunday", value: "sunday"},
|
||||
];
|
||||
|
||||
export const ManuallyAddEventModal = ({
|
||||
show,
|
||||
close,
|
||||
initialDate,
|
||||
}: {
|
||||
show: boolean;
|
||||
close: () => void;
|
||||
initialDate?: Date;
|
||||
}) => {
|
||||
const { addEvent } = useCalendarContext();
|
||||
const { user } = useAuthContext();
|
||||
export const ManuallyAddEventModal = () => {
|
||||
const insets = useSafeAreaInsets();
|
||||
|
||||
const [selectedNewEventDate, setSelectedNewEndDate] = useAtom(selectedNewEventDateAtom)
|
||||
|
||||
const {show, close, initialDate} = {
|
||||
show: !!selectedNewEventDate,
|
||||
close: () => setSelectedNewEndDate(undefined),
|
||||
initialDate: selectedNewEventDate
|
||||
}
|
||||
|
||||
const [title, setTitle] = useState<string>("");
|
||||
|
||||
const [isAllDay, setIsAllDay] = useState(false);
|
||||
@ -84,6 +74,8 @@ export const ManuallyAddEventModal = ({
|
||||
|
||||
const {mutateAsync: createEvent, isLoading, isError} = useCreateEvent();
|
||||
|
||||
if (!selectedNewEventDate) return null;
|
||||
|
||||
const formatDateTime = (date?: Date | string) => {
|
||||
if (!date) return undefined;
|
||||
return new Date(date).toLocaleDateString("en-US", {
|
||||
|
||||
9
components/pages/calendar/atoms.ts
Normal file
9
components/pages/calendar/atoms.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { atom } from 'jotai';
|
||||
import {CalendarEvent} from "@/components/pages/calendar/interfaces";
|
||||
|
||||
export const editVisibleAtom = atom<boolean>(false);
|
||||
export const eventForEditAtom = atom<CalendarEvent | undefined>(undefined);
|
||||
export const isFamilyViewAtom = atom<boolean>(false);
|
||||
export const modeAtom = atom<"week" | "month" | "day">("week");
|
||||
export const selectedDateAtom = atom<Date>(new Date());
|
||||
export const selectedNewEventDateAtom = atom<Date | undefined>(undefined);
|
||||
20
components/pages/calendar/constants.ts
Normal file
20
components/pages/calendar/constants.ts
Normal file
@ -0,0 +1,20 @@
|
||||
export const modeMap = new Map([
|
||||
[0, "day"],
|
||||
[1, "week"],
|
||||
[2, "month"],
|
||||
]);
|
||||
|
||||
export const months = [
|
||||
"January",
|
||||
"February",
|
||||
"March",
|
||||
"April",
|
||||
"May",
|
||||
"June",
|
||||
"July",
|
||||
"August",
|
||||
"September",
|
||||
"October",
|
||||
"November",
|
||||
"December",
|
||||
];
|
||||
13
components/pages/calendar/interfaces.ts
Normal file
13
components/pages/calendar/interfaces.ts
Normal file
@ -0,0 +1,13 @@
|
||||
export interface CalendarEvent {
|
||||
id?: number | string; // Unique identifier for the event
|
||||
user?: string;
|
||||
title: string; // Event title or name
|
||||
description?: string; // Optional description for the event
|
||||
start: Date; // Start date and time of the event
|
||||
end: Date; // End date and time of the event
|
||||
location?: string; // Optional event location
|
||||
allDay?: boolean; // Specifies if the event lasts all day
|
||||
eventColor?: string; // Optional color to represent the event
|
||||
participants?: string[]; // Optional list of participants or attendees
|
||||
private?: boolean;
|
||||
}
|
||||
@ -1,17 +1,17 @@
|
||||
import {Button, ButtonSize, Dialog, Text, TextField, View} from "react-native-ui-lib";
|
||||
import React, {useEffect, useState} from "react";
|
||||
import React, {useState} from "react";
|
||||
import {useSignIn} from "@/hooks/firebase/useSignIn";
|
||||
import {StyleSheet} from "react-native";
|
||||
import Toast from 'react-native-toast-message';
|
||||
import {useLoginWithQrCode} from "@/hooks/firebase/useLoginWithQrCode";
|
||||
import {Camera, CameraView} from 'expo-camera';
|
||||
import {BarCodeScanner} from "expo-barcode-scanner";
|
||||
|
||||
const SignInPage = ({setTab}: { setTab: React.Dispatch<React.SetStateAction<"register" | "login" | "reset-password">> }) => {
|
||||
const SignInPage = ({setTab}: {
|
||||
setTab: React.Dispatch<React.SetStateAction<"register" | "login" | "reset-password">>
|
||||
}) => {
|
||||
const [email, setEmail] = useState<string>("");
|
||||
const [password, setPassword] = useState<string>("");
|
||||
const [hasPermission, setHasPermission] = useState<boolean | null>(null);
|
||||
const [scanned, setScanned] = useState<boolean>(false);
|
||||
const [showCameraDialog, setShowCameraDialog] = useState<boolean>(false);
|
||||
|
||||
const {mutateAsync: signIn, error, isError} = useSignIn();
|
||||
@ -88,7 +88,7 @@ const SignInPage = ({setTab}: { setTab: React.Dispatch<React.SetStateAction<"re
|
||||
style={{marginBottom: 20}}
|
||||
backgroundColor="#fd1775"
|
||||
/>
|
||||
{isError && <Text center style={{marginBottom: 20}}>{`${error}`}</Text>}
|
||||
{isError && <Text center style={{marginBottom: 20}}>{`${error?.toString()?.split("]")?.[1]}`}</Text>}
|
||||
|
||||
<View row centerH marginB-5 gap-5>
|
||||
<Text text70>
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import { View, Text, Button } from "react-native-ui-lib";
|
||||
import {Button, Text, View} from "react-native-ui-lib";
|
||||
import React, {useState} from "react";
|
||||
import {StyleSheet} from "react-native";
|
||||
import { Entypo, Ionicons, Octicons } from "@expo/vector-icons";
|
||||
import {Octicons} from "@expo/vector-icons";
|
||||
import CalendarSettingsPage from "./CalendarSettingsPage";
|
||||
import ChoreRewardSettings from "./ChoreRewardSettings";
|
||||
import UserSettings from "./UserSettings";
|
||||
import { AuthContextProvider } from "@/contexts/AuthContext";
|
||||
import ProfileIcon from "@/assets/svgs/ProfileIcon";
|
||||
import CalendarIcon from "@/assets/svgs/CalendarIcon";
|
||||
import PrivacyPolicyIcon from "@/assets/svgs/PrivacyPolicyIcon";
|
||||
@ -18,6 +17,7 @@ const pageIndex = {
|
||||
chore: 3,
|
||||
policy: 4,
|
||||
};
|
||||
|
||||
const SettingsPage = () => {
|
||||
const [selectedPage, setSelectedPage] = useState<number>(0);
|
||||
return (
|
||||
|
||||
@ -99,6 +99,7 @@ export const AuthContextProvider: FC<{ children: ReactNode }> = ({children}) =>
|
||||
const onAuthStateChangedHandler = async (authUser: FirebaseAuthTypes.User | null) => {
|
||||
setUser(authUser);
|
||||
|
||||
|
||||
if (authUser) {
|
||||
await refreshProfileData(authUser);
|
||||
const pushToken = await registerForPushNotificationsAsync();
|
||||
|
||||
@ -1,194 +0,0 @@
|
||||
// CalendarContext.tsx
|
||||
import React, { createContext, useContext, useState, ReactNode } from "react";
|
||||
|
||||
// Define the CalendarEvent interface
|
||||
export interface CalendarEvent {
|
||||
id?: number | string; // Unique identifier for the event
|
||||
user?: string;
|
||||
title: string; // Event title or name
|
||||
description?: string; // Optional description for the event
|
||||
start: Date; // Start date and time of the event
|
||||
end: Date; // End date and time of the event
|
||||
location?: string; // Optional event location
|
||||
allDay?: boolean; // Specifies if the event lasts all day
|
||||
color?: string; // Optional color to represent the event
|
||||
participants?: string[]; // Optional list of participants or attendees
|
||||
private?: boolean;
|
||||
}
|
||||
|
||||
// Define the context type
|
||||
interface CalendarContextType {
|
||||
events: CalendarEvent[];
|
||||
familyEvents: CalendarEvent[];
|
||||
addEvent: (event: CalendarEvent) => void; // Function to add an event
|
||||
removeEvent: (id: number) => void; // Function to remove an event by ID
|
||||
updateEvent: (changes: Partial<CalendarEvent>, id?: number) => void;
|
||||
}
|
||||
|
||||
// Create the CalendarContext
|
||||
const CalendarContext = createContext<CalendarContextType | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
// Create a provider component
|
||||
export const CalendarProvider: React.FC<{ children: ReactNode }> = ({
|
||||
children,
|
||||
}) => {
|
||||
const [events, setEvents] = useState<CalendarEvent[]>([
|
||||
{
|
||||
id: 1,
|
||||
title: "Team Meeting",
|
||||
description: "Discuss project milestones and deadlines.",
|
||||
start: new Date("2024-09-15T10:00:00"),
|
||||
end: new Date("2024-09-15T11:00:00"),
|
||||
location: "Office Conference Room",
|
||||
allDay: false,
|
||||
color: "#FF5733",
|
||||
participants: ["Alice", "Bob", "Charlie"],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "Doctor's Appointment",
|
||||
description: "Annual check-up with Dr. Smith.",
|
||||
start: new Date("2024-09-20T14:30:00"),
|
||||
end: new Date("2024-09-20T15:30:00"),
|
||||
location: "Health Clinic",
|
||||
allDay: false,
|
||||
color: "#33FF57",
|
||||
participants: ["You"],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "Birthday Party",
|
||||
description: "Celebrating Sarah's 30th birthday.",
|
||||
start: new Date("2024-09-25T18:00:00"),
|
||||
end: new Date("2024-09-25T21:00:00"),
|
||||
location: "Sarah's House",
|
||||
allDay: false,
|
||||
color: "#3357FF",
|
||||
participants: ["You", "Sarah", "Tom", "Lily"],
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: "Project Deadline",
|
||||
description: "Final submission for the project.",
|
||||
start: new Date("2024-10-01T00:00:00"),
|
||||
end: new Date("2024-10-01T23:59:00"),
|
||||
location: "Online",
|
||||
allDay: false,
|
||||
color: "#FF33A1",
|
||||
participants: ["You"],
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: "Halloween Costume Party",
|
||||
description: "Join us for a spooky night of fun!",
|
||||
start: new Date("2024-10-31T19:00:00"),
|
||||
end: new Date("2024-10-31T23:00:00"),
|
||||
location: "Downtown Club",
|
||||
allDay: false,
|
||||
color: "#FFB733",
|
||||
participants: ["You", "Friends"],
|
||||
},
|
||||
]);
|
||||
|
||||
const [familyEvents, setFamilyEvents] = useState<CalendarEvent[]>([
|
||||
{
|
||||
id: 1,
|
||||
user: "jakesId",
|
||||
title: "Team Meeting",
|
||||
description: "Discuss project milestones and deadlines.",
|
||||
start: new Date("2024-09-10T10:00:00"),
|
||||
end: new Date("2024-09-10T11:00:00"),
|
||||
location: "Office Conference Room",
|
||||
allDay: false,
|
||||
color: "#FF5733",
|
||||
participants: ["Alice", "Bob", "Charlie"],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
user: "mikesId",
|
||||
title: "Doctor's Appointment",
|
||||
description: "Annual check-up with Dr. Smith.",
|
||||
start: new Date("2024-09-21T14:30:00"),
|
||||
end: new Date("2024-09-21T15:30:00"),
|
||||
location: "Health Clinic",
|
||||
allDay: false,
|
||||
color: "#33FF57",
|
||||
participants: ["You"],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
user: "jakesId",
|
||||
title: "Birthday Party",
|
||||
description: "Celebrating Sarah's 30th birthday.",
|
||||
start: new Date("2024-09-5T18:00:00"),
|
||||
end: new Date("2024-09-5T21:00:00"),
|
||||
location: "Sarah's House",
|
||||
allDay: false,
|
||||
color: "#3357FF",
|
||||
participants: ["You", "Sarah", "Tom", "Lily"],
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
user: "davidsId",
|
||||
title: "Project Deadline",
|
||||
description: "Final submission for the project.",
|
||||
start: new Date("2024-10-03T00:00:00"),
|
||||
end: new Date("2024-10-03T23:59:00"),
|
||||
location: "Online",
|
||||
allDay: false,
|
||||
color: "#FF33A1",
|
||||
participants: ["You"],
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
user: "jakesId",
|
||||
title: "Halloween Costume Party",
|
||||
description: "Join us for a spooky night of fun!",
|
||||
start: new Date("2024-10-02T19:00:00"),
|
||||
end: new Date("2024-10-02T23:00:00"),
|
||||
location: "Downtown Club",
|
||||
allDay: false,
|
||||
color: "#FFB733",
|
||||
participants: ["You", "Friends"],
|
||||
},
|
||||
]);
|
||||
|
||||
// Function to add an event
|
||||
const addEvent = (event: CalendarEvent) => {
|
||||
event.id = events.length + 1;
|
||||
setEvents((prevEvents) => [...prevEvents, event]);
|
||||
};
|
||||
|
||||
// Function to remove an event by ID
|
||||
const removeEvent = (id: number) => {
|
||||
setEvents((prevEvents) => prevEvents.filter((event) => event.id !== id));
|
||||
};
|
||||
|
||||
// Function to update an event
|
||||
const updateEvent = ( changes: Partial<CalendarEvent>, id?: number) => {
|
||||
setEvents((prevEvents) =>
|
||||
prevEvents.map((event) =>
|
||||
event.id === id ? { ...event, ...changes } : event
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<CalendarContext.Provider
|
||||
value={{ events, addEvent, removeEvent, updateEvent, familyEvents }}
|
||||
>
|
||||
{children}
|
||||
</CalendarContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
// Custom hook to use the CalendarContext
|
||||
export const useCalendarContext = () => {
|
||||
const context = useContext(CalendarContext);
|
||||
if (!context) {
|
||||
throw new Error("useCalendar must be used within a CalendarProvider");
|
||||
}
|
||||
return context;
|
||||
};
|
||||
@ -10,5 +10,5 @@ export interface EventData {
|
||||
surpriseEvent?: boolean,
|
||||
notes?: string,
|
||||
reminders?: string[]
|
||||
id?: string,
|
||||
id?: string | number,
|
||||
}
|
||||
@ -2,9 +2,12 @@ import {useQuery} from "react-query";
|
||||
import firestore from "@react-native-firebase/firestore";
|
||||
import {useAuthContext} from "@/contexts/AuthContext";
|
||||
import {colorMap} from "@/contexts/SettingsContext";
|
||||
import {useAtomValue} from "jotai";
|
||||
import {isFamilyViewAtom} from "@/components/pages/calendar/atoms";
|
||||
|
||||
export const useGetEvents = (isFamilyView: boolean) => {
|
||||
export const useGetEvents = () => {
|
||||
const { user, profileData } = useAuthContext();
|
||||
const isFamilyView = useAtomValue(isFamilyViewAtom)
|
||||
|
||||
return useQuery({
|
||||
queryKey: ["events", user?.uid, isFamilyView],
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
import {useAuthContext} from "@/contexts/AuthContext";
|
||||
import {useMutation, useQueryClient} from "react-query";
|
||||
import firestore from "@react-native-firebase/firestore";
|
||||
import {EventData} from "@/hooks/firebase/types/eventData";
|
||||
|
||||
export const useUpdateEvent = () => {
|
||||
const {user: currentUser} = useAuthContext()
|
||||
const queryClients = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
@ -13,7 +11,7 @@ export const useUpdateEvent = () => {
|
||||
try {
|
||||
await firestore()
|
||||
.collection("Events")
|
||||
.doc(eventData.id)
|
||||
.doc(`${eventData.id}`)
|
||||
.update(eventData);
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
|
||||
@ -441,7 +441,7 @@
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.cally.app;
|
||||
PRODUCT_NAME = "CallyFamilyPlanner";
|
||||
PRODUCT_NAME = CallyFamilyPlanner;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "cally/cally-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@ -472,7 +472,7 @@
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.cally.app;
|
||||
PRODUCT_NAME = "CallyFamilyPlanner";
|
||||
PRODUCT_NAME = CallyFamilyPlanner;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "cally/cally-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
||||
Reference in New Issue
Block a user