Bladeren bron

Create ScaleTool component

Tatiana Inama 6 jaren geleden
bovenliggende
commit
e169f20e05

+ 114 - 0
recipes/src/components/Ingredient/ScaleTool/index.tsx

@@ -0,0 +1,114 @@
+import React, { useState } from 'react';
+
+import { SubRecipe } from 'src/types/recipes';
+import Button from 'components/Button';
+import Input from 'components/Input';
+
+import { FormatFloat } from 'services/measurements';
+import './styles.scss';
+
+enum MODE {
+  Predefined,
+  Custom
+}
+type Props = {
+  ingredients: SubRecipe[],
+};
+
+const ScaleTool: React.FunctionComponent<Props> = ({ ingredients }) => {
+  const [ mode, setMode ] = useState<MODE>(MODE.Predefined);
+  const [ multiplier, setMultiplier ] = useState<number>(1);
+  const [ stick, setStick ] = useState<{ value: number, key: string, multiplier: number, original: number }>({
+    original: 1,
+    value: 1,
+    key: '',
+    multiplier: 1,
+  });
+
+  const humanized = (value: number) => {
+    return value.toFixed(2);
+  }
+
+  const changeMultiplier = (multiplier: number) => {
+    if (mode === MODE.Custom) {
+      setMode(MODE.Predefined);
+    }
+    setMultiplier(multiplier)
+  }
+
+  const setStickMultiplier = (newValue: number) => {
+    setStick({
+      ...stick,
+      value: newValue,
+      multiplier: (newValue || 1) / stick.original
+    })
+  }
+
+  const setNewStick = (value: number, key: string) => {
+    setStick({
+      original: value,
+      multiplier: 1,
+      value,
+      key
+    })
+  }
+
+  return (
+    <div className="cbk-scale-tool">
+      <div className="cbk-scale-tool__actions">
+        <Button onClick={() => { changeMultiplier(2) }}>x 2</Button>
+        <Button onClick={() => { changeMultiplier(1) }}>x 1</Button>
+        <Button onClick={() => { changeMultiplier(0.5) }}>x 1/2</Button>
+        <Button onClick={() => { changeMultiplier(0.33) }} >x 1/3</Button>
+        <Button onClick={() => { changeMultiplier(0.25) }}>x 1/4</Button>
+        <Button onClick={() => { setMode(MODE.Custom) }}>with stick</Button>
+      </div>
+      <div className="cbk-scale-tool__ingredients">
+        {
+          ingredients.map((subrecipe, subrecipeKey) => (
+            <ul key={subrecipeKey}>
+              {
+                subrecipe.name ? (
+                  <li>{ subrecipe.name }</li>
+                ) : null
+              }
+              {
+                subrecipe.ingredients.map((ingredient, ingredientKey) => {
+                  const key = `${subrecipeKey}-${ingredientKey}`;
+                  return mode === MODE.Predefined ? (
+                    (
+                      <li key={key}>
+                        { FormatFloat(ingredient.quantity * multiplier) }{ ingredient.unit } { ingredient.name }
+                      </li>
+                    )
+                  ) : (
+                    (
+                      <li key={key}>
+                        <input type="radio" value={key} checked={stick.key === key} onChange={e => { setNewStick(ingredient.quantity, key)}}/>
+                        {
+                          stick.key === key ? (
+                            <span>
+                              <input min={1} value={stick.value} type='number' onChange={e => {setStickMultiplier(parseInt(e.currentTarget.value))}}/>
+                              {ingredient.unit} {ingredient.name}
+                            </span>
+                          ) : (
+                            <span>
+                              { FormatFloat(ingredient.quantity * stick.multiplier) }{ ingredient.unit } { ingredient.name }
+                            </span>
+                          )
+                        }
+                      </li>
+                    )
+                  )
+                })
+              }
+            </ul>
+          ))
+        }
+      </div>
+    </div>
+
+  )
+};
+
+export default ScaleTool;

+ 0 - 0
recipes/src/components/Ingredient/ScaleTool/styles.scss


+ 2 - 0
recipes/src/components/Ingredient/index.tsx

