✨ feat(templates): Améliore la lisibilité et l'esthétique de l'interface
Ce commit met à jour les couleurs et les styles de texte dans plusieurs
templates pour améliorer la lisibilité et l'esthétique globale de
l'interface utilisateur. Les couleurs de texte secondaires sont
ajustées pour un meilleur contraste.
```
213 lines
16 KiB
Twig
213 lines
16 KiB
Twig
{% extends 'dashboard/base.twig' %}
|
|
|
|
{% block title %}Catalogue Produits{% endblock %}
|
|
{% block title_header %}Gestion du <span class="text-blue-500">Matériel</span>{% endblock %}
|
|
|
|
{% block actions %}
|
|
<div class="flex items-center space-x-3">
|
|
{# LIEN VERS LE CATALOGUE PDF EXISTANT #}
|
|
<a href="/images/Catalogue.pdf" target="_blank" class="flex items-center space-x-2 px-5 py-3 bg-white/5 hover:bg-white/10 text-slate-300 text-[10px] font-black uppercase tracking-[0.2em] rounded-xl transition-all border border-white/10 group">
|
|
<svg class="w-4 h-4 text-rose-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
|
|
</svg>
|
|
<span>Voir le Catalogue PDF</span>
|
|
</a>
|
|
|
|
<a data-turbo="false" href="{{ path('app_crm_product_add') }}" class="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>Nouveau Produit</span>
|
|
</a>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block body %}
|
|
{# SECTION PRODUITS #}
|
|
<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-300 uppercase tracking-[0.2em]">Visuel & Réf</th>
|
|
<th class="px-6 py-5 text-[10px] font-black text-slate-300 uppercase tracking-[0.2em]">Désignation</th>
|
|
<th class="px-6 py-5 text-[10px] font-black text-slate-300 uppercase tracking-[0.2em]">Catégorie</th>
|
|
<th class="px-6 py-5 text-[10px] font-black text-slate-300 uppercase tracking-[0.2em]">Stripe</th>
|
|
<th class="px-6 py-5 text-[10px] font-black text-slate-300 uppercase tracking-[0.2em] text-center">Tarif J1</th>
|
|
<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">
|
|
{% for product in products %}
|
|
<tr class="group hover:bg-white/[0.02] transition-colors">
|
|
<td class="px-6 py-4">
|
|
<div class="flex items-center space-x-4">
|
|
<div class="h-12 w-12 rounded-xl overflow-hidden border border-white/10 bg-slate-900 flex-shrink-0">
|
|
{% if product.imageName %}
|
|
<img src="{{ vich_uploader_asset(product, 'imageFile') | imagine_filter('webp') }}" class="h-full w-full object-cover">
|
|
{% else %}
|
|
<div class="h-full w-full flex items-center justify-center bg-slate-800 text-slate-600">
|
|
<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="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>
|
|
{% endif %}
|
|
</div>
|
|
<span class="text-[10px] font-mono font-bold text-blue-500 tracking-wider">{{ product.ref }}</span>
|
|
</div>
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
<span class="text-sm font-bold text-white group-hover:text-blue-400 transition-colors capitalize">{{ product.name }}</span>
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
<span class="px-3 py-1 bg-white/5 border border-white/10 rounded-lg text-[9px] font-black text-slate-400 uppercase tracking-widest">{{ product.category }}</span>
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
{% if product.productId %}
|
|
<div class="flex items-center text-[8px] font-black text-emerald-400 uppercase tracking-widest">
|
|
<span class="h-1.5 w-1.5 rounded-full bg-emerald-500 mr-2 shadow-[0_0_8px_rgba(16,185,129,0.5)]"></span>
|
|
Synchronisé
|
|
</div>
|
|
{% else %}
|
|
<div class="flex items-center text-[8px] font-black text-rose-500 uppercase tracking-widest opacity-60">
|
|
<span class="h-1.5 w-1.5 rounded-full bg-rose-500 mr-2 animate-pulse"></span>
|
|
En attente
|
|
</div>
|
|
{% endif %}
|
|
</td>
|
|
<td class="px-6 py-4 text-center">
|
|
<span class="text-sm font-black text-emerald-400">{{ product.priceDay|number_format(2, ',', ' ') }}€</span>
|
|
</td>
|
|
<td class="px-6 py-4 text-right">
|
|
<div class="flex items-center justify-end space-x-2">
|
|
<a data-turbo="false" href="{{ path('app_crm_product_edit', {id: product.id}) }}" class="p-2 bg-blue-600/10 hover:bg-blue-600 text-blue-500 hover:text-white rounded-xl transition-all border border-blue-500/20 shadow-lg shadow-blue-600/5">
|
|
<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="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" /></svg>
|
|
</a>
|
|
<a data-turbo="false" href="{{ path('app_crm_product_delete', {id: product.id}) }}?_token={{ csrf_token('delete' ~ product.id) }}" data-turbo-method="post" data-turbo-confirm="Confirmer la suppression ?" class="p-2 bg-rose-500/10 hover:bg-rose-500 text-rose-500 hover:text-white rounded-xl transition-all border border-rose-500/20 shadow-lg shadow-rose-500/5">
|
|
<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="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>
|
|
</a>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{% else %}
|
|
<tr><td colspan="6" class="py-24 text-center italictext-slate-300 text-[10px] font-black uppercase tracking-[0.2em]">Aucun produit</td></tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
{# PAGINATION PRODUITS #}
|
|
{% if products.getTotalItemCount is defined and products.getTotalItemCount > products.getItemNumberPerPage %}
|
|
<div class="mt-8 flex justify-center custom-pagination">{{ knp_pagination_render(products) }}</div>
|
|
{% endif %}
|
|
|
|
{# SECTION OPTIONS #}
|
|
<div class="mt-16 flex items-end justify-between mb-8 pb-6 border-b border-white/5">
|
|
<h2 class="text-4xl font-extrabold text-white">Gestion des <span class="text-blue-500">Options</span></h2>
|
|
<a data-turbo="false" href="{{ path('app_crm_product_options_add') }}" class="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 Option</span>
|
|
</a>
|
|
</div>
|
|
|
|
<div class="backdrop-blur-xl bg-[#1e293b]/40 border border-white/5 rounded-[2.5rem] overflow-hidden shadow-2xl">
|
|
<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-300 uppercase tracking-[0.2em]">Visuel</th>
|
|
<th class="px-6 py-5 text-[10px] font-black text-slate-300 uppercase tracking-[0.2em]">Désignation</th>
|
|
<th class="px-6 py-5 text-[10px] font-black text-slate-300 uppercase tracking-[0.2em]">Stripe</th>
|
|
<th class="px-6 py-5 text-[10px] font-black text-slate-300 uppercase tracking-[0.2em] text-center">Tarif</th>
|
|
<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">
|
|
{% for option in options %}
|
|
<tr class="group hover:bg-white/[0.02] transition-colors">
|
|
<td class="px-6 py-4">
|
|
<div class="h-12 w-12 rounded-xl overflow-hidden border border-white/10 bg-slate-900">
|
|
{% if option.imageName %}
|
|
<img src="{{ vich_uploader_asset(option, 'imageFile') | imagine_filter('webp') }}" class="h-full w-full object-cover">
|
|
{% else %}
|
|
<div class="h-full w-full flex items-center justify-center bg-slate-800 text-slate-600">
|
|
<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="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>
|
|
{% endif %}
|
|
</div>
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
<span class="text-sm font-bold text-white group-hover:text-blue-400 transition-colors capitalize">{{ option.name }}</span>
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
{% if option.stripeId != "" %}
|
|
<div class="flex items-center text-[8px] font-black text-emerald-400 uppercase tracking-widest">
|
|
<span class="h-1.5 w-1.5 rounded-full bg-emerald-500 mr-2"></span> Synchronisé
|
|
</div>
|
|
{% else %}
|
|
<div class="flex items-center text-[8px] font-black text-rose-500 uppercase tracking-widest opacity-60">
|
|
<span class="h-1.5 w-1.5 rounded-full bg-rose-500 mr-2 animate-pulse"></span> En attente
|
|
</div>
|
|
{% endif %}
|
|
</td>
|
|
<td class="px-6 py-4 text-center">
|
|
<span class="text-sm font-black text-emerald-400">{{ option.priceHt|number_format(2, ',', ' ') }}€</span>
|
|
</td>
|
|
<td class="px-6 py-4 text-right">
|
|
<div class="flex items-center justify-end space-x-2">
|
|
<a data-turbo="false" href="{{ path('app_crm_product_options_edit', {id: option.id}) }}" class="p-2 bg-blue-600/10 hover:bg-blue-600 text-blue-500 hover:text-white rounded-xl transition-all border border-blue-500/20"><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="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" /></svg></a>
|
|
<a data-turbo="false" href="{{ path('app_crm_product_option_delete', {id: option.id}) }}?_token={{ csrf_token('delete' ~ option.id) }}" data-turbo-method="post" data-turbo-confirm="Supprimer ?" class="p-2 bg-rose-500/10 hover:bg-rose-500 text-rose-500 hover:text-white rounded-xl transition-all border border-rose-500/20"><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="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></a>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{% else %}
|
|
<tr><td colspan="5" class="py-24 text-center italic text-slate-300 text-[10px] font-black uppercase tracking-[0.2em]">Aucune option</td></tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
{# SECTION MISE À JOUR CATALOGUE PDF (BOT) #}
|
|
<div class="mt-20">
|
|
<div class="mb-6">
|
|
<h3 class="text-2xl font-extrabold text-white flex items-center space-x-3">
|
|
<svg class="w-6 h-6 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
|
</svg>
|
|
<span>Mise à jour du <span class="text-blue-500">catalogue PDF</span></span>
|
|
</h3>
|
|
<p class="text-slate-400 text-xs mt-2 uppercase tracking-widest font-bold">Remplacez le fichier PDF accessible par les clients</p>
|
|
</div>
|
|
|
|
<form data-turbo="false" action="{{ path('app_crm_catalogue_upload') }}" method="POST" enctype="multipart/form-data" class="relative group">
|
|
<div class="flex items-center space-x-4 p-4 bg-[#1e293b]/60 border border-white/10 rounded-2xl hover:border-blue-500/30 transition-all">
|
|
<div class="flex-grow">
|
|
<input type="file" name="catalogue_pdf" accept="application/pdf" required
|
|
class="block w-full text-[10px] text-slate-400 font-bold uppercase tracking-widest
|
|
file:mr-4 file:py-2 file:px-4 file:rounded-lg file:border-0
|
|
file:text-[10px] file:font-black file:uppercase file:tracking-widest
|
|
file:bg-blue-600/20 file:text-blue-400 file:cursor-pointer
|
|
hover:file:bg-blue-600/30 transition-all">
|
|
</div>
|
|
<button type="submit" class="px-6 py-2 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">
|
|
Mettre à jour
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<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 %}
|