Drobnosti GUI + sloupeček Stav v Obvodech
parent
0e18b46a15
commit
acbdb6ba83
|
|
@ -61,6 +61,7 @@
|
||||||
<a class='nav-link' n:href=":Sign:out">Odhlásit</a>
|
<a class='nav-link' n:href=":Sign:out">Odhlásit</a>
|
||||||
{else}
|
{else}
|
||||||
<a class='nav-link' n:href=':Home:'>Home</a>
|
<a class='nav-link' n:href=':Home:'>Home</a>
|
||||||
|
<a class='nav-link' n:href=':Nastaveni:'>Nastavení</a>
|
||||||
<a class='nav-link' n:href=":Sign:in, backlink: (isset($navrat) ? $navrat : '')">Přihlásit</a>
|
<a class='nav-link' n:href=":Sign:in, backlink: (isset($navrat) ? $navrat : '')">Přihlásit</a>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,20 @@ declare(strict_types=1);
|
||||||
namespace App\Presentation\Nastaveni;
|
namespace App\Presentation\Nastaveni;
|
||||||
|
|
||||||
use App\Core\MapovyPodklad;
|
use App\Core\MapovyPodklad;
|
||||||
use App\Presentation\BasePresenter;
|
|
||||||
use Nette\Application\UI\Form;
|
use Nette\Application\UI\Form;
|
||||||
|
use Nette\Application\UI\Presenter;
|
||||||
use Nette\Utils\ArrayHash;
|
use Nette\Utils\ArrayHash;
|
||||||
|
|
||||||
|
|
||||||
final class NastaveniPresenter extends BasePresenter
|
final class NastaveniPresenter extends Presenter
|
||||||
{
|
{
|
||||||
|
public function beforeRender(): void
|
||||||
|
{
|
||||||
|
if (!$this->getUser()->isLoggedIn()) {
|
||||||
|
$this->template->navrat = $this->storeRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected function createComponentPodkladForm(): Form
|
protected function createComponentPodkladForm(): Form
|
||||||
{
|
{
|
||||||
$form = new Form;
|
$form = new Form;
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ namespace App\Presentation\Obvod;
|
||||||
use App\Model\ObvodFacade;
|
use App\Model\ObvodFacade;
|
||||||
use App\Model\ZaznamFacade;
|
use App\Model\ZaznamFacade;
|
||||||
use App\Presentation\BasePresenter;
|
use App\Presentation\BasePresenter;
|
||||||
|
use App\Presentation\Mapa\MapaPresenter;
|
||||||
use Nette;
|
use Nette;
|
||||||
use Nette\Application\UI\Form;
|
use Nette\Application\UI\Form;
|
||||||
use Nette\Application\UI\Multiplier;
|
use Nette\Application\UI\Multiplier;
|
||||||
|
|
@ -40,9 +41,21 @@ final class ObvodPresenter extends BasePresenter
|
||||||
|
|
||||||
public function renderList(): void
|
public function renderList(): void
|
||||||
{
|
{
|
||||||
|
$stari = $this->zaznam->getStariObvodu();
|
||||||
|
$obvody = [];
|
||||||
|
foreach ($this->obvod->getObvody($this->skupina) as $obvod) {
|
||||||
|
$info = $stari[(int) $obvod->CISLO] ?? null;
|
||||||
|
$obvody[] = (object) [
|
||||||
|
'ID' => (int) $obvod->ID,
|
||||||
|
'CISLO' => (int) $obvod->CISLO,
|
||||||
|
'NAZEV' => (string) $obvod->NAZEV,
|
||||||
|
'stav' => $this->stavObvodu($info),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
$this->template->skupina = $this->skupina;
|
$this->template->skupina = $this->skupina;
|
||||||
$this->template->skupiny = $this->obvod->getSkupiny();
|
$this->template->skupiny = $this->obvod->getSkupiny();
|
||||||
$this->template->obvody = $this->obvod->getObvody($this->skupina);
|
$this->template->obvody = $obvody;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function renderView(int $id = null): void
|
public function renderView(int $id = null): void
|
||||||
|
|
@ -198,6 +211,86 @@ final class ObvodPresenter extends BasePresenter
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array{mesice: int|null, probiha: bool, prideleni: int|null}|null $info
|
||||||
|
* @return object{popisek: string, barva: string, text: string}
|
||||||
|
*/
|
||||||
|
private function stavObvodu(?array $info): object
|
||||||
|
{
|
||||||
|
if ($info !== null && $info['probiha']) {
|
||||||
|
$mesice = $info['prideleni'];
|
||||||
|
return (object) [
|
||||||
|
'popisek' => 'Rozpracován ' . $this->textMesicu($mesice),
|
||||||
|
'barva' => $this->cssBarva($this->barvaStari($mesice, MapaPresenter::STUPNICE_PRIDELENI)),
|
||||||
|
'text' => $this->cssBarva($this->barvaTextu($mesice, MapaPresenter::STUPNICE_PRIDELENI)),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($info !== null && $info['mesice'] !== null) {
|
||||||
|
return (object) [
|
||||||
|
'popisek' => 'Nepropracován ' . $this->textMesicu($info['mesice']),
|
||||||
|
'barva' => $this->cssBarva($this->barvaStari($info['mesice'], MapaPresenter::STUPNICE_MESICU)),
|
||||||
|
'text' => $this->cssBarva($this->barvaTextu($info['mesice'], MapaPresenter::STUPNICE_MESICU)),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (object) [
|
||||||
|
'popisek' => 'Bez záznamu',
|
||||||
|
'barva' => '#b0bec5',
|
||||||
|
'text' => '#1a1a1a',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function cssBarva(string $barva): string
|
||||||
|
{
|
||||||
|
if (preg_match('/^rgb\((?:25[0-5]|2[0-4]\d|1?\d?\d),(?:25[0-5]|2[0-4]\d|1?\d?\d),(?:25[0-5]|2[0-4]\d|1?\d?\d)\)$/', $barva)) {
|
||||||
|
return $barva;
|
||||||
|
}
|
||||||
|
if (preg_match('/^#[0-9a-fA-F]{3}(?:[0-9a-fA-F]{3})?$/', $barva)) {
|
||||||
|
return $barva;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '#b0bec5';
|
||||||
|
}
|
||||||
|
|
||||||
|
private function textMesicu(?int $mesice): string
|
||||||
|
{
|
||||||
|
return $mesice === null ? '—' : $mesice . ' měs.';
|
||||||
|
}
|
||||||
|
|
||||||
|
private function barvaStari(?int $mesice, int $max): string
|
||||||
|
{
|
||||||
|
$t = $mesice === null || $max <= 0 ? 1 : max(0, min($mesice / $max, 1));
|
||||||
|
$zelena = [27, 158, 62];
|
||||||
|
$zluta = [230, 184, 0];
|
||||||
|
$cervena = [198, 40, 40];
|
||||||
|
$kanaly = $t < 0.5
|
||||||
|
? $this->mixBarvy($zelena, $zluta, $t / 0.5)
|
||||||
|
: $this->mixBarvy($zluta, $cervena, ($t - 0.5) / 0.5);
|
||||||
|
|
||||||
|
return 'rgb(' . implode(',', $kanaly) . ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
private function barvaTextu(?int $mesice, int $max): string
|
||||||
|
{
|
||||||
|
$t = $mesice === null || $max <= 0 ? 1 : max(0, min($mesice / $max, 1));
|
||||||
|
return $t > 0.72 ? '#fff' : '#1a1a1a';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array{0: int, 1: int, 2: int} $a
|
||||||
|
* @param array{0: int, 1: int, 2: int} $b
|
||||||
|
* @return array{0: int, 1: int, 2: int}
|
||||||
|
*/
|
||||||
|
private function mixBarvy(array $a, array $b, float $t): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
(int) round($a[0] + ($b[0] - $a[0]) * $t),
|
||||||
|
(int) round($a[1] + ($b[1] - $a[1]) * $t),
|
||||||
|
(int) round($a[2] + ($b[2] - $a[2]) * $t),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
private function obvodId(): int
|
private function obvodId(): int
|
||||||
{
|
{
|
||||||
$id = $this->getParameter('id');
|
$id = $this->getParameter('id');
|
||||||
|
|
|
||||||
|
|
@ -19,14 +19,16 @@
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">Číslo</th>
|
<th scope="col">Číslo</th>
|
||||||
<th scope="col">Název</th>
|
<th scope="col">Název</th>
|
||||||
|
<th scope="col">Stav</th>
|
||||||
<th scope="col">Akce</th>
|
<th scope="col">Akce</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{foreach $obvody as $obvod}
|
{foreach $obvody as $obvod}
|
||||||
<tr>
|
<tr>
|
||||||
<td data-popisek="Číslo">{$obvod->CISLO}</td>
|
<td data-popisek="Číslo"><span class="tabulka-cislo">{$obvod->CISLO}</span></td>
|
||||||
<td data-popisek="Název">{$obvod->NAZEV}</td>
|
<td data-popisek="Název">{$obvod->NAZEV}</td>
|
||||||
|
<td data-popisek="Stav"><span class="stav-badge" style="background: {$obvod->stav->barva|noescape}; color: {$obvod->stav->text|noescape}">{$obvod->stav->popisek}</span></td>
|
||||||
<td class="bunka-akce" data-popisek="Akce">
|
<td class="bunka-akce" data-popisek="Akce">
|
||||||
<div class="akce-radek">
|
<div class="akce-radek">
|
||||||
<a n:href=":Obvod:view id:$obvod->ID" class="tlacitko">Otevřít</a>
|
<a n:href=":Obvod:view id:$obvod->ID" class="tlacitko">Otevřít</a>
|
||||||
|
|
|
||||||
|
|
@ -786,6 +786,35 @@ body:has(#map[data-max]) {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tabulka-cislo {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 2.75rem;
|
||||||
|
height: 2.75rem;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid #1d4f91;
|
||||||
|
background: #2652a8;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 1.05rem;
|
||||||
|
font-weight: 800;
|
||||||
|
line-height: 1;
|
||||||
|
box-shadow: 0 4px 10px rgba(29, 79, 145, 0.28);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stav-badge {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.28rem 0.7rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.22);
|
||||||
|
font-size: 0.82rem;
|
||||||
|
font-weight: 800;
|
||||||
|
line-height: 1.2;
|
||||||
|
white-space: nowrap;
|
||||||
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
.bunka-akce .akce-radek {
|
.bunka-akce .akce-radek {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue