diff --git a/api/app/Http/Controllers/RecipesController.php b/api/app/Http/Controllers/RecipesController.php new file mode 100644 index 0000000..c1eff13 --- /dev/null +++ b/api/app/Http/Controllers/RecipesController.php @@ -0,0 +1,32 @@ +recipesRepository = $recipesRepository; + } + + public function add(AddRecipeRequest $request) + { + $recipe = $this->recipesRepository->create(collect($request->all())); + + return response()->json(['success' => true, 'data' => ['recipe' => $recipe]], 200); + } + + public function index(Request $request) + { + $recipes = $this->recipesRepository->paginate($this->paginationSize); + + return response()->json(['success' => true, 'data' => ['recipes' => $recipes]], 200); + } +} diff --git a/api/app/Http/Requests/AddProductRequest.php b/api/app/Http/Requests/AddProductRequest.php index a58a7d4..650b094 100644 --- a/api/app/Http/Requests/AddProductRequest.php +++ b/api/app/Http/Requests/AddProductRequest.php @@ -25,6 +25,10 @@ class AddProductRequest extends FormRequest { return [ 'name' => 'required', + 'kcal' => 'required', + 'carbohydrates' => 'required', + 'protein' => 'required', + 'fat' => 'required', ]; } @@ -32,6 +36,10 @@ class AddProductRequest extends FormRequest { return [ 'name.required' => 'Product name is required', + 'kcal.required' => 'Kcal are required', + 'carbohydrates.required' => 'Carbohydrates are required', + 'protein.required' => 'Protein are required', + 'fat.required' => 'Fat is required', ]; } } diff --git a/api/app/Http/Requests/AddRecipeRequest.php b/api/app/Http/Requests/AddRecipeRequest.php new file mode 100644 index 0000000..833d661 --- /dev/null +++ b/api/app/Http/Requests/AddRecipeRequest.php @@ -0,0 +1,41 @@ + 'required', + 'steps' => 'required', + 'ingredients' => 'required', + ]; + } + + public function messages() + { + return [ + 'name.required' => 'Product name is required', + 'steps.required' => 'Recipe steps are required', + 'ingredients.required' => 'Recipe ingredients are required', + ]; + } +} diff --git a/api/app/Models/Recipe.php b/api/app/Models/Recipe.php new file mode 100644 index 0000000..fc17729 --- /dev/null +++ b/api/app/Models/Recipe.php @@ -0,0 +1,25 @@ +hasMany(RecipeStep::class); + } + + public function ingredients() + { + return $this->hasMany(RecipeProduct::class); + } +} diff --git a/api/app/Models/RecipeProduct.php b/api/app/Models/RecipeProduct.php new file mode 100644 index 0000000..632dc10 --- /dev/null +++ b/api/app/Models/RecipeProduct.php @@ -0,0 +1,32 @@ +belongsTo(Product::class); + } + +} diff --git a/api/app/Models/RecipeStep.php b/api/app/Models/RecipeStep.php new file mode 100644 index 0000000..563d7db --- /dev/null +++ b/api/app/Models/RecipeStep.php @@ -0,0 +1,14 @@ +app->bind(UsersRepositoryInterface::class, UsersRepository::class); $this->app->bind(ProductsRepositoryInterface::class, ProductsRepository::class); + $this->app->bind(RecipesRepositoryInterface::class, RecipesRepository::class); } } diff --git a/api/app/Repositories/RecipesRepository.php b/api/app/Repositories/RecipesRepository.php new file mode 100644 index 0000000..e9c361a --- /dev/null +++ b/api/app/Repositories/RecipesRepository.php @@ -0,0 +1,64 @@ +only(['name', 'description']); + $ingredients = $data->get('ingredients'); + $steps = $data->get('steps'); + + $recipe = Recipe::create($recipeData->toArray()); + + foreach ($ingredients as $ingredient) { + RecipeProduct::create([ + 'recipe_id' => $recipe['id'], + 'product_id' => $ingredient['id'], + 'weight' => $ingredient['weight'] + ]); + } + + foreach ($steps as $step) { + RecipeStep::create(['recipe_id' => $recipe['id'], 'step' => $step]); + } + return $this->get($recipe['id']); + }); + } + + public function get(int $id) + { + $rawRecipe = Recipe::where('id', $id)->first(); + $recipe = [ + 'name' => $rawRecipe['name'], + 'description' => $rawRecipe['description'], + 'ingredients' => $this->processIngredients($rawRecipe['ingredients']), + 'steps' => $rawRecipe['steps']->pluck('step') + ]; + + return $recipe; + } + + public function processIngredients(Collection $ingredients) + { + return $ingredients->map(function ($item) { + return collect(array_merge($item->toArray(), $item['product']->toArray()))->only(['name', 'weight']); + }); + } + + + public function paginate($chunkSize) + { + return Recipe::paginate($chunkSize); + } +} diff --git a/api/app/Repositories/RecipesRepositoryInterface.php b/api/app/Repositories/RecipesRepositoryInterface.php new file mode 100644 index 0000000..6cb1726 --- /dev/null +++ b/api/app/Repositories/RecipesRepositoryInterface.php @@ -0,0 +1,12 @@ +bigIncrements('id'); + $table->increments('id'); $table->string('email')->unique(); $table->string('password'); $table->integer('role')->default(UserRole::USER); diff --git a/api/database/migrations/2019_12_04_112630_create_products_table.php b/api/database/migrations/2019_12_04_112630_create_products_table.php index e5f28b6..9e2790b 100644 --- a/api/database/migrations/2019_12_04_112630_create_products_table.php +++ b/api/database/migrations/2019_12_04_112630_create_products_table.php @@ -14,12 +14,12 @@ class CreateProductsTable extends Migration public function up() { Schema::create('products', function (Blueprint $table) { - $table->bigIncrements('id'); + $table->increments('id'); $table->string('name')->unique(); - $table->integer('kcal')->nullable(); - $table->float('carbohydrates')->nullable(); - $table->float('protein')->nullable(); - $table->float('fat')->nullable(); + $table->integer('kcal')->unsigned(); + $table->float('carbohydrates'); + $table->float('protein'); + $table->float('fat'); $table->timestamps(); }); } diff --git a/api/database/migrations/2019_12_15_124537_create_recipes_table.php b/api/database/migrations/2019_12_15_124537_create_recipes_table.php new file mode 100644 index 0000000..154f797 --- /dev/null +++ b/api/database/migrations/2019_12_15_124537_create_recipes_table.php @@ -0,0 +1,33 @@ +increments('id'); + $table->string('name')->unique(); + $table->text('description')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('recipes'); + } +} diff --git a/api/database/migrations/2019_12_15_124912_create_recipe_products_table.php b/api/database/migrations/2019_12_15_124912_create_recipe_products_table.php new file mode 100644 index 0000000..0044d9c --- /dev/null +++ b/api/database/migrations/2019_12_15_124912_create_recipe_products_table.php @@ -0,0 +1,43 @@ +integer('recipe_id')->unsigned(); + $table->integer('product_id')->unsigned(); + $table->integer('weight')->unsigned(); + $table->foreign('recipe_id') + ->references('id') + ->on('recipes') + ->onUpdate('cascade') + ->onDelete('cascade'); + $table->foreign('product_id') + ->references('id') + ->on('products') + ->onUpdate('cascade') + ->onDelete('cascade'); + $table->primary(['recipe_id', 'product_id']); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('recipe_products'); + } +} diff --git a/api/database/migrations/2019_12_15_124929_create_recipe_steps_table.php b/api/database/migrations/2019_12_15_124929_create_recipe_steps_table.php new file mode 100644 index 0000000..dad5eef --- /dev/null +++ b/api/database/migrations/2019_12_15_124929_create_recipe_steps_table.php @@ -0,0 +1,37 @@ +increments('id'); + $table->integer('recipe_id')->unsigned(); + $table->string('step'); + $table->foreign('recipe_id') + ->references('id') + ->on('recipes') + ->onUpdate('cascade') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('recipe_steps'); + } +} diff --git a/api/routes/api.php b/api/routes/api.php index 6be8601..f900ea6 100644 --- a/api/routes/api.php +++ b/api/routes/api.php @@ -9,6 +9,11 @@ Route::group(['prefix' => 'user', 'middleware' => ['assign.guard:users']], funct }); Route::prefix('product')->group(function () { - Route::post('/', 'ProductsController@add')->middleware(['assign.guard:users']); + Route::post('/', 'ProductsController@add')->middleware(['jwt.auth']); Route::get('/', 'ProductsController@index'); }); + +Route::prefix('recipe')->group(function () { + Route::post('/', 'RecipesController@add')->middleware(['jwt.auth']); + Route::get('/', 'RecipesController@index'); +});