PM-Liste: Hinweis auf laufende Boost-Platzierung unter dem Status

Badge "Boost bis TT.MM.JJJJ" in der Status-Spalte; Boost-Enden der
Seite in einer Query aggregiert statt isBoosted() je Zeile.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-07-10 17:11:38 +00:00
parent bbcdc72e2f
commit 927523ca63
2 changed files with 51 additions and 0 deletions

View file

@ -2,6 +2,7 @@
use App\Enums\Portal; use App\Enums\Portal;
use App\Enums\PressReleaseStatus; use App\Enums\PressReleaseStatus;
use App\Models\Boost;
use App\Models\PressRelease; use App\Models\PressRelease;
use App\Services\Customer\CustomerCompanyContext; use App\Services\Customer\CustomerCompanyContext;
use App\Services\PressRelease\AiDeclarationRequiredException; use App\Services\PressRelease\AiDeclarationRequiredException;
@ -150,8 +151,19 @@ new #[Layout('components.layouts.app'), Title('Meine Pressemitteilungen')] class
$prs = PressRelease::accessiblePageFor($user, $applyListFilters, $this->sortBy, $this->sortDir); $prs = PressRelease::accessiblePageFor($user, $applyListFilters, $this->sortBy, $this->sortDir);
// Laufende Boosts der Seite in einer Query (statt isBoosted() je
// Zeile): [press_release_id => spätestes ends_at].
$boostEndsById = Boost::query()
->active()
->whereIn('press_release_id', collect($prs->items())->pluck('id'))
->selectRaw('press_release_id, max(ends_at) as ends_at')
->groupBy('press_release_id')
->pluck('ends_at', 'press_release_id')
->map(fn ($endsAt) => \Illuminate\Support\Carbon::parse($endsAt));
return [ return [
'pressReleases' => $prs, 'pressReleases' => $prs,
'boostEndsById' => $boostEndsById,
'statusOptions' => PressReleaseStatus::cases(), 'statusOptions' => PressReleaseStatus::cases(),
'portalOptions' => Portal::cases(), 'portalOptions' => Portal::cases(),
'selectedCompany' => $context->selectedCompany(auth()->user()), 'selectedCompany' => $context->selectedCompany(auth()->user()),
@ -472,6 +484,14 @@ new #[Layout('components.layouts.app'), Title('Meine Pressemitteilungen')] class
:has-title-image="$pr->images_count > 0" /> :has-title-image="$pr->images_count > 0" />
@endif @endif
</div> </div>
@if ($boostEndsAt = $boostEndsById->get($pr->id))
{{-- Laufende Boost-Platzierung (Add-on) direkt unter dem Status. --}}
<div class="mt-1">
<span class="badge hub dot" title="{{ __('Boost — Platzierung auf Start- und Branchenseite') }}">
{{ __('Boost bis :date', ['date' => $boostEndsAt->format('d.m.Y')]) }}
</span>
</div>
@endif
</flux:table.cell> </flux:table.cell>
<flux:table.cell> <flux:table.cell>

View file

@ -1,6 +1,7 @@
<?php <?php
use App\Enums\PressReleaseClassification; use App\Enums\PressReleaseClassification;
use App\Models\Boost;
use App\Models\Category; use App\Models\Category;
use App\Models\Company; use App\Models\Company;
use App\Models\PressRelease; use App\Models\PressRelease;
@ -181,6 +182,36 @@ test('a boost without enough credits opens the shortfall modal instead of bookin
expect($pr->fresh()->isBoosted())->toBeFalse(); expect($pr->fresh()->isBoosted())->toBeFalse();
}); });
test('the press release list shows a hint with end date for an active boost', function () {
/** @var TestCase $this */
['customer' => $customer, 'pr' => $pr] = publishedGreenPrForOwner();
$this->wallet->credit($customer, 40);
$this->actingAs($customer);
LivewireVolt::test('customer.press-releases.index')
->assertDontSee('Boost bis');
Boost::factory()->for($pr)->create([
'ends_at' => now()->addDays(7)->setTime(9, 0),
]);
LivewireVolt::test('customer.press-releases.index')
->assertSee('Boost bis '.now()->addDays(7)->format('d.m.Y'));
});
test('an expired boost shows no hint in the press release list', function () {
/** @var TestCase $this */
['customer' => $customer, 'pr' => $pr] = publishedGreenPrForOwner();
$this->actingAs($customer);
Boost::factory()->for($pr)->expired()->create();
LivewireVolt::test('customer.press-releases.index')
->assertDontSee('Boost bis');
});
test('a non-green release cannot be boosted from the detail page', function () { test('a non-green release cannot be boosted from the detail page', function () {
/** @var TestCase $this */ /** @var TestCase $this */
['customer' => $customer, 'pr' => $pr] = publishedGreenPrForOwner(); ['customer' => $customer, 'pr' => $pr] = publishedGreenPrForOwner();