Files
e-ticket/templates/order/public.html.twig
Serreau Jovann 52cb19df8b Add BilletOrder entity, PDF generation, email with QR codes, public order page
- BilletOrder entity: individual tickets with unique ETICKET-XXXX reference,
  billetBuyer link, billet link, isScanned, scannedAt for entry control
- BilletOrderService: generates tickets after payment, creates A4 PDF with
  BilletDesign colors if present (default otherwise), real QR code via
  endroid/qr-code, event poster + org logo as base64, sends confirmation
  email with all ticket PDFs attached
- PDF template (pdf/billet.html.twig): A4 layout matching preview design,
  real QR code linking to /ticket/verify/{reference}
- Email template: order recap table, ticket references list, link to
  /ma-commande/{reference}
- Public order page /ma-commande/{reference}: no auth required, shows
  order details, ticket list with individual PDF download links
- Ticket verification page /ticket/verify/{reference}: shows valid/scanned
  status with ticket and event details
- Download route /ma-commande/{ref}/billet/{ticketRef}: generates PDF on-the-fly
- Migration for billet_order table with unique reference index
- BilletOrderTest: 8 tests, 24 assertions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 14:04:45 +01:00

63 lines
3.2 KiB
Twig

{% extends 'base.html.twig' %}
{% block title %}Commande {{ order.reference }} - E-Ticket{% endblock %}
{% block body %}
<div class="page-container">
<h1 class="text-3xl font-black uppercase tracking-tighter italic heading-page">Ma commande</h1>
<p class="font-bold text-gray-600 italic mb-8">{{ order.reference }}{{ order.event.title }}</p>
<div class="flex flex-col lg:flex-row gap-8">
<div class="flex-1">
<div class="card-brutal overflow-hidden mb-6">
<div class="section-header">
<h2 class="text-[10px] font-black uppercase tracking-widest text-white">Informations</h2>
</div>
<div class="p-6 space-y-2">
<p class="text-sm font-bold">{{ order.firstName }} {{ order.lastName }}</p>
<p class="text-sm font-bold text-gray-500">{{ order.email }}</p>
<p class="text-sm font-bold">
{% if order.status == 'paid' %}
<span class="badge-green text-xs font-black uppercase">Payee</span>
{% elseif order.status == 'pending' %}
<span class="badge-yellow text-xs font-black uppercase">En attente</span>
{% else %}
<span class="badge-red text-xs font-black uppercase">Annulee</span>
{% endif %}
</p>
</div>
</div>
{% if tickets|length > 0 %}
<div class="card-brutal overflow-hidden">
<div class="section-header">
<h2 class="text-[10px] font-black uppercase tracking-widest text-white">Vos billets</h2>
</div>
<div class="p-6">
{% for ticket in tickets %}
<div class="flex flex-wrap items-center gap-4 py-3 {{ not loop.last ? 'border-b border-gray-200' : '' }}">
<div class="flex-1 min-w-0">
<p class="font-black uppercase text-sm">{{ ticket.billetName }}</p>
<p class="text-xs font-mono text-gray-400">{{ ticket.reference }}</p>
</div>
<span class="font-black text-sm text-indigo-600">{{ ticket.unitPriceHTDecimal|number_format(2, ',', ' ') }} &euro;</span>
{% if ticket.scanned %}
<span class="badge-yellow text-[10px] font-black uppercase">Scanne</span>
{% endif %}
<a href="{{ path('app_order_download_ticket', {reference: order.reference, ticketReference: ticket.reference}) }}" class="px-3 py-1 border-2 border-gray-900 bg-white text-xs font-black uppercase hover:bg-indigo-600 hover:text-white transition-all" target="_blank">
Telecharger PDF
</a>
</div>
{% endfor %}
</div>
</div>
{% endif %}
</div>
<div class="w-full lg:w-[350px] flex-shrink-0">
{% include 'order/_summary.html.twig' %}
</div>
</div>
</div>
{% endblock %}