Files
cally/components/pages/grocery/GroceryList.tsx
Dejan 86231daba4 Shopping List backend implementation
- Small code improvements
2024-10-11 16:28:17 +02:00

269 lines
7.8 KiB
TypeScript

import {FlatList, StyleSheet} from "react-native";
import React, {useEffect, useState} from "react";
import {Button, Text, View} from "react-native-ui-lib";
import GroceryItem from "./GroceryItem";
import {GroceryCategory, GroceryFrequency, useGroceryContext,} from "@/contexts/GroceryContext";
import HeaderTemplate from "@/components/shared/HeaderTemplate";
import {AntDesign, MaterialIcons} from "@expo/vector-icons";
import EditGroceryItem from "./EditGroceryItem";
import {ProfileType, useAuthContext} from "@/contexts/AuthContext";
import {IGrocery} from "@/hooks/firebase/types/groceryData";
const GroceryList = () => {
const {
groceries,
updateGroceryItem,
isAddingGrocery,
setIsAddingGrocery,
addGrocery,
} = useGroceryContext();
const { profileData } = useAuthContext();
const [approvedGroceries, setapprovedGroceries] = useState<IGrocery[]>(
groceries?.filter((item) => item.approved === true)
);
const [pendingGroceries, setPendingGroceries] = useState<IGrocery[]>(
groceries?.filter((item) => item.approved !== true)
);
const [category, setCategory] = useState<GroceryCategory>(
GroceryCategory.Bakery
);
const [title, setTitle] = useState<string>("");
const [submit, setSubmitted] = useState<boolean>(false);
const [pendingVisible, setPendingVisible] = useState<boolean>(true);
const [approvedVisible, setApprovedVisible] = useState<boolean>(true);
// Group approved groceries by category
const approvedGroceriesByCategory = approvedGroceries?.reduce(
(groups: any, item: IGrocery) => {
const category = item.category || "Uncategorized";
if (!groups[category]) {
groups[category] = [];
}
groups[category].push(item);
return groups;
},
{}
);
useEffect(() => {
if (submit) {
if (title?.length > 2 && title?.length <= 25) {
addGrocery({
id: "",
title: title,
category: category,
approved: profileData?.userType === ProfileType.PARENT,
recurring: false,
frequency: GroceryFrequency.Never,
bought: false,
});
setIsAddingGrocery(false);
setSubmitted(false);
setTitle("");
}
}
}, [submit]);
useEffect(() => {
/**/
}, [category]);
useEffect(() => {
setapprovedGroceries(groceries?.filter((item) => item.approved === true));
setPendingGroceries(groceries?.filter((item) => item.approved !== true));
}, [groceries]);
return (
<View marginH-20 marginB-20>
<HeaderTemplate
message={"Welcome to your grocery list"}
isWelcome={false}
>
<View row spread gap-5>
<View
backgroundColor="#e2eed8"
padding-8
style={{ borderRadius: 50 }}
>
<Text text70BL color="#46a80a">
{approvedGroceries?.length} list{" "}
{approvedGroceries?.length === 1 ? (
<Text text70BL color="#46a80a">
item
</Text>
) : (
<Text text70BL color="#46a80a">
items
</Text>
)}
</Text>
</View>
<View
backgroundColor="#faead2"
padding-8
style={{ borderRadius: 50 }}
>
<Text text70BL color="#e28800">
{pendingGroceries?.length} pending
</Text>
</View>
<Button
backgroundColor="transparent"
paddingH-10
iconSource={() => (
<MaterialIcons name="person-add-alt" size={24} color="gray" />
)}
/>
</View>
</HeaderTemplate>
{/* Pending Approval Section */}
<View row spread marginT-40 marginB-10 centerV>
<View row centerV>
<Text text70BL>Pending Approval</Text>
{pendingVisible && (
<AntDesign
name="down"
size={17}
style={styles.dropIcon}
color="#9f9f9f"
onPress={() => {
setPendingVisible(false);
}}
/>
)}
{!pendingVisible && (
<AntDesign
name="right"
size={15}
style={styles.dropIcon}
color="#9f9f9f"
onPress={() => {
setPendingVisible(true);
}}
/>
)}
</View>
<View
centerV
style={{
aspectRatio: 1,
width: 35,
backgroundColor: "#faead2",
borderRadius: 50,
}}
>
<Text text70 center color="#e28800">
{pendingGroceries?.length.toString()}
</Text>
</View>
</View>
{pendingGroceries?.length > 0
? pendingVisible && (
<FlatList
data={pendingGroceries}
renderItem={({ item }) => (
<GroceryItem
item={item}
handleItemApproved={(id, changes) => updateGroceryItem({...changes, id: id})}
/>
)}
keyExtractor={(item) => item.id.toString()}
/>
)
: pendingVisible && <Text>No items pending approval.</Text>}
{/* Approved Section */}
<View row spread marginT-40 marginB-0 centerV>
<View row centerV>
<Text text70BL>Shopping List</Text>
{approvedVisible && (
<AntDesign
name="down"
size={17}
style={styles.dropIcon}
color="#9f9f9f"
onPress={() => {
setApprovedVisible(false);
}}
/>
)}
{!approvedVisible && (
<AntDesign
name="right"
size={15}
style={styles.dropIcon}
color="#9f9f9f"
onPress={() => {
setApprovedVisible(true);
}}
/>
)}
</View>
<View
centerV
style={{
aspectRatio: 1,
width: 35,
backgroundColor: "#e2eed8",
borderRadius: 50,
}}
>
<Text text70 center color="#46a80a">
{approvedGroceries?.length.toString()}
</Text>
</View>
</View>
{isAddingGrocery && (
<EditGroceryItem
editGrocery={{
title: title,
setCategory: setCategory,
category: category,
setTitle: setTitle,
setSubmit: setSubmitted,
}}
/>
)}
{/* Render Approved Groceries Grouped by Category */}
{approvedGroceries?.length > 0
? approvedVisible && (
<FlatList
data={Object.keys(approvedGroceriesByCategory)}
renderItem={({ item: category }) => (
<View key={category}>
{/* Render Category Header */}
<Text text80M style={{ marginTop: 10 }} color="#666">
{category}
</Text>
{/* Render Grocery Items for this Category */}
{approvedGroceriesByCategory[category].map(
(grocery: IGrocery) => (
<GroceryItem
key={grocery.id}
item={grocery}
handleItemApproved={(id, changes) => updateGroceryItem({...changes, id: id})}
/>
)
)}
</View>
)}
keyExtractor={(category) => category}
/>
)
: approvedVisible && <Text>No approved items.</Text>}
</View>
);
};
const styles = StyleSheet.create({
dropIcon: {
marginHorizontal: 10,
},
});
export default GroceryList;