2026-01-16 11:43:28 +01:00
|
|
|
{% extends 'dashboard/base.twig' %}
|
|
|
|
|
|
|
|
|
|
{% block title %}Gestion Clients{% endblock %}
|
|
|
|
|
{% block title_header %}Annuaire <span class="text-blue-500">Clients</span>{% endblock %}
|
|
|
|
|
|
|
|
|
|
{% block actions %}
|
|
|
|
|
<div class="flex items-center space-x-3">
|
|
|
|
|
<a href="{{ path('app_crm_customer_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 Client</span>
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
{% endblock %}
|
|
|
|
|
|
|
|
|
|
{% block body %}
|
|
|
|
|
<div class="w-full backdrop-blur-xl bg-[#1e293b]/40 border border-white/5 rounded-[2.5rem] shadow-2xl overflow-hidden">
|
|
|
|
|
|
|
|
|
|
{# HEADER TABLEAU #}
|
|
|
|
|
<div class="px-8 py-6 border-b border-white/5 bg-white/5 flex items-center justify-between">
|
|
|
|
|
<div>
|
|
|
|
|
<h2 class="text-xl font-bold text-white tracking-tight">Liste des clients</h2>
|
|
|
|
|
<p class="text-[10px] text-slate-500 font-bold uppercase tracking-widest mt-1">Base de données centralisée</p>
|
|
|
|
|
</div>
|
|
|
|
|
<span class="px-4 py-1.5 bg-blue-500/10 text-blue-400 text-[10px] font-black uppercase rounded-lg border border-blue-500/20">
|
|
|
|
|
{{ customers|length }} CONTACTS
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="overflow-x-auto custom-scrollbar">
|
|
|
|
|
<table class="w-full text-left border-collapse">
|
|
|
|
|
<thead>
|
|
|
|
|
<tr class="bg-slate-900/40 border-b border-white/5">
|
|
|
|
|
<th class="px-8 py-5 text-[10px] font-black text-slate-500 uppercase tracking-widest">Identité</th>
|
|
|
|
|
<th class="px-8 py-5 text-[10px] font-black text-slate-500 uppercase tracking-widest text-center">Type</th>
|
|
|
|
|
<th class="px-8 py-5 text-[10px] font-black text-slate-500 uppercase tracking-widest">Coordonnées</th>
|
|
|
|
|
<th class="px-8 py-5 text-[10px] font-black text-slate-500 uppercase tracking-widest">SIRET / ID</th>
|
|
|
|
|
<th class="px-8 py-5 text-[10px] font-black text-slate-500 uppercase tracking-widest text-right">Actions</th>
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody class="divide-y divide-white/5">
|
|
|
|
|
{% for customer in customers %}
|
|
|
|
|
<tr class="hover:bg-white/5 transition-all group">
|
|
|
|
|
|
|
|
|
|
{# 1. IDENTITÉ #}
|
|
|
|
|
<td class="px-8 py-6 whitespace-nowrap">
|
|
|
|
|
<div class="flex items-center">
|
2026-01-16 13:15:42 +01:00
|
|
|
{# Avatar avec initiales #}
|
2026-01-16 11:43:28 +01:00
|
|
|
<div class="h-10 w-10 rounded-xl bg-gradient-to-br from-slate-700 to-slate-800 flex flex-shrink-0 items-center justify-center text-white font-black text-xs border border-white/10 shadow-lg">
|
|
|
|
|
{{ customer.surname|first|upper }}{{ customer.name|first|upper }}
|
|
|
|
|
</div>
|
2026-01-16 13:15:42 +01:00
|
|
|
|
2026-01-16 11:43:28 +01:00
|
|
|
<div class="ml-4">
|
2026-01-16 13:15:42 +01:00
|
|
|
{# Nom et Civilité #}
|
2026-01-16 11:43:28 +01:00
|
|
|
<div class="text-sm font-bold text-white">
|
|
|
|
|
<span class="text-slate-500 text-[10px] uppercase mr-1">{{ customer.civ }}</span>
|
|
|
|
|
{{ customer.surname|upper }} {{ customer.name }}
|
|
|
|
|
</div>
|
2026-01-16 13:15:42 +01:00
|
|
|
|
|
|
|
|
{# ID Interne et État Stripe #}
|
|
|
|
|
<div class="flex items-center mt-1 space-x-2">
|
|
|
|
|
{# Badge ID Interne #}
|
|
|
|
|
<span class="text-[9px] font-bold text-slate-500 tracking-tighter">
|
|
|
|
|
ID: #{{ customer.id }}
|
|
|
|
|
</span>
|
|
|
|
|
|
|
|
|
|
{% if customer.customerId %}
|
|
|
|
|
{# ÉTAT : SYNCHRONISÉ (VERT) #}
|
|
|
|
|
<div class="flex items-center text-[8px] font-black text-emerald-400 uppercase tracking-[0.1em] bg-emerald-500/10 px-2 py-0.5 rounded-md border border-emerald-500/30 shadow-sm shadow-emerald-500/10">
|
|
|
|
|
<span class="flex h-1.5 w-1.5 rounded-full bg-emerald-500 mr-2"></span>
|
|
|
|
|
Stripe synchronisé
|
|
|
|
|
</div>
|
|
|
|
|
{% else %}
|
|
|
|
|
{# ÉTAT : NON SYNCHRONISÉ (ROUGE) #}
|
|
|
|
|
<div class="flex items-center text-[8px] font-black text-rose-500 uppercase tracking-[0.1em] bg-rose-500/10 px-2 py-0.5 rounded-md border border-rose-500/30 shadow-sm shadow-rose-500/10">
|
|
|
|
|
<span class="flex h-1.5 w-1.5 rounded-full bg-rose-500 mr-2 animate-pulse"></span>
|
|
|
|
|
Stripe non synchronisé
|
|
|
|
|
</div>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</div>
|
2026-01-16 11:43:28 +01:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</td>
|
|
|
|
|
|
|
|
|
|
{# 2. TYPE (Badge dynamique) #}
|
|
|
|
|
<td class="px-8 py-6 text-center">
|
|
|
|
|
{% set typeStyles = {
|
|
|
|
|
'company': 'bg-purple-500/10 text-purple-400 border-purple-500/20',
|
|
|
|
|
'personal': 'bg-sky-500/10 text-sky-400 border-sky-500/20',
|
|
|
|
|
'association': 'bg-emerald-500/10 text-emerald-400 border-emerald-500/20',
|
|
|
|
|
'mairie': 'bg-amber-500/10 text-amber-400 border-amber-500/20'
|
|
|
|
|
} %}
|
|
|
|
|
<span class="px-3 py-1 rounded-lg text-[9px] font-black border uppercase tracking-widest {{ typeStyles[customer.type] ?? 'bg-slate-500/10 text-slate-400' }}">
|
|
|
|
|
{{ customer.type|default('Indéfini') }}
|
|
|
|
|
</span>
|
|
|
|
|
</td>
|
|
|
|
|
|
|
|
|
|
{# 3. COORDONNÉES #}
|
|
|
|
|
<td class="px-8 py-6">
|
|
|
|
|
<div class="flex flex-col space-y-1">
|
|
|
|
|
<div class="flex items-center text-slate-300 text-xs">
|
|
|
|
|
<svg class="w-3.5 h-3.5 mr-2 text-slate-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" /></svg>
|
|
|
|
|
{{ customer.email }}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="flex items-center text-slate-400 text-[11px] font-mono">
|
|
|
|
|
<svg class="w-3.5 h-3.5 mr-2 text-slate-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" /></svg>
|
|
|
|
|
{{ customer.phone }}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</td>
|
|
|
|
|
|
|
|
|
|
{# 4. SIRET #}
|
|
|
|
|
<td class="px-8 py-6">
|
|
|
|
|
{% if customer.siret %}
|
|
|
|
|
<div class="text-[10px] font-mono text-slate-500 bg-black/20 px-2 py-1 rounded border border-white/5 inline-block">
|
|
|
|
|
{{ customer.siret }}
|
|
|
|
|
</div>
|
|
|
|
|
{% else %}
|
|
|
|
|
<span class="text-[10px] text-slate-600 italic">N/A</span>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</td>
|
|
|
|
|
|
|
|
|
|
{# 5. ACTIONS #}
|
|
|
|
|
<td class="px-8 py-6 text-right">
|
|
|
|
|
<div class="flex items-center justify-end space-x-2">
|
|
|
|
|
<a href="#" class="p-2 text-slate-400 hover:text-blue-400 hover:bg-blue-400/10 rounded-lg transition-all" title="Modifier">
|
|
|
|
|
<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="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 href="#" class="p-2 text-slate-400 hover:text-white hover:bg-white/10 rounded-lg transition-all" title="Voir fiche">
|
|
|
|
|
<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="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" /></svg>
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
</td>
|
|
|
|
|
|
|
|
|
|
</tr>
|
|
|
|
|
{% else %}
|
|
|
|
|
<tr>
|
|
|
|
|
<td colspan="5" class="px-8 py-20 text-center italic text-slate-500 font-medium">
|
|
|
|
|
Aucun client enregistré dans la base.
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</div>
|
|
|
|
|
{# PAGINATION #}
|
|
|
|
|
<div class="px-8 py-8 bg-black/20 border-t border-white/5">
|
|
|
|
|
<div class="flex flex-col md:flex-row items-center justify-between gap-6">
|
|
|
|
|
<div class="text-[10px] font-black text-slate-500 uppercase tracking-[0.2em]">
|
|
|
|
|
Affichage de {{ customers.getItemNumberPerPage }} clients par page
|
|
|
|
|
</div>
|
|
|
|
|
<div class="navigation custom-pagination">
|
|
|
|
|
{{ knp_pagination_render(customers) }}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div> {# Fin du conteneur principal #}
|
|
|
|
|
|
|
|
|
|
{# CSS pour styliser KnpPagination aux couleurs de ton dashboard #}
|
|
|
|
|
<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-white/5 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 %}
|