From 61b6ec23ebaa6e3d9d59ed897fdffc46c981844a Mon Sep 17 00:00:00 2001 From: breitenbach76 Date: Tue, 9 Jun 2026 12:36:55 +0200 Subject: [PATCH] v22 --- 04_Tablet-Quiz/app/index.html | 85 ++++++++++++++++++++++++++--------- 04_Tablet-Quiz/app/sw.js | 2 +- 2 files changed, 66 insertions(+), 21 deletions(-) diff --git a/04_Tablet-Quiz/app/index.html b/04_Tablet-Quiz/app/index.html index 1659664..664683b 100644 --- a/04_Tablet-Quiz/app/index.html +++ b/04_Tablet-Quiz/app/index.html @@ -173,8 +173,9 @@ .pfad b { display:block; } /* ---- Minimal Run-Screens ---- */ - .sHead{display:flex;align-items:center;gap:10px} - .sHead .sId{color:var(--muted);font-size:13px;font-variant-numeric:tabular-nums} + .sHead{display:flex;align-items:center;gap:12px;flex-wrap:wrap} + .sHead .phaseChip{font-size:15px;padding:8px 18px;letter-spacing:.8px} + .sHead .sId{color:var(--ink);font-size:18px;font-weight:800;font-variant-numeric:tabular-nums} .sTitle{font-size:22px;font-weight:700;line-height:1.25;margin:10px 0 4px} .caseLine{color:var(--muted);font-size:13px;margin:0 0 22px} .lead{font-size:16px;margin:0 0 16px} @@ -182,6 +183,13 @@ .todo li{margin:8px 0} .crit{margin:8px 0 0;padding-left:20px;color:var(--muted)} .crit li{margin:4px 0} + .critHead{font-size:13px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.5px;margin:16px 0 8px} + .gateCrit{display:flex;flex-direction:column;gap:8px;margin:0 0 16px} + .critItem{display:flex;align-items:flex-start;gap:10px;text-align:left;padding:11px 14px;border:1px solid var(--line);border-radius:10px;background:var(--soft);color:var(--ink);cursor:pointer;font-size:14px;line-height:1.45;animation:critIn .22s ease} + .critItem:hover{border-color:#c9d2dd} + .critItem.checked{border-color:rgba(31,157,87,.4);background:var(--okBg)} + .critItem .critBox{font-size:17px;flex:none;line-height:1.25} + @keyframes critIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}} details.det{margin:8px 0 4px;border-top:1px solid var(--line);padding-top:12px} details.det>summary{cursor:pointer;color:var(--muted);font-size:14px;font-weight:600;list-style:none} details.det>summary::-webkit-details-marker{display:none} @@ -613,8 +621,8 @@ const STATIONEN = [ expl:"Early Life Support = erhöhte Betreuung direkt nach Go-Live (siehe op_01)."} ]}, { id:"tr_01", phase:"transition", typ:"gate", gateNr:1, - name:"Gate 1: Entwicklung oder Konfiguration?", - beschreibung:"Entry-Gate der Transition: Entscheidung, ob die Service-Komponenten entwickelt oder nur konfiguriert werden. Erfordert SOR-Approval (Budget- und Ressourcenimplikationen).", + name:"Gate 1: Darf es in die Transition?", + beschreibung:"Entry-Gate der Transition: Die SOR entscheidet zuerst, ob das Vorhaben überhaupt in die Transition darf — und wenn ja, ob die Service-Komponenten neu entwickelt oder nur konfiguriert werden. Erfordert SOR-Approval (Budget- und Ressourcenimplikationen).", umfasst:["Aufwandsschätzung (Build vs. Configure)","Technische Risiken","Budget-Abgleich","ggf. Lieferanten-Einbindung","SOR-Vorlage für Freigabe"], artefakt:"Gate-Entscheidung + SOR-Vorlage", pfade:[ @@ -1135,7 +1143,7 @@ function defaultState(){ freigabeDone:false, freigabeWrong:null, entryDone:false, entryWrong:null, bonusReveal:false, bonusDone:{}, servicesDone:{}, akteFlash:null, - index:0, stage:"discuss", quizIndex:0, + index:0, stage:"discuss", quizIndex:0, gateDeciderDone:false, gateCrit:0, actStep:0, actReveal:false, actDone:false, arteWrong:null, picks:{}, done:{}, akte:{}, loopback:null, revisit:{}, endReason:null, endGate:null }; @@ -1495,7 +1503,7 @@ function renderBonusPick(){ const done = S.bonusDone && S.bonusDone[ci]; return ``; }).join(""); @@ -1512,7 +1520,7 @@ function renderBonusPick(){ `; $("#panel").querySelectorAll(".bonusCard").forEach(el=>{ el.onclick=()=>{ S.change=+el.dataset.c; S.mode="bonus"; - S.classifyDone=true; S.classifyWrong=null; // Typ ist auf der Karte ausgewiesen → nur Begründung, kein Quiz + S.classifyDone=false; S.classifyWrong=null; // Change-Art ist auf der Karte verdeckt → Gruppe bestimmt sie selbst (Quiz) S.freigabeDone=false; S.freigabeWrong=null; S.entryDone=false; S.entryWrong=null; S.bonusReveal=false; S.view="classify"; save(); draw(); }; @@ -1584,7 +1592,7 @@ function enterStation(idx){ } S.index = idx; S.stage = STATIONEN[idx].typ==="gate" ? "gate" : "act"; - S.gatePick = null; S.quizIndex = 0; + S.gatePick = null; S.quizIndex = 0; S.gateDeciderDone = false; S.gateCrit = 0; S.actStep = 0; S.actReveal = false; S.actDone = false; S.arteWrong = null; S.akteFlash = null; document.body.classList.remove("akteOpen"); } @@ -1773,7 +1781,28 @@ function renderActivity(st){ /* Gate — Entscheidung nach Kriterien */ function renderGate(st){ const keeper = (st.raci.find(([r,c])=>c==="A")||[])[0]; - const pruef = (st.pruef||[]).map(([n,d])=>`
  • ${n} — ${d}
  • `).join(""); + const sorNote = (keeper==="sor") + ? `

    Die SOR ist ein Gremium (SPM · Betrieb · Support-Manager · Service Owner …), das am Gate-Puck zusammenkommt — keine Einzelfigur.

    ` : ``; + const revisitNote = (S.revisit && S.revisit[st.id]) + ? `
    ↩ Erneute Vorlage nach Nacharbeit — prüft erneut und entscheidet neu.
    ` : ``; + + // Schritt 1: Entscheider ermitteln (nur Aufforderung — Figuren auf den Gate-Puck) + if(!S.gateDeciderDone){ + return ` + ${revisitNote} +
    +
    Schritt 1 · Entscheider ermitteln
    + Wer entscheidet an diesem Gate? Stellt die Entscheider-Figur(en) auf den Gate-Puck. +
    +

    Entscheidet: ${roleLabel(keeper)}

    + ${sorNote} +
    +
    + +
    `; + } + + // Schritt 2: Prüf-Kriterien (nacheinander) + Entscheidung // Harte Artefakt-Kopplung: Gate "oeffnet" nur mit den geforderten Artefakten in der Akte. const req = GATE_REQ[st.id] || []; const missing = req.filter(a => !(S.akte && S.akte[a])); @@ -1783,21 +1812,31 @@ function renderGate(st){ const reqLine = req.length === 0 ? `` : blocked ? `
    🔒 Gate öffnet nicht — es fehlt in der Akte: ${missing.map(a=>a+" "+ARTEFAKTE[a].name).join(" · ")}. Erzeugt diese Artefakte zuerst.
    ` : `
    ✓ Alle geforderten Artefakte liegen in der Akte (${req.join(" · ")}).
    `; - const revisitNote = (S.revisit && S.revisit[st.id]) - ? `
    ↩ Erneute Vorlage nach Nacharbeit — prüft erneut und entscheidet neu.
    ` : ``; + + // Prüf-Kriterien als nacheinander erscheinende Checkboxen (nur Anzeige, nicht blockierend) + const pruef = st.pruef || []; + const shown = Math.min(S.gateCrit||0, pruef.length); // Anzahl abgehakter Kriterien + const critItems = pruef.map(([n,d],i)=>{ + if(i > shown) return ""; // noch nicht eingeblendet + const checked = i < shown; + return ``; + }).join(""); + const allChecked = pruef.length>0 && shown >= pruef.length; + const critWrap = pruef.length ? ` +
    Worum geht's & Prüf-Kriterien
    +

    ${st.beschreibung}

    +
    ${critItems}
    + ${allChecked?`

    Alle Kriterien geprüft. Geforderte Artefakte in der Akte (siehe oben)? Pflicht-Figuren am Gate-Puck?

    `:``}` : ``; + return ` ${revisitNote}

    Entscheidet: ${roleLabel(keeper)}

    ${reqLine} -
    ${opts}
    -
    - Worum geht's & Prüf-Kriterien -
    -

    ${st.beschreibung}

    -
      ${pruef}
    -

    Geforderte Artefakte in der Akte (siehe oben)? Pflicht-Figuren am Gate-Puck?

    -
    -
    `; + ${critWrap} +
    ${opts}
    `; } /* Gate — Konsequenz der Entscheidung */ @@ -1859,6 +1898,12 @@ function wire(st){ if(b("nextStation")) b("nextStation").onclick = ()=>{ S.done[st.id]=true; enterStation(S.index+1); save(); draw(); }; if(b("finish")) b("finish").onclick = ()=>{ S.done[st.id]=true; S.view="end"; S.endReason="done"; save(); draw(); }; // Gate + if(b("gateDeciderNext")) b("gateDeciderNext").onclick = ()=>{ S.gateDeciderDone=true; save(); draw(); }; + $("#panel").querySelectorAll(".critItem[data-ci]").forEach(el=>{ + el.onclick = ()=>{ const i=+el.dataset.ci; + S.gateCrit = (i < (S.gateCrit||0)) ? i : i+1; // abgehaktes wieder lösen vs. nächstes aufdecken + save(); draw(); }; + }); $("#panel").querySelectorAll(".choiceGrid .choice[data-i]").forEach(el=>{ el.onclick = ()=>{ S.gatePick=+el.dataset.i; S.stage="gateDone"; save(); draw(); }; }); diff --git a/04_Tablet-Quiz/app/sw.js b/04_Tablet-Quiz/app/sw.js index ad19a2b..4ad784b 100644 --- a/04_Tablet-Quiz/app/sw.js +++ b/04_Tablet-Quiz/app/sw.js @@ -1,5 +1,5 @@ /* Service Worker — SLC-Workshop Companion (App-Shell, offline-first) */ -const CACHE = "slc-companion-v28"; +const CACHE = "slc-companion-v29"; const SHELL = ["./", "index.html", "manifest.webmanifest", "icon.svg"]; // Action-Card-Grafiken (cards/s-c.png) fuer Offline vorab cachen (alle 24). const CARDS = [];