mirror of
https://github.com/urosran/cally.git
synced 2025-11-26 00:24:53 +00:00
Shopping List backend implementation
- Implemented fetching, create and update of groceries in db
This commit is contained in:
@ -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");
|
||||
|
||||
@ -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 })
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -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})}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
import { MaterialCommunityIcons } from "@expo/vector-icons";
|
||||
import { createContext, useContext, useState } from "react";
|
||||
import {createContext, useContext, useState} from "react";
|
||||
import fuzzysort from "fuzzysort";
|
||||
import {useCreateGrocery} from "@/hooks/firebase/useCreateGrocery";
|
||||
import {IGrocery} from "@/hooks/firebase/types/groceryData";
|
||||
import {useUpdateGrocery} from "@/hooks/firebase/useUpdateGrocery";
|
||||
import {useGetGroceries} from "@/hooks/firebase/useGetGroceries";
|
||||
|
||||
export enum GroceryFrequency {
|
||||
Never = "Never",
|
||||
@ -11,16 +14,6 @@ export enum GroceryFrequency {
|
||||
Quarterly = "Quarterly",
|
||||
}
|
||||
|
||||
export interface IGrocery {
|
||||
id: number;
|
||||
title: string;
|
||||
category: GroceryCategory;
|
||||
approved: boolean;
|
||||
recurring: boolean;
|
||||
frequency: GroceryFrequency;
|
||||
bought: boolean;
|
||||
}
|
||||
|
||||
export enum GroceryCategory {
|
||||
Fruit = "Fruit",
|
||||
Dairy = "Dairy",
|
||||
@ -52,10 +45,136 @@ const iconMapping: { [key in GroceryCategory]: MaterialIconNames } = {
|
||||
[GroceryCategory.Frozen]: "snowflake",
|
||||
};*/
|
||||
|
||||
const initialGroceryList = [
|
||||
{
|
||||
id: 0,
|
||||
title: "Carrots",
|
||||
category: GroceryCategory.Vegetables,
|
||||
approved: false,
|
||||
bought: false,
|
||||
recurring: false,
|
||||
frequency: GroceryFrequency.Never,
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: "Steak",
|
||||
category: GroceryCategory.Meat,
|
||||
approved: true,
|
||||
bought: false,
|
||||
recurring: false,
|
||||
frequency: GroceryFrequency.Never,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "Chicken Breast",
|
||||
category: GroceryCategory.Poultry,
|
||||
approved: true,
|
||||
bought: false,
|
||||
recurring: false,
|
||||
frequency: GroceryFrequency.Never,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "Greek Yoghurt",
|
||||
category: GroceryCategory.Dairy,
|
||||
approved: false,
|
||||
bought: false,
|
||||
recurring: false,
|
||||
frequency: GroceryFrequency.Never,
|
||||
},
|
||||
];
|
||||
|
||||
const groceryExamples = {
|
||||
[GroceryCategory.Fruit]: [
|
||||
'apple', 'apples', 'banana', 'bananas', 'orange', 'oranges', 'grape', 'grapes',
|
||||
'pear', 'pears', 'pineapple', 'pineapples', 'kiwi', 'kiwis', 'strawberry',
|
||||
'strawberries', 'blueberry', 'blueberries', 'mango', 'mangoes', 'watermelon',
|
||||
'watermelons', 'peach', 'peaches', 'plum', 'plums', 'cherry', 'cherries',
|
||||
'raspberry', 'raspberries', 'blackberry', 'blackberries', 'pomegranate',
|
||||
'pomegranates', 'lemon', 'lemons', 'lime', 'limes', 'coconut', 'coconuts'
|
||||
],
|
||||
[GroceryCategory.Dairy]: [
|
||||
'milk', 'whole milk', 'skim milk', 'almond milk', 'soy milk', 'cheese',
|
||||
'cheeses', 'yoghurt', 'yogurt', 'greek yoghurt', 'greek yogurt', 'butter',
|
||||
'margarine', 'cream', 'whipping cream', 'heavy cream', 'ice cream', 'ice creams',
|
||||
'sour cream', 'whipped cream', 'cream cheese', 'cream cheeses', 'buttermilk',
|
||||
'cottage cheese', 'ghee', 'kefir'
|
||||
],
|
||||
[GroceryCategory.Vegetables]: [
|
||||
'carrot', 'carrots', 'broccoli', 'lettuce', 'lettuces', 'spinach', 'kale',
|
||||
'cabbage', 'cabbages', 'cauliflower', 'zucchini', 'zucchinis', 'onion', 'onions',
|
||||
'garlic', 'pepper', 'peppers', 'bell pepper', 'bell peppers', 'tomato', 'tomatoes',
|
||||
'cucumber', 'cucumbers', 'potato', 'potatoes', 'sweet potato', 'sweet potatoes',
|
||||
'beet', 'beets', 'eggplant', 'eggplants', 'celery', 'radish', 'radishes',
|
||||
'asparagus', 'mushroom', 'mushrooms'
|
||||
],
|
||||
[GroceryCategory.Meat]: [
|
||||
'steak', 'steaks', 'beef', 'pork', 'lamb', 'veal', 'ribeye', 'tenderloin',
|
||||
'filet mignon', 'bacon', 'ham', 'sausage', 'sausages', 'salami', 'ground beef',
|
||||
'beef mince', 'hamburger meat', 'prosciutto', 'brisket', 'pork chop', 'pork chops'
|
||||
],
|
||||
[GroceryCategory.Poultry]: [
|
||||
'chicken', 'whole chicken', 'chickens', 'chicken breast', 'chicken breasts',
|
||||
'breast of chicken', 'chicken thigh', 'chicken thighs', 'chicken leg', 'chicken legs',
|
||||
'chicken wing', 'chicken wings', 'wing', 'wings', 'drumsticks', 'chicken drumstick',
|
||||
'turkey', 'whole turkey', 'ground turkey', 'turkey breast', 'turkey breasts',
|
||||
'turkey leg', 'duck', 'ducks', 'goose', 'quail', 'pheasant'
|
||||
],
|
||||
[GroceryCategory.Bakery]: [
|
||||
'bread', 'breads', 'whole wheat bread', 'sourdough bread', 'bagel', 'bagels',
|
||||
'croissant', 'croissants', 'muffin', 'muffins', 'buns', 'hamburger bun',
|
||||
'hamburger buns', 'hotdog bun', 'hotdog buns', 'donut', 'donuts', 'roll', 'rolls',
|
||||
'dinner roll', 'dinner rolls', 'scone', 'scones', 'toast', 'ciabatta',
|
||||
'focaccia', 'brioche', 'pita', 'pitas', 'naan', 'baguette', 'baguettes',
|
||||
'pastry', 'pastries', 'pretzel', 'pretzels'
|
||||
],
|
||||
[GroceryCategory.Beverages]: [
|
||||
'coffee', 'decaf coffee', 'iced coffee', 'cold brew', 'tea', 'iced tea',
|
||||
'black tea', 'green tea', 'herbal tea', 'juice', 'apple juice', 'orange juice',
|
||||
'grape juice', 'water', 'sparkling water', 'flavored water', 'soda', 'cola',
|
||||
'diet soda', 'beer', 'lager', 'ale', 'wine', 'red wine', 'white wine',
|
||||
'whiskey', 'whisky', 'vodka', 'rum', 'gin', 'smoothie', 'smoothies', 'milkshake',
|
||||
'milkshakes', 'energy drink', 'energy drinks', 'sports drink', 'sports drinks',
|
||||
'lemonade', 'sparkling lemonade', 'iced lemonade', 'sparkling water', 'cider',
|
||||
'hard cider', 'kombucha'
|
||||
],
|
||||
[GroceryCategory.Snacks]: [
|
||||
'chips', 'potato chips', 'tortilla chips', 'corn chips', 'candy', 'candies',
|
||||
'chocolate', 'chocolates', 'dark chocolate', 'milk chocolate', 'white chocolate',
|
||||
'cookies', 'popcorn', 'pretzel', 'pretzels', 'nuts', 'mixed nuts', 'almonds',
|
||||
'cashews', 'trail mix', 'granola bar', 'granola bars', 'protein bar', 'protein bars',
|
||||
'crackers', 'gummies', 'gummy bears', 'fruit snacks', 'dried fruit',
|
||||
'peanut butter', 'rice cakes', 'snack cakes'
|
||||
],
|
||||
[GroceryCategory.Household]: [
|
||||
'detergent', 'laundry detergent', 'dish soap', 'dishwasher detergent',
|
||||
'toilet paper', 'paper towels', 'trash bags', 'bin liners', 'broom', 'mop',
|
||||
'cleaner', 'surface cleaner', 'multi-purpose cleaner', 'disinfectant', 'bleach',
|
||||
'fabric softener', 'vacuum bags', 'aluminum foil', 'plastic wrap', 'cling wrap',
|
||||
'light bulbs', 'batteries', 'laundry soap', 'sponges', 'scrubbers',
|
||||
'dishwashing liquid'
|
||||
],
|
||||
[GroceryCategory.PersonalCare]: [
|
||||
'shampoo', 'conditioner', 'hair shampoo', 'hair conditioner', 'soap', 'bar soap',
|
||||
'liquid soap', 'toothpaste', 'toothbrush', 'toothbrushes', 'electric toothbrush',
|
||||
'deodorant', 'antiperspirant', 'lotion', 'moisturizer', 'razor', 'shaving razor',
|
||||
'shaving cream', 'body wash', 'face wash', 'sunscreen', 'hair gel', 'hair spray',
|
||||
'nail polish', 'cotton swabs', 'lip balm', 'chapstick', 'hand cream', 'sanitizer'
|
||||
],
|
||||
[GroceryCategory.Frozen]: [
|
||||
'ice cream', 'ice creams', 'frozen pizza', 'frozen pizzas', 'frozen vegetables',
|
||||
'frozen veg', 'frozen peas', 'frozen fruit', 'frozen fish', 'frozen chicken',
|
||||
'frozen wings', 'frozen fries', 'frozen french fries', 'frozen shrimp',
|
||||
'frozen prawns', 'frozen dumplings', 'frozen waffles', 'frozen pancakes',
|
||||
'frozen pie', 'frozen pies', 'frozen lasagna', 'frozen burrito', 'frozen burritos',
|
||||
'frozen nuggets', 'frozen pastry', 'frozen pastries', 'frozen meals'
|
||||
],
|
||||
};
|
||||
|
||||
interface IGroceryContext {
|
||||
groceries: IGrocery[];
|
||||
//iconMapping: { [key in GroceryCategory]: MaterialIconNames };
|
||||
updateGroceryItem: (id: number, changes: Partial<IGrocery>) => void;
|
||||
updateGroceryItem: (changes: Partial<IGrocery>) => void;
|
||||
isAddingGrocery: boolean;
|
||||
setIsAddingGrocery: (value: boolean) => void;
|
||||
addGrocery: (grocery: IGrocery) => void;
|
||||
@ -68,142 +187,14 @@ export const GroceryProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
children,
|
||||
}) => {
|
||||
const [isAddingGrocery, setIsAddingGrocery] = useState<boolean>(false);
|
||||
const [groceries, setGroceries] = useState<IGrocery[]>([
|
||||
{
|
||||
id: 0,
|
||||
title: "Carrots",
|
||||
category: GroceryCategory.Vegetables,
|
||||
approved: false,
|
||||
bought: false,
|
||||
recurring: false,
|
||||
frequency: GroceryFrequency.Never,
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: "Steak",
|
||||
category: GroceryCategory.Meat,
|
||||
approved: true,
|
||||
bought: false,
|
||||
recurring: false,
|
||||
frequency: GroceryFrequency.Never,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "Chicken Breast",
|
||||
category: GroceryCategory.Poultry,
|
||||
approved: true,
|
||||
bought: false,
|
||||
recurring: false,
|
||||
frequency: GroceryFrequency.Never,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "Greek Yoghurt",
|
||||
category: GroceryCategory.Dairy,
|
||||
approved: false,
|
||||
bought: false,
|
||||
recurring: false,
|
||||
frequency: GroceryFrequency.Never,
|
||||
},
|
||||
]);
|
||||
|
||||
const { mutateAsync: createGrocery } = useCreateGrocery();
|
||||
const { mutateAsync: updateGrocery } = useUpdateGrocery();
|
||||
const { data: groceries } = useGetGroceries();
|
||||
|
||||
|
||||
const addGrocery = (grocery: IGrocery) => {
|
||||
setGroceries((prevGroceries) => [
|
||||
...prevGroceries,
|
||||
{
|
||||
...grocery,
|
||||
id: prevGroceries.length
|
||||
? prevGroceries[prevGroceries.length - 1].id + 1
|
||||
: 0,
|
||||
},
|
||||
]);
|
||||
};
|
||||
|
||||
const groceryExamples = {
|
||||
[GroceryCategory.Fruit]: [
|
||||
'apple', 'apples', 'banana', 'bananas', 'orange', 'oranges', 'grape', 'grapes',
|
||||
'pear', 'pears', 'pineapple', 'pineapples', 'kiwi', 'kiwis', 'strawberry',
|
||||
'strawberries', 'blueberry', 'blueberries', 'mango', 'mangoes', 'watermelon',
|
||||
'watermelons', 'peach', 'peaches', 'plum', 'plums', 'cherry', 'cherries',
|
||||
'raspberry', 'raspberries', 'blackberry', 'blackberries', 'pomegranate',
|
||||
'pomegranates', 'lemon', 'lemons', 'lime', 'limes', 'coconut', 'coconuts'
|
||||
],
|
||||
[GroceryCategory.Dairy]: [
|
||||
'milk', 'whole milk', 'skim milk', 'almond milk', 'soy milk', 'cheese',
|
||||
'cheeses', 'yoghurt', 'yogurt', 'greek yoghurt', 'greek yogurt', 'butter',
|
||||
'margarine', 'cream', 'whipping cream', 'heavy cream', 'ice cream', 'ice creams',
|
||||
'sour cream', 'whipped cream', 'cream cheese', 'cream cheeses', 'buttermilk',
|
||||
'cottage cheese', 'ghee', 'kefir'
|
||||
],
|
||||
[GroceryCategory.Vegetables]: [
|
||||
'carrot', 'carrots', 'broccoli', 'lettuce', 'lettuces', 'spinach', 'kale',
|
||||
'cabbage', 'cabbages', 'cauliflower', 'zucchini', 'zucchinis', 'onion', 'onions',
|
||||
'garlic', 'pepper', 'peppers', 'bell pepper', 'bell peppers', 'tomato', 'tomatoes',
|
||||
'cucumber', 'cucumbers', 'potato', 'potatoes', 'sweet potato', 'sweet potatoes',
|
||||
'beet', 'beets', 'eggplant', 'eggplants', 'celery', 'radish', 'radishes',
|
||||
'asparagus', 'mushroom', 'mushrooms'
|
||||
],
|
||||
[GroceryCategory.Meat]: [
|
||||
'steak', 'steaks', 'beef', 'pork', 'lamb', 'veal', 'ribeye', 'tenderloin',
|
||||
'filet mignon', 'bacon', 'ham', 'sausage', 'sausages', 'salami', 'ground beef',
|
||||
'beef mince', 'hamburger meat', 'prosciutto', 'brisket', 'pork chop', 'pork chops'
|
||||
],
|
||||
[GroceryCategory.Poultry]: [
|
||||
'chicken', 'whole chicken', 'chickens', 'chicken breast', 'chicken breasts',
|
||||
'breast of chicken', 'chicken thigh', 'chicken thighs', 'chicken leg', 'chicken legs',
|
||||
'chicken wing', 'chicken wings', 'wing', 'wings', 'drumsticks', 'chicken drumstick',
|
||||
'turkey', 'whole turkey', 'ground turkey', 'turkey breast', 'turkey breasts',
|
||||
'turkey leg', 'duck', 'ducks', 'goose', 'quail', 'pheasant'
|
||||
],
|
||||
[GroceryCategory.Bakery]: [
|
||||
'bread', 'breads', 'whole wheat bread', 'sourdough bread', 'bagel', 'bagels',
|
||||
'croissant', 'croissants', 'muffin', 'muffins', 'buns', 'hamburger bun',
|
||||
'hamburger buns', 'hotdog bun', 'hotdog buns', 'donut', 'donuts', 'roll', 'rolls',
|
||||
'dinner roll', 'dinner rolls', 'scone', 'scones', 'toast', 'ciabatta',
|
||||
'focaccia', 'brioche', 'pita', 'pitas', 'naan', 'baguette', 'baguettes',
|
||||
'pastry', 'pastries', 'pretzel', 'pretzels'
|
||||
],
|
||||
[GroceryCategory.Beverages]: [
|
||||
'coffee', 'decaf coffee', 'iced coffee', 'cold brew', 'tea', 'iced tea',
|
||||
'black tea', 'green tea', 'herbal tea', 'juice', 'apple juice', 'orange juice',
|
||||
'grape juice', 'water', 'sparkling water', 'flavored water', 'soda', 'cola',
|
||||
'diet soda', 'beer', 'lager', 'ale', 'wine', 'red wine', 'white wine',
|
||||
'whiskey', 'whisky', 'vodka', 'rum', 'gin', 'smoothie', 'smoothies', 'milkshake',
|
||||
'milkshakes', 'energy drink', 'energy drinks', 'sports drink', 'sports drinks',
|
||||
'lemonade', 'sparkling lemonade', 'iced lemonade', 'sparkling water', 'cider',
|
||||
'hard cider', 'kombucha'
|
||||
],
|
||||
[GroceryCategory.Snacks]: [
|
||||
'chips', 'potato chips', 'tortilla chips', 'corn chips', 'candy', 'candies',
|
||||
'chocolate', 'chocolates', 'dark chocolate', 'milk chocolate', 'white chocolate',
|
||||
'cookies', 'popcorn', 'pretzel', 'pretzels', 'nuts', 'mixed nuts', 'almonds',
|
||||
'cashews', 'trail mix', 'granola bar', 'granola bars', 'protein bar', 'protein bars',
|
||||
'crackers', 'gummies', 'gummy bears', 'fruit snacks', 'dried fruit',
|
||||
'peanut butter', 'rice cakes', 'snack cakes'
|
||||
],
|
||||
[GroceryCategory.Household]: [
|
||||
'detergent', 'laundry detergent', 'dish soap', 'dishwasher detergent',
|
||||
'toilet paper', 'paper towels', 'trash bags', 'bin liners', 'broom', 'mop',
|
||||
'cleaner', 'surface cleaner', 'multi-purpose cleaner', 'disinfectant', 'bleach',
|
||||
'fabric softener', 'vacuum bags', 'aluminum foil', 'plastic wrap', 'cling wrap',
|
||||
'light bulbs', 'batteries', 'laundry soap', 'sponges', 'scrubbers',
|
||||
'dishwashing liquid'
|
||||
],
|
||||
[GroceryCategory.PersonalCare]: [
|
||||
'shampoo', 'conditioner', 'hair shampoo', 'hair conditioner', 'soap', 'bar soap',
|
||||
'liquid soap', 'toothpaste', 'toothbrush', 'toothbrushes', 'electric toothbrush',
|
||||
'deodorant', 'antiperspirant', 'lotion', 'moisturizer', 'razor', 'shaving razor',
|
||||
'shaving cream', 'body wash', 'face wash', 'sunscreen', 'hair gel', 'hair spray',
|
||||
'nail polish', 'cotton swabs', 'lip balm', 'chapstick', 'hand cream', 'sanitizer'
|
||||
],
|
||||
[GroceryCategory.Frozen]: [
|
||||
'ice cream', 'ice creams', 'frozen pizza', 'frozen pizzas', 'frozen vegetables',
|
||||
'frozen veg', 'frozen peas', 'frozen fruit', 'frozen fish', 'frozen chicken',
|
||||
'frozen wings', 'frozen fries', 'frozen french fries', 'frozen shrimp',
|
||||
'frozen prawns', 'frozen dumplings', 'frozen waffles', 'frozen pancakes',
|
||||
'frozen pie', 'frozen pies', 'frozen lasagna', 'frozen burrito', 'frozen burritos',
|
||||
'frozen nuggets', 'frozen pastry', 'frozen pastries', 'frozen meals'
|
||||
],
|
||||
createGrocery(grocery);
|
||||
};
|
||||
|
||||
const fuzzyMatchGroceryCategory = (groceryTitle: string): GroceryCategory => {
|
||||
@ -221,12 +212,8 @@ export const GroceryProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
return bestMatchCategory;
|
||||
};
|
||||
|
||||
const updateGroceryItem = (id: number, changes: Partial<IGrocery>) => {
|
||||
setGroceries((prevGroceries) =>
|
||||
prevGroceries.map((grocery) =>
|
||||
grocery.id === id ? { ...grocery, ...changes } : grocery
|
||||
)
|
||||
);
|
||||
const updateGroceryItem = (changes: Partial<IGrocery>) => {
|
||||
updateGrocery(changes);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
12
hooks/firebase/types/groceryData.ts
Normal file
12
hooks/firebase/types/groceryData.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import {GroceryCategory, GroceryFrequency} from "@/contexts/GroceryContext";
|
||||
|
||||
export interface IGrocery {
|
||||
id: string;
|
||||
title: string;
|
||||
category: GroceryCategory;
|
||||
approved: boolean;
|
||||
recurring: boolean;
|
||||
frequency: GroceryFrequency;
|
||||
bought: boolean;
|
||||
familyId?: string,
|
||||
}
|
||||
26
hooks/firebase/useCreateGrocery.ts
Normal file
26
hooks/firebase/useCreateGrocery.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { useMutation, useQueryClient } from "react-query";
|
||||
import firestore from "@react-native-firebase/firestore";
|
||||
import { useAuthContext } from "@/contexts/AuthContext";
|
||||
import {IGrocery} from "@/hooks/firebase/types/groceryData";
|
||||
|
||||
export const useCreateGrocery = () => {
|
||||
const { profileData } = useAuthContext();
|
||||
const queryClients = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationKey: ["createGrocery"],
|
||||
mutationFn: async (groceryData: Partial<IGrocery>) => {
|
||||
try {
|
||||
const newDoc = firestore().collection('Groceries').doc();
|
||||
await firestore()
|
||||
.collection("Groceries")
|
||||
.add({...groceryData, id: newDoc.id, familyId: profileData?.familyId})
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClients.invalidateQueries("groceries")
|
||||
}
|
||||
})
|
||||
}
|
||||
31
hooks/firebase/useGetGroceries.ts
Normal file
31
hooks/firebase/useGetGroceries.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import {useQuery} from "react-query";
|
||||
import firestore from "@react-native-firebase/firestore";
|
||||
import {useAuthContext} from "@/contexts/AuthContext";
|
||||
|
||||
export const useGetGroceries = () => {
|
||||
const { user, profileData } = useAuthContext();
|
||||
|
||||
return useQuery({
|
||||
queryKey: ["groceries", user?.uid],
|
||||
queryFn: async () => {
|
||||
const snapshot = await firestore()
|
||||
.collection("Groceries")
|
||||
.where("familyId", "==", profileData?.familyId)
|
||||
.get();
|
||||
|
||||
return snapshot.docs.map((doc) => {
|
||||
const data = doc.data();
|
||||
|
||||
return {
|
||||
id: doc.id,
|
||||
title: data.title,
|
||||
category: data.category,
|
||||
approved: data.approved,
|
||||
bought: data.bought,
|
||||
recurring: data.recurring,
|
||||
frequency: data.frequency
|
||||
};
|
||||
});
|
||||
}
|
||||
})
|
||||
};
|
||||
25
hooks/firebase/useUpdateGrocery.ts
Normal file
25
hooks/firebase/useUpdateGrocery.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import {useMutation, useQueryClient} from "react-query";
|
||||
import firestore from "@react-native-firebase/firestore";
|
||||
import {IGrocery} from "@/hooks/firebase/types/groceryData";
|
||||
|
||||
export const useUpdateGrocery = () => {
|
||||
const queryClients = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
mutationKey: ["updateGrocery"],
|
||||
mutationFn: async (groceryData: Partial<IGrocery>) => {
|
||||
console.log(groceryData);
|
||||
try {
|
||||
await firestore()
|
||||
.collection("Groceries")
|
||||
.doc(groceryData.id)
|
||||
.update(groceryData);
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClients.invalidateQueries("events")
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user