Remplace le bloc RGPD permanent par une modale de bienvenue au 1er passage

Demande Kévin : mot de bienvenue personnalisé (nom de l'événement) +
mention légale RGPD, affiché une fois par événement (localStorage) au
lieu d'un bloc toujours visible dans le formulaire. Texte légal conservé
à l'identique (docs/rgpd.md), seule la présentation change. Reste
consultable à tout moment via un lien "Infos sur tes données" sous le
formulaire, qui rouvre la même modale.
This commit is contained in:
2026-09-16 15:57:09 +02:00
parent 3afd475a55
commit 45e0bd7bcc
3 changed files with 196 additions and 11 deletions
+45 -11
View File
@@ -30,6 +30,48 @@
<p class="page__kicker">Une photo, un petit mot, et hop dans l'album&nbsp;!</p>
</header>
<!-- Mot de bienvenue + mention légale RGPD condensée, affiché une seule
fois par événement (localStorage, cf. upload.js) plutôt qu'en bloc
permanent dans le formulaire — décision Kévin 2026-09-16. Reste
consultable à tout moment via le lien "Infos sur tes données" sous
le formulaire, pour ne jamais perdre l'info, juste la rendre moins
envahissante au quotidien. -->
<div id="welcome-modal" class="welcome-modal" hidden>
<div class="welcome-modal__card">
<p class="brand brand--modal" aria-hidden="true">
<svg class="brand__mark" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" focusable="false">
<path d="M4 8h3l1.5-2h7L17 8h3a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V9a1 1 0 0 1 1-1Z"/>
<circle cx="12" cy="13" r="3.5"/>
</svg>
<span class="brand__name">photobooth</span>
</p>
<p class="welcome-modal__title" id="welcome-modal-title">Bienvenue&nbsp;!</p>
<p class="welcome-modal__text">
Scanne, souris, dépose ta photo — elle rejoint l'album de l'événement
en quelques secondes.
</p>
<p class="legal-notice welcome-modal__legal">
<svg class="legal-notice__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
<rect x="4.5" y="10.5" width="15" height="9.5" rx="2"/>
<path d="M8 10.5V7.5a4 4 0 0 1 8 0v3"/>
</svg>
<!-- Texte légal complet, identique à docs/rgpd.md (mention
obligatoire) — seule la présentation change (modale au premier
passage + lien de rappel), pas le contenu. -->
<span>
En déposant une photo, tu acceptes qu'elle soit stockée temporairement
dans le cadre de cet événement et mise à disposition de l'organisateur.
Tes photos sont automatiquement supprimées 7 jours après la date de
l'événement, sans action de ta part. Aucune photo n'est utilisée à
d'autres fins, ni transmise à des tiers. Tu peux demander la
suppression anticipée d'une photo en contactant l'organisateur de
l'événement.
</span>
</p>
<button type="button" id="welcome-modal-dismiss">C'est parti&nbsp;!</button>
</div>
</div>
<section id="status-loading" class="state-block state-block--loading" role="status">
<span class="spinner" aria-hidden="true"></span>
<p>Chargement de l'événement…</p>
@@ -142,21 +184,13 @@
</div>
</div>
<p class="legal-notice">
<button type="button" id="legal-link" class="legal-link">
<svg class="legal-notice__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
<rect x="4.5" y="10.5" width="15" height="9.5" rx="2"/>
<path d="M8 10.5V7.5a4 4 0 0 1 8 0v3"/>
</svg>
<span>
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.
</span>
</p>
<span>Infos sur tes données (RGPD)</span>
</button>
<p id="progress-text" class="progress-text" aria-live="polite"></p>
+96
View File
@@ -441,6 +441,102 @@ button:focus-visible {
color: var(--color-plum);
}
.legal-link {
display: flex;
align-items: center;
gap: 0.5rem;
background: none;
border: none;
box-shadow: none;
padding: 0.4rem 0.1rem;
margin: 0;
font: inherit;
font-size: 0.8rem;
font-weight: 600;
color: var(--color-muted);
text-decoration: underline;
text-underline-offset: 2px;
cursor: pointer;
min-height: 0;
}
.legal-link .legal-notice__icon {
color: var(--color-muted);
}
/* Mot de bienvenue + RGPD — overlay affiché une fois par événement,
au-dessus du formulaire déjà présent en arrière-plan (cf. upload.js). */
.welcome-modal {
position: fixed;
inset: 0;
z-index: 100;
display: flex;
align-items: flex-end;
justify-content: center;
padding: 0;
background: rgba(43, 32, 22, 0.45);
animation: fade-in 0.2s ease both;
}
.welcome-modal__card {
width: 100%;
max-width: 480px;
max-height: 88vh;
overflow-y: auto;
background: var(--color-surface);
border-radius: var(--radius) var(--radius) 0 0;
padding: 1.5rem 1.25rem calc(1.5rem + env(safe-area-inset-bottom));
box-shadow: var(--shadow-md);
animation: slide-up 0.35s var(--ease-bounce) both;
display: flex;
flex-direction: column;
gap: 0.9rem;
}
@media (min-width: 520px) {
.welcome-modal {
align-items: center;
}
.welcome-modal__card {
border-radius: var(--radius);
}
}
.welcome-modal .brand {
margin-bottom: 0;
}
.welcome-modal__title {
font-family: var(--font-display);
font-weight: 600;
font-size: 1.5rem;
text-align: center;
margin: 0;
color: var(--color-accent);
}
.welcome-modal__text {
text-align: center;
margin: 0;
color: var(--color-text);
}
#welcome-modal-dismiss {
background: var(--color-accent);
color: var(--color-accent-contrast);
box-shadow: var(--shadow-sm);
}
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slide-up {
from { transform: translateY(24px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.progress-text {
min-height: 1.2em;
font-size: 0.9rem;
+55
View File
@@ -48,6 +48,10 @@ const messageInput = document.getElementById("message-input");
const progressText = document.getElementById("progress-text");
const submitBtn = document.getElementById("submit-btn");
const submitBtnLabel = document.getElementById("submit-btn-label");
const welcomeModal = document.getElementById("welcome-modal");
const welcomeModalTitle = document.getElementById("welcome-modal-title");
const welcomeModalDismiss = document.getElementById("welcome-modal-dismiss");
const legalLink = document.getElementById("legal-link");
// ---------------------------------------------------------------------------
// État
@@ -201,6 +205,52 @@ function incrementLocalGuestPhotoCount(slug) {
}
}
// ---------------------------------------------------------------------------
// Mot de bienvenue + RGPD — affiché une fois par événement (localStorage),
// plutôt qu'en bloc permanent dans le formulaire (décision Kévin 2026-09-16).
// Reste ré-ouvrable à tout moment via le lien "Infos sur tes données".
// ---------------------------------------------------------------------------
function welcomeSeenStorageKey(slug) {
return `photobooth_welcome_seen_${slug}`;
}
function hasSeenWelcome(slug) {
try {
return window.localStorage.getItem(welcomeSeenStorageKey(slug)) === "1";
} catch {
return false;
}
}
function markWelcomeSeen(slug) {
try {
window.localStorage.setItem(welcomeSeenStorageKey(slug), "1");
} catch {
// Pas grave : la modale se réaffichera simplement à la prochaine visite,
// ce n'est pas un risque de conformité (juste redondant pour l'invité).
}
}
function openWelcomeModal(eventName) {
welcomeModalTitle.textContent = eventName ? `Bienvenue à ${eventName} !` : "Bienvenue !";
welcomeModal.hidden = false;
}
function closeWelcomeModal() {
welcomeModal.hidden = true;
}
welcomeModalDismiss.addEventListener("click", () => {
const slug = getSlugFromPath();
if (slug) markWelcomeSeen(slug);
closeWelcomeModal();
});
legalLink.addEventListener("click", () => {
openWelcomeModal(state.event ? state.event.nom : null);
});
function isHeicFile(file) {
const type = (file.type || "").toLowerCase();
if (type === "image/heic" || type === "image/heif") return true;
@@ -232,6 +282,11 @@ function showForm(event) {
errorBlock.hidden = true;
successBlock.hidden = true;
form.hidden = false;
const slug = getSlugFromPath();
if (slug && !hasSeenWelcome(slug)) {
openWelcomeModal(event.nom);
}
}
function showError(rawErr, retryAction) {