Application Laravel 12 + Inertia + Vue 3 + Tailwind. Fonctionnalités : dashboard glycémique, saisie de mesures, courbe SVG, statistiques (jour/semaine/mois/trimestre), défis & badges, chat coach IA (Gemini), paramètres profil avec palette de couleurs, pages auth redessinées, emails transactionnels via Resend avec thème Diabetix. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
76 lines
2.8 KiB
PHP
76 lines
2.8 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Carbon;
|
|
use Inertia\Inertia;
|
|
use Inertia\Response;
|
|
|
|
class StatsController extends Controller
|
|
{
|
|
public function index(Request $request): Response
|
|
{
|
|
$user = $request->user();
|
|
$period = $request->string('period', 'week')->toString();
|
|
|
|
[$from, $bucket, $format] = match ($period) {
|
|
'day' => [Carbon::today(), 'hour', 'H\h'],
|
|
'month' => [Carbon::now()->subDays(30), 'day', 'D'],
|
|
'quarter' => [Carbon::now()->subDays(90), 'week', '\SW'],
|
|
default => [Carbon::now()->subDays(7), 'day', 'ddd'],
|
|
};
|
|
|
|
$rows = $user->measurements()
|
|
->where('measured_at', '>=', $from)
|
|
->orderBy('measured_at')
|
|
->get();
|
|
|
|
$points = $rows->groupBy(fn ($m) => match ($bucket) {
|
|
'hour' => $m->measured_at->format('H'),
|
|
'day' => $m->measured_at->format('Y-m-d'),
|
|
'week' => $m->measured_at->isoWeek(),
|
|
})->map(function ($group) use ($format) {
|
|
$first = $group->first();
|
|
return [
|
|
'l' => $first->measured_at->locale('fr')->isoFormat($format === 'ddd' ? 'dd' : ($format === '\SW' ? '[S]W' : ($format === 'D' ? 'D' : 'HH'))),
|
|
'v' => (int) round($group->avg('value')),
|
|
];
|
|
})->values();
|
|
|
|
$inRange = $rows->filter(fn ($m) => $m->value >= $user->target_min && $m->value <= $user->target_max);
|
|
$stats = [
|
|
'avg' => $rows->count() ? (int) round($rows->avg('value')) : null,
|
|
'in_range_pct' => $rows->count() ? (int) round(($inRange->count() / $rows->count()) * 100) : 0,
|
|
'min' => $rows->min('value') !== null ? (int) $rows->min('value') : null,
|
|
'max' => $rows->max('value') !== null ? (int) $rows->max('value') : null,
|
|
];
|
|
|
|
$history = $user->measurements()
|
|
->orderByDesc('measured_at')
|
|
->limit(8)
|
|
->get()
|
|
->map(fn ($m) => [
|
|
'id' => $m->id,
|
|
'time' => $m->measured_at->isoFormat('HH:mm'),
|
|
'value' => (int) $m->value,
|
|
'context' => match ($m->context) {
|
|
'fasting' => 'À jeun',
|
|
'before_meal' => 'Avant repas',
|
|
'after_meal' => 'Après repas',
|
|
'bedtime' => 'Coucher',
|
|
default => 'Autre',
|
|
},
|
|
'in_range' => $m->isInRange($user->target_min, $user->target_max),
|
|
]);
|
|
|
|
return Inertia::render('Diabetix/Stats', [
|
|
'period' => $period,
|
|
'points' => $points,
|
|
'stats' => $stats,
|
|
'history' => $history,
|
|
'target' => ['min' => (int) $user->target_min, 'max' => (int) $user->target_max],
|
|
]);
|
|
}
|
|
}
|