```
✨ feat(ReserverController): Ordonne les formules par position 🎨 style(formule/show.twig): Simplifie le texte de tarification ♻️ refactor(FormulesController): Permet de réordonner les formules 🐛 fix(SortableReorder.js): Corrige l'attribut URL de tbody ✨ feat(formules/view.twig): Ajoute un sélecteur de type de formule 🐛 fix(formules.twig): Correction de l'ordre d'affichage 🐛 fix(revervation.twig): Correction de la description SEO ```
This commit is contained in:
@@ -17,8 +17,7 @@ export class SortableReorder extends HTMLTableElement {
|
||||
|
||||
init() {
|
||||
const tbody = this.querySelector('tbody');
|
||||
const url = this.getAttribute('url');
|
||||
|
||||
const url = tbody.getAttribute('url');
|
||||
if (!tbody || !url) {
|
||||
console.warn('SortableReorder: <tbody> ou attribut "url" manquant.');
|
||||
return;
|
||||
|
||||
@@ -33,13 +33,24 @@ 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
|
||||
#[Route(path: '/crm/formules', name: 'app_crm_formules', methods: ['GET','POST'])]
|
||||
public function formules(PaginatorInterface $paginator,EntityManagerInterface $entityManager,AppLogger $appLogger,Request $request,FormulesRepository $formulesRepository): Response
|
||||
{
|
||||
if($request->isMethod('POST')) {
|
||||
$items = $request->getContent();
|
||||
$items = json_decode($items, true)['items'];
|
||||
foreach ($items as $key => $item) {
|
||||
$fv = $formulesRepository->find($item);
|
||||
$fv->setPos($key);
|
||||
$entityManager->persist($fv);
|
||||
}
|
||||
$entityManager->flush();
|
||||
return $this->json([]);
|
||||
}
|
||||
$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),
|
||||
'formules' => $paginator->paginate($formulesRepository->findBy([],['pos'=>'asc']), $request->query->getInt('page', 1), 10),
|
||||
]);
|
||||
}
|
||||
#[Route(path: '/crm/formules/delete/{id}', name: 'app_crm_formules_delete', methods: ['POST', 'GET'])]
|
||||
@@ -116,11 +127,13 @@ class FormulesController extends AbstractController
|
||||
#[Route(path: '/crm/formules/{id}', name: 'app_crm_formules_view', methods: ['GET', 'POST'])]
|
||||
public function formulesView(?Formules $formules,FormulesProductInclusRepository $formulesProductInclusRepository,ProductRepository $productRepository, Request $request, EntityManagerInterface $entityManager, AppLogger $appLogger): Response
|
||||
{
|
||||
|
||||
if (!$formules instanceof Formules) {
|
||||
$this->addFlash('error', 'Formule introuvable.');
|
||||
return $this->redirectToRoute('app_crm_formules');
|
||||
}
|
||||
|
||||
if($request->query->has('type'))
|
||||
$formules->setType($request->get('type',"pack"));
|
||||
// 1. GESTION DU STATUT (Toggle Publish)
|
||||
if ($request->get('act') === 'togglePublish') {
|
||||
$status = $request->get('status') === 'true';
|
||||
|
||||
@@ -151,7 +151,7 @@ class ReserverController extends AbstractController
|
||||
{
|
||||
|
||||
return $this->render('revervation/formules.twig',[
|
||||
'formules' => $formulesRepository->findBy(['isPublish'=>true],['updatedAt' => 'DESC']),
|
||||
'formules' => $formulesRepository->findBy(['isPublish'=>true],['pos' => 'ASC']),
|
||||
'tvaEnabled' => isset($_ENV['TVA_ENABLED']) && $_ENV['TVA_ENABLED'] === "true",
|
||||
|
||||
]);
|
||||
|
||||
@@ -33,9 +33,9 @@
|
||||
<th class="px-6 py-5 text-[10px] font-black text-slate-300 uppercase tracking-[0.2em] text-right">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-white/5">
|
||||
<tbody class="divide-y divide-white/5" url="{{ path('app_crm_formules') }}">
|
||||
{% for formule in formules %}
|
||||
<tr class="group hover:bg-white/[0.02] transition-colors">
|
||||
<tr class="group hover:bg-white/[0.02] transition-colors" data-id="{{ formule.id }}">
|
||||
{# MOVE ICON #}
|
||||
<td class="px-6 py-4 text-center">
|
||||
<div class="cursor-move text-slate-600 group-hover:text-blue-500 transition-colors p-2 rounded-xl hover:bg-blue-500/10 inline-flex">
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
{% block title %}Modifier : {{ formule.name }}{% endblock %}
|
||||
|
||||
{% block actions %}
|
||||
|
||||
<div class="flex items-center space-x-4">
|
||||
{# SYSTÈME DE STATUT TYPE 'ADMIN' ADAPTÉ AUX FORMULES #}
|
||||
<div class="flex items-center">
|
||||
@@ -50,7 +51,12 @@
|
||||
<p class="text-[10px] font-bold text-blue-500 uppercase tracking-[0.3em]">{{ type|default('PACK')|upper }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-full max-w-4xl mb-8 flex flex-col md:flex-row justify-center items-center gap-6">
|
||||
<div class="flex gap-2 p-1 bg-white/5 backdrop-blur-xl border border-white/10 rounded-2xl">
|
||||
<a href="{{ path('app_crm_formules_view',{type:"pack",id:formule.id}) }}" class="px-6 py-2 rounded-xl text-sm font-bold transition-all {% if type == 'pack' %}bg-blue-600 text-white shadow-lg shadow-blue-600/20{% else %}text-slate-400 hover:text-white{% endif %}">Mode Pack</a>
|
||||
<a href="{{ path('app_crm_formules_view',{type:"free",id:formule.id}) }}" class="px-6 py-2 rounded-xl text-sm font-bold transition-all {% if type == 'free' %}bg-blue-600 text-white shadow-lg shadow-blue-600/20{% else %}text-slate-400 hover:text-white{% endif %}">Mode Libre</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full space-y-6">
|
||||
{{ form_start(form, {'attr': {'class': 'space-y-6'}}) }}
|
||||
|
||||
@@ -143,7 +149,7 @@
|
||||
|
||||
{# Badge de rappel du type #}
|
||||
<span class="text-[9px] font-boldtext-slate-300 uppercase px-3 py-1 bg-white/5 rounded-lg border border-white/10 italic">
|
||||
Tarification dégressive
|
||||
Tarification
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
|
||||
{# BOX TARIFS DÉGRESSIFS #}
|
||||
<div class="bg-slate-50 border-4 border-slate-900 rounded-[2.5rem] p-8 mb-8 relative">
|
||||
<div class="absolute -top-4 left-6 bg-white border-2 border-slate-900 px-4 py-1 rounded-full text-[10px] font-black uppercase text-[#f39e36]">Tarification Dégressive</div>
|
||||
<div class="absolute -top-4 left-6 bg-white border-2 border-slate-900 px-4 py-1 rounded-full text-[10px] font-black uppercase text-[#f39e36]">Tarification</div>
|
||||
|
||||
<div class="grid grid-cols-3 gap-4">
|
||||
<div class="text-center">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
{# --- SEO OPTIMISÉ --- #}
|
||||
{% block title %}Nos Formules Location | Packs Gonflables & Événements - Ludik Event{% endblock %}
|
||||
{% block description %}Découvrez nos packs événementiels clés en main. Location de châteaux gonflables, machines gourmandes et animations regroupés dans nos formules exclusives à prix dégressifs.{% endblock %}
|
||||
{% block description %}Découvrez nos packs événementiels clés en main. Location de châteaux gonflables, machines gourmandes et animations regroupés dans nos formules exclusives.{% endblock %}
|
||||
|
||||
{% block breadcrumb_json %}
|
||||
,{
|
||||
@@ -60,7 +60,6 @@
|
||||
{# Tags / Avantages #}
|
||||
<div class="flex flex-wrap gap-2 mt-4">
|
||||
<span class="text-[9px] font-black bg-blue-50 text-blue-600 px-3 py-1 rounded-lg border border-blue-100">Profitez de la livraison offerte dans un rayon de 50 à 70 km autour de Saint-Quentin.</span>
|
||||
<span class="text-[9px] font-black bg-amber-50 text-amber-600 px-3 py-1 rounded-lg border border-amber-100">TARIF DÉGRESSIF</span>
|
||||
</div>
|
||||
|
||||
{# Grille de Tarifs Dégressifs #}
|
||||
|
||||
Reference in New Issue
Block a user