- Rewrote add, edit groceries

- Added validation
This commit is contained in:
Dejan
2024-12-29 21:10:10 +01:00
parent 81d791dd17
commit ff81570e15
4 changed files with 86 additions and 125 deletions

View File

@ -1,33 +1,43 @@
import { Text, TextField, TextFieldRef, View } from "react-native-ui-lib"; import { Text, TextField, TextFieldRef, View } from "react-native-ui-lib";
import React, { useEffect, useRef } from "react"; import React, { useEffect, useRef, useState } from "react";
import { GroceryCategory, useGroceryContext } from "@/contexts/GroceryContext"; import { GroceryCategory, GroceryFrequency, useGroceryContext } from "@/contexts/GroceryContext";
import { Dropdown } from "react-native-element-dropdown"; import { Dropdown } from "react-native-element-dropdown";
import CloseXIcon from "@/assets/svgs/CloseXIcon"; import CloseXIcon from "@/assets/svgs/CloseXIcon";
import { findNodeHandle, StyleSheet, UIManager } from "react-native"; import {Alert, findNodeHandle, StyleSheet, UIManager} from "react-native";
import DropdownIcon from "@/assets/svgs/DropdownIcon"; import DropdownIcon from "@/assets/svgs/DropdownIcon";
import { AntDesign } from "@expo/vector-icons"; import { AntDesign } from "@expo/vector-icons";
import { ProfileType, useAuthContext } from "@/contexts/AuthContext";
import { IGrocery } from "@/hooks/firebase/types/groceryData";
interface IEditGrocery { const defaultGroceryItem = {
id?: string; id: "",
title: string; title: "",
category: GroceryCategory; category: GroceryCategory.None,
setTitle: (value: string) => void; approved: false,
setCategory?: (category: GroceryCategory) => void; recurring: false,
setSubmit?: (value: boolean) => void; frequency: GroceryFrequency.Never,
closeEdit?: () => void; bought: false,
handleEditSubmit?: Function; };
}
const EditGroceryItem = ({ const EditGroceryItem = ({
editGrocery, editGrocery,
onInputFocus, onInputFocus,
closeEdit
}: { }: {
editGrocery: IEditGrocery; editGrocery?: IGrocery;
onInputFocus: (y: number) => void; onInputFocus: (y: number) => void;
closeEdit?: Function
}) => { }) => {
const { fuzzyMatchGroceryCategory } = useGroceryContext(); const { fuzzyMatchGroceryCategory } = useGroceryContext();
const inputRef = useRef<TextFieldRef>(null); const inputRef = useRef<TextFieldRef>(null);
const containerRef = useRef(null); const containerRef = useRef(null);
const { profileData } = useAuthContext();
const {
updateGroceryItem,
addGrocery,
} = useGroceryContext();
const [grocery, setGrocery] = useState(editGrocery ?? defaultGroceryItem);
const handleFocus = () => { const handleFocus = () => {
if (containerRef.current) { if (containerRef.current) {
@ -57,29 +67,47 @@ const EditGroceryItem = ({
}) })
); );
const handleClose = () => {
setGrocery(defaultGroceryItem);
}
const handleSubmit = () => { const handleSubmit = () => {
inputRef?.current?.blur(); if (validateGrocery()) {
if (editGrocery.setSubmit) { if (grocery?.id === "") {
editGrocery.setSubmit(true); addGrocery({...grocery, approved: profileData?.userType === ProfileType.PARENT || profileData?.userType === ProfileType.CAREGIVER});
} else {
updateGroceryItem(grocery);
} }
if (editGrocery.handleEditSubmit) { setGrocery(defaultGroceryItem);
editGrocery.handleEditSubmit({ if (closeEdit) {
id: editGrocery.id, closeEdit();
title: editGrocery.title,
category: editGrocery.category,
});
} }
if (editGrocery.closeEdit) { } else {
editGrocery.closeEdit(); return;
}
}
const validateGrocery = () => {
if (!grocery?.title || grocery?.title === "") {
Alert.alert('Alert', 'Title field cannot be empty');
return false;
} else if (grocery.title?.length < 3 || grocery.title?.length > 25) {
Alert.alert('Alert', 'Title should be between 3 and 25 characters');
return false;
}
if (!grocery?.category || grocery?.category === "") {
Alert.alert('Alert', 'Category cannot be empty');
return false;
}
return true;
} }
};
useEffect(() => { useEffect(() => {
if (inputRef.current) { if (inputRef.current) {
inputRef.current.focus(); inputRef.current.focus();
} }
console.log(editGrocery.category);
}, []); }, []);
return ( return (
@ -100,20 +128,19 @@ const EditGroceryItem = ({
ref={inputRef} ref={inputRef}
onFocus={handleFocus} onFocus={handleFocus}
placeholder="Grocery" placeholder="Grocery"
value={editGrocery.title} value={grocery?.title}
onSubmitEditing={handleSubmit} onSubmitEditing={handleSubmit}
numberOfLines={1} numberOfLines={1}
returnKeyType="done" returnKeyType="done"
onChangeText={(value) => { onChangeText={(value) => {
editGrocery.setTitle(value);
let groceryCategory = fuzzyMatchGroceryCategory(value); let groceryCategory = fuzzyMatchGroceryCategory(value);
if (editGrocery.setCategory) { setGrocery((oldData) => ({...oldData, title: value, category: groceryCategory}));
editGrocery.setCategory(groceryCategory);
}
}} }}
maxLength={25} maxLength={25}
/> />
{(editGrocery.title || editGrocery.title !== "") && <View row centerV> {(grocery?.title !== "") &&
<View row centerV>
{grocery.title?.length > 2 && grocery.title?.length <= 25 &&
<AntDesign <AntDesign
name="check" name="check"
size={24} size={24}
@ -123,14 +150,14 @@ const EditGroceryItem = ({
}} }}
onPress={handleSubmit} onPress={handleSubmit}
/> />
}
<CloseXIcon <CloseXIcon
onPress={() => { onPress={() => {
if (editGrocery.closeEdit) { handleClose();
editGrocery.closeEdit();
}
}} }}
/> />
</View>} </View>
}
</View> </View>
<Dropdown <Dropdown
style={{ marginTop: 15 }} style={{ marginTop: 15 }}
@ -143,7 +170,7 @@ const EditGroceryItem = ({
}} }}
labelField="label" labelField="label"
valueField="value" valueField="value"
value={editGrocery.category} value={grocery?.category ?? GroceryCategory.None}
iconColor="white" iconColor="white"
activeColor={"#fd1775"} activeColor={"#fd1775"}
containerStyle={styles.dropdownStyle} containerStyle={styles.dropdownStyle}
@ -154,7 +181,7 @@ const EditGroceryItem = ({
<DropdownIcon <DropdownIcon
style={{ marginRight: 8 }} style={{ marginRight: 8 }}
color={ color={
editGrocery.category == GroceryCategory.None grocery?.category == GroceryCategory.None
? "#7b7b7b" ? "#7b7b7b"
: "#fd1775" : "#fd1775"
} }
@ -168,17 +195,7 @@ const EditGroceryItem = ({
); );
}} }}
onChange={(item) => { onChange={(item) => {
if (editGrocery.handleEditSubmit) { setGrocery((oldData) => ({...oldData, category: item.value}));
editGrocery.handleEditSubmit({
id: editGrocery.id,
category: item.value,
});
if (editGrocery.closeEdit) editGrocery.closeEdit();
} else {
if (editGrocery.setCategory) {
editGrocery.setCategory(item.value);
}
}
}} }}
/> />
</View> </View>

