feat: teamer season disposition count in info modal

addresses #869dv94n4
This commit is contained in:
fromme committed 2026-08-31 16:26:53 +02:00
1 parent 39e6f35374
commit 86c5d23181
8 files changed
+344 -2

No files matched your search

@@ -0,0 +1,58 @@
<?php
namespace App\Service\Teamer;
use App\Config\SeasonCalendar;
use App\Entity\Teamer;
use App\Repository\DispositionRepository;
/**
* Tallies a teamer's dispositions per season for the info modal.
*
* Each non-called-off disposition is bucketed by the season its assignment starts in
* (see SeasonCalendar); assignments starting outside any season window land in a single
* "außerhalb der Saison" bucket that is always listed last.
*/
class SeasonDispositionCounter
{
private const OFF_SEASON = 'off_season';
public function __construct(
private readonly DispositionRepository $dispositionRepository,
private readonly SeasonCalendar $seasonCalendar,
) {
}
/**
* @return list<array{label: string, count: int}> newest season first, off-season last
*/
public function countPerSeason(Teamer $teamer): array
{
$counts = [];
foreach ($this->dispositionRepository->findDispositionSeasonDatesByTeamer($teamer) as $row) {
if (empty($row['seasonDate'])) {
continue;
}
$seasonYear = $this->seasonCalendar->seasonYearFor(new \DateTimeImmutable($row['seasonDate']));
$key = $seasonYear ?? self::OFF_SEASON;
$counts[$key] = ($counts[$key] ?? 0) + 1;
}
$offSeasonCount = $counts[self::OFF_SEASON] ?? null;
unset($counts[self::OFF_SEASON]);
krsort($counts);
$rows = [];
foreach ($counts as $seasonYear => $count) {
$rows[] = ['label' => $this->seasonCalendar->label((int) $seasonYear), 'count' => $count];
}
if (null !== $offSeasonCount) {
$rows[] = ['label' => $this->seasonCalendar->label(null), 'count' => $offSeasonCount];
}
return $rows;
}
}