Show remaining budget in mobile category buttons
Each category button now displays "X € restants" below the name, alongside the existing progress gauge and percentage — so the user sees both how much of the budget is used and how much is left without leaving the entry form. Remaining is floored at 0 to match the gauge's 100% cap. categoryProgress now returns a ['pct', 'remaining'] pair per category instead of a bare percentage; tests updated accordingly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
613220f43a
commit
1b3906ade2
@@ -199,7 +199,10 @@ class Index extends Component
|
|||||||
|
|
||||||
$tracked = $this->trackedForCategoryThisMonth($category, $year, $month);
|
$tracked = $this->trackedForCategoryThisMonth($category, $year, $month);
|
||||||
|
|
||||||
return [$category->id => min(100, round($tracked / $budget * 100))];
|
return [$category->id => [
|
||||||
|
'pct' => min(100, round($tracked / $budget * 100)),
|
||||||
|
'remaining' => max(0, $budget - $tracked),
|
||||||
|
]];
|
||||||
});
|
});
|
||||||
|
|
||||||
return view('livewire.suivi.index', [
|
return view('livewire.suivi.index', [
|
||||||
|
|||||||
@@ -70,13 +70,20 @@
|
|||||||
<span
|
<span
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
class="absolute inset-y-0 left-0 {{ $isActive ? 'bg-white/25' : 'bg-text/10' }}"
|
class="absolute inset-y-0 left-0 {{ $isActive ? 'bg-white/25' : 'bg-text/10' }}"
|
||||||
style="width: {{ $progress }}%"
|
style="width: {{ $progress['pct'] }}%"
|
||||||
></span>
|
></span>
|
||||||
@endif
|
@endif
|
||||||
<span class="relative flex items-center justify-between gap-2">
|
<span class="relative flex flex-col gap-0.5">
|
||||||
|
<span class="flex items-center justify-between gap-2">
|
||||||
<span>{{ $category->name }}</span>
|
<span>{{ $category->name }}</span>
|
||||||
@if ($progress !== null)
|
@if ($progress !== null)
|
||||||
<span class="text-xs font-normal {{ $isActive ? 'text-white/80' : 'text-text-muted' }}">{{ $progress }}%</span>
|
<span class="text-xs font-normal {{ $isActive ? 'text-white/80' : 'text-text-muted' }}">{{ $progress['pct'] }}%</span>
|
||||||
|
@endif
|
||||||
|
</span>
|
||||||
|
@if ($progress !== null)
|
||||||
|
<span class="text-xs font-normal {{ $isActive ? 'text-white/70' : 'text-text-muted' }}">
|
||||||
|
{{ number_format($progress['remaining'], 0, ',', ' ') }} € restants
|
||||||
|
</span>
|
||||||
@endif
|
@endif
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ it('shows the recurrence again the following month after being confirmed', funct
|
|||||||
expect($component->viewData('pendingRecurrences')->pluck('id'))->toContain($recurring->id);
|
expect($component->viewData('pendingRecurrences')->pluck('id'))->toContain($recurring->id);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('computes the percentage of budget already tracked for a category this month', function (): void {
|
it('computes the percentage and remaining budget already tracked for a category this month', function (): void {
|
||||||
$this->travelTo(now()->setDate(2026, 3, 10));
|
$this->travelTo(now()->setDate(2026, 3, 10));
|
||||||
|
|
||||||
$user = User::factory()->create();
|
$user = User::factory()->create();
|
||||||
@@ -198,11 +198,13 @@ it('computes the percentage of budget already tracked for a category this month'
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
$component = Livewire::actingAs($user)->test(Index::class);
|
$component = Livewire::actingAs($user)->test(Index::class);
|
||||||
|
$progress = $component->viewData('categoryProgress')[$category->id];
|
||||||
|
|
||||||
expect($component->viewData('categoryProgress')[$category->id])->toBe(60.0);
|
expect($progress['pct'])->toBe(60.0);
|
||||||
|
expect($progress['remaining'])->toBe(400.0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('caps the category progress percentage at 100', function (): void {
|
it('caps the category progress percentage at 100 and floors remaining at 0', function (): void {
|
||||||
$this->travelTo(now()->setDate(2026, 3, 10));
|
$this->travelTo(now()->setDate(2026, 3, 10));
|
||||||
|
|
||||||
$user = User::factory()->create();
|
$user = User::factory()->create();
|
||||||
@@ -216,8 +218,10 @@ it('caps the category progress percentage at 100', function (): void {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
$component = Livewire::actingAs($user)->test(Index::class);
|
$component = Livewire::actingAs($user)->test(Index::class);
|
||||||
|
$progress = $component->viewData('categoryProgress')[$category->id];
|
||||||
|
|
||||||
expect($component->viewData('categoryProgress')[$category->id])->toBe(100);
|
expect($progress['pct'])->toBe(100);
|
||||||
|
expect($progress['remaining'])->toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns no progress for a category without a budget defined', function (): void {
|
it('returns no progress for a category without a budget defined', function (): void {
|
||||||
|
|||||||
Reference in New Issue
Block a user