feat: stats

This commit is contained in:
2026-05-16 17:11:07 +02:00
parent d9e80f7603
commit 7b8ede2a1a
18 changed files with 254 additions and 53 deletions
@@ -3,12 +3,16 @@
namespace App\Http\Controllers;
use App\Http\Requests\MealPostsRequest;
use App\Http\Requests\MealPostStatsRequest;
use App\Http\Resources\MealPostsResource;
use App\Models\MealPosts;
use Carbon\CarbonImmutable;
use Carbon\CarbonInterface;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Http\Response;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage;
class MealPostController extends Controller
@@ -27,6 +31,40 @@ class MealPostController extends Controller
return MealPostsResource::collection($mealPosts);
}
public function stats(MealPostStatsRequest $request): JsonResponse
{
$validated = $request->validated();
$period = $validated['period'] ?? 'day';
$referenceDate = CarbonImmutable::createFromFormat('!Y-m-d', $validated['date'] ?? now()->toDateString());
[$startDate, $endDate] = match ($period) {
'week' => [
$referenceDate->startOfWeek(CarbonInterface::MONDAY),
$referenceDate->endOfWeek(CarbonInterface::SUNDAY),
],
default => [
$referenceDate->startOfDay(),
$referenceDate->endOfDay(),
],
};
$mealPosts = MealPosts::query()
->where('user_id', $request->user()->getKey())
->whereBetween('eaten_at', [$startDate, $endDate])
->get(['calories', 'proteins', 'carbs', 'fats', 'eaten_at']);
return response()->json([
'data' => [
'period' => $period,
'date' => $referenceDate->toDateString(),
'startDate' => $startDate->toDateString(),
'endDate' => $endDate->toDateString(),
'totals' => $this->getNutritionTotals($mealPosts),
'days' => $this->getDailyNutritionTotals($mealPosts, $startDate, $endDate),
],
]);
}
public function store(MealPostsRequest $request): JsonResponse
{
$mealPost = MealPosts::create([
@@ -85,4 +123,34 @@ class MealPostController extends Controller
return $data;
}
private function getDailyNutritionTotals(Collection $mealPosts, CarbonImmutable $startDate, CarbonImmutable $endDate): array
{
$days = [];
for ($date = $startDate; $date->lte($endDate); $date = $date->addDay()) {
$day = $date->toDateString();
$dayMealPosts = $mealPosts->filter(
fn (MealPosts $mealPost): bool => $mealPost->eaten_at->toDateString() === $day
);
$days[] = [
'date' => $day,
'totals' => $this->getNutritionTotals($dayMealPosts),
];
}
return $days;
}
private function getNutritionTotals(Collection $mealPosts): array
{
return [
'calories' => (int) $mealPosts->sum(fn (MealPosts $mealPost): int => (int) ($mealPost->calories ?? 0)),
'proteins' => round((float) $mealPosts->sum(fn (MealPosts $mealPost): float => (float) ($mealPost->proteins ?? 0)), 2),
'carbs' => round((float) $mealPosts->sum(fn (MealPosts $mealPost): float => (float) ($mealPost->carbs ?? 0)), 2),
'fats' => round((float) $mealPosts->sum(fn (MealPosts $mealPost): float => (float) ($mealPost->fats ?? 0)), 2),
'mealsCount' => $mealPosts->count(),
];
}
}