diff --git a/app/(auth)/_layout.tsx b/app/(auth)/_layout.tsx
index acb68fd..394628a 100644
--- a/app/(auth)/_layout.tsx
+++ b/app/(auth)/_layout.tsx
@@ -2,7 +2,13 @@ import React, { useEffect } from "react";
import { Drawer } from "expo-router/drawer";
import { useSignOut } from "@/hooks/firebase/useSignOut";
import { DrawerContentScrollView } from "@react-navigation/drawer";
-import { Button, ButtonSize, Text, View } from "react-native-ui-lib";
+import {
+ Button,
+ ButtonSize,
+ Text,
+ TouchableOpacity,
+ View,
+} from "react-native-ui-lib";
import { ImageBackground, StyleSheet } from "react-native";
import DrawerButton from "@/components/shared/DrawerButton";
import NavGroceryIcon from "@/assets/svgs/NavGroceryIcon";
@@ -11,7 +17,6 @@ import NavBrainDumpIcon from "@/assets/svgs/NavBrainDumpIcon";
import NavCalendarIcon from "@/assets/svgs/NavCalendarIcon";
import NavSettingsIcon from "@/assets/svgs/NavSettingsIcon";
import ViewSwitch from "@/components/pages/(tablet_pages)/ViewSwitch";
-import { MaterialIcons } from "@expo/vector-icons";
import { useSetAtom } from "jotai";
import {
isFamilyViewAtom,
@@ -23,6 +28,7 @@ import Ionicons from "@expo/vector-icons/Ionicons";
import * as Device from "expo-device";
import { DeviceType } from "expo-device";
import FeedbackNavIcon from "@/assets/svgs/FeedbackNavIcon";
+import DrawerIcon from "@/assets/svgs/DrawerIcon";
export default function TabLayout() {
const { mutateAsync: signOut } = useSignOut();
@@ -37,6 +43,20 @@ export default function TabLayout() {
detachInactiveScreens
screenOptions={({ navigation, route }) => ({
headerShown: true,
+ headerTitleAlign:
+ Device.deviceType === DeviceType.TABLET ? "left" : "center",
+ headerTitleStyle: {
+ fontFamily: "Manrope_600SemiBold",
+ fontSize: Device.deviceType === DeviceType.TABLET ? 22 : 17,
+ },
+ headerLeft: (props) => (
+
+
+
+ ),
headerRight: () => {
// Only show ViewSwitch on calendar and todos pages
const showViewSwitch = ["calendar", "todos", "index"].includes(
@@ -48,9 +68,8 @@ export default function TabLayout() {
) : null;
},
- headerStyle: { height: Device.deviceType === DeviceType.TABLET ? 100 : undefined},
drawerStyle: {
- width: Device.deviceType === DeviceType.TABLET ? "50%" : "90%",
+ width: Device.deviceType === DeviceType.TABLET ? "30%" : "90%",
backgroundColor: "#f9f8f7",
height: "100%",
},
@@ -117,7 +136,7 @@ export default function TabLayout() {
icon={}
/>
-
+
{/*
@@ -276,7 +301,10 @@ export default function TabLayout() {
name="todos"
options={{
drawerLabel: "To-Do",
- title: "To-Dos",
+ title:
+ Device.deviceType === DeviceType.TABLET
+ ? "Family To Do's"
+ : "To Do's",
}}
/>
{
setRefreshing(true);
@@ -18,45 +30,76 @@ export default function Screen() {
const minimumDelay = new Promise((resolve) => setTimeout(resolve, 1000));
try {
- setRefreshTrigger((prev) => !prev);
-
- await Promise.all([minimumDelay]);
+ if (isConnectedToGoogle || isConnectedToMicrosoft || isConnectedToApple) {
+ await Promise.all([resyncAllCalendars(), minimumDelay]);
+ } else {
+ await minimumDelay;
+ }
} catch (error) {
console.error("Refresh failed:", error);
} finally {
setRefreshing(false);
+ setShouldRefresh((prev) => !prev);
}
- }, [setRefreshTrigger]);
-
+ }, [
+ resyncAllCalendars,
+ isConnectedToGoogle,
+ isConnectedToMicrosoft,
+ isConnectedToApple,
+ ]);
+
return (
- <>
- {Device.deviceType === DeviceType.TABLET ? (
-
- ) : (
-
- }
- bounces={true}
- showsVerticalScrollIndicator={false}
- >
-
-
- )}
- >
+
+
+ {Device.deviceType === DeviceType.TABLET ? (
+
+ ) : (
+
+ )}
+
+
+
+ }
+ bounces={true}
+ showsVerticalScrollIndicator={false}
+ pointerEvents={refreshing || isSyncing ? "auto" : "none"}
+ />
+
);
}
diff --git a/assets/svgs/DrawerIcon.tsx b/assets/svgs/DrawerIcon.tsx
new file mode 100644
index 0000000..c3424e9
--- /dev/null
+++ b/assets/svgs/DrawerIcon.tsx
@@ -0,0 +1,19 @@
+import * as React from "react"
+import Svg, { SvgProps, Path } from "react-native-svg"
+const DrawerIcon = (props: SvgProps) => (
+
+)
+export default DrawerIcon
diff --git a/components/pages/(tablet_pages)/ViewSwitch.tsx b/components/pages/(tablet_pages)/ViewSwitch.tsx
index 0f1455e..b450364 100644
--- a/components/pages/(tablet_pages)/ViewSwitch.tsx
+++ b/components/pages/(tablet_pages)/ViewSwitch.tsx
@@ -1,92 +1,88 @@
-import { Text, TouchableOpacity, View } from "react-native-ui-lib";
-import React, { useEffect, useState } from "react";
+import { SegmentedControl, View } from "react-native-ui-lib";
+import React, { memo, useCallback, useEffect, useRef, useState } from "react";
import { StyleSheet } from "react-native";
-import { NavigationProp } from "@react-navigation/native";
-import view from "react-native-ui-lib/src/components/view";
+import { NavigationProp, useNavigationState } from "@react-navigation/native";
-interface ViewSwitchProps {
- navigation: NavigationProp; // Adjust according to your navigation structure
-}
-
-const ViewSwitch: React.FC = ({ navigation }) => {
- const [pageIndex, setPageIndex] = useState(navigation.getState().index);
+const ViewSwitch = memo(function ViewSwitch({
+ navigation,
+}: {
+ navigation: any;
+}) {
+ const isNavigating = useRef(false);
+ const navigationState = useNavigationState((state) => state);
+ const [selectedIndex, setSelectedIndex] = useState(
+ navigationState.index === 6 ? 1 : 0
+ );
+ // Sync the selected index with navigation state
useEffect(() => {
- setPageIndex(navigation.getState().index);
- }, [navigation.getState().index])
-
- return (
-
- {
- navigation.navigate("calendar");
- }}
- >
-
-
- Calendar
-
-
-
+ const newIndex = navigationState.index === 6 ? 1 : 0;
+ if (selectedIndex !== newIndex) {
+ setSelectedIndex(newIndex);
+ }
+ isNavigating.current = false;
+ }, [navigationState.index]);
- {
- navigation.navigate("todos");
- }}
- >
-
-
- Chores
-
-
-
+ const handleSegmentChange = useCallback(
+ (index: number) => {
+ if (isNavigating.current) return;
+ if (index === selectedIndex) return;
+
+ isNavigating.current = true;
+ setSelectedIndex(index);
+
+ // Delay navigation slightly to allow the segment control to update
+ requestAnimationFrame(() => {
+ navigation.navigate(index === 0 ? "calendar" : "todos");
+ });
+ console.log(selectedIndex)
+ },
+ [navigation, selectedIndex]
+ );
+
+ return (
+
+
);
-};
-
+});
export default ViewSwitch;
const styles = StyleSheet.create({
- switchBtnActive: {
- backgroundColor: "#ea156c",
- borderRadius: 50,
- width: 110,
- },
- switchBtn: {
+ container: {
+ borderRadius: 30,
backgroundColor: "#ebebeb",
- borderRadius: 50,
- width: 110,
+ shadowColor: "#000",
+ shadowOffset: { width: 0, height: 0 },
+ shadowOpacity: 0,
+ shadowRadius: 0,
+ elevation: 0,
},
- switchTxt: {
+ segmentContainer: {
+ height: 44,
+ width: 220,
+ },
+ segment: {
+ borderRadius: 50,
+ borderWidth: 0,
+ height: 44,
+ },
+ labelStyle: {
fontSize: 16,
fontFamily: "Manrope_600SemiBold",
},
diff --git a/components/pages/(tablet_pages)/calendar/TabletCalendarPage.tsx b/components/pages/(tablet_pages)/calendar/TabletCalendarPage.tsx
index 8465b9b..d951372 100644
--- a/components/pages/(tablet_pages)/calendar/TabletCalendarPage.tsx
+++ b/components/pages/(tablet_pages)/calendar/TabletCalendarPage.tsx
@@ -21,7 +21,9 @@ const TabletCalendarPage = () => {
return (
-
+
+
+
);
};
diff --git a/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx b/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx
index f5f2559..56beca6 100644
--- a/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx
+++ b/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx
@@ -38,7 +38,14 @@ const TabletChoresPage = () => {
{user.pfp ? (
) : (
diff --git a/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx b/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx
index 4471b2c..52a9d3e 100644
--- a/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx
+++ b/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx
@@ -1,6 +1,6 @@
import { View, Text, ViewProps } from "react-native-ui-lib";
-import React, { ReactNode } from "react";
-import { Dimensions, StyleSheet } from "react-native";
+import React, { ReactNode, useEffect, useState } from "react";
+import { Dimensions, StyleSheet, useWindowDimensions } from "react-native";
import UsersList from "./UsersList";
import { ScrollView } from "react-native-gesture-handler";
@@ -8,12 +8,52 @@ interface TabletContainerProps extends ViewProps {
children: ReactNode;
}
-const { width, height } = Dimensions.get("window");
-
const TabletContainer: React.FC = ({
children,
...props
}) => {
+ const window = useWindowDimensions();
+ const [containerWidth, setContainerWidth] = useState(Dimensions.get('window').width);
+ const [containerHeight, setContainerHeight] = useState(Dimensions.get('window').height);
+
+ // Update dimensions on mount and when window size changes
+ useEffect(() => {
+ const updateDimensions = () => {
+ setContainerWidth(window.width);
+ setContainerHeight(window.height);
+ };
+
+ updateDimensions();
+
+ // Force a second update after a brief delay to handle any initial rendering issues
+ const timer = setTimeout(updateDimensions, 100);
+
+ return () => clearTimeout(timer);
+ }, [window.width, window.height]);
+
+ const styles = StyleSheet.create({
+ container: {
+ backgroundColor: "white",
+ flex: 1,
+ flexDirection: 'row',
+ borderTopColor: "#a9a9a9",
+ width: containerWidth,
+ borderTopWidth: 1,
+ },
+ calendarContainer: {
+ backgroundColor: "white",
+ height: containerHeight,
+ width: containerWidth * 0.89,
+ },
+ profilesContainer: {
+ width: containerWidth * 0.11,
+ height: containerHeight,
+ borderLeftWidth: 1,
+ borderLeftColor: "#a9a9a9",
+ backgroundColor: "white",
+ },
+ });
+
return (
@@ -28,27 +68,4 @@ const TabletContainer: React.FC = ({
);
};
-const styles = StyleSheet.create({
- container: {
- backgroundColor: "white",
- flex: 1,
- flexDirection: 'row',
- borderTopColor: "#a9a9a9",
- width: '80%',
- borderTopWidth: 1,
- },
- calendarContainer: {
- backgroundColor: "white",
- height: height,
- width: width * 0.89,
- },
- profilesContainer: {
- width: width * 0.11,
- height: height,
- borderLeftWidth: 1,
- borderLeftColor: "#a9a9a9",
- backgroundColor: "white",
- },
-});
-
-export default TabletContainer;
+export default TabletContainer;
\ No newline at end of file
diff --git a/components/pages/(tablet_pages)/tablet_components/UsersList.tsx b/components/pages/(tablet_pages)/tablet_components/UsersList.tsx
index 82b488d..f62f0c7 100644
--- a/components/pages/(tablet_pages)/tablet_components/UsersList.tsx
+++ b/components/pages/(tablet_pages)/tablet_components/UsersList.tsx
@@ -20,7 +20,14 @@ const UsersList = () => {
) : (
diff --git a/components/pages/calendar/AddEventDialog.tsx b/components/pages/calendar/AddEventDialog.tsx
index e6aa012..702b571 100644
--- a/components/pages/calendar/AddEventDialog.tsx
+++ b/components/pages/calendar/AddEventDialog.tsx
@@ -1,5 +1,4 @@
import React, {useState} from "react";
-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 AddChoreDialog from "../todos/AddChoreDialog";
@@ -11,7 +10,6 @@ import NavToDosIcon from "@/assets/svgs/NavToDosIcon";
import {useSetAtom} from "jotai";
import {selectedNewEventDateAtom} from "@/components/pages/calendar/atoms";
import PlusIcon from "@/assets/svgs/PlusIcon";
-import {useNavigation} from "expo-router";
export const AddEventDialog = () => {
const [show, setShow] = useState(false);
@@ -33,7 +31,6 @@ export const AddEventDialog = () => {
}, 100);
};
- const navigation = useNavigation()
return (
<>
@@ -118,7 +115,7 @@ export const AddEventDialog = () => {
}}
label="Add To Do"
labelStyle={styles.btnLabel}
- onPress={() => navigation.navigate("todos")}
+ onPress={() => setChoreDialogVisible(true)}
iconSource={() => (
setRefreshEnabled(false);
- const enableRefreshControl = () => setRefreshEnabled(true);
return (
- {
- enableRefreshControl();
- console.log("yeah");
- return true;
- }}
- onResponderRelease={() => {
- disableRefreshControl();
- console.log("sure");
- console.log(refreshEnabledAtom)
- }}
- >
-
-
+ {/**/}
);
diff --git a/components/pages/calendar/EventCalendar.tsx b/components/pages/calendar/EventCalendar.tsx
index af143af..a2bb06f 100644
--- a/components/pages/calendar/EventCalendar.tsx
+++ b/components/pages/calendar/EventCalendar.tsx
@@ -324,6 +324,7 @@ export const EventCalendar: React.FC = React.memo(
ampm
// renderCustomDateForMonth={renderCustomDateForMonth}
/>
+
>
);
@@ -337,6 +338,7 @@ const styles = StyleSheet.create({
},
calHeader: {
borderWidth: 0,
+ paddingBottom: 60,
},
dayModeHeader: {
alignSelf: "flex-start",
diff --git a/components/pages/calendar/InnerCalendar.tsx b/components/pages/calendar/InnerCalendar.tsx
index 5744bdc..269682c 100644
--- a/components/pages/calendar/InnerCalendar.tsx
+++ b/components/pages/calendar/InnerCalendar.tsx
@@ -25,7 +25,7 @@ export const InnerCalendar = () => {
return (
<>
diff --git a/components/pages/grocery/EditGroceryItem.tsx b/components/pages/grocery/EditGroceryItem.tsx
index 812e98d..4f8e559 100644
--- a/components/pages/grocery/EditGroceryItem.tsx
+++ b/components/pages/grocery/EditGroceryItem.tsx
@@ -59,7 +59,6 @@ const EditGroceryItem = ({
const handleSubmit = () => {
inputRef?.current?.blur();
- console.log("CALLLLLL");
if (editGrocery.setSubmit) {
editGrocery.setSubmit(true);
}
diff --git a/components/pages/grocery/GroceryItem.tsx b/components/pages/grocery/GroceryItem.tsx
index 1e8faea..246375a 100644
--- a/components/pages/grocery/GroceryItem.tsx
+++ b/components/pages/grocery/GroceryItem.tsx
@@ -190,6 +190,8 @@ const GroceryItem = ({
aspectRatio: 1,
borderRadius: 22,
overflow: "hidden",
+ borderWidth: 2,
+ borderColor: profileData.eventColor
}}
/>
) : (
diff --git a/components/pages/settings/user_settings_views/MyGroup.tsx b/components/pages/settings/user_settings_views/MyGroup.tsx
index 613b334..77856e3 100644
--- a/components/pages/settings/user_settings_views/MyGroup.tsx
+++ b/components/pages/settings/user_settings_views/MyGroup.tsx
@@ -170,7 +170,14 @@ const MyGroup: React.FC = ({
>
{member.pfp ? (
diff --git a/components/pages/settings/user_settings_views/MyProfile.tsx b/components/pages/settings/user_settings_views/MyProfile.tsx
index e0ecc2e..cabb58c 100644
--- a/components/pages/settings/user_settings_views/MyProfile.tsx
+++ b/components/pages/settings/user_settings_views/MyProfile.tsx
@@ -173,7 +173,14 @@ const MyProfile = () => {
{pfpUri ? (
) : (
diff --git a/components/pages/settings/user_settings_views/UpdateUserDialog.tsx b/components/pages/settings/user_settings_views/UpdateUserDialog.tsx
new file mode 100644
index 0000000..eaa8807
--- /dev/null
+++ b/components/pages/settings/user_settings_views/UpdateUserDialog.tsx
@@ -0,0 +1,383 @@
+import {Button, Colors, Dialog, Image, Picker, Text, TextField, View} from "react-native-ui-lib";
+import {UserProfile} from "@/hooks/firebase/types/profileTypes";
+import {Dimensions, ScrollView, StyleSheet, TouchableOpacity} from "react-native";
+import {colorMap} from "@/constants/colorMap";
+import Ionicons from "@expo/vector-icons/Ionicons";
+import {AntDesign} from "@expo/vector-icons";
+import React, {useState} from "react";
+import * as Localization from "expo-localization";
+import * as ImagePicker from "expo-image-picker";
+import {useUpdateUserData} from "@/hooks/firebase/useUpdateUserData";
+import {useChangeProfilePicture} from "@/hooks/firebase/useChangeProfilePicture";
+import * as tz from "tzdata";
+import {PanningDirectionsEnum} from "react-native-ui-lib/src/incubator/panView";
+import {useUpdateSubUser} from "@/hooks/firebase/useUpdateSubUser";
+
+type Props = {
+ open: boolean,
+ handleClose: Function,
+ profileData: UserProfile
+}
+const UpdateUserDialog = ({open, handleClose, profileData} : Props) => {
+ const [timeZone, setTimeZone] = useState(
+ profileData?.timeZone! ?? Localization.getCalendars()[0].timeZone
+ );
+ const [lastName, setLastName] = useState(profileData?.lastName || "");
+ const [firstName, setFirstName] = useState(
+ profileData?.firstName || ""
+ );
+ const [profileImage, setProfileImage] = useState<
+ string | ImagePicker.ImagePickerAsset | null
+ >(profileData?.pfp || null);
+
+ const [selectedColor, setSelectedColor] = useState(
+ profileData?.eventColor ?? colorMap.pink
+ );
+
+ const { mutateAsync: updateUserData } = useUpdateUserData();
+ const { mutateAsync: updateSubUser} = useUpdateSubUser();
+ const { mutateAsync: changeProfilePicture } = useChangeProfilePicture();
+
+ const handleUpdateUserData = async () => {
+ await updateSubUser({ userProfile: {...profileData, firstName, lastName, timeZone, eventColor: selectedColor } });
+ handleClose();
+ };
+
+ const pickImage = async () => {
+ const permissionResult =
+ await ImagePicker.requestMediaLibraryPermissionsAsync();
+ if (!permissionResult.granted) {
+ alert("Permission to access camera roll is required!");
+ return;
+ }
+
+ const result = await ImagePicker.launchImageLibraryAsync({
+ mediaTypes: ImagePicker.MediaTypeOptions.Images,
+ allowsEditing: true,
+ aspect: [1, 1],
+ quality: 1,
+ });
+
+ if (!result.canceled) {
+ setProfileImage(result.assets[0].uri);
+ await changeProfilePicture(result.assets[0]);
+ }
+ };
+
+ const handleClearImage = async () => {
+ await updateUserData({ newUserData: { pfp: null } });
+ setProfileImage(null);
+ };
+
+ const pfpUri =
+ profileImage && typeof profileImage === "object" && "uri" in profileImage
+ ? profileImage.uri
+ : profileImage;
+
+ const handleChangeColor = (color: string) => {
+ setSelectedColor(color);
+ };
+
+ const {width} = Dimensions.get("screen");
+ return (
+
+ )
+};
+
+const timeZoneItems = Object.keys(tz.zones)
+ .sort()
+ .map((zone) => (
+
+ ));
+
+const styles = StyleSheet.create({
+ dialogContent: {
+ paddingHorizontal: 10,
+ paddingTop: 10,
+ paddingBottom: 10,
+ flexGrow: 1
+ },
+ cardTitle: {
+ fontFamily: "Manrope_500Medium",
+ fontSize: 15,
+ },
+ colorBox: {
+ aspectRatio: 1,
+ justifyContent: "center",
+ alignItems: "center",
+ width: 51,
+ borderRadius: 12,
+ },
+ card: {
+ marginVertical: 15,
+ backgroundColor: "white",
+ width: "100%",
+ borderRadius: 12,
+ paddingHorizontal: 20,
+ paddingVertical: 21,
+ },
+ pfpTxt: {
+ fontFamily: "Manrope_500Medium",
+ fontSize: 30,
+ color: "white",
+ },
+ pfp: {
+ aspectRatio: 1,
+ width: 65.54,
+ backgroundColor: "gray",
+ borderRadius: 20,
+ },
+ txtBox: {
+ backgroundColor: "#fafafa",
+ borderRadius: 50,
+ borderWidth: 2,
+ borderColor: "#cecece",
+ padding: 15,
+ height: 45,
+ fontFamily: "PlusJakartaSans_500Medium",
+ fontSize: 13,
+ },
+ subTit: {
+ fontFamily: "Manrope_500Medium",
+ fontSize: 15,
+ },
+ title: {
+ fontFamily: "Manrope_500Medium",
+ fontSize: 20
+ },
+ label: {
+ fontFamily: "PlusJakartaSans_500Medium",
+ fontSize: 12,
+ color: "#a1a1a1",
+ },
+ photoSet: {
+ fontFamily: "PlusJakartaSans_500Medium",
+ fontSize: 13.07,
+ },
+ jakarta12: {
+ paddingVertical: 10,
+ fontFamily: "PlusJakartaSans_500Medium",
+ fontSize: 12,
+ color: "#a1a1a1",
+ },
+ viewPicker: {
+ borderRadius: 50,
+ backgroundColor: Colors.grey80,
+ marginBottom: 16,
+ borderColor: Colors.grey50,
+ borderWidth: 1,
+ marginTop: 0,
+ height: 40,
+ zIndex: 10,
+ },
+ inViewPicker: {
+ borderRadius: 50,
+ paddingVertical: 12,
+ paddingHorizontal: 16,
+ marginBottom: 16,
+ marginTop: -20,
+ height: 40,
+ zIndex: 10,
+ },
+});
+
+export default UpdateUserDialog;
\ No newline at end of file
diff --git a/components/pages/settings/user_settings_views/UserOptions.tsx b/components/pages/settings/user_settings_views/UserOptions.tsx
index 936eedb..f703e0e 100644
--- a/components/pages/settings/user_settings_views/UserOptions.tsx
+++ b/components/pages/settings/user_settings_views/UserOptions.tsx
@@ -5,10 +5,12 @@ import { Dialog, Text, View, Button } from "react-native-ui-lib";
import MenuDotsIcon from "@/assets/svgs/MenuDotsIcon";
import { UserProfile } from "@/hooks/firebase/types/profileTypes";
import { useRemoveSubUser } from "@/hooks/firebase/useRemoveSubUser";
+import UpdateUserDialog from "@/components/pages/settings/user_settings_views/UpdateUserDialog";
const UserOptions = ({ user }: { user: UserProfile }) => {
const [visible, setVisible] = useState(false);
const { mutateAsync: removeSubUser } = useRemoveSubUser();
+ const [updateUserDialogOpen, setUpdateUserDialogOpen] = useState(false);
const handleDeleteUser = async () => {
try {
@@ -20,6 +22,14 @@ const UserOptions = ({ user }: { user: UserProfile }) => {
}
};
+ const handleOpenUpdateDialog = () => {
+ setUpdateUserDialogOpen(true);
+ }
+
+ const handleCloseUpdateDialog = () => {
+ setUpdateUserDialogOpen(false);
+ }
+
const menuOptions = [
{
id: "edit",
@@ -53,7 +63,7 @@ const UserOptions = ({ user }: { user: UserProfile }) => {
onPressAction={({ nativeEvent }) => {
switch (nativeEvent.event) {
case "edit":
- console.log("Edit User here");
+ handleOpenUpdateDialog();
break;
case "delete":
setTimeout(() => setVisible(true), 300);
@@ -104,6 +114,7 @@ const UserOptions = ({ user }: { user: UserProfile }) => {
/>
+ {updateUserDialogOpen && }
>
);
};
diff --git a/components/pages/todos/AddChoreDialog.tsx b/components/pages/todos/AddChoreDialog.tsx
index d095dc9..e5149f9 100644
--- a/components/pages/todos/AddChoreDialog.tsx
+++ b/components/pages/todos/AddChoreDialog.tsx
@@ -106,6 +106,24 @@ const AddChoreDialog = (addChoreDialogProps: IAddChoreDialog) => {
}, 500)
}, []);
+ const repeatPickerRef = useRef();
+ const showRepeatPicker = () => {
+ repeatPickerRef.current?.toggleExpandable(true);
+ }
+
+ const validateTodo = () => {
+ if (!todo?.title) {
+ Alert.alert('Alert', 'Title field cannot be empty');
+ return false;
+ }
+ if (!selectedAssignees || selectedAssignees?.length === 0) {
+ Alert.alert('Alert', 'Cannot have a todo without any assignees');
+ return false;
+ }
+
+ return true;
+ }
+
return (
-
+
{
if (value) {
- if (value.toString() == "None") {
- setTodo((oldValue) => ({
- ...oldValue,
- date: null,
- repeatType: "None",
- }));
- } else {
- setTodo((oldValue) => ({
- ...oldValue,
- date: new Date(),
- repeatType: value.toString(),
- }));
- }
+ setTodo((oldValue) => ({
+ ...oldValue,
+ date: new Date(),
+ repeatType: value.toString(),
+ }));
}
}}
topBarProps={{title: "Repeat"}}
diff --git a/components/pages/todos/ToDoItem.tsx b/components/pages/todos/ToDoItem.tsx
index 81fd8bf..4eff2c7 100644
--- a/components/pages/todos/ToDoItem.tsx
+++ b/components/pages/todos/ToDoItem.tsx
@@ -179,6 +179,8 @@ const ToDoItem = (props: {
aspectRatio: 1,
borderRadius: 22,
overflow: "hidden",
+ borderWidth: 2,
+ borderColor: member.eventColor || 'transparent'
}}
/>
) : (
@@ -187,6 +189,9 @@ const ToDoItem = (props: {
position: "relative",
width: 24.64,
aspectRatio: 1,
+ borderWidth: 2,
+ borderRadius: 100,
+ borderColor: member.eventColor || 'transparent'
}}
>
{
let sortedTodos = toDos.sort((a, b) => a.date - b.date);
return sortedTodos.reduce(
@@ -75,13 +80,16 @@ const groupToDosByDate = (toDos: IToDo[]) => {
const resolveFilterOptions = (members, user) => {
- return members?.map((member) => {
+ let options = members?.map((member) => {
let label = member?.firstName;
if (member.uid === user?.uid) {
- label = "Me";
+ label = FILTER_OPTIONS.ME;
}
- return (member.uid !== user?.uid || member.profileType !== ProfileType.PARENT) && {value: member?.uid, label: label};
+ return {value: member?.uid, label: label};
});
+ options.push({value: FILTER_OPTIONS.EVERYONE, label: FILTER_OPTIONS.EVERYONE})
+
+ return options;
}
const ToDosList = ({ isSettings }: { isSettings?: boolean }) => {
@@ -110,10 +118,15 @@ const ToDosList = ({ isSettings }: { isSettings?: boolean }) => {
useEffect(() => {
if (toDos && selectedFilter) {
- let filtered = toDos?.filter((todo) => todo.assignees?.includes(selectedFilter.value) || todo.creatorId === selectedFilter.value) || [];
+ let resolvedGroupedTodos;
+ if (selectedFilter?.value === FILTER_OPTIONS.EVERYONE) {
+ resolvedGroupedTodos = groupToDosByDate(toDos ?? []);
+ } else {
+ let filtered = toDos?.filter((todo) => todo.assignees?.includes(selectedFilter.value)) || [];
- let filteredGroupedTodos = groupToDosByDate(filtered || []);
- setGroupedToDos(filteredGroupedTodos || []);
+ resolvedGroupedTodos = groupToDosByDate(filtered || []);
+ }
+ setGroupedToDos(resolvedGroupedTodos || []);
}
}, [selectedFilter, JSON.stringify(toDos)]);
diff --git a/components/shared/AssigneesDisplay.tsx b/components/shared/AssigneesDisplay.tsx
index fdbcb44..b883ee2 100644
--- a/components/shared/AssigneesDisplay.tsx
+++ b/components/shared/AssigneesDisplay.tsx
@@ -28,11 +28,11 @@ const AssigneesDisplay = ({selectedAttendees, setSelectedAttendees}: {
{member?.pfp ? (
}
/>
) : (
-
+
{getInitials(member.firstName, member.lastName)}
diff --git a/components/shared/DrawerButton.tsx b/components/shared/DrawerButton.tsx
index 53b6c7f..6a15e9e 100644
--- a/components/shared/DrawerButton.tsx
+++ b/components/shared/DrawerButton.tsx
@@ -17,9 +17,9 @@ const DrawerButton = (props: IDrawerButtonProps) => {
const styles = StyleSheet.create({
iconContainer: {
- width: "70%",
+ width: isTablet ? '50%' : "70%",
aspectRatio: 1,
- borderRadius: 50,
+ borderRadius: 100,
},
labelStyle: { fontSize: 15, fontFamily: "Poppins_400Regular" },
});
@@ -42,7 +42,7 @@ const DrawerButton = (props: IDrawerButtonProps) => {
)}
style={{
- aspectRatio: 1,
+ aspectRatio: isTablet ? 1.2 : 1,
borderRadius: 18.55,
marginBottom: 12,
flexDirection: "column",
diff --git a/components/shared/HeaderTemplate.tsx b/components/shared/HeaderTemplate.tsx
index adbf51b..6005fd4 100644
--- a/components/shared/HeaderTemplate.tsx
+++ b/components/shared/HeaderTemplate.tsx
@@ -5,10 +5,8 @@ import { StyleSheet } from "react-native";
import { colorMap } from "@/constants/colorMap";
import { useAtom, useSetAtom } from "jotai";
import { isFamilyViewAtom, settingsPageIndex } from "../pages/calendar/atoms";
-import { useGetChildrenByParentId } from "@/hooks/firebase/useGetChildrenByParentId";
import { useGetFamilyMembers } from "@/hooks/firebase/useGetFamilyMembers";
import { UserProfile } from "@/hooks/firebase/types/profileTypes";
-import { child } from "@react-native-firebase/storage";
import CachedImage from "expo-cached-image";
import { router } from "expo-router";
@@ -24,7 +22,7 @@ const HeaderTemplate = (props: {
}) => {
const { user, profileData } = useAuthContext();
- const { data: members } = useGetFamilyMembers();
+ const { data: members, refetch } = useGetFamilyMembers();
const [children, setChildren] = useState([]);
const [isFamilyView] = useAtom(isFamilyViewAtom);
const setSettingsPageIndexAtom = useSetAtom(settingsPageIndex);
@@ -48,6 +46,7 @@ const HeaderTemplate = (props: {
overflow: "hidden",
marginRight: 20,
backgroundColor: profileData?.eventColor ?? colorMap.pink,
+ zIndex: 100,
},
pfpTxt: {
fontFamily: "Manrope_500Medium",
@@ -94,13 +93,23 @@ const HeaderTemplate = (props: {
- {isFamilyView && props.isCalendar && (
+ {isFamilyView && props.isCalendar && children.length > 0 && (
- {children?.slice(0, 3).map((child, index) => {
+ {children.slice(0, 3).map((child, index) => {
+ {
+ console.log("yeaaaah");
+ }
const bgColor: string = child.eventColor || colorMap.pink;
return child.pfp ? (
) : (
-
+
) : (
-
-
- {profileData?.firstName?.at(0)}
- {profileData?.lastName?.at(0)}
-
-
+ <>
+
+
+
+ {profileData?.firstName?.at(0)}
+ {profileData?.lastName?.at(0)}
+
+
+
+ {isFamilyView && props.isCalendar && children.length > 0 && (
+
+ {children.slice(0, 3).map((child, index) => {
+ {
+ console.log("yeaaaah");
+ }
+ const bgColor: string = child.eventColor || colorMap.pink;
+ return child.pfp ? (
+
+ ) : (
+
+
+
+ {child?.firstName?.at(0)}
+ {child?.firstName?.at(1)}
+
+
+
+ );
+ })}
+ {children?.length > 3 && (
+
+
+ +{children.length - 3}
+
+
+ )}
+
+ )}
+ >
)}
{props.isWelcome && (
diff --git a/hooks/firebase/useUpdateSubUser.ts b/hooks/firebase/useUpdateSubUser.ts
new file mode 100644
index 0000000..8a86aa9
--- /dev/null
+++ b/hooks/firebase/useUpdateSubUser.ts
@@ -0,0 +1,49 @@
+import {useMutation, useQueryClient} from "react-query";
+import {UserProfile} from "@/hooks/firebase/types/profileTypes";
+import {ProfileType, useAuthContext} from "@/contexts/AuthContext";
+import firestore from "@react-native-firebase/firestore";
+
+export const useUpdateSubUser = () => {
+ const queryClient = useQueryClient()
+ const {profileType} = useAuthContext()
+
+ return useMutation({
+ mutationKey: ["updateSubUser"],
+ mutationFn: async ({ userProfile }: { userProfile: Partial; }) => {
+ if (profileType === ProfileType.PARENT) {
+ if (userProfile) {
+ console.log("Updating user data for UID:", userProfile.uid);
+
+ try {
+ const updatedUserData = Object.fromEntries(
+ Object.entries(userProfile).map(([key, value]) =>
+ [key, value === null ? firestore.FieldValue.delete() : value]
+ )
+ );
+
+ console.log("Updated user data with deletions:", updatedUserData);
+
+ await firestore()
+ .collection("Profiles")
+ .doc(userProfile.uid)
+ .update(updatedUserData);
+
+ console.log("User data updated successfully, fetching updated profile...");
+
+ console.log("Profile data updated in context.");
+ } catch (e) {
+ console.error("Error updating user data:", e);
+ }
+ } else {
+ console.warn("No user found: user profile is undefined.");
+ }
+ } else {
+ throw Error("Can't update sub-users as a non-parent.")
+ }
+ },
+ onSuccess: () => {
+ queryClient.invalidateQueries({queryKey: ["getChildrenByParentId"]})
+ queryClient.invalidateQueries({queryKey: ["familyMembers"]})
+ }
+ });
+}
\ No newline at end of file