Pārlūkot izejas kodu

Remove Material Input component from TagInput and fix styles

Tatiana Inama 6 gadi atpakaļ
vecāks
revīzija
fa8ab1067b

+ 20 - 0
recipes/src/components/Input/index.tsx

@@ -127,4 +127,24 @@ export const LightInput = (label?: string, type = 'text') => ({ field }: FieldPr
 	);
 };
 
+type NoFormikProps = {
+	[x: string]: any,
+	label?: string,
+	type?: 'input' | 'textarea',
+}
+export const LightInputNotFormk = ({label, type = 'input', ...props }: NoFormikProps) => {
+	const Tag = type;
+	return (
+		<div className="cbk-light-input">
+			{ label && (<label>{label}</label>)}
+			<Tag
+				className={props.value ? 'has-value': ''}
+				type={type}
+				{...props}
+			/>
+			<span></span>
+		</div>
+	)
+}
+
 export default Input;

+ 96 - 167
recipes/src/components/RecipeForm/index.tsx

@@ -9,9 +9,10 @@ import { LightInput as Input } from 'components/Input';
 import Button from 'components/Button';
 import Dialog from 'components/DialogConverter';
 import { GetMeasure } from 'services/measurements';
+import TagInput from 'components/TagInput';
 
 //@ts-ignore
