notes, tablet sort, grocery list and other fixes

This commit is contained in:
ivic00
2024-12-02 18:46:36 +01:00
parent 12b4ce3a70
commit c86a355b97
8 changed files with 94 additions and 56 deletions

View File

@ -1,4 +1,4 @@
import React, {useEffect} from "react"; import React, {useEffect, useMemo} from "react";
import {Text, View} from "react-native-ui-lib"; import {Text, View} from "react-native-ui-lib";
import * as ScreenOrientation from "expo-screen-orientation"; import * as ScreenOrientation from "expo-screen-orientation";
import TabletContainer from "../tablet_components/TabletContainer"; import TabletContainer from "../tablet_components/TabletContainer";
@ -7,10 +7,29 @@ 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"; import { ProfileType, useAuthContext } from "@/contexts/AuthContext";
const TabletChoresPage = () => { const TabletChoresPage = () => {
const {data: users} = useGetFamilyMembers(); const {data: users} = useGetFamilyMembers();
const { user: currentUser } = useAuthContext();
const sortedUsers = useMemo(() => {
return users
?.filter(member => member.userType !== ProfileType.FAMILY_DEVICE)
.sort((a, b) => {
if (a.uid === currentUser?.uid) return -1;
if (b.uid === currentUser?.uid) return 1;
const typePriority = {
[ProfileType.PARENT]: 0,
[ProfileType.CHILD]: 1,
[ProfileType.CAREGIVER]: 2
};
return typePriority[a.userType] - typePriority[b.userType];
});
}, [users, currentUser]);
// Function to lock the screen orientation to landscape // Function to lock the screen orientation to landscape
const lockScreenOrientation = async () => { const lockScreenOrientation = async () => {
await ScreenOrientation.lockAsync( await ScreenOrientation.lockAsync(
@ -27,11 +46,16 @@ const TabletChoresPage = () => {
}; };
}, []); }, []);
const capitalizeFirstLetter = (str: string) => {
if (!str) return "";
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
};
return ( return (
<TabletContainer> <TabletContainer>
<ScrollView horizontal> <ScrollView horizontal>
<View row gap-25 padding-25> <View row gap-25 padding-25>
{users {sortedUsers
?.filter((member) => member.userType !== ProfileType.FAMILY_DEVICE) ?.filter((member) => member.userType !== ProfileType.FAMILY_DEVICE)
.map((user, index) => ( .map((user, index) => (
<View key={index}> <View key={index}>
@ -66,7 +90,7 @@ const TabletChoresPage = () => {
{user.firstName} {user.firstName}
</Text> </Text>
<Text style={[styles.name, { color: "#9b9b9b" }]} marginL-5> <Text style={[styles.name, { color: "#9b9b9b" }]} marginL-5>
({user.userType}) ({capitalizeFirstLetter(user.userType)})
</Text> </Text>
</View> </View>
<SingleUserChoreList user={user} /> <SingleUserChoreList user={user} />

View File

@ -1,11 +1,13 @@
import { View, Text } from "react-native-ui-lib"; import { View, Text } from "react-native-ui-lib";
import React, { useEffect } from "react"; import React, { useEffect, useMemo } 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"; import { ProfileType, useAuthContext } from "@/contexts/AuthContext";
import { ScrollView } from "react-native-gesture-handler";
const UsersList = () => { const UsersList = () => {
const { user: currentUser } = useAuthContext();
const { data: familyMembers, refetch: refetchFamilyMembers } = const { data: familyMembers, refetch: refetchFamilyMembers } =
useGetFamilyMembers(); useGetFamilyMembers();
@ -13,17 +15,34 @@ const UsersList = () => {
refetchFamilyMembers(); refetchFamilyMembers();
}, []); }, []);
const sortedMembers = useMemo(() => {
return familyMembers
?.filter((member) => member.userType !== ProfileType.FAMILY_DEVICE)
.sort((a, b) => {
// Current user first
if (a.uid === currentUser?.uid) return -1;
if (b.uid === currentUser?.uid) return 1;
// Then sort by user type priority
const typePriority = {
[ProfileType.PARENT]: 0,
[ProfileType.CHILD]: 1,
[ProfileType.CAREGIVER]: 2,
};
return typePriority[a.userType] - typePriority[b.userType];
});
}, [familyMembers, currentUser]);
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 marginB-70>
{familyMembers {sortedMembers?.map((member, index) => (
?.filter((member) => member.userType !== ProfileType.FAMILY_DEVICE) <React.Fragment key={member.uid}>
.map((member, index) => (
<>
{member.pfp ? ( {member.pfp ? (
<ImageBackground <ImageBackground
key={index} key={index}
@ -38,19 +57,18 @@ const UsersList = () => {
style={styles.pfp} style={styles.pfp}
center center
backgroundColor={member.eventColor || colorMap.teal} backgroundColor={member.eventColor || colorMap.teal}
children={ >
<Text color="white"> <Text color="white">
{member.firstName.at(0)} {member.firstName.at(0)}
{member.lastName.at(0)} {member.lastName.at(0)}
</Text> </Text>
} </View>
/>
)} )}
<Text style={styles.fName}>{member.firstName}</Text> <Text style={styles.fName}>{member.firstName}</Text>
<Text style={styles.role}> <Text style={styles.role}>
{capitalizeFirstLetter(member.userType)} {capitalizeFirstLetter(member.userType)}
</Text> </Text>
</> </React.Fragment>
))} ))}
</View> </View>
); );

View File

@ -3,11 +3,11 @@ import React from "react";
import { useBrainDumpContext } from "@/contexts/DumpContext"; import { useBrainDumpContext } from "@/contexts/DumpContext";
import { FlatList } from "react-native"; import { FlatList } from "react-native";
import BrainDumpItem from "./DumpItem"; import BrainDumpItem from "./DumpItem";
import { StyleSheet } from "react-native";
const DumpList = (props: { searchText: string }) => { const DumpList = (props: { searchText: string }) => {
const { brainDumps } = useBrainDumpContext(); const { brainDumps } = useBrainDumpContext();
const filteredBrainDumps = const sortedDumps =
props.searchText.trim() === "" props.searchText.trim() === ""
? brainDumps ? brainDumps
: brainDumps.filter( : brainDumps.filter(
@ -18,18 +18,21 @@ const DumpList = (props: { searchText: string }) => {
.includes(props.searchText.toLowerCase()) .includes(props.searchText.toLowerCase())
); );
return ( return (
<View marginB-70> <View marginB-70>
<FlatList {brainDumps?.length ? <FlatList
style={{ zIndex: -1 }} style={{ zIndex: -1 }}
data={filteredBrainDumps} data={sortedDumps}
keyExtractor={(item) => item.title} keyExtractor={(item) => item.title}
renderItem={({ item }) => ( renderItem={({ item }) => (
<BrainDumpItem key={item.title} item={item} /> <BrainDumpItem key={item.title} item={item} />
)} )}
/> /> : <Text marginT-20 center style={styles.alert}>You have no notes</Text>}
</View> </View>
); );
}; };
const styles = StyleSheet.create({
alert: {fontFamily: "PlusJakartaSans_300Light", fontSize: 20}
})
export default DumpList; export default DumpList;

View File

@ -122,16 +122,14 @@ const GroceryList = ({onInputFocus}: {onInputFocus: (y: number) => void}) => {
{/* Pending Approval Section */} {/* Pending Approval Section */}
<View row spread marginT-40 marginB-10 centerV> <View row spread marginT-40 marginB-10 centerV>
<View row centerV> <View row centerV>
<TouchableOpacity row centerV onPress={() => {setPendingVisible(!pendingVisible)}}>
<Text style={styles.subHeader}>Pending Approval</Text> <Text style={styles.subHeader}>Pending Approval</Text>
{pendingVisible && ( {pendingVisible && (
<AntDesign <AntDesign
name="down" name="down"
size={17} size={17}
style={styles.dropIcon} style={styles.dropIcon}
color="#9f9f9f" color="#9f9f9f"
onPress={() => {
setPendingVisible(false);
}}
/> />
)} )}
{!pendingVisible && ( {!pendingVisible && (
@ -140,11 +138,9 @@ const GroceryList = ({onInputFocus}: {onInputFocus: (y: number) => void}) => {
size={15} size={15}
style={styles.dropIcon} style={styles.dropIcon}
color="#9f9f9f" color="#9f9f9f"
onPress={() => { />
setPendingVisible(true); )}
}} </TouchableOpacity>
/>
)}
</View> </View>
<View <View
centerV centerV
@ -183,6 +179,7 @@ const GroceryList = ({onInputFocus}: {onInputFocus: (y: number) => void}) => {
{/* Approved Section */} {/* Approved Section */}
<View row spread marginT-40 marginB-0 centerV> <View row spread marginT-40 marginB-0 centerV>
<View row centerV> <View row centerV>
<TouchableOpacity row centerV onPress={() => {setApprovedVisible(!approvedVisible)}}>
<Text style={styles.subHeader}>Shopping List</Text> <Text style={styles.subHeader}>Shopping List</Text>
{approvedVisible && ( {approvedVisible && (
<AntDesign <AntDesign
@ -190,9 +187,6 @@ const GroceryList = ({onInputFocus}: {onInputFocus: (y: number) => void}) => {
size={17} size={17}
style={styles.dropIcon} style={styles.dropIcon}
color="#9f9f9f" color="#9f9f9f"
onPress={() => {
setApprovedVisible(false);
}}
/> />
)} )}
{!approvedVisible && ( {!approvedVisible && (
@ -201,11 +195,9 @@ const GroceryList = ({onInputFocus}: {onInputFocus: (y: number) => void}) => {
size={15} size={15}
style={styles.dropIcon} style={styles.dropIcon}
color="#9f9f9f" color="#9f9f9f"
onPress={() => {
setApprovedVisible(true);
}}
/> />
)} )}
</TouchableOpacity>
</View> </View>
<View <View
centerV centerV

View File

@ -32,7 +32,7 @@ const AssigneesDisplay = ({selectedAttendees, setSelectedAttendees}: {
children={<RemoveAssigneeBtn/>} children={<RemoveAssigneeBtn/>}
/> />
) : ( ) : (
<View style={[styles.initialsCircle, {borderWidth: 2, borderColor: member.eventColor || 'transparent'}]}> <View style={[styles.initialsCircle, {borderWidth: 2, borderColor: member.eventColor || 'transparent', backgroundColor: member.eventColor || 'gray'}]}>
<Text style={styles.initialsText}> <Text style={styles.initialsText}>
{getInitials(member.firstName, member.lastName)} {getInitials(member.firstName, member.lastName)}
</Text> </Text>

View File

@ -26,7 +26,7 @@ const BrainDumpContext = createContext<IBrainDumpContext | undefined>(
export const BrainDumpProvider: React.FC<{ children: React.ReactNode }> = ({ export const BrainDumpProvider: React.FC<{ children: React.ReactNode }> = ({
children, children,
}) => { }) => {
const { data: brainDumps } = useGetNotes(); const { data: brainDumps, refetch } = useGetNotes();
const { mutate: deleteNote } = useDeleteNote(); const { mutate: deleteNote } = useDeleteNote();
const { mutateAsync: createBrainDump } = useCreateNote(); const { mutateAsync: createBrainDump } = useCreateNote();
const { mutateAsync: updateNoteMutate } = useUpdateNote(); const { mutateAsync: updateNoteMutate } = useUpdateNote();

View File

@ -5,7 +5,7 @@ import { IFeedback } from "@/contexts/FeedbackContext";
import { IBrainDump } from "@/contexts/DumpContext"; import { IBrainDump } from "@/contexts/DumpContext";
export const useCreateNote = () => { export const useCreateNote = () => {
const { user: currentUser, profileData } = useAuthContext(); const { user: currentUser } = useAuthContext();
const queryClients = useQueryClient(); const queryClients = useQueryClient();
return useMutation({ return useMutation({

View File

@ -13,6 +13,7 @@ export const useGetNotes = () => {
const snapshot = await firestore() const snapshot = await firestore()
.collection("BrainDumps") .collection("BrainDumps")
.where("creatorId", "==", currentUser?.uid) .where("creatorId", "==", currentUser?.uid)
.orderBy("updatedAt", "desc")
.get(); .get();
return snapshot.docs.map((doc) => ({ return snapshot.docs.map((doc) => ({