Kaynağa Gözat

Work in Card Component

Tati 7 yıl önce
ebeveyn
işleme
16cba2cb3b

+ 8 - 10
recipes/src/App.tsx

@@ -46,16 +46,14 @@ class App extends Component<{}, {}> {
               ))
             }
           </CBKDrawer>
-          <Grid className="cbk-grid">
-            <Row>
-              <Route path="/recipes" component={Recipes}>
-              </Route>
-              <Route path="/planner">
-              </Route>
-              <Route path="/planner">
-              </Route>
-            </Row>
-          </Grid>
+          <div className="cbk-main">
+            <Route path="/recipes" component={Recipes}>
+            </Route>
+            <Route path="/planner">
+            </Route>
+            <Route path="/planner">
+            </Route>
+          </div>
         </Router>
       </Provider>
     )

+ 40 - 17
recipes/src/components/Card/index.tsx

@@ -11,35 +11,58 @@ import Button from "@material/react-button";
 import '@material/react-card/dist/card.min.css';
 import '@material/react-button/dist/button.min.css';
 import './styles.scss';
-import { ReactNodeArray } from 'react';
 import sample_img from "./sample.png";
-
-type fc = (recipe: any) => undefined;
+import IRecipe from 'types/recipes';
+import { ReactNodeArray } from 'react';
 
 type CBKCardProps = {
-  children?: ReactNodeArray,
+  withImg?: boolean,
+  withActions?: boolean,
   title: string,
+  summary?: string,
   img?: string,
+  actions?: {
+    label: string,
+    handler: (event: React.MouseEvent) => void,
+  }[],
   recipe?: any,
-  onClick: fc,
+  onClick: (event: React.MouseEvent) => void,
 }
   
-function _Card(props: CBKCardProps){
+function CBKCard(props: CBKCardProps){
+  const {onClick, img, title, summary, actions} = props;
   return(
     <Card outlined className='cbk-card'>
-      <CardMedia imageUrl={props.img || sample_img}></CardMedia>
-      <CardPrimaryContent onClick={props.onClick}>
-        <h6>{props.title}</h6>
+      <CardPrimaryContent onClick={onClick}>
+        <CardMedia square imageUrl={props.img || sample_img}></CardMedia>
+        <div className='cbk-card__main'>
+          <h6 className='cbk-card__main__title'>{props.title}</h6>
+          {
+            summary ? 
+              <div className='cbk-card__main__summary'>{summary}</div> :
+              null
+          }
+        </div>
       </CardPrimaryContent>
-      <CardActions>
-        <CardActionButtons>
-          <Button>Edit</Button>
-          <Button>shopping</Button>
-          <Button>delete</Button>
-        </CardActionButtons>
-      </CardActions>
+      {
+        actions ?
+        (
+          <CardActions>
+            <CardActionButtons>
+              {
+                actions.map(({label, handler}, i) => (
+                  <Button key={i} onClick={handler}>
+                    {label}
+                  </Button>
+                )) 
+              }
+            </CardActionButtons>
+          </CardActions>
+        ) :
+        null
+      }
     </Card>
   )
 }
 
-export default _Card;
+export default CBKCard;

+ 22 - 2
recipes/src/components/Card/styles.scss

@@ -1,5 +1,7 @@
+@import 'styles/_variables.scss';
+
 .cbk-card {
-  flex-direction: row;
+  //flex-direction: row;
   border-radius: 0px;
   border: 0px;
   margin: 8px 0;
@@ -7,7 +9,25 @@
     width: 168px;
   }
   .mdc-card__primary-action {
-    padding: 8px;
+    flex-direction: row;
     width: 100%;
   }
+  &__main {
+    width: 100%;
+    padding: $spacing-small;
+    &__title {
+      margin: inherit;
+    }
+    &__summary {
+      font-size: $font-size-small;
+      color: $grey-500;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      display: -webkit-box;
+      line-height: 16px;
+      max-height: 48px; 
+      -webkit-line-clamp: 2;
+      -webkit-box-orient: vertical;
+    }
+  }
 }

+ 54 - 23
recipes/src/containers/recipes.tsx

