Преглед изворни кода

Edit recipes view and backend

Tatiana Inama пре 7 година
родитељ
комит
184fcdde21

+ 3 - 1
ktchn/src/mongo.ts

@@ -1,4 +1,4 @@
-import { Db, Cursor, MongoClient, InsertOneWriteOpResult, Collection, ObjectID, FilterQuery, ObjectId } from 'mongodb';
+import { Db, Cursor, MongoClient, InsertOneWriteOpResult, Collection, ObjectID, FilterQuery, ObjectId, UpdateWriteOpResult, WriteOpResult } from 'mongodb';
 
 export interface IDDocument {
   _id: ObjectID
@@ -12,6 +12,7 @@ export interface IMongoService {
   findOne<T>(query: FilterQuery<T>): Promise<IDBDocument<T>|null>,
   findOneById<T>(idParam: string): Promise<IDBDocument<T>|null>,
   find<T>(query: FilterQuery<T>, optionalQuery?: FilterQuery<T>): Promise<IDBDocument<T>[]>,
+  update<T>(id: string, data: T): Promise<WriteOpResult>
 }
 
 export const mongoService = (db: Db) => (col: string): IMongoService => {
@@ -23,6 +24,7 @@ export const mongoService = (db: Db) => (col: string): IMongoService => {
     findOne: <T>(query: FilterQuery<T>) => collection.findOne(query),
     findOneById: (idParam: string) => collection.findOne({ _id: new ObjectId(idParam) }),
     find: <T>(query: FilterQuery<T>, optionalQuery: FilterQuery<T> = {} ): Promise<IDBDocument<T>[]> => collection.find(query, optionalQuery).toArray(),
+    update: <T>(id: string, data: T) => collection.update({_id: new ObjectId(id)}, data)
   }
 };
 

+ 0 - 1
ktchn/src/promise-all-middleware.ts

@@ -13,7 +13,6 @@ const piddleware = (middlewares: IMiddleware[]) => (req: Request, res: Response,
   middlewares.reduce((middlewaresChain, currentMiddleware) => {
     return middlewaresChain.then(x => currentMiddleware(req, res, next))
   }, Promise.resolve([])).then(results => { // results would be ever necessary ?  
-    console.log("results", results)
     next();
   }).catch(error => next(error));
 }

+ 5 - 0
ktchn/src/recipes/controller.ts

@@ -90,6 +90,10 @@ const getByIngredients: Controller = (db) => ({ query }, res) => {
   )
 }
 
