Files
ludikevent_crm/templates/dashboard/customer/show.twig
Serreau Jovann e644dc4b85 ```
 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.
```
2026-01-29 18:20:22 +01:00

310 lines
20 KiB
Twig

{% extends 'dashboard/base.twig' %}
{% block title %}Modifier le Client{% endblock %}
{% block title_header %}Fiche <span class="text-blue-500">Client</span>{% endblock %}
{% block actions %}
<a data-turbo="false" href="{{ path('app_crm_customer') }}" class="flex items-center px-4 py-2 text-[10px] font-black text-slate-400 hover:text-white uppercase tracking-widest transition-all 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 listing
</a>
{% endblock %}
{% block body %}
<div class="w-full max-w-full mx-auto space-y-8 animate-in fade-in duration-700">
{{ form_start(form) }}
{# HEADER DE LA FICHE #}
<div class="w-full backdrop-blur-xl bg-[#1e293b]/40 border border-white/5 rounded-[2.5rem] p-8 flex flex-col md:flex-row items-center justify-between mb-8 gap-6 shadow-2xl">
<div class="flex items-center space-x-6">
<div class="h-20 w-20 rounded-3xl bg-gradient-to-br from-blue-600 to-indigo-600 flex items-center justify-center text-white text-2xl font-black shadow-2xl ring-4 ring-white/5">
{{ customer.surname|first|upper }}{{ customer.name|first|upper }}
</div>
<div>
<h2 class="text-3xl font-black text-white tracking-tight">
<span class="text-slate-500 text-sm uppercase tracking-[0.2em] block mb-1">Dossier Personnel</span>
{{ customer.surname|upper }} {{ customer.name }}
</h2>
<div class="flex items-center mt-2 space-x-4">
<span class="text-[10px] font-bold text-blue-400 uppercase tracking-widest">ID #{{ customer.id }}</span>
{% if customer.customerId %}
<span class="flex items-center text-[10px] font-bold text-emerald-400 uppercase tracking-widest bg-emerald-500/10 px-2 py-1 rounded-lg border border-emerald-500/20">
<span class="w-1.5 h-1.5 rounded-full bg-emerald-500 mr-2 shadow-[0_0_8px_rgba(16,185,129,0.5)]"></span>
Stripe Sync
</span>
{% endif %}
</div>
</div>
</div>
<button type="submit" class="w-full md:w-auto px-10 py-4 bg-blue-600 hover:bg-blue-500 text-white text-[10px] font-black uppercase tracking-widest rounded-2xl shadow-lg shadow-blue-600/20 transition-all active:scale-95">
Mettre à jour le profil
</button>
</div>
{# GRILLE PRINCIPALE INFOS #}
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<div class="lg:col-span-2 space-y-8">
{# FORMULAIRE COORDONNÉES #}
<div class="backdrop-blur-xl bg-[#1e293b]/40 border border-white/5 rounded-[2.5rem] p-10">
<div class="flex items-center space-x-4 mb-10">
<span class="w-8 h-px bg-blue-500/30"></span>
<span class="text-[10px] font-black text-blue-500 uppercase tracking-[0.3em]">Coordonnées de base</span>
</div>
<div class="space-y-8">
<div class="grid grid-cols-1 md:grid-cols-6 gap-8">
<div class="md:col-span-1">{{ form_row(form.civ) }}</div>
<div class="md:col-span-2">{{ form_row(form.surname) }}</div>
<div class="md:col-span-3">{{ form_row(form.name) }}</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
<div>{{ form_row(form.email) }}</div>
<div>{{ form_row(form.phone) }}</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
<div>{{ form_row(form.type) }}</div>
<div>{{ form_row(form.siret) }}</div>
</div>
</div>
</div>
{# SECTION DOCUMENTS (DEVIS & CONTRATS) #}
<div class="grid grid-cols-1 gap-8">
{# DEVIS #}
<div class="backdrop-blur-xl bg-[#1e293b]/20 border border-white/5 rounded-[2.5rem] p-8">
<h3 class="text-sm font-black text-white uppercase tracking-widest mb-6 flex items-center">
<span class="w-2 h-2 rounded-full bg-blue-500 mr-3"></span>
Devis récents
</h3>
<div class="overflow-x-auto">
<table class="w-full text-left">
<thead>
<tr class="border-b border-white/5">
<th class="pb-4 text-[10px] font-black text-slate-300 uppercase tracking-widest">Numéro</th>
<th class="pb-4 text-[10px] font-black text-slate-300 uppercase tracking-widest text-center">Statut</th>
<th class="pb-4 text-[10px] font-black text-slate-300 uppercase tracking-widest text-right">Montant HT</th>
</tr>
</thead>
<tbody class="divide-y divide-white/5">
{% for devis in customer.devis %}
<tr>
<td class="py-4 text-xs font-bold text-white">
<a target="_blank" href="{{ path('app_crm_devis_edit',{id:devis.id}) }}"> {{ devis.num }}</a>
</td>
<td class="py-4 text-center">
<span class="px-2 py-1 bg-blue-500/10 text-blue-400 rounded-md text-[9px] font-black uppercase tracking-tighter">
{{ devis.state|default('Brouillon') }}
</span>
</td>
<td class="py-4 text-right text-xs font-mono text-slate-300">
{{ devis|totalQuoto|number_format(2, ',', ' ') }}
</td>
</tr>
{% else %}
<tr>
<td colspan="3" class="py-6 text-center text-[10px] font-bold text-slate-600 uppercase">Aucun devis</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{# CONTRATS #}
<div class="backdrop-blur-xl bg-[#1e293b]/20 border border-white/5 rounded-[2.5rem] p-8">
<h3 class="text-sm font-black text-white uppercase tracking-widest mb-6 flex items-center">
<span class="w-2 h-2 rounded-full bg-emerald-500 mr-3"></span>
Contrats & Réservations
</h3>
<div class="overflow-x-auto">
<table class="w-full text-left">
<thead>
<tr class="border-b border-white/5">
<th class="pb-4 text-[10px] font-black text-slate-300 uppercase tracking-widest">Réservation</th>
<th class="pb-4 text-[10px] font-black text-slate-300 uppercase tracking-widest text-right">Total</th>
<th class="pb-4 text-[10px] font-black text-slate-300 uppercase tracking-widest text-right">Réglé</th>
<th class="pb-4 text-[10px] font-black text-slate-300 uppercase tracking-widest text-right">Solde</th>
</tr>
</thead>
<tbody class="divide-y divide-white/5">
{% for contrat in customer.contrats %}
{% set total = contrat|totalContrat %}
{% set paid = contrat|totalPayContrat %}
{% set rest = contrat|totalRestpayContrat %}
<tr class="group hover:bg-white/[0.02] transition-colors">
<td class="py-4 text-xs font-bold text-white">
<a target="_blank" href="{{ path('app_crm_contrats_view',{id:contrat.id}) }}"> {{ contrat.numReservation }}</a>
</td>
<td class="py-4 text-right text-xs font-mono text-slate-400">
{{ total|number_format(2, ',', ' ') }}
</td>
<td class="py-4 text-right text-xs font-mono text-emerald-400">
{{ paid|number_format(2, ',', ' ') }}
</td>
<td class="py-4 text-right text-xs font-mono {{ rest > 0 ? 'text-rose-400' : 'text-emerald-500' }}">
{{ rest|number_format(2, ',', ' ') }}
{% if rest > 0 %}
<div class="text-[8px] font-black uppercase opacity-50 tracking-tighter">En attente</div>
{% else %}
<div class="text-[8px] font-black uppercase opacity-50 tracking-tighter italic">Soldé</div>
{% endif %}
</td>
</tr>
{% else %}
<tr>
<td colspan="4" class="py-6 text-center text-[10px] font-bold text-slate-600 uppercase tracking-widest">Aucun contrat actif</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="space-y-8">
{# CARTE RÉSUMÉ & CHIFFRE D'AFFAIRES #}
<div class="backdrop-blur-xl bg-emerald-500/5 border border-emerald-500/10 rounded-[2.5rem] p-8 shadow-xl">
<h3 class="text-[10px] font-black text-emerald-500 uppercase tracking-widest mb-6 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="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
Résumé financier
</h3>
<div class="space-y-6">
{# CALCUL DU CA GLOBAL (Devis + Contrats) #}
{% set totalCA = 0 %}
{% for c in customer.contrats %}{% set totalCA = totalCA + (c|totalContrat) %}{% endfor %}
<div class="p-6 bg-emerald-500/10 rounded-3xl border border-emerald-500/20">
<span class="text-[9px] font-black text-emerald-500/60 uppercase tracking-widest block mb-1">Total HT généré</span>
<div class="flex items-baseline gap-1">
<span class="text-3xl font-black text-white tracking-tighter">{{ totalCA|number_format(2, ',', ' ') }}</span>
<span class="text-xs font-bold text-emerald-500">€</span>
</div>
<div class="mt-3 grid grid-cols-2 gap-2">
<div class="text-[8px text-slate-300 font-bold uppercase">
{{ customer.devis|length }} Devis
</div>
<div class="text-[8px text-slate-300 font-bold uppercase text-right">
{{ customer.contrats|length }} Contrats
</div>
</div>
</div>
<div class="flex justify-between items-center border-b border-white/5 pb-4">
<span class="text-xs text-slate-400 font-medium">Type Client</span>
<span class="text-[10px] text-white font-black uppercase tracking-widest bg-white/5 px-3 py-1 rounded-full border border-white/5">
{{ customer.type|default('Standard') }}
</span>
</div>
</div>
</div>
{# ZONE SENSIBLE #}
<div class="backdrop-blur-xl bg-rose-500/5 border border-rose-500/10 rounded-[2.5rem] p-8">
<h4 class="text-[10px] font-black text-rose-500 uppercase tracking-widest mb-4">Zone sensible</h4>
<p class="text-[9px] text-slate-300 mb-6 leading-relaxed uppercase font-bold tracking-tight">
La suppression est définitive sur l'intranet et Stripe.
</p>
<a data-turbo="false" href="{{ path('app_crm_customer_delete', {id: customer.id}) }}?_token={{ csrf_token('delete' ~ customer.id) }}"
data-turbo-method="post"
data-turbo-confirm="Confirmer la suppression définitive ?"
class="flex items-center justify-center w-full py-3 border border-rose-500/20 hover:bg-rose-600 text-rose-500 hover:text-white text-[9px] font-black uppercase tracking-widest rounded-xl transition-all shadow-lg shadow-rose-500/5">
Désactiver le client
</a>
</div>
</div>
</div>
{{ form_end(form) }}
{# SECTION ADRESSES #}
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8 mt-12">
{# LISTE DES ADRESSES #}
<div class="lg:col-span-2 space-y-6">
<h3 class="text-lg font-bold text-white mb-6 flex items-center ml-4">
<span class="w-2 h-2 rounded-full bg-blue-500 mr-3"></span>
Carnet d'adresses ({{ customer.customerAddresses|length }})
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
{% for address in customer.customerAddresses %}
<div class="backdrop-blur-xl bg-white/[0.02] border border-white/5 rounded-3xl p-6 hover:border-blue-500/30 transition-all group relative">
<div class="flex items-start justify-between">
<div class="space-y-1">
<p class="text-white text-sm font-bold">{{ address.address }}</p>
{% if address.address2 %}<p class="text-slate-400 text-xs">{{ address.address2 }}</p>{% endif %}
<p class="text-slate-500 text-[11px] font-mono tracking-tighter uppercase">
{{ address.zipcode }} {{ address.city }}{{ address.country }}
</p>
</div>
<div class="flex space-x-2">
<a data-turbo="false" href="{{ path('app_crm_customer_edit', {id: customer.id, idAddr: address.id}) }}" class="p-2 bg-blue-500/10 text-blue-400 rounded-lg hover:bg-blue-500 hover:text-white transition-all">
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"/></svg>
</a>
</div>
</div>
</div>
{% else %}
<div class="col-span-full p-12 text-center border-2 border-dashed border-white/5 rounded-[2.5rem]">
<p class="text-[10px] font-black text-slate-600 uppercase tracking-widest">Aucune adresse enregistrée</p>
</div>
{% endfor %}
</div>
</div>
{# FORMULAIRE D'ADRESSE #}
<div class="lg:col-span-1">
<div class="backdrop-blur-xl bg-[#1e293b]/40 border border-white/10 rounded-[2.5rem] p-8 shadow-2xl sticky top-8">
<div class="mb-8">
<h3 class="text-sm font-black text-white uppercase tracking-widest flex items-center">
<svg class="w-4 h-4 mr-2 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"/></svg>
{{ editingAddress ? 'Modifier l\'adresse' : 'Ajouter une adresse' }}
</h3>
</div>
{{ form_start(formAddress) }}
<div class="space-y-4">
{{ form_row(formAddress.address) }}
{{ form_row(formAddress.address2) }}
{{ form_row(formAddress.address3) }}
<div class="grid grid-cols-2 gap-4">
{{ form_row(formAddress.zipcode) }}
{{ form_row(formAddress.city) }}
</div>
{{ form_row(formAddress.country) }}
<div class="pt-4 flex flex-col gap-3">
<button type="submit" class="w-full py-4 bg-emerald-600 hover:bg-emerald-500 text-white text-[10px] font-black uppercase tracking-widest rounded-2xl shadow-lg shadow-emerald-600/10 transition-all">
{{ editingAddress ? 'Enregistrer les modifications' : 'Ajouter au carnet' }}
</button>
{% if editingAddress %}
<a data-turbo="false" href="{{ path('app_crm_customer_edit', {id: customer.id}) }}" class="text-center py-2 text-[9px] font-black text-slate-300 uppercase tracking-widest hover:text-white transition-colors">
Annuler la modification
</a>
{% endif %}
</div>
</div>
{{ form_end(formAddress) }}
</div>
</div>
</div>
</div>
<style>
label { @apply block text-[10px] font-black text-slate-300 uppercase tracking-[0.2em] mb-2 ml-2; }
input, select, textarea {
@apply w-full bg-slate-900/60 border border-white/5 rounded-2xl px-5 py-3.5 text-xs text-white outline-none focus:border-blue-500/30 focus:bg-slate-900/80 transition-all duration-300 !important;
}
select {
@apply appearance-none cursor-pointer;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%23475569'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 1.25rem center;
background-size: 0.8rem;
}
</style>
{% endblock %}