```
✨ feat(reservation/contrat): Ajoute la gestion complète des contrats
```
This commit is contained in:
272
templates/reservation/contrat/view.twig
Normal file
272
templates/reservation/contrat/view.twig
Normal file
@@ -0,0 +1,272 @@
|
||||
{% extends 'revervation/base.twig' %}
|
||||
|
||||
{% block title %}Récapitulatif de réservation #{{ contrat.numReservation }}{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="min-h-screen bg-slate-50 py-12 px-4">
|
||||
<div class="max-w-7xl mx-auto">
|
||||
|
||||
{# HEADER : NAVIGATION, TITRE & DATES #}
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-10">
|
||||
<div class="md:col-span-2 flex items-center gap-6">
|
||||
<a href="{{ path('reservation') }}" class="w-12 h-12 bg-white rounded-2xl border border-slate-100 flex items-center justify-center text-slate-400 hover:text-blue-600 transition-all shadow-sm">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/></svg>
|
||||
</a>
|
||||
<div class="flex flex-col md:flex-row md:items-center gap-4 md:gap-8">
|
||||
<div>
|
||||
<h1 class="text-3xl font-black italic uppercase text-slate-900 leading-none">Détails <span class="text-blue-600">Réservation</span></h1>
|
||||
<p class="text-slate-400 text-[10px] font-black uppercase tracking-[0.2em] mt-2">Référence : #{{ contrat.numReservation }}</p>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center bg-white px-6 py-3 rounded-2xl border border-slate-100 shadow-sm gap-6">
|
||||
<div class="text-center">
|
||||
<p class="text-[8px] font-black uppercase text-slate-400 tracking-widest mb-1">Du</p>
|
||||
<p class="text-sm font-black text-slate-900 uppercase italic">{{ contrat.dateAt|date('d/m/Y') }}</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="h-px w-8 bg-blue-200 mb-1"></div>
|
||||
<span class="text-[9px] font-black text-blue-600 uppercase">{{ days }} J</span>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<p class="text-[8px] font-black uppercase text-slate-400 tracking-widest mb-1">Au</p>
|
||||
<p class="text-sm font-black text-slate-900 uppercase italic">{{ contrat.endAt|date('d/m/Y') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-blue-600 rounded-[2rem] p-5 text-white flex items-center gap-4 shadow-lg shadow-blue-200">
|
||||
<div class="w-10 h-10 rounded-xl bg-white/20 flex items-center justify-center 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"/></svg>
|
||||
</div>
|
||||
<div class="overflow-hidden">
|
||||
<p class="text-[9px] font-black uppercase tracking-widest opacity-80 mb-1">Ville de l'événement</p>
|
||||
<p class="font-black uppercase italic text-sm truncate">{{ contrat.townEvent }} ({{ contrat.zipCodeEvent }})</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 lg:grid-cols-5 gap-8 items-start">
|
||||
{# COLONNE GAUCHE #}
|
||||
<div class="lg:col-span-3 space-y-6">
|
||||
|
||||
{# STATUT SIGNATURE #}
|
||||
{% if not contrat.signed %}
|
||||
<div class="bg-amber-50 border border-amber-100 rounded-[2.5rem] p-8 flex items-start gap-6 shadow-sm">
|
||||
<div class="w-14 h-14 bg-white rounded-2xl flex items-center justify-center text-amber-500 shadow-sm shrink-0 border border-amber-100">
|
||||
<svg class="w-8 h-8 animate-pulse" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-amber-900 font-black uppercase italic text-lg leading-tight">Action requise : Signature</h3>
|
||||
<p class="text-amber-700/80 text-sm mt-1 font-medium italic">Veuillez signer le contrat pour activer les options de paiement.</p>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="bg-green-600 rounded-[3rem] p-10 text-white shadow-xl shadow-green-200/50 flex flex-col md:flex-row items-center justify-between gap-6 border-b-8 border-green-700">
|
||||
<div class="flex items-center gap-6">
|
||||
<div class="w-16 h-16 bg-white/20 rounded-2xl flex items-center justify-center shadow-inner">
|
||||
<svg class="w-10 h-10" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-2xl font-black uppercase italic leading-none">Contrat validé</h2>
|
||||
<p class="text-green-100 text-sm font-medium mt-1">Signature enregistrée avec succès.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# TABLEAU PRESTATIONS #}
|
||||
<div class="bg-white rounded-[2.5rem] border border-slate-100 shadow-xl shadow-slate-200/40 overflow-hidden">
|
||||
<div class="p-8 border-b border-slate-50 flex justify-between items-center bg-slate-50/30">
|
||||
<h2 class="text-xs font-black uppercase tracking-widest text-slate-900">Détail des prestations</h2>
|
||||
<span class="bg-blue-600 text-white text-[10px] font-black px-4 py-1.5 rounded-full uppercase">{{ days }} Jours</span>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-left">
|
||||
<tbody class="divide-y divide-slate-50">
|
||||
{% for line in contrat.contratsLines %}
|
||||
{% set priceLine = line.price1DayHt + (line.priceSupDayHt * (days - 1)) %}
|
||||
<tr class="hover:bg-slate-50/30 transition-colors">
|
||||
<td class="px-8 py-6">
|
||||
<p class="font-black text-slate-900 uppercase text-sm leading-tight">{{ line.name }}</p>
|
||||
<p class="text-[10px] text-slate-400 font-bold italic mt-1 uppercase">Caution : {{ line.caution|number_format(0, ',', ' ') }}€</p>
|
||||
</td>
|
||||
<td class="px-8 py-6 text-right font-black text-slate-900 italic text-lg">{{ priceLine|number_format(2, ',', ' ') }}€</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if not contrat.signed %}
|
||||
<div class="space-y-4 pt-4">
|
||||
<a href="{{ signUrl }}" class="group block w-full bg-slate-900 rounded-[2rem] p-8 text-white hover:bg-blue-600 transition-all shadow-xl hover:shadow-blue-200/50 relative overflow-hidden text-center">
|
||||
<h3 class="text-2xl font-black uppercase italic">Signer le contrat</h3>
|
||||
<p class="text-blue-300 text-[10px] font-black uppercase mt-1 tracking-widest">Étape obligatoire avant règlement</p>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{# COLONNE DROITE : FINANCES #}
|
||||
<div class="lg:col-span-2 space-y-6">
|
||||
<div class="bg-white rounded-[2rem] p-10 border border-slate-100 shadow-sm text-center">
|
||||
<p class="text-[10px] font-black text-slate-400 uppercase tracking-widest mb-4">Total Prestations HT</p>
|
||||
<p class="text-5xl font-black text-slate-900 italic tracking-tighter">{{ totalHT|number_format(2, ',', ' ') }}€</p>
|
||||
</div>
|
||||
|
||||
{# --- SECTION ACOMPTE --- #}
|
||||
{% if not contratPaymentPay(contrat, 'accompte') %}
|
||||
<div class="bg-white rounded-[2rem] border border-red-100 shadow-xl shadow-red-100/20 overflow-hidden">
|
||||
<div class="bg-red-500 p-6 text-white flex items-center gap-4">
|
||||
<div class="w-10 h-10 bg-white/20 rounded-xl flex items-center justify-center">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2"></path></svg>
|
||||
</div>
|
||||
<p class="text-sm font-black uppercase italic leading-none">Acompte à régler (25%)</p>
|
||||
</div>
|
||||
<div class="p-8 text-center">
|
||||
<p class="text-4xl font-black text-slate-900 italic tracking-tighter">{{ arrhes|number_format(2, ',', ' ') }}€</p>
|
||||
|
||||
{% if contrat.signed %}
|
||||
<a href="{{ path('gestion_contrat_view', {'num': contrat.numReservation,'act':'accomptePay'}) }}"
|
||||
class="mt-6 inline-flex items-center justify-center gap-4 w-full bg-slate-900 text-white px-8 py-4 rounded-2xl font-black uppercase italic hover:bg-blue-600 transition-all shadow-lg">
|
||||
<span>Payer l'acompte</span>
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M17 8l4 4m0 0l-4 4m4-4H3"></path></svg>
|
||||
</a>
|
||||
{% else %}
|
||||
<p class="mt-4 text-[10px] text-amber-600 font-bold uppercase italic tracking-widest leading-tight">Veuillez signer le contrat<br>pour débloquer le paiement</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="bg-white rounded-[2rem] border border-green-100 shadow-xl shadow-green-100/20 overflow-hidden">
|
||||
<div class="bg-green-500 p-6 text-white flex items-center gap-4">
|
||||
<div class="w-10 h-10 bg-white/20 rounded-xl flex items-center justify-center">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7"></path></svg>
|
||||
</div>
|
||||
<p class="text-sm font-black uppercase italic leading-none">Acompte encaissé</p>
|
||||
</div>
|
||||
<div class="p-6 space-y-4">
|
||||
{% for payment in paymentList %}
|
||||
<div class="flex flex-col gap-3 p-5 bg-slate-50 rounded-[1.5rem] border border-slate-100">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[9px] font-black uppercase text-green-600 bg-green-100 px-2 py-0.5 rounded-full tracking-tighter">Paiement validé</span>
|
||||
<span class="text-[9px] font-medium text-slate-400 italic">{{ payment.validateAt|date('d/m/Y à H:i') }}</span>
|
||||
</div>
|
||||
<div class="space-y-1">
|
||||
<p class="text-[8px] font-black text-slate-400 uppercase tracking-widest">ID Transaction</p>
|
||||
<p class="text-[10px] font-mono font-bold text-slate-600 bg-white px-2 py-1.5 rounded border border-slate-100 select-all">{{ payment.paymentId }}</p>
|
||||
</div>
|
||||
<div class="flex justify-between items-end pt-2 border-t border-slate-200/50">
|
||||
<div>
|
||||
<p class="text-[8px] font-black text-slate-400 uppercase tracking-widest mb-1">Moyen utilisé</p>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-[10px] font-black uppercase text-slate-700 italic">
|
||||
{# Affiche le nom propre (ex: Carte Bancaire, Klarna...) #}
|
||||
{{ payment.card.method_label|default('Paiement Stripe') }}
|
||||
</span>
|
||||
|
||||
{% if payment.card.type == "card" %}
|
||||
<span class="text-[10px] text-slate-400 font-bold uppercase italic">
|
||||
{# Affiche la marque et les 4 chiffres #}
|
||||
({{ payment.card.card.brand|default('') }} **** {{ payment.card.card.last4|default('') }})
|
||||
</span>
|
||||
|
||||
{# Badge optionnel pour le type de débit #}
|
||||
{% if payment.card.card.funding == "debit" %}
|
||||
<span class="text-[7px] bg-slate-100 text-slate-500 px-1 rounded">DEBIT</span>
|
||||
{% endif %}
|
||||
{% if payment.card.card.funding == "credit" %}
|
||||
<span class="text-[7px] bg-slate-100 text-slate-500 px-1 rounded">CREDIT</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-xl font-black text-slate-900 italic leading-none">{{ payment.amount|number_format(2, ',', ' ') }}€</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# --- SECTION CAUTION --- #}
|
||||
{% if contratPaymentPay(contrat, 'accompte') %}
|
||||
{% if not contratPaymentPay(contrat, 'caution') %}
|
||||
<div class="bg-white rounded-[2rem] border border-red-100 shadow-xl shadow-red-100/20 overflow-hidden">
|
||||
<div class="bg-red-500 p-6 text-white flex items-center gap-4">
|
||||
<div class="w-10 h-10 bg-white/20 rounded-xl flex items-center justify-center">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M12 9v2m0 4h.01"></path></svg>
|
||||
</div>
|
||||
<p class="text-sm font-black uppercase italic leading-none">Caution à déposer</p>
|
||||
</div>
|
||||
<div class="p-8 text-center">
|
||||
<p class="text-4xl font-black text-slate-900 italic tracking-tighter">{{ totalCaution|number_format(2, ',', ' ') }}€</p>
|
||||
|
||||
{% set canPayCaution = (date('now') >= contrat.dateAt.modify('-7 days')) %}
|
||||
{% if canPayCaution %}
|
||||
<a href="{{ path('gestion_contrat_view', {'num': contrat.numReservation,'act':'cautionPay'}) }}"
|
||||
class="mt-6 inline-flex items-center justify-center gap-4 w-full bg-slate-900 text-white px-8 py-4 rounded-2xl font-black uppercase italic hover:bg-red-600 transition-all shadow-lg">
|
||||
<span>Déposer la caution</span>
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M17 8l4 4m0 0l-4 4m4-4H3"></path></svg>
|
||||
</a>
|
||||
{% else %}
|
||||
<div class="mt-6 p-4 bg-slate-50 rounded-2xl border border-slate-100">
|
||||
<p class="text-[10px] text-amber-600 font-black uppercase tracking-widest leading-tight">
|
||||
Lien actif le {{ contrat.dateAt.modify('-7 days')|date('d/m/Y') }}
|
||||
</p>
|
||||
<p class="text-[9px] text-slate-400 italic mt-1">(7 jours avant le début)</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="bg-white rounded-[2rem] border border-green-100 shadow-xl shadow-green-100/20 overflow-hidden">
|
||||
<div class="bg-green-500 p-6 text-white flex items-center gap-4">
|
||||
<div class="w-10 h-10 bg-white/20 rounded-xl flex items-center justify-center">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7"></path></svg>
|
||||
</div>
|
||||
<p class="text-sm font-black uppercase italic leading-none">Caution sécurisée</p>
|
||||
</div>
|
||||
<div class="p-6 space-y-4">
|
||||
{% for payment in paymentCaution %}
|
||||
<div class="flex flex-col gap-3 p-5 bg-slate-50 rounded-[1.5rem] border border-slate-100">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-[9px] font-black uppercase text-blue-600 bg-blue-100 px-2 py-0.5 rounded-full tracking-tighter">Empreinte OK</span>
|
||||
<span class="text-[9px] font-medium text-slate-400 italic">{{ payment.validateAt|date('d/m/Y à H:i') }}</span>
|
||||
</div>
|
||||
<div class="space-y-1">
|
||||
<p class="text-[8px] font-black text-slate-400 uppercase tracking-widest">ID Garantie</p>
|
||||
<p class="text-[10px] font-mono font-bold text-slate-600 bg-white px-2 py-1.5 rounded border border-slate-100 select-all">{{ payment.paymentId }}</p>
|
||||
</div>
|
||||
<div class="flex justify-between items-end pt-2 border-t border-slate-200/50">
|
||||
<div>
|
||||
<p class="text-[8px] font-black text-slate-400 uppercase tracking-widest mb-1">Source</p>
|
||||
<span class="text-[10px] font-black uppercase text-slate-700 italic">
|
||||
{{ payment.card.method_label|default('Empreinte CB') }}
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-xl font-black text-slate-900 italic leading-none">{{ payment.amount|number_format(2, ',', ' ') }}€</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{# SOLDE #}
|
||||
<div class="bg-white rounded-[2rem] p-10 border border-slate-100 shadow-sm text-center">
|
||||
<p class="text-xs font-black text-slate-400 uppercase tracking-widest mb-4">Solde restant</p>
|
||||
<p class="text-5xl font-black text-slate-900 italic tracking-tighter">{{ solde|number_format(2, ',', ' ') }}€</p>
|
||||
<div class="mt-4 p-4 bg-slate-50 rounded-2xl">
|
||||
<p class="text-[10px] text-slate-400 font-bold uppercase italic">À régler le jour de la prestation</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user