year = (int) now()->year; $this->period = (string) now()->month; } private function budgetFor(Category $category): float { $lines = $category->budgetLines()->where('year', $this->year)->get(); if ($this->period === 'year') { $default = (float) ($lines->firstWhere('month', null)->amount ?? 0); $total = 0.0; for ($m = 1; $m <= 12; $m++) { $override = $lines->firstWhere('month', $m); $total += $override ? (float) $override->amount : $default; } return $total; } $month = (int) $this->period; $override = $lines->firstWhere('month', $month); return $override ? (float) $override->amount : (float) ($lines->firstWhere('month', null)->amount ?? 0); } private function trackedFor(Category $category): float { $query = $category->transactions()->whereYear('date_effective', $this->year); if ($this->period !== 'year') { $query->whereMonth('date_effective', (int) $this->period); } return (float) $query->sum('amount'); } public function render() { $household = auth()->user()->currentHousehold; $sections = collect(CategoryType::cases())->mapWithKeys(function (CategoryType $type) use ($household) { $rows = $household->categories() ->where('type', $type) ->orderBy('position') ->get() ->map(function (Category $category) { $budget = $this->budgetFor($category); $tracked = $this->trackedFor($category); return [ 'category' => $category, 'tracked' => $tracked, 'budget' => $budget, 'pct' => $budget > 0 ? min(100, round($tracked / $budget * 100)) : 0, 'reste' => max(0, $budget - $tracked), 'manque' => max(0, $tracked - $budget), ]; }); return [$type->value => [ 'rows' => $rows, 'totals' => [ 'tracked' => $rows->sum('tracked'), 'budget' => $rows->sum('budget'), 'reste' => $rows->sum('reste'), 'manque' => $rows->sum('manque'), ], ]]; }); $chartData = $sections->mapWithKeys(function ($section, $key) { $top = $section['rows'] ->filter(fn ($row) => $row['tracked'] > 0) ->sortByDesc('tracked') ->take(6) ->values(); return [$key => [ 'labels' => $top->pluck('category.name')->values(), 'data' => $top->pluck('tracked')->values(), ]]; }); return view('livewire.dashboard.index', [ 'types' => CategoryType::cases(), 'sections' => $sections, 'chartData' => $chartData, ]); } }