Clean templates, add Caddy dev, Ansible and Gitea config

- Reset templates: clean base.html.twig + new email base template
- Remove old templates (account, legal, security, emails, etc.)
- Add Caddy service to docker-compose-dev
- Add ansible hosts.ini for production deployment
- Add .gitea/CODEOWNERS
- Clean app.scss

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Serreau Jovann
2026-03-18 20:23:16 +01:00
parent 8193930f60
commit 75f8beb119
24 changed files with 40 additions and 842 deletions

0
.gitea/.gitkeep Normal file
View File

1
.gitea/CODEOWNERS Normal file
View File

@@ -0,0 +1 @@
* contact@e-cosplay.fr

View File

@@ -1,94 +1,31 @@
# E-Cosplay Ticket # E-Ticket
Système de billetterie professionnelle pour associations cosplay. Génération, scan et contrôle de tickets pour événements. Plateforme destinée aux associations pour la vente de tickets événementiels, la réservation de tables, l'organisation de brocantes et le vote en ligne.
## Fonctionnalités
- **Génération de tickets** — Création de billets avec QR codes uniques pour chaque participant
- **Scan & Contrôle** — Vérification des tickets par scan QR à l'entrée de l'événement
- **Gestion des événements** — Création et configuration d'événements (date, lieu, capacité, tarifs)
- **Gestion des participants** — Suivi des inscriptions et des présences
- **SEO** — Sitemap XML, métadonnées Open Graph, données structurées (JSON-LD) pour le référencement des événements
- **Notifications** — Envoi des tickets par email avec confirmation de commande
- **Tableau de bord** — Statistiques en temps réel (ventes, entrées, taux de remplissage)
## Stack technique ## Stack technique
| Composant | Technologie | - Symfony 8
|-----------|-------------| - PHP 8.4
| Framework | Symfony 8.0 | - PostgreSQL
| PHP | >= 8.4 | - Redis
| Base de données | PostgreSQL 16 | - Messenger
| ORM | Doctrine 3.6 | - Amazon SES
| Frontend | Twig + Stimulus 3.2 + Turbo | - Cloudflare
| Assets | Asset Mapper (sans build) |
| PDF | Dompdf 3.1 |
| QR Code | endroid/qr-code 6.1 |
| Emails | Symfony Mailer |
| File d'attente | Symfony Messenger + Redis |
| Tests | PHPUnit 13 |
## Prérequis ## Prérequis
- PHP 8.4+ - PHP 8.4+
- PostgreSQL 16
- Redis 7+
- Composer - Composer
- Symfony CLI (recommandé) - Symfony CLI
## Installation ## Installation
```bash ```bash
# Cloner le dépôt
git clone https://github.com/your-org/e-cosplay-ticket.git
cd e-cosplay-ticket
# Installer les dépendances
composer install composer install
```
# Configurer l'environnement ## Lancement
cp .env .env.local
# Éditer .env.local avec vos paramètres (DATABASE_URL, MAILER_DSN, etc.)
# Créer la base de données et exécuter les migrations ```bash
php bin/console doctrine:database:create
php bin/console doctrine:migrations:migrate
# Lancer le serveur de développement
symfony server:start symfony server:start
``` ```
## Docker (développement)
```bash
docker compose up -d
```
Services inclus :
- **PostgreSQL 16** — port 5432
- **Redis 7** — port 6379 (transport Messenger)
- **Mailpit** — port 8025 (interface web pour les emails)
## Structure du projet
```
src/
├── Controller/ # Contrôleurs HTTP
├── Entity/ # Entités Doctrine (Ticket, Event, User…)
└── Repository/ # Repositories Doctrine
templates/ # Templates Twig
assets/ # JS (Stimulus) & CSS
config/ # Configuration Symfony
migrations/ # Migrations Doctrine
tests/ # Tests PHPUnit
```
## Tests
```bash
php bin/phpunit
```
## Licence
Projet privé — Tous droits réservés.

0
ansible/.gitkeep Normal file
View File

5
ansible/hosts.ini Normal file
View File

@@ -0,0 +1,5 @@
[production]
ticket.e-cosplay.fr ansible_user=bot
[production:vars]
deploy_path=/var/www/e-ticket/

View File

@@ -1,30 +1,3 @@
@import "tailwindcss"; @import "tailwindcss";
@import url('https://fonts.googleapis.com/css2?family=Intel+One+Mono:ital,wght@0,300..700;1,300..700&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Intel+One+Mono:ital,wght@0,300..700;1,300..700&display=swap');
.bg-op {
background: rgba(0,0,0,0.5);
backdrop-filter: blur(5px);
}
.epage{
color: orangered;
}
#userMenuDesktop {
margin-top: -4px; /* Remonte légèrement le menu pour toucher le bouton */
padding-top: 10px; /* Ajoute du padding interne pour garder la zone réactive */
}
@media (max-width: 764px) {
.list {
display: block !important;
.listitem{
width: 100% !important;
margin-bottom: 1rem !important;
}
}
}
#join_role {
display: flex;
flex-direction: row;
}

View File

@@ -46,6 +46,17 @@ services:
timeout: 5s timeout: 5s
retries: 5 retries: 5
caddy:
image: caddy:2-alpine
container_name: e-ticket_caddy
ports:
- "8000:80"
volumes:
- ./docker/caddy/Caddyfile:/etc/caddy/Caddyfile
- .:/app
depends_on:
- php
messenger: messenger:
build: build:
context: ./docker/php/dev context: ./docker/php/dev

View File

