From 36ebfc38aa200393480c1168d5c9a44513a2bd31 Mon Sep 17 00:00:00 2001 From: ivic00 <102467664+ivic00@users.noreply.github.com> Date: Thu, 24 Oct 2024 21:34:12 +0200 Subject: [PATCH 1/5] added tablet view --- app/(auth)/_layout.tsx | 15 +++- app/(auth)/calendar/index.tsx | 6 +- app/(auth)/todos/index.tsx | 5 +- assets/svgs/MenuIcon.tsx | 4 +- assets/svgs/NavBrainDumpIcon.tsx | 19 +++-- assets/svgs/NavCalendarIcon.tsx | 12 +-- assets/svgs/NavGroceryIcon.tsx | 9 +- assets/svgs/NavToDosIcon.tsx | 2 +- .../pages/(tablet_pages)/ViewSwitch.tsx | 83 +++++++++++++++++++ .../calendar/TabletCalendarPage.tsx | 56 +++++++++++++ .../chores/TabletChoresPage.tsx | 27 ++++++ package.json | 1 + yarn.lock | 5 ++ 13 files changed, 213 insertions(+), 31 deletions(-) create mode 100644 components/pages/(tablet_pages)/ViewSwitch.tsx create mode 100644 components/pages/(tablet_pages)/calendar/TabletCalendarPage.tsx create mode 100644 components/pages/(tablet_pages)/chores/TabletChoresPage.tsx diff --git a/app/(auth)/_layout.tsx b/app/(auth)/_layout.tsx index 2b7927b..5edd485 100644 --- a/app/(auth)/_layout.tsx +++ b/app/(auth)/_layout.tsx @@ -6,7 +6,7 @@ import { DrawerItem, DrawerItemList, } from "@react-navigation/drawer"; -import { Button, View, Text, ButtonSize } from "react-native-ui-lib"; +import { Button, View, Text, ButtonSize, Constants } from "react-native-ui-lib"; import { StyleSheet } from "react-native"; import Feather from "@expo/vector-icons/Feather"; import DrawerButton from "@/components/shared/DrawerButton"; @@ -23,6 +23,7 @@ import NavToDosIcon from "@/assets/svgs/NavToDosIcon"; 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"; export default function TabLayout() { const { mutateAsync: signOut } = useSignOut(); @@ -33,6 +34,12 @@ export default function TabLayout() { detachInactiveScreens screenOptions={{ headerShown: true, + headerRight: () => + Constants.isTablet ? ( + + ) : ( + <> + ), drawerStyle: { width: "90%", backgroundColor: "#f9f8f7", @@ -203,7 +210,7 @@ const styles = StyleSheet.create({ label: { fontFamily: "Poppins_400Medium", fontSize: 15 }, title: { fontSize: 26.13, - fontFamily: 'Manrope_600SemiBold', - color: "#262627" - } + fontFamily: "Manrope_600SemiBold", + color: "#262627", + }, }); diff --git a/app/(auth)/calendar/index.tsx b/app/(auth)/calendar/index.tsx index 1b239ac..8d47936 100644 --- a/app/(auth)/calendar/index.tsx +++ b/app/(auth)/calendar/index.tsx @@ -1,8 +1,8 @@ import React from "react"; import CalendarPage from "@/components/pages/calendar/CalendarPage"; +import { Constants } from "react-native-ui-lib"; +import TabletCalendarPage from "@/components/pages/(tablet_pages)/calendar/TabletCalendarPage"; export default function Screen() { - return ( - - ); + return <>{Constants.isTablet ? : }; } diff --git a/app/(auth)/todos/index.tsx b/app/(auth)/todos/index.tsx index 7ccb813..518f346 100644 --- a/app/(auth)/todos/index.tsx +++ b/app/(auth)/todos/index.tsx @@ -1,3 +1,4 @@ +import TabletChoresPage from "@/components/pages/(tablet_pages)/chores/TabletChoresPage"; import AddChore from "@/components/pages/todos/AddChore"; import ProgressCard from "@/components/pages/todos/ProgressCard"; import ToDoItem from "@/components/pages/todos/ToDoItem"; @@ -8,12 +9,12 @@ import { useAuthContext } from "@/contexts/AuthContext"; import { ToDosContextProvider, useToDosContext } from "@/contexts/ToDosContext"; import { AntDesign } from "@expo/vector-icons"; import { ScrollView } from "react-native-gesture-handler"; -import { Button, ButtonSize, View, Text } from "react-native-ui-lib"; +import { Button, ButtonSize, View, Text, Constants } from "react-native-ui-lib"; export default function Screen() { return ( - + {Constants.isTablet ? : } ); } diff --git a/assets/svgs/MenuIcon.tsx b/assets/svgs/MenuIcon.tsx index ad114a9..f54091a 100644 --- a/assets/svgs/MenuIcon.tsx +++ b/assets/svgs/MenuIcon.tsx @@ -7,8 +7,8 @@ interface MenuIconProps extends SvgProps { const MenuIcon: React.FC = (props) => ( = (props) => ( = (props) => ( d="M21.1.859H3.994C2.284.859.976 2.167.976 3.877c0 1.71 1.308 3.019 3.018 3.019H21.1V27.02" /> = (props) => ( d="M21.1 27.021H3.994c-1.71 0-3.018-1.308-3.018-3.018V3.878M21.097 3.878H3.991" /> = (props) => ( d="M6.007 6.897v12.075l3.019-1.006 3.018 1.006V6.897" /> -) -export default NavBrainDumpIcon +); +export default NavBrainDumpIcon; diff --git a/assets/svgs/NavCalendarIcon.tsx b/assets/svgs/NavCalendarIcon.tsx index 5744643..c7db638 100644 --- a/assets/svgs/NavCalendarIcon.tsx +++ b/assets/svgs/NavCalendarIcon.tsx @@ -1,9 +1,9 @@ -import * as React from "react" -import Svg, { Path, SvgProps } from "react-native-svg" +import * as React from "react"; +import Svg, { Path, SvgProps } from "react-native-svg"; const NavCalendarIcon: React.FC = (props) => ( = (props) => ( d="M1.825 10.075h25.043m-5.565 5.567L7.39 15.64m4.638 5.566H7.39m0-19.478V4.51m13.913-2.782V4.51M6.277 26.77h16.139c1.558 0 2.337 0 2.933-.303.523-.267.949-.692 1.216-1.216.303-.595.303-1.375.303-2.933V8.962c0-1.558 0-2.337-.303-2.933a2.782 2.782 0 0 0-1.216-1.216c-.596-.303-1.375-.303-2.933-.303H6.277c-1.558 0-2.337 0-2.933.303-.523.267-.949.693-1.216 1.216-.303.596-.303 1.375-.303 2.933v13.356c0 1.558 0 2.338.303 2.933.267.523.693.95 1.216 1.216.596.303 1.375.303 2.933.303Z" /> -) -export default NavCalendarIcon +); +export default NavCalendarIcon; diff --git a/assets/svgs/NavGroceryIcon.tsx b/assets/svgs/NavGroceryIcon.tsx index cb219b8..3bda0bf 100644 --- a/assets/svgs/NavGroceryIcon.tsx +++ b/assets/svgs/NavGroceryIcon.tsx @@ -2,17 +2,18 @@ import * as React from "react"; import Svg, { Path, SvgProps } from "react-native-svg"; const NavGroceryIcon: React.FC = (props) => ( diff --git a/assets/svgs/NavToDosIcon.tsx b/assets/svgs/NavToDosIcon.tsx index 9592aa3..1da328d 100644 --- a/assets/svgs/NavToDosIcon.tsx +++ b/assets/svgs/NavToDosIcon.tsx @@ -3,7 +3,7 @@ import Svg, { Path, SvgProps } from "react-native-svg" const NavToDosIcon: React.FC = (props) => ( { + const [view, setView] = useState(false); + + return ( + + { + setView(true); + }} + > + + + Calendar + + + + + { + setView(false); + }} + > + + + Chores + + + + + ); +}; + +export default ViewSwitch; + +const styles = StyleSheet.create({ + switchBtnActive: { + backgroundColor: "#ea156c", + borderRadius: 50, + width: 110, + }, + switchBtn: { + backgroundColor: "#ebebeb", + borderRadius: 50, + width: 110, + }, + switchTxt: { + fontSize: 16, + fontFamily: "Manrope_600SemiBold", + }, +}); diff --git a/components/pages/(tablet_pages)/calendar/TabletCalendarPage.tsx b/components/pages/(tablet_pages)/calendar/TabletCalendarPage.tsx new file mode 100644 index 0000000..3e709e0 --- /dev/null +++ b/components/pages/(tablet_pages)/calendar/TabletCalendarPage.tsx @@ -0,0 +1,56 @@ +import { View, Text } from "react-native-ui-lib"; +import React, { useEffect } from "react"; +import * as ScreenOrientation from "expo-screen-orientation"; +import { Dimensions, StyleSheet } from "react-native"; +import { InnerCalendar } from "../../calendar/InnerCalendar"; + +const { width, height } = Dimensions.get("window"); + +const TabletCalendarPage = () => { + // Function to lock the screen orientation to landscape + const lockScreenOrientation = async () => { + await ScreenOrientation.lockAsync( + ScreenOrientation.OrientationLock.LANDSCAPE_LEFT + ); + }; + + useEffect(() => { + lockScreenOrientation(); // Lock orientation when the component mounts + + return () => { + // Optional: Unlock to default when the component unmounts + ScreenOrientation.unlockAsync(); + }; + }, []); + + return ( + + + + + + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + backgroundColor: "white", + width: "100%", + flex: 1, + }, + calendarContainer: { + backgroundColor: "white", + height: height, + width: width * 0.85, + }, + profilesContainer: { + width: width * 0.15, + backgroundColor: "green", + height: height, + }, +}); + +export default TabletCalendarPage; diff --git a/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx b/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx new file mode 100644 index 0000000..3bf40d8 --- /dev/null +++ b/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx @@ -0,0 +1,27 @@ +import React, { useEffect } from 'react'; +import { View, Text } from 'react-native'; +import * as ScreenOrientation from 'expo-screen-orientation'; + +const TabletChoresPage = () => { + // Function to lock the screen orientation to landscape + const lockScreenOrientation = async () => { + await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE_LEFT); + }; + + useEffect(() => { + lockScreenOrientation(); // Lock orientation when the component mounts + + return () => { + // Optional: Unlock to default when the component unmounts + ScreenOrientation.unlockAsync(); + }; + }, []); + + return ( + + TabletChoresPage + + ); +}; + +export default TabletChoresPage; diff --git a/package.json b/package.json index c6e9a7b..f05e3e3 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "expo-localization": "~15.0.3", "expo-notifications": "~0.28.18", "expo-router": "~3.5.20", + "expo-screen-orientation": "~7.0.5", "expo-splash-screen": "~0.27.5", "expo-status-bar": "~1.12.1", "expo-system-ui": "~3.0.7", diff --git a/yarn.lock b/yarn.lock index f22d5d1..4c0db75 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5232,6 +5232,11 @@ expo-router@~3.5.20: react-native-helmet-async "2.0.4" schema-utils "^4.0.1" +expo-screen-orientation@~7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/expo-screen-orientation/-/expo-screen-orientation-7.0.5.tgz#0a517982151c6519fa4b10ce27047de39c1f92cf" + integrity sha512-1j0MzVzYpjKQo4BWowQ3ZYwC3OnddX/8k06C8VYTAxMyd8ou1k+rG4tm+GIV2n2RSzc3g7cfPlQwSYr3/SGmbg== + expo-splash-screen@0.27.5, expo-splash-screen@~0.27.5: version "0.27.5" resolved "https://registry.npmjs.org/expo-splash-screen/-/expo-splash-screen-0.27.5.tgz" From 6dc09ee44873c270cb45043959b49850f482b27f Mon Sep 17 00:00:00 2001 From: ivic00 <102467664+ivic00@users.noreply.github.com> Date: Sun, 3 Nov 2024 18:39:32 +0100 Subject: [PATCH 2/5] changes to tablet detection and more --- app/(auth)/_layout.tsx | 13 ++++-- app/(auth)/calendar/index.tsx | 12 ++++- app/(auth)/todos/index.tsx | 7 ++- .../pages/(tablet_pages)/ViewSwitch.tsx | 28 +++++++---- .../calendar/TabletCalendarPage.tsx | 39 +++------------- .../chores/TabletChoresPage.tsx | 2 +- .../tablet_components/TabletContainer.tsx | 46 +++++++++++++++++++ .../tablet_components/UsersList.tsx | 27 +++++++++++ 8 files changed, 124 insertions(+), 50 deletions(-) create mode 100644 components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx create mode 100644 components/pages/(tablet_pages)/tablet_components/UsersList.tsx diff --git a/app/(auth)/_layout.tsx b/app/(auth)/_layout.tsx index 13d04c3..d91d8d6 100644 --- a/app/(auth)/_layout.tsx +++ b/app/(auth)/_layout.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect } from "react"; import { Drawer } from "expo-router/drawer"; import { useSignOut } from "@/hooks/firebase/useSignOut"; import { @@ -32,6 +32,9 @@ import { userSettingsView, } from "@/components/pages/calendar/atoms"; import FeedbackNavIcon from "@/assets/svgs/FeedbackNavIcon"; +import Constants from "expo-constants"; +import * as Device from "expo-device"; +import { DeviceType } from "expo-device"; export default function TabLayout() { const { mutateAsync: signOut } = useSignOut(); @@ -44,11 +47,11 @@ export default function TabLayout() { ({ headerShown: true, headerRight: () => - Constants.isTablet ? ( - + Device.deviceType === DeviceType.TABLET ? ( + ) : ( <> ), @@ -57,7 +60,7 @@ export default function TabLayout() { backgroundColor: "#f9f8f7", height: "100%", }, - }} + })} drawerContent={(props) => { return ( diff --git a/app/(auth)/calendar/index.tsx b/app/(auth)/calendar/index.tsx index 8d47936..444563f 100644 --- a/app/(auth)/calendar/index.tsx +++ b/app/(auth)/calendar/index.tsx @@ -2,7 +2,17 @@ import React from "react"; import CalendarPage from "@/components/pages/calendar/CalendarPage"; import { Constants } from "react-native-ui-lib"; import TabletCalendarPage from "@/components/pages/(tablet_pages)/calendar/TabletCalendarPage"; +import { DeviceType } from "expo-device"; +import * as Device from "expo-device"; export default function Screen() { - return <>{Constants.isTablet ? : }; + return ( + <> + {Device.deviceType === DeviceType.TABLET ? ( + + ) : ( + + )} + + ); } diff --git a/app/(auth)/todos/index.tsx b/app/(auth)/todos/index.tsx index 518f346..33103a5 100644 --- a/app/(auth)/todos/index.tsx +++ b/app/(auth)/todos/index.tsx @@ -10,11 +10,16 @@ import { ToDosContextProvider, useToDosContext } from "@/contexts/ToDosContext"; import { AntDesign } from "@expo/vector-icons"; import { ScrollView } from "react-native-gesture-handler"; import { Button, ButtonSize, View, Text, Constants } from "react-native-ui-lib"; +import * as Device from "expo-device"; export default function Screen() { return ( - {Constants.isTablet ? : } + {Device.deviceType === Device.DeviceType.TABLET ? ( + + ) : ( + + )} ); } diff --git a/components/pages/(tablet_pages)/ViewSwitch.tsx b/components/pages/(tablet_pages)/ViewSwitch.tsx index d051681..0f1455e 100644 --- a/components/pages/(tablet_pages)/ViewSwitch.tsx +++ b/components/pages/(tablet_pages)/ViewSwitch.tsx @@ -1,10 +1,20 @@ import { Text, TouchableOpacity, View } from "react-native-ui-lib"; -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { StyleSheet } from "react-native"; +import { NavigationProp } from "@react-navigation/native"; +import view from "react-native-ui-lib/src/components/view"; -const ViewSwitch = () => { - const [view, setView] = useState(false); +interface ViewSwitchProps { + navigation: NavigationProp; // Adjust according to your navigation structure +} +const ViewSwitch: React.FC = ({ navigation }) => { + const [pageIndex, setPageIndex] = useState(navigation.getState().index); + + useEffect(() => { + setPageIndex(navigation.getState().index); + }, [navigation.getState().index]) + return ( { > { - setView(true); + navigation.navigate("calendar"); }} > { centerH height={54} paddingH-15 - style={view ? styles.switchBtnActive : styles.switchBtn} + style={ pageIndex == 1 || pageIndex == 0 ? styles.switchBtnActive : styles.switchBtn} > - + Calendar @@ -44,7 +54,7 @@ const ViewSwitch = () => { { - setView(false); + navigation.navigate("todos"); }} > { centerH height={54} paddingH-15 - style={!view ? styles.switchBtnActive : styles.switchBtn} + style={pageIndex == 6 ? styles.switchBtnActive : styles.switchBtn} > - + Chores diff --git a/components/pages/(tablet_pages)/calendar/TabletCalendarPage.tsx b/components/pages/(tablet_pages)/calendar/TabletCalendarPage.tsx index 3e709e0..8465b9b 100644 --- a/components/pages/(tablet_pages)/calendar/TabletCalendarPage.tsx +++ b/components/pages/(tablet_pages)/calendar/TabletCalendarPage.tsx @@ -1,56 +1,29 @@ import { View, Text } from "react-native-ui-lib"; import React, { useEffect } from "react"; import * as ScreenOrientation from "expo-screen-orientation"; -import { Dimensions, StyleSheet } from "react-native"; import { InnerCalendar } from "../../calendar/InnerCalendar"; - -const { width, height } = Dimensions.get("window"); +import TabletContainer from "../tablet_components/TabletContainer"; const TabletCalendarPage = () => { - // Function to lock the screen orientation to landscape const lockScreenOrientation = async () => { await ScreenOrientation.lockAsync( - ScreenOrientation.OrientationLock.LANDSCAPE_LEFT + ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT ); }; useEffect(() => { - lockScreenOrientation(); // Lock orientation when the component mounts + lockScreenOrientation(); return () => { - // Optional: Unlock to default when the component unmounts ScreenOrientation.unlockAsync(); }; }, []); return ( - - - - - - - - + + + ); }; -const styles = StyleSheet.create({ - container: { - backgroundColor: "white", - width: "100%", - flex: 1, - }, - calendarContainer: { - backgroundColor: "white", - height: height, - width: width * 0.85, - }, - profilesContainer: { - width: width * 0.15, - backgroundColor: "green", - height: height, - }, -}); - export default TabletCalendarPage; diff --git a/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx b/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx index 3bf40d8..c05b5d4 100644 --- a/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx +++ b/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx @@ -5,7 +5,7 @@ import * as ScreenOrientation from 'expo-screen-orientation'; const TabletChoresPage = () => { // Function to lock the screen orientation to landscape const lockScreenOrientation = async () => { - await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE_LEFT); + await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT); }; useEffect(() => { diff --git a/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx b/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx new file mode 100644 index 0000000..168f6ff --- /dev/null +++ b/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx @@ -0,0 +1,46 @@ +import { View, Text, ViewProps } from "react-native-ui-lib"; +import React, { ReactNode } from "react"; +import { Dimensions, StyleSheet } from "react-native"; +import UsersList from "./UsersList"; + +interface TabletContainerProps extends ViewProps { + children: ReactNode; +} + +const { width, height } = Dimensions.get("window"); + +const TabletContainer: React.FC = ({ + children, + ...props +}) => { + return ( + + + {children} + + + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + backgroundColor: "white", + width: "100%", + flex: 1, + }, + calendarContainer: { + backgroundColor: "white", + height: height, + width: width * 0.85, + }, + profilesContainer: { + width: width * 0.15, + backgroundColor: "green", + height: height, + }, +}); + +export default TabletContainer; diff --git a/components/pages/(tablet_pages)/tablet_components/UsersList.tsx b/components/pages/(tablet_pages)/tablet_components/UsersList.tsx new file mode 100644 index 0000000..6104a1e --- /dev/null +++ b/components/pages/(tablet_pages)/tablet_components/UsersList.tsx @@ -0,0 +1,27 @@ +import { View, Text } from "react-native-ui-lib"; +import React from "react"; + +const UsersList = () => { + return ( + + + + + ); +}; + +export default UsersList; From e3084a70a7593b51297f8f7ddc5979c8c85680e9 Mon Sep 17 00:00:00 2001 From: ivic00 <102467664+ivic00@users.noreply.github.com> Date: Sun, 10 Nov 2024 13:53:19 +0100 Subject: [PATCH 3/5] added pfp to tablet view --- .../tablet_components/TabletContainer.tsx | 9 ++- .../tablet_components/UsersList.tsx | 74 ++++++++++++++----- 2 files changed, 63 insertions(+), 20 deletions(-) diff --git a/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx b/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx index 168f6ff..b00bdd0 100644 --- a/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx +++ b/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx @@ -2,6 +2,7 @@ import { View, Text, ViewProps } from "react-native-ui-lib"; import React, { ReactNode } from "react"; import { Dimensions, StyleSheet } from "react-native"; import UsersList from "./UsersList"; +import { ScrollView } from "react-native-gesture-handler"; interface TabletContainerProps extends ViewProps { children: ReactNode; @@ -18,7 +19,9 @@ const TabletContainer: React.FC = ({ {children} - + + + @@ -28,7 +31,6 @@ const TabletContainer: React.FC = ({ const styles = StyleSheet.create({ container: { backgroundColor: "white", - width: "100%", flex: 1, }, calendarContainer: { @@ -38,8 +40,9 @@ const styles = StyleSheet.create({ }, profilesContainer: { width: width * 0.15, - backgroundColor: "green", height: height, + borderLeftWidth: 1, + borderLeftColor: "#a9a9a9", }, }); diff --git a/components/pages/(tablet_pages)/tablet_components/UsersList.tsx b/components/pages/(tablet_pages)/tablet_components/UsersList.tsx index 6104a1e..82b488d 100644 --- a/components/pages/(tablet_pages)/tablet_components/UsersList.tsx +++ b/components/pages/(tablet_pages)/tablet_components/UsersList.tsx @@ -1,27 +1,67 @@ import { View, Text } from "react-native-ui-lib"; import React from "react"; +import { useGetFamilyMembers } from "@/hooks/firebase/useGetFamilyMembers"; +import { ImageBackground, StyleSheet } from "react-native"; +import { colorMap } from "@/constants/colorMap"; const UsersList = () => { + const { data: familyMembers } = useGetFamilyMembers(); + + const capitalizeFirstLetter = (str: string) => { + if (!str) return ''; + return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase(); + }; + return ( - - - + + {familyMembers?.map((member, index) => ( + <> + {member.pfp ? ( + + ) : ( + + {member.firstName.at(0)} + {member.lastName.at(0)} + + } + /> + )} + {member.firstName} + {capitalizeFirstLetter(member.userType)} + + ))} ); }; +const styles = StyleSheet.create({ + pfp: { + aspectRatio: 1, + width: 113, + borderRadius: 100, + marginBottom: 8, + }, + fName: { + fontFamily: "Manrope_600SemiBold", + fontSize: 18.15, + }, + role: { + fontFamily: "Manrope_600SemiBold", + fontSize: 12.95, + color: "#9b9b9b", + marginBottom: 20, + }, +}); + export default UsersList; From 1d3daa49ec6d565a57dd38b7ae7a613c93dedaf3 Mon Sep 17 00:00:00 2001 From: ivic00 <102467664+ivic00@users.noreply.github.com> Date: Sun, 10 Nov 2024 14:07:27 +0100 Subject: [PATCH 4/5] fixed chores page tablet --- .../pages/(tablet_pages)/chores/TabletChoresPage.tsx | 8 +++++--- .../(tablet_pages)/tablet_components/TabletContainer.tsx | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx b/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx index c05b5d4..4066a57 100644 --- a/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx +++ b/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx @@ -1,6 +1,8 @@ import React, { useEffect } from 'react'; import { View, Text } from 'react-native'; import * as ScreenOrientation from 'expo-screen-orientation'; +import TabletContainer from '../tablet_components/TabletContainer'; +import ToDosPage from '../../todos/ToDosPage'; const TabletChoresPage = () => { // Function to lock the screen orientation to landscape @@ -18,9 +20,9 @@ const TabletChoresPage = () => { }, []); return ( - - TabletChoresPage - + + + ); }; diff --git a/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx b/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx index b00bdd0..c6aa220 100644 --- a/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx +++ b/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx @@ -31,6 +31,7 @@ const TabletContainer: React.FC = ({ const styles = StyleSheet.create({ container: { backgroundColor: "white", + width: width, flex: 1, }, calendarContainer: { From 653f72dc94d36a50c832bbbebfe4d9cdd054adc7 Mon Sep 17 00:00:00 2001 From: ivic00 <102467664+ivic00@users.noreply.github.com> Date: Sun, 17 Nov 2024 19:09:13 +0100 Subject: [PATCH 5/5] added chores page --- app/(auth)/calendar/index.tsx | 6 +- .../chores/SingleUserChoreList.tsx | 271 ++++++++++++++++++ .../chores/TabletChoresPage.tsx | 72 ++++- .../tablet_components/TabletContainer.tsx | 8 +- components/pages/todos/ToDoItem.tsx | 4 +- 5 files changed, 345 insertions(+), 16 deletions(-) create mode 100644 components/pages/(tablet_pages)/chores/SingleUserChoreList.tsx diff --git a/app/(auth)/calendar/index.tsx b/app/(auth)/calendar/index.tsx index 444563f..ccce6a8 100644 --- a/app/(auth)/calendar/index.tsx +++ b/app/(auth)/calendar/index.tsx @@ -1,18 +1,18 @@ import React from "react"; import CalendarPage from "@/components/pages/calendar/CalendarPage"; -import { Constants } from "react-native-ui-lib"; +import { View } from "react-native-ui-lib"; import TabletCalendarPage from "@/components/pages/(tablet_pages)/calendar/TabletCalendarPage"; import { DeviceType } from "expo-device"; import * as Device from "expo-device"; export default function Screen() { return ( - <> + {Device.deviceType === DeviceType.TABLET ? ( ) : ( )} - + ); } diff --git a/components/pages/(tablet_pages)/chores/SingleUserChoreList.tsx b/components/pages/(tablet_pages)/chores/SingleUserChoreList.tsx new file mode 100644 index 0000000..c1a2e35 --- /dev/null +++ b/components/pages/(tablet_pages)/chores/SingleUserChoreList.tsx @@ -0,0 +1,271 @@ +import { View, Text, TouchableOpacity, Icon } from "react-native-ui-lib"; +import React, { useState } from "react"; +import { useToDosContext } from "@/contexts/ToDosContext"; +import { + addDays, + format, + isToday, + isTomorrow, + isWithinInterval, +} from "date-fns"; +import { AntDesign } from "@expo/vector-icons"; +import { IToDo } from "@/hooks/firebase/types/todoData"; +import ToDoItem from "../../todos/ToDoItem"; +import { UserProfile } from "@/hooks/firebase/types/profileTypes"; + +const groupToDosByDate = (toDos: IToDo[]) => { + let sortedTodos = toDos.sort((a, b) => a.date - b.date); + return sortedTodos.reduce( + (groups, toDo) => { + let dateKey; + let subDateKey; + + const isNext7Days = (date: Date) => { + const today = new Date(); + return isWithinInterval(date, { start: today, end: addDays(today, 7) }); + }; + + const isNext30Days = (date: Date) => { + const today = new Date(); + return isWithinInterval(date, { + start: today, + end: addDays(today, 30), + }); + }; + + if (toDo.date === null) { + dateKey = "No Date"; + } else if (isToday(toDo.date)) { + dateKey = "Today"; + } else if (isTomorrow(toDo.date)) { + dateKey = "Tomorrow"; + } else if (isNext7Days(toDo.date)) { + dateKey = "Next 7 Days"; + } else if (isNext30Days(toDo.date)) { + dateKey = "Next 30 Days"; + subDateKey = format(toDo.date, "MMM d"); + } else { + return groups; + } + + if (!groups[dateKey]) { + groups[dateKey] = { + items: [], + subgroups: {}, + }; + } + + if (dateKey === "Next 30 Days" && subDateKey) { + if (!groups[dateKey].subgroups[subDateKey]) { + groups[dateKey].subgroups[subDateKey] = []; + } + groups[dateKey].subgroups[subDateKey].push(toDo); + } else { + groups[dateKey].items.push(toDo); + } + + return groups; + }, + {} as { + [key: string]: { + items: IToDo[]; + subgroups: { [key: string]: IToDo[] }; + }; + } + ); +}; + +const filterToDosByUser = (toDos: IToDo[], uid: string | undefined) => { + if (!uid) return []; + return toDos.filter((todo) => + todo.assignees?.includes(uid) + ); +}; + +const SingleUserChoreList = ({ user }: { user: UserProfile }) => { + const { toDos } = useToDosContext(); + const userTodos = filterToDosByUser(toDos, user.uid); + const groupedToDos = groupToDosByDate(userTodos); + + const [expandedGroups, setExpandedGroups] = useState<{ + [key: string]: boolean; + }>({}); + + const [expandNoDate, setExpandNoDate] = useState(true); + + const toggleExpand = (dateKey: string) => { + setExpandedGroups((prev) => ({ + ...prev, + [dateKey]: !prev[dateKey], + })); + }; + + const noDateToDos = groupedToDos["No Date"]?.items || []; + const datedToDos = Object.keys(groupedToDos).filter( + (key) => key !== "No Date" + ); + + const renderTodoGroup = (dateKey: string) => { + const isExpanded = expandedGroups[dateKey] || false; + + if (dateKey === "Next 30 Days") { + const subgroups = Object.entries(groupedToDos[dateKey].subgroups).sort( + ([dateA], [dateB]) => { + const dateAObj = new Date(dateA); + const dateBObj = new Date(dateB); + return dateAObj.getTime() - dateBObj.getTime(); + } + ); + + return ( + + toggleExpand(dateKey)} + style={{ + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + paddingHorizontal: 0, + marginBottom: 4, + marginTop: 15, + }} + > + + {dateKey} + + + + + {isExpanded && + subgroups.map(([subDate, items]) => { + const sortedItems = [ + ...items.filter((toDo) => !toDo.done), + ...items.filter((toDo) => toDo.done), + ]; + + return ( + + + + {subDate} + + + + {sortedItems.map((item) => ( + + ))} + + ); + })} + + ); + } + + const sortedToDos = [ + ...groupedToDos[dateKey].items.filter((toDo) => !toDo.done), + ...groupedToDos[dateKey].items.filter((toDo) => toDo.done), + ]; + + return ( + + toggleExpand(dateKey)} + style={{ + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + paddingHorizontal: 0, + marginBottom: 4, + marginTop: 15, + }} + > + + {dateKey} + + + + + {isExpanded && + sortedToDos.map((item) => ( + + ))} + + ); + }; + + return ( + + {noDateToDos.length > 0 && ( + + + + Unscheduled + + { + setExpandNoDate(!expandNoDate); + }} + /> + + {expandNoDate && + noDateToDos + .sort((a, b) => Number(a.done) - Number(b.done)) + .map((item) => )} + + )} + + {datedToDos.map(renderTodoGroup)} + + ); +}; + +export default SingleUserChoreList; diff --git a/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx b/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx index 4066a57..f5f2559 100644 --- a/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx +++ b/components/pages/(tablet_pages)/chores/TabletChoresPage.tsx @@ -1,17 +1,26 @@ -import React, { useEffect } from 'react'; -import { View, Text } from 'react-native'; -import * as ScreenOrientation from 'expo-screen-orientation'; -import TabletContainer from '../tablet_components/TabletContainer'; -import ToDosPage from '../../todos/ToDosPage'; +import React, { useEffect } from "react"; +import { View, Text } from "react-native-ui-lib"; +import * as ScreenOrientation from "expo-screen-orientation"; +import TabletContainer from "../tablet_components/TabletContainer"; +import ToDosPage from "../../todos/ToDosPage"; +import ToDosList from "../../todos/ToDosList"; +import SingleUserChoreList from "./SingleUserChoreList"; +import { useGetFamilyMembers } from "@/hooks/firebase/useGetFamilyMembers"; +import { ImageBackground, StyleSheet } from "react-native"; +import { colorMap } from "@/constants/colorMap"; +import { ScrollView } from "react-native-gesture-handler"; const TabletChoresPage = () => { + const { data: users } = useGetFamilyMembers(); // Function to lock the screen orientation to landscape const lockScreenOrientation = async () => { - await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT); + await ScreenOrientation.lockAsync( + ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT + ); }; useEffect(() => { - lockScreenOrientation(); // Lock orientation when the component mounts + lockScreenOrientation(); // Lock orientation when the component mounts return () => { // Optional: Unlock to default when the component unmounts @@ -21,9 +30,56 @@ const TabletChoresPage = () => { return ( - + + + {users?.map((user, index) => ( + + + {user.pfp ? ( + + ) : ( + + + {user.firstName.at(0)} + {user.lastName.at(0)} + + + )} + + {user.firstName} + + + ({user.userType}) + + + + + ))} + + ); }; +const styles = StyleSheet.create({ + pfp: { + width: 46.74, + aspectRatio: 1, + borderRadius: 13.33, + }, + name: { + fontFamily: "Manrope_600SemiBold", + fontSize: 22.43, + color: "#2c2c2c", + }, +}); + export default TabletChoresPage; diff --git a/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx b/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx index c6aa220..68cb0a1 100644 --- a/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx +++ b/components/pages/(tablet_pages)/tablet_components/TabletContainer.tsx @@ -31,19 +31,21 @@ const TabletContainer: React.FC = ({ const styles = StyleSheet.create({ container: { backgroundColor: "white", - width: width, flex: 1, + borderTopColor: "#a9a9a9", + borderTopWidth: 1, }, calendarContainer: { backgroundColor: "white", height: height, - width: width * 0.85, + width: width * 0.89, }, profilesContainer: { - width: width * 0.15, + width: width * 0.11, height: height, borderLeftWidth: 1, borderLeftColor: "#a9a9a9", + backgroundColor: "white", }, }); diff --git a/components/pages/todos/ToDoItem.tsx b/components/pages/todos/ToDoItem.tsx index aa50175..81fd8bf 100644 --- a/components/pages/todos/ToDoItem.tsx +++ b/components/pages/todos/ToDoItem.tsx @@ -84,7 +84,7 @@ const ToDoItem = (props: { style={{ textDecorationLine: props.item.done ? "line-through" : "none", fontFamily: "Manrope_500Medium", - color: props.item.done? "#a09f9f": "black", + color: props.item.done ? "#a09f9f" : "black", fontSize: 15, }} onPress={() => { @@ -191,7 +191,7 @@ const ToDoItem = (props: { >