✨ feat(Product.php): Ajoute ProductDoc pour gérer les documents. ✨ feat(Contrats.php): Gère les fichiers du contrat via VichUploader. ✨ feat(templates): Crée template mail signature contrat. ✨ feat(SignatureController): Ajoute la signature du contrat. ✨ feat(ContratsController): Crée contrat depuis devis et liste contrats. ✨ feat(Client): Crée soumission contrat Docuseal. ✨ feat(DevisPdfService): Corrige l'assurance RC Pro. ✨ feat(.env): Ajoute CONTRAT_BASEURL. ✨ feat(ProductDocType): Crée formulaire pour les documents produit. ✨ feat(contrats/list.twig): Liste et actions pour les contrats. ✨ feat(UtmEvent.js): Track click document produit. ✨ feat(ContratEvent.php): Crée event pour envoi contrat. ✨ feat(admin.js): Initialise la recherche dynamique des contrats. ✨ feat(ContratPdfService): Génère le PDF du contrat DocuSeal. ✨ feat(products/add.twig): Ajoute gestion des documents produits. ✨ feat(ContratController): Crée controlleur contrat. ✨ feat(ContratSubscriber.php): Envoi du contrat par email. ✨ feat(reservation/produit.twig): Affiche les documents produit. ✨ feat(ProductController.php): Refactorisation et ajout des documents. ```
123 lines
10 KiB
Twig
123 lines
10 KiB
Twig
{% extends 'dashboard/base.twig' %}
|
|
|
|
{% block title %}Contrats de locations{% endblock %}
|
|
{% block title_header %}Contrats de locations{% endblock %}
|
|
|
|
{% block body %}
|
|
<div class="space-y-6 pb-20">
|
|
|
|
{# --- BARRE DE RECHERCHE --- #}
|
|
<div class="relative group mb-12">
|
|
<div class="absolute inset-y-0 left-0 pl-6 flex items-center pointer-events-none">
|
|
<svg class="w-5 h-5 text-slate-500 group-focus-within:text-blue-500 transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
|
|
</svg>
|
|
</div>
|
|
<input type="text"
|
|
id="searchContrat"
|
|
placeholder="Rechercher un contrat (Nom, N° ou Ville)..."
|
|
class="w-full bg-white/5 border border-white/10 backdrop-blur-xl text-white text-sm rounded-[1.5rem] pl-14 pr-6 py-5 focus:outline-none focus:ring-2 focus:ring-blue-500/50 focus:border-blue-500 transition-all placeholder:text-slate-500 font-medium">
|
|
</div>
|
|
|
|
<div id="contratsList" class="space-y-6">
|
|
{% for contrat in contrats %}
|
|
<div class="contrat-card bg-white/5 border border-white/10 backdrop-blur-md rounded-[2rem] overflow-hidden hover:border-blue-500/40 transition-all group">
|
|
<div class="grid grid-cols-1 lg:grid-cols-12">
|
|
|
|
{# --- COLONNE 1 : NUMÉRO & STATUS --- #}
|
|
<div class="lg:col-span-2 p-8 bg-white/[0.02] flex flex-col justify-center border-r border-white/5">
|
|
<span class="text-[9px] font-black text-blue-500 uppercase tracking-widest mb-2 block text-search">Référence</span>
|
|
<h3 class="text-white font-black italic text-lg tracking-tighter text-search">{{ contrat.numReservation }}</h3>
|
|
<div class="mt-4">
|
|
{% if contrat.isSigned %}
|
|
<span class="px-3 py-1 bg-emerald-500/10 text-emerald-500 text-[8px] font-black uppercase rounded-lg border border-emerald-500/20 inline-flex items-center gap-1">
|
|
<svg class="w-2 h-2" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path></svg>
|
|
Signé
|
|
</span>
|
|
{% else %}
|
|
<span class="px-3 py-1 bg-amber-500/10 text-amber-500 text-[8px] font-black uppercase rounded-lg border border-amber-500/20 inline-flex items-center gap-1">
|
|
<svg class="w-2 h-2" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clip-rule="evenodd"></path></svg>
|
|
En attente
|
|
</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
{# --- COLONNE 2 : CLIENT --- #}
|
|
<div class="lg:col-span-4 p-8 border-r border-white/5">
|
|
<div class="flex items-start gap-4">
|
|
<div class="w-10 h-10 bg-blue-600/10 rounded-xl flex items-center justify-center text-blue-500 shrink-0">
|
|
<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="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path></svg>
|
|
</div>
|
|
<div>
|
|
<span class="text-[9px] font-black text-slate-500 uppercase tracking-widest mb-1 block">Locataire</span>
|
|
<p class="text-white font-bold text-lg uppercase italic text-search">{{ contrat.customer.surname }} {{ contrat.customer.name }}</p>
|
|
<div class="mt-2 space-y-1">
|
|
<p class="text-slate-400 text-xs flex items-center gap-2">
|
|
<svg class="w-3 h-3 text-blue-500/50" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 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"></path></svg>
|
|
{{ contrat.customer.email }}
|
|
</p>
|
|
<p class="text-slate-400 text-xs flex items-center gap-2">
|
|
<svg class="w-3 h-3 text-blue-500/50" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 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"></path></svg>
|
|
{{ contrat.customer.phone }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{# --- COLONNE 3 : ÉVÉNEMENT --- #}
|
|
<div class="lg:col-span-4 p-8 border-r border-white/5">
|
|
<div class="flex items-start gap-4">
|
|
<div class="w-10 h-10 bg-amber-500/10 rounded-xl flex items-center justify-center text-amber-500 shrink-0">
|
|
<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="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><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
|
|
</div>
|
|
<div>
|
|
<span class="text-[9px] font-black text-slate-500 uppercase tracking-widest mb-1 block">Lieu de l'événement</span>
|
|
<p class="text-white font-medium text-sm leading-relaxed">
|
|
{{ contrat.addressEvent }}<br>
|
|
<span class="text-amber-500 font-bold tracking-wider text-search">{{ contrat.zipCodeEvent }}</span>
|
|
<span class="text-white font-black uppercase italic text-search">{{ contrat.townEvent }}</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{# --- COLONNE 4 : ACTIONS (2/12) --- #}
|
|
<div class="lg:col-span-2 p-6 flex flex-row lg:flex-col justify-center gap-2">
|
|
{# VOIR #}
|
|
<a href="{{ path('app_crm_contrats', {id: contrat.id}) }}"
|
|
title="Voir les détails"
|
|
class="flex-1 lg:flex-none py-3 bg-white/5 hover:bg-blue-600 text-white rounded-xl flex items-center justify-center transition-all group/btn border border-white/5 shadow-lg shadow-black/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="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path><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"></path></svg>
|
|
</a>
|
|
|
|
{# TÉLÉCHARGER #}
|
|
<a download="contrat N°{{ contrat.numReservation }}"
|
|
href="{{ vich_uploader_asset(contrat,'devisFile') }}"
|
|
title="Télécharger le PDF"
|
|
class="flex-1 lg:flex-none py-3 bg-white/5 hover:bg-emerald-600 text-white rounded-xl flex items-center justify-center transition-all border border-white/5 shadow-lg shadow-black/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="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"></path></svg>
|
|
</a>
|
|
|
|
{# ENVOYER PAR EMAIL #}
|
|
<a href="{{ path('app_crm_contrats', {idSend: contrat.id}) }}"
|
|
title="Envoyer le contrat au client"
|
|
onclick="return confirm('Souhaitez-vous envoyer ce contrat par email à {{ contrat.customer.email }} ?')"
|
|
class="flex-1 lg:flex-none py-3 bg-white/5 hover:bg-indigo-500 text-white rounded-xl flex items-center justify-center transition-all border border-white/5 shadow-lg shadow-black/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="M12 19l9 2-9-18-9 18 9-2zm0 0v-8"></path>
|
|
</svg>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
|
|
{{ knp_pagination_render(contrats) }}
|
|
|
|
{# --- JS SIMPLE POUR LA RECHERCHE INSTANTANÉE --- #}
|
|
{% endblock %}
|