Ajoute la V1 fonctionnelle : upload invité, galerie admin, QR code, backend Supabase
Schéma dédié `photobooth` (jamais exposé via PostgREST, accès exclusivement via fonctions SECURITY DEFINER dans public) avec RLS, policies Storage sur bucket privé event-photos, Edge Functions admin-gallery et expire-events, et job pg_cron d'expiration J+7. Le tout déployé et testé en conditions réelles sur le projet Supabase kevin-lecou-hub avant relecture sécurité (faille d'abus sur insert_public_photo corrigée en cours de route). Côté front : page upload invité (compression + HEIC + RGPD), galerie admin avec export ZIP, générateur de QR code autonome. Workflow n8n de purge Storage J+7 fourni (à activer manuellement côté n8n).
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
<title>Ajouter une photo</title>
|
||||
<!--
|
||||
Cette page est servie pour toute URL du type /e/<slug> (le slug est lu
|
||||
côté client depuis window.location.pathname, voir upload.js).
|
||||
Ça suppose une règle de réécriture côté serveur (ex. nginx try_files)
|
||||
qui renvoie ce fichier pour toute requête sous /e/* — à mettre en place
|
||||
lors du déploiement, hors scope de ce fichier front.
|
||||
-->
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="page">
|
||||
<header class="page__header">
|
||||
<h1 id="event-name">Ajouter une photo</h1>
|
||||
</header>
|
||||
|
||||
<section id="status-loading" class="state-block" role="status">
|
||||
<p>Chargement de l'événement…</p>
|
||||
</section>
|
||||
|
||||
<section id="status-error" class="state-block state-block--error" hidden role="alert">
|
||||
<p id="status-error-message"></p>
|
||||
<button type="button" id="retry-btn" hidden>Réessayer</button>
|
||||
</section>
|
||||
|
||||
<section id="success-block" class="state-block state-block--success" hidden role="status">
|
||||
<p>Merci ! Ta photo est bien envoyée 🎉</p>
|
||||
<button type="button" id="add-another-btn">Ajouter une autre photo</button>
|
||||
</section>
|
||||
|
||||
<form id="upload-form" class="upload-form" hidden novalidate>
|
||||
<div class="field">
|
||||
<label for="photo-input">Ta photo</label>
|
||||
<!-- Pas d'attribut "capture" : on laisse le téléphone proposer à la
|
||||
fois l'appareil photo ET la galerie (capture forcerait l'un ou
|
||||
l'autre selon les navigateurs). -->
|
||||
<input
|
||||
type="file"
|
||||
id="photo-input"
|
||||
name="photo"
|
||||
accept="image/*,.heic,.heif"
|
||||
required
|
||||
>
|
||||
</div>
|
||||
|
||||
<img id="preview" class="preview" alt="Aperçu de la photo choisie" hidden>
|
||||
|
||||
<div class="field">
|
||||
<label for="nom-input">Ton prénom <span class="optional">(facultatif)</span></label>
|
||||
<input
|
||||
type="text"
|
||||
id="nom-input"
|
||||
name="nom"
|
||||
maxlength="60"
|
||||
autocomplete="given-name"
|
||||
placeholder="Ex : Camille"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label for="message-input">Un petit mot <span class="optional">(facultatif)</span></label>
|
||||
<textarea
|
||||
id="message-input"
|
||||
name="message"
|
||||
maxlength="300"
|
||||
rows="3"
|
||||
placeholder="Ton petit mot pour l'occasion…"
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<p class="legal-notice">
|
||||
En déposant une photo, vous acceptez qu'elle soit stockée temporairement
|
||||
dans le cadre de cet événement et mise à disposition de l'organisateur.
|
||||
Vos photos sont automatiquement supprimées 7 jours après la date de
|
||||
l'événement, sans action de votre part. Aucune photo n'est utilisée à
|
||||
d'autres fins, ni transmise à des tiers. Vous pouvez demander la
|
||||
suppression anticipée d'une photo en contactant l'organisateur de
|
||||
l'événement.
|
||||
</p>
|
||||
|
||||
<p id="progress-text" class="progress-text" aria-live="polite"></p>
|
||||
|
||||
<button type="submit" id="submit-btn">Envoyer ma photo</button>
|
||||
</form>
|
||||
</main>
|
||||
|
||||
<!--
|
||||
config.js n'est PAS commité (voir .gitignore) : copier config.example.js
|
||||
en config.js et renseigner les vraies valeurs Supabase avant déploiement.
|
||||
Chargé en script classique (donc synchrone, avant le module) pour garantir
|
||||
que window.__PHOTOBOOTH_CONFIG__ existe avant l'exécution de upload.js.
|
||||
-->
|
||||
<script src="config.js"></script>
|
||||
<script type="module" src="upload.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user