diff --git a/server/pruef-kalender.mjs b/server/pruef-kalender.mjs index 557a660b..25787abc 100644 --- a/server/pruef-kalender.mjs +++ b/server/pruef-kalender.mjs @@ -240,6 +240,93 @@ for (const [breite, wie] of [[1440, "Computer"], [390, "Handy"]]) { await seite.click('.k-ansicht[data-ansicht="monat"]'); await seite.waitForTimeout(400); + /* ---- BLAETTERN DIREKT UEBER DEM KALENDER (09.09.2026) -------------- + Filipe, mit Bildschirmfoto: "ich will dass genau da ueber dem + kalender auch noch buttons sind um den monat zu wechseln, tage + wechseln ... die einen rot und die anderen gruen von den neuen." + + Die Pfeile gab es schon -- oben neben der Ueberschrift, einen + halben Bildschirm entfernt von dem Raster, das sie bewegen. + + Geprueft wird nicht nur, DASS die Knoepfe da sind, sondern dass + ihre Beschriftung die Wahrheit sagt: Ein Pfeil verspricht keinen + Sprungweite, ein Wort schon. Steht "Monat vor" und es springt eine + Woche, ist das schlimmer als gar keine Beschriftung. */ + { + const vorher = await seite.textContent("#zeitraum"); + await seite.click("#schritt-vor"); + await seite.waitForTimeout(700); + const nachher = await seite.textContent("#zeitraum"); + ok(vorher !== nachher, `der gruene Knopf blaettert weiter ("${vorher}" -> "${nachher}")`); + + const b = await seite.evaluate(() => ({ + zurueck: document.getElementById("schritt-zurueck-text")?.textContent, + vor: document.getElementById("schritt-vor-text")?.textContent, + heuteAus: document.getElementById("schritt-heute")?.disabled, + })); + ok(b.zurueck === "Monat zurück" && b.vor === "Monat vor", + `und die Beschriftung nennt die Schrittweite ("${b.zurueck}" / "${b.vor}")`); + ok(b.heuteAus === false, "Heute ist jetzt anklickbar, weil man woanders steht"); + + await seite.click("#schritt-zurueck"); + await seite.waitForTimeout(700); + const zurueck = await seite.textContent("#zeitraum"); + ok(zurueck === vorher, `der rote Knopf blaettert zurueck ("${zurueck}")`); + const wiederDa = await seite.evaluate(() => + document.getElementById("schritt-heute")?.disabled); + ok(wiederDa === true, + "und Heute ist wieder ausgegraut -- ein Knopf, der nichts tut, wird sonst nie ernst genommen"); + + /* DIE BESCHRIFTUNG FOLGT DER ANSICHT. In der Wochenansicht ist ein + Schritt eine Woche -- steht dort weiter "Monat", luegt der Knopf. */ + await seite.click('.k-ansicht[data-ansicht="woche"]'); + await seite.waitForTimeout(600); + const w = await seite.evaluate(() => ({ + zurueck: document.getElementById("schritt-zurueck-text")?.textContent, + vor: document.getElementById("schritt-vor-text")?.textContent, + })); + ok(w.zurueck === "Woche zurück" && w.vor === "Woche vor", + `in der Wochenansicht heissen sie anders ("${w.zurueck}" / "${w.vor}")`); + + /* Und sie springt dort wirklich eine Woche, nicht einen Monat. */ + const wVor = await seite.textContent("#zeitraum"); + await seite.click("#schritt-vor"); + await seite.waitForTimeout(700); + const wNach = await seite.textContent("#zeitraum"); + ok(wVor !== wNach, `der Schritt wirkt auch dort ("${wVor}" -> "${wNach}")`); + + await seite.click('.k-ansicht[data-ansicht="monat"]'); + await seite.waitForTimeout(500); + await seite.click("#schritt-heute"); + await seite.waitForTimeout(700); + + /* ROT UND GRUEN, an echten Bildpunkten. Eine Farbe im Stylesheet + sagt nichts darueber, was am Bildschirm ankommt -- dieselbe + Lehre wie beim Rollenstreifen der Personenkachel. */ + const farben = await seite.evaluate(() => { + const lies = (id) => { + const c = document.createElement("canvas"); + c.width = 1; c.height = 1; + const g = c.getContext("2d", { willReadFrequently: true }); + g.fillStyle = "#000000"; + g.fillStyle = getComputedStyle(document.getElementById(id)).color; + g.fillRect(0, 0, 1, 1); + const p = g.getImageData(0, 0, 1, 1).data; + return [p[0], p[1], p[2]]; + }; + return { rot: lies("schritt-zurueck"), gruen: lies("schritt-vor") }; + }); + ok(farben.rot[0] > farben.rot[1] + 25 && farben.rot[0] > farben.rot[2] + 25, + `der Zurueck-Knopf ist wirklich rot (rgb(${farben.rot}))`); + ok(farben.gruen[1] > farben.gruen[0] + 25 && farben.gruen[1] > farben.gruen[2] + 25, + `der Vor-Knopf ist wirklich gruen (rgb(${farben.gruen}))`); + + /* GEGENPROBE: Die beiden sind NICHT dieselbe Farbe. Ohne sie hiesse + "rot" und "gruen" nur, dass zweimal etwas gemessen wurde. */ + const abstand = farben.rot.reduce((s, x, i) => s + Math.abs(x - farben.gruen[i]), 0); + ok(abstand > 120, `und die beiden unterscheiden sich deutlich (Abstand ${abstand})`); + } + /* ---- Tagesdialog ---- */ await seite.click(`.k-tag[data-tag="${heute}"]`); await seite.waitForTimeout(300); diff --git a/workspace/assets/css/kalender.css b/workspace/assets/css/kalender.css index 41c14620..12367b6c 100644 --- a/workspace/assets/css/kalender.css +++ b/workspace/assets/css/kalender.css @@ -1411,3 +1411,138 @@ inset 0 1px 0 rgba(200, 230, 255, .14), inset 0 0 22px -8px color-mix(in srgb, var(--akzent) 55%, transparent); } + +/* ===================================================================== + BLÄTTERN DIREKT ÜBER DEM KALENDER (09.09.2026) + + Filipe, mit Bildschirmfoto: "ich will dass genau da über dem kalender + auch noch buttons sind um den monat zu wechseln, tage wechseln. + perfektionnier mir das bitte. und mach auch die buttons die schon da + sind noch viel klarer bitte und die neuen auch. lass die neuen auch + richtig geil aussehen, die einen rot und die anderen grün." + + ROT UND GRÜN, aber nicht Signalrot und Grasgrün: Diese beiden Knöpfe + stehen den ganzen Tag auf dem Bildschirm. Genommen sind deshalb die + Haustöne -- das gedeckte Rot der Warnfarbe und das Grün der + Scout-Rolle. Beide sind hell genug für Schrift auf dunklem Grund und + leuchten nicht. + + Die Richtung steckt zusätzlich in der FORM, nicht nur in der Farbe: + Der Pfeil steht links beim Zurück und rechts beim Vor. Wer Rot und + Grün nicht unterscheidet -- etwa acht Prozent der Männer --, liest + die Richtung trotzdem. + ===================================================================== */ +.k-schritte { + display: inline-flex; align-items: stretch; gap: 6px; + flex-wrap: wrap; +} +.k-schritt { + --s: var(--text-leise); + display: inline-flex; align-items: center; gap: 7px; + min-height: 38px; padding: 8px 15px; + border: 1px solid color-mix(in srgb, var(--s) 42%, transparent); + border-radius: 999px; + background: + linear-gradient(180deg, + color-mix(in srgb, var(--s) 15%, transparent), + color-mix(in srgb, var(--s) 7%, transparent)); + color: color-mix(in srgb, var(--s) 88%, #ffffff); + font: inherit; font-size: .86rem; font-weight: 650; + cursor: pointer; + transition: border-color var(--tempo), background var(--tempo), transform var(--tempo); +} +.k-schritt:hover:not(:disabled) { + border-color: color-mix(in srgb, var(--s) 72%, transparent); + background: + linear-gradient(180deg, + color-mix(in srgb, var(--s) 24%, transparent), + color-mix(in srgb, var(--s) 12%, transparent)); + transform: translateY(-1px); +} +.k-schritt:active:not(:disabled) { transform: translateY(0); } +.k-schritt:focus-visible { + outline: 2px solid color-mix(in srgb, var(--s) 70%, #ffffff); + outline-offset: 2px; +} +.k-schritt:disabled { opacity: .42; cursor: default; } +/* Der Pfeil ist größer als die Schrift -- er ist das, was man aus dem + Augenwinkel trifft. */ +.k-schritt__pfeil { font-size: 1.15rem; line-height: 1; opacity: .9; } + +.k-schritt--zurueck { --s: #ef8b93; } /* gedecktes Rot des Hauses */ +.k-schritt--vor { --s: #5fc99a; } /* das Grün der Scout-Rolle */ +.k-schritt--heute { --s: #9fb0c6; } /* neutral: es ist kein Schritt */ + +@media (max-width: 620px) { + /* Am Handy zählt die Richtung, nicht das Wort -- und die Leiste soll + nicht umbrechen. + + Aus dem Wort wird aber KEIN schmaler Rest: Der erste Anlauf liess + die Polsterung stehen, und übrig blieb ein 30 px breites Pillchen + mit einem winzigen Pfeil darin -- kleiner als das, was man mit dem + Daumen sicher trifft, und die Farbe war auf der Fläche kaum noch zu + sehen. Jetzt ein rundes Ziel von 44 px mit einem Pfeil, der die + Fläche auch füllt. */ + .k-schritt__text { display: none; } + .k-schritt--zurueck, .k-schritt--vor { + width: 44px; min-width: 44px; height: 44px; padding: 0; + justify-content: center; gap: 0; + } + .k-schritt--zurueck .k-schritt__pfeil, + .k-schritt--vor .k-schritt__pfeil { font-size: 1.5rem; opacity: 1; } + .k-schritt--heute { min-height: 44px; padding: 8px 18px; } +} + +/* ===================================================================== + UND DIE VORHANDENEN KNÖPFE WERDEN KLARER + + "mach auch die buttons die schon da sind noch viel klarer bitte." + + Der Ansichts-Umschalter: Die drei nicht gewählten Knöpfe waren nackte + Schrift auf dunklem Grund -- sie sahen aus wie Beschriftungen, nicht + wie Schaltflächen. Wer nicht weiß, dass "Woche" anklickbar ist, + klickt nicht darauf. Sie bekommen jetzt eine eigene Fläche; die + gewählte bleibt unverändert das gebürstete Metall und hebt sich + dadurch sogar deutlicher ab als vorher. + ===================================================================== */ +.k-ansicht { + border: 1px solid rgba(150, 186, 220, .16); + background: rgba(255, 255, 255, .035); + color: var(--text-leise); + padding: 8px 16px; +} +.k-ansicht:hover:not([aria-pressed="true"]) { + color: var(--text); + border-color: rgba(150, 186, 220, .34); + background: rgba(255, 255, 255, .07); +} +.k-ansicht[aria-pressed="true"] { border-color: transparent; } + +/* Die Filterknöpfe: Die Beschriftung stand auf --text-still und war + damit die leiseste Schrift der Seite -- ausgerechnet an einem + Bedienelement. Und "aus" unterschied sich nur am hohlen Punkt. */ +.k-chip { + color: var(--text-leise); + padding: 8px 15px; + border-color: rgba(150, 186, 220, .2); +} +.k-chip:hover { color: var(--text); border-color: rgba(150, 186, 220, .4); } +.k-chip[aria-pressed="true"] { + color: #ffffff; + border-color: color-mix(in srgb, var(--cfarbe) 55%, transparent); + background: color-mix(in srgb, var(--cfarbe) 15%, transparent); + font-weight: 650; +} +/* Ausgeschaltet heisst: durchgestrichen wäre zu viel, aber die Zahl + gehört gedämpft -- sonst zählt man Einträge, die gerade nicht + angezeigt werden. */ +.k-chip[aria-pressed="false"] { opacity: .72; } +.k-chip[aria-pressed="false"]:hover { opacity: 1; } + +@media (prefers-reduced-motion: reduce) { + .k-schritt, .k-schritt:hover { transition: none; transform: none; } +} +@media (forced-colors: active) { + .k-schritt { border: 1px solid ButtonText; background: ButtonFace; color: ButtonText; } + .k-ansicht { border: 1px solid ButtonText; } +} diff --git a/workspace/assets/js/kalender.js b/workspace/assets/js/kalender.js index 58518635..0aa01b49 100644 --- a/workspace/assets/js/kalender.js +++ b/workspace/assets/js/kalender.js @@ -1223,6 +1223,11 @@ async function laden() { melde(''); + /* Die Beschriftung der Schrittknoepfe folgt dem Zustand -- nach + jedem Sprung und jedem Umschalten. Sie hier zu setzen und nicht + an jeder Aufrufstelle heisst: Es gibt genau EINEN Ort, an dem sie + stimmen muss. */ + schrittBeschriften(); const { von, bis } = zeitraum(); const tage = Math.round((ausText(bis) - ausText(von)) / 86400000) + 1; try { @@ -1271,12 +1276,52 @@ $('vor-zeit').addEventListener('click', () => springen(1)); $('heute-knopf').addEventListener('click', () => { anker = heuteText(); laden(); }); + /* ---------- Blättern direkt über dem Kalender (09.09.2026) ------------- + Filipe: "ich will dass genau da über dem kalender auch noch buttons + sind um den monat zu wechseln, tage wechseln." + + DIESELBE Funktion wie oben, nur an der Stelle, an der man hinsieht. + `springen()` wird nicht kopiert, sondern gerufen -- zwei Fassungen + desselben Schritts wären zwei Gelegenheiten, dass die eine später + anders springt als die andere. + + Beschriftet, nicht nur bepfeilt: Ein Pfeil sagt nicht, wie weit er + springt. In der Monatsansicht ist ein Schritt ein Monat, in der + Woche eine Woche, in Liste und Zeitstrahl sechs Wochen -- das steht + drauf und wird beim Umschalten mitgeführt. */ + const SCHRITT_NAME = { + monat: 'Monat', woche: 'Woche', liste: 'Zeitraum', zeitstrahl: 'Zeitraum', + }; + function schrittBeschriften() { + const wort = SCHRITT_NAME[ansicht] || 'Zeitraum'; + const z = $('schritt-zurueck-text'); + const v = $('schritt-vor-text'); + if (z) z.textContent = `${wort} zurück`; + if (v) v.textContent = `${wort} vor`; + $('schritt-zurueck')?.setAttribute('aria-label', `Einen ${wort} zurück`); + $('schritt-vor')?.setAttribute('aria-label', `Einen ${wort} vor`); + /* "Heute" tritt zurück, solange man schon dort steht -- ein Knopf, + der nichts tut, ist ein Knopf, den man einmal drückt und danach + nicht mehr ernst nimmt. Ausgegraut statt versteckt: Sonst + springen die drei Knöpfe beim Blättern in der Breite. */ + const daheim = anker === heuteText(); + const h = $('schritt-heute'); + if (h) { + h.disabled = daheim; + h.title = daheim ? 'Du bist bereits beim heutigen Tag.' : 'Zurück zum heutigen Tag'; + } + } + $('schritt-zurueck')?.addEventListener('click', () => springen(-1)); + $('schritt-vor')?.addEventListener('click', () => springen(1)); + $('schritt-heute')?.addEventListener('click', () => { anker = heuteText(); laden(); }); + for (const b of document.querySelectorAll('.k-ansicht')) { b.addEventListener('click', () => { ansicht = b.dataset.ansicht; for (const x of document.querySelectorAll('.k-ansicht')) { x.setAttribute('aria-pressed', String(x === b)); } + schrittBeschriften(); laden(); }); } diff --git a/workspace/aufgaben.html b/workspace/aufgaben.html index 88e579f3..997ccf0e 100644 --- a/workspace/aufgaben.html +++ b/workspace/aufgaben.html @@ -14,10 +14,10 @@ - - - - + + + + @@ -231,10 +231,10 @@ - - - - - + + + + + diff --git a/workspace/automation.html b/workspace/automation.html index b303929b..6a5e9e65 100644 --- a/workspace/automation.html +++ b/workspace/automation.html @@ -14,11 +14,11 @@ - - - - - + + + + + @@ -140,10 +140,10 @@ - - - - - + + + + + diff --git a/workspace/bereich.html b/workspace/bereich.html index 4e176db7..ab410a06 100644 --- a/workspace/bereich.html +++ b/workspace/bereich.html @@ -14,11 +14,11 @@ - - - - - + + + + + @@ -149,14 +149,14 @@ - - - - - - - - - + + + + + + + + + diff --git a/workspace/calls.html b/workspace/calls.html index 49222c1c..e24e443a 100644 --- a/workspace/calls.html +++ b/workspace/calls.html @@ -14,11 +14,11 @@ - - - - - + + + + + @@ -82,11 +82,11 @@ - - - - - - + + + + + + diff --git a/workspace/chat.html b/workspace/chat.html index 237c66a0..e540e5ca 100644 --- a/workspace/chat.html +++ b/workspace/chat.html @@ -14,17 +14,17 @@ - - + + - - - + + + @@ -247,10 +247,10 @@ - - - - - + + + + + diff --git a/workspace/content.html b/workspace/content.html index 1299bbaa..9228b5ae 100644 --- a/workspace/content.html +++ b/workspace/content.html @@ -14,11 +14,11 @@ - - - - - + + + + + @@ -172,12 +172,12 @@ - - - - - - - + + + + + + + diff --git a/workspace/dateien.html b/workspace/dateien.html index 65245fb7..a993fdb7 100644 --- a/workspace/dateien.html +++ b/workspace/dateien.html @@ -14,11 +14,11 @@ - - - - - + + + + + @@ -101,10 +101,10 @@ - - - - - + + + + + diff --git a/workspace/index.html b/workspace/index.html index 4eb56359..e2bb6ce6 100644 --- a/workspace/index.html +++ b/workspace/index.html @@ -32,7 +32,7 @@ - + @@ -401,6 +401,6 @@ - + diff --git a/workspace/kalender.html b/workspace/kalender.html index 01fb6136..11db4828 100644 --- a/workspace/kalender.html +++ b/workspace/kalender.html @@ -14,11 +14,11 @@ - - - - - + + + + + @@ -275,6 +275,36 @@ + + +
+ + + +
+
@@ -340,11 +370,11 @@ - - - - - - + + + + + + diff --git a/workspace/leistung.html b/workspace/leistung.html index 1fe17883..c2739b93 100644 --- a/workspace/leistung.html +++ b/workspace/leistung.html @@ -14,11 +14,11 @@ - - - - - + + + + + @@ -217,10 +217,10 @@ - - - - - + + + + + diff --git a/workspace/personen.html b/workspace/personen.html index 6fd3aefb..8aada2e7 100644 --- a/workspace/personen.html +++ b/workspace/personen.html @@ -14,11 +14,11 @@ - - - - - + + + + + @@ -335,10 +335,10 @@ - - - - - + + + + + diff --git a/workspace/profil.html b/workspace/profil.html index eb6dff01..012bec1b 100644 --- a/workspace/profil.html +++ b/workspace/profil.html @@ -14,11 +14,11 @@ - - - - - + + + + + @@ -207,11 +207,11 @@ - - - - - - + + + + + + diff --git a/workspace/report.html b/workspace/report.html index 4333c4cc..301a8485 100644 --- a/workspace/report.html +++ b/workspace/report.html @@ -14,11 +14,11 @@ - - - - - + + + + + @@ -99,11 +99,11 @@ - - - - - - + + + + + + diff --git a/workspace/scouting.html b/workspace/scouting.html index 4bf5af14..08e8b4f5 100644 --- a/workspace/scouting.html +++ b/workspace/scouting.html @@ -14,11 +14,11 @@ - - - - - + + + + + @@ -132,10 +132,10 @@ - - - - - + + + + + diff --git a/workspace/start.html b/workspace/start.html index 3b6ad116..455b630d 100644 --- a/workspace/start.html +++ b/workspace/start.html @@ -14,12 +14,12 @@ - - + + - - + + @@ -667,10 +667,10 @@

- - - - - + + + + + diff --git a/workspace/startcheck.html b/workspace/startcheck.html index 85840c83..e4464e9e 100644 --- a/workspace/startcheck.html +++ b/workspace/startcheck.html @@ -14,11 +14,11 @@ - - - - - + + + + + @@ -78,11 +78,11 @@ - - - - - - + + + + + + diff --git a/workspace/steckbrief.html b/workspace/steckbrief.html index cd53b370..952f411a 100644 --- a/workspace/steckbrief.html +++ b/workspace/steckbrief.html @@ -14,11 +14,11 @@ - - - - - + + + + + @@ -119,10 +119,10 @@ - - - - - + + + + + diff --git a/workspace/uebersicht.html b/workspace/uebersicht.html index 38aa033b..7a00dd0e 100644 --- a/workspace/uebersicht.html +++ b/workspace/uebersicht.html @@ -14,13 +14,13 @@ - - + + - - - + + + @@ -142,11 +142,11 @@ - + - - - - + + + + diff --git a/workspace/wissen.html b/workspace/wissen.html index a14ba12f..f7d2532e 100644 --- a/workspace/wissen.html +++ b/workspace/wissen.html @@ -14,11 +14,11 @@ - - - - - + + + + + @@ -183,10 +183,10 @@ - - - - - + + + + +