@@ -1,7 +1,9 @@
 import IngredientForm from './Form';
 import IngredientList from './List';
+import ScaleTool from './ScaleTool';
 
 export {
   IngredientForm as Form,
   IngredientList as List,
+  ScaleTool
 };

+ 5 - 57
recipes/src/components/RecipeCard/index.tsx

@@ -1,10 +1,8 @@
-import React, { Component } from 'react';
-import Recipe, { SubRecipe, Ingredient } from '../../types/recipes';
-import Card, {
-  CardMedia,
-} from "@material/react-card";
+import React from 'react';
+import Recipe from '../../types/recipes';
 import Icon from 'components/Icon';
 import { List as Ingredients } from 'components/Ingredient';
+import { ScaleTool } from 'components/Ingredient/'
 import StrikeText from 'components/StrikeText';
 import moment from 'moment';
 
@@ -74,7 +72,8 @@ const CBKRecipeCard: React.FunctionComponent<RecipeCardProps> = ({ recipe }) =>
       </div>
       <div className="cbk-recipe-card__content">
         <div className="cbk-recipe-card__content__ingredients">
-          <Ingredients ingredients={recipe.ingredients} />
+          <ScaleTool ingredients={recipe.ingredients}></ScaleTool>
+          {/* <Ingredients ingredients={recipe.ingredients} /> */}
         </div>
         <div className="cbk-recipe-card__content__instructions">
           <ol>
@@ -94,55 +93,4 @@ const CBKRecipeCard: React.FunctionComponent<RecipeCardProps> = ({ recipe }) =>
   );
 }
 
-function CBKRecipeCard2(props: RecipeCardProps) {
-  const { recipe } = props;
-  const prepTime = moment.duration(recipe.details.preparationTime).humanize();
-  const cookTime = moment.duration(recipe.details.cookingTime).humanize();
-  const servings = recipe.details.servings;
-
-
-  return (
-    <Card outlined className='cbk-recipe-card'>
-      <div className='cbk-recipe-card__primary'>
-        <CardMedia square imageUrl={recipe.image ? `${API}/${recipe.image}` : sample_img} className='cbk-recipe-card__primary__image'/>
-        <div className='cbk-recipe-card__primary__title'>
-          <h4>{recipe.name}</h4>
-          <p>{recipe.summary}</p>
-          <p>
-            <b>Author:</b> {recipe.author.name} {recipe.details.url && (<a href={recipe.details.url}>(website)</a>)}
-          </p>
-          <ul>
-            <li>
-              <Icon width={32} height={32} icon='preparation' />
-              <label>{prepTime}</label>
-            </li>
-            <li>
-              <Icon width={32} height={32} icon='cooking' />
-              <label>{cookTime}</label>
-            </li>
-            <li>
-              <Icon width={32} height={32} icon='servings' />
-              <label>{servings}</label>
-            </li>
-          </ul>
-        </div>
-      </div>
-      <div className='cbk-recipe-card__content'>
-        <div className='cbk-recipe-card__content__ingredients'>
-          <Ingredients ingredients={recipe.ingredients} />
-        </div>
-        <div className='cbk-recipe-card__content__instructions'>
-          <ol>
-            {
-              recipe.instructions.map((instruction, i) => (
-                <li key={i}>{instruction}</li>
-              ))
-            }            
-          </ol>
-        </div>
-      </div>
-    </Card>
-  )
-}
-
 export default CBKRecipeCard;

+ 7 - 0
recipes/src/services/measurements.ts

@@ -77,6 +77,12 @@ const ParseUnit = (unit: string): Measure => {
   return 'mass';
 }
 
+const FormatFloat = (n: number) => {
+  const _n = n.toFixed(2);
+  const [ integer, decimal ] = _n.split('.');
+  return decimal === '00' ? parseFloat(integer) : parseFloat(_n);
+}
+
 const MeasuresTypes = GetMeasuresTypes();
 
 export {
@@ -85,4 +91,5 @@ export {
   Convert,
   ParseUnit,
   GetMeasure,
+  FormatFloat
 };