feat: meal post ingredients

This commit is contained in:
2026-05-18 14:39:57 +02:00
parent 7916e7f718
commit 7a907f2b17
12 changed files with 404 additions and 10 deletions
+42 -7
View File
@@ -13,6 +13,7 @@ use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Http\Response;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
class MealPostController extends Controller
{
@@ -66,12 +67,26 @@ class MealPostController extends Controller
public function store(MealPostsRequest $request): JsonResponse
{
$mealPost = MealPosts::create([
...$this->getValidatedDataWithImageUrl($request),
'user_id' => $request->user()->getKey(),
]);
$data = $this->getValidatedDataWithImageUrl($request);
$ingredients = $data['ingredients'] ?? [];
unset($data['ingredients']);
$mealPost = DB::transaction(function () use ($data, $ingredients, $request): MealPosts {
$mealPost = MealPosts::create([
...$data,
'user_id' => $request->user()->getKey(),
]);
if ($ingredients !== []) {
$mealPost->ingredients()->createMany($ingredients);
}
return $mealPost;
});
$mealPost->setRelation('user', $request->user());
$mealPost->loadMissing('ingredients');
return (new MealPostsResource($mealPost))
->response()
@@ -82,16 +97,36 @@ class MealPostController extends Controller
{
$this->abortIfNotOwner($request, $mealPost);
return new MealPostsResource($mealPost->loadMissing('user:id,name,avatar_url'));
return new MealPostsResource($mealPost->loadMissing('user:id,name,avatar_url', 'ingredients'));
}
public function update(MealPostsRequest $request, MealPosts $mealPost): MealPostsResource
{
$this->abortIfNotOwner($request, $mealPost);
$mealPost->update($this->getValidatedDataWithImageUrl($request));
$data = $this->getValidatedDataWithImageUrl($request);
$shouldSyncIngredients = array_key_exists('ingredients', $data);
$ingredients = $data['ingredients'] ?? [];
return new MealPostsResource($mealPost->refresh()->loadMissing('user:id,name,avatar_url'));
unset($data['ingredients']);
$mealPost = DB::transaction(function () use ($data, $ingredients, $mealPost, $shouldSyncIngredients): MealPosts {
if ($data !== []) {
$mealPost->update($data);
}
if ($shouldSyncIngredients) {
$mealPost->ingredients()->delete();
if ($ingredients !== []) {
$mealPost->ingredients()->createMany($ingredients);
}
}
return $mealPost->refresh();
});
return new MealPostsResource($mealPost->loadMissing('user:id,name,avatar_url', 'ingredients'));
}
public function destroy(Request $request, MealPosts $mealPost): Response
@@ -0,0 +1,25 @@
<?php
namespace App\Http\Requests;
use App\Enums\IngredientUnit;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class MealPostIngredientsRequest extends FormRequest
{
public function rules(): array
{
return [
'meal_posts_id' => ['required', 'exists:meal_posts,id'],
'position' => ['required', 'integer'],
'ingredient' => ['required', 'string'],
'unit' => ['required', Rule::enum(IngredientUnit::class)],
];
}
public function authorize(): bool
{
return true;
}
}
+6
View File
@@ -2,6 +2,7 @@
namespace App\Http\Requests;
use App\Enums\IngredientUnit;
use App\Enums\MealPostType;
use App\Enums\MealPostVisibility;
use Illuminate\Foundation\Http\FormRequest;
@@ -25,6 +26,11 @@ class MealPostsRequest extends FormRequest
'eaten_at' => [$isCreating ? 'required' : 'sometimes', 'date'],
'type' => [$isCreating ? 'required' : 'sometimes', Rule::enum(MealPostType::class)],
'visibility' => ['sometimes', Rule::enum(MealPostVisibility::class)],
'ingredients' => ['sometimes', 'array'],
'ingredients.*' => ['required', 'array:position,ingredient,unit'],
'ingredients.*.position' => ['required', 'integer', 'min:0'],
'ingredients.*.ingredient' => ['required', 'string', 'max:255'],
'ingredients.*.unit' => ['required', Rule::enum(IngredientUnit::class)],
];
}
@@ -0,0 +1,27 @@
<?php
namespace App\Http\Resources;
use App\Models\MealPostIngredients;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
/** @mixin MealPostIngredients */
class MealPostIngredientsResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'position' => $this->position,
'ingredient' => $this->ingredient,
'unit' => $this->unit,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'meal_posts_id' => $this->meal_posts_id,
'mealPosts' => new MealPostsResource($this->whenLoaded('mealPosts')),
];
}
}
+1
View File
@@ -29,6 +29,7 @@ class MealPostsResource extends JsonResource
'eatenAt' => $this->eaten_at,
'createdAt' => $this->created_at,
'updatedAt' => $this->updated_at,
'ingredients' => MealPostIngredientsResource::collection($this->whenLoaded('ingredients')),
'user' => [
'name' => $user?->name,