tablet view fixes, grocery item fix

This commit is contained in:
ivic00
2024-11-27 20:17:48 +01:00
parent 4b5900c652
commit 01b4fc2e33
6 changed files with 171 additions and 155 deletions

View File

@ -9,6 +9,7 @@ import { useGetFamilyMembers } from "@/hooks/firebase/useGetFamilyMembers";
import { ImageBackground, StyleSheet } from "react-native"; import { ImageBackground, StyleSheet } from "react-native";
import { colorMap } from "@/constants/colorMap"; import { colorMap } from "@/constants/colorMap";
import { ScrollView } from "react-native-gesture-handler"; import { ScrollView } from "react-native-gesture-handler";
import { ProfileType } from "@/contexts/AuthContext";
const TabletChoresPage = () => { const TabletChoresPage = () => {
const { data: users } = useGetFamilyMembers(); const { data: users } = useGetFamilyMembers();
@ -32,20 +33,23 @@ const TabletChoresPage = () => {
<TabletContainer> <TabletContainer>
<ScrollView horizontal> <ScrollView horizontal>
<View row gap-25 padding-25> <View row gap-25 padding-25>
{users?.map((user, index) => ( {users
<View> ?.filter(member => member.userType !== ProfileType.FAMILY_DEVICE)
.map((user, index) => (
<View key={index}>
<View row centerV> <View row centerV>
{user.pfp ? ( {user.pfp ? (
<ImageBackground <ImageBackground
source={{ uri: user.pfp }} source={{ uri: user.pfp }}
style={[ style={
styles.pfp, styles.pfp
(user.eventColor && { }
borderWidth: 2, imageStyle={(user.eventColor && {
borderColor: user.eventColor, borderWidth: 2,
}) || borderColor: user.eventColor,
undefined, }) ||
]} undefined
}
borderRadius={13.33} borderRadius={13.33}
/> />
) : ( ) : (

View File

@ -1,53 +1,57 @@
import { View, Text } from "react-native-ui-lib"; import { View, Text } from "react-native-ui-lib";
import React from "react"; import React, { useEffect } from "react";
import { useGetFamilyMembers } from "@/hooks/firebase/useGetFamilyMembers"; import { useGetFamilyMembers } from "@/hooks/firebase/useGetFamilyMembers";
import { ImageBackground, StyleSheet } from "react-native"; import { ImageBackground, StyleSheet } from "react-native";
import { colorMap } from "@/constants/colorMap"; import { colorMap } from "@/constants/colorMap";
import { ProfileType } from "@/contexts/AuthContext";
const UsersList = () => { const UsersList = () => {
const { data: familyMembers } = useGetFamilyMembers(); const { data: familyMembers, refetch: refetchFamilyMembers } =
useGetFamilyMembers();
useEffect(() => {
refetchFamilyMembers();
}, []);
const capitalizeFirstLetter = (str: string) => { const capitalizeFirstLetter = (str: string) => {
if (!str) return ''; if (!str) return "";
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase(); return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
}; };
return ( return (
<View centerH paddingT-10> <View centerH paddingT-10>
{familyMembers?.map((member, index) => ( {familyMembers
<> ?.filter((member) => member.userType !== ProfileType.FAMILY_DEVICE)
{member.pfp ? ( .map((member, index) => (
<ImageBackground <>
key={index} {member.pfp ? (
source={{ uri: member.pfp }} <ImageBackground
style={[ key={index}
styles.pfp, source={{ uri: member.pfp }}
(member.eventColor && { style={styles.pfp}
borderWidth: 2, borderRadius={200}
borderColor: member.eventColor, imageStyle={{ borderWidth: 2, borderColor: "red" }}
}) || />
undefined, ) : (
]} <View
borderRadius={100} key={index}
/> style={styles.pfp}
) : ( center
<View backgroundColor={member.eventColor || colorMap.teal}
key={index} children={
style={styles.pfp} <Text color="white">
center {member.firstName.at(0)}
backgroundColor={member.eventColor || colorMap.teal} {member.lastName.at(0)}
children={ </Text>
<Text color="white"> }
{member.firstName.at(0)} />
{member.lastName.at(0)} )}
</Text> <Text style={styles.fName}>{member.firstName}</Text>
} <Text style={styles.role}>
/> {capitalizeFirstLetter(member.userType)}
)} </Text>
<Text style={styles.fName}>{member.firstName}</Text> </>
<Text style={styles.role}>{capitalizeFirstLetter(member.userType)}</Text> ))}
</>
))}
</View> </View>
); );
}; };

View File

@ -6,9 +6,9 @@ import EditGroceryFrequency from "./EditGroceryFrequency";
import EditGroceryItem from "./EditGroceryItem"; import EditGroceryItem from "./EditGroceryItem";
import { ImageBackground, StyleSheet } from "react-native"; import { ImageBackground, StyleSheet } from "react-native";
import { IGrocery } from "@/hooks/firebase/types/groceryData"; import { IGrocery } from "@/hooks/firebase/types/groceryData";
import firestore from "@react-native-firebase/firestore";
import { UserProfile } from "@/hooks/firebase/types/profileTypes"; import { UserProfile } from "@/hooks/firebase/types/profileTypes";
import { ProfileType, useAuthContext } from "@/contexts/AuthContext"; import { ProfileType, useAuthContext } from "@/contexts/AuthContext";
import { useGetUserById } from "@/hooks/firebase/useGetUserById";
const GroceryItem = ({ const GroceryItem = ({
item, item,
@ -21,6 +21,7 @@ const GroceryItem = ({
}) => { }) => {
const { updateGroceryItem } = useGroceryContext(); const { updateGroceryItem } = useGroceryContext();
const { profileData } = useAuthContext(); const { profileData } = useAuthContext();
const { data: creator } = useGetUserById(item.creatorId);
const isParent = profileData?.userType === ProfileType.PARENT; const isParent = profileData?.userType === ProfileType.PARENT;
const [openFreqEdit, setOpenFreqEdit] = useState<boolean>(false); const [openFreqEdit, setOpenFreqEdit] = useState<boolean>(false);
@ -29,37 +30,8 @@ const GroceryItem = ({
const [category, setCategory] = useState<GroceryCategory>( const [category, setCategory] = useState<GroceryCategory>(
item.category ?? GroceryCategory.None item.category ?? GroceryCategory.None
); );
const [itemCreator, setItemCreator] = useState<UserProfile>(null);
const closeEdit = () => { const closeEdit = () => setIsEditingTitle(false);
setIsEditingTitle(false);
};
const handleTitleChange = (newTitle: string) => {
updateGroceryItem({ id: item?.id, title: newTitle });
};
const handleCategoryChange = (newCategory: GroceryCategory) => {
updateGroceryItem({ id: item?.id, category: newCategory });
};
useEffect(() => {
console.log(item);
getItemCreator(item?.creatorId);
}, []);
const getItemCreator = async (uid: string | undefined) => {
if (uid) {
const documentSnapshot = await firestore()
.collection("Profiles")
.doc(uid)
.get();
if (documentSnapshot.exists) {
setItemCreator(documentSnapshot.data() as UserProfile);
}
}
};
const getInitials = (firstName: string, lastName: string) => { const getInitials = (firstName: string, lastName: string) => {
return `${firstName.charAt(0)}${lastName.charAt(0)}`; return `${firstName.charAt(0)}${lastName.charAt(0)}`;
@ -71,23 +43,27 @@ const GroceryItem = ({
style={{ style={{
borderRadius: 17, borderRadius: 17,
marginVertical: 5, marginVertical: 5,
paddingHorizontal: isEditingTitle ? 0 : 13,
paddingVertical: isEditingTitle ? 0 : 10,
height: 44.64,
backgroundColor: item.bought ? "#cbcbcb" : "white", backgroundColor: item.bought ? "#cbcbcb" : "white",
overflow: "hidden",
}} }}
backgroundColor="white"
centerV
> >
<View row spread> <View
row
spread
centerV
style={{
paddingHorizontal: isEditingTitle ? 0 : 13,
paddingVertical: isEditingTitle ? 0 : 10,
minHeight: 44.64,
}}
>
<EditGroceryFrequency <EditGroceryFrequency
visible={openFreqEdit} visible={openFreqEdit}
key={item.id} key={item.id}
item={item} item={item}
onClose={() => { onClose={() => setOpenFreqEdit(false)}
setOpenFreqEdit(false);
}}
/> />
{isEditingTitle ? ( {isEditingTitle ? (
<EditGroceryItem <EditGroceryItem
editGrocery={{ editGrocery={{
@ -102,12 +78,11 @@ const GroceryItem = ({
onInputFocus={onInputFocus} onInputFocus={onInputFocus}
/> />
) : ( ) : (
<View> <View flex>
{isParent ? ( {isParent ? (
<TouchableOpacity onPress={() => setIsEditingTitle(true)}> <TouchableOpacity onPress={() => setIsEditingTitle(true)}>
<Text <Text
text70T text70T
black
style={[ style={[
styles.title, styles.title,
{ {
@ -121,7 +96,6 @@ const GroceryItem = ({
) : ( ) : (
<Text <Text
text70T text70T
black
style={[styles.title, { color: item.bought ? "red" : "black" }]} style={[styles.title, { color: item.bought ? "red" : "black" }]}
> >
{item.title} {item.title}
@ -129,31 +103,25 @@ const GroceryItem = ({
)} )}
</View> </View>
)} )}
{!item.approved ? ( {!item.approved ? (
<View row centerV marginB-10> <View row centerV>
{isParent && ( {isParent && (
<> <>
<AntDesign <AntDesign
name="check" name="check"
size={24} size={24}
style={{ style={{ color: "green", marginRight: 15 }}
color: "green", onPress={() =>
marginRight: 15, handleItemApproved(item.id, { approved: true })
}}
onPress={
isParent
? () => handleItemApproved(item.id, { approved: true })
: null
} }
/> />
<AntDesign <AntDesign
name="close" name="close"
size={24} size={24}
style={{ color: "red" }} style={{ color: "red" }}
onPress={ onPress={() =>
isParent handleItemApproved(item.id, { approved: false })
? () => handleItemApproved(item.id, { approved: false })
: null
} }
/> />
</> </>
@ -176,69 +144,69 @@ const GroceryItem = ({
) )
)} )}
</View> </View>
{!item.approved && ( {!item.approved && (
<View> <>
<View centerH> <View paddingH-20>
<View height={0.7} backgroundColor="#e7e7e7" width={"98%"} /> <View height={0.7} backgroundColor="#e7e7e7" width="100%" />
</View> </View>
<View paddingL-0 paddingT-12 flexS row centerV> <View
{profileData?.pfp ? ( row
centerV
style={{
paddingHorizontal: 13,
paddingVertical: 10,
}}
>
{creator?.pfp ? (
<ImageBackground <ImageBackground
source={require("../../../assets/images/child-picture.png")} source={{ uri: creator.pfp }}
style={{ style={{
height: 24.64, height: 24.64,
aspectRatio: 1, aspectRatio: 1,
borderRadius: 22, borderRadius: 22,
overflow: "hidden", overflow: "hidden",
borderWidth: 2, borderWidth: 2,
borderColor: profileData.eventColor borderColor: creator.eventColor || undefined,
marginRight: 8,
}} }}
/> />
) : ( ) : (
<View <View
style={{ style={{
position: "relative",
width: 24.64, width: 24.64,
aspectRatio: 1, aspectRatio: 1,
marginRight: 4, marginRight: 8,
backgroundColor: "#ccc",
borderRadius: 100,
justifyContent: "center",
alignItems: "center",
}} }}
> >
<View <Text
style={{ style={{ color: "#fff", fontSize: 12, fontWeight: "bold" }}
backgroundColor: "#ccc",
justifyContent: "center",
alignItems: "center",
borderRadius: 100, // Circular shape
width: "100%",
height: "100%",
}}
> >
<Text {creator
style={{ ? getInitials(creator.firstName, creator.lastName)
color: "#fff", : ""}
fontSize: 12, </Text>
fontWeight: "bold",
}}
>
{itemCreator
? getInitials(itemCreator.firstName, itemCreator.lastName)
: ""}
</Text>
</View>
</View> </View>
)} )}
<Text color="#858585" style={styles.authorTxt}> <Text color="#858585" style={styles.authorTxt}>
Requested by {itemCreator?.firstName} Requested by {creator?.firstName}
</Text> </Text>
</View> </View>
</View> </>
)} )}
</View> </View>
); );
}; };
const styles = StyleSheet.create({ const styles = StyleSheet.create({
authorTxt: { fontFamily: "Manrope_500Medium", fontSize: 12 }, authorTxt: {
fontFamily: "Manrope_500Medium",
fontSize: 12,
},
checkbox: { checkbox: {
borderRadius: 50, borderRadius: 50,
borderWidth: 0.7, borderWidth: 0.7,

View File

@ -11,7 +11,12 @@ import {
} from "react-native-ui-lib"; } from "react-native-ui-lib";
import React, { useEffect, useRef, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
import { useSignIn } from "@/hooks/firebase/useSignIn"; import { useSignIn } from "@/hooks/firebase/useSignIn";
import { Dimensions, KeyboardAvoidingView, Platform, StyleSheet } from "react-native"; import {
Dimensions,
KeyboardAvoidingView,
Platform,
StyleSheet,
} from "react-native";
import Toast from "react-native-toast-message"; import Toast from "react-native-toast-message";
import KeyboardManager from "react-native-keyboard-manager"; import KeyboardManager from "react-native-keyboard-manager";
import { SafeAreaView } from "react-native-safe-area-context"; import { SafeAreaView } from "react-native-safe-area-context";
@ -28,24 +33,24 @@ const SignInPage = () => {
const isTablet: boolean = Device.deviceType === DeviceType.TABLET; const isTablet: boolean = Device.deviceType === DeviceType.TABLET;
const [isPortrait, setIsPortrait] = useState(() => { const [isPortrait, setIsPortrait] = useState(() => {
const dim = Dimensions.get('screen'); const dim = Dimensions.get("screen");
return dim.height >= dim.width; return dim.height >= dim.width;
}); });
useEffect(() => { useEffect(() => {
const subscription = Dimensions.addEventListener('change', ({ screen }) => { const subscription = Dimensions.addEventListener("change", ({ screen }) => {
setIsPortrait(screen.height >= screen.width); setIsPortrait(screen.height >= screen.width);
}); });
return () => subscription.remove(); return () => subscription.remove();
}, []); }, []);
const getTopPadding = () => { const getTopPadding = () => {
if (Device.deviceType === DeviceType.TABLET) { if (Device.deviceType === DeviceType.TABLET) {
return isPortrait ? "50%" : "15%"; return isPortrait ? "50%" : "15%";
} }
return "20%"; // non-tablet case, regardless of orientation return "20%"; // non-tablet case, regardless of orientation
}; };
const { mutateAsync: signIn, error, isError, isLoading } = useSignIn(); const { mutateAsync: signIn, error, isError, isLoading } = useSignIn();
@ -68,9 +73,12 @@ const SignInPage = () => {
}; };
return ( return (
<SafeAreaView style={{ flex: 1, alignItems: isTablet ? "center" : undefined}}> <SafeAreaView style={{ flex: 1 }}>
<KeyboardAwareScrollView <KeyboardAwareScrollView
contentContainerStyle={{ flexGrow: 1 }} contentContainerStyle={{
flexGrow: 1,
alignItems: isTablet ? "center" : undefined,
}}
enableOnAndroid enableOnAndroid
> >
<View <View
@ -79,7 +87,7 @@ const SignInPage = () => {
padding: 21, padding: 21,
paddingBottom: 45, paddingBottom: 45,
paddingTop: isLoading ? "20%" : getTopPadding(), paddingTop: isLoading ? "20%" : getTopPadding(),
width: isLoading ? '100%' : (isTablet ? 629 : undefined), width: isLoading ? "100%" : isTablet ? 629 : undefined,
}} }}
> >
<View gap-13 width={"100%"} marginB-20> <View gap-13 width={"100%"} marginB-20>
@ -92,9 +100,9 @@ const SignInPage = () => {
</View> </View>
<KeyboardAvoidingView <KeyboardAvoidingView
style={{ width: "100%" }} style={{ width: "100%", flex: 1 }}
contentContainerStyle={{ justifyContent: "center" }} contentContainerStyle={{ justifyContent: "center" }}
keyboardVerticalOffset={50} keyboardVerticalOffset={Platform.OS === "ios" ? 50 : 200}
behavior={Platform.OS === "ios" ? "padding" : "height"} behavior={Platform.OS === "ios" ? "padding" : "height"}
> >
<TextField <TextField
@ -187,6 +195,7 @@ const SignInPage = () => {
<LoaderScreen <LoaderScreen
overlay overlay
message={"Signing in..."} message={"Signing in..."}
containerStyle={{ width: Dimensions.get('screen').width }}
backgroundColor={Colors.white} backgroundColor={Colors.white}
color={Colors.grey40} color={Colors.grey40}
/> />

View File

@ -75,12 +75,12 @@ const SignUpPage = () => {
<SafeAreaView <SafeAreaView
style={{ style={{
flex: 1, flex: 1,
alignItems: isTablet ? "center" : undefined,
width: "100%",
}} }}
> >
<KeyboardAwareScrollView <KeyboardAwareScrollView
contentContainerStyle={{ flexGrow: 1 }} contentContainerStyle={{ flexGrow: 1,
alignItems: isTablet ? "center" : undefined,
width: '100%' }}
enableOnAndroid enableOnAndroid
> >
<View <View

View File

@ -0,0 +1,31 @@
import { useQuery } from "react-query";
import { UserProfile } from "@/hooks/firebase/types/profileTypes";
import firestore from "@react-native-firebase/firestore";
export const useGetUserById = (uid: string | undefined) => {
return useQuery({
queryKey: ["getUserById", uid],
queryFn: async (): Promise<UserProfile | null> => {
if (!uid) return null;
try {
const doc = await firestore()
.collection("Profiles")
.doc(uid)
.get();
if (!doc.exists) return null;
const data = doc.data();
return {
...data,
uid: doc.id,
} as UserProfile;
} catch (error) {
console.error("Error retrieving user:", error);
return null;
}
},
enabled: !!uid
});
};