Produkty Objednávky Zákazníci Dokumentace
Nepřihlášen Uživatel 1 Uživatel 2 Uživatel 3
Část III · Enum sloupce

8.2. Prezentační rozhraní case

Enum smí implementovat čtyři rozhraní – HasIcon, HasColor, HasBadge a HasShort. Sloupec se přidává pořád stejným addEnum(); jak bude vypadat, rozhoduje sám enum.

Ukázka

Stav a Platba mají ikonu, barvu i pilulku, Doprava jen barvu a zkratku. V columns() se ty tři sloupce neliší jediným znakem.

Zdrojový kód

php app/Modules/AdminModule/Components/Docs/Columns/EnumPresentationGridControl/EnumPresentationGridControl.php
<?php

declare(strict_types=1);

namespace App\Components\Docs\Columns\EnumPresentationGridControl;

use App\Enum\OrderPayment;
use App\Enum\OrderShipping;
use App\Enum\OrderStatus;
use Xart\Grid\Button\ButtonManager;
use Xart\Grid\Column\ColumnManager;
use Xart\Grid\Control\GridControl;
use Xart\Grid\DataOutput\Row;
use Xart\Grid\DataSource\DataSource;
use Xart\Grid\DataSource\SQL\SQLDataSource;

/**
 * Dokumentace, kapitola 8.2 – Prezentační rozhraní case.
 *
 * Tři enumy, každý s jinou sadou rozhraní: Stav a Platba mají ikonu, barvu i pilulku, Doprava jen
 * barvu a zkratku. V columns() se přitom neliší jediným znakem – všechno rozhoduje enum sám.
 */
class EnumPresentationGridControl extends GridControl
{
    public function createDataSource(): DataSource
    {
        return new SQLDataSource(__DIR__ . '/EnumPresentationGridControl.sql');
    }


    public function columns(ColumnManager $cm): void
    {
        $cm->add('number', 'Číslo');

        // OrderStatus: HasIcon, HasColor, HasBadge – v buňce ikona v barevné pilulce.
        $cm->addEnum('status', 'Stav', OrderStatus::class);

        // OrderPayment: totéž, jen s jinými barvami.
        $cm->addEnum('payment', 'Platba', OrderPayment::class);

        // OrderShipping: HasColor a HasShort – barevný podklad a místo popisku zkratka.
        $cm->addEnum('shipping', 'Doprava', OrderShipping::class);

        $cm->addNumber('total_price', 'Celkem', 2, 'Kč');
    }


    public function buttons(ButtonManager $bm): void
    {
    }


    public function rows(Row $row): void
    {
    }


    public function render(): void
    {
        $this->template->render(__DIR__ . '/EnumPresentationGridControl.latte');
    }
}
php app/Enum/OrderStatus.php
<?php

declare(strict_types=1);

namespace App\Enum;

use Xart\Grid\Color\Color;
use Xart\Grid\Column\Enum\HasBadge;
use Xart\Grid\Column\Enum\HasColor;
use Xart\Grid\Column\Enum\HasIcon;

enum OrderStatus: string implements HasIcon, HasColor, HasBadge
{
    case new = 'Nová';
    case confirmed = 'Potvrzená';
    case shipped = 'Odeslaná';
    case delivered = 'Doručená';
    case cancelled = 'Stornovaná';


    public function icon(): ?string
    {
        return match ($this) {
            self::new => 'ti ti-sparkles',
            self::confirmed => 'ti ti-checkbox',
            self::shipped => 'ti ti-truck-delivery',
            self::delivered => 'ti ti-home-check',
            self::cancelled => 'ti ti-ban',
        };
    }


    public function color(): Color|string|null
    {
        return match ($this) {
            self::new => '#b091ff',
            self::confirmed => '#74c0fc',
            self::shipped => '#ffd43b',
            self::delivered => '#40c057',
            self::cancelled => '#fa5252',
        };
    }


    public function badge(): Color|string|null
    {
        return match ($this) {
            self::new => new Color('#9e3bdb', '#edf2ff'),
            self::confirmed => new Color('#1c7ed6', '#e7f5ff'),
            self::shipped => new Color('#d9480f', '#fff9db'),
            self::delivered => new Color('#2b8a3e', '#ebfbee'),
            self::cancelled => new Color('#c92a2a', '#fff5f5'),
        };
    }
}
php app/Enum/OrderShipping.php
<?php

declare(strict_types=1);

namespace App\Enum;

use Xart\Grid\Color\Color;
use Xart\Grid\Color\ColorScheme;
use Xart\Grid\Column\Enum\HasColor;
use Xart\Grid\Column\Enum\HasShort;

enum OrderShipping: string implements HasColor, HasShort
{
    case ppl = 'PPL';
    case dpd = 'DPD';
    case zasilkovna = 'Zásilkovna';
    case post = 'Česká pošta';
    case pickup = 'Osobní odběr';


    public function color(): Color|string|null
    {
        return match ($this) {
            self::ppl => ColorScheme::purple()->subtle(),
            self::dpd => ColorScheme::orange()->subtle(),
            self::zasilkovna => ColorScheme::red()->subtle(),
            self::post => ColorScheme::yellow()->subtle(),
            self::pickup => ColorScheme::green()->subtle()
        };
    }


    public function short(): string
    {
        return match ($this) {
            self::zasilkovna => 'ZAS',
            self::post => 'ČP',
            self::pickup => 'OS',
            default => $this->value
        };
    }
}

Čtyři rozhraní

RozhraníMetodaCo přidá
HasIcon icon(): ?string CSS třídy ikony (ti ti-truck) – vždy před textem. Hodnota jde rovnou do atributu class, takže se při definici gridu ověří proti ^[a-zA-Z0-9 _-]+$.
HasColor color(): Color|string|null Barevný podklad přes celou plochu buňky. Řetězec je zkratka za new Color($barva) – barva textu se dopočítá tak, aby byla čitelná.
HasBadge badge(): Color|string|null Barevná pilulka kolem ikony a textu – tedy jen kus buňky, ne celá.
HasShort short(): ?string Zkratka místo plného popisku (ČP). Do exportu jde vždycky plný popisek – zkratku by v CSV nikdo nevysvětlil.

Rozhraní se implementují po jednom, jak se hodí. Case, který v match vrátí null, prostě tu část nemá – ostatní case v témže enumu ji mít můžou.

Kam se prezentace propíše

  • Buňka – vykreslí se vše, co case umí (doladit jde v kapitole 8.3).
  • Nabídka filtru – tytéž části kreslí frontend, jen barva se v ní vejde pouze na chip položky.
  • Export – vždy plný popisek. Barva podkladu se propíše jako pozadí buňky tam, kde to formát umí (XLSX, PDF); pilulka ne, ta je prvek uvnitř buňky, ne barva buňky.
  • Přístupnost – plný popisek zůstává v title buňky, a když je v ní jen ikona nebo barva, ještě v aria-label.

Barvy

color() i badge() berou Color, nebo rovnou hex jako řetězec. Pojmenovanou paletu má ColorScheme (ColorScheme::blue(), ->subtle() pro světlejší odstín), vlastní dvojici podklad + text zapíšete new Color('#c92a2a', '#fff5f5'). Celá paleta má svou kapitolu 16.