| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617 |
- import React from 'react';
- import { assocPath, remove } from 'ramda';
- import Navbar from 'components/Navbar';
- import { Grid, Row, Cell } from '@material/react-layout-grid';
- import Btn from 'components/Button';
- import Input from 'components/Input';
- import TagInput from 'components/TagInput';
- import Select from 'components/Select';
- import { Form as IngredientForm } from 'components/Ingredient';
- import './styles.scss';
- import { scrapeRecipe } from './services';
- import sample_img from "../../sample.png";
- import Recipe, { SubRecipe, Author, Details, _recipe, _subRecipe, _ingredient, Ingredient, Suggestion } from 'types/recipes';
- type CreateRecipeProps = {
- };
- type CreateRecipeState = {
- form: Recipe,
- scrapeUrl: string,
- };
- type FormKeys = keyof Recipe | keyof SubRecipe | keyof Ingredient | keyof Author | keyof Details | number;
- const Suggestions = (suggestions: Suggestion[] = []) => (
- <div>
- {
- suggestions.map(suggestion => (
- <Btn>{suggestion.name}</Btn>
- ))
- }
- </div>
- )
- class CreateRecipe extends React.Component<CreateRecipeProps, CreateRecipeState> {
- constructor(props: any) {
- super(props);
- this.state = {
- form: {
- ..._recipe,
- ingredients: [
- {
- "name": "For the Chicken:",
- "ingredients": [
- {
- "name": "thin boneless skinless chicken breast",
- "quantity": 1.5,
- "unit": "pound",
- "_original": "1-1/2 lb of Thin Boneless Skinless Chicken Breast",
- "suggestions": []
- },
- {
- "name": "olive oil",
- "quantity": 2,
- "unit": "tablespoon",
- "_original": "2 Tbsp of Olive Oil",
- "suggestions": []
- },
- {
- "name": "juice of lime",
- "quantity": 1,
- "unit": "",
- "_original": "Juice of 1 Lime",
- "suggestions": []
- },
- {
- "name": "chili powder",
- "quantity": 0.5,
- "unit": "teaspoon",
- "_original": "1/2 tsp of Chili Powder",
- "suggestions": [
- {
- "_id": "5cf1397d72cd194524435041",
- "name": "cocoa powder",
- "variants": [
- "cocoa"
- ],
- "equivalence": 118,
- "referenceUnit": "cup",
- "prefferedUnit": "gr",
- "measure": 2
- },
- {
- "_id": "5cf1397d72cd19452443503c",
- "name": "icing sugar",
- "variants": [
- "confectioner sugar",
- "powdered sugar"
- ],
- "equivalence": 125,
- "referenceUnit": "cup",
- "prefferedUnit": "gr",
- "measure": 2
- }
- ]
- },
- {
- "name": "oregano",
- "quantity": 0.5,
- "unit": "teaspoon",
- "_original": "1/2 tsp of Oregano",
- "suggestions": []
- },
- {
- "name": "cumin",
- "quantity": 0.5,
- "unit": "teaspoon",
- "_original": "1/2 tsp of Cumin",
- "suggestions": []
- },
- {
- "name": "paprika",
- "quantity": 0.5,
- "unit": "teaspoon",
- "_original": "1/2 tsp of Paprika",
- "suggestions": []
- },
- {
- "name": "granulated garlic",
- "quantity": 0.5,
- "unit": "teaspoon",
- "_original": "1/2 tsp of Granulated Garlic",
- "suggestions": [
- {
- "_id": "5cf1397d72cd19452443503b",
- "name": "granulated sugar",
- "variants": [
- "sugar",
- "plain sugar"
- ],
- "equivalence": 200,
- "referenceUnit": "cup",
- "prefferedUnit": "gr",
- "measure": 2
- }
- ]
- },
- {
- "name": "salt, to taste",
- "quantity": 0,
- "unit": "",
- "_original": "Salt, to taste",
- "suggestions": []
- }
- ]
- },
- {
- "name": "For the Dressing:",
- "ingredients": [
- {
- "name": "plain greek yogurt",
- "quantity": 0.5,
- "unit": "cup",
- "_original": "1/2 cup of Plain Greek Yogurt",
- "suggestions": [
- {
- "_id": "5cf1397d72cd194524435040",
- "name": "yogurt",
- "variants": [
- "plain yogurt"
- ],
- "equivalence": 245,
- "referenceUnit": "cup",
- "prefferedUnit": "gr",
- "measure": 2
- },
- {
- "_id": "5cf1397d72cd19452443503b",
- "name": "granulated sugar",
- "variants": [
- "sugar",
- "plain sugar"
- ],
- "equivalence": 200,
- "referenceUnit": "cup",
- "prefferedUnit": "gr",
- "measure": 2
- },
- {
- "_id": "5cf1397d72cd194524435030",
- "name": "all purpose flour",
- "variants": [
- "plain flour",
- "all purpose flour",
- "regular flour",
- "flour"
- ],
- "equivalence": 125,
- "referenceUnit": "cup",
- "prefferedUnit": "gr",
- "translation": {
- "dutch": "patentbloem"
- },
- "measure": 2
- }
- ]
- },
- {
- "name": "fresh cilantro",
- "quantity": 1,
- "unit": "cup",
- "_original": "1 cup of Fresh Cilantro",
- "suggestions": []
- },
- {
- "name": "scallions, roughly chopped",
- "quantity": 2,
- "unit": "",
- "_original": "2 Scallions, roughly chopped",
- "suggestions": []
- },
- {
- "name": "juice of lime or more, according to taste",
- "quantity": 1,
- "unit": "",
- "_original": "Juice of 1 Lime or more, according to taste",
- "suggestions": []
- },
- {
- "name": "olive oil",
- "quantity": 1,
- "unit": "tablespoon",
- "_original": "1 Tbsp of Olive Oil",
- "suggestions": []
- },
- {
- "name": "salt, to taste",
- "quantity": 0,
- "unit": "",
- "_original": "Salt, to taste",
- "suggestions": []
- }
- ]
- },
- {
- "name": "For the rest of the salad:",
- "ingredients": [
- {
- "name": "fresh lettuce of your choice",
- "quantity": 0,
- "unit": "",
- "_original": "Fresh Lettuce of your choice",
- "suggestions": []
- },
- {
- "name": "bell peppers, halved and seeded",
- "quantity": 2,
- "unit": "",
- "_original": "2 Bell Peppers, halved and seeded",
- "suggestions": []
- },
- {
- "name": "scallions or red onion, sliced",
- "quantity": 0,
- "unit": "",
- "_original": "Scallions or REd Onion, sliced",
- "suggestions": []
- },
- {
- "name": "pico de gallo salsa",
- "quantity": 0.5,
- "unit": "cup",
- "_original": "1/2 cup of Pico De Gallo Salsa",
- "suggestions": []
- },
- {
- "name": "avocado, sliced",
- "quantity": 1,
- "unit": "",
- "_original": "1 Avocado, sliced",
- "suggestions": []
- }
- ]
- }
- ],
- },
- scrapeUrl: '',
- }
- }
- scrapeRecipe = () => {
- scrapeRecipe(this.state.scrapeUrl).then(recipe => {
- this.setState({
- form: {
- ...recipe,
- details: {
- url: this.state.scrapeUrl,
- ...recipe.details,
- }
- }
- })
- })
- }
- updateField = (key: FormKeys[]) => {
- return (e: any) => {
- const newValue = e.currentTarget.value;
- this.setState({
- form: assocPath(key, newValue, this.state.form)
- } as Pick<CreateRecipeState, keyof CreateRecipeState>)
- }
- }
- updateSubrecipeName = (subrecipe: number, newValue: string) => {
- this.setState({
- form: assocPath(['ingredients', subrecipe, 'name'], newValue, this.state.form),
- } as Pick<CreateRecipeState, keyof CreateRecipeState>)
- }
- updateIngredientUnit = (key: Array<string | number | symbol>, newValue: string) => {
- console.log('change', key, newValue)
- this.setState({
- form: assocPath(key, newValue, this.state.form)
- })
- }
- addIngredient = (subrecipe: number, last: number) => {
- return () => {
- const { ingredients } = this.state.form;
- if (ingredients[subrecipe].ingredients[last].name) {
- const newIngredients = ingredients[subrecipe].ingredients.concat([_ingredient]);
- this.setState({
- form: {
- ...this.state.form,
- ingredients: assocPath([subrecipe, 'ingredients'], newIngredients, this.state.form.ingredients)
- }
- })
- }
- }
- }
- removeIngredient = (subrecipe: number, index: number) => {
- return () => {
- const { ingredients } = this.state.form;
- this.setState({
- form: {
- ...this.state.form,
- ingredients: assocPath(
- [subrecipe, 'ingredients'],
- remove(index, 1, ingredients[subrecipe].ingredients),
- this.state.form.ingredients
- )
- }
- })
- }
- }
- addInstruction = () => {
- this.setState({
- form: {
- ...this.state.form,
- instructions: this.state.form.instructions.concat([''])
- }
- })
- }
- removeInstruction = (index: number) => {
- return () => {
- this.setState({
- form: {
- ...this.state.form,
- instructions: remove(index, 1, this.state.form.instructions)
- }
- })
- }
- }
- actionButton = (path: any[], index: number, AddFc: () => void, RemoveFc: () => void) => {
- const isLast = (xs: any[], i: number) => xs.length === i + 1;
- return isLast(path, index) ?
- {
- icon: 'add_circle_outline',
- onClick: AddFc
- } : {
- icon: 'remove_circle_outline',
- onClick: RemoveFc
- }
- }
- addSubrecipe = () => {
- this.setState({
- form: {
- ...this.state.form,
- ingredients: this.state.form.ingredients.concat([_subRecipe]),
- }
- })
- }
- removeSubrecipe = (index: number) => {
- this.setState({
- form: {
- ...this.state.form,
- ingredients: remove(index, 1, this.state.form.ingredients)
- }
- })
- }
-
- render() {
- const { form, scrapeUrl } = this.state;
- return (
- <div>
- <Navbar
- title="Create a recipe"
- >
- <Input
- label='scrape recipe'
- value={scrapeUrl}
- onChange={(e: any)=>{
- console.log('data', e.currentTarget.value);
- this.setState({scrapeUrl: e.currentTarget.value})}}
- button={{
- icon: 'format_shapes',
- onClick: this.scrapeRecipe
- }}
- />
- </Navbar>
-
- <div className="cbk-create-recipe">
- <Grid>
- <Row>
- <Cell columns={2}>
- <img src={sample_img} style={{ width: '100%' }}/>
- </Cell>
- <Cell columns={10}>
- <Input
- label='name'
- value={form.name}
- onChange={this.updateField(['name'])}
- style='display'
- />
- <Input
- label='summary'
- value={form.summary}
- onChange={this.updateField(['summary'])}
- textarea
- />
- </Cell>
- </Row>
-
- <h5>Author Information</h5>
- <section>
- <Row>
- <Cell columns={3}>
- <Input
- label='name'
- value={form.author.name}
- onChange={this.updateField(['author', 'name'])}
- />
- </Cell>
- <Cell columns={3}>
- <Input
- label='website'
- value={form.author.website}
- onChange={this.updateField(['author', 'website'])}
- />
- </Cell>
- </Row>
- </section>
- <h5>Recipe Information</h5>
- <section>
- <Row>
- <Cell columns={3}>
- <Input
- label='Preparation time'
- value={form.details.preparationTime}
- onChange={this.updateField(['details', 'preparationTime'])}
- icon='preparation'
- />
- </Cell>
- <Cell columns={3}>
- <Input
- label='Cooking time'
- value={form.details.cookingTime}
- onChange={this.updateField(['details', 'cookingTime'])}
- icon='cooking'
- />
- </Cell>
- <Cell columns={3}>
- <Input
- label='servings'
- value={form.details.servings}
- onChange={this.updateField(['details', 'servings'])}
- type='number'
- icon='servings'
- />
- </Cell>
- <Cell columns={3}>
- <Input
- label='recipe url'
- value={form.details.url || ''}
- onChange={this.updateField(['details', 'url'])}
- icon='recipe'
- />
- </Cell>
- <Cell columns={12}>
- <TagInput
- initialValues={form.tags}
- onNewTag={(tags) => { this.setState({
- form: {
- ...this.state.form,
- tags,
- }
- })}}
- />
- </Cell>
- </Row>
- </section>
- <h5>Ingredients</h5>
- <section>
- <IngredientForm
- components={form.ingredients}
- updateField={this.updateField}
- addSubrecipe={this.addSubrecipe}
- updateSubrecipeName={this.updateSubrecipeName}
- removeSubrecipe={this.removeSubrecipe}
- updateIngredientUnit={this.updateIngredientUnit}
- />
- {/* {
- form.ingredients.map((group, i) => (
- <div key={i}>
- <Row>
- <Cell columns={4}>
- <Input
- label='group name'
- value={group.name}
- onChange={this.updateField(['ingredients', i, 'name'])}
- button={this.actionButton(form.ingredients, i, this.addSubrecipe, this.removeSubrecipe(i))}
- />
- </Cell>
- </Row>
- <div>
- {
- group.ingredients.map((ingredient, j) => (
- <Row key={j}>
- <Cell columns={4}>
- <Input
- label="ingredient"
- value={ingredient.name}
- onChange={this.updateField(['ingredients', i, 'ingredients', j, 'name'])}
- />
- </Cell>
- <Cell columns={2}>
- <Input
- label="quantity"
- value={ingredient.quantity}
- onChange={this.updateField(['ingredients', i, 'ingredients', j, 'quantity'])}
- />
- </Cell>
- <Cell columns={2}>
- <Select
- label='unit'
- options={[
- {label: 'grams', value: 'gr'},
- {label: 'cups', value: 'cup'},
- {label: 'mililiters', value: 'ml'},
- ]}
- onChange={(x) => {console.log('selected', x)}}
- />
- </Cell>
- <Cell columns={4}>
- <Input
- label="original/notes"
- value={ingredient._original}
- onChange={this.updateField(['ingredients', i, 'ingredients', j, '_original'])}
- button={this.actionButton(form.ingredients[i].ingredients, j, this.addIngredient(i, j), this.removeIngredient(i, j))}
- />
- </Cell>
- <Cell columns={12}>
- { Suggestions(ingredient.suggestions) }
- </Cell>
- </Row>
- ))
- }
- </div>
-
- </div>
- ))
- } */}
- </section>
- <h5>Instructions</h5>
- <section>
- {
- form.instructions.map((instruction, i) => (
- <Row key={i}>
- <Cell columns={12}>
- <Input
- label={`Step ${i+1}`}
- value={instruction}
- onChange={this.updateField(['instructions', i])}
- button={this.actionButton(form.instructions, i, this.addInstruction, this.removeInstruction(i))}
- />
- </Cell>
- </Row>
- ))
- }
- </section>
- <Row>
- <Cell columns={12} className='cbk-create-recipe-actions'>
- <Btn raised unelevated>Create</Btn>
- </Cell>
- </Row>
- </Grid>
- </div>
- </div>
- )
- }
- }
- export default CreateRecipe;
|