+const update: Controller = (db) => ({params, body}, res) => {
+  return db.update<Recipe>(params.id, body).then(result => res.json(result))
+}
+
 export {
   save,
   scrapeRecipe,
@@ -97,4 +101,5 @@ export {
   get,
   getAll,
   getByIngredients,
+  update,
 }

+ 2 - 1
ktchn/src/recipes/routes.ts

@@ -1,5 +1,5 @@
 import { Request, Response, Router, NextFunction } from "express";
-import { save, get, getById, getAll, getByIngredients, scrapeRecipe } from './controller';
+import { save, get, getById, getAll, getByIngredients, scrapeRecipe, update } from './controller';
 import MongoClient from 'mongodb';
 import { mongoService, IMongoService } from '../mongo';
 import piddleware, { chainP } from '../promise-all-middleware';
@@ -23,6 +23,7 @@ class RecipeRoutes {
     this.router.get("/id/:id", piddleware([getById(this.RecipeDB)]));
     this.router.post("/", piddleware([save(this.RecipeDB)]));
     this.router.post("/scrape", chainP([scrapeRecipe(this.IngredientDB)]));
+    this.router.put("/edit/:id", piddleware([update(this.RecipeDB)]));
   }
 
   private logData(req:Request, res:Response, next: NextFunction): void {

+ 64 - 0
recipes/src/containers/Recipes/Edit/index.tsx

@@ -0,0 +1,64 @@
+import React from 'react';
+import  Navbar from 'components/Navbar';
+import Input from 'components/Input';
+import RecipeForm from 'components/RecipeForm';
+
+import './styles.scss';
+
+import Recipe, { SubRecipe, Author, Details, _recipe, _subRecipe, _ingredient, Ingredient } from 'types/recipes';
+import { getRecipeById, saveRecipe } from '../services';
+import { RouteComponentProps } from 'react-router';
+
+interface EditRecipeProps extends RouteComponentProps<{id: string}> {
+
+};
+
+interface EdirRecipeState {
+  form: Recipe,
+};
+
+class EditRecipe extends React.Component<EditRecipeProps, EdirRecipeState> {
+  constructor(props: EditRecipeProps) {
+    super(props);
+    this.state = { 
+      form: {
+        ..._recipe,
+      }
+    }
+  }
+
+  componentDidMount = () => {
+    getRecipeById(this.props.match.params.id).then(recipe => this.setState({ form: recipe }))
+  }
+
+  saveRecipe = (recipe: Recipe) => {
+    saveRecipe(recipe)
+      .then(response => {
+        if (response.status === 200) {
+          this.props.history.push('/recipes')
+        } else {
+          alert(response.statusText)
+        }
+      })
+  }
+
+  render() {
+    const { form } = this.state; 
+    return (
+      <div>
+        <Navbar
+          title="Create a recipe"
+        />
+        
+        <div className="cbk-create-recipe">
+          <RecipeForm
+            initialValues={form}
+            onSubmit={(recipe) => this.saveRecipe(recipe)}
+          />
+        </div>
+      </div>
+    )
+  }
+}
+
+export default EditRecipe;

+ 0 - 0
recipes/src/containers/Recipes/Edit/styles.scss


+ 10 - 5
recipes/src/containers/Recipes/List/index.tsx

@@ -52,15 +52,20 @@ class RecipeList extends Component<RecipeListProps, {phoneDisplay: boolean}> {
     };
   }
 
-  handler(event: React.MouseEvent) {
-    console.log('click');
+  handleEditRecipe = (id = '') => (event: React.MouseEvent) => {
+    this.props.history.push('/recipes/edit/' + id)
+  }
+
+  handler = (event: React.MouseEvent) => {
+    console.log('click', event);
   }
 
   render() {
     const {data, selectedRecipe, selectRecipe} = this.props;
-    const actions = [{
+    
+    const actions = (id = '') => [{
       label: 'edit',
-      handler: this.handler,
+      handler: this.handleEditRecipe(id),
     }, {
       label: 'shopping',
       handler: this.handler
@@ -93,7 +98,7 @@ class RecipeList extends Component<RecipeListProps, {phoneDisplay: boolean}> {
                       title={recipe.name}
                       onClick={this.handleRecipeSelection(recipe)}
                       summary={recipe.summary}
-                      actions={actions}
+                      actions={actions(recipe._id)}
                     />
                   )
                 })

+ 2 - 1
recipes/src/containers/Recipes/View/index.tsx

@@ -1,6 +1,7 @@
 import React, { useState, useEffect } from 'react';
 import { getRecipeById } from './../services';
 import { RouteComponentProps } from 'react-router';
+import {dissoc} from 'ramda';
 
 import RecipeCard from 'components/RecipeCard';
 import Recipe, { _recipe } from 'types/recipes';
@@ -19,7 +20,7 @@ class ViewRecipe extends React.Component<ViewRecipeProps, {recipe: Recipe}> {
 
   componentDidMount() {
     getRecipeById(this.props.match.params.id).then(
-      recipe => this.setState({ recipe })
+      recipe => this.setState({ recipe: dissoc('_id', recipe) })
     );
   }
 

+ 3 - 2
recipes/src/route.config.tsx

@@ -3,6 +3,7 @@ import { Route } from 'react-router';
 import RecipesContainer from 'containers/Recipes';
 import CreateRecipe from 'containers/Recipes/Create';
 import ViewRecipe from 'containers/Recipes/View';
+import EditRecipe from 'containers/Recipes/Edit';
 
 const emptyRoute = (title: string) => (props: any) => {
   console.log(props);
@@ -21,8 +22,8 @@ const routes = [
       component: ViewRecipe
     },
     {
-      path: '/recipes/edit',
-      component: emptyRoute('edit recipe'),
+      path: '/recipes/edit/:id',
+      component: EditRecipe,
     }]
   }, {
     path: '/planner',