View File

@ -1,7 +1,7 @@
import { Checkbox, Text, TouchableOpacity, View } from "react-native-ui-lib"; import { Checkbox, Text, TouchableOpacity, View } from "react-native-ui-lib";
import React, { useState } from "react"; import React, { useState } from "react";
import { AntDesign } from "@expo/vector-icons"; import { AntDesign } from "@expo/vector-icons";
import { GroceryCategory, useGroceryContext } from "@/contexts/GroceryContext"; import { useGroceryContext } from "@/contexts/GroceryContext";
import EditGroceryFrequency from "./EditGroceryFrequency"; import EditGroceryFrequency from "./EditGroceryFrequency";
import EditGroceryItem from "./EditGroceryItem"; import EditGroceryItem from "./EditGroceryItem";
import { ImageBackground, StyleSheet } from "react-native"; import { ImageBackground, StyleSheet } from "react-native";
@ -32,10 +32,6 @@ const GroceryItem = ({
const [openFreqEdit, setOpenFreqEdit] = useState<boolean>(false); const [openFreqEdit, setOpenFreqEdit] = useState<boolean>(false);
const [isEditingTitle, setIsEditingTitle] = useState<boolean>(false); const [isEditingTitle, setIsEditingTitle] = useState<boolean>(false);
const [newTitle, setNewTitle] = useState<string>(item.title ?? "");
const [category, setCategory] = useState<GroceryCategory>(
item.category ?? GroceryCategory.None
);
const closeEdit = () => setIsEditingTitle(false); const closeEdit = () => setIsEditingTitle(false);
@ -72,15 +68,9 @@ const GroceryItem = ({
{isEditingTitle ? ( {isEditingTitle ? (
<EditGroceryItem <EditGroceryItem
editGrocery={{ editGrocery={item}
id: item.id,
title: newTitle,
category: category,
setTitle: setNewTitle,
setCategory: setCategory,
closeEdit: closeEdit,
}}
onInputFocus={onInputFocus} onInputFocus={onInputFocus}
closeEdit={closeEdit}
/> />
) : ( ) : (
<View flex> <View flex>

View File

@ -2,11 +2,10 @@ import { ActivityIndicator, Dimensions, FlatList, StyleSheet } from "react-nativ
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { Text, TouchableOpacity, View } from "react-native-ui-lib"; import { Text, TouchableOpacity, View } from "react-native-ui-lib";
import GroceryItem from "./GroceryItem"; import GroceryItem from "./GroceryItem";
import { GroceryCategory, GroceryFrequency, useGroceryContext } from "@/contexts/GroceryContext"; import { useGroceryContext } from "@/contexts/GroceryContext";
import HeaderTemplate from "@/components/shared/HeaderTemplate"; import HeaderTemplate from "@/components/shared/HeaderTemplate";
import { AntDesign } from "@expo/vector-icons"; import { AntDesign } from "@expo/vector-icons";
import EditGroceryItem from "./EditGroceryItem"; import EditGroceryItem from "./EditGroceryItem";
import { ProfileType, useAuthContext } from "@/contexts/AuthContext";
import { IGrocery } from "@/hooks/firebase/types/groceryData"; import { IGrocery } from "@/hooks/firebase/types/groceryData";
import Ionicons from '@expo/vector-icons/Ionicons'; import Ionicons from '@expo/vector-icons/Ionicons';
import AddChoreDialog from "@/components/pages/todos/AddChoreDialog"; import AddChoreDialog from "@/components/pages/todos/AddChoreDialog";
@ -28,24 +27,14 @@ const GroceryList = ({onInputFocus}: {onInputFocus: (y: number) => void}) => {
const { const {
groceries, groceries,
updateGroceryItem, updateGroceryItem,
isAddingGrocery,
setIsAddingGrocery,
addGrocery,
} = useGroceryContext(); } = useGroceryContext();
const { profileData } = useAuthContext();
const [approvedGroceries, setApprovedGroceries] = useState<IGrocery[]>( const [approvedGroceries, setApprovedGroceries] = useState<IGrocery[]>(
groceries?.filter((item) => item.approved) groceries?.filter((item) => item.approved)
); );
const [pendingGroceries, setPendingGroceries] = useState<IGrocery[]>( const [pendingGroceries, setPendingGroceries] = useState<IGrocery[]>(
groceries?.filter((item) => !item.approved) groceries?.filter((item) => !item.approved)
); );
const [category, setCategory] = useState<GroceryCategory>(
GroceryCategory.None
);
const [title, setTitle] = useState<string>("");
const [submit, setSubmitted] = useState<boolean>(false);
const [pendingVisible, setPendingVisible] = useState<boolean>(true); const [pendingVisible, setPendingVisible] = useState<boolean>(true);
const [approvedVisible, setApprovedVisible] = useState<boolean>(true); const [approvedVisible, setApprovedVisible] = useState<boolean>(true);
@ -74,37 +63,11 @@ const GroceryList = ({onInputFocus}: {onInputFocus: (y: number) => void}) => {
{} {}
); );
useEffect(() => {
if (submit) {
if (title?.length > 2 && title?.length <= 25) {
addGrocery({
id: "",
title: title,
category: category,
approved: profileData?.userType === ProfileType.PARENT || profileData?.userType === ProfileType.CAREGIVER,
recurring: false,
frequency: GroceryFrequency.Never,
bought: false,
});
setIsAddingGrocery(false);
setSubmitted(false);
setTitle("");
}
}
}, [submit]);
useEffect(() => { useEffect(() => {
setApprovedGroceries(groceries?.filter((item) => item.approved)); setApprovedGroceries(groceries?.filter((item) => item.approved));
setPendingGroceries(groceries?.filter((item) => !item.approved)); setPendingGroceries(groceries?.filter((item) => !item.approved));
}, [groceries]); }, [groceries]);
const handleCancelAddGrocery = () => {
setIsAddingGrocery(false);
setTitle("");
setCategory(GroceryCategory.None)
}
return ( return (
<> <>
{!groceries && {!groceries &&
@ -260,14 +223,6 @@ const GroceryList = ({onInputFocus}: {onInputFocus: (y: number) => void}) => {
</View> </View>
<View style={{marginTop: 8}}> <View style={{marginTop: 8}}>
<EditGroceryItem <EditGroceryItem
editGrocery={{
title: title,
setCategory: setCategory,
category: category,
setTitle: setTitle,
setSubmit: setSubmitted,
closeEdit: handleCancelAddGrocery
}}
onInputFocus={onInputFocus} onInputFocus={onInputFocus}
/> />
</View> </View>

View File

@ -1,7 +1,6 @@
import { Dimensions, ScrollView, Keyboard, Platform } from "react-native"; import { Dimensions, ScrollView, Keyboard, Platform } from "react-native";
import { View } from "react-native-ui-lib"; import { View } from "react-native-ui-lib";
import React, { useEffect, useRef, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
import AddGroceryItem from "./AddGroceryItem";
import GroceryList from "./GroceryList"; import GroceryList from "./GroceryList";
import { useGroceryContext } from "@/contexts/GroceryContext"; import { useGroceryContext } from "@/contexts/GroceryContext";