diff --git a/src/components/AddProductToMealDialog/FormModel/formInitialValues.js b/src/components/AddProductToMealDialog/FormModel/formInitialValues.js new file mode 100644 index 0000000..975f893 --- /dev/null +++ b/src/components/AddProductToMealDialog/FormModel/formInitialValues.js @@ -0,0 +1,14 @@ +import productFormModel from './productFormModel'; +const { + formField: { + quantity, + unit, + } +} = productFormModel; + +const formInitialValues = { + [quantity.name]: 1, + [unit.name]: 'portion', +}; + +export default formInitialValues diff --git a/src/components/AddProductToMealDialog/FormModel/productFormModel.js b/src/components/AddProductToMealDialog/FormModel/productFormModel.js new file mode 100644 index 0000000..424ca79 --- /dev/null +++ b/src/components/AddProductToMealDialog/FormModel/productFormModel.js @@ -0,0 +1,17 @@ +const productFormModel = { + formId: 'addProductsToMealForm', + formField: { + quantity: { + name: 'quantity', + label: 'Quantity*', + requiredErrorMsg: 'Quantity is required' + }, + unit: { + name: 'unit', + label: 'Unit*', + requiredErrorMsg: 'Unit is required' + }, + } +}; + +export default productFormModel diff --git a/src/components/AddProductToMealDialog/FormModel/validationSchema.js b/src/components/AddProductToMealDialog/FormModel/validationSchema.js new file mode 100644 index 0000000..79703ee --- /dev/null +++ b/src/components/AddProductToMealDialog/FormModel/validationSchema.js @@ -0,0 +1,15 @@ +import * as Yup from 'yup'; +import productFormModel from './productFormModel'; +const { + formField: { + unit, + quantity, + } +} = productFormModel; + +const validationSchema = + Yup.object().shape({ + [unit.name]: Yup.string().required(`${unit.requiredErrorMsg}`), + [quantity.name]: Yup.number().required(`${quantity.requiredErrorMsg}`), + }) +export default validationSchema diff --git a/src/components/AddProductToMealDialog/Forms/ProductDetailsForm/index.js b/src/components/AddProductToMealDialog/Forms/ProductDetailsForm/index.js new file mode 100644 index 0000000..70d7811 --- /dev/null +++ b/src/components/AddProductToMealDialog/Forms/ProductDetailsForm/index.js @@ -0,0 +1,111 @@ +import {Button, Dialog, DialogActions, Typography, FormControl, DialogContent, DialogTitle} from "@material-ui/core"; +import React from "react"; +import {Form, Formik} from "formik"; +import { useDispatch, useSelector } from 'react-redux'; +import { createStructuredSelector } from 'reselect' +import PropTypes from "prop-types"; +import SelectField from "components/SelectField"; +import InputField from "components/InputField"; +import formInitialValues from "../../FormModel/formInitialValues"; +import validationSchema from "../../FormModel/validationSchema"; +import productFormModel from "../../FormModel/productFormModel"; +import {createMealAction, addProductsToMealAction} from "pages/Home/actions"; +import { makeSelectMealId, makeSelectMealLabel } from 'pages/Home/selectors' +import {format} from "date-fns"; + +const stateSelector = createStructuredSelector({ + mealId: makeSelectMealId(), + mealLabel: makeSelectMealLabel() +}) + +const { formId, formField } = productFormModel; + +const ProductDetailsForm = ({ + isOpen, + handleClose, + id, + label, + unit, + servingCapacity, + macronutrients +}) => { + const dispatch = useDispatch() + const { mealId, mealLabel } = useSelector(stateSelector) + + const unitTypes = [ + { label: 'None', value: undefined }, + { label: 'portion', value: 'portion' }, + { label: unit, value: unit }, + ] + + const today = format(new Date(), "yyyy-MM-dd"); + + const onSubmit = (values, actions) => { + const products = [{ + ...values, + product: id, + }] + + if (mealId) { + dispatch(addProductsToMealAction({ id: mealId, products })) + } else { + dispatch(createMealAction({ date: today, label: mealLabel, products })) + } + + actions.setSubmitting(false); + handleClose(); + } + + return ( + + + {({ isSubmitting }) => ( +
+ {label} + + 1 portion = {servingCapacity}${unit} + + + + + + + + + + + +
+ )} +
+
+ ) +} + +ProductDetailsForm.propTypes = { + isOpen: PropTypes.bool.isRequired, + handleClose: PropTypes.func.isRequired, + id: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, + unit: PropTypes.string.isRequired, + servingCapacity: PropTypes.number.isRequired, + macronutrients: PropTypes.shape({ + salt: PropTypes.number.isRequired, + calories: PropTypes.number.isRequired, + fat: PropTypes.number.isRequired, + carbohydrates: PropTypes.number.isRequired, + protein: PropTypes.number.isRequired, + }).isRequired +} + +export default ProductDetailsForm diff --git a/src/components/AddProductToMealDialog/ProductItem.js b/src/components/AddProductToMealDialog/ProductItem.js index fac8ac1..06dcfe1 100644 --- a/src/components/AddProductToMealDialog/ProductItem.js +++ b/src/components/AddProductToMealDialog/ProductItem.js @@ -1,25 +1,55 @@ -import React from 'react'; +import React, { useState } from 'react'; import PropTypes from 'prop-types' -import {Checkbox, ListItem, ListItemSecondaryAction, ListItemText} from "@material-ui/core"; +import {Checkbox, ListItem, Typography, ListItemSecondaryAction, ListItemText} from "@material-ui/core"; import ProductLabel from 'components/ProductLabel' +import ProductDetailsForm from './Forms/ProductDetailsForm' const ProductItem = ({ id, verified, eco, label, unit, servingCapacity, macronutrients }) => { + const [isProductDetailsDialogOpen, setIsProductDetailsDialogOpen] = useState(false); + const { calories } = macronutrients + const handleOpenDialog = () => { + setIsProductDetailsDialogOpen(true) + } + + const handleCloseDialog = () => { + setIsProductDetailsDialogOpen(false) + } + return ( - - } - disableTypography - /> - - + + } + secondary={ + 1 portion = {Math.floor((servingCapacity / 100) * calories)}kcal + } + disableTypography /> - - + + + + + + ); }; ProductItem.propTypes = { + selected: PropTypes.bool.isRequired, id: PropTypes.string.isRequired, verified: PropTypes.bool.isRequired, eco: PropTypes.bool.isRequired, diff --git a/src/components/AddProductToMealDialog/index.js b/src/components/AddProductToMealDialog/index.js index 91d75c9..447241c 100644 --- a/src/components/AddProductToMealDialog/index.js +++ b/src/components/AddProductToMealDialog/index.js @@ -10,22 +10,26 @@ import { Dialog, List, } from '@material-ui/core'; -import {Add as AddIcon, Delete as DeleteIcon} from "@material-ui/icons"; +import { useDispatch } from 'react-redux' +import {Add as AddIcon} from "@material-ui/icons"; import SearchInput from 'components/SearchInput' import BarcodeScanner from 'components/BarcodeScanner' import { createStructuredSelector } from 'reselect' -import { makeSelectProducts, makeSelectProduct } from 'pages/Home/selectors' import { useSelector } from 'react-redux' +import { makeSelectProducts } from 'pages/Home/selectors' import ProductItem from './ProductItem' +import { setSelectedMealAction } from 'pages/Home/actions' const stateSelector = createStructuredSelector({ products: makeSelectProducts(), - product: makeSelectProduct(), }) -const AddProductToMealDialog = ({ mealLabel }) => { +const AddProductToMealDialog = ({ mealId, mealLabel }) => { const [isOpen, setIsOpen] = useState(false); - const { products, product } = useSelector(stateSelector) + const { products } = useSelector(stateSelector) + const dispatch = useDispatch() + + const selectMeal = () => dispatch(setSelectedMealAction({ label: mealLabel, id: mealId })) const handleClose = (event) => { event.stopPropagation(); @@ -35,8 +39,8 @@ const AddProductToMealDialog = ({ mealLabel }) => { const handleOpen = (event) => { event.stopPropagation(); setIsOpen(true) + selectMeal(); } - return ( event.stopPropagation()}> @@ -61,6 +65,7 @@ const AddProductToMealDialog = ({ mealLabel }) => { {products.map(({ id, verified, eco, salt, brand, servingCapacity, barcode, label, unit, calories, fat, carbohydrates, protein }) => ( { protein, }} /> - ))} + ))}