mirror of
https://github.com/urosran/cally.git
synced 2025-11-26 00:24:53 +00:00
notes, tablet sort, grocery list and other fixes
This commit is contained in:
@ -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} />
|
||||||
|
|||||||
@ -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>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
@ -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({
|
||||||
|
|||||||
@ -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) => ({
|
||||||
|
|||||||
Reference in New Issue
Block a user