Files
cally/components/pages/grocery/EditGroceryItem.tsx
Dejan ff81570e15 - Rewrote add, edit groceries
- Added validation
2024-12-29 21:10:10 +01:00

221 lines
6.1 KiB
TypeScript

import { Text, TextField, TextFieldRef, View } from "react-native-ui-lib";
import React, { useEffect, useRef, useState } from "react";
import { GroceryCategory, GroceryFrequency, useGroceryContext } from "@/contexts/GroceryContext";
import { Dropdown } from "react-native-element-dropdown";
import CloseXIcon from "@/assets/svgs/CloseXIcon";
import {Alert, findNodeHandle, StyleSheet, UIManager} from "react-native";
import DropdownIcon from "@/assets/svgs/DropdownIcon";
import { AntDesign } from "@expo/vector-icons";
import { ProfileType, useAuthContext } from "@/contexts/AuthContext";
import { IGrocery } from "@/hooks/firebase/types/groceryData";
const defaultGroceryItem = {
id: "",
title: "",
category: GroceryCategory.None,
approved: false,
recurring: false,
frequency: GroceryFrequency.Never,
bought: false,
};
const EditGroceryItem = ({
editGrocery,
onInputFocus,
closeEdit
}: {
editGrocery?: IGrocery;
onInputFocus: (y: number) => void;
closeEdit?: Function
}) => {
const { fuzzyMatchGroceryCategory } = useGroceryContext();
const inputRef = useRef<TextFieldRef>(null);
const containerRef = useRef(null);
const { profileData } = useAuthContext();
const {
updateGroceryItem,
addGrocery,
} = useGroceryContext();
const [grocery, setGrocery] = useState(editGrocery ?? defaultGroceryItem);
const handleFocus = () => {
if (containerRef.current) {
const handle = findNodeHandle(containerRef.current);
if (handle) {
UIManager.measure(
handle,
(
x: number,
y: number,
width: number,
height: number,
pageX: number,
pageY: number
) => {
onInputFocus(pageY);
}
);
}
}
};
const groceryCategoryOptions = Object.values(GroceryCategory).map(
(category) => ({
label: category,
value: category,
})
);
const handleClose = () => {
setGrocery(defaultGroceryItem);
}
const handleSubmit = () => {
if (validateGrocery()) {
if (grocery?.id === "") {
addGrocery({...grocery, approved: profileData?.userType === ProfileType.PARENT || profileData?.userType === ProfileType.CAREGIVER});
} else {
updateGroceryItem(grocery);
}
setGrocery(defaultGroceryItem);
if (closeEdit) {
closeEdit();
}
} else {
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(() => {
if (inputRef.current) {
inputRef.current.focus();
}
}, []);
return (
<View
ref={containerRef}
style={{
backgroundColor: "white",
width: "100%",
borderRadius: 25,
paddingHorizontal: 13,
paddingVertical: 10,
marginTop: 0,
}}
>
<View row spread centerV>
<TextField
text70T
ref={inputRef}
onFocus={handleFocus}
placeholder="Grocery"
value={grocery?.title}
onSubmitEditing={handleSubmit}
numberOfLines={1}
returnKeyType="done"
onChangeText={(value) => {
let groceryCategory = fuzzyMatchGroceryCategory(value);
setGrocery((oldData) => ({...oldData, title: value, category: groceryCategory}));
}}
maxLength={25}
/>
{(grocery?.title !== "") &&
<View row centerV>
{grocery.title?.length > 2 && grocery.title?.length <= 25 &&
<AntDesign
name="check"
size={24}
style={{
color: "green",
marginRight: 15,
}}
onPress={handleSubmit}
/>
}
<CloseXIcon
onPress={() => {
handleClose();
}}
/>
</View>
}
</View>
<Dropdown
style={{ marginTop: 15 }}
data={groceryCategoryOptions}
placeholder="Select grocery category"
placeholderStyle={{
color: "#a2a2a2",
fontFamily: "Manrope_500Medium",
fontSize: 13.2,
}}
labelField="label"
valueField="value"
value={grocery?.category ?? GroceryCategory.None}
iconColor="white"
activeColor={"#fd1775"}
containerStyle={styles.dropdownStyle}
itemTextStyle={styles.itemText}
itemContainerStyle={styles.itemStyle}
selectedTextStyle={styles.selectedText}
renderLeftIcon={() => (
<DropdownIcon
style={{ marginRight: 8 }}
color={
grocery?.category == GroceryCategory.None
? "#7b7b7b"
: "#fd1775"
}
/>
)}
renderItem={(item) => {
return (
<View height={36.02} centerV>
<Text style={styles.itemText}>{item.label}</Text>
</View>
);
}}
onChange={(item) => {
setGrocery((oldData) => ({...oldData, category: item.value}));
}}
/>
</View>
);
};
const styles = StyleSheet.create({
itemText: {
fontFamily: "Manrope_400Regular",
fontSize: 15.42,
paddingLeft: 15,
},
selectedText: {
fontFamily: "Manrope_500Medium",
fontSize: 13.2,
color: "#fd1775",
},
dropdownStyle: { borderRadius: 6.61, height: 115.34, width: 187 },
itemStyle: { padding: 0, margin: 0 },
});
export default EditGroceryItem;