✨ feat(Formules.php): Ajoute relation OneToOne avec FormulesRestriction. ✨ feat(Dashboard/FormulesController.php): Gère restrictions formules et formulaire. 🎨 refactor(template/formules): Améliore interface configuration restriction formule. 🐛 fix(assets/RepeatLine.js): Corrige réinitialisation TomSelect et selects "Type". ✨ feat(assets/initTomSelect.js): Gère cache options et init TomSelect. ```
153 lines
11 KiB
Twig
153 lines
11 KiB
Twig
{# Définitions de classes conservées #}
|
|
{% set input_class = "w-full bg-slate-900/60 border border-white/10 rounded-2xl px-5 py-4 text-sm text-white outline-none focus:border-blue-500/50 focus:bg-slate-900/90 transition-all duration-300" %}
|
|
{% set label_class = "block text-[10px] font-black text-slate-500 uppercase tracking-[0.2em] mb-3 ml-2" %}
|
|
<form action="{{ path('app_crm_formules_view', {id: formule.id}) }}" method="POST"
|
|
class="w-full backdrop-blur-2xl bg-white/5 border border-white/10 rounded-[2.5rem] p-8 shadow-2xl relative overflow-hidden mt-6">
|
|
<div class="w-full form-repeater" data-component="repeater" is="repeat-line">
|
|
<div class="flex items-center justify-between mb-6 px-4">
|
|
<h4 class="text-sm font-black text-white uppercase tracking-widest">Détail des produits inclus</h4>
|
|
</div>
|
|
|
|
<ol class="form-repeater__rows space-y-4" data-ref="rows">
|
|
{% for key,line in lines %}
|
|
<li class="form-repeater__row group animate-in slide-in-from-right-5 duration-300">
|
|
<fieldset class="backdrop-blur-md bg-white/5 border border-white/10 rounded-[2.5rem] p-8 hover:border-blue-500/30 transition-all shadow-xl">
|
|
{% if line.id is defined %}
|
|
<input type="hidden" name="lines[{{ key }}][id]" value="{{ line.id }}">
|
|
{% endif %}
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-12 gap-5 items-start">
|
|
{# 1. PRODUIT / WYSIWYG #}
|
|
<div class="lg:col-span-11">
|
|
<label class="text-[9px] font-black text-slate-500 uppercase tracking-widest ml-1 mb-2 block">
|
|
Produit / Prestation
|
|
</label>
|
|
<div class="relative flex items-center">
|
|
{# Utilisation de l'input texte standard sans l'attribut 'is' #}
|
|
<input
|
|
readonly
|
|
type="text"
|
|
name="lines[{{ key }}][product]"
|
|
value="{{ line.product }}"
|
|
required
|
|
class="w-full bg-slate-950/50 border border-white/5 rounded-2xl text-white focus:ring-purple-500/20 focus:border-purple-500 transition-all py-3 pl-5 pr-12 text-sm outline-none"
|
|
>
|
|
|
|
{# BOUTON RECHERCHER #}
|
|
<button
|
|
is="search-productformule"
|
|
type="button"
|
|
class="absolute right-2 p-2 bg-purple-500/10 hover:bg-purple-500 text-purple-400 hover:text-white rounded-xl transition-all duration-300 group/search"
|
|
title="Rechercher un produit"
|
|
>
|
|
{# Icône loupe pour un look plus compact #}
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{# 6. SUPPRIMER #}
|
|
<div class="lg:col-span-1 flex justify-center lg:pt-5">
|
|
<button type="button" data-ref="removeButton" class="p-4 bg-red-500/10 hover:bg-red-500 text-red-500 hover:text-white rounded-2xl transition-all duration-300 shadow-lg hover:shadow-red-500/20">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
</li>
|
|
{% endfor %}
|
|
</ol>
|
|
|
|
<div class="mt-6 px-4">
|
|
<button type="button" data-ref="addButton" class="w-full py-4 border-2 border-dashed border-white/10 hover:border-purple-500/50 bg-white/5 hover:bg-purple-500/10 rounded-3xl text-purple-400 text-[10px] font-black uppercase tracking-[0.4em] transition-all flex items-center justify-center space-x-3 group">
|
|
<span class="text-xl group-hover:rotate-90 transition-transform duration-300">+</span>
|
|
<span>Ajouter une prestation</span>
|
|
</button>
|
|
</div>
|
|
<button type="submit" class="mt-2 group w-full py-5 bg-blue-600 hover:bg-blue-500 text-white font-black text-[11px] uppercase tracking-[0.3em] rounded-2xl shadow-xl shadow-blue-600/20 transition-all hover:-translate-y-1 active:scale-[0.98] flex items-center justify-center">
|
|
<span>Sauvegarder les modifications</span>
|
|
<svg class="w-4 h-4 ml-3 transform group-hover:translate-x-1 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</form>
|
|
|
|
<form action="{{ path('app_crm_formules_view', {id: formule.id}) }}" method="POST" class="w-full backdrop-blur-2xl bg-white/5 border border-white/10 rounded-[2.5rem] p-8 shadow-2xl relative overflow-hidden mt-6">
|
|
<div class="w-full form-repeater" data-component="options" is="repeat-line">
|
|
<div class="flex items-center justify-between mb-6 px-4">
|
|
<h4 class="text-sm font-black text-white uppercase tracking-widest">Détail des options inclus</h4>
|
|
</div>
|
|
|
|
<ol class="form-repeater__rows space-y-4" data-ref="rows">
|
|
{% for key,line in option %}
|
|
<li class="form-repeater__row group animate-in slide-in-from-right-5 duration-300">
|
|
<fieldset class="backdrop-blur-md bg-white/5 border border-white/10 rounded-[2.5rem] p-8 hover:border-blue-500/30 transition-all shadow-xl">
|
|
{% if line.id is defined %}
|
|
<input type="hidden" name="option[{{ key }}][id]" value="{{ line.id }}">
|
|
{% endif %}
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-12 gap-5 items-start">
|
|
{# 1. PRODUIT / WYSIWYG #}
|
|
<div class="lg:col-span-11">
|
|
<label class="text-[9px] font-black text-slate-500 uppercase tracking-widest ml-1 mb-2 block">
|
|
Options
|
|
</label>
|
|
<div class="relative flex items-center">
|
|
{# Utilisation de l'input texte standard sans l'attribut 'is' #}
|
|
<input
|
|
type="text"
|
|
name="option[{{ key }}][product]"
|
|
value="{{ line.product }}"
|
|
required
|
|
class="w-full bg-slate-950/50 border border-white/5 rounded-2xl text-white focus:ring-purple-500/20 focus:border-purple-500 transition-all py-3 pl-5 pr-12 text-sm outline-none"
|
|
>
|
|
|
|
{# BOUTON RECHERCHER #}
|
|
<button
|
|
is="search-optionsformule"
|
|
type="button"
|
|
class="absolute right-2 p-2 bg-purple-500/10 hover:bg-purple-500 text-purple-400 hover:text-white rounded-xl transition-all duration-300 group/search"
|
|
title="Rechercher un produit"
|
|
>
|
|
{# Icône loupe pour un look plus compact #}
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{# 6. SUPPRIMER #}
|
|
<div class="lg:col-span-1 flex justify-center lg:pt-5">
|
|
<button type="button" data-ref="removeButton" class="p-4 bg-red-500/10 hover:bg-red-500 text-red-500 hover:text-white rounded-2xl transition-all duration-300 shadow-lg hover:shadow-red-500/20">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
</li>
|
|
{% endfor %}
|
|
</ol>
|
|
|
|
<div class="mt-6 px-4">
|
|
<button type="button" data-ref="addButton" class="w-full py-4 border-2 border-dashed border-white/10 hover:border-purple-500/50 bg-white/5 hover:bg-purple-500/10 rounded-3xl text-purple-400 text-[10px] font-black uppercase tracking-[0.4em] transition-all flex items-center justify-center space-x-3 group">
|
|
<span class="text-xl group-hover:rotate-90 transition-transform duration-300">+</span>
|
|
<span>Ajouter une option</span>
|
|
</button>
|
|
</div>
|
|
<button type="submit" class="mt-2 group w-full py-5 bg-blue-600 hover:bg-blue-500 text-white font-black text-[11px] uppercase tracking-[0.3em] rounded-2xl shadow-xl shadow-blue-600/20 transition-all hover:-translate-y-1 active:scale-[0.98] flex items-center justify-center">
|
|
<span>Sauvegarder les modifications</span>
|
|
<svg class="w-4 h-4 ml-3 transform group-hover:translate-x-1 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</form>
|