[CLEAR-42] adding recipes
This commit is contained in:
parent
a62b3b5868
commit
ef20883542
32
api/app/Http/Controllers/RecipesController.php
Normal file
32
api/app/Http/Controllers/RecipesController.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Requests\AddRecipeRequest;
|
||||||
|
use App\Repositories\RecipesRepositoryInterface;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class RecipesController extends Controller
|
||||||
|
{
|
||||||
|
private $recipesRepository;
|
||||||
|
private $paginationSize = 10;
|
||||||
|
|
||||||
|
public function __construct(RecipesRepositoryInterface $recipesRepository)
|
||||||
|
{
|
||||||
|
$this->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);
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,10 @@ class AddProductRequest extends FormRequest
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => 'required',
|
'name' => 'required',
|
||||||
|
'kcal' => 'required',
|
||||||
|
'carbohydrates' => 'required',
|
||||||
|
'protein' => 'required',
|
||||||
|
'fat' => 'required',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,6 +36,10 @@ class AddProductRequest extends FormRequest
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name.required' => 'Product name is required',
|
'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',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
41
api/app/Http/Requests/AddRecipeRequest.php
Normal file
41
api/app/Http/Requests/AddRecipeRequest.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class AddRecipeRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => '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',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
25
api/app/Models/Recipe.php
Normal file
25
api/app/Models/Recipe.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
use App\Models\Product;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Recipe extends Model
|
||||||
|
{
|
||||||
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
protected $with = ['steps', 'ingredients'];
|
||||||
|
|
||||||
|
protected $hidden = ['created_at', 'updated_at'];
|
||||||
|
|
||||||
|
public function steps()
|
||||||
|
{
|
||||||
|
return $this->hasMany(RecipeStep::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ingredients()
|
||||||
|
{
|
||||||
|
return $this->hasMany(RecipeProduct::class);
|
||||||
|
}
|
||||||
|
}
|
32
api/app/Models/RecipeProduct.php
Normal file
32
api/app/Models/RecipeProduct.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
use App\Models\Product;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use App\Traits\HasCompositeKey;
|
||||||
|
|
||||||
|
class RecipeProduct extends Model
|
||||||
|
{
|
||||||
|
use HasCompositeKey;
|
||||||
|
|
||||||
|
protected $primaryKey = ['recipe_id', 'product_id'];
|
||||||
|
|
||||||
|
protected $with = ['product'];
|
||||||
|
|
||||||
|
public $incrementing = false;
|
||||||
|
|
||||||
|
public $timestamps = false;
|
||||||
|
|
||||||
|
protected $table = 'recipe_products';
|
||||||
|
|
||||||
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
protected $hidden = ['recipe_id', 'product_id'];
|
||||||
|
|
||||||
|
public function product()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Product::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
api/app/Models/RecipeStep.php
Normal file
14
api/app/Models/RecipeStep.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class RecipeStep extends Model
|
||||||
|
{
|
||||||
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
protected $hidden = ['recipe_id'];
|
||||||
|
|
||||||
|
public $timestamps = false;
|
||||||
|
}
|
@ -24,6 +24,5 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
*/
|
*/
|
||||||
public function boot()
|
public function boot()
|
||||||
{
|
{
|
||||||
Schema::defaultStringLength(191);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ namespace App\Providers;
|
|||||||
|
|
||||||
use App\Repositories\ProductsRepository;
|
use App\Repositories\ProductsRepository;
|
||||||
use App\Repositories\ProductsRepositoryInterface;
|
use App\Repositories\ProductsRepositoryInterface;
|
||||||
|
use App\Repositories\RecipesRepository;
|
||||||
|
use App\Repositories\RecipesRepositoryInterface;
|
||||||
use App\Repositories\UsersRepository;
|
use App\Repositories\UsersRepository;
|
||||||
use App\Repositories\UsersRepositoryInterface;
|
use App\Repositories\UsersRepositoryInterface;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
@ -29,5 +31,6 @@ class RepositoriesServiceProvider extends ServiceProvider
|
|||||||
{
|
{
|
||||||
$this->app->bind(UsersRepositoryInterface::class, UsersRepository::class);
|
$this->app->bind(UsersRepositoryInterface::class, UsersRepository::class);
|
||||||
$this->app->bind(ProductsRepositoryInterface::class, ProductsRepository::class);
|
$this->app->bind(ProductsRepositoryInterface::class, ProductsRepository::class);
|
||||||
|
$this->app->bind(RecipesRepositoryInterface::class, RecipesRepository::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
64
api/app/Repositories/RecipesRepository.php
Normal file
64
api/app/Repositories/RecipesRepository.php
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
|
||||||
|
use App\Recipe;
|
||||||
|
use App\RecipeProduct;
|
||||||
|
use App\RecipeStep;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class RecipesRepository implements RecipesRepositoryInterface
|
||||||
|
{
|
||||||
|
public function create(Collection $data)
|
||||||
|
{
|
||||||
|
return DB::transaction(function () use ($data) {
|
||||||
|
$recipeData = $data->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);
|
||||||
|
}
|
||||||
|
}
|
12
api/app/Repositories/RecipesRepositoryInterface.php
Normal file
12
api/app/Repositories/RecipesRepositoryInterface.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
interface RecipesRepositoryInterface
|
||||||
|
{
|
||||||
|
public function create(Collection $data);
|
||||||
|
public function paginate(int $chunkSize);
|
||||||
|
}
|
@ -15,7 +15,7 @@ class CreateUsersTable extends Migration
|
|||||||
public function up()
|
public function up()
|
||||||
{
|
{
|
||||||
Schema::create('users', function (Blueprint $table) {
|
Schema::create('users', function (Blueprint $table) {
|
||||||
$table->bigIncrements('id');
|
$table->increments('id');
|
||||||
$table->string('email')->unique();
|
$table->string('email')->unique();
|
||||||
$table->string('password');
|
$table->string('password');
|
||||||
$table->integer('role')->default(UserRole::USER);
|
$table->integer('role')->default(UserRole::USER);
|
||||||
|
@ -14,12 +14,12 @@ class CreateProductsTable extends Migration
|
|||||||
public function up()
|
public function up()
|
||||||
{
|
{
|
||||||
Schema::create('products', function (Blueprint $table) {
|
Schema::create('products', function (Blueprint $table) {
|
||||||
$table->bigIncrements('id');
|
$table->increments('id');
|
||||||
$table->string('name')->unique();
|
$table->string('name')->unique();
|
||||||
$table->integer('kcal')->nullable();
|
$table->integer('kcal')->unsigned();
|
||||||
$table->float('carbohydrates')->nullable();
|
$table->float('carbohydrates');
|
||||||
$table->float('protein')->nullable();
|
$table->float('protein');
|
||||||
$table->float('fat')->nullable();
|
$table->float('fat');
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class CreateRecipesTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('recipes', function (Blueprint $table) {
|
||||||
|
$table->increments('id');
|
||||||
|
$table->string('name')->unique();
|
||||||
|
$table->text('description')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('recipes');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class CreateRecipeProductsTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('recipe_products', function (Blueprint $table) {
|
||||||
|
$table->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');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class CreateRecipeStepsTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('recipe_steps', function (Blueprint $table) {
|
||||||
|
$table->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');
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,11 @@ Route::group(['prefix' => 'user', 'middleware' => ['assign.guard:users']], funct
|
|||||||
});
|
});
|
||||||
|
|
||||||
Route::prefix('product')->group(function () {
|
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::get('/', 'ProductsController@index');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Route::prefix('recipe')->group(function () {
|
||||||
|
Route::post('/', 'RecipesController@add')->middleware(['jwt.auth']);
|
||||||
|
Route::get('/', 'RecipesController@index');
|
||||||
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user