diff --git a/app/Presentation/Obvod/ObvodPresenter.php b/app/Presentation/Obvod/ObvodPresenter.php index 6ed8e82..e09c79c 100644 --- a/app/Presentation/Obvod/ObvodPresenter.php +++ b/app/Presentation/Obvod/ObvodPresenter.php @@ -16,8 +16,22 @@ use Nette\Utils\ArrayHash; final class ObvodPresenter extends BasePresenter { + private const RAZENI_COOKIE = 'obvodRazeni'; + + /** @var array */ + private const RAZENI = [ + 'cislo-vzestupne' => 'Číslo vzestupně', + 'cislo-sestupne' => 'Číslo sestupně', + 'rozpracovani-sestupne' => 'Rozpracování sestupně', + 'rozpracovani-vzestupne' => 'Rozpracování vzestupně', + 'nepropracovani-vzestupne' => 'Nepropracování vzestupně', + 'nepropracovani-sestupne' => 'Nepropracování sestupně', + ]; + private string $skupina = ''; + private string $razeni = 'cislo-vzestupne'; + public function __construct( private ObvodFacade $obvod, private ZaznamFacade $zaznam @@ -28,7 +42,7 @@ final class ObvodPresenter extends BasePresenter { } - public function actionList(?string $skupina = null): void + public function actionList(?string $skupina = null, ?string $razeni = null): void { $this->skupina = $this->obvod->vyberSkupinu( $skupina, @@ -37,6 +51,14 @@ final class ObvodPresenter extends BasePresenter if ($skupina !== null && $skupina === $this->skupina && $this->skupina !== '') { $this->getHttpResponse()->setCookie(ObvodFacade::SKUPINA_COOKIE, $this->skupina, '+1 year', '/'); } + + if ($razeni !== null && isset(self::RAZENI[$razeni])) { + $this->razeni = $razeni; + $this->getHttpResponse()->setCookie(self::RAZENI_COOKIE, $razeni, '+1 year', '/'); + } else { + $ulozeny = $this->getHttpRequest()->getCookie(self::RAZENI_COOKIE); + $this->razeni = is_string($ulozeny) && isset(self::RAZENI[$ulozeny]) ? $ulozeny : 'cislo-vzestupne'; + } } public function renderList(): void @@ -45,16 +67,24 @@ final class ObvodPresenter extends BasePresenter $obvody = []; foreach ($this->obvod->getObvody($this->skupina) as $obvod) { $info = $stari[(int) $obvod->CISLO] ?? null; + $rozpracovan = $info !== null && $info['probiha']; $obvody[] = (object) [ 'ID' => (int) $obvod->ID, 'CISLO' => (int) $obvod->CISLO, 'NAZEV' => (string) $obvod->NAZEV, 'stav' => $this->stavObvodu($info), + 'rozpracovani' => $rozpracovan ? (int) ($info['prideleni'] ?? 0) : null, + 'nepropracovani' => !$rozpracovan && $info !== null && $info['mesice'] !== null + ? (int) $info['mesice'] + : null, ]; } + $this->seradObvody($obvody); $this->template->skupina = $this->skupina; $this->template->skupiny = $this->obvod->getSkupiny(); + $this->template->razeni = $this->razeni; + $this->template->razeniMoznosti = self::RAZENI; $this->template->obvody = $obvody; } @@ -211,6 +241,46 @@ final class ObvodPresenter extends BasePresenter }); } + /** + * @param list $obvody + */ + private function seradObvody(array &$obvody): void + { + $razeni = $this->razeni; + $sestupne = str_ends_with($razeni, 'sestupne'); + $klic = match (true) { + str_starts_with($razeni, 'rozpracovani') => 'rozpracovani', + str_starts_with($razeni, 'nepropracovani') => 'nepropracovani', + default => null, + }; + + usort($obvody, function (object $a, object $b) use ($sestupne, $klic): int { + if ($klic === null) { + $poradi = $a->CISLO <=> $b->CISLO; + return $sestupne ? -$poradi : $poradi; + } + + $prvni = $a->{$klic}; + $druhy = $b->{$klic}; + if ($prvni === null && $druhy === null) { + return $a->CISLO <=> $b->CISLO; + } + if ($prvni === null) { + return 1; + } + if ($druhy === null) { + return -1; + } + + $poradi = $prvni <=> $druhy; + if ($poradi === 0) { + return $a->CISLO <=> $b->CISLO; + } + + return $sestupne ? -$poradi : $poradi; + }); + } + /** * @param array{mesice: int|null, probiha: bool, prideleni: int|null}|null $info * @return object{popisek: string, barva: string, text: string} diff --git a/app/Presentation/Obvod/list.latte b/app/Presentation/Obvod/list.latte index 59ec62d..8d72eb3 100644 --- a/app/Presentation/Obvod/list.latte +++ b/app/Presentation/Obvod/list.latte @@ -10,8 +10,16 @@
-
- {$s} +
+
+ {$s} +
+
diff --git a/www/css/base.css b/www/css/base.css index a9173ea..018a264 100644 --- a/www/css/base.css +++ b/www/css/base.css @@ -661,16 +661,52 @@ body:has(#map[data-max]) { } .filtry, -.akce { +.akce, +.filtry-skupiny { display: flex; flex-wrap: wrap; gap: 0.5rem; } .filtry { + align-items: center; + justify-content: space-between; margin-bottom: 0.85rem; } +.razeni { + display: flex; + align-items: center; + gap: 0.55rem; + margin-left: auto; + min-width: min(100%, 18.5rem); +} + +.razeni-popisek { + color: #1d4f91; + font-weight: 800; + white-space: nowrap; +} + +.razeni-vyber { + width: 100%; + min-height: 2.75rem; + padding: 0.4rem 2.3rem 0.4rem 0.95rem; + border-radius: 999px; + border: 2px solid #1d4f91; + background-color: #fff; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%231d4f91' d='M1.2 1.4 6 6.2 10.8 1.4'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right 0.9rem center; + color: #1d4f91; + font-weight: 800; + font-size: 0.98rem; + line-height: 1.2; + appearance: none; + cursor: pointer; + box-shadow: 0 4px 12px rgba(29, 79, 145, 0.12); +} + .tlacitko.tlacitko-filtr { background: #f8efd0; color: #6f5410; @@ -966,8 +1002,14 @@ body:has(#map[data-max]) { .lista > .tlacitko, .akce, - .formular-akce { + .formular-akce, + .razeni { width: 100%; + margin-left: 0; + } + + .razeni-vyber { + font-size: 1rem; } .akce,