@@ -1,36 +0,0 @@
{% extends 'base.html.twig' %}
{% block title %}Mon compte - E-Cosplay Ticket{% endblock %}
{% block body %}
<div class="max-w-4xl mx-auto py-20 px-4">
<h1 class="text-5xl font-black uppercase tracking-tighter mb-12">Mon Compte</h1>
<div class="bg-white border-4 border-gray-900 p-8 shadow-[8px_8px_0px_rgba(0,0,0,1)]">
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
<div>
<p class="text-xs font-black uppercase tracking-widest text-gray-400 mb-1">Prénom</p>
<p class="text-2xl font-black">{{ app.user.firstName }}</p>
</div>
<div>
<p class="text-xs font-black uppercase tracking-widest text-gray-400 mb-1">Nom</p>
<p class="text-2xl font-black">{{ app.user.lastName }}</p>
</div>
<div>
<p class="text-xs font-black uppercase tracking-widest text-gray-400 mb-1">Email</p>
<p class="text-2xl font-black">{{ app.user.email }}</p>
</div>
<div>
<p class="text-xs font-black uppercase tracking-widest text-gray-400 mb-1">Membre depuis</p>
<p class="text-2xl font-black">{{ app.user.createdAt|date('d/m/Y') }}</p>
</div>
</div>
<div class="mt-8 pt-8 border-t-4 border-gray-900 flex gap-4">
<a href="{{ path('app_logout') }}" class="bg-red-500 text-white font-black uppercase tracking-widest px-6 py-3 border-4 border-gray-900 shadow-[4px_4px_0px_rgba(0,0,0,1)] hover:shadow-none hover:translate-x-1 hover:translate-y-1 transition-all">
Déconnexion
</a>
</div>
</div>
</div>
{% endblock %}

View File

