Onboarding guidé systématique + tableau de bord simplifié
Comportement SYSTÉMATIQUE à chaque création de jeu (admin compris), pas une formalité réservée à l'inscription : /onboarding (routes/onboarding/) devient le point d'entrée unique — 4 cartes retournables (survol = explication au dos), défilement horizontal animé vers le nom du jeu. Un admin y repasse à volonté (pas de project_slug dédié, jamais bloqué/ redirigé vers un projet précédent) ; un compte "user" n'en a plus qu'un créé d'office (routes/auth/register_2fa.py), guidé ici à la place. - db/games/game_type_catalog.py : catalogue des 4 types (Quiz/ Embranchement-escape game/RPG/Créer mon jeu de A à Z), _meta['onboarding_type'] décide du "kind" du premier écran créé et si le tableau de bord complet reste accessible. - routes/games/game_dashboard.py, templates/game_dashboard_simple.html : un type restreint (quiz/embranchement/rpg) voit désormais SON tableau de bord (même route que "custom"), rendu en version simplifiée — juste ses écrans en cartes avec un aperçu RÉEL du contenu (scène mise à l'échelle par container query CSS, adaptée à la largeur réelle de la carte). "+ Ajouter un écran" n'y propose pas de choix de type : imposé par le projet (routes/screens/screens_new.py), verrouillé aussi côté serveur. - core/auth_guard.py : plus de blocage de game_dashboard par type — la restriction se fait au rendu, pas à l'accès à la route. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
0f23024882
commit
76a50fa87a
@@ -0,0 +1,65 @@
|
||||
// Onboarding guidé (templates/onboarding/onboarding_new.html) — interactions
|
||||
// pures DOM, aucune logique métier ici (voir routes/onboarding/
|
||||
// onboarding_new.py pour la validation réelle, côté serveur). Deux
|
||||
// "pages" (choix du type / nom du jeu) posées côte à côte dans
|
||||
// #onboardingTrack, révélées par un défilement horizontal animé en CSS
|
||||
// (voir .onboardingTrack--step2 dans static/style.css) plutôt qu'un vrai
|
||||
// changement de page — pas de rechargement, pas d'aller-retour serveur
|
||||
// tant que le formulaire n'est pas soumis pour de vrai.
|
||||
|
||||
function forgeOnboardingGoToStep(step) {
|
||||
var track = document.getElementById("onboardingTrack");
|
||||
if (track) track.classList.toggle("onboardingTrack--step2", step === 2);
|
||||
if (step === 2) {
|
||||
var nameField = document.getElementById("onboardingNameInput");
|
||||
// Après la fin de l'animation de défilement (voir la durée de
|
||||
// transition posée sur .onboardingTrack) — focus immédiat plus tôt
|
||||
// ferait sauter le scroll du champ à moitié visible.
|
||||
if (nameField) setTimeout(function () { nameField.focus(); }, 500);
|
||||
}
|
||||
}
|
||||
|
||||
function forgeOnboardingChooseType(card) {
|
||||
document.querySelectorAll(".onboardingCard").forEach(function (c) {
|
||||
c.classList.toggle("is-selected", c === card);
|
||||
});
|
||||
var hiddenType = document.getElementById("onboardingTypeHidden");
|
||||
if (hiddenType) hiddenType.value = card.dataset.type || "";
|
||||
forgeOnboardingUpdateSubmitState();
|
||||
forgeOnboardingGoToStep(2);
|
||||
}
|
||||
|
||||
function forgeOnboardingUpdateSubmitState() {
|
||||
var nameField = document.getElementById("onboardingNameInput");
|
||||
var hiddenType = document.getElementById("onboardingTypeHidden");
|
||||
var submitBtn = document.getElementById("onboardingSubmitBtn");
|
||||
if (!nameField || !hiddenType || !submitBtn) return;
|
||||
submitBtn.disabled = !(hiddenType.value && nameField.value.trim());
|
||||
}
|
||||
|
||||
function forgeOnboardingInit() {
|
||||
// Appelé directement (pas de DOMContentLoaded) : ce fichier est chargé
|
||||
// par un <script src> posé à la fin du contenu de la page — les
|
||||
// éléments dont on a besoin existent déjà à ce stade. Nécessaire aussi
|
||||
// pour la navigation pjax (voir static/pjax.js — runScriptsIn
|
||||
// ré-exécute ce script à chaque page swappée, mais DOMContentLoaded,
|
||||
// lui, ne se redéclenche jamais après le tout premier chargement réel).
|
||||
|
||||
// Entrée en cascade des cartes — délai posé en JS plutôt qu'en CSS pur
|
||||
// (nth-child) pour rester correct quel que soit le nombre de types
|
||||
// affichés (voir db.ONBOARDING_TYPES, appelé à générer la liste).
|
||||
document.querySelectorAll(".onboardingCard").forEach(function (card, i) {
|
||||
card.style.animationDelay = (i * 70) + "ms";
|
||||
card.addEventListener("click", function () { forgeOnboardingChooseType(card); });
|
||||
});
|
||||
|
||||
var backBtn = document.getElementById("onboardingBackBtn");
|
||||
if (backBtn) backBtn.addEventListener("click", function () { forgeOnboardingGoToStep(1); });
|
||||
|
||||
var nameField = document.getElementById("onboardingNameInput");
|
||||
if (nameField) nameField.addEventListener("input", forgeOnboardingUpdateSubmitState);
|
||||
|
||||
forgeOnboardingUpdateSubmitState();
|
||||
}
|
||||
|
||||
forgeOnboardingInit();
|
||||
Reference in New Issue
Block a user