diff --git a/components/CustomModal/CustomModal.js b/components/CustomModal/CustomModal.js new file mode 100644 index 0000000..1524cd8 --- /dev/null +++ b/components/CustomModal/CustomModal.js @@ -0,0 +1,127 @@ +import React, { useState, useEffect } from "react"; +import { Modal, TextInput, View } from "react-native"; +import { Picker } from "@react-native-picker/picker"; // Import Picker for dropdown +import { RadioButton } from "react-native-paper"; // Import RadioButton for radio inputs +import styles from "./styles"; +import { ThemedView } from "../common/ThemedView"; +import ThemedButton from "../common/ThemedButton"; +import { ThemedText } from "../common/ThemedText"; + +const CustomModal = ({ onClose, onSave, onDelete, item, schema }) => { + const initializeFormData = (schema, item) => { + return schema.reduce((acc, field) => { + acc[field.name] = item ? item[field.name] : ""; + return acc; + }, {}); + }; + + const [formData, setFormData] = useState(() => + initializeFormData(schema, item) + ); + + useEffect(() => { + setFormData(initializeFormData(schema, item)); + }, [item, schema]); + + const handleInputChange = (name, value) => { + setFormData((prevData) => ({ ...prevData, [name]: value })); + }; + + const handleSave = () => { + onSave(formData); + }; + + const handleDelete = () => { + onDelete(); + }; + + return ( + + + {schema.map((field) => { + switch (field.type) { + case "dropdown": + return ( + + handleInputChange(field.name, value) + } + style={styles.dropdown} + > + + {field.options.map((option) => ( + + ))} + + ); + case "radio": + return ( + + {field.placeholder} + {field.options.map((option) => ( + + handleInputChange(field.name, option)} + /> + {option} + + ))} + + ); + default: + return ( + handleInputChange(field.name, value)} + keyboardType={field.inputMode} + /> + ); + } + })} + + + Delete + + + Update + + + + + Close + + + + + ); +}; + +export default CustomModal; diff --git a/components/Modal/styles.js b/components/CustomModal/styles.js similarity index 63% rename from components/Modal/styles.js rename to components/CustomModal/styles.js index 12f1572..646eb1c 100644 --- a/components/Modal/styles.js +++ b/components/CustomModal/styles.js @@ -18,6 +18,7 @@ export default StyleSheet.create({ elevation: 10, backgroundColor: "#fff", }, + // Input fields input: { borderWidth: 1, borderColor: "#ccc", @@ -26,6 +27,38 @@ export default StyleSheet.create({ marginBottom: 15, fontSize: 16, }, + radioGroup: { + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", + marginBottom: 15, + padding: 10, + paddingHorizontal: 20, + borderWidth: 1, + borderColor: "#ccc", + borderRadius: 10, + backgroundColor: "#fff", + }, + radioItem: { + flexDirection: "row", + alignItems: "center", + }, + radioLabel: { + marginLeft: 8, + fontSize: 16, + color: "#333", + }, + dropdown: { + width: "100%", + marginBottom: 15, + borderWidth: 1, + borderColor: "#ccc", + borderRadius: 10, + padding: 15, + backgroundColor: "#fff", + fontSize: 16, + }, + buttonContainer: { flexDirection: "row", justifyContent: "space-between", diff --git a/components/FloatingLabelInput/FloatingLabelInput.js b/components/FloatingLabelInput/FloatingLabelInput.js new file mode 100644 index 0000000..9774ba9 --- /dev/null +++ b/components/FloatingLabelInput/FloatingLabelInput.js @@ -0,0 +1,54 @@ +import React, { useState } from "react"; +import { View, TextInput, Text, Animated } from "react-native"; + +const FloatingLabelInput = ({ label, value, onChangeText, ...props }) => { + const [isFocused, setIsFocused] = useState(false); + const animatedIsFocused = new Animated.Value(value === "" ? 0 : 1); + + const handleFocus = () => setIsFocused(true); + const handleBlur = () => setIsFocused(false); + + React.useEffect(() => { + Animated.timing(animatedIsFocused, { + toValue: isFocused || value !== "" ? 1 : 0, + duration: 200, + useNativeDriver: false, + }).start(); + }, [isFocused, value]); + + const labelStyle = { + position: "absolute", + left: 15, + top: animatedIsFocused.interpolate({ + inputRange: [0, 1], + outputRange: [20, 0], + }), + fontSize: animatedIsFocused.interpolate({ + inputRange: [0, 1], + outputRange: [16, 12], + }), + color: "#aaa", + }; + + return ( + + {label} + + + ); +}; + +export default FloatingLabelInput; diff --git a/components/Modal/Modal.js b/components/Modal/Modal.js deleted file mode 100644 index 15f82bd..0000000 --- a/components/Modal/Modal.js +++ /dev/null @@ -1,88 +0,0 @@ -import React, { useState, useEffect } from "react"; -import { Modal, TextInput } from "react-native"; -import styles from "./styles"; -import { ThemedView } from "../common/ThemedView"; -import ThemedButton from "../common/ThemedButton"; -import { ThemedText } from "../common/ThemedText"; -import { View } from "react-native-animatable"; - -const CustomModal = ({ visible, onClose, onSave, onDelete, item, schema }) => { - const [formData, setFormData] = useState({}); - - useEffect(() => { - if (item) { - setFormData(item); - } else { - const initialFormData = schema.reduce((acc, field) => { - acc[field.name] = ""; - return acc; - }, {}); - setFormData(initialFormData); - } - }, [item, schema]); - - const handleInputChange = (name, value) => { - console.log(`Updating ${name} with value:`, value); - setFormData((prevData) => { - const newData = { ...prevData, [name]: value }; - return newData; - }); - }; - - const handleSave = () => { - onSave(formData); - }; - - const handleDelete = () => { - onDelete(); - }; - - return ( - - - {schema.map((field) => ( - handleInputChange(field.name, value)} - keyboardType={field.keyboardType} - /> - ))} - - - Delete - - - Update - - - - - Close - - - - - ); -}; - -export default CustomModal; diff --git a/package-lock.json b/package-lock.json index 046c890..8f983c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ "react-native-animatable": "^1.4.0", "react-native-elements": "^3.4.3", "react-native-gesture-handler": "~2.16.1", + "react-native-paper": "^5.12.5", "react-native-parallax-scroll-view": "^0.21.3", "react-native-reanimated": "~3.10.1", "react-native-responsive-screen": "^1.4.2", @@ -2156,6 +2157,28 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@callstack/react-theme-provider": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@callstack/react-theme-provider/-/react-theme-provider-3.0.9.tgz", + "integrity": "sha512-tTQ0uDSCL0ypeMa8T/E9wAZRGKWj8kXP7+6RYgPTfOPs9N07C9xM8P02GJ3feETap4Ux5S69D9nteq9mEj86NA==", + "license": "MIT", + "dependencies": { + "deepmerge": "^3.2.0", + "hoist-non-react-statics": "^3.3.0" + }, + "peerDependencies": { + "react": ">=16.3.0" + } + }, + "node_modules/@callstack/react-theme-provider/node_modules/deepmerge": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.3.0.tgz", + "integrity": "sha512-GRQOafGHwMHpjPx9iCvTgpu9NojZ49q794EEL94JVEw6VaeA8XTUyBKvAkOOjBX9oJNiV6G3P+T+tihFjo2TqA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@egjs/hammerjs": { "version": "2.0.17", "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", @@ -11824,9 +11847,9 @@ "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==" }, "node_modules/fast-xml-parser": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.0.tgz", - "integrity": "sha512-kLY3jFlwIYwBNDojclKsNAC12sfD6NwW74QB2CoNGPvtVxjliYehVunB3HYyNi+n4Tt1dAcgwYvmKF/Z18flqg==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", "funding": [ { "type": "github", @@ -11837,6 +11860,7 @@ "url": "https://paypal.me/naturalintelligence" } ], + "license": "MIT", "dependencies": { "strnum": "^1.0.5" }, @@ -18412,6 +18436,33 @@ "react": "^16.6.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-native-paper": { + "version": "5.12.5", + "resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-5.12.5.tgz", + "integrity": "sha512-Qpqd1g9PClmjGj/Dkr1htAwt8cTZ3SCHVmhttxRuG/QML7KzHm5ArLNgR7vz5dW1EwJqTmyl/3gd6gnrtw90mw==", + "license": "MIT", + "dependencies": { + "@callstack/react-theme-provider": "^3.0.9", + "color": "^3.1.2", + "use-latest-callback": "^0.1.5" + }, + "peerDependencies": { + "react": "*", + "react-native": "*", + "react-native-safe-area-context": "*", + "react-native-vector-icons": "*" + } + }, + "node_modules/react-native-paper/node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, "node_modules/react-native-parallax-scroll-view": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/react-native-parallax-scroll-view/-/react-native-parallax-scroll-view-0.21.3.tgz", diff --git a/package.json b/package.json index 8287e95..eb088f6 100644 --- a/package.json +++ b/package.json @@ -38,13 +38,14 @@ "react-native-animatable": "^1.4.0", "react-native-elements": "^3.4.3", "react-native-gesture-handler": "~2.16.1", + "react-native-paper": "^5.12.5", "react-native-parallax-scroll-view": "^0.21.3", "react-native-reanimated": "~3.10.1", "react-native-responsive-screen": "^1.4.2", "react-native-safe-area-context": "4.10.1", "react-native-screens": "3.31.1", - "react-native-vector-icons": "^10.1.0", "react-native-super-grid": "^6.0.1", + "react-native-vector-icons": "^10.1.0", "react-native-web": "^0.19.12" }, "devDependencies": { diff --git a/screens/InventoryScreen/InventoryScreenView.js b/screens/InventoryScreen/InventoryScreenView.js index d5d4a8e..1e99553 100644 --- a/screens/InventoryScreen/InventoryScreenView.js +++ b/screens/InventoryScreen/InventoryScreenView.js @@ -1,7 +1,7 @@ import React, { useState, useEffect } from "react"; import { FlatList } from "react-native"; import InventoryItem from "@/components/InventoryItem/InventoryItem"; -import CustomModal from "@/components/Modal/Modal"; +import CustomModal from "@/components/CustomModal/CustomModal"; import { searchByNameKey } from "@/screens/common/searchCriteria"; import styles from "@/screens/common/styles"; import CustomSearchBar from "@/screens/common/SearchBar"; @@ -10,12 +10,37 @@ import ThemedButton from "@/components/common/ThemedButton"; import { ThemedText } from "@/components/common/ThemedText"; const formSchema = [ - { name: "searchableKey", placeholder: "Key", keyboardType: "default" }, - { name: "name", placeholder: "Item Name", keyboardType: "default" }, - { name: "price", placeholder: "Price", keyboardType: "numeric" }, - { name: "quantity", placeholder: "Quantity", keyboardType: "numeric" }, - { name: "unit", placeholder: "Unit", keyboardType: "default" }, - { name: "image", placeholder: "Image URL", keyboardType: "default" }, + { + name: "searchableKey", + placeholder: "Key", + inputMode: "default", + type: "text", + }, + { + name: "name", + placeholder: "Item Name", + inputMode: "default", + type: "text", + }, + { + name: "price", + placeholder: "Price", + inputMode: "numeric", + type: "text", + }, + { + name: "quantity", + placeholder: "Quantity", + inputMode: "numeric", + type: "text", + }, + { name: "unit", placeholder: "Unit", inputMode: "default", type: "text" }, + { + name: "image", + placeholder: "Image URL", + inputMode: "default", + type: "text", + }, ]; const InventoryScreenView = ({ @@ -81,14 +106,15 @@ const InventoryScreenView = ({ /> )} /> - setModalVisible(false)} - onSave={handleSaveItem} - onDelete={handleDeleteItem} - item={currentItem} - schema={formSchema} - /> + {modalVisible && ( + setModalVisible(false)} + onSave={handleSaveItem} + onDelete={handleDeleteItem} + item={currentItem} + schema={formSchema} + /> + )} ); diff --git a/screens/MenuScreen/MenuScreenView.js b/screens/MenuScreen/MenuScreenView.js index 036b4de..ef30eea 100644 --- a/screens/MenuScreen/MenuScreenView.js +++ b/screens/MenuScreen/MenuScreenView.js @@ -1,7 +1,7 @@ import React, { useState, useEffect } from "react"; import { FlatList } from "react-native"; import MenuItem from "../../components/MenuItem/MenuItem"; -import CustomModal from "../../components/Modal/Modal"; +import CustomModal from "../../components/CustomModal/CustomModal"; import { searchByNameKey } from "@/screens/common/searchCriteria"; import styles from "@/screens/common/styles"; import CustomSearchBar from "@/screens/common/SearchBar"; @@ -10,11 +10,65 @@ import { ThemedText } from "@/components/common/ThemedText"; import { ThemedButton } from "@/components/common/ThemedButton"; const formSchema = [ - { name: "searchableKey", placeholder: "Key", keyboardType: "default" }, - { name: "name", placeholder: "Item Name", keyboardType: "default" }, - { name: "price", placeholder: "Price", keyboardType: "numeric" }, - { name: "cuisine", placeholder: "Cuisine", keyboardType: "default" }, - { name: "image", placeholder: "Image URL", keyboardType: "default" }, + { + name: "searchableKey", + placeholder: "Key", + inputMode: "default", + type: "text", + }, + { + name: "name", + placeholder: "Item Name", + inputMode: "default", + type: "text", + }, + { + name: "type", + placeholder: "Type", + inputMode: "default", + type: "dropdown", + options: ["Veg", "Non-Veg", "Vegan"], + }, + { + name: "isAvailable", + placeholder: "Is Available?", + inputMode: "default", + type: "radio", + options: ["Yes", "No"], + }, + { + name: "category", + placeholder: "Category", + inputMode: "default", + type: "dropdown", + options: [ + "Beverages", + "Burgers", + "EGG", + "Chicken", + "Chakhna", + "Chinese Snacks", + "Chinese Soups", + "Garlic Bread", + "Gravy Items", + "Hawaiian Wraps", + "Maggie Lover", + ], + }, + { name: "price", placeholder: "Price", inputMode: "numeric", type: "text" }, + { + name: "cuisine", + placeholder: "Cuisine", + inputMode: "default", + type: "dropdown", + options: ["Italian", "Chinese", "Indian"], + }, + { + name: "image", + placeholder: "Image URL", + inputMode: "default", + type: "text", + }, ]; const MenuScreenView = ({ @@ -95,14 +149,15 @@ const MenuScreenView = ({ /> )} /> - setModalVisible(false)} - onSave={handleSaveItem} - onDelete={handleDeleteItem} - item={currentItem} - schema={formSchema} - /> + {modalVisible && ( + setModalVisible(false)} + onSave={handleSaveItem} + onDelete={handleDeleteItem} + item={currentItem} + schema={formSchema} + /> + )} { @@ -91,15 +101,16 @@ const StaffScreenView = ({ staffs, addStaff, deleteStaff, updateStaff }) => { )} style={styles.itemList} /> - setModalVisible(false)} - onSave={handleSaveItem} - onDelete={handleDeleteItem} - item={currentItem} - schema={formSchema} - style={styles.container} - /> + {modalVisible && ( + setModalVisible(false)} + onSave={handleSaveItem} + onDelete={handleDeleteItem} + item={currentItem} + schema={formSchema} + style={styles.container} + /> + )}