Files
e-ticket/templates/admin/organizers.html.twig
Serreau Jovann 100ff96c70 Add SIRET/RNA verification, organizer management, registration flow pages
SIRET/RNA verification:
- Create SiretService with API gouv lookup + JOAFE RNA lookup + cache pool (24h)
- Verification page: declared info vs API data side by side
- Display NAF code + label (from naf.json), nature juridique code + label
- Association/Entreprise/EI badges, ESS badge, RNA, coordonnees lat/long
- JOAFE section: objet, regime, domaine, dates, lieu, PDF download link
- Tranche effectif with readable labels
- Refresh cache button
- Page restricted to non-approved organizers only

Organizer approval flow:
- Approval form with offer (free/basic/custom) and commission rate (default 3%)
- Add commissionRate field to User entity + migration
- Rejection form with required reason textarea, sent in email
- Edit page for approved organizers: all fields modifiable
- Modify button in approved organizers table

Registration flow pages:
- Post-registration success page with email verification message
- Organizer gets additional 48h staff review notice
- Post-email-verification page: confirmed for buyers, 48h notice for organizers

Dashboard:
- Simplified Meilisearch sync to single button

Tests: SiretServiceTest (9), AdminControllerTest (31), RegistrationControllerTest updated, UserTest updated

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

101 lines
6.9 KiB
Twig

