Files
ludikevent_crm/templates/dashboard/options/add.twig
Serreau Jovann 5ab4b06d7d ```
 feat(Devis.php): Ajoute liaison Options <-> Devis et méthode get/set.

 feat(options/add.twig): Ajoute template création/édition des options.

♻️ refactor(.env): Met à jour les URLs ngrok pour la synchro Stripe.

🐛 fix(StripeCommand.php): Corrige et améliore la synchro Stripe.

 feat(products.twig): Ajoute gestion et affichage des options.

 feat(Client.php): Ajoute gestion des options (CRUD) pour Stripe.

 feat(vich_uploader.yaml): Ajoute configuration pour upload images options.

 feat(ProductController.php): Gère les options (CRUD) dans le contrôleur.

 feat(OptionsType.php): Ajoute formulaire pour la gestion des options.
```
2026-01-22 09:19:04 +01:00

104 lines
6.9 KiB
Twig

{% extends 'dashboard/base.twig' %}
{% block title %}Fiche Option{% endblock %}
{% block title_header %}Gestion des <span class="text-purple-500">Options</span>{% endblock %}
{% block body %}
<div class="max-w-6xl mx-auto animate-in fade-in slide-in-from-bottom-4 duration-700">
{{ form_start(form) }}
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
{# --- BLOC VISUEL (Gauche) --- #}
<div class="lg:col-span-2 space-y-8">
<div class="backdrop-blur-xl bg-[#1e293b]/40 border border-white/5 rounded-[2.5rem] p-8 shadow-2xl">
<h3 class="text-lg font-bold text-white mb-6 flex items-center">
<span class="w-8 h-8 bg-purple-600/20 text-purple-500 rounded-lg flex items-center justify-center mr-3 text-[10px] font-black">00</span>
Image du Produit
</h3>
<div class="flex flex-col md:flex-row items-center gap-8">
<div class="relative flex-shrink-0">
<div class="w-48 h-48 rounded-[2rem] overflow-hidden border-2 border-white/10 bg-slate-900/50 flex items-center justify-center">
{# L'image avec un ID spécifique pour le JS #}
<img id="product-image-preview"
src="{{ options.imageName ? vich_uploader_asset(options, 'imageFile') | imagine_filter('webp') : '#' }}"
class="w-full h-full object-cover {{ options.imageName ? '' : 'hidden' }}">
{# L'icône de remplacement #}
<svg id="product-image-placeholder"
class="w-12 h-12 text-slate-700 {{ options.imageName ? 'hidden' : '' }}"
fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
</div>
</div>
<div class="flex-1 w-full">
{{ form_label(form.imageFile, 'Sélectionner un fichier', {'label_attr': {'class': 'text-[10px] font-black text-slate-500 uppercase tracking-widest mb-2 block'}}) }}
{# On enlève le "onchange" inline, on cible via l'ID généré par Symfony ou un ID fixe #}
{{ form_widget(form.imageFile, {
'id': 'product_image_input',
'attr': {
'class': 'block w-full text-xs text-slate-400 file:mr-4 file:py-2.5 file:px-4 file:rounded-xl file:border-0 file:text-[10px] file:font-black file:uppercase file:tracking-widest file:bg-blue-600/10 file:text-blue-500 hover:file:bg-blue-600/20 transition-all cursor-pointer'
}
}) }}
</div>
</div>
</div>
</div>
{# --- BLOC CONFIGURATION (Droite) --- #}
<div class="lg:col-span-1 space-y-8">
<div class="backdrop-blur-xl bg-slate-900/40 border border-white/5 rounded-[2.5rem] p-8 shadow-2xl">
<h3 class="text-sm font-black text-purple-500 uppercase tracking-widest mb-8 flex items-center">
<span class="w-6 h-6 bg-purple-600/20 rounded-lg flex items-center justify-center mr-3 text-[10px]">01</span>
Détails de l'Option
</h3>
<div class="space-y-8">
{# Nom de l'option #}
<div>
{{ form_label(form.name, 'Nom de l\'option', {'label_attr': {'class': 'text-[10px] font-black text-slate-500 uppercase tracking-[0.2em] ml-1 mb-3 block'}}) }}
{{ form_widget(form.name, {'attr': {'class': 'w-full bg-slate-950/50 border-white/5 rounded-2xl text-white focus:ring-purple-500/20 focus:border-purple-500 transition-all py-4 px-6 text-lg font-bold', 'placeholder': 'ex: Assurance Sérénité, Nettoyage...'}}) }}
</div>
<div class="space-y-6">
<div>
{{ form_label(form.priceHt, 'Prix Ht', {'label_attr': {'class': 'text-[10px] font-black text-slate-500 uppercase tracking-widest ml-1 mb-2 block'}}) }}
<div class="relative">
{{ form_widget(form.priceHt, {'attr': {'class': 'w-full bg-slate-900/50 border-white/5 rounded-2xl text-emerald-400 font-black text-xl focus:ring-emerald-500/20 focus:border-emerald-500 transition-all py-4 px-5'}}) }}
<span class="absolute right-5 top-1/2 -translate-y-1/2 text-slate-600 font-bold">€HT</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{# FOOTER ACTIONS #}
<div class="mt-12 mb-20 flex items-center justify-between backdrop-blur-xl bg-slate-900/40 p-6 rounded-[2.5rem] border border-white/5 shadow-xl">
<a href="{{ path('app_crm_product') }}" class="px-8 py-4 text-[10px] font-black text-slate-400 hover:text-white uppercase tracking-widest transition-colors flex items-center group">
<svg class="w-4 h-4 mr-2 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="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
Annuler
</a>
<button type="submit" class="relative overflow-hidden group px-12 py-5 bg-purple-600 hover:bg-purple-500 text-white text-[10px] font-black uppercase tracking-[0.3em] rounded-2xl transition-all shadow-lg shadow-purple-600/30 flex items-center hover:scale-[1.02] active:scale-95">
<span class="relative z-10 flex items-center">
<svg class="w-4 h-4 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7" />
</svg>
Enregistrer l'option
</span>
<div class="absolute inset-0 bg-gradient-to-r from-transparent via-white/10 to-transparent -translate-x-full group-hover:translate-x-full transition-transform duration-1000"></div>
</button>
</div>
{{ form_end(form) }}
</div>
{% endblock %}