@@ -7,13 +7,14 @@ import {
 import { connect } from "react-redux";
 import { Grid, Row, Cell } from "@material/react-layout-grid";
 import Card from 'components/Card';
+import IRecipe from 'types/recipes';
 
 type RecipesContainerProps = {
-  data: [],
+  data: IRecipe[],
   isFetching: boolean,
-  selectedRecipe: {} | undefined,
+  selectedRecipe: any | undefined,
   fetchRecipes: (query: any) => undefined,
-  receiveRecipes: (recipes: []) => undefined,
+  receiveRecipes: (recipes: IRecipe[]) => undefined,
   selectRecipe: (recipe: any) => undefined,
 };
 
@@ -29,31 +30,61 @@ class Recipes extends Component<RecipesContainerProps> {
 
   componentDidUpdate(prevProps: any) {
     const { data, receiveRecipes, isFetching } = this.props;
-
+    console.log('update');
     if (isFetching === false && data.length !== prevProps.data.length) {
       receiveRecipes(data);
     }
   }
 
+  handleRecipeSelection(recipe: any) {
+    return (event: React.MouseEvent) => this.props.selectRecipe(recipe);
+  }
+
+  handler(event: React.MouseEvent) {
+    console.log('click');
+  }
+
   render() {
+    const {data, selectedRecipe, selectRecipe} = this.props;
+    const actions = [{
+      label: 'edit',
+      handler: this.handler,
+    }, {
+      label: 'shopping',
+      handler: this.handler
+    }];
+
     return(
-      <Cell columns={6}>
-        {
-          this.props.data.map((recipe: any, i: number) => {
-            return (
-              <Row key={i}>
-                <Cell columns={10}>
-                  <Card
-                    title={recipe.name}
-                    recipe={recipe}
-                    onClick={() => this.props.selectRecipe(recipe)}
-                  />
-                </Cell>
-              </Row>
-            )
-          })
-        }
-      </Cell>
+      <Grid>
+        <Row>
+          <Cell columns={6}>
+            {
+              data.map((recipe: any, i: number) => {
+                return (
+                  <Row key={i}>
+                    <Cell columns={10}>
+                      <Card
+                        title={recipe.name}
+                        recipe={recipe}
+                        onClick={this.handleRecipeSelection(recipe)}
+                        summary={recipe.summary}
+                        actions={actions}
+                      />
+                    </Cell>
+                  </Row>
+                )
+              })
+            }
+          </Cell>
+          <Cell columns={6}>
+            { selectedRecipe !== undefined && 
+              <section>
+                <h3>{selectedRecipe.name}</h3>
+              </section>
+            }
+          </Cell>
+        </Row>
+      </Grid>
     )
   }
 }
@@ -67,10 +98,10 @@ const mapDispatchToProps = (dispatch: any) => {
     fetchRecipes: (query: any) => {
       dispatch(fetch(query))
     },
-    receiveRecipes: (recipes: []) => {
+    receiveRecipes: (recipes: IRecipe[]) => {
       dispatch(receive(recipes))
     },
-    selectRecipe: (recipe: any) => {
+    selectRecipe: (recipe: IRecipe) => {
       dispatch(select(recipe))
     }
   }

+ 4 - 3
recipes/src/store/recipes/actions.ts

@@ -1,5 +1,6 @@
 // import { Dispatch } from "react";
 import axios from 'axios';
+import IRecipe from 'types/recipes';
 
 export const RECEIVE_RECIPES = 'RECEIVE_RECIPES';
 export const REQUEST_RECIPES = 'REQUEST_RECIPES';
@@ -10,13 +11,13 @@ export const requestRecipes = (query: {}) => ({
   isFetching: true,
 });
 
-export const receiveRecipes = (json: []) => ({
+export const receiveRecipes = (json: IRecipe[]) => ({
   type: RECEIVE_RECIPES,
   isFetching: false,
   payload: json,
 });
 
-export const selectRecipe = (recipe: any) => ({
+export const selectRecipe = (recipe: IRecipe) => ({
   type: SELECT_RECIPE,
   payload: recipe,
 });
@@ -36,7 +37,7 @@ export function fetchRecipes(query: any) {
   }
 }
 
-function shouldFetch(recipes: []) {
+function shouldFetch(recipes: IRecipe[]) {
   return recipes.length ? false : true;
 }
 

+ 8 - 4
recipes/src/styles/app.scss

@@ -41,11 +41,15 @@ code {
   height: 100vh;
 }
 
-.cbk-grid {
-  display: flex;
+.cbk-main {
   width: 100%;
-
-  .mdc-layout-grid__inner {
+  .mdc-layout-grid {
+    display: flex;
     width: 100%;
+    
+    .mdc-layout-grid__inner {
+      width: 100%;
+    }
   }
+
 }

+ 24 - 0
recipes/src/types/recipes.ts

@@ -0,0 +1,24 @@
+export default interface IRecipe {
+  _id: string,
+  author: {
+    name: string,
+  },
+  details: {
+    preparationTime: string,
+    cookingTime: string,
+    servings: number
+  },
+  ingredients: {
+    name: string,
+    ingredients: {
+      name: string,
+      quantity: number,
+      unit: string,
+      _original: string,
+    }[]
+  }[],
+  instructions: string[],
+  name: string,
+  summary: string,
+  tags: string[],
+}