Files
e-ticket/templates/account/add_billet.html.twig

81 lines
4.7 KiB
Twig
Raw Normal View History

Add Billet entity, BilletDesign, ticket designer, CRUD billets, commissions - Create Billet entity: name, position, priceHT, quantity (nullable=unlimited), isGeneratedBillet, hasDefinedExit, notBuyable, type (billet/reservation_brocante/vote), stripeProductId, description, picture (VichUploader), category (ManyToOne CASCADE) - Create BilletDesign entity (OneToOne Event): accentColor, invitationTitle, invitationColor - Billet CRUD: add/edit/delete with access control, Stripe product sync on connected account - Billet reorder: drag & drop with position field, refactored sortable.js for both categories and billets - Ticket designer tab (custom offer only): accent color, invitation title/color, live iframe preview - A4 ticket preview: 4 zones (HG infos+billet, HD affiche, BG association, BD sortie+invitation), fake QR code SVG - Commission calculator JS: live breakdown of E-Ticket fee, Stripe fee (1.5%+0.25EUR), net amount - Sales recap on categories tab: qty sold, total HT, total commissions, total net - DisableProfilerSubscriber: disable web profiler toolbar on preview iframe - CSP: allow self in frame-src and frame-ancestors for preview iframe - Flysystem: dedicated billets.storage for billet images - Upload accept restricted to png/jpeg/webp/gif (no HEIC) - Makefile: add force_sql_dev command - CLAUDE.md: add rule to never modify existing migrations - Consolidate all migrations into single Version20260321111125 - Tests: BilletTest (20), BilletDesignTest (6), DisableProfilerSubscriberTest (5), billet-designer.test.js (7), commission-calculator.test.js (7), AccountControllerTest billet CRUD tests (11) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:19:46 +01:00
{% extends 'base.html.twig' %}
{% block title %}Ajouter un billet - {{ category.name }} - E-Ticket{% endblock %}
{% block body %}
<div class="page-container">
<a href="{{ path('app_account_edit_event', {id: event.id, tab: 'categories'}) }}" class="inline-flex items-center gap-2 text-sm font-black uppercase tracking-widest text-gray-500 hover:text-gray-900 transition-colors mb-8">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M15 19l-7-7 7-7"/></svg>
Retour aux categories
</a>
<h1 class="text-3xl font-black uppercase tracking-tighter italic heading-page">Ajouter un billet</h1>
<p class="font-bold text-gray-600 italic mb-8">{{ event.title }}{{ category.name }}</p>
{% for message in app.flashes('error') %}
<div class="flash-error"><p class="font-black text-sm">{{ message }}</p></div>
{% endfor %}
<div class="card-brutal">
<form method="post" action="{{ path('app_account_event_add_billet', {id: event.id, categoryId: category.id}) }}" enctype="multipart/form-data" class="form-col">
<div>
<label for="billet_type" class="text-xs font-black uppercase tracking-widest form-label">Type</label>
<select id="billet_type" name="type" class="form-input focus:border-indigo-600">
<option value="billet">Billet</option>
<option value="reservation_brocante">Reservation brocante</option>
<option value="vote">Vote</option>
</select>
</div>
<div>
<label for="billet_name" class="text-xs font-black uppercase tracking-widest form-label">Nom du billet</label>
<input type="text" id="billet_name" name="name" required class="form-input focus:border-indigo-600" placeholder="Ex: Entree adulte, Pass VIP...">
</div>
<div>
<label for="billet_price" class="text-xs font-black uppercase tracking-widest form-label">Prix HT (&euro;)</label>
<input type="number" id="billet_price" name="price_ht" required min="0" step="0.01" class="form-input focus:border-indigo-600" placeholder="Ex: 15.00">
</div>
<div>
<label for="billet_quantity" class="text-xs font-black uppercase tracking-widest form-label">Quantite disponible (vide = illimite)</label>
<input type="number" id="billet_quantity" name="quantity" min="1" class="form-input focus:border-indigo-600" placeholder="Illimite">
</div>
{% include 'account/_billet_commission.html.twig' %}
<div>
<label for="billet_description" class="text-xs font-black uppercase tracking-widest form-label">Description</label>
<textarea id="billet_description" name="description" rows="3" class="form-input focus:border-indigo-600" placeholder="Description optionnelle du billet..."></textarea>
</div>
<div>
<label for="billet_picture" class="text-xs font-black uppercase tracking-widest form-label">Image</label>
<input type="file" id="billet_picture" name="picture" accept="image/png, image/jpeg, image/webp, image/gif" class="form-file">
</div>
<div class="flex items-center gap-3">
<input type="checkbox" id="billet_generated" name="is_generated_billet" value="1" class="w-5 h-5 border-2 border-gray-900 cursor-pointer" checked>
<label for="billet_generated" class="text-sm font-black uppercase tracking-widest cursor-pointer">Generer un billet PDF</label>
</div>
<div class="flex items-center gap-3">
<input type="checkbox" id="billet_exit" name="has_defined_exit" value="1" class="w-5 h-5 border-2 border-gray-900 cursor-pointer">
<label for="billet_exit" class="text-sm font-black uppercase tracking-widest cursor-pointer">Sortie definitive</label>
</div>
<div class="flex items-center gap-3">
<input type="checkbox" id="billet_not_buyable" name="not_buyable" value="1" class="w-5 h-5 border-2 border-gray-900 cursor-pointer">
<label for="billet_not_buyable" class="text-sm font-black uppercase tracking-widest cursor-pointer">Non achetable</label>
</div>
<div>
<button type="submit" class="btn-brutal font-black uppercase text-sm tracking-widest hover:bg-indigo-600 hover:text-white transition-all">
Ajouter le billet
</button>
</div>
</form>
</div>
</div>
{% endblock %}