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:
+45
-11
@@ -30,6 +30,48 @@
|
|||||||
<p class="page__kicker">Une photo, un petit mot, et hop dans l'album !</p>
|
<p class="page__kicker">Une photo, un petit mot, et hop dans l'album !</p>
|
||||||
</header>
|
</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 !</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 !</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<section id="status-loading" class="state-block state-block--loading" role="status">
|
<section id="status-loading" class="state-block state-block--loading" role="status">
|
||||||
<span class="spinner" aria-hidden="true"></span>
|
<span class="spinner" aria-hidden="true"></span>
|
||||||
<p>Chargement de l'événement…</p>
|
<p>Chargement de l'événement…</p>
|
||||||
@@ -142,21 +184,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</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">
|
<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"/>
|
<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"/>
|
<path d="M8 10.5V7.5a4 4 0 0 1 8 0v3"/>
|
||||||
</svg>
|
</svg>
|
||||||
<span>
|
<span>Infos sur tes données (RGPD)</span>
|
||||||
En déposant une photo, vous acceptez qu'elle soit stockée temporairement
|
</button>
|
||||||
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>
|
|
||||||
|
|
||||||
<p id="progress-text" class="progress-text" aria-live="polite"></p>
|
<p id="progress-text" class="progress-text" aria-live="polite"></p>
|
||||||
|
|
||||||
|
|||||||
@@ -441,6 +441,102 @@ button:focus-visible {
|
|||||||
color: var(--color-plum);
|
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 {
|
.progress-text {
|
||||||
min-height: 1.2em;
|
min-height: 1.2em;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ const messageInput = document.getElementById("message-input");
|
|||||||
const progressText = document.getElementById("progress-text");
|
const progressText = document.getElementById("progress-text");
|
||||||
const submitBtn = document.getElementById("submit-btn");
|
const submitBtn = document.getElementById("submit-btn");
|
||||||
const submitBtnLabel = document.getElementById("submit-btn-label");
|
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
|
// É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) {
|
function isHeicFile(file) {
|
||||||
const type = (file.type || "").toLowerCase();
|
const type = (file.type || "").toLowerCase();
|
||||||
if (type === "image/heic" || type === "image/heif") return true;
|
if (type === "image/heic" || type === "image/heif") return true;
|
||||||
@@ -232,6 +282,11 @@ function showForm(event) {
|
|||||||
errorBlock.hidden = true;
|
errorBlock.hidden = true;
|
||||||
successBlock.hidden = true;
|
successBlock.hidden = true;
|
||||||
form.hidden = false;
|
form.hidden = false;
|
||||||
|
|
||||||
|
const slug = getSlugFromPath();
|
||||||
|
if (slug && !hasSeenWelcome(slug)) {
|
||||||
|
openWelcomeModal(event.nom);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showError(rawErr, retryAction) {
|
function showError(rawErr, retryAction) {
|
||||||
|
|||||||
Reference in New Issue
Block a user