Wizard evenement tactile + menu admin simplifie + bouton update + logo SikaPics

- Wizard: 6 etapes (nom, theme, modes, nb photos, partage, resume)
- Gros boutons tactiles, une question par ecran
- Parametres avances accessibles depuis le wizard
- Bouton "Mettre a jour l'affichage" dans Fonctions > Systeme
- Logo SikaPics dans le theme sikapics
- Menu admin reorganise: Materiel / Compteur / Destinations / Personnalisation / Evenement / Fonctions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-07 18:12:51 +02:00
parent 626db8905a
commit 229a388a1e
4 changed files with 440 additions and 59 deletions

View File

@@ -1203,6 +1203,193 @@ h3 {
border-radius: 3px; border-radius: 3px;
} }
/* === Wizard === */
.wizard-header {
position: absolute;
top: 0;
left: 0;
right: 0;
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem 1.5rem;
z-index: 10;
}
.wizard-progress {
display: flex;
gap: 8px;
}
.wizard-dot {
width: 12px;
height: 12px;
border-radius: 50%;
background: rgba(255,255,255,0.2);
transition: 0.3s;
}
.wizard-dot.actif {
background: var(--primaire);
transform: scale(1.3);
}
.wizard-dot.fait {
background: var(--succes);
}
.wizard-step {
display: none;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 2rem;
padding: 2rem;
width: 100%;
height: 100%;
animation: fadeIn 0.3s ease;
}
.wizard-step.actif {
display: flex;
}
.wizard-step h2 {
font-size: 2rem;
font-weight: 600;
}
.wizard-input {
width: 80%;
max-width: 500px;
padding: 1.2rem 1.5rem;
font-size: 1.5rem;
border: 2px solid rgba(255,255,255,0.2);
border-radius: var(--rayon);
background: var(--fond-carte);
color: var(--texte);
text-align: center;
outline: none;
}
.wizard-input:focus {
border-color: var(--primaire);
}
.wizard-choix {
display: flex;
gap: 1.5rem;
flex-wrap: wrap;
justify-content: center;
}
.wizard-choix-wrap {
max-width: 600px;
}
.wizard-card {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.8rem;
padding: 1.5rem 2rem;
border: 3px solid rgba(255,255,255,0.1);
border-radius: var(--rayon);
background: var(--fond-carte);
color: var(--texte);
cursor: pointer;
transition: 0.2s;
min-width: 140px;
font-size: 1.1rem;
}
.wizard-card:active {
transform: scale(0.95);
}
.wizard-card.actif {
border-color: var(--primaire);
background: rgba(233, 30, 99, 0.15);
}
.wizard-card-icon {
font-size: 3rem;
width: 80px;
height: 80px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
}
.wizard-nombre {
display: flex;
align-items: center;
gap: 2rem;
}
.wizard-nb-btn {
width: 80px;
height: 80px;
border-radius: 50%;
border: 3px solid var(--primaire);
background: transparent;
color: var(--primaire);
font-size: 2.5rem;
font-weight: bold;
cursor: pointer;
}
.wizard-nb-btn:active {
background: var(--primaire);
color: #fff;
}
.wizard-nb-val {
font-size: 5rem;
font-weight: bold;
min-width: 80px;
text-align: center;
}
.wizard-btn-next {
padding: 1.2rem 3rem;
font-size: 1.3rem;
font-weight: 600;
border: none;
border-radius: var(--rayon);
background: var(--primaire);
color: #fff;
cursor: pointer;
min-width: 200px;
margin-top: 1rem;
}
.wizard-btn-next:active {
transform: scale(0.95);
}
.wizard-btn-go {
font-size: 1.5rem;
padding: 1.5rem 4rem;
background: var(--succes);
}
.wizard-resume {
background: var(--fond-carte);
border-radius: var(--rayon);
padding: 1.5rem 2rem;
font-size: 1.1rem;
line-height: 2;
text-align: left;
min-width: 300px;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
/* Responsive tactile */ /* Responsive tactile */
@media (max-width: 800px) { @media (max-width: 800px) {
.accueil-contenu h1 { font-size: 2.5rem; } .accueil-contenu h1 { font-size: 2.5rem; }

View File

@@ -54,6 +54,18 @@
font-weight: 600; font-weight: 600;
} }
[data-theme="sikapics"] #nom-evenement::before {
content: '';
display: block;
width: 180px;
height: 60px;
margin: 0 auto 1rem;
background-image: url('https://sikapics.com/wp-content/uploads/2024/03/sikapics-logo-sans-fond.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
[data-theme="sikapics"] .accueil-instruction { [data-theme="sikapics"] .accueil-instruction {
color: var(--texte-secondaire); color: var(--texte-secondaire);
font-weight: 300; font-weight: 300;

View File

@@ -134,10 +134,100 @@
<button class="btn-retour" onclick="allerA('accueil')">Retour</button> <button class="btn-retour" onclick="allerA('accueil')">Retour</button>
</section> </section>
<!-- Menu Admin / Backoffice --> <!-- Wizard evenement -->
<section id="ecran-wizard" class="ecran">
<div class="wizard-header">
<button class="btn-fermer" onclick="allerA('accueil')">&times;</button>
<div class="wizard-progress" id="wizard-progress"></div>
</div>
<!-- Etape 1 : Nom -->
<div class="wizard-step actif" data-step="1">
<h2>Nom de l'evenement</h2>
<input type="text" id="wiz-nom" class="wizard-input" placeholder="Mariage Julie & Thomas" autocomplete="off">
<button class="wizard-btn-next" onclick="wizardSuivant()">Suivant</button>
</div>
<!-- Etape 2 : Theme -->
<div class="wizard-step" data-step="2">
<h2>Theme visuel</h2>
<div class="wizard-choix">
<button class="wizard-card" data-val="base" onclick="wizardChoisir(this, 'theme')">
<div class="wizard-card-icon" style="background:#1a1a2e;color:#e91e63">&#9790;</div>
<span>Sombre</span>
</button>
<button class="wizard-card" data-val="sikapics" onclick="wizardChoisir(this, 'theme')">
<div class="wizard-card-icon" style="background:#fbe7e8;color:#c31f48">&#10047;</div>
<span>SikaPics</span>
</button>
</div>
<button class="wizard-btn-next" onclick="wizardSuivant()">Suivant</button>
</div>
<!-- Etape 3 : Modes photo -->
<div class="wizard-step" data-step="3">
<h2>Modes photo</h2>
<div class="wizard-choix">
<button class="wizard-card wizard-toggle actif" data-val="simple" onclick="wizardToggle(this)">
<div class="wizard-card-icon">&#128247;</div>
<span>Photo</span>
</button>
<button class="wizard-card wizard-toggle actif" data-val="multi" onclick="wizardToggle(this)">
<div class="wizard-card-icon">&#127902;</div>
<span>Pellicule</span>
</button>
</div>
<button class="wizard-btn-next" onclick="wizardSuivant()">Suivant</button>
</div>
<!-- Etape 4 : Nombre de photos pellicule -->
<div class="wizard-step" data-step="4">
<h2>Photos par pellicule</h2>
<div class="wizard-nombre">
<button class="wizard-nb-btn" onclick="wizardNbPhotos(-1)">-</button>
<span id="wiz-nb-photos" class="wizard-nb-val">4</span>
<button class="wizard-nb-btn" onclick="wizardNbPhotos(1)">+</button>
</div>
<button class="wizard-btn-next" onclick="wizardSuivant()">Suivant</button>
</div>
<!-- Etape 5 : Fonctions partage -->
<div class="wizard-step" data-step="5">
<h2>Partage</h2>
<div class="wizard-choix wizard-choix-wrap">
<button class="wizard-card wizard-toggle" data-val="impression" onclick="wizardToggle(this)">
<div class="wizard-card-icon">&#128424;</div>
<span>Impression</span>
</button>
<button class="wizard-card wizard-toggle" data-val="email" onclick="wizardToggle(this)">
<div class="wizard-card-icon">&#9993;</div>
<span>Email</span>
</button>
<button class="wizard-card wizard-toggle" data-val="galerie_live" onclick="wizardToggle(this)">
<div class="wizard-card-icon">&#127760;</div>
<span>Galerie live</span>
</button>
<button class="wizard-card wizard-toggle" data-val="qr" onclick="wizardToggle(this)">
<div class="wizard-card-icon">&#9641;</div>
<span>QR Code</span>
</button>
</div>
<button class="wizard-btn-next" onclick="wizardSuivant()">Suivant</button>
</div>
<!-- Etape 6 : Resume -->
<div class="wizard-step" data-step="6">
<h2>C'est pret !</h2>
<div id="wiz-resume" class="wizard-resume"></div>
<button class="wizard-btn-next wizard-btn-go" onclick="wizardTerminer()">Lancer le photobooth</button>
<button class="btn-secondaire" onclick="allerA('admin')">Parametres avances</button>
</div>
</section>
<!-- Menu Admin / Backoffice (avance) -->
<section id="ecran-admin" class="ecran"> <section id="ecran-admin" class="ecran">
<div class="admin-header"> <div class="admin-header">
<h2>Parametres</h2> <h2>Parametres avances</h2>
<button class="btn-fermer" onclick="allerA('accueil')">&times;</button> <button class="btn-fermer" onclick="allerA('accueil')">&times;</button>
</div> </div>
<div class="admin-contenu"> <div class="admin-contenu">
@@ -145,15 +235,9 @@
<button class="onglet actif" data-onglet="materiel">Materiel</button> <button class="onglet actif" data-onglet="materiel">Materiel</button>
<button class="onglet" data-onglet="compteur-admin">Compteur</button> <button class="onglet" data-onglet="compteur-admin">Compteur</button>
<button class="onglet" data-onglet="destinations-admin">Destinations</button> <button class="onglet" data-onglet="destinations-admin">Destinations</button>
<button class="onglet" data-onglet="cadres-admin">Cadres</button> <button class="onglet" data-onglet="personnalisation">Personnalisation</button>
<button class="onglet" data-onglet="fonds-admin">Fonds verts</button>
<button class="onglet" data-onglet="animations-admin">Animation 3-2-1</button>
<button class="onglet" data-onglet="evenement">Evenement</button> <button class="onglet" data-onglet="evenement">Evenement</button>
<button class="onglet" data-onglet="fonctionnalites">Fonctions</button> <button class="onglet" data-onglet="fonctions">Fonctions</button>
<button class="onglet" data-onglet="email-admin">Email</button>
<button class="onglet" data-onglet="booth-admin">Galerie Live</button>
<button class="onglet" data-onglet="galerie-admin">Galerie</button>
<button class="onglet" data-onglet="systeme">Systeme</button>
</div> </div>
<!-- Panneau Materiel (Camera + Imprimante) --> <!-- Panneau Materiel (Camera + Imprimante) -->
@@ -254,50 +338,39 @@
<button class="btn-action" onclick="sauvegarderDestinations()">Sauvegarder</button> <button class="btn-action" onclick="sauvegarderDestinations()">Sauvegarder</button>
</div> </div>
<!-- Panneau Cadres --> <!-- Panneau Personnalisation (Cadres + Fonds + Animations) -->
<div class="admin-panneau" id="panneau-cadres-admin"> <div class="admin-panneau" id="panneau-personnalisation">
<h3>Cadres disponibles</h3> <h3>Cadres / Overlays</h3>
<p class="aide">Cochez les cadres a proposer aux utilisateurs.</p> <p class="aide">Cochez les cadres a proposer aux utilisateurs.</p>
<div id="liste-cadres" class="liste-cadres"> <div id="liste-cadres" class="liste-cadres">
<p class="texte-secondaire">Aucun cadre importe</p> <p class="texte-secondaire">Aucun cadre importe</p>
</div> </div>
<h3>Importer un cadre</h3>
<div class="champ"> <div class="champ">
<input type="file" id="input-cadre" accept=".png" class="input-fichier"> <input type="file" id="input-cadre" accept=".png" class="input-fichier">
<button class="btn-action" onclick="uploaderCadre()">Importer</button> <button class="btn-action" onclick="uploaderCadre()">Importer un cadre</button>
</div> </div>
</div>
<!-- Panneau Fonds verts --> <h3>Fonds (chroma key)</h3>
<div class="admin-panneau" id="panneau-fonds-admin"> <p class="aide">Importez des images de fond pour le mode fond vert.</p>
<h3>Fonds pour chroma key</h3>
<p class="aide">Importez des images de fond. Les utilisateurs choisiront leur fond apres la photo.</p>
<div id="liste-fonds" class="liste-fonds"> <div id="liste-fonds" class="liste-fonds">
<p class="texte-secondaire">Aucun fond importe</p> <p class="texte-secondaire">Aucun fond importe</p>
</div> </div>
<h3>Importer un fond</h3>
<div class="champ"> <div class="champ">
<input type="file" id="input-fond" accept=".jpg,.jpeg,.png" class="input-fichier"> <input type="file" id="input-fond" accept=".jpg,.jpeg,.png" class="input-fichier">
<button class="btn-action" onclick="uploaderFond()">Importer</button> <button class="btn-action" onclick="uploaderFond()">Importer un fond</button>
</div> </div>
</div>
<!-- Panneau Animations --> <h3>Animations 3-2-1</h3>
<div class="admin-panneau" id="panneau-animations-admin"> <p class="aide">Si plusieurs sont cochees, une sera choisie au hasard.</p>
<h3>Animations CSS</h3>
<p class="aide">Cochez les animations a utiliser. Si plusieurs sont cochees, une sera choisie au hasard a chaque photo.</p>
<div id="liste-animations" class="liste-animations"> <div id="liste-animations" class="liste-animations">
</div> </div>
<h4>Animations personnalisees (video/GIF)</h4>
<h3>Animations personnalisees (video/GIF)</h3>
<p class="aide">Importez vos propres animations (GIF, MP4, WebM). Elles seront jouees en plein ecran avant la capture.</p>
<div id="liste-animations-custom" class="liste-animations"> <div id="liste-animations-custom" class="liste-animations">
</div> </div>
<div class="champ"> <div class="champ">
<input type="file" id="input-animation" accept=".gif,.mp4,.webm" class="input-fichier"> <input type="file" id="input-animation" accept=".gif,.mp4,.webm" class="input-fichier">
<button class="btn-action" onclick="uploaderAnimation()">Importer</button> <button class="btn-action" onclick="uploaderAnimation()">Importer</button>
</div> </div>
<div class="animation-preview"> <div class="animation-preview">
<h4>Apercu</h4> <h4>Apercu</h4>
<div id="preview-animation" class="preview-animation-box"> <div id="preview-animation" class="preview-animation-box">
@@ -343,56 +416,50 @@
<button class="btn-action" onclick="sauvegarderEvenement()">Sauvegarder</button> <button class="btn-action" onclick="sauvegarderEvenement()">Sauvegarder</button>
</div> </div>
<!-- Panneau Fonctionnalites --> <!-- Panneau Fonctions (toggles + email + booth + galerie + systeme) -->
<div class="admin-panneau" id="panneau-fonctionnalites"> <div class="admin-panneau" id="panneau-fonctions">
<h3>Modes photo</h3>
<div class="toggle-groupe"> <div class="toggle-groupe">
<label class="toggle"><input type="checkbox" id="tog-photo-simple" checked><span class="toggle-slider"></span> Photo simple</label> <label class="toggle"><input type="checkbox" id="tog-photo-simple" checked><span class="toggle-slider"></span> Photo simple</label>
<label class="toggle"><input type="checkbox" id="tog-multi-shot"><span class="toggle-slider"></span> Multi-shot</label> <label class="toggle"><input type="checkbox" id="tog-multi-shot"><span class="toggle-slider"></span> Pellicule (multi-shot)</label>
<label class="toggle"><input type="checkbox" id="tog-filtres"><span class="toggle-slider"></span> Filtres</label> <label class="toggle"><input type="checkbox" id="tog-filtres"><span class="toggle-slider"></span> Filtres</label>
<label class="toggle"><input type="checkbox" id="tog-overlays"><span class="toggle-slider"></span> Overlays / Cadres</label> <label class="toggle"><input type="checkbox" id="tog-overlays"><span class="toggle-slider"></span> Overlays / Cadres</label>
<label class="toggle"><input type="checkbox" id="tog-chroma-key"><span class="toggle-slider"></span> Chroma key (fond vert)</label> <label class="toggle"><input type="checkbox" id="tog-chroma-key"><span class="toggle-slider"></span> Chroma key (fond vert)</label>
</div>
<h3>Partage</h3>
<div class="toggle-groupe">
<label class="toggle"><input type="checkbox" id="tog-impression"><span class="toggle-slider"></span> Impression</label> <label class="toggle"><input type="checkbox" id="tog-impression"><span class="toggle-slider"></span> Impression</label>
<label class="toggle"><input type="checkbox" id="tog-email"><span class="toggle-slider"></span> Email</label> <label class="toggle"><input type="checkbox" id="tog-email"><span class="toggle-slider"></span> Email</label>
<label class="toggle"><input type="checkbox" id="tog-qr-code"><span class="toggle-slider"></span> QR Code</label> <label class="toggle"><input type="checkbox" id="tog-qr-code"><span class="toggle-slider"></span> QR Code</label>
<label class="toggle"><input type="checkbox" id="tog-galerie"><span class="toggle-slider"></span> Galerie</label> <label class="toggle"><input type="checkbox" id="tog-galerie"><span class="toggle-slider"></span> Galerie locale</label>
</div> </div>
</div>
<!-- Panneau Email --> <h3>Email SMTP</h3>
<div class="admin-panneau" id="panneau-email-admin">
<div class="champ"><label>Serveur SMTP</label><input type="text" id="admin-smtp-host" placeholder="smtp.gmail.com"></div> <div class="champ"><label>Serveur SMTP</label><input type="text" id="admin-smtp-host" placeholder="smtp.gmail.com"></div>
<div class="champ"><label>Port</label><input type="number" id="admin-smtp-port" value="587"></div> <div class="champ"><label>Port</label><input type="number" id="admin-smtp-port" value="587"></div>
<div class="champ"><label>Utilisateur</label><input type="text" id="admin-smtp-user" placeholder="user@gmail.com"></div> <div class="champ"><label>Utilisateur</label><input type="text" id="admin-smtp-user" placeholder="user@gmail.com"></div>
<div class="champ"><label>Mot de passe</label><input type="password" id="admin-smtp-pass"></div> <div class="champ"><label>Mot de passe</label><input type="password" id="admin-smtp-pass"></div>
<div class="champ"><label>Expediteur</label><input type="text" id="admin-expediteur" placeholder="photobooth@event.com"></div> <div class="champ"><label>Expediteur</label><input type="text" id="admin-expediteur" placeholder="photobooth@event.com"></div>
<button class="btn-action" onclick="sauvegarderEmail()">Sauvegarder</button> <button class="btn-action" onclick="sauvegarderEmail()">Sauvegarder email</button>
</div>
<!-- Panneau Galerie Live (Booth) -->
<div class="admin-panneau" id="panneau-booth-admin">
<h3>Galerie Live</h3> <h3>Galerie Live</h3>
<p class="aide">Les photos sont envoyees en temps reel sur un site web. Les invites scannent le QR code sur l'ecran d'accueil.</p> <p class="aide">Photos envoyees en temps reel. QR code + code sur l'ecran d'accueil.</p>
<div class="champ"> <div class="champ">
<label class="toggle-label"> <label class="toggle"><input type="checkbox" id="admin-booth-actif" onchange="sauvegarderBooth()"><span class="toggle-slider"></span> Galerie live active</label>
<span>Activer la galerie live</span>
<label class="toggle"><input type="checkbox" id="admin-booth-actif" onchange="sauvegarderBooth()"><span class="toggle-slider"></span></label>
</label>
</div> </div>
<div class="champ"><label>URL du serveur</label><input type="text" id="admin-booth-url" placeholder="https://booth.copydev.fr" value="https://booth.copydev.fr"></div> <div class="champ"><label>URL du serveur</label><input type="text" id="admin-booth-url" placeholder="https://booth.copydev.fr" value="https://booth.copydev.fr"></div>
<div class="champ"><label>Cle API</label><input type="text" id="admin-booth-apikey" placeholder="booth-photobooth-2026" value="booth-photobooth-2026"></div> <div class="champ"><label>Cle API</label><input type="text" id="admin-booth-apikey" placeholder="booth-photobooth-2026" value="booth-photobooth-2026"></div>
<div class="champ"><label>ID evenement</label><input type="text" id="admin-booth-eventid" placeholder="default" value="default"></div> <div class="champ"><label>ID evenement</label><input type="text" id="admin-booth-eventid" placeholder="default" value="default"></div>
<div id="booth-status" class="champ"> <div class="champ">
<label>Code invites : <span id="admin-booth-password" style="font-size:1.5rem;font-weight:bold;letter-spacing:4px">--</span></label> <label>Code invites : <span id="admin-booth-password" style="font-size:1.5rem;font-weight:bold;letter-spacing:4px">--</span></label>
</div> </div>
<button class="btn-action" onclick="sauvegarderBooth()">Sauvegarder</button> <button class="btn-action" onclick="sauvegarderBooth()">Sauvegarder booth</button>
<button class="btn-secondaire" onclick="regenererBoothPassword()">Nouveau code</button> <button class="btn-secondaire" onclick="regenererBoothPassword()">Nouveau code</button>
</div>
<!-- Panneau Galerie --> <h3>Galerie locale</h3>
<div class="admin-panneau" id="panneau-galerie-admin">
<div class="champ"> <div class="champ">
<label>Photos prises : <span id="admin-nb-photos">0</span></label> <label>Photos prises : <span id="admin-nb-photos">0</span> | Exports : <span id="admin-nb-exports">0</span></label>
<label>Exports : <span id="admin-nb-exports">0</span></label>
</div> </div>
<div class="champ"> <div class="champ">
<label>URL galerie en ligne</label> <label>URL galerie en ligne</label>
@@ -400,10 +467,9 @@
</div> </div>
<button class="btn-action" onclick="sauvegarderGalerie()">Sauvegarder URL</button> <button class="btn-action" onclick="sauvegarderGalerie()">Sauvegarder URL</button>
<button class="btn-danger" onclick="confirmerViderGalerie()">Vider toute la galerie</button> <button class="btn-danger" onclick="confirmerViderGalerie()">Vider toute la galerie</button>
</div>
<!-- Panneau Systeme --> <h3>Systeme</h3>
<div class="admin-panneau" id="panneau-systeme"> <button class="btn-action" onclick="location.reload()">Mettre a jour l'affichage</button>
<button class="btn-danger" onclick="confirmerRedemarrage()">Redemarrer le systeme</button> <button class="btn-danger" onclick="confirmerRedemarrage()">Redemarrer le systeme</button>
<button class="btn-danger" onclick="confirmerExtinction()">Eteindre le systeme</button> <button class="btn-danger" onclick="confirmerExtinction()">Eteindre le systeme</button>
</div> </div>

View File

@@ -152,11 +152,11 @@ function validerMdpAdmin() {
const input = document.getElementById('input-mdp-admin'); const input = document.getElementById('input-mdp-admin');
if (input.value === MDP_ADMIN) { if (input.value === MDP_ADMIN) {
fermerPopupMdp(); fermerPopupMdp();
allerA('admin'); allerA('wizard');
wizardInit();
} else { } else {
document.getElementById('mdp-erreur').classList.remove('cache'); document.getElementById('mdp-erreur').classList.remove('cache');
input.value = ''; input.value = '';
input.focus();
} }
} }
@@ -252,5 +252,121 @@ wsOnMessage('config_maj', (msg) => {
appliquerConfig(); appliquerConfig();
}); });
// === WIZARD ===
let wizardStep = 1;
const WIZARD_TOTAL = 6;
let wizardData = {
nom: '',
theme: 'base',
modes: { simple: true, multi: true },
nbPhotos: 4,
fonctions: {},
};
function wizardInit() {
wizardStep = 1;
wizardData.nom = config.evenement?.nom || '';
wizardData.theme = config.evenement?.theme || 'base';
wizardData.nbPhotos = config.multi_shot?.nombre_photos || 4;
document.getElementById('wiz-nom').value = wizardData.nom;
document.getElementById('wiz-nb-photos').textContent = wizardData.nbPhotos;
wizardAfficherStep();
}
function wizardAfficherStep() {
document.querySelectorAll('.wizard-step').forEach(s => s.classList.remove('actif'));
const step = document.querySelector(`.wizard-step[data-step="${wizardStep}"]`);
if (step) step.classList.add('actif');
// Progress dots
const prog = document.getElementById('wizard-progress');
prog.innerHTML = '';
for (let i = 1; i <= WIZARD_TOTAL; i++) {
const dot = document.createElement('div');
dot.className = 'wizard-dot' + (i === wizardStep ? ' actif' : '') + (i < wizardStep ? ' fait' : '');
prog.appendChild(dot);
}
}
function wizardSuivant() {
// Sauvegarder l'etape courante
if (wizardStep === 1) wizardData.nom = document.getElementById('wiz-nom').value;
if (wizardStep === 4) wizardData.nbPhotos = parseInt(document.getElementById('wiz-nb-photos').textContent);
wizardStep++;
if (wizardStep > WIZARD_TOTAL) wizardStep = WIZARD_TOTAL;
// Resume
if (wizardStep === WIZARD_TOTAL) {
const modes = Object.keys(wizardData.modes).filter(k => wizardData.modes[k]);
const foncs = Object.keys(wizardData.fonctions).filter(k => wizardData.fonctions[k]);
document.getElementById('wiz-resume').innerHTML = `
<div><strong>Evenement :</strong> ${wizardData.nom || 'Photobooth'}</div>
<div><strong>Theme :</strong> ${wizardData.theme}</div>
<div><strong>Modes :</strong> ${modes.join(', ') || 'photo'}</div>
<div><strong>Photos/pellicule :</strong> ${wizardData.nbPhotos}</div>
<div><strong>Partage :</strong> ${foncs.join(', ') || 'aucun'}</div>
`;
}
wizardAfficherStep();
}
function wizardChoisir(btn, key) {
btn.closest('.wizard-choix').querySelectorAll('.wizard-card').forEach(c => c.classList.remove('actif'));
btn.classList.add('actif');
wizardData[key] = btn.dataset.val;
}
function wizardToggle(btn) {
btn.classList.toggle('actif');
const val = btn.dataset.val;
const isActive = btn.classList.contains('actif');
if (['simple', 'multi'].includes(val)) {
wizardData.modes[val] = isActive;
} else {
wizardData.fonctions[val] = isActive;
}
}
function wizardNbPhotos(delta) {
const el = document.getElementById('wiz-nb-photos');
let n = parseInt(el.textContent) + delta;
n = Math.max(2, Math.min(8, n));
el.textContent = n;
wizardData.nbPhotos = n;
}
async function wizardTerminer() {
// Sauvegarder toute la config
await apiPost('/api/config', {
evenement: {
nom: wizardData.nom || 'Photobooth',
theme: wizardData.theme,
},
fonctionnalites: {
photo_simple: wizardData.modes.simple !== false,
multi_shot: wizardData.modes.multi !== false,
impression: !!wizardData.fonctions.impression,
email: !!wizardData.fonctions.email,
qr_code: !!wizardData.fonctions.qr,
},
multi_shot: {
nombre_photos: wizardData.nbPhotos,
mode: 'strip',
},
booth: {
actif: !!wizardData.fonctions.galerie_live,
},
});
config = await apiGet('/api/config');
appliquerConfig();
chargerBoothInfo();
allerA('accueil');
}
// Demarrage // Demarrage
document.addEventListener('DOMContentLoaded', init); document.addEventListener('DOMContentLoaded', init);