2026-03-18 22:38:42 +01:00
|
|
|
import "./app.scss"
|
2026-03-19 00:19:34 +01:00
|
|
|
import { initMobileMenu } from "./modules/mobile-menu.js"
|
|
|
|
|
import { initTabs } from "./modules/tabs.js"
|
Add Event entity, create event page, and custom WYSIWYG editor component
- Create Event entity with fields: account, title, description (text), startAt, endAt, address, zipcode, city, eventMainPicture (VichUploader), isOnline, createdAt, updatedAt
- Create EventRepository
- Add migration for event table with all columns
- Add "Creer un evenement" button on account events tab
- Add create event page (/mon-compte/evenement/creer) with full form
- Build custom web component <e-ticket-editor> WYSIWYG editor:
- Toolbar: bold, italic, underline, paragraph, bullet list, remove formatting
- contentEditable div with HTML sync to hidden textarea
- HTML sanitizer (strips disallowed tags, XSS safe)
- Neo-brutalist CSS styling
- CSP compliant (no inline styles)
- Register editor in app.js via customElements.define
- Add editor CSS in app.scss
- Add 16 Event entity tests (all fields + isOnline + picture upload + updatedAt)
- Add 16 editor JS tests (sanitizer + custom element lifecycle)
- Add 3 AccountController tests (create event page, submit, access control)
- Update placeholders to generic examples (no association-specific data)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 12:49:24 +01:00
|
|
|
import { registerEditor } from "./modules/editor.js"
|
2026-03-20 16:02:36 +01:00
|
|
|
import { initCookieConsent } from "./modules/cookie-consent.js"
|
2026-03-20 18:35:54 +01:00
|
|
|
import { initEventMap } from "./modules/event-map.js"
|
2026-03-20 21:37:12 +01:00
|
|
|
import { initCopyUrl } from "./modules/copy-url.js"
|
2026-03-20 23:16:52 +01:00
|
|
|
import { initSortable } from "./modules/sortable.js"
|
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
|
|
|
import { initBilletDesigner } from "./modules/billet-designer.js"
|
|
|
|
|
import { initCommissionCalculator } from "./modules/commission-calculator.js"
|
2026-03-21 13:46:06 +01:00
|
|
|
import { initCart } from "./modules/cart.js"
|
2026-03-21 16:13:06 +01:00
|
|
|
import { initStripePayment } from "./modules/stripe-payment.js"
|
Add social sharing buttons and QR code for events
Public event page:
- Share buttons: X (Twitter), Facebook, Instagram (copy link), TikTok (copy link), copy link
- Buttons use url_encode for share URLs with event title + URL
- Instagram/TikTok copy to clipboard (no direct share URL support)
- Consistent brutal design with aria-labels
Organizer dashboard:
- Share X, Facebook, copy link buttons per event in events list
- QR code download button per event
- Route /mon-compte/evenement/{id}/qrcode: generates 400px PNG QR code via Endroid
- QR code points to public event URL, downloaded as qrcode-{slug}.png
JS module:
- assets/modules/share.js: initShare() handles data-share-copy buttons
- Copies URL to clipboard, shows checkmark for 1.5s then restores icon
- 4 tests (no buttons, copy, checkmark restore, multiple buttons)
Social icons already displayed via _social_icons.html.twig component
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 15:11:53 +01:00
|
|
|
import { initShare } from "./modules/share.js"
|
Remove inline script from API doc, add CSP policy section
Security:
- Move env switcher logic to assets/modules/api-env-switcher.js (no inline script)
- Register in app.js via initApiEnvSwitcher()
- Compliant with CSP script-src (no unsafe-inline needed for this page)
API doc:
- Add CSP policy section showing all authorized origins per directive
- Table: script-src, connect-src, style-src, img-src, font-src, frame-src, form-action, object-src, worker-src
- Note: inline scripts not allowed, must use nonce or external file
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 19:02:28 +01:00
|
|
|
import { initApiEnvSwitcher } from "./modules/api-env-switcher.js"
|
2026-03-26 11:52:07 +01:00
|
|
|
import { initAnalytics } from "./modules/analytics.js"
|
2026-03-20 17:54:02 +01:00
|
|
|
|
Add homepage, tarifs, legal pages, navbar, footer and full test coverage
- Homepage: hero, how it works (buyer/organizer), features, CTA
- Tarifs: 3 plans (Gratuit, Basique 10€, Sur-mesure), JSON-LD Product
- Legal pages: mentions legales, CGU (tabs buyer/organizer), CGV, RGPD, cookies, hosting
- Navbar: neubrutalism style, logo liip, mobile menu, SEO attributes
- Footer: contact, description, legal links, tarifs
- Sitemap: add /tarifs and /sitemap-orgas-{page}.xml
- Liip Imagine: remove S3, webp format on all filters
- Tests: full coverage for all controllers, services, repositories
- Fix CSP: replace inline onclick with data-tab JS
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 00:01:58 +01:00
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
2026-03-19 00:19:34 +01:00
|
|
|
initMobileMenu()
|
|
|
|
|
initTabs()
|
Add Event entity, create event page, and custom WYSIWYG editor component
- Create Event entity with fields: account, title, description (text), startAt, endAt, address, zipcode, city, eventMainPicture (VichUploader), isOnline, createdAt, updatedAt
- Create EventRepository
- Add migration for event table with all columns
- Add "Creer un evenement" button on account events tab
- Add create event page (/mon-compte/evenement/creer) with full form
- Build custom web component <e-ticket-editor> WYSIWYG editor:
- Toolbar: bold, italic, underline, paragraph, bullet list, remove formatting
- contentEditable div with HTML sync to hidden textarea
- HTML sanitizer (strips disallowed tags, XSS safe)
- Neo-brutalist CSS styling
- CSP compliant (no inline styles)
- Register editor in app.js via customElements.define
- Add editor CSS in app.scss
- Add 16 Event entity tests (all fields + isOnline + picture upload + updatedAt)
- Add 16 editor JS tests (sanitizer + custom element lifecycle)
- Add 3 AccountController tests (create event page, submit, access control)
- Update placeholders to generic examples (no association-specific data)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 12:49:24 +01:00
|
|
|
registerEditor()
|
2026-03-20 16:02:36 +01:00
|
|
|
initCookieConsent()
|
2026-03-20 17:54:02 +01:00
|
|
|
initCopyUrl()
|
2026-03-20 18:35:54 +01:00
|
|
|
initEventMap()
|
2026-03-20 23:16:52 +01:00
|
|
|
initSortable()
|
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
|
|
|
initBilletDesigner()
|
|
|
|
|
initCommissionCalculator()
|
2026-03-21 13:46:06 +01:00
|
|
|
initCart()
|
2026-03-21 16:13:06 +01:00
|
|
|
initStripePayment()
|
Add social sharing buttons and QR code for events
Public event page:
- Share buttons: X (Twitter), Facebook, Instagram (copy link), TikTok (copy link), copy link
- Buttons use url_encode for share URLs with event title + URL
- Instagram/TikTok copy to clipboard (no direct share URL support)
- Consistent brutal design with aria-labels
Organizer dashboard:
- Share X, Facebook, copy link buttons per event in events list
- QR code download button per event
- Route /mon-compte/evenement/{id}/qrcode: generates 400px PNG QR code via Endroid
- QR code points to public event URL, downloaded as qrcode-{slug}.png
JS module:
- assets/modules/share.js: initShare() handles data-share-copy buttons
- Copies URL to clipboard, shows checkmark for 1.5s then restores icon
- 4 tests (no buttons, copy, checkmark restore, multiple buttons)
Social icons already displayed via _social_icons.html.twig component
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 15:11:53 +01:00
|
|
|
initShare()
|
Remove inline script from API doc, add CSP policy section
Security:
- Move env switcher logic to assets/modules/api-env-switcher.js (no inline script)
- Register in app.js via initApiEnvSwitcher()
- Compliant with CSP script-src (no unsafe-inline needed for this page)
API doc:
- Add CSP policy section showing all authorized origins per directive
- Table: script-src, connect-src, style-src, img-src, font-src, frame-src, form-action, object-src, worker-src
- Note: inline scripts not allowed, must use nonce or external file
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 19:02:28 +01:00
|
|
|
initApiEnvSwitcher()
|
2026-03-26 11:52:07 +01:00
|
|
|
initAnalytics()
|
Complete TASK_CHECKUP: security, UX, tests, coverage, accessibility, config externalization
Billetterie:
- Partial refund support (STATUS_PARTIALLY_REFUNDED, refundedAmount field, migration)
- Race condition fix: PESSIMISTIC_WRITE lock on stock decrement in transaction
- Idempotency key on PaymentIntent::create, reuse existing PI if stripeSessionId set
- Disable checkout when event ended (server 400 + template hide)
- Webhook deduplication via cache (24h TTL on stripe event.id)
- Email validation (filter_var) in OrderController guest flow
- JSON cart validation (structure check before processing)
- Invitation expiration after 7 days (isExpired method + landing page message)
- Stripe Checkout fallback when JS fails to load (noscript + redirect)
Config externalization:
- Move Stripe fees (STRIPE_FEE_RATE, STRIPE_FEE_FIXED) and admin email (ADMIN_EMAIL) to .env/services.yaml
- Replace all hardcoded contact@e-cosplay.fr across 13 files
- MailerService: getAdminEmail()/getAdminFrom(), default $from=null resolves to admin
UX & Accessibility:
- ARIA tabs: role=tablist/tab/tabpanel, aria-selected, keyboard nav (arrows, Home, End)
- aria-label on cart +/- buttons and editor toolbar buttons
- tabindex=0 on editor toolbar buttons for keyboard access
- data-confirm handler in app.js (was only in admin.js)
- Cart error feedback on checkout failure
- Billet designer save feedback (loading/success/error states)
- Stock polling every 30s with rupture/low stock badges
- Back to event link on payment page
Security:
- HTML sanitizer: BLOCKED_TAGS list (script, style, iframe, svg, etc.) - content fully removed
- Stripe polling timeout (15s max) with fallback redirect
- Rate limiting on public order access (20/5min)
- .catch() on all fetch() calls (sortable, billet-designer)
Tests (92% PHP, 100% JS lines):
- PCOV added to dev Dockerfile
- Test DB setup: .env.test with DATABASE_URL, Redis auth, Meilisearch key
- Rate limiter disabled in test env
- Makefile: test_db_setup, test_db_reset, run_test_php, run_test_coverage_php/js
- New tests: InvitationFlowTest (21), AuditServiceTest (4), ExportServiceTest (9), InvoiceServiceTest (4)
- New tests: SuspendedUserSubscriberTest, RateLimiterSubscriberTest, MeilisearchServiceTest
- New tests: Stripe webhook payment_failed (6) + charge.refunded (6)
- New tests: BilletBuyer refund, User suspended, OrganizerInvitation expiration
- JS tests: stock polling (6), data-confirm (2), copy-url restore (1), editor ARIA (2), XSS (9), tabs keyboard (9)
- ESLint + PHP CS Fixer: 0 errors
- SonarQube exclusions aligned with vitest coverage config
Infra:
- Meilisearch consistency command (app:meilisearch:check-consistency --fix) + cron daily 3am
- MeilisearchService: getAllDocumentIds(), listIndexes()
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 11:14:06 +01:00
|
|
|
|
|
|
|
|
document.querySelectorAll('[data-confirm]').forEach(form => {
|
|
|
|
|
form.addEventListener('submit', (e) => {
|
|
|
|
|
if (!globalThis.confirm(form.dataset.confirm)) {
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
})
|
Add homepage, tarifs, legal pages, navbar, footer and full test coverage
- Homepage: hero, how it works (buyer/organizer), features, CTA
- Tarifs: 3 plans (Gratuit, Basique 10€, Sur-mesure), JSON-LD Product
- Legal pages: mentions legales, CGU (tabs buyer/organizer), CGV, RGPD, cookies, hosting
- Navbar: neubrutalism style, logo liip, mobile menu, SEO attributes
- Footer: contact, description, legal links, tarifs
- Sitemap: add /tarifs and /sitemap-orgas-{page}.xml
- Liip Imagine: remove S3, webp format on all filters
- Tests: full coverage for all controllers, services, repositories
- Fix CSP: replace inline onclick with data-tab JS
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 00:01:58 +01:00
|
|
|
})
|