{% extends 'admin/base.html.twig' %}
{% block title %}Organisateurs{% endblock %}
{% block body %}
<div style="margin-bottom:2rem;">
<h1 class="text-3xl font-black uppercase tracking-tighter italic" style="border-bottom:4px solid #111827;display:inline-block;margin-bottom:0.5rem;">Organisateurs</h1>
<p class="font-bold text-gray-500 italic">{{ organizers.getTotalItemCount }} organisateur{{ organizers.getTotalItemCount > 1 ? 's' : '' }}.</p>
</div>
<div style="border:4px solid #111827;box-shadow:6px 6px 0 rgba(0,0,0,1);background:white;padding:1.5rem;margin-bottom:2rem;">
<h2 class="text-sm font-black uppercase tracking-widest" style="margin-bottom:1rem;">Rechercher</h2>
<form method="get" action="{{ path('app_admin_organizers') }}" style="display:flex;gap:1rem;align-items:flex-end;">
<div style="flex:1;">
<input type="text" name="q" value="{{ query }}"
style="width:100%;padding:0.5rem 0.75rem;border:2px solid #111827;font-weight:700;outline:none;"
placeholder="Rechercher par nom, email, raison sociale, SIRET...">
</div>
<input type="hidden" name="tab" value="{{ tab }}">
<button type="submit" style="padding:0.5rem 1rem;border:2px solid #111827;background:#fabf04;cursor:pointer;white-space:nowrap;" class="font-black uppercase text-xs tracking-widest hover:bg-indigo-600 hover:text-black transition-all">Rechercher</button>
{% if query %}
<a href="{{ path('app_admin_organizers', {tab: tab}) }}" style="padding:0.5rem 1rem;border:2px solid #111827;background:white;white-space:nowrap;" class="font-black uppercase text-xs tracking-widest hover:bg-gray-100 transition-all">Effacer</a>
{% endif %}
</form>
</div>
{% if not query %}
<div style="display:flex;gap:0;margin-bottom:2rem;">
<a href="{{ path('app_admin_organizers', {tab: 'pending'}) }}" style="flex:1;text-align:center;padding:0.75rem;border:3px solid #111827;border-right:none;{{ tab == 'pending' ? 'background:#fabf04;' : 'background:white;' }}" class="font-black uppercase text-sm tracking-widest transition-all">En attente</a>
<a href="{{ path('app_admin_organizers', {tab: 'approved'}) }}" style="flex:1;text-align:center;padding:0.75rem;border:3px solid #111827;{{ tab == 'approved' ? 'background:#fabf04;' : 'background:white;' }}" class="font-black uppercase text-sm tracking-widest transition-all">Valides</a>
</div>
{% endif %}
<div style="border:4px solid #111827;box-shadow:6px 6px 0 rgba(0,0,0,1);background:white;">
<table style="width:100%;border-collapse:collapse;">
<thead>
<tr style="background:#111827;">
<th style="padding:0.75rem 1.5rem;text-align:left;" class="text-[10px] font-black uppercase tracking-widest text-white">Organisateur</th>
<th style="padding:0.75rem 1.5rem;text-align:left;" class="text-[10px] font-black uppercase tracking-widest text-white">Raison sociale</th>
<th style="padding:0.75rem 1.5rem;text-align:left;" class="text-[10px] font-black uppercase tracking-widest text-white">SIRET</th>
<th style="padding:0.75rem 1.5rem;text-align:left;" class="text-[10px] font-black uppercase tracking-widest text-white">Ville</th>
<th style="padding:0.75rem 1.5rem;text-align:left;" class="text-[10px] font-black uppercase tracking-widest text-white">Offre</th>
<th style="padding:0.75rem 1.5rem;text-align:right;" class="text-[10px] font-black uppercase tracking-widest text-white">Actions</th>
</tr>
</thead>
<tbody>
{% for orga in organizers %}
<tr style="border-bottom:1px solid #e5e7eb;" class="hover:bg-gray-50 transition-all">
<td style="padding:0.75rem 1.5rem;">
<p class="font-bold text-sm">{{ orga.firstName }} {{ orga.lastName }}</p>
<p class="text-gray-400 text-xs">{{ orga.email }}</p>
</td>
<td style="padding:0.75rem 1.5rem;" class="text-sm text-gray-600">{{ orga.companyName }}</td>
<td style="padding:0.75rem 1.5rem;" class="text-sm text-gray-600 font-mono">{{ orga.siret }}</td>
<td style="padding:0.75rem 1.5rem;" class="text-sm text-gray-600">{{ orga.postalCode }} {{ orga.city }}</td>
<td style="padding:0.75rem 1.5rem;">
{% if orga.offer %}
<span style="background:#e0e7ff;border:2px solid #111827;padding:0.15rem 0.5rem;" class="text-xs font-black uppercase">{{ orga.offer }}</span>
{% else %}
<span class="text-gray-400 text-xs">—</span>
{% endif %}
</td>
<td style="padding:0.75rem 1.5rem;text-align:right;">
{% if not orga.approved %}
<a href="{{ path('app_admin_siret_check', {id: orga.id}) }}" style="border:2px solid #111827;padding:0.4rem 0.75rem;background:#fabf04;display:inline-block;" class="text-xs font-black uppercase tracking-widest hover:bg-indigo-600 hover:text-black transition-all">Voir la demande</a>
{% else %}
<div style="display:flex;gap:0.5rem;justify-content:flex-end;align-items:center;">
<span style="background:#d1fae5;border:2px solid #111827;padding:0.15rem 0.5rem;" class="text-xs font-black uppercase">{{ orga.offer ?? '—' }}{{ orga.commissionRate ?? '3' }}%</span>
<a href="{{ path('app_admin_edit_organizer', {id: orga.id}) }}" style="border:2px solid #111827;padding:0.4rem 0.75rem;background:white;display:inline-block;" class="text-xs font-black uppercase tracking-widest hover:bg-indigo-600 hover:text-black transition-all">Modifier</a>
</div>
{% endif %}
</td>
</tr>
{% else %}
<tr>
<td colspan="6" style="padding:3rem;text-align:center;" class="text-gray-400 font-bold text-sm">
{% if tab == 'pending' %}
Aucune demande en attente.
{% else %}
Aucun organisateur valide.
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if organizers.getTotalItemCount > 10 %}
<div style="display:flex;justify-content:center;gap:0.5rem;margin-top:1.5rem;">
{% for page in 1..organizers.getPageCount %}
{% if page == organizers.getCurrentPageNumber %}
<span style="border:2px solid #111827;padding:0.4rem 0.75rem;background:#fabf04;" class="text-xs font-black">{{ page }}</span>
{% else %}
<a href="{{ path('app_admin_organizers', {tab: tab, page: page}) }}" style="border:2px solid #111827;padding:0.4rem 0.75rem;background:white;" class="text-xs font-black hover:bg-gray-100 transition-all">{{ page }}</a>
{% endif %}
{% endfor %}
</div>
{% endif %}
{% endblock %}