feat: calendar
Laravel CI-CD / Tests Unitaires (push) Successful in 19s Details
Laravel CI-CD / Build & Push Docker (push) Successful in 41s Details
Laravel CI-CD / Deploy via Portainer (push) Successful in 2s Details

This commit is contained in:
Leon Morival 2026-05-18 16:32:28 +02:00
parent fe78c000f0
commit 5a81c27665
4 changed files with 112 additions and 0 deletions

View File

@ -2,6 +2,7 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Http\Requests\MealPostCalendarRequest;
use App\Http\Requests\MealPostsRequest; use App\Http\Requests\MealPostsRequest;
use App\Http\Requests\MealPostStatsRequest; use App\Http\Requests\MealPostStatsRequest;
use App\Http\Resources\MealPostsResource; use App\Http\Resources\MealPostsResource;
@ -65,6 +66,36 @@ class MealPostController extends Controller
]); ]);
} }
public function calendar(MealPostCalendarRequest $request): JsonResponse
{
$month = $request->validated('month') ?? now()->format('Y-m');
$referenceDate = CarbonImmutable::createFromFormat('!Y-m', $month);
$startDate = $referenceDate->startOfMonth();
$endDate = $referenceDate->endOfMonth();
$days = MealPosts::query()
->where('user_id', $request->user()->getKey())
->whereBetween('eaten_at', [$startDate->startOfDay(), $endDate->endOfDay()])
->selectRaw('DATE(eaten_at) as date, COUNT(*) as meals_count')
->groupByRaw('DATE(eaten_at)')
->orderBy('date')
->get()
->map(fn (MealPosts $mealPost): array => [
'date' => CarbonImmutable::parse((string) $mealPost->date)->toDateString(),
'mealsCount' => (int) $mealPost->meals_count,
])
->values();
return response()->json([
'data' => [
'month' => $referenceDate->format('Y-m'),
'startDate' => $startDate->toDateString(),
'endDate' => $endDate->toDateString(),
'days' => $days,
],
]);
}
public function store(MealPostsRequest $request): JsonResponse public function store(MealPostsRequest $request): JsonResponse
{ {
$data = $this->getValidatedDataWithImageUrl($request); $data = $this->getValidatedDataWithImageUrl($request);

View File

@ -0,0 +1,27 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class MealPostCalendarRequest extends FormRequest
{
public function rules(): array
{
return [
'month' => ['sometimes', 'date_format:Y-m'],
];
}
public function authorize(): bool
{
return true;
}
public function messages(): array
{
return [
'month.date_format' => 'Choisis un mois valide.',
];
}
}

View File

@ -26,6 +26,7 @@ Route::middleware('auth:sanctum')->group(function (): void {
Route::middleware('auth:sanctum')->group(function (): void { Route::middleware('auth:sanctum')->group(function (): void {
Route::get('meal-posts/stats', [MealPostController::class, 'stats']); Route::get('meal-posts/stats', [MealPostController::class, 'stats']);
Route::get('meal-posts/calendar', [MealPostController::class, 'calendar']);
Route::post('meal-posts/analyze-image', [MealImageAnalysisController::class, 'store']); Route::post('meal-posts/analyze-image', [MealImageAnalysisController::class, 'store']);
Route::apiResource('meal-posts', MealPostController::class)->except(['update']); Route::apiResource('meal-posts', MealPostController::class)->except(['update']);
Route::put('meal-posts/{mealPost}', [MealPostController::class, 'update'])->name('meal-posts.update'); Route::put('meal-posts/{mealPost}', [MealPostController::class, 'update'])->name('meal-posts.update');

View File

@ -0,0 +1,53 @@
<?php
use App\Models\MealPosts;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Sanctum\Sanctum;
uses(RefreshDatabase::class);
it('returns meal post days for a month', function () {
$user = User::factory()->create();
$otherUser = User::factory()->create();
MealPosts::factory()->for($user, 'user')->create([
'eaten_at' => '2026-02-04 08:00:00',
]);
MealPosts::factory()->for($user, 'user')->create([
'eaten_at' => '2026-02-04 20:00:00',
]);
MealPosts::factory()->for($user, 'user')->create([
'eaten_at' => '2026-02-12 12:00:00',
]);
MealPosts::factory()->for($user, 'user')->create([
'eaten_at' => '2026-03-01 12:00:00',
]);
MealPosts::factory()->for($otherUser, 'user')->create([
'eaten_at' => '2026-02-12 12:00:00',
]);
Sanctum::actingAs($user);
$response = $this->getJson('/api/meal-posts/calendar?month=2026-02');
$response
->assertOk()
->assertJsonPath('data.month', '2026-02')
->assertJsonPath('data.startDate', '2026-02-01')
->assertJsonPath('data.endDate', '2026-02-28')
->assertJsonCount(2, 'data.days')
->assertJsonPath('data.days.0.date', '2026-02-04')
->assertJsonPath('data.days.0.mealsCount', 2)
->assertJsonPath('data.days.1.date', '2026-02-12')
->assertJsonPath('data.days.1.mealsCount', 1);
});
it('validates the requested calendar month', function () {
Sanctum::actingAs(User::factory()->create());
$this
->getJson('/api/meal-posts/calendar?month=02-2026')
->assertUnprocessable()
->assertJsonValidationErrors(['month']);
});