-import { Field, FieldArray, FormikProps, ArrayHelpers, Formik, useField, Form, FieldAttributes } from 'formik';
+import { Field, FieldArray, FormikProps, ArrayHelpers, Formik, useField, Form, FieldAttributes, FieldArrayRenderProps } from 'formik';
 import TextField from '@material/react-text-field';
 
 type RecipeFormProps<T> = {
@@ -88,7 +89,7 @@ const SubrecipeForm = (props: any) => {
         </Row>
         <FieldArray
           name={`ingredients[${selectedTab}].ingredients`}
-          render={ (ingredientHelpers: any) => {
+          component={ (ingredientHelpers: any) => {
             return (
               <div>
                 {
@@ -177,94 +178,6 @@ const SubrecipeForm = (props: any) => {
   )
 }
 
-const RenderForm = ({
-  values,
-  handleChange,
-  handleSubmit
-}: FormikProps<Recipe|DBRecipe>) => {
-  return (
-    <Grid>
-      <form onSubmit={handleSubmit} className='cbk-recipe-form'>
-      <Row>
-        <Cell columns={2}>
-          <img src={sample_image} style={{ width: '100%' }}/>
-        </Cell>
-        <Cell columns={10}>
-          <Field name='name' render={Input('name')}/>
-  
-          <Field name='summary' render={Input('summary', 'textarea')}/>
-        </Cell>
-      </Row>
-      
-      <h5>Author Information</h5>
-      <section>
-        <Row>
-          <Cell columns={3}>
-            <Field name='author.name' render={Input('name')}/>
-          </Cell>
-          <Cell columns={3}>
-            <Field name='author.website' render={Input('website')}/>
-          </Cell>
-        </Row>
-      </section>
-  
-      <h5>Recipe Information</h5>
-      <section>
-        <Row>
-          <Cell columns={3}>
-            <Field name='details.preparationTime' render={Input('preparation time')}/>
-          </Cell>
-          <Cell columns={3}>
-            <Field name='details.cookingTime' render={Input('cooking time')}/>
-          </Cell>
-          <Cell columns={3}>
-            <Field name='details.servings' render={Input('servings', 'number')}/>
-          </Cell>
-          <Cell columns={3}>
-            <Field name='details.url' render={Input('recipe url')}/>
-          </Cell>
-        </Row>
-      </section>
-  
-      <h5>Ingredients</h5>
-      <section>
-        {/* <FieldArray
-          name='ingredients'
-          component={SubrecipeForm}
-        /> */}
-      </section>
-  
-      <h5>Instructions</h5>
-      <section>
-        <FieldArray
-          name='instructions'
-          render={({remove, push}:ArrayHelpers) => (
-            <div>
-              {
-                values.instructions.map((instruction: string, instructionIdx: number) => (
-                  <Row key={instructionIdx}>
-                    <Cell columns={11}>
-                      <Field name={`instructions[${instructionIdx}]`}/>
-                    </Cell>
-                    <Cell columns={1}>
-                      <Button icon='clear' onClick={() => remove(instructionIdx)} small></Button>
-                    </Cell>
-                  </Row>
-                ))
-              }
-              <Button type="button" onClick={() => push('')}>Add instruction</Button>
-            </div>
-          )}
-        />
-      </section>
-      <Button type='submit' raised unelevated>Submit</Button>
-      </form>
-    </Grid>
-    
-      
-  );
-}
-
 type FormikInputProps = {
   [x: string]: any,
   label?: string,
@@ -296,83 +209,99 @@ const RecipeForm = <T extends Recipe|DBRecipe>({ initialValues, onSubmit }: Reci
         console.log('submit', values)
       }}
     >
-      <Grid>
-      <Form className='cbk-recipe-form'>
-      <Row>
-        <Cell columns={2}>
-          <img src={sample_image} style={{ width: '100%' }}/>
-        </Cell>
-        <Cell columns={10}>
-          <Field name='name' render={Input('name')}/>
-  
-          <Field name='summary' render={Input('summary', 'textarea')}/>
-        </Cell>
-      </Row>
-      
-      <h5>Author Information</h5>
-      <section>
-        <Row>
-          <Cell columns={3}>
-            <Field name='author.name' render={Input('name')}/>
-          </Cell>
-          <Cell columns={3}>
-            <Field name='author.website' render={Input('website')}/>
-          </Cell>
-        </Row>
-      </section>
-  
-      <h5>Recipe Information</h5>
-      <section>
-        <Row>
-          <Cell columns={3}>
-            <Field name='details.preparationTime' render={Input('preparation time')}/>
-          </Cell>
-          <Cell columns={3}>
-            <Field name='details.cookingTime' render={Input('cooking time')}/>
-          </Cell>
-          <Cell columns={3}>
-            <Field name='details.servings' render={Input('servings', 'number')}/>
-          </Cell>
-          <Cell columns={3}>
-            <Field name='details.url' render={Input('recipe url')}/>
-          </Cell>
-        </Row>
-      </section>
-  
-      <h5>Ingredients</h5>
-      <section>
-        <FieldArray
-          name='ingredients'
-          component={SubrecipeForm}
-        />
-      </section>
-  
-      <h5>Instructions</h5>
-      {/* <section>
-        <FieldArray
-          name='instructions'
-          render={({remove, push}:ArrayHelpers) => (
-            <div>
-              {
-                values.instructions.map((instruction: string, instructionIdx: number) => (
-                  <Row key={instructionIdx}>
-                    <Cell columns={11}>
-                      <Field name={`instructions[${instructionIdx}]`}/>
-                    </Cell>
-                    <Cell columns={1}>
-                      <Button icon='clear' onClick={() => remove(instructionIdx)} small></Button>
-                    </Cell>
-                  </Row>
-                ))
-              }
-              <Button type="button" onClick={() => push('')}>Add instruction</Button>
-            </div>
-          )}
-        />
-      </section> */}
-      <Button type='submit' raised unelevated>Submit</Button>
-      </Form>
-    </Grid>
+      {
+        ({setFieldValue, submitForm}) => (
+          <Grid>
+            <Form className='cbk-recipe-form'>
+            <Row>
+              <Cell columns={2}>
+                <img src={sample_image} style={{ width: '100%' }}/>
+              </Cell>
+              <Cell columns={10}>
+                <Field name='name' component={Input('name')}/>
+        
+                <Field name='summary' component={Input('summary', 'textarea')}/>
+              </Cell>
+            </Row>
+            
+            <h5>Author Information</h5>
+            <section>
+              <Row>
+                <Cell columns={3}>
+                  <Field name='author.name' component={Input('name')}/>
+                </Cell>
+                <Cell columns={3}>
+                  <Field name='author.website' component={Input('website')}/>
+                </Cell>
+              </Row>
+            </section>
+        
+            <h5>Recipe Information</h5>
+            <section>
+              <Row>
+                <Cell columns={3}>
+                  <Field name='details.preparationTime' component={Input('preparation time')}/>
+                </Cell>
+                <Cell columns={3}>
+                  <Field name='details.cookingTime' component={Input('cooking time')}/>
+                </Cell>
+                <Cell columns={3}>
+                  <Field name='details.servings' component={Input('servings', 'number')}/>
+                </Cell>
+                <Cell columns={3}>
+                  <Field name='details.url' component={Input('recipe url')}/>
+                </Cell>
+              </Row>
+              <Row>
+                <Cell columns={12}>
+                  <div>
+                    <TagInput
+                      label='tags'
+                      onNewTag={(tags) => {
+                        setFieldValue('tags', tags)
+                      }}
+                    />
+                  </div>
+                </Cell>
+              </Row>
+            </section>
+        
+            <h5>Ingredients</h5>
+            <section>
+              {/* <FieldArray
+                name='ingredients'
+                render={SubrecipeForm}
+              /> */}
+            </section>
+        
+            <h5>Instructions</h5>
+            {/* <section>
+              <FieldArray
+                name='instructions'
+                component={({remove, push}:ArrayHelpers) => (
+                  <div>
+                    {
+                      values.instructions.map((instruction: string, instructionIdx: number) => (
+                        <Row key={instructionIdx}>
+                          <Cell columns={11}>
+                            <Field name={`instructions[${instructionIdx}]`}/>
+                          </Cell>
+                          <Cell columns={1}>
+                            <Button icon='clear' onClick={() => remove(instructionIdx)} small></Button>
+                          </Cell>
+                        </Row>
+                      ))
+                    }
+                    <Button type="button" onClick={() => push('')}>Add instruction</Button>
+                  </div>
+                )}
+              />
+            </section> */}
+            <Button type='button' raised unelevated onClick={() => submitForm()} >Submit</Button>
+            </Form>
+          </Grid>
+        )
+      }
     </Formik>
   </div>
   {/* <Formik

+ 24 - 24
recipes/src/components/TagInput/index.tsx

@@ -2,7 +2,8 @@
 import React, { Component } from 'react';
 import { ChipSet, Chip } from '@material/react-chips';
 import MaterialIcon from '@material/react-material-icon';
-import Input from 'components/Input';
+import Input, {LightInputNotFormk} from 'components/Input';
+import { uniq } from 'ramda';
 
 import './styles.scss';
 
@@ -18,7 +19,7 @@ type TagInputProps = {
 }
 
 type TagInputState = {
-  tags: Tag[],
+  tags: string[],
   newTag: string,
 }
 
@@ -26,54 +27,53 @@ class TagInput extends Component<TagInputProps, TagInputState> {
   
   constructor(props: TagInputProps) {
     super(props);
-    const tags = props.initialValues ? props.initialValues.map(this.mkTag) : [];
     this.state = {
-      tags: tags,
+      tags: props.initialValues || [],
       newTag: '',
     }
   }
   
-  mkTag = (tagLike: string): Tag => ({
-    label: tagLike,
-    id: tagLike.replace(/\s/g,''),
-  })
+  mkTagId = (tag: string) => tag.replace(/\s/g,'');
 
-  updateTags = (newTags: Tag[]) => {
+  updateTags = (newTags: string[]) => {
     this.setState({
       tags: newTags,
-      newTag: '',
+      newTag: ''
     });
-    this.props.onNewTag(newTags.map(t => t.label||''))
+    this.props.onNewTag(newTags);
   }
 
   handleKeyDown = (e: any) => {
     const label = e.target.value;
     if (!!label && e.key === 'Enter') {
-      this.updateTags(this.state.tags.concat([this.mkTag(label)]))
+      this.updateTags(uniq([...this.state.tags, label]));
     }
   }
 
   render() {
     return (
       <div className="cbk-tag-input">
-        <Input
+        <LightInputNotFormk
+          label={this.props.label}
           value={this.state.newTag}
-          label={this.props.label || 'Tags'}
-          onChange={(e) => this.setState({newTag: e.currentTarget.value})}
+          onChange={(e: any) => this.setState({newTag: e.currentTarget.value})}
           onKeyDown={this.handleKeyDown}
-          icon='waiter'
         />
         <ChipSet
           input
-          updateChips={this.updateTags}
+          updateChips={(chips) => this.updateTags(chips.map(chip => chip.label || ''))}
         >
-          {this.state.tags.map((tag: any) =>
-            <Chip
-              id={tag.id}
-              key={tag.id}
-              label={tag.label}
-              trailingIcon={<MaterialIcon icon='cancel' />}
-            />
+          {this.state.tags.map((tag) => {
+            const id = this.mkTagId(tag);
+            return (
+              <Chip
+                id={id}
+                key={id}
+                label={tag}
+                trailingIcon={<MaterialIcon icon='cancel' />}
+              />
+            )
+          }
           )}
         </ChipSet>
       </div>

+ 2 - 4
recipes/src/components/TagInput/styles.scss

@@ -3,11 +3,9 @@
 .cbk-tag-input {
   display: flex;
   flex-direction: row;
-  align-items: flex-end;
 
-  .mdc-text-field {
-    grid-column-end: span 3;
-    width: auto!important;
+  .cbk-light-input {
+    flex-basis: 25%;
   }
 
   .mdc-chip__text {