@@ -1,203 +1,13 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="fr"> <html lang="fr">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}E-Cosplay Ticket{% endblock %}</title> <title>{% block title %}{% endblock %}</title>
<meta name="description" content="{% block meta_description %}Billetterie en ligne pour associations - E-Cosplay{% endblock %}"> {% block stylesheets %}{% endblock %}
<meta name="author" content="Association E-Cosplay"> </head>
<body>
<meta property="og:type" content="website"> {% block body %}{% endblock %}
<meta property="og:url" content="{% block og_url %}{{ app.request.uri }}{% endblock %}"> {% block javascripts %}{% endblock %}
<meta property="og:title" content="{% block og_title %}E-Cosplay Ticket{% endblock %}"> </body>
<meta property="og:description" content="{% block og_description %}Billetterie en ligne pour associations{% endblock %}">
<meta property="og:image" content="{% block og_image %}{{ absolute_url(asset('logo.png')) }}{% endblock %}">
<meta property="og:locale" content="fr_FR">
<meta property="og:site_name" content="E-Cosplay Ticket">
<meta name="twitter:card" content="summary_large_image">
<meta name="robots" content="{% block robots %}index, follow{% endblock %}">
<link rel="canonical" href="{% block canonical %}{{ app.request.uri }}{% endblock %}">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
{{ vite_favicons() }}
{% block stylesheets %}{% endblock %}
{% block javascripts %}
{{ vite_asset('app.js') }}
{% endblock %}
{% block structured_data %}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "E-Cosplay",
"url": "https://www.e-cosplay.fr",
"logo": "{{ absolute_url(asset('logo.png')) }}",
"email": "contact@e-cosplay.fr",
"address": {
"@type": "PostalAddress",
"streetAddress": "42 Rue de Saint-Quentin",
"addressLocality": "Beautor",
"postalCode": "02800",
"addressCountry": "FR"
},
"sameAs": [
"https://www.facebook.com/assocationecosplay",
"https://www.instagram.com/asso_ecosplay/"
]
}
</script>
{% endblock %}
<style>
:root {
--accent-indigo: #4f46e5;
--accent-yellow: #fabf04;
--accent-pink: #ec4899;
--brutal-black: #111827;
--border-width: 4px;
}
</style>
</head>
<body class="flex flex-col min-h-screen font-sans antialiased text-gray-900 bg-[#fbfbfb] italic">
{# ── NAVBAR ── #}
<header class="sticky top-0 z-50 bg-white border-b-4 border-gray-900">
<nav class="mx-auto px-4 lg:px-8">
<div class="flex justify-between items-center h-20">
<div class="flex-shrink-0">
<a href="{{ path('app_home') }}" class="flex items-center group">
<div class="relative p-2 border-2 border-gray-900 shadow-[4px_4px_0px_rgba(0,0,0,1)] group-hover:translate-x-1 group-hover:translate-y-1 group-hover:shadow-none transition-all">
<img class="h-8 w-auto" src="{{ asset('logo.png') }}" alt="E-Cosplay">
</div>
<span class="ml-4 text-2xl font-black uppercase tracking-tighter">E-Cosplay <span class="text-indigo-600">Ticket</span></span>
</a>
</div>
<div class="hidden lg:flex items-center space-x-1">
{% block nav_items %}
<a href="{{ path('app_home') }}" class="px-3 py-2 text-xs font-black uppercase tracking-widest transition-all bg-yellow-400 border-2 border-gray-900 shadow-[2px_2px_0px_rgba(0,0,0,1)]">
Accueil
</a>
{% endblock %}
</div>
<div class="flex items-center space-x-4 border-l-4 border-gray-900 pl-6 h-full">
<div class="relative group">
{% if app.user %}
<a href="{{ path('app_account') }}" class="p-2 border-2 border-gray-900 bg-white text-gray-900 hover:bg-gray-900 hover:text-white transition-all flex items-center justify-center">
<i class="fas fa-user-circle"></i>
</a>
{% else %}
<a href="{{ path('app_login') }}" class="p-2 border-2 border-gray-900 bg-white text-gray-900 hover:bg-gray-900 hover:text-white transition-all flex items-center justify-center">
<i class="fas fa-user-circle"></i>
</a>
{% endif %}
</div>
<button id="mobile-menu-btn" class="lg:hidden p-2 border-2 border-gray-900 bg-yellow-400 font-black">
</button>
</div>
</div>
</nav>
{# ── MOBILE MENU ── #}
<div id="mobile-menu" class="hidden lg:hidden border-t-4 border-gray-900 bg-white">
<div class="p-4 space-y-2 uppercase font-black">
{% block nav_items_mobile %}
<a href="{{ path('app_home') }}" class="block p-3 border-2 border-transparent hover:border-gray-900 hover:bg-gray-50">
Accueil
</a>
{% endblock %}
</div>
</div>
</header>
{# ── FLASH MESSAGES ── #}
{% for type, messages in app.flashes %}
{% for message in messages %}
<div class="mx-auto mt-4 max-w-7xl px-4">
<div class="border-4 border-gray-900 px-6 py-4 font-black shadow-[4px_4px_0px_rgba(0,0,0,1)]
{% if type == 'success' %} bg-green-400
{% elseif type == 'error' %} bg-red-400
{% elseif type == 'warning' %} bg-yellow-400
{% else %} bg-indigo-400 text-white {% endif %}">
{{ message }}
</div>
</div>
{% endfor %}
{% endfor %}
{# ── CONTENT ── #}
<main role="main" class="flex-grow">
{% block body %}{% endblock %}
</main>
{# ── FOOTER ── #}
<footer class="bg-yellow-400 border-t-8 border-gray-900 text-gray-900 mt-auto">
<div class="max-w-7xl mx-auto py-12 px-4 lg:px-8">
<div class="grid grid-cols-1 md:grid-cols-3 gap-12 mb-12 border-b-4 border-gray-900 pb-12">
<div class="space-y-4">
<h3 class="text-3xl font-black uppercase tracking-tighter border-b-4 border-gray-900 inline-block">Nous Contacter</h3>
<p class="font-bold text-lg leading-tight">42 RUE DE SAINT-QUENTIN<br>02800 BEAUTOR, FRANCE</p>
<a href="mailto:contact@e-cosplay.fr" class="inline-block bg-gray-900 text-white px-4 py-2 font-black uppercase text-sm hover:bg-indigo-600 transition-colors">
contact@e-cosplay.fr
</a>
</div>
<div class="space-y-6">
<h3 class="text-3xl font-black uppercase tracking-tighter border-b-4 border-gray-900 inline-block">Nous Suivre</h3>
<div class="flex gap-4">
<a href="https://www.facebook.com/assocationecosplay" target="_blank" class="w-12 h-12 border-4 border-gray-900 flex items-center justify-center hover:bg-white transition-all font-black">f</a>
<a href="https://www.instagram.com/asso_ecosplay/" target="_blank" class="w-12 h-12 border-4 border-gray-900 flex items-center justify-center hover:bg-white transition-all font-black">ig</a>
</div>
</div>
<div class="space-y-4">
<h3 class="text-3xl font-black uppercase tracking-tighter border-b-4 border-gray-900 inline-block">E-Cosplay Ticket</h3>
<p class="font-bold text-gray-800 leading-snug">
Plateforme de billetterie destinée aux associations !
</p>
</div>
</div>
<div class="flex flex-col md:flex-row justify-between items-center gap-6">
<div class="text-center md:text-left">
<p class="font-black uppercase text-sm">&copy; {{ "now"|date("Y") }} E-COSPLAY.</p>
<p class="text-[10px] font-bold opacity-70">RNA N°W022006988</p>
</div>
<div class="flex flex-wrap justify-center gap-3">
{% block footer_links %}
<a href="{{ path('app_mentions_legales') }}" class="text-[10px] font-black uppercase bg-gray-900 text-white px-2 py-1 hover:bg-indigo-600 transition-colors">
Mentions Légales
</a>
<a href="{{ path('app_cgu') }}" class="text-[10px] font-black uppercase bg-gray-900 text-white px-2 py-1 hover:bg-indigo-600 transition-colors">
CGU
</a>
<a href="{{ path('app_cgv') }}" class="text-[10px] font-black uppercase bg-gray-900 text-white px-2 py-1 hover:bg-indigo-600 transition-colors">
CGV
</a>
<a href="{{ path('app_hosting') }}" class="text-[10px] font-black uppercase bg-gray-900 text-white px-2 py-1 hover:bg-indigo-600 transition-colors">
Hébergement
</a>
<a href="{{ path('app_cookies') }}" class="text-[10px] font-black uppercase bg-gray-900 text-white px-2 py-1 hover:bg-indigo-600 transition-colors">
Politique de Cookies
</a>
<a href="{{ path('app_rgpd') }}" class="text-[10px] font-black uppercase bg-gray-900 text-white px-2 py-1 hover:bg-indigo-600 transition-colors">
Politique RGPD
</a>
{% endblock %}
</div>
</div>
</div>
</footer>
<script>
document.getElementById('mobile-menu-btn')?.addEventListener('click', () => {
document.getElementById('mobile-menu')?.classList.toggle('hidden');
});
</script>
</body>
</html> </html>

View File

@@ -1,9 +0,0 @@
{% extends 'emails/base.html.twig' %}
{% block content %}
<h2>Bonjour {{ participant }},</h2>
<p>Votre inscription à <strong>{{ event }}</strong> est confirmée.</p>
<p>Vous recevrez votre ticket avec le QR code par email avant l'événement.</p>
<p>Si vous avez des questions, n'hésitez pas à nous contacter.</p>
<p>À bientôt !</p>
{% endblock %}

View File

@@ -1,14 +0,0 @@
{% extends 'emails/base.html.twig' %}
{% block content %}
<h2>Bonjour {{ participant }},</h2>
<p>Votre ticket pour <strong>{{ event }}</strong> est prêt !</p>
<p>Présentez le QR code ci-dessous à l'entrée de l'événement :</p>
<div class="qr-code">
<img src="{{ qrCode }}" alt="QR Code ticket">
</div>
<p>Conservez bien cet email, il constitue votre preuve d'inscription.</p>
<p>À bientôt !</p>
{% endblock %}

View File

@@ -1,105 +0,0 @@
{% extends 'base.html.twig' %}
{% block title %}Accueil - E-Cosplay Ticket{% endblock %}
{% block meta_description %}Billetterie officielle E-Cosplay. Achetez vos tickets en ligne, recevez votre QR code et présentez-le à l'entrée.{% endblock %}
{% block body %}
{# ── HERO ── #}
<section class="relative min-h-[90vh] flex items-center justify-center bg-white border-b-8 border-gray-900 px-4 pt-20 pb-32">
<div class="absolute inset-0 opacity-[0.03] pointer-events-none select-none overflow-hidden">
<span class="text-[30rem] font-black uppercase leading-none block -rotate-12 translate-y-20">TICKET</span>
</div>
<div class="max-w-7xl mx-auto relative z-10 text-center">
<h1 class="text-6xl md:text-9xl font-black uppercase tracking-tighter leading-[0.85] mb-8">
<span class="block">Plateforme de billetterie</span>
<span class="block text-indigo-600">destinée aux associations !</span>
</h1>
<p class="max-w-2xl mx-auto text-xl md:text-3xl font-bold text-gray-600 mb-12 border-l-8 border-indigo-600 pl-6 text-left md:text-center md:border-l-0 md:pl-0">
Achetez vos tickets en ligne, recevez votre QR code et présentez-le à l'entrée.
</p>
<div class="flex flex-col sm:flex-row justify-center gap-6">
<a href="#events" class="group relative px-10 py-6 bg-indigo-600 text-white font-black uppercase tracking-widest border-4 border-gray-900 shadow-[8px_8px_0px_rgba(0,0,0,1)] hover:shadow-none hover:translate-x-2 hover:translate-y-2 transition-all">
Voir les événements
</a>
</div>
</div>
</section>
{# ── MARQUEE ── #}
<div class="bg-gray-900 py-6 border-b-4 border-indigo-600 overflow-hidden">
<div class="flex whitespace-nowrap animate-marquee">
{% for i in 1..8 %}
<span class="text-white font-black uppercase mx-8 text-2xl opacity-80">
Ticket numérique // Scan QR // Paiement sécurisé // Associations
</span>
{% endfor %}
</div>
</div>
{# ── FEATURES ── #}
<section class="bg-gray-50 py-24 px-4">
<div class="max-w-7xl mx-auto">
<h2 class="text-5xl md:text-7xl font-black uppercase tracking-tighter mb-20 text-center">
Comment ça Marche
</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-12">
<div class="group bg-white border-4 border-gray-900 p-8 shadow-[10px_10px_0px_rgba(0,0,0,1)] hover:shadow-[14px_14px_0px_#4f46e5] transition-all">
<div class="w-16 h-16 bg-indigo-600 text-white flex items-center justify-center mb-8 border-2 border-gray-900 text-3xl group-hover:rotate-12 transition-transform">
🎟️
</div>
<h3 class="text-3xl font-black uppercase tracking-tighter mb-4">Choisissez</h3>
<p class="text-gray-600 font-bold leading-tight">Sélectionnez votre événement et le nombre de tickets souhaités.</p>
</div>
<div class="group bg-white border-4 border-gray-900 p-8 shadow-[10px_10px_0px_rgba(0,0,0,1)] hover:shadow-[14px_14px_0px_#ef4444] transition-all md:translate-y-8">
<div class="w-16 h-16 bg-red-600 text-white flex items-center justify-center mb-8 border-2 border-gray-900 text-3xl group-hover:rotate-12 transition-transform">
💳
</div>
<h3 class="text-3xl font-black uppercase tracking-tighter mb-4">Payez</h3>
<p class="text-gray-600 font-bold leading-tight">Paiement sécurisé par carte bancaire via Stripe.</p>
</div>
<div class="group bg-white border-4 border-gray-900 p-8 shadow-[10px_10px_0px_rgba(0,0,0,1)] hover:shadow-[14px_14px_0px_#eab308] transition-all">
<div class="w-16 h-16 bg-yellow-500 text-white flex items-center justify-center mb-8 border-2 border-gray-900 text-3xl group-hover:rotate-12 transition-transform">
📱
</div>
<h3 class="text-3xl font-black uppercase tracking-tighter mb-4">Scannez</h3>
<p class="text-gray-600 font-bold leading-tight">Recevez votre QR code par email signé et présentez-le à l'entrée.</p>
</div>
</div>
</div>
</section>
{# ── EVENTS ── #}
<section id="events" class="bg-white py-24 px-4 border-t-4 border-gray-900">
<div class="max-w-7xl mx-auto">
<div class="flex flex-col md:flex-row justify-between items-end mb-16 gap-6">
<div>
<p class="text-indigo-600 font-black uppercase tracking-[0.3em] mb-4">// Prochainement</p>
<h2 class="text-5xl md:text-7xl font-black uppercase tracking-tighter leading-none">
Événements à Venir
</h2>
</div>
</div>
<div class="border-4 border-dashed border-gray-300 p-16 text-center">
<p class="text-2xl font-black text-gray-300 uppercase">Aucun événement pour le moment</p>
</div>
</div>
</section>
<style>
@keyframes marquee {
0% { transform: translateX(0); }
100% { transform: translateX(-50%); }
}
.animate-marquee {
display: flex;
width: 200%;
animation: marquee 40s linear infinite;
}
</style>
{% endblock %}

View File

@@ -1,12 +0,0 @@
{% extends 'base.html.twig' %}
{% block body %}
<div class="max-w-4xl mx-auto py-16 px-4">
<h1 class="text-5xl md:text-7xl font-black uppercase tracking-tighter mb-12 leading-none">
{% block legal_title %}{% endblock %}
</h1>
<div class="bg-white border-4 border-gray-900 p-8 md:p-12 shadow-[8px_8px_0px_rgba(0,0,0,1)] space-y-6 font-bold text-gray-700 leading-relaxed not-italic">
{% block legal_content %}{% endblock %}
</div>
</div>
{% endblock %}

View File

@@ -1,18 +0,0 @@
{% extends 'legal/_layout.html.twig' %}
{% block title %}CGU - E-Cosplay Ticket{% endblock %}
{% block legal_title %}Conditions Générales d'Utilisation{% endblock %}
{% block legal_content %}
<h2 class="text-2xl font-black uppercase text-gray-900">Article 1 — Objet et Promotion du Site</h2>
<p>E-Cosplay Ticket est une plateforme de billetterie en ligne destinée aux associations, proposée à tarifs réduits. Les présentes CGU régissent l'utilisation de cette plateforme, éditée par l'association E-Cosplay.</p>
<h2 class="text-2xl font-black uppercase text-gray-900 mt-8">Article 2 — Accès au service</h2>
<p>La plateforme est accessible gratuitement à tout utilisateur disposant d'un accès internet. L'achat de tickets nécessite la création d'un compte.</p>
<h2 class="text-2xl font-black uppercase text-gray-900 mt-8">Article 3 — Responsabilités</h2>
<p>L'association E-Cosplay s'efforce d'assurer la disponibilité du service mais ne saurait être tenue responsable en cas d'interruption temporaire.</p>
<h2 class="text-2xl font-black uppercase text-gray-900 mt-8">Article 4 — Données personnelles</h2>
<p>Voir notre <a href="{{ path('app_rgpd') }}" class="text-indigo-600 underline font-black">Politique RGPD</a>.</p>
{% endblock %}

View File

@@ -1,18 +0,0 @@
{% extends 'legal/_layout.html.twig' %}
{% block title %}CGV - E-Cosplay Ticket{% endblock %}
{% block legal_title %}Conditions Générales de Vente{% endblock %}
{% block legal_content %}
<h2 class="text-2xl font-black uppercase text-gray-900">Article 1 — Objet</h2>
<p>Les présentes CGV régissent la vente de tickets pour les événements organisés par l'association E-Cosplay via la plateforme E-Cosplay Ticket.</p>
<h2 class="text-2xl font-black uppercase text-gray-900 mt-8">Article 2 — Prix et paiement</h2>
<p>Les prix sont indiqués en euros TTC. Le paiement est effectué en ligne par carte bancaire via la plateforme sécurisée Stripe.</p>
<h2 class="text-2xl font-black uppercase text-gray-900 mt-8">Article 3 — Tickets</h2>
<p>Après paiement, un ticket numérique avec QR code unique est envoyé par email. Ce ticket est nominatif et non cessible sauf accord de l'organisateur.</p>
<h2 class="text-2xl font-black uppercase text-gray-900 mt-8">Article 4 — Annulation et remboursement</h2>
<p>Toute demande d'annulation doit être adressée à contact@e-cosplay.fr. Les remboursements sont étudiés au cas par cas selon les conditions de l'événement.</p>
{% endblock %}

View File

@@ -1,18 +0,0 @@
{% extends 'legal/_layout.html.twig' %}
{% block title %}Politique de Cookies - E-Cosplay Ticket{% endblock %}
{% block legal_title %}Politique de Cookies{% endblock %}
{% block legal_content %}
<h2 class="text-2xl font-black uppercase text-gray-900">Qu'est-ce qu'un cookie ?</h2>
<p>Un cookie est un petit fichier texte déposé sur votre navigateur lors de votre visite. Il permet de mémoriser vos préférences et d'assurer le bon fonctionnement du site.</p>
<h2 class="text-2xl font-black uppercase text-gray-900 mt-8">Cookies utilisés</h2>
<ul class="list-disc pl-6 space-y-2">
<li><strong>Cookies essentiels :</strong> session utilisateur, jeton CSRF (sécurité des formulaires).</li>
<li><strong>Cookies de performance :</strong> mesure d'audience anonymisée.</li>
</ul>
<h2 class="text-2xl font-black uppercase text-gray-900 mt-8">Gestion des cookies</h2>
<p>Vous pouvez configurer votre navigateur pour refuser les cookies. La désactivation des cookies essentiels peut affecter le fonctionnement du site.</p>
{% endblock %}

View File

@@ -1,14 +0,0 @@
{% extends 'legal/_layout.html.twig' %}
{% block title %}Hébergement - E-Cosplay Ticket{% endblock %}
{% block legal_title %}Hébergement{% endblock %}
{% block legal_content %}
<h2 class="text-2xl font-black uppercase text-gray-900">Hébergeur du site</h2>
<p>Ce site est hébergé par :<br>
SARL SITECONSEIL<br>
<a href="https://www.siteconseil.fr" target="_blank" class="text-indigo-600 underline font-black">www.siteconseil.fr</a></p>
<h2 class="text-2xl font-black uppercase text-gray-900 mt-8">Infrastructure</h2>
<p>Les serveurs sont situés en France et conformes aux exigences du RGPD en matière de protection des données personnelles.</p>
{% endblock %}

View File

@@ -1,151 +0,0 @@
{% extends 'base.html.twig' %}
{% block title %}Mentions Légales - E-Cosplay Ticket{% endblock %}
{% block meta_description %}Mentions Légales de la plateforme E-Cosplay Ticket{% endblock %}
{% block structured_data %}
{{ parent() }}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{ "@type": "ListItem", "position": 1, "name": "Accueil", "item": "{{ url('app_home') }}" },
{ "@type": "ListItem", "position": 2, "name": "Mentions Légales", "item": "{{ url('app_mentions_legales') }}" }
]
}
</script>
{% endblock %}
{% block body %}
<div class="max-w-6xl mx-auto px-4 py-12 text-gray-800">
{# ── Header ── #}
<header class="mb-20 relative py-10">
<div class="relative z-10">
<h1 class="text-5xl md:text-7xl font-black text-gray-900 tracking-tighter uppercase italic leading-none">
Mentions Légales
</h1>
<div class="mt-4 flex items-center gap-2">
<div class="h-2 w-24 bg-yellow-500 skew-x-[-20deg]"></div>
<div class="h-2 w-12 bg-gray-900 skew-x-[-20deg]"></div>
</div>
</div>
<div class="absolute top-0 right-0 -mr-8 opacity-[0.03] pointer-events-none select-none hidden md:block">
<span class="text-[10rem] font-black italic uppercase tracking-tighter leading-none">LEGAL</span>
</div>
</header>
<div class="space-y-20">
{# ── 1. Objet ── #}
<section class="relative">
<div class="inline-block bg-[#0f172a] text-yellow-500 px-6 py-3 font-black italic skew-x-[-15deg] mb-6 shadow-xl border-b-2 border-yellow-600">
<span class="skew-x-[15deg] block uppercase tracking-wider text-lg">// 1. Objet et Promotion du Site</span>
</div>
<div class="bg-white border-2 border-gray-900 p-8 rounded-lg shadow-[8px_8px_0px_rgba(0,0,0,1)] italic">
<p class="mb-4 text-gray-900 font-bold">E-Cosplay Ticket est une plateforme de billetterie en ligne destinée aux associations, proposée à tarifs réduits. Elle a pour objectif de faciliter la gestion, la génération et le contrôle de tickets pour les événements associatifs.</p>
<ul class="space-y-2 text-sm text-gray-600">
<li class="flex items-center gap-2"><span class="text-yellow-500 font-black">/</span> La génération de tickets numériques avec QR code unique.</li>
<li class="flex items-center gap-2"><span class="text-yellow-500 font-black">/</span> Le scan et le contrôle d'accès aux événements.</li>
<li class="flex items-center gap-2"><span class="text-yellow-500 font-black">/</span> Le paiement sécurisé via Stripe.</li>
</ul>
</div>
</section>
{# ── 2. Éditeur ── #}
<section class="relative">
<div class="inline-block bg-[#0f172a] text-yellow-500 px-6 py-3 font-black italic skew-x-[-15deg] mb-6 shadow-xl border-b-2 border-yellow-600">
<span class="skew-x-[15deg] block uppercase tracking-wider text-lg">// 2. Identification de l'Éditeur du Site</span>
</div>
<div class="bg-gray-900 text-white p-8 rounded-lg border-r-8 border-yellow-500 shadow-xl italic grid grid-cols-1 md:grid-cols-2 gap-8">
<div class="space-y-2 text-sm">
<p><strong class="text-yellow-500 uppercase tracking-widest text-xs">Nom de l'Association :</strong> E-Cosplay</p>
<p><strong class="text-yellow-500 uppercase tracking-widest text-xs">Numéro RNA :</strong> W022006988</p>
<p><strong class="text-yellow-500 uppercase tracking-widest text-xs">SIREN :</strong> 943121517</p>
<p><strong class="text-yellow-500 uppercase tracking-widest text-xs">Adresse du siège social :</strong> 42 rue de Saint-Quentin, 02800 Beautor</p>
</div>
<div class="flex flex-col justify-center items-start md:items-end">
<p class="mb-2"><strong class="text-yellow-500 uppercase tracking-widest text-xs">Directeur de la publication :</strong></p>
<span class="text-xl font-black uppercase text-white">Serreau Jovann</span>
<p class="text-xs text-gray-400 mt-1">Directeur en charge de la gestion de la billetterie</p>
<a href="mailto:contact@e-cosplay.fr" class="text-yellow-500 font-bold hover:underline mt-2">contact@e-cosplay.fr</a>
</div>
</div>
</section>
{# ── 3 & 4 ── #}
<div class="grid grid-cols-1 md:grid-cols-2 gap-12">
<section>
<div class="inline-block bg-[#0f172a] text-yellow-500 px-6 py-2 font-black italic skew-x-[-15deg] mb-6 shadow-lg border-b-2 border-yellow-600">
<span class="skew-x-[15deg] block uppercase text-sm">// 3. Hébergement du Site</span>
</div>
<div class="bg-white border-2 border-gray-900 p-6 rounded-lg shadow-[6px_6px_0px_rgba(0,0,0,1)] italic text-sm">
<p class="font-black text-gray-900 uppercase mb-2">Google Cloud Platform</p>
<p class="text-gray-600">1600 Amphitheatre Parkway, Mountain View, CA 94043, États-Unis (Siège social)</p>
<p class="mt-4 text-[10px] font-mono bg-gray-100 p-2">Google Cloud Netherlands B.V., O'Mahony's Corner, Block R, Spencer Dock, Dublin 1, Irlande.</p>
</div>
</section>
<section>
<div class="inline-block bg-[#0f172a] text-yellow-500 px-6 py-2 font-black italic skew-x-[-15deg] mb-6 shadow-lg border-b-2 border-yellow-600">
<span class="skew-x-[15deg] block uppercase text-sm">// 4. Propriété Intellectuelle et Droit à l'Image</span>
</div>
<div class="bg-white border-2 border-gray-900 p-6 rounded-lg shadow-[6px_6px_0px_rgba(0,0,0,1)] italic text-sm">
<p class="text-gray-700 leading-tight mb-2">L'association E-Cosplay est propriétaire des droits de propriété intellectuelle ou détient les droits d'usage sur tous les éléments accessibles sur le site.</p>
<p class="font-bold text-red-600 uppercase text-xs tracking-tighter">Toute reproduction, représentation, modification, publication, adaptation de tout ou partie des éléments du site, quel que soit le moyen ou le procédé utilisé, est interdite, sauf autorisation écrite préalable de l'association E-Cosplay.</p>
</div>
</section>
</div>
{# ── 5. RGPD ── #}
<section class="relative">
<div class="inline-block bg-[#0f172a] text-yellow-500 px-6 py-3 font-black italic skew-x-[-15deg] mb-6 shadow-xl border-b-2 border-yellow-600">
<span class="skew-x-[15deg] block uppercase tracking-wider text-lg">// 5. Protection des Données Personnelles (RGPD)</span>
</div>
<div class="bg-white border-2 border-gray-900 p-8 rounded-lg shadow-[8px_8px_0px_rgba(0,0,0,1)] grid grid-cols-1 md:grid-cols-2 gap-8 italic">
<div>
<p class="text-sm text-gray-600 mb-4">Conformément au Règlement Général sur la Protection des Données (RGPD), l'association E-Cosplay s'engage à protéger la confidentialité des données personnelles collectées. Pour toute information ou exercice de vos droits Informatique et Libertés sur les traitements de données personnelles, vous pouvez contacter notre Délégué à la Protection des Données (DPO).</p>
<a href="mailto:rgpd@e-cosplay.fr" class="inline-block bg-yellow-500 text-gray-900 px-6 py-2 font-black uppercase text-xs skew-x-[-10deg]">
<span class="skew-x-[10deg] block">Contact DPO</span>
</a>
</div>
<div class="bg-gray-50 p-6 border-l-4 border-indigo-600">
<p class="text-xs font-black uppercase text-indigo-600 mb-2 tracking-widest">Identifiant DPO</p>
<p class="text-xl font-black text-gray-900">DPO-167945</p>
</div>
</div>
</section>
{# ── 6 & 7 ── #}
<div class="grid grid-cols-1 md:grid-cols-2 gap-12">
<section>
<div class="inline-block bg-[#0f172a] text-yellow-500 px-6 py-2 font-black italic skew-x-[-15deg] mb-6 shadow-lg border-b-2 border-yellow-600">
<span class="skew-x-[15deg] block uppercase text-sm">// 6. Partenariats et Publicité</span>
</div>
<div class="bg-white border-2 border-gray-900 p-6 rounded-lg shadow-[6px_6px_0px_rgba(0,0,0,1)] italic text-sm text-gray-600">
La présence de partenaires sur le site internet de l'association E-Cosplay est le fruit d'une collaboration formalisée.
</div>
</section>
<section>
<div class="inline-block bg-[#0f172a] text-yellow-500 px-6 py-2 font-black italic skew-x-[-15deg] mb-6 shadow-lg border-b-2 border-yellow-600">
<span class="skew-x-[15deg] block uppercase text-sm">// 7. Limitations de Responsabilité</span>
</div>
<div class="bg-white border-2 border-gray-900 p-6 rounded-lg shadow-[6px_6px_0px_rgba(0,0,0,1)] italic text-sm text-gray-600">
L'association E-Cosplay ne pourra être tenue responsable des dommages directs et indirects causés au matériel de l'utilisateur, lors de l'accès au site, et résultant soit de l'utilisation d'un matériel ne répondant pas aux spécifications indiquées au point 4, soit de l'apparition d'un bug ou d'une incompatibilité.
</div>
</section>
</div>
{# ── 8. Droit applicable ── #}
<section class="relative">
<div class="bg-gray-900 text-white p-8 rounded-lg border-b-8 border-red-600 shadow-xl italic text-center">
<h2 class="text-red-500 font-black uppercase tracking-widest mb-4">// 8. Droit applicable et attribution de juridiction</h2>
<p class="text-sm font-bold">Tout litige en relation avec l'utilisation du site E-Cosplay Ticket est soumis au droit français. Il est fait attribution exclusive de juridiction aux tribunaux compétents de Laon.</p>
</div>
</section>
</div>
</div>
{% endblock %}

View File

@@ -1,30 +0,0 @@
{% extends 'legal/_layout.html.twig' %}
{% block title %}Politique RGPD - E-Cosplay Ticket{% endblock %}
{% block legal_title %}Politique RGPD{% endblock %}
{% block legal_content %}
<h2 class="text-2xl font-black uppercase text-gray-900">Responsable du traitement</h2>
<p>Association E-Cosplay<br>
42 Rue de Saint-Quentin, 02800 Beautor, France<br>
Email : contact@e-cosplay.fr</p>
<h2 class="text-2xl font-black uppercase text-gray-900 mt-8">Données collectées</h2>
<ul class="list-disc pl-6 space-y-2">
<li>Nom, prénom, adresse email (inscription et achat de tickets).</li>
<li>Données de paiement (traitées par Stripe, non stockées sur nos serveurs).</li>
<li>Données de connexion (adresse IP, logs).</li>
</ul>
<h2 class="text-2xl font-black uppercase text-gray-900 mt-8">Finalité du traitement</h2>
<p>Les données sont collectées pour la gestion des inscriptions, la délivrance des tickets, l'envoi de communications liées aux événements et le respect de nos obligations légales.</p>
<h2 class="text-2xl font-black uppercase text-gray-900 mt-8">Durée de conservation</h2>
<p>Les données sont conservées pendant la durée nécessaire aux finalités du traitement, puis supprimées conformément à la réglementation en vigueur.</p>
<h2 class="text-2xl font-black uppercase text-gray-900 mt-8">Vos droits</h2>
<p>Conformément au RGPD, vous disposez d'un droit d'accès, de rectification, de suppression et de portabilité de vos données. Vous pouvez exercer ces droits en contactant <a href="mailto:contact@e-cosplay.fr" class="text-indigo-600 underline font-black">contact@e-cosplay.fr</a>.</p>
<h2 class="text-2xl font-black uppercase text-gray-900 mt-8">Désinscription</h2>
<p>Vous pouvez vous désinscrire de nos communications à tout moment via le lien présent dans chaque email ou en nous contactant directement.</p>
{% endblock %}

View File

@@ -1,40 +0,0 @@
{% extends 'base.html.twig' %}
{% block title %}Connexion - E-Cosplay Ticket{% endblock %}
{% block body %}
<div class="max-w-md mx-auto py-20 px-4">
<h1 class="text-5xl font-black uppercase tracking-tighter mb-12 text-center">Connexion</h1>
{% if error %}
<div class="border-4 border-gray-900 bg-red-400 px-6 py-4 font-black shadow-[4px_4px_0px_rgba(0,0,0,1)] mb-8">
{{ error.messageKey|trans(error.messageData, 'security') }}
</div>
{% endif %}
<form method="post" class="bg-white border-4 border-gray-900 p-8 shadow-[8px_8px_0px_rgba(0,0,0,1)] space-y-6">
<div>
<label for="email" class="block text-xs font-black uppercase tracking-widest mb-2">Email</label>
<input type="email" id="email" name="_username" value="{{ last_username }}" required autofocus
class="w-full border-2 border-gray-900 p-3 font-bold focus:bg-indigo-50 outline-none">
</div>
<div>
<label for="password" class="block text-xs font-black uppercase tracking-widest mb-2">Mot de passe</label>
<input type="password" id="password" name="_password" required
class="w-full border-2 border-gray-900 p-3 font-bold focus:bg-indigo-50 outline-none">
</div>
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
<button type="submit" class="w-full bg-indigo-600 text-white font-black uppercase tracking-widest py-4 border-4 border-gray-900 shadow-[6px_6px_0px_rgba(0,0,0,1)] hover:shadow-none hover:translate-x-1 hover:translate-y-1 transition-all">
Se connecter
</button>
<p class="text-center font-bold text-sm">
Pas encore de compte ?
<a href="{{ path('app_register') }}" class="text-indigo-600 underline font-black">Inscription</a>
</p>
</form>
</div>
{% endblock %}

View File

@@ -1,45 +0,0 @@
{% extends 'base.html.twig' %}
{% block title %}Inscription - E-Cosplay Ticket{% endblock %}
{% block body %}
<div class="max-w-md mx-auto py-20 px-4">
<h1 class="text-5xl font-black uppercase tracking-tighter mb-12 text-center">Inscription</h1>
<form method="post" class="bg-white border-4 border-gray-900 p-8 shadow-[8px_8px_0px_rgba(0,0,0,1)] space-y-6">
<div class="grid grid-cols-2 gap-4">
<div>
<label for="first_name" class="block text-xs font-black uppercase tracking-widest mb-2">Prénom</label>
<input type="text" id="first_name" name="first_name" required
class="w-full border-2 border-gray-900 p-3 font-bold focus:bg-indigo-50 outline-none">
</div>
<div>
<label for="last_name" class="block text-xs font-black uppercase tracking-widest mb-2">Nom</label>
<input type="text" id="last_name" name="last_name" required
class="w-full border-2 border-gray-900 p-3 font-bold focus:bg-indigo-50 outline-none">
</div>
</div>
<div>
<label for="email" class="block text-xs font-black uppercase tracking-widest mb-2">Email</label>
<input type="email" id="email" name="email" required
class="w-full border-2 border-gray-900 p-3 font-bold focus:bg-indigo-50 outline-none">
</div>
<div>
<label for="password" class="block text-xs font-black uppercase tracking-widest mb-2">Mot de passe</label>
<input type="password" id="password" name="password" required minlength="8"
class="w-full border-2 border-gray-900 p-3 font-bold focus:bg-indigo-50 outline-none">
</div>
<button type="submit" class="w-full bg-yellow-400 text-gray-900 font-black uppercase tracking-widest py-4 border-4 border-gray-900 shadow-[6px_6px_0px_rgba(0,0,0,1)] hover:shadow-none hover:translate-x-1 hover:translate-y-1 transition-all">
Créer mon compte
</button>
<p class="text-center font-bold text-sm">
Déjà un compte ?
<a href="{{ path('app_login') }}" class="text-indigo-600 underline font-black">Connexion</a>
</p>
</form>
</div>
{% endblock %}

View File

@@ -1,12 +0,0 @@
{% extends 'base.html.twig' %}
{% block title %}Désinscription confirmée - E-Cosplay Ticket{% endblock %}
{% block body %}
<main class="min-h-screen flex items-center justify-center bg-zinc-100">
<div class="bg-white rounded-xl shadow p-8 max-w-md w-full text-center">
<h1 class="text-2xl font-bold mb-4">Désinscription confirmée</h1>
<p class="text-zinc-600">L'adresse <strong>{{ email }}</strong> ne recevra plus nos emails.</p>
</div>
</main>
{% endblock %}

View File

@@ -1,17 +0,0 @@
{% extends 'base.html.twig' %}
{% block title %}Se désinscrire - E-Cosplay Ticket{% endblock %}
{% block body %}
<main class="min-h-screen flex items-center justify-center bg-zinc-100">
<div class="bg-white rounded-xl shadow p-8 max-w-md w-full text-center">
<h1 class="text-2xl font-bold mb-4">Se désinscrire</h1>
<p class="text-zinc-600 mb-6">Vous ne souhaitez plus recevoir nos emails à l'adresse <strong>{{ email }}</strong> ?</p>
<form method="post" action="{{ path('app_unsubscribe', {token: token}) }}">
<button type="submit" class="bg-red-600 hover:bg-red-700 text-white font-semibold py-3 px-6 rounded-lg">
Confirmer la désinscription
</button>
</form>
</div>
</main>
{% endblock %}