```
✨ feat(Product): Ajoute la relation avec l'entité FormulesProductInclus. ✨ feat(FormulesController): Crée le contrôleur pour gérer les formules. ✨ feat(templates): Ajoute le template pour afficher les formules dans le dashboard. ✨ feat(base.twig): Ajoute un lien vers la gestion des formules dans le menu. ⚙️ chore(vich_uploader): Configure vich uploader pour les images des formules. ```
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
vich_uploader:
|
||||
db_driver: orm
|
||||
mappings:
|
||||
image_formules:
|
||||
uri_prefix: /images/image_formules
|
||||
upload_destination: '%kernel.project_dir%/public/images/image_formules'
|
||||
namer: Vich\UploaderBundle\Naming\SmartUniqueNamer
|
||||
image_product:
|
||||
uri_prefix: /images/image_product
|
||||
upload_destination: '%kernel.project_dir%/public/images/image_product'
|
||||
|
||||
42
migrations/Version20260128075215.php
Normal file
42
migrations/Version20260128075215.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20260128075215 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE TABLE formules (id SERIAL NOT NULL, name VARCHAR(255) NOT NULL, image_name VARCHAR(255) DEFAULT NULL, image_size INT DEFAULT NULL, updated_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, type VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('COMMENT ON COLUMN formules.updated_at IS \'(DC2Type:datetime_immutable)\'');
|
||||
$this->addSql('CREATE TABLE formules_product_inclus (id SERIAL NOT NULL, formules_id INT DEFAULT NULL, product_id INT DEFAULT NULL, config TEXT NOT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE INDEX IDX_BD36A828168F3793 ON formules_product_inclus (formules_id)');
|
||||
$this->addSql('CREATE INDEX IDX_BD36A8284584665A ON formules_product_inclus (product_id)');
|
||||
$this->addSql('COMMENT ON COLUMN formules_product_inclus.config IS \'(DC2Type:array)\'');
|
||||
$this->addSql('ALTER TABLE formules_product_inclus ADD CONSTRAINT FK_BD36A828168F3793 FOREIGN KEY (formules_id) REFERENCES formules (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE formules_product_inclus ADD CONSTRAINT FK_BD36A8284584665A FOREIGN KEY (product_id) REFERENCES product (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE SCHEMA public');
|
||||
$this->addSql('ALTER TABLE formules_product_inclus DROP CONSTRAINT FK_BD36A828168F3793');
|
||||
$this->addSql('ALTER TABLE formules_product_inclus DROP CONSTRAINT FK_BD36A8284584665A');
|
||||
$this->addSql('DROP TABLE formules');
|
||||
$this->addSql('DROP TABLE formules_product_inclus');
|
||||
}
|
||||
}
|
||||
40
src/Controller/Dashboard/FormulesController.php
Normal file
40
src/Controller/Dashboard/FormulesController.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Dashboard;
|
||||
|
||||
use App\Entity\Options;
|
||||
use App\Entity\Product;
|
||||
use App\Entity\ProductDoc;
|
||||
use App\Form\OptionsType;
|
||||
use App\Form\ProductDocType;
|
||||
use App\Form\ProductType;
|
||||
use App\Logger\AppLogger;
|
||||
use App\Repository\FormulesRepository;
|
||||
use App\Repository\OptionsRepository;
|
||||
use App\Repository\ProductRepository;
|
||||
use App\Service\Stripe\Client;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Messenger\MessageBusInterface;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Presta\SitemapBundle\Messenger\DumpSitemapMessage;
|
||||
use Vich\UploaderBundle\Templating\Helper\UploaderHelper;
|
||||
|
||||
class FormulesController extends AbstractController
|
||||
{
|
||||
// --- JSON ENDPOINTS ---
|
||||
|
||||
#[Route(path: '/crm/formules', name: 'app_crm_formules', methods: ['GET'])]
|
||||
public function formules(PaginatorInterface $paginator,AppLogger $appLogger,Request $request,FormulesRepository $formulesRepository): Response
|
||||
{
|
||||
$appLogger->record('VIEW', 'Consultation des formules');
|
||||
|
||||
return $this->render('dashboard/formules.twig', [
|
||||
'formules' => $paginator->paginate($formulesRepository->findBy([],['id'=>'asc']), $request->query->getInt('page', 1), 10),
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
174
src/Entity/Formules.php
Normal file
174
src/Entity/Formules.php
Normal file
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\FormulesRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\HttpFoundation\File\File;
|
||||
use Vich\UploaderBundle\Mapping\Attribute\Uploadable;
|
||||
use Vich\UploaderBundle\Mapping\Attribute\UploadableField;
|
||||
|
||||
#[ORM\Entity(repositoryClass: FormulesRepository::class)]
|
||||
#[Uploadable]
|
||||
class Formules
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(length: 255)]
|
||||
private ?string $name = null;
|
||||
|
||||
|
||||
#[UploadableField(mapping: 'image_formules', fileNameProperty: 'imageName', size: 'imageSize')]
|
||||
private ?File $imageFile = null;
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?string $imageName = null;
|
||||
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?int $imageSize = null;
|
||||
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?\DateTimeImmutable $updatedAt = null;
|
||||
|
||||
#[ORM\Column(length: 255)]
|
||||
private ?string $type = null;
|
||||
|
||||
/**
|
||||
* @var Collection<int, FormulesProductInclus>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: FormulesProductInclus::class, mappedBy: 'formules')]
|
||||
private Collection $formulesProductIncluses;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->formulesProductIncluses = new ArrayCollection();
|
||||
}
|
||||
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTimeImmutable|null
|
||||
*/
|
||||
public function getUpdatedAt(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return File|null
|
||||
*/
|
||||
public function getImageFile(): ?File
|
||||
{
|
||||
return $this->imageFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getImageName(): ?string
|
||||
{
|
||||
return $this->imageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getImageSize(): ?int
|
||||
{
|
||||
return $this->imageSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTimeImmutable|null $updatedAt
|
||||
*/
|
||||
public function setUpdatedAt(?\DateTimeImmutable $updatedAt): void
|
||||
{
|
||||
$this->updatedAt = $updatedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param File|null $imageFile
|
||||
*/
|
||||
public function setImageFile(?File $imageFile): void
|
||||
{
|
||||
$this->imageFile = $imageFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $imageName
|
||||
*/
|
||||
public function setImageName(?string $imageName): void
|
||||
{
|
||||
$this->imageName = $imageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $imageSize
|
||||
*/
|
||||
public function setImageSize(?int $imageSize): void
|
||||
{
|
||||
$this->imageSize = $imageSize;
|
||||
}
|
||||
|
||||
public function getType(): ?string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function setType(string $type): static
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, FormulesProductInclus>
|
||||
*/
|
||||
public function getFormulesProductIncluses(): Collection
|
||||
{
|
||||
return $this->formulesProductIncluses;
|
||||
}
|
||||
|
||||
public function addFormulesProductInclus(FormulesProductInclus $formulesProductInclus): static
|
||||
{
|
||||
if (!$this->formulesProductIncluses->contains($formulesProductInclus)) {
|
||||
$this->formulesProductIncluses->add($formulesProductInclus);
|
||||
$formulesProductInclus->setFormules($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeFormulesProductInclus(FormulesProductInclus $formulesProductInclus): static
|
||||
{
|
||||
if ($this->formulesProductIncluses->removeElement($formulesProductInclus)) {
|
||||
// set the owning side to null (unless already changed)
|
||||
if ($formulesProductInclus->getFormules() === $this) {
|
||||
$formulesProductInclus->setFormules(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
66
src/Entity/FormulesProductInclus.php
Normal file
66
src/Entity/FormulesProductInclus.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\FormulesProductInclusRepository;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: FormulesProductInclusRepository::class)]
|
||||
class FormulesProductInclus
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\ManyToOne(inversedBy: 'formulesProductIncluses')]
|
||||
private ?Formules $formules = null;
|
||||
|
||||
#[ORM\ManyToOne(inversedBy: 'formulesProductIncluses')]
|
||||
private ?Product $PRODUCT = null;
|
||||
|
||||
#[ORM\Column(type: Types::ARRAY)]
|
||||
private array $config = [];
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getFormules(): ?Formules
|
||||
{
|
||||
return $this->formules;
|
||||
}
|
||||
|
||||
public function setFormules(?Formules $formules): static
|
||||
{
|
||||
$this->formules = $formules;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPRODUCT(): ?Product
|
||||
{
|
||||
return $this->PRODUCT;
|
||||
}
|
||||
|
||||
public function setPRODUCT(?Product $PRODUCT): static
|
||||
{
|
||||
$this->PRODUCT = $PRODUCT;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getConfig(): array
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
public function setConfig(array $config): static
|
||||
{
|
||||
$this->config = $config;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -81,10 +81,17 @@ class Product
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?float $dimP = null;
|
||||
|
||||
/**
|
||||
* @var Collection<int, FormulesProductInclus>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: FormulesProductInclus::class, mappedBy: 'PRODUCT')]
|
||||
private Collection $formulesProductIncluses;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->productReserves = new ArrayCollection();
|
||||
$this->productDocs = new ArrayCollection();
|
||||
$this->formulesProductIncluses = new ArrayCollection();
|
||||
}
|
||||
public function slug()
|
||||
{
|
||||
@@ -363,4 +370,34 @@ class Product
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, FormulesProductInclus>
|
||||
*/
|
||||
public function getFormulesProductIncluses(): Collection
|
||||
{
|
||||
return $this->formulesProductIncluses;
|
||||
}
|
||||
|
||||
public function addFormulesProductInclus(FormulesProductInclus $formulesProductInclus): static
|
||||
{
|
||||
if (!$this->formulesProductIncluses->contains($formulesProductInclus)) {
|
||||
$this->formulesProductIncluses->add($formulesProductInclus);
|
||||
$formulesProductInclus->setPRODUCT($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeFormulesProductInclus(FormulesProductInclus $formulesProductInclus): static
|
||||
{
|
||||
if ($this->formulesProductIncluses->removeElement($formulesProductInclus)) {
|
||||
// set the owning side to null (unless already changed)
|
||||
if ($formulesProductInclus->getPRODUCT() === $this) {
|
||||
$formulesProductInclus->setPRODUCT(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
43
src/Repository/FormulesProductInclusRepository.php
Normal file
43
src/Repository/FormulesProductInclusRepository.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\FormulesProductInclus;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<FormulesProductInclus>
|
||||
*/
|
||||
class FormulesProductInclusRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, FormulesProductInclus::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return FormulesProductInclus[] Returns an array of FormulesProductInclus objects
|
||||
// */
|
||||
// public function findByExampleField($value): array
|
||||
// {
|
||||
// return $this->createQueryBuilder('f')
|
||||
// ->andWhere('f.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->orderBy('f.id', 'ASC')
|
||||
// ->setMaxResults(10)
|
||||
// ->getQuery()
|
||||
// ->getResult()
|
||||
// ;
|
||||
// }
|
||||
|
||||
// public function findOneBySomeField($value): ?FormulesProductInclus
|
||||
// {
|
||||
// return $this->createQueryBuilder('f')
|
||||
// ->andWhere('f.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->getQuery()
|
||||
// ->getOneOrNullResult()
|
||||
// ;
|
||||
// }
|
||||
}
|
||||
43
src/Repository/FormulesRepository.php
Normal file
43
src/Repository/FormulesRepository.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Formules;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Formules>
|
||||
*/
|
||||
class FormulesRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Formules::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return Formules[] Returns an array of Formules objects
|
||||
// */
|
||||
// public function findByExampleField($value): array
|
||||
// {
|
||||
// return $this->createQueryBuilder('f')
|
||||
// ->andWhere('f.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->orderBy('f.id', 'ASC')
|
||||
// ->setMaxResults(10)
|
||||
// ->getQuery()
|
||||
// ->getResult()
|
||||
// ;
|
||||
// }
|
||||
|
||||
// public function findOneBySomeField($value): ?Formules
|
||||
// {
|
||||
// return $this->createQueryBuilder('f')
|
||||
// ->andWhere('f.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->getQuery()
|
||||
// ->getOneOrNullResult()
|
||||
// ;
|
||||
// }
|
||||
}
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
{{ menu.nav_link(path('app_crm'), 'Dashboard', '<path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path>', 'app_crm') }}
|
||||
{{ menu.nav_link(path('app_crm_product'), 'Produits', '<path d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"></path>', 'app_clients') }}
|
||||
{{ menu.nav_link(path('app_crm_formules'), 'Formules', '<path d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"></path>', 'app_clients') }}
|
||||
{# {{ menu.nav_link(path('app_crm_contrats'), 'Contrat de location', '<path d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"></path>', 'app_clients') }}#}
|
||||
{# {{ menu.nav_link(path('app_crm_facture'), 'Facture', '<path d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"></path>', 'app_clients') }}#}
|
||||
{# {{ menu.nav_link(path('app_crm_devis'), 'Devis', '<path d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"></path>', 'app_clients') }}#}
|
||||
|
||||
66
templates/dashboard/formules.twig
Normal file
66
templates/dashboard/formules.twig
Normal file
@@ -0,0 +1,66 @@
|
||||
{% extends 'dashboard/base.twig' %}
|
||||
|
||||
{% block title %}Catalogue Formules{% endblock %}
|
||||
{% block title_header %}Gestion du <span class="text-blue-500">Formules</span>{% endblock %}
|
||||
|
||||
{% block actions %}
|
||||
<div class="flex items-center space-x-3">
|
||||
<a data-turbo="false" href="{{ path('app_crm_product_add') }}" class="hidden flex items-center space-x-2 px-6 py-3 bg-blue-600 hover:bg-blue-500 text-white text-[10px] font-black uppercase tracking-[0.2em] rounded-xl transition-all shadow-lg shadow-blue-600/20 group">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M12 4v16m8-8H4" />
|
||||
</svg>
|
||||
<span>Nouvelle Formules</span>
|
||||
</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="backdrop-blur-xl bg-[#1e293b]/40 border border-white/5 rounded-[2.5rem] overflow-hidden shadow-2xl animate-in fade-in duration-700">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-left border-collapse">
|
||||
<thead>
|
||||
<tr class="border-b border-white/5 bg-black/20">
|
||||
<th class="px-6 py-5 text-[10px] font-black text-slate-500 uppercase tracking-[0.2em]">Visuel</th>
|
||||
<th class="px-6 py-5 text-[10px] font-black text-slate-500 uppercase tracking-[0.2em]">Désignation</th>
|
||||
<th class="px-6 py-5 text-[10px] font-black text-slate-500 uppercase tracking-[0.2em] text-center">Tarif</th>
|
||||
<th class="px-6 py-5 text-[10px] font-black text-slate-500 uppercase tracking-[0.2em] text-right">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-white/5">
|
||||
{% for formule in formules %}
|
||||
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="7" class="py-24 text-center">
|
||||
<p class="text-slate-500 italic uppercase tracking-[0.2em] text-[10px] font-black">Aucune formules</p>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# PAGINATION #}
|
||||
{% if formules.getTotalItemCount is defined and formules.getTotalItemCount > formules.getItemNumberPerPage %}
|
||||
<div class="mt-8 flex justify-center custom-pagination">
|
||||
{{ knp_pagination_render(formules) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
<style>
|
||||
.custom-pagination nav ul { @apply flex space-x-2; }
|
||||
.custom-pagination nav ul li span,
|
||||
.custom-pagination nav ul li a {
|
||||
@apply px-4 py-2 rounded-xl bg-[#1e293b]/40 backdrop-blur-md border border-white/5 text-slate-400 text-xs font-bold transition-all;
|
||||
}
|
||||
.custom-pagination nav ul li.active span {
|
||||
@apply bg-blue-600 border-blue-500 text-white shadow-lg shadow-blue-600/20;
|
||||
}
|
||||
.custom-pagination nav ul li a:hover {
|
||||
@apply bg-white/10 text-white border-white/20;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user