Shopping List backend implementation

- Implemented fetching, create and update of groceries in db
This commit is contained in:
Dejan
2024-10-11 16:11:46 +02:00
parent a05de1b333
commit 9b94aa8e70
8 changed files with 272 additions and 208 deletions
@@ -1,5 +1,5 @@
import { StyleSheet } from "react-native";
import React, { useState } from "react";
import React from "react";
import {
Dialog,
Text,
@@ -11,9 +11,9 @@ import {
} from "react-native-ui-lib";
import {
GroceryFrequency,
IGrocery,
useGroceryContext,
} from "@/contexts/GroceryContext";
import { IGrocery } from "@/hooks/firebase/types/groceryData";
interface EditGroceryFrequencyProps {
visible: boolean;
onClose: () => void;
@@ -42,7 +42,7 @@ const EditGroceryFrequency = (props: EditGroceryFrequencyProps) => {
<Switch
value={props.item.recurring}
onValueChange={(value) =>
updateGroceryItem(props.item.id, { recurring: value })
updateGroceryItem({id: props.item.id, recurring: value})
}
onColor={"lime"}
/>
@@ -56,8 +56,9 @@ const EditGroceryFrequency = (props: EditGroceryFrequencyProps) => {
const selectedFrequency =
GroceryFrequency[item as keyof typeof GroceryFrequency];
if (selectedFrequency) {
updateGroceryItem(props.item.id, {
frequency: selectedFrequency,
updateGroceryItem({
id: props.item.id,
frequency: selectedFrequency,
});
} else {
console.error("Invalid frequency selected");
+11 -24
View File
@@ -1,34 +1,21 @@
import {
View,
Text,
Button,
TouchableOpacity,
Checkbox,
ButtonSize,
} from "react-native-ui-lib";
import React, { useEffect, useState } from "react";
import { ProfileType, useAuthContext } from "@/contexts/AuthContext";
import { MaterialCommunityIcons, AntDesign } from "@expo/vector-icons";
import { ListItem } from "react-native-ui-lib";
import {
GroceryCategory,
IGrocery,
useGroceryContext,
} from "@/contexts/GroceryContext";
import {Checkbox, Text, TouchableOpacity, View,} from "react-native-ui-lib";
import React, {useEffect, useState} from "react";
import {AntDesign} from "@expo/vector-icons";
import {GroceryCategory, useGroceryContext,} from "@/contexts/GroceryContext";
import EditGroceryFrequency from "./EditGroceryFrequency";
import EditGroceryItem from "./EditGroceryItem";
import { StyleSheet } from "react-native";
import {StyleSheet} from "react-native";
import {IGrocery} from "@/hooks/firebase/types/groceryData";
const GroceryItem = ({
item,
handleItemApproved,
}: {
item: IGrocery;
handleItemApproved: (id: number, changes: Partial<IGrocery>) => void;
handleItemApproved: (id: string, changes: Partial<IGrocery>) => void;
}) => {
const { updateGroceryItem, groceries } = useGroceryContext();
const { updateGroceryItem } = useGroceryContext();
const { profileType } = useAuthContext();
const [openFreqEdit, setOpenFreqEdit] = useState<boolean>(false);
const [isEditingTitle, setIsEditingTitle] = useState<boolean>(false);
const [newTitle, setNewTitle] = useState<string>("");
@@ -37,11 +24,11 @@ const GroceryItem = ({
);
const handleTitleChange = (newTitle: string) => {
updateGroceryItem(item.id, { title: newTitle });
updateGroceryItem({id: item?.id, title: newTitle});
};
const handleCategoryChange = (newCategory: GroceryCategory) => {
updateGroceryItem(item.id, { category: newCategory });
updateGroceryItem({id: item?.id, category: newCategory});
};
useEffect(() => {
@@ -114,7 +101,7 @@ const GroceryItem = ({
containerStyle={styles.checkbox}
hitSlop={20}
onValueChange={() =>
updateGroceryItem(item.id, { bought: !item.bought })
updateGroceryItem({ id: item.id, bought: !item.bought })
}
/>
)}
+21 -26
View File
@@ -1,18 +1,13 @@
import { FlatList, StyleSheet } from "react-native";
import React, { RefObject, useEffect, useState } from "react";
import { View, Text, ListItem, Button, TextField, TextFieldRef } from "react-native-ui-lib";
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 {
IGrocery,
GroceryCategory,
GroceryFrequency,
useGroceryContext,
} from "@/contexts/GroceryContext";
import {GroceryCategory, GroceryFrequency, useGroceryContext,} from "@/contexts/GroceryContext";
import HeaderTemplate from "@/components/shared/HeaderTemplate";
import CategoryDropdown from "./CategoryDropdown";
import { AntDesign, MaterialIcons } from "@expo/vector-icons";
import {AntDesign, MaterialIcons} from "@expo/vector-icons";
import EditGroceryItem from "./EditGroceryItem";
import { ProfileType, useAuthContext } from "@/contexts/AuthContext";
import {ProfileType, useAuthContext} from "@/contexts/AuthContext";
import {IGrocery} from "@/hooks/firebase/types/groceryData";
const GroceryList = () => {
const {
@@ -24,10 +19,10 @@ const GroceryList = () => {
} = useGroceryContext();
const { profileData } = useAuthContext();
const [approvedGroceries, setapprovedGroceries] = useState<IGrocery[]>(
groceries.filter((item) => item.approved === true)
groceries?.filter((item) => item.approved === true)
);
const [pendingGroceries, setPendingGroceries] = useState<IGrocery[]>(
groceries.filter((item) => item.approved !== true)
groceries?.filter((item) => item.approved !== true)
);
const [category, setCategory] = useState<GroceryCategory>(
GroceryCategory.Bakery
@@ -39,7 +34,7 @@ const GroceryList = () => {
const [approvedVisible, setApprovedVisible] = useState<boolean>(true);
// Group approved groceries by category
const approvedGroceriesByCategory = approvedGroceries.reduce(
const approvedGroceriesByCategory = approvedGroceries?.reduce(
(groups: any, item: IGrocery) => {
const category = item.category || "Uncategorized";
if (!groups[category]) {
@@ -76,8 +71,8 @@ const GroceryList = () => {
}, [category]);
useEffect(() => {
setapprovedGroceries(groceries.filter((item) => item.approved === true));
setPendingGroceries(groceries.filter((item) => item.approved !== true));
setapprovedGroceries(groceries?.filter((item) => item.approved === true));
setPendingGroceries(groceries?.filter((item) => item.approved !== true));
}, [groceries]);
return (
@@ -93,8 +88,8 @@ const GroceryList = () => {
style={{ borderRadius: 50 }}
>
<Text text70BL color="#46a80a">
{approvedGroceries.length} list{" "}
{approvedGroceries.length === 1 ? (
{approvedGroceries?.length} list{" "}
{approvedGroceries?.length === 1 ? (
<Text text70BL color="#46a80a">
item
</Text>
@@ -111,7 +106,7 @@ const GroceryList = () => {
style={{ borderRadius: 50 }}
>
<Text text70BL color="#e28800">
{pendingGroceries.length} pending
{pendingGroceries?.length} pending
</Text>
</View>
<Button
@@ -161,18 +156,18 @@ const GroceryList = () => {
}}
>
<Text text70 center color="#e28800">
{pendingGroceries.length.toString()}
{pendingGroceries?.length.toString()}
</Text>
</View>
</View>
{pendingGroceries.length > 0
{pendingGroceries?.length > 0
? pendingVisible && (
<FlatList
data={pendingGroceries}
renderItem={({ item }) => (
<GroceryItem
item={item}
handleItemApproved={updateGroceryItem}
handleItemApproved={(id, changes) => updateGroceryItem({...changes, id: id})}
/>
)}
keyExtractor={(item) => item.id.toString()}
@@ -217,7 +212,7 @@ const GroceryList = () => {
}}
>
<Text text70 center color="#46a80a">
{approvedGroceries.length.toString()}
{approvedGroceries?.length.toString()}
</Text>
</View>
</View>
@@ -234,7 +229,7 @@ const GroceryList = () => {
)}
{/* Render Approved Groceries Grouped by Category */}
{approvedGroceries.length > 0
{approvedGroceries?.length > 0
? approvedVisible && (
<FlatList
data={Object.keys(approvedGroceriesByCategory)}
@@ -250,7 +245,7 @@ const GroceryList = () => {
<GroceryItem
key={grocery.id}
item={grocery}
handleItemApproved={updateGroceryItem}
handleItemApproved={(id, changes) => updateGroceryItem({...changes, id: id})}
/>
)
)}