Terminplaner: Marke „Bald verfügbar“ (noch nicht für Kunden buchbar)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
knsoandClaude Opus 5.5 committed 2026-10-04 20:09:28 +00:00
1 parent c1d775e090
commit 4139f31925
3 files changed
+44 -3

No files matched your search

+10 -1
View File
@@ -96,8 +96,12 @@ type Funktion = {
beschreibung?: string; beschreibung?: string;
/** Hinweis unter dem MacBook (Live-Vorschau, Chat, Terminplaner, Pinnwand; bei der Website-Analyse steht dort die Diagnose). */ /** Hinweis unter dem MacBook (Live-Vorschau, Chat, Terminplaner, Pinnwand; bei der Website-Analyse steht dort die Diagnose). */
hinweis?: string; hinweis?: string;
/** Noch nicht für Kunden buchbar: Marke „Bald verfügbar“ am Titel (Terminplaner läuft bisher nur im Pilot, Stand 04.10.2026). */
bald?: boolean;
}; };
const BaldMarke = ({ f }: { f: Funktion }) => (f.bald ? <span className="kp-bald">Bald verfügbar</span> : null);
/** Mitte des Knopfes "Aufhängen" im Portal-Screenshot der News-Pinnwand (Designpunkte der iPhone-Fläche 402 x 874). */ /** Mitte des Knopfes "Aufhängen" im Portal-Screenshot der News-Pinnwand (Designpunkte der iPhone-Fläche 402 x 874). */
const AUFHAENGEN_PUNKT = { x: 201, y: 613 }; const AUFHAENGEN_PUNKT = { x: 201, y: 613 };
@@ -151,6 +155,7 @@ const FUNKTIONEN: Funktion[] = [
id: "terminplaner", id: "terminplaner",
titel: "Terminplaner", titel: "Terminplaner",
demo: "termin", demo: "termin",
bald: true,
adresse: "salon-schnittstelle.example", adresse: "salon-schnittstelle.example",
beschreibung: beschreibung:
"Beispiel-Website eines Friseursalons mit Buchungsformular und einem Kalender, in dem der neue Termin erscheint", "Beispiel-Website eines Friseursalons mit Buchungsformular und einem Kalender, in dem der neue Termin erscheint",
@@ -553,7 +558,10 @@ const Buehne = () => {
onClick={() => springe(d)} onClick={() => springe(d)}
> >
<span className="kp-eintrag__punkt" aria-hidden="true" /> <span className="kp-eintrag__punkt" aria-hidden="true" />
<span className="kp-untereintrag__titel">{FUNKTIONEN[d].titel}</span> <span className="kp-untereintrag__titel">
{FUNKTIONEN[d].titel}
<BaldMarke f={FUNKTIONEN[d]} />
</span>
</button> </button>
</li> </li>
))} ))}
@@ -728,6 +736,7 @@ const DemoKarteRahmen = ({
</HandyRahmen> </HandyRahmen>
</div> </div>
<h3 className="wk-h3 kp-karte__titel">{f.titel}</h3> <h3 className="wk-h3 kp-karte__titel">{f.titel}</h3>
<BaldMarke f={f} />
<KartenUnterschrift f={f} /> <KartenUnterschrift f={f} />
<p className="kp-karte__beispiel">{beispielText(f)}</p> <p className="kp-karte__beispiel">{beispielText(f)}</p>
{f.bedienhinweis ? <p className="kp-karte__bedienen">{f.bedienhinweis.tippen}</p> : null} {f.bedienhinweis ? <p className="kp-karte__bedienen">{f.bedienhinweis.tippen}</p> : null}
+18
View File
@@ -235,6 +235,20 @@
line-height: 1.2; line-height: 1.2;
transition: color var(--dur-state) var(--ease); transition: color var(--dur-state) var(--ease);
} }
/* „Bald verfügbar“: Funktion noch nicht buchbar */
.kp-bald {
display: inline-block;
margin-left: 0.5rem;
padding: 0.125rem 0.5rem;
border: 1px solid var(--line-strong);
border-radius: 999px;
color: var(--fg-muted);
font-size: 0.75rem;
font-weight: 600;
line-height: 1.4;
white-space: nowrap;
vertical-align: 0.15em;
}
.kp-untereintrag[aria-current="step"] .kp-untereintrag__titel { .kp-untereintrag[aria-current="step"] .kp-untereintrag__titel {
color: var(--fg); color: var(--fg);
} }
@@ -495,6 +509,10 @@
.kp-karte__titel { .kp-karte__titel {
margin-bottom: 0.35rem; margin-bottom: 0.35rem;
} }
/* auf der Karte steht die Marke unter dem Titel (die Überschrift bleibt der reine Titel) */
.kp-karte > .kp-bald {
margin: 0 0 0.5rem;
}
.kp-karte__text { .kp-karte__text {
max-width: 26ch; max-width: 26ch;
} }
+16 -2
View File
@@ -129,10 +129,24 @@ describe("Kundenportal: Text und Reihenfolge", () => {
expect(unterliste).toHaveAttribute("aria-label", "Funktionen"); expect(unterliste).toHaveAttribute("aria-label", "Funktionen");
expect(unterliste).not.toBeVisible(); expect(unterliste).not.toBeVisible();
const unter = within(unterliste).getAllByRole("button", { hidden: true }); const unter = within(unterliste).getAllByRole("button", { hidden: true });
expect(unter.map((b) => b.textContent)).toEqual(["Terminplaner", "Website-Analyse", "News-Pinnwand"]); expect(unter.map((b) => b.textContent)).toEqual(["TerminplanerBald verfügbar", "Website-Analyse", "News-Pinnwand"]);
expect(liste).not.toHaveTextContent("Heatmap: wohin Besucher klicken"); expect(liste).not.toHaveTextContent("Heatmap: wohin Besucher klicken");
}); });
it("der Terminplaner trägt „Bald verfügbar“ (noch nicht buchbar), die anderen Stationen nicht", () => {
zeigeDesktop();
const liste = screen.getByRole("list", { name: "Funktionen des Kundenportals" });
const marken = liste.querySelectorAll(".kp-bald");
expect(marken).toHaveLength(1);
expect(marken[0].closest("button")).toHaveTextContent(/^Terminplaner/);
cleanup();
zeigeHandy();
const karten = screen.getAllByText("Bald verfügbar");
expect(karten).toHaveLength(1);
expect(karten[0].closest(".kp-karte")).toContainElement(screen.getByRole("heading", { level: 3, name: "Terminplaner" }));
});
it("Tablet quer (Bühne ohne Maus): der Bedienhinweis der Website-Analyse sagt „Tippen Sie“ statt „Zeigen Sie mit der Maus“", () => { it("Tablet quer (Bühne ohne Maus): der Bedienhinweis der Website-Analyse sagt „Tippen Sie“ statt „Zeigen Sie mit der Maus“", () => {
const { container } = zeigeTablet(); const { container } = zeigeTablet();
const hinweis = Array.from(container.querySelectorAll(".kp-beispiel")).find((h) => h.textContent?.includes("Tippen")); const hinweis = Array.from(container.querySelectorAll(".kp-beispiel")).find((h) => h.textContent?.includes("Tippen"));
@@ -335,7 +349,7 @@ describe("Kundenportal: Bühne wechselt mit dem IntersectionObserver", () => {
meldeMarke(4); meldeMarke(4);
expect(gruppe).toHaveAttribute("aria-expanded", "true"); expect(gruppe).toHaveAttribute("aria-expanded", "true");
expect(screen.getByRole("list", { name: "Funktionen" })).toBeVisible(); expect(screen.getByRole("list", { name: "Funktionen" })).toBeVisible();
expect(aktiverEintrag()).toBe("Terminplaner"); expect(aktiverEintrag()).toBe("TerminplanerBald verfügbar");
meldeMarke(5); meldeMarke(5);
expect(aktiverEintrag()).toBe("Website-Analyse"); expect(aktiverEintrag()).toBe("Website-Analyse");
meldeMarke(7); meldeMarke(7);