Browse Source

Add conversion dialog

Tatiana Inama 7 năm trước cách đây
mục cha
commit
123a7d6ea4

+ 1 - 0
package.json

@@ -11,6 +11,7 @@
   "dependencies": {
     "@material/react-button": "^0.11.0",
     "@material/react-card": "^0.11.0",
+    "@material/react-dialog": "^0.14.1",
     "@material/react-drawer": "^0.11.0",
     "@material/react-layout-grid": "^0.11.0",
     "@material/textfield": "^2.0.0",

+ 77 - 0
recipes/src/components/Dialog/index.tsx

@@ -0,0 +1,77 @@
+import React, { useState } from 'react';
+import Dialog, {
+  DialogContent,
+  DialogFooter,
+  DialogButton
+} from '@material/react-dialog';
+import { GetMeasure, Convert, Measure } from 'services/measurements';
+import Button from 'components/Button';
+
+import '@material/react-dialog/dist/dialog.min.css';
+import './styles.scss';
+
+type Data = {
+  unit: string,
+  quantity: number
+}
+
+interface DialogProps {
+  measure: Data,
+  onConvert: (result: Data) => void
+}
+
+const CBKDialog = ({measure, onConvert}: DialogProps) => {
+  const { name, values } = GetMeasure(measure.unit);
+  const [ isOpen, setOpen ] = useState(false);
+  const [ result, setResult ] = useState({...measure})
+  
+
+  const convert = (qty: number, from: string, to: string) => {
+    setResult({unit: to, quantity: Convert(qty, from, to, name as Measure)})
+  }
+  return (
+    <>
+      <Button
+        icon='compare_arrows'
+        type='button'
+        onClick={() => setOpen(true)}
+        disabled={measure.unit === ''}
+        className='cbk-convert__button'
+        title='convert unit'
+      ></Button>
+      <Dialog
+        onClose={(action) => {
+          console.log(action)
+          if (action === 'confirm') {
+            onConvert(result)
+          }
+          setOpen(false)
+        }}
+        open={isOpen}
+      >
+        <DialogContent className='cbk-convert__dialog'>
+          <p>Converting <b>{measure.quantity + ' ' + measure.unit}</b> to:</p>
+          <div className='cbk-convert__dialog__content'>
+            <select value={result.unit} onChange={(e) => {
+              convert(measure.quantity, measure.unit, e.target.value);
+            }}>
+              {
+                values.map(option => (
+                  <option key={option} value={option}>{option}</option>
+                ))
+              }
+            </select>
+              {`${result.quantity} ${result.unit}`} 
+          </div>
+
+        </DialogContent>
+        <DialogFooter>
+          <DialogButton action='dismiss' type='button'>cancel</DialogButton>
+          <DialogButton action='confirm' type='button'>ok</DialogButton>
+        </DialogFooter>
+      </Dialog>
+    </>
+  )
+}
+
+export default CBKDialog;

+ 14 - 0
recipes/src/components/Dialog/styles.scss

@@ -0,0 +1,14 @@
+@import 'styles/_variables.scss';
+
+.cbk-convert {
+  &__dialog {
+    &__content {
+      display: flex;
+      align-content: space-between;
+      select {
+        flex-basis: 50%;
+        margin-right: $spacing-small;
+      }
+    }
+  }
+}

+ 7 - 1
recipes/src/components/RecipeForm/index.tsx

@@ -7,6 +7,9 @@ import sample_image from 'sample.png';
 import { MeasuresTypes } from 'services/measurements';
 import { LightInput as Input } from 'components/Input';
 import Button from 'components/Button';
+import Dialog from 'components/Dialog';
+import { GetMeasure } from 'services/measurements';
+
 //@ts-ignore
 import { Field, FieldArray, FormikProps, ArrayHelpers, Formik } from 'formik';
 
@@ -95,6 +98,10 @@ const SubrecipeForm = (props: any) => {
                         </Cell>
                         <Cell columns={1}>
                           <Field name={`ingredients[${selectedTab}].ingredients[${index}].quantity`}/>
+                          <Dialog
+                            measure={{unit: ingredient.unit, quantity: ingredient.quantity}}
+                            onConvert={result => ingredientHelpers.replace(index, { ...ingredient, ...result })}
+                          />
                         </Cell>
                         <Cell columns={1}>
                           <Field component='select' name={`ingredients[${selectedTab}].ingredients[${index}].unit`}>
@@ -197,7 +204,6 @@ const RenderForm = ({
       </section>
   
       <h5>Ingredients</h5>
-      
       <section>
         <FieldArray
           name='ingredients'

+ 5 - 1
recipes/src/components/RecipeForm/styles.scss

@@ -118,6 +118,9 @@
 
       .ingredient-detail {
         align-items: end;
+        & > * {
+          display: flex;
+        }
       }
       input {
         line-height: 1rem;
@@ -148,7 +151,8 @@
       }
     }
   }
-  button.remove {
+  button.remove,
+  button.cbk-convert__button {
     align-self: center;
     --mdc-ripple-fg-size: 14px;
     --mdc-ripple-left: 5px;

+ 18 - 5
recipes/src/services/measurements.ts

@@ -1,6 +1,4 @@
-import convert from 'convert-units';
-
-type Measure = 'mass'|'volume';
+export type Measure = 'mass'|'volume';
 type UnitDic = {
   [unitName: string]: number
 }
@@ -24,13 +22,27 @@ const conversionTable: {
     tbsp: 14.78,
     tsp: 4.92,
     gal: 3785.41,
-    pt: 473.176,
+    pnt: 473.176,
   }
 }
 
+const conversionTableDic: { [measure: string]: string[] } = {
+  mass: ['mg', 'g', 'kg', 'lb', 'oz'],
+  volume: ['ml', 'l', 'cup', 'tbsp', 'tsp', 'gal', 'pnt']
+};
+
 const Convert = (qty: number, from: string, to: string, measure: Measure) => {
   const toAnchor = (unit: string, amount: number) => conversionTable[measure][unit] * amount;
-  return (qty * toAnchor(from, qty)) / toAnchor(to, 1);
+  return ((qty * toAnchor(from, qty)) / toAnchor(to, 1)).toFixed(2);
+}
+
+const GetMeasure = (unit: string): { name: string, values: string[]} => {
+  return ['mass', 'volume'].reduce((result, measure)=>{
+    return conversionTableDic[measure].includes(unit) ? {
+      name: measure,
+      values: conversionTableDic[measure]
+    } : result
+  }, {name: '', values: ['']});
 }
 
 const measurements = [
@@ -69,4 +81,5 @@ export {
   MeasuresTypes,
   Convert,
   ParseUnit,
+  GetMeasure,
 };

+ 1 - 0
recipes/src/styles/_ui.scss

@@ -23,6 +23,7 @@ $phone: "(max-width: 839px)";
     padding: 4px 0;
     border-bottom: 1px solid #ccc;
     background-color: transparent;
+    resize: vertical;
   }
 
   span {