Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ux.symfony.com/src/Controller/Demo/LiveDemoController.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ public function invoice(LiveDemoRepository $liveDemoRepository, ?Invoice $invoic
}

#[Route('/{demo}', name: 'app_demo_live_component_demo')]
#[Route('/animalz', name: 'app_demo_live_component_animalz')]
#[Route('/auto-validating-form', name: 'app_demo_live_component_auto_validating_form')]
#[Route('/chartjs', name: 'app_demo_live_component_chartjs')]
#[Route('/dependent-form-fields', name: 'app_demo_live_component_dependent_form_fields')]
Expand Down
44 changes: 44 additions & 0 deletions ux.symfony.com/src/Enum/AnimalzType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace App\Enum;

enum AnimalzType: string
{
case Normal = 'Normal';
case Water = 'Water';
case Flying = 'Flying';
case Bug = 'Bug';
case Fight = 'Fight';
case Dark = 'Dark';
case Poison = 'Poison';
case Grass = 'Grass';
case Fairy = 'Fairy';
case Fossil = 'Fossil';

public function getColor(): string
{
return match ($this) {
self::Normal => '#9fa19f',
self::Water => '#2980ef',
self::Flying => '#81b9ef',
self::Bug => '#91a119',
self::Fight => '#ff8100',
self::Dark => '#4f3f3d',
self::Poison => '#9141cb',
self::Grass => '#3fa129',
self::Fairy => '#ef70ef',
self::Fossil => '#5060e1',
};
}
}
26 changes: 26 additions & 0 deletions ux.symfony.com/src/Model/Animalz.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace App\Model;

use App\Enum\AnimalzType;

final class Animalz
{
public function __construct(
public string $name,
public AnimalzType $type1,
public ?AnimalzType $type2,
public int $legs,
public string $description,
) {
}
}
100 changes: 100 additions & 0 deletions ux.symfony.com/src/Service/AnimalzRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace App\Service;

use App\Enum\AnimalzType;
use App\Model\Animalz;

class AnimalzRepository
{
private const string DATA_FILE = __DIR__.'/data/animalz-properties.json';

/** @var list<Animalz>|null */
private ?array $zanimalz = null;

/**
* @return list<Animalz>
*/
public function findAll(): array
{
return $this->zanimalz ??= $this->loadZanimalz();
}

/**
* @return list<Animalz>
*/
public function findByNameAndTypeAndLegs(?string $name, ?AnimalzType $type, ?int $maxLegs): array
{
$zanimalz = $this->findAll();

if (null !== $name && '' !== $name) {
$zanimalz = array_filter(
$zanimalz,
fn (Animalz $animalz): bool => str_contains(
strtolower($animalz->name),
strtolower($name),
),
);
}

if (null !== $type) {
$zanimalz = array_filter(
$zanimalz,
fn (Animalz $animalz): bool => $animalz->type1 === $type || $animalz->type2 === $type,
);
}

if (null !== $maxLegs) {
$zanimalz = array_filter(
$zanimalz,
fn (Animalz $animalz): bool => $animalz->legs <= $maxLegs,
);
}

$zanimalz = array_values($zanimalz);
usort($zanimalz, fn (Animalz $a, Animalz $b): int => $a->name <=> $b->name);

return $zanimalz;
}

public function getMaxLegs(): int
{
$zanimalz = $this->findAll();

return max(array_map(fn (Animalz $a): int => $a->legs, $zanimalz));
}

/**
* @return list<Animalz>
*/
private function loadZanimalz(): array
{
$content = file_get_contents(self::DATA_FILE);

if (false === $content) {
return [];
}

$data = json_decode($content, true, 512, \JSON_THROW_ON_ERROR);

return array_map(
fn (array $item): Animalz => new Animalz(
name: $item['name'],
type1: AnimalzType::from($item['type'][0]),
type2: isset($item['type'][1]) ? AnimalzType::from($item['type'][1]) : null,
legs: $item['legs'],
description: $item['description'],
),
$data,
);
}
}
15 changes: 14 additions & 1 deletion ux.symfony.com/src/Service/LiveDemoRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,19 @@ class LiveDemoRepository
public function findAll(): array
{
return [
new LiveDemo(
identifier: 'animalz',
name: 'Facet Filtering',
description: 'Filter results based on a facet menu, with URL parameters.',
author: 'Nayte',
publishedAt: '2025-12-12',
tags: ['facets', 'filter', 'LiveAction'],
longDescription: <<<'EOF'
This demo showcases faceted search with two Live Components working together.
Filter a list of animals by their **number of legs**, **weight**, or **natural habitat** using a dynamic facet menu that updates the results in real time.
EOF,
),
new LiveDemo(
'infinite-scroll-2',
name: 'Infinite Scroll - 2/2',
Expand All @@ -29,7 +42,7 @@ public function findAll(): array
publishedAt: '2024-06-07',
tags: ['grid', 'pagination', 'loading', 'scroll'],
longDescription: <<<EOF
The second and final part of the **Infinite Scroll Serie**, with a new range of (lovely) T-Shirts!
The second and final part of the **Infinite Scroll Series**, with a new range of (lovely) T-Shirts!
Now with `automatic loading on scroll`, a new trick and amazing `loading animations`!
EOF,
),
Expand Down
Loading
Loading