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>
This commit is contained in:
Serreau Jovann
2026-03-23 15:11:53 +01:00
parent 1af242c307
commit 6b009a4511
7 changed files with 171 additions and 1 deletions

View File

@@ -10,6 +10,7 @@ import { initBilletDesigner } from "./modules/billet-designer.js"
import { initCommissionCalculator } from "./modules/commission-calculator.js"
import { initCart } from "./modules/cart.js"
import { initStripePayment } from "./modules/stripe-payment.js"
import { initShare } from "./modules/share.js"
document.addEventListener('DOMContentLoaded', () => {
initMobileMenu()
@@ -23,6 +24,7 @@ document.addEventListener('DOMContentLoaded', () => {
initCommissionCalculator()
initCart()
initStripePayment()
initShare()
document.querySelectorAll('[data-confirm]').forEach(form => {
form.addEventListener('submit', (e) => {

12
assets/modules/share.js Normal file
View File

@@ -0,0 +1,12 @@
export function initShare() {
document.querySelectorAll('[data-share-copy]').forEach(btn => {
btn.addEventListener('click', () => {
const url = btn.dataset.shareCopy
globalThis.navigator.clipboard.writeText(url).then(() => {
const original = btn.innerHTML
btn.innerHTML = '<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>'
setTimeout(() => { btn.innerHTML = original }, 1500)
})
})
})
}