Ce commit ajoute la gestion des images pour les produits, l'indexation des produits pour la recherche et la synchronisation avec Stripe. Ajoute un formulaire de création/édition de produits avec gestion de l'image, l'indexation pour la recherche, et la synchronisation des produits avec Stripe. Gère les uploads d'images.
148 lines
11 KiB
Twig
148 lines
11 KiB
Twig
{% extends 'dashboard/base.twig' %}
|
|
|
|
{% block title %}Fiche Produit{% endblock %}
|
|
{% block title_header %}Gestion du <span class="text-blue-500">Matériel</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">
|
|
|
|
{# COLONNE GAUCHE : VISUEL & IDENTITÉ #}
|
|
<div class="lg:col-span-2 space-y-8">
|
|
|
|
{# 00. IMAGE DU PRODUIT #}
|
|
{# SECTION IMAGE #}
|
|
<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="{{ product.imageName ? vich_uploader_asset(product, 'imageFile') | imagine_filter('webp') : '#' }}"
|
|
class="w-full h-full object-cover {{ product.imageName ? '' : 'hidden' }}">
|
|
|
|
{# L'icône de remplacement #}
|
|
<svg id="product-image-placeholder"
|
|
class="w-12 h-12 text-slate-700 {{ product.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>
|
|
{# 01. INFORMATIONS GÉNÉRALES #}
|
|
<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-blue-600/20 text-blue-500 rounded-lg flex items-center justify-center mr-3 text-[10px] font-black">01</span>
|
|
Détails du Catalogue
|
|
</h3>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<div class="md:col-span-2">
|
|
{{ form_label(form.name, 'Désignation Commerciale', {'label_attr': {'class': 'text-[10px] font-black text-slate-500 uppercase tracking-[0.2em] ml-1 mb-2 block'}}) }}
|
|
{{ form_widget(form.name, {'attr': {'placeholder': 'Ex: Château Gonflable Jungle', 'class': 'w-full bg-slate-900/50 border-white/5 rounded-2xl text-white focus:ring-blue-500/20 focus:border-blue-500 transition-all py-3.5 px-5'}}) }}
|
|
</div>
|
|
|
|
<div>
|
|
{{ form_label(form.category, 'Catégorie', {'label_attr': {'class': 'text-[10px] font-black text-slate-500 uppercase tracking-[0.2em] ml-1 mb-2 block'}}) }}
|
|
{{ form_widget(form.category, {'attr': {'class': 'w-full bg-slate-900/50 border-white/5 rounded-2xl text-white focus:ring-blue-500/20 focus:border-blue-500 transition-all py-3.5 px-5'}}) }}
|
|
</div>
|
|
|
|
<div>
|
|
{{ form_label(form.ref, 'Référence Interne (SKU)', {'label_attr': {'class': 'text-[10px] font-black text-slate-500 uppercase tracking-[0.2em] ml-1 mb-2 block'}}) }}
|
|
{{ form_widget(form.ref, {'attr': {'placeholder': 'REF-000', 'class': 'w-full bg-slate-900/50 border-white/5 rounded-2xl text-white font-mono focus:ring-blue-500/20 focus:border-blue-500 transition-all py-3.5 px-5'}}) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{# COLONNE DROITE : TARIFICATION #}
|
|
<div class="lg:col-span-1 space-y-8">
|
|
<div class="backdrop-blur-xl bg-[#1e293b]/40 border border-white/5 rounded-[2.5rem] p-8 shadow-2xl h-full border-l-emerald-500/10 border-l-2">
|
|
<h3 class="text-lg font-bold text-white mb-8 flex items-center">
|
|
<span class="w-8 h-8 bg-emerald-600/20 text-emerald-500 rounded-lg flex items-center justify-center mr-3 text-[10px] font-black">02</span>
|
|
Finances & Tarifs
|
|
</h3>
|
|
|
|
<div class="space-y-8">
|
|
{# INSTALLATION (Montant) #}
|
|
<div class="p-5 bg-white/5 rounded-3xl border border-white/5 relative overflow-hidden group">
|
|
<div class="absolute top-0 right-0 p-2 opacity-10">
|
|
<svg class="w-12 h-12 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
|
|
</div>
|
|
{{ form_label(form.installation, 'Forfait Installation (€)', {'label_attr': {'class': 'text-[9px] font-black text-amber-500 uppercase tracking-widest mb-3 block'}}) }}
|
|
{{ form_widget(form.installation, {'attr': {'class': 'w-full bg-slate-950/50 border-white/10 rounded-xl text-amber-500 font-bold focus:ring-amber-500/20 focus:border-amber-500 transition-all py-3 px-4 text-lg'}}) }}
|
|
<p class="text-[8px] text-slate-500 mt-2 font-bold uppercase italic tracking-tighter">Saisir 0 si inclus dans la loc</p>
|
|
</div>
|
|
|
|
{# PRIX LOCATION #}
|
|
<div class="space-y-6">
|
|
<div>
|
|
{{ form_label(form.priceDay, 'Tarif 1er Jour (€)', {'label_attr': {'class': 'text-[10px] font-black text-slate-500 uppercase tracking-widest ml-1 mb-2 block'}}) }}
|
|
<div class="relative">
|
|
{{ form_widget(form.priceDay, {'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>
|
|
{{ form_label(form.priceSup, 'Tarif Jour Sup. (€)', {'label_attr': {'class': 'text-[10px] font-black text-slate-500 uppercase tracking-widest ml-1 mb-2 block'}}) }}
|
|
<div class="relative">
|
|
{{ form_widget(form.priceSup, {'attr': {'class': 'w-full bg-slate-900/50 border-white/5 rounded-2xl text-blue-400 font-black text-xl focus:ring-blue-500/20 focus:border-blue-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>
|
|
|
|
{# CAUTION #}
|
|
<div class="pt-8 border-t border-white/5">
|
|
{{ form_label(form.caution, 'Montant de la Caution (€)', {'label_attr': {'class': 'text-[10px] font-black text-slate-500 uppercase tracking-widest ml-1 mb-2 block'}}) }}
|
|
<div class="relative">
|
|
{{ form_widget(form.caution, {'attr': {'class': 'w-full bg-slate-900/50 border-white/5 rounded-2xl text-white font-mono focus:ring-blue-500/20 focus:border-blue-500 transition-all py-3 px-5 text-center'}}) }}
|
|
</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-[2rem] border border-white/5 shadow-xl">
|
|
<a href="{{ path('app_crm_product') }}" class="px-8 py-3 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>
|
|
Retour au catalogue
|
|
</a>
|
|
|
|
<button type="submit" class="relative overflow-hidden group px-12 py-4 bg-blue-600 hover:bg-blue-500 text-white text-[10px] font-black uppercase tracking-[0.2em] rounded-2xl transition-all shadow-lg shadow-blue-600/30">
|
|
<span class="relative z-10 flex items-center">
|
|
<svg class="w-4 h-4 mr-2" 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 la fiche
|
|
</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 %}
|