Website: Abo-Seiten an die Vertragsbedingungen angeglichen (Wechsel, Zusatzspeicher, Sicherheit), AGB-Verweise, Tests
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
dc27e508dd
commit
2c1a4c150c
5 files changed
+131
-66
No files matched your search
+12
-1
@@ -2,7 +2,8 @@ import { Toaster } from "@/components/ui/toaster";
|
|||||||
import { Toaster as Sonner } from "@/components/ui/sonner";
|
import { Toaster as Sonner } from "@/components/ui/sonner";
|
||||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||||
import { BrowserRouter, Routes, Route } from "react-router-dom";
|
import { useEffect } from "react";
|
||||||
|
import { BrowserRouter, Routes, Route, useLocation } from "react-router-dom";
|
||||||
import { ThemeProvider } from "@/components/ThemeProvider";
|
import { ThemeProvider } from "@/components/ThemeProvider";
|
||||||
import { AnalyticsProvider } from "@/components/AnalyticsProvider";
|
import { AnalyticsProvider } from "@/components/AnalyticsProvider";
|
||||||
import Index from "./pages/Index";
|
import Index from "./pages/Index";
|
||||||
@@ -17,6 +18,15 @@ import NotFound from "./pages/NotFound";
|
|||||||
|
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
|
/** Scrollt bei einem Seitenwechsel nach oben; Anker-Links (URL mit #) bleiben unberührt. */
|
||||||
|
const ScrollToTop = () => {
|
||||||
|
const { pathname, hash } = useLocation();
|
||||||
|
useEffect(() => {
|
||||||
|
if (!hash) window.scrollTo(0, 0);
|
||||||
|
}, [pathname, hash]);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
const App = () => (
|
const App = () => (
|
||||||
<ThemeProvider>
|
<ThemeProvider>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
@@ -24,6 +34,7 @@ const App = () => (
|
|||||||
<Toaster />
|
<Toaster />
|
||||||
<Sonner />
|
<Sonner />
|
||||||
<BrowserRouter future={{ v7_startTransition: true, v7_relativeSplatPath: true }}>
|
<BrowserRouter future={{ v7_startTransition: true, v7_relativeSplatPath: true }}>
|
||||||
|
<ScrollToTop />
|
||||||
<AnalyticsProvider>
|
<AnalyticsProvider>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<Index />} />
|
<Route path="/" element={<Index />} />
|
||||||
|
|||||||
+5
-5
@@ -124,10 +124,10 @@ const AGB = () => {
|
|||||||
<ol className="list-decimal list-inside space-y-2 text-muted-foreground leading-relaxed [&>li]:pl-2">
|
<ol className="list-decimal list-inside space-y-2 text-muted-foreground leading-relaxed [&>li]:pl-2">
|
||||||
<li>
|
<li>
|
||||||
Hosting bietet WEBklar als Hosting-Abo an. Für das Hosting-Abo und das Wartungs-Abo gelten die{" "}
|
Hosting bietet WEBklar als Hosting-Abo an. Für das Hosting-Abo und das Wartungs-Abo gelten die{" "}
|
||||||
<a href="https://project.webklar.com/abo-bedingungen.html" className="text-foreground underline hover:no-underline">Vertragsbedingungen der WEBklar-Abos</a>
|
<a href="https://project.webklar.com/abo-bedingungen.html" className="text-foreground underline hover:no-underline">Vertragsbedingungen für die WEBklar-Abos</a>
|
||||||
{" "}mit Leistungsbeschreibung; sie gehen diesen AGB vor.
|
{" "}mit Leistungsbeschreibungen; sie gehen diesen AGB vor.
|
||||||
</li>
|
</li>
|
||||||
<li>Bestehende Hostingverträge mit jährlicher Laufzeit behalten die bei ihrem Abschluss geltende Fassung dieses Moduls.</li>
|
<li>Bestehende Hosting-Verträge mit jährlicher Laufzeit behalten die bei ihrem Abschluss vereinbarten Bedingungen.</li>
|
||||||
<li>WEBklar ist berechtigt, externe Anbieter (z. B. Rechenzentren) einzusetzen.</li>
|
<li>WEBklar ist berechtigt, externe Anbieter (z. B. Rechenzentren) einzusetzen.</li>
|
||||||
<li>WEBklar übernimmt keine Haftung für Ausfälle externer Anbieter.</li>
|
<li>WEBklar übernimmt keine Haftung für Ausfälle externer Anbieter.</li>
|
||||||
</ol>
|
</ol>
|
||||||
@@ -194,7 +194,7 @@ const AGB = () => {
|
|||||||
<ol className="list-decimal list-inside space-y-2 text-muted-foreground leading-relaxed [&>li]:pl-2">
|
<ol className="list-decimal list-inside space-y-2 text-muted-foreground leading-relaxed [&>li]:pl-2">
|
||||||
<li>Die Vergütung ergibt sich aus dem Angebot.</li>
|
<li>Die Vergütung ergibt sich aus dem Angebot.</li>
|
||||||
<li>Projektleistungen sind nach Vereinbarung fällig.</li>
|
<li>Projektleistungen sind nach Vereinbarung fällig.</li>
|
||||||
<li>Für das Hosting-Abo und das Wartungs-Abo gelten die Zahlungsbedingungen der Vertragsbedingungen der WEBklar-Abos (monatlich im Voraus).</li>
|
<li>Für die Abos gelten die Vertragsbedingungen für die WEBklar-Abos.</li>
|
||||||
</ol>
|
</ol>
|
||||||
</section>
|
</section>
|
||||||
{contractDivider}
|
{contractDivider}
|
||||||
@@ -243,7 +243,7 @@ const AGB = () => {
|
|||||||
12. Kündigung
|
12. Kündigung
|
||||||
</h2>
|
</h2>
|
||||||
<ol className="list-decimal list-inside space-y-2 text-muted-foreground leading-relaxed [&>li]:pl-2">
|
<ol className="list-decimal list-inside space-y-2 text-muted-foreground leading-relaxed [&>li]:pl-2">
|
||||||
<li>Laufzeitverträge (z. B. Hosting, Wartung) können zum Ende der jeweiligen Laufzeit gekündigt werden. Laufzeit und Kündigung des Hosting-Abos und des Wartungs-Abos richten sich nach den Vertragsbedingungen der WEBklar-Abos (Mindestlaufzeit 12 Monate, danach jederzeit zum Ende des Abrechnungsmonats kündbar).</li>
|
<li>Laufzeitverträge können zum Ende der jeweiligen Laufzeit gekündigt werden. Laufzeit und Kündigung der Abos richten sich nach den Vertragsbedingungen für die WEBklar-Abos.</li>
|
||||||
<li>Das Recht zur außerordentlichen Kündigung bleibt unberührt.</li>
|
<li>Das Recht zur außerordentlichen Kündigung bleibt unberührt.</li>
|
||||||
</ol>
|
</ol>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
+30
-29
@@ -19,7 +19,7 @@ const leistungen = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
titel: "1 E-Mail-Postfach",
|
titel: "1 E-Mail-Postfach",
|
||||||
text: `Mit Ihrer eigenen Domain, 5 GB Speicher, Webmail und Zugriff per Outlook oder Smartphone. Mehr Platz gibt es über den E-Mail-Zusatzspeicher: je 5 GB für 1,00 € pro Monat (${STEUER}).`,
|
text: `Unter Ihrer eigenen Domain, 5 GB Speicher, Webmail und Zugriff per Outlook oder Smartphone. Mehr Platz gibt es über den E-Mail-Zusatzspeicher: je 5 GB für 1,00 € pro Monat (${STEUER}).`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
titel: "Störungen inklusive",
|
titel: "Störungen inklusive",
|
||||||
@@ -36,12 +36,12 @@ const HostingAbo = () => {
|
|||||||
<Link to="/" className="flex items-center gap-2 group">
|
<Link to="/" className="flex items-center gap-2 group">
|
||||||
<span className="text-xl font-display font-medium text-foreground tracking-tight">Webklar</span>
|
<span className="text-xl font-display font-medium text-foreground tracking-tight">Webklar</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
<Button asChild variant="ghost" className="text-muted-foreground hover:text-foreground">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<Button variant="ghost" className="text-muted-foreground hover:text-foreground">
|
|
||||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||||
Zurück
|
Zurück
|
||||||
</Button>
|
|
||||||
</Link>
|
</Link>
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
@@ -92,8 +92,8 @@ const HostingAbo = () => {
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Updates und Pflege der Website selbst sind nicht enthalten; bei statischen Websites sind sie für den sicheren
|
Updates und Pflege der Website selbst sind nicht enthalten; bei statischen Websites sind sie für den sicheren
|
||||||
Betrieb nicht nötig. Braucht Ihre Website dynamische Teile oder wünschen Sie laufende Pflege und eine Stunde
|
Betrieb in der Regel nicht nötig. Braucht Ihre Website dynamische Teile oder wünschen Sie laufende Pflege und
|
||||||
Arbeitszeit pro Monat, ist unser{" "}
|
eine Stunde Arbeitszeit pro Monat, ist unser{" "}
|
||||||
<Link to="/wartungs-abo" className={linkClass}>Wartungs-Abo</Link> das Richtige.
|
<Link to="/wartungs-abo" className={linkClass}>Wartungs-Abo</Link> das Richtige.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -115,9 +115,9 @@ const HostingAbo = () => {
|
|||||||
<h2 className="text-lg font-display font-medium uppercase tracking-tight mb-3">E-Mail-Zusatzspeicher</h2>
|
<h2 className="text-lg font-display font-medium uppercase tracking-tight mb-3">E-Mail-Zusatzspeicher</h2>
|
||||||
<p className="text-muted-foreground leading-relaxed">
|
<p className="text-muted-foreground leading-relaxed">
|
||||||
Brauchen Sie mehr Platz für E-Mails, buchen Sie im Kundenportal unter „Verträge“ Zusatzspeicher: Pakete von je
|
Brauchen Sie mehr Platz für E-Mails, buchen Sie im Kundenportal unter „Verträge“ Zusatzspeicher: Pakete von je
|
||||||
5 GB für 1,00 € pro Monat ({STEUER}), bis zu 10 Pakete. Die Zahl der Pakete können Sie dort jederzeit erhöhen
|
5 GB für 1,00 € pro Monat ({STEUER}), bis zu 10 Pakete. Bestellen und verringern können Sie die Pakete dort,
|
||||||
oder verringern, solange Ihr Abo nicht gekündigt ist. Eine Verringerung wirkt zum Ende des Abrechnungsmonats.
|
sobald Ihr Abo begonnen hat, solange es nicht gekündigt ist und keine Zahlung offen ist. Eine Verringerung wirkt
|
||||||
Einzelheiten:{" "}
|
zum Ende des Abrechnungsmonats. Einzelheiten:{" "}
|
||||||
<a href={`${PORTAL}/abo-bedingungen.html#zusatzspeicher`} className={linkClass}>§ 10 der Vertragsbedingungen</a>.
|
<a href={`${PORTAL}/abo-bedingungen.html#zusatzspeicher`} className={linkClass}>§ 10 der Vertragsbedingungen</a>.
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
@@ -127,10 +127,10 @@ const HostingAbo = () => {
|
|||||||
<h2 className="text-lg font-display font-medium uppercase tracking-tight mb-3">Wechsel ins Wartungs-Abo</h2>
|
<h2 className="text-lg font-display font-medium uppercase tracking-tight mb-3">Wechsel ins Wartungs-Abo</h2>
|
||||||
<p className="text-muted-foreground leading-relaxed">
|
<p className="text-muted-foreground leading-relaxed">
|
||||||
Braucht Ihre Website später dynamische Teile oder möchten Sie Pflege und Arbeitszeit dazubuchen, wechseln Sie
|
Braucht Ihre Website später dynamische Teile oder möchten Sie Pflege und Arbeitszeit dazubuchen, wechseln Sie
|
||||||
im Kundenportal unter „Verträge“ jederzeit ins{" "}
|
im Kundenportal unter „Verträge“ ins{" "}
|
||||||
<Link to="/wartungs-abo" className={linkClass}>Wartungs-Abo</Link>, auch während der Mindestlaufzeit, solange
|
<Link to="/wartungs-abo" className={linkClass}>Wartungs-Abo</Link>, auch während der Mindestlaufzeit: sobald
|
||||||
Ihr Hosting-Abo nicht gekündigt ist. Mit dem Wechsel beginnt eine neue Mindestlaufzeit von 12 Monaten.
|
Ihr Hosting-Abo begonnen hat, solange es nicht gekündigt ist und keine Zahlung offen ist. Mit dem Wechsel
|
||||||
Einzelheiten:{" "}
|
beginnt eine neue Mindestlaufzeit von 12 Monaten. Einzelheiten:{" "}
|
||||||
<a href={`${PORTAL}/abo-bedingungen.html#wechsel`} className={linkClass}>§ 9 der Vertragsbedingungen</a>.
|
<a href={`${PORTAL}/abo-bedingungen.html#wechsel`} className={linkClass}>§ 9 der Vertragsbedingungen</a>.
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
@@ -140,8 +140,8 @@ const HostingAbo = () => {
|
|||||||
<h2 className="text-lg font-display font-medium uppercase tracking-tight mb-3">So schließen Sie das Abo ab</h2>
|
<h2 className="text-lg font-display font-medium uppercase tracking-tight mb-3">So schließen Sie das Abo ab</h2>
|
||||||
<p className="text-muted-foreground leading-relaxed">
|
<p className="text-muted-foreground leading-relaxed">
|
||||||
Das Hosting-Abo schließen Sie in unserem Kundenportal ab. Den Zugang richten wir Ihnen ein, sprechen Sie uns
|
Das Hosting-Abo schließen Sie in unserem Kundenportal ab. Den Zugang richten wir Ihnen ein, sprechen Sie uns
|
||||||
einfach an. Nach der Anmeldung finden Sie das Angebot im Bereich „Verträge“. Dort sehen Sie danach jederzeit
|
einfach an. Nach der Anmeldung finden Sie das Angebot im Bereich „Verträge“. Im Kundenportal sehen Sie danach
|
||||||
Ihre Verträge und Rechnungen, buchen Zusatzspeicher und können uns Aufträge schicken.
|
jederzeit Ihre Verträge und Rechnungen, buchen Zusatzspeicher und schicken uns Aufträge über den Chat.
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
{divider}
|
{divider}
|
||||||
@@ -149,18 +149,19 @@ const HostingAbo = () => {
|
|||||||
<section>
|
<section>
|
||||||
<h2 className="text-lg font-display font-medium uppercase tracking-tight mb-3">Widerruf und Kündigung</h2>
|
<h2 className="text-lg font-display font-medium uppercase tracking-tight mb-3">Widerruf und Kündigung</h2>
|
||||||
<p className="text-muted-foreground leading-relaxed">
|
<p className="text-muted-foreground leading-relaxed">
|
||||||
Verbraucher können den Vertrag innerhalb von 14 Tagen widerrufen; das gilt für jede Bestellung, also für das
|
Verbraucher können jede Bestellung innerhalb von 14 Tagen ab Vertragsschluss widerrufen: den Abschluss des
|
||||||
Abo, den Wechsel ins Wartungs-Abo und den Zusatzspeicher. Bereits gezahlte Beträge erstatten wir dann nach der{" "}
|
Abos, den Wechsel ins Wartungs-Abo und die Bestellung von Zusatzspeicher. Bereits gezahlte Beträge erstatten
|
||||||
|
wir dann nach der{" "}
|
||||||
<a href={`${PORTAL}/abo-bedingungen.html#widerruf`} className={linkClass}>Widerrufsbelehrung</a>.
|
<a href={`${PORTAL}/abo-bedingungen.html#widerruf`} className={linkClass}>Widerrufsbelehrung</a>.
|
||||||
Kündigen können Sie online ohne Anmeldung oder per E-Mail.
|
Kündigen können Sie online ohne Anmeldung oder per E-Mail.
|
||||||
</p>
|
</p>
|
||||||
<div className="mt-4 flex flex-wrap gap-3">
|
<div className="mt-4 flex flex-wrap gap-3">
|
||||||
<a href={`${PORTAL}/kuendigen.html`}>
|
<Button asChild variant="outline" className="rounded-full">
|
||||||
<Button variant="outline" className="rounded-full">Verträge hier kündigen</Button>
|
<a href={`${PORTAL}/kuendigen.html`}>Verträge hier kündigen</a>
|
||||||
</a>
|
</Button>
|
||||||
<a href={`${PORTAL}/widerrufen.html`}>
|
<Button asChild variant="outline" className="rounded-full">
|
||||||
<Button variant="outline" className="rounded-full">Vertrag widerrufen</Button>
|
<a href={`${PORTAL}/widerrufen.html`}>Vertrag widerrufen</a>
|
||||||
</a>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{divider}
|
{divider}
|
||||||
@@ -168,7 +169,7 @@ const HostingAbo = () => {
|
|||||||
<section>
|
<section>
|
||||||
<h2 className="text-lg font-display font-medium uppercase tracking-tight mb-3">Unterlagen und Kontakt</h2>
|
<h2 className="text-lg font-display font-medium uppercase tracking-tight mb-3">Unterlagen und Kontakt</h2>
|
||||||
<p className="text-muted-foreground leading-relaxed">
|
<p className="text-muted-foreground leading-relaxed">
|
||||||
<a href={`${PORTAL}/abo-bedingungen.html`} className={linkClass}>Vertragsbedingungen der WEBklar-Abos</a>
|
<a href={`${PORTAL}/abo-bedingungen.html`} className={linkClass}>Vertragsbedingungen für die WEBklar-Abos</a>
|
||||||
{" · "}
|
{" · "}
|
||||||
<a href={`${PORTAL}/abo-bedingungen.html#hosting`} className={linkClass}>Leistungsbeschreibung A (Hosting-Abo)</a>
|
<a href={`${PORTAL}/abo-bedingungen.html#hosting`} className={linkClass}>Leistungsbeschreibung A (Hosting-Abo)</a>
|
||||||
{" · "}
|
{" · "}
|
||||||
@@ -182,12 +183,12 @@ const HostingAbo = () => {
|
|||||||
</article>
|
</article>
|
||||||
|
|
||||||
<div className="mt-16 pt-12 border-t border-border flex flex-wrap gap-4">
|
<div className="mt-16 pt-12 border-t border-border flex flex-wrap gap-4">
|
||||||
<a href={`${PORTAL}/login.html`}>
|
<Button asChild className="btn-minimal rounded-full">
|
||||||
<Button className="btn-minimal rounded-full">Zum Kundenportal</Button>
|
<a href={`${PORTAL}/login.html`}>Zum Kundenportal</a>
|
||||||
</a>
|
</Button>
|
||||||
<Link to="/kontakt">
|
<Button asChild variant="outline" className="rounded-full">
|
||||||
<Button variant="outline" className="rounded-full">Kontakt aufnehmen</Button>
|
<Link to="/kontakt">Kontakt aufnehmen</Link>
|
||||||
</Link>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+31
-26
@@ -11,7 +11,7 @@ const linkClass = "text-foreground underline hover:no-underline";
|
|||||||
const leistungen = [
|
const leistungen = [
|
||||||
{
|
{
|
||||||
titel: "Betrieb & Pflege Ihrer Website",
|
titel: "Betrieb & Pflege Ihrer Website",
|
||||||
text: "Hosting auf unserem Server in Deutschland, Sicherheitsupdates für Server und Website, SSL-Zertifikat, tägliche Datensicherung und Überwachung der Erreichbarkeit. Für alle Websites und Web-Anwendungen, die wir erstellt oder zur Betreuung übernommen haben, auch mit Content-Management-System, Login oder Datenbank.",
|
text: "Hosting auf unserem Server in Deutschland, Sicherheitsupdates für den Server und für die Software-Komponenten Ihrer Website, die wir einsetzen, SSL-Zertifikat, tägliche Datensicherung und Überwachung der Erreichbarkeit. Für alle Websites und Web-Anwendungen, die wir erstellt oder zur Betreuung übernommen haben, auch mit Content-Management-System, Login oder Datenbank.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
titel: "1 Domain inklusive",
|
titel: "1 Domain inklusive",
|
||||||
@@ -36,12 +36,12 @@ const WartungsAbo = () => {
|
|||||||
<Link to="/" className="flex items-center gap-2 group">
|
<Link to="/" className="flex items-center gap-2 group">
|
||||||
<span className="text-xl font-display font-medium text-foreground tracking-tight">Webklar</span>
|
<span className="text-xl font-display font-medium text-foreground tracking-tight">Webklar</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
<Button asChild variant="ghost" className="text-muted-foreground hover:text-foreground">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<Button variant="ghost" className="text-muted-foreground hover:text-foreground">
|
|
||||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||||
Zurück
|
Zurück
|
||||||
</Button>
|
|
||||||
</Link>
|
</Link>
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
@@ -92,10 +92,11 @@ const WartungsAbo = () => {
|
|||||||
<h2 className="text-lg font-display font-medium uppercase tracking-tight mb-3">E-Mail-Postfächer und Zusatzspeicher</h2>
|
<h2 className="text-lg font-display font-medium uppercase tracking-tight mb-3">E-Mail-Postfächer und Zusatzspeicher</h2>
|
||||||
<p className="text-muted-foreground leading-relaxed">
|
<p className="text-muted-foreground leading-relaxed">
|
||||||
Im Wartungs-Abo richten wir Ihnen beliebig viele Postfächer unter Ihrer Domain ein, mit zusammen 5 GB
|
Im Wartungs-Abo richten wir Ihnen beliebig viele Postfächer unter Ihrer Domain ein, mit zusammen 5 GB
|
||||||
Speicher. Wie der Speicher auf die Postfächer verteilt wird, bestimmen Sie. Brauchen Sie mehr
|
Speicher. Wie der Speicher auf die Postfächer verteilt wird, bestimmen Sie. Brauchen Sie mehr Platz, buchen Sie
|
||||||
Platz, buchen Sie im Kundenportal unter „Verträge“ Zusatzspeicher: Pakete von je 5 GB für 1,00 € pro Monat
|
im Kundenportal unter „Verträge“ Zusatzspeicher: Pakete von je 5 GB für 1,00 € pro Monat ({STEUER}), bis zu
|
||||||
({STEUER}), bis zu 10 Pakete. Die Zahl der Pakete können Sie dort jederzeit erhöhen oder verringern, solange
|
10 Pakete. Bestellen und verringern können Sie die Pakete dort, sobald Ihr Abo begonnen hat, solange es nicht
|
||||||
Ihr Abo nicht gekündigt ist. Eine Verringerung wirkt zum Ende des Abrechnungsmonats. Einzelheiten:{" "}
|
gekündigt ist und keine Zahlung offen ist. Eine Verringerung wirkt zum Ende des Abrechnungsmonats.
|
||||||
|
Einzelheiten:{" "}
|
||||||
<a href={`${PORTAL}/abo-bedingungen.html#zusatzspeicher`} className={linkClass}>§ 10 der Vertragsbedingungen</a>.
|
<a href={`${PORTAL}/abo-bedingungen.html#zusatzspeicher`} className={linkClass}>§ 10 der Vertragsbedingungen</a>.
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
@@ -106,8 +107,11 @@ const WartungsAbo = () => {
|
|||||||
<p className="text-muted-foreground leading-relaxed">
|
<p className="text-muted-foreground leading-relaxed">
|
||||||
Sie haben eine statische Website und brauchen weder Pflege noch Arbeitszeit? Dann genügt vielleicht unser{" "}
|
Sie haben eine statische Website und brauchen weder Pflege noch Arbeitszeit? Dann genügt vielleicht unser{" "}
|
||||||
<Link to="/hosting-abo" className={linkClass}>Hosting-Abo</Link> für 15,00 € pro Monat ({STEUER}). Vom
|
<Link to="/hosting-abo" className={linkClass}>Hosting-Abo</Link> für 15,00 € pro Monat ({STEUER}). Vom
|
||||||
Hosting- ins Wartungs-Abo können Sie jederzeit wechseln; ein Wechsel vom Wartungs- ins Hosting-Abo ist auf
|
Hosting- ins Wartungs-Abo wechseln Sie im Kundenportal, sobald das Hosting-Abo begonnen hat, solange es nicht
|
||||||
Anfrage nach Ablauf der Mindestlaufzeit möglich.
|
gekündigt ist und keine Zahlung offen ist; mit dem Wechsel beginnt eine neue Mindestlaufzeit von 12 Monaten.
|
||||||
|
Ein Wechsel vom Wartungs- ins Hosting-Abo ist auf Anfrage nach Ablauf der Mindestlaufzeit zum Ende eines
|
||||||
|
Abrechnungsmonats möglich, wenn Ihre Website statisch ist. Einzelheiten in{" "}
|
||||||
|
<a href={`${PORTAL}/abo-bedingungen.html#wechsel`} className={linkClass}>§ 9 der Vertragsbedingungen</a>.
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
{divider}
|
{divider}
|
||||||
@@ -116,8 +120,8 @@ const WartungsAbo = () => {
|
|||||||
<h2 className="text-lg font-display font-medium uppercase tracking-tight mb-3">So schließen Sie das Abo ab</h2>
|
<h2 className="text-lg font-display font-medium uppercase tracking-tight mb-3">So schließen Sie das Abo ab</h2>
|
||||||
<p className="text-muted-foreground leading-relaxed">
|
<p className="text-muted-foreground leading-relaxed">
|
||||||
Das Wartungs-Abo schließen Sie in unserem Kundenportal ab. Den Zugang richten wir Ihnen ein, sprechen Sie uns
|
Das Wartungs-Abo schließen Sie in unserem Kundenportal ab. Den Zugang richten wir Ihnen ein, sprechen Sie uns
|
||||||
einfach an. Nach der Anmeldung finden Sie das Angebot im Bereich „Verträge“. Dort sehen Sie danach jederzeit
|
einfach an. Nach der Anmeldung finden Sie das Angebot im Bereich „Verträge“. Im Kundenportal sehen Sie danach
|
||||||
Ihr Stundenkontingent, Ihre Rechnungen und können uns Aufträge schicken.
|
jederzeit Ihr Stundenkontingent und Ihre Rechnungen und schicken uns Aufträge über den Chat.
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
{divider}
|
{divider}
|
||||||
@@ -125,18 +129,19 @@ const WartungsAbo = () => {
|
|||||||
<section>
|
<section>
|
||||||
<h2 className="text-lg font-display font-medium uppercase tracking-tight mb-3">Widerruf und Kündigung</h2>
|
<h2 className="text-lg font-display font-medium uppercase tracking-tight mb-3">Widerruf und Kündigung</h2>
|
||||||
<p className="text-muted-foreground leading-relaxed">
|
<p className="text-muted-foreground leading-relaxed">
|
||||||
Verbraucher können den Vertrag innerhalb von 14 Tagen widerrufen; das gilt für jede Bestellung, also für das
|
Verbraucher können jede Bestellung innerhalb von 14 Tagen ab Vertragsschluss widerrufen: den Abschluss des
|
||||||
Abo und den Zusatzspeicher. Bereits gezahlte Beträge erstatten wir dann nach der{" "}
|
Abos, den Wechsel ins Wartungs-Abo und die Bestellung von Zusatzspeicher. Bereits gezahlte Beträge erstatten
|
||||||
|
wir dann nach der{" "}
|
||||||
<a href={`${PORTAL}/abo-bedingungen.html#widerruf`} className={linkClass}>Widerrufsbelehrung</a>.
|
<a href={`${PORTAL}/abo-bedingungen.html#widerruf`} className={linkClass}>Widerrufsbelehrung</a>.
|
||||||
Kündigen können Sie online ohne Anmeldung oder per E-Mail.
|
Kündigen können Sie online ohne Anmeldung oder per E-Mail.
|
||||||
</p>
|
</p>
|
||||||
<div className="mt-4 flex flex-wrap gap-3">
|
<div className="mt-4 flex flex-wrap gap-3">
|
||||||
<a href={`${PORTAL}/kuendigen.html`}>
|
<Button asChild variant="outline" className="rounded-full">
|
||||||
<Button variant="outline" className="rounded-full">Verträge hier kündigen</Button>
|
<a href={`${PORTAL}/kuendigen.html`}>Verträge hier kündigen</a>
|
||||||
</a>
|
</Button>
|
||||||
<a href={`${PORTAL}/widerrufen.html`}>
|
<Button asChild variant="outline" className="rounded-full">
|
||||||
<Button variant="outline" className="rounded-full">Vertrag widerrufen</Button>
|
<a href={`${PORTAL}/widerrufen.html`}>Vertrag widerrufen</a>
|
||||||
</a>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{divider}
|
{divider}
|
||||||
@@ -144,7 +149,7 @@ const WartungsAbo = () => {
|
|||||||
<section>
|
<section>
|
||||||
<h2 className="text-lg font-display font-medium uppercase tracking-tight mb-3">Unterlagen und Kontakt</h2>
|
<h2 className="text-lg font-display font-medium uppercase tracking-tight mb-3">Unterlagen und Kontakt</h2>
|
||||||
<p className="text-muted-foreground leading-relaxed">
|
<p className="text-muted-foreground leading-relaxed">
|
||||||
<a href={`${PORTAL}/abo-bedingungen.html`} className={linkClass}>Vertragsbedingungen der WEBklar-Abos</a>
|
<a href={`${PORTAL}/abo-bedingungen.html`} className={linkClass}>Vertragsbedingungen für die WEBklar-Abos</a>
|
||||||
{" · "}
|
{" · "}
|
||||||
<a href={`${PORTAL}/abo-bedingungen.html#wartung`} className={linkClass}>Leistungsbeschreibung B (Wartungs-Abo)</a>
|
<a href={`${PORTAL}/abo-bedingungen.html#wartung`} className={linkClass}>Leistungsbeschreibung B (Wartungs-Abo)</a>
|
||||||
{" · "}
|
{" · "}
|
||||||
@@ -158,12 +163,12 @@ const WartungsAbo = () => {
|
|||||||
</article>
|
</article>
|
||||||
|
|
||||||
<div className="mt-16 pt-12 border-t border-border flex flex-wrap gap-4">
|
<div className="mt-16 pt-12 border-t border-border flex flex-wrap gap-4">
|
||||||
<a href={`${PORTAL}/login.html`}>
|
<Button asChild className="btn-minimal rounded-full">
|
||||||
<Button className="btn-minimal rounded-full">Zum Kundenportal</Button>
|
<a href={`${PORTAL}/login.html`}>Zum Kundenportal</a>
|
||||||
</a>
|
</Button>
|
||||||
<Link to="/kontakt">
|
<Button asChild variant="outline" className="rounded-full">
|
||||||
<Button variant="outline" className="rounded-full">Kontakt aufnehmen</Button>
|
<Link to="/kontakt">Kontakt aufnehmen</Link>
|
||||||
</Link>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+53
-5
@@ -1,17 +1,27 @@
|
|||||||
import { describe, it, expect } from "vitest";
|
import { describe, it, expect } from "vitest";
|
||||||
import { render, screen } from "@testing-library/react";
|
import { render, screen, within } from "@testing-library/react";
|
||||||
import { MemoryRouter } from "react-router-dom";
|
import { MemoryRouter } from "react-router-dom";
|
||||||
import HostingAbo from "@/pages/HostingAbo";
|
import HostingAbo from "@/pages/HostingAbo";
|
||||||
import WartungsAbo from "@/pages/WartungsAbo";
|
import WartungsAbo from "@/pages/WartungsAbo";
|
||||||
import AGB from "@/pages/AGB";
|
import AGB from "@/pages/AGB";
|
||||||
|
|
||||||
|
// Dieselben Future-Flags wie der BrowserRouter in App.tsx, sonst warnt React Router in der Testausgabe.
|
||||||
|
const routerFuture = { v7_startTransition: true, v7_relativeSplatPath: true };
|
||||||
|
|
||||||
// Texte, die auf einer Seite mehrfach vorkommen können, werden mit getAllByText
|
// Texte, die auf einer Seite mehrfach vorkommen können, werden mit getAllByText
|
||||||
// geprüft (getByText wirft bei mehreren Treffern); Abwesenheit mit queryAllByText.
|
// geprüft (getByText wirft bei mehreren Treffern); Abwesenheit mit queryAllByText.
|
||||||
|
|
||||||
|
/** Liefert den <section>-Abschnitt zu einer Überschrift. */
|
||||||
|
const sectionOf = (name: string | RegExp): HTMLElement => {
|
||||||
|
const section = screen.getByRole("heading", { name }).closest("section");
|
||||||
|
if (!section) throw new Error(`Abschnitt zur Überschrift ${String(name)} fehlt`);
|
||||||
|
return section;
|
||||||
|
};
|
||||||
|
|
||||||
describe("Abo-Seiten", () => {
|
describe("Abo-Seiten", () => {
|
||||||
it("Hosting-Abo-Seite: Preis, Postfach, Links", () => {
|
it("Hosting-Abo-Seite: Preis, Postfach, Links", () => {
|
||||||
render(
|
render(
|
||||||
<MemoryRouter>
|
<MemoryRouter future={routerFuture}>
|
||||||
<HostingAbo />
|
<HostingAbo />
|
||||||
</MemoryRouter>,
|
</MemoryRouter>,
|
||||||
);
|
);
|
||||||
@@ -27,25 +37,63 @@ describe("Abo-Seiten", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Hosting-Abo-Seite: Wechsel und Zusatzspeicher nur unter den Bedingungen des Portals", () => {
|
||||||
|
render(
|
||||||
|
<MemoryRouter future={routerFuture}>
|
||||||
|
<HostingAbo />
|
||||||
|
</MemoryRouter>,
|
||||||
|
);
|
||||||
|
// § 9 Abs. 1: Wechsel nur, wenn das Hosting-Abo begonnen hat, nicht gekündigt ist und keine Zahlung offen ist;
|
||||||
|
// mit dem Wechsel beginnt eine neue Mindestlaufzeit.
|
||||||
|
const wechsel = within(sectionOf("Wechsel ins Wartungs-Abo"));
|
||||||
|
expect(wechsel.getAllByText(/begonnen hat/).length).toBeGreaterThan(0);
|
||||||
|
expect(wechsel.getAllByText(/nicht gekündigt/).length).toBeGreaterThan(0);
|
||||||
|
expect(wechsel.getAllByText(/keine Zahlung offen/).length).toBeGreaterThan(0);
|
||||||
|
expect(wechsel.getAllByText(/neue Mindestlaufzeit von 12 Monaten/).length).toBeGreaterThan(0);
|
||||||
|
// § 10 Abs. 1: dieselben Bedingungen für Bestellung und Verringerung des Zusatzspeichers.
|
||||||
|
const speicher = within(sectionOf("E-Mail-Zusatzspeicher"));
|
||||||
|
expect(speicher.getAllByText(/begonnen hat/).length).toBeGreaterThan(0);
|
||||||
|
expect(speicher.getAllByText(/nicht gekündigt/).length).toBeGreaterThan(0);
|
||||||
|
expect(speicher.getAllByText(/keine Zahlung offen/).length).toBeGreaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
it("Wartungs-Abo-Seite: beliebig viele Postfächer, Zusatzspeicher", () => {
|
it("Wartungs-Abo-Seite: beliebig viele Postfächer, Zusatzspeicher", () => {
|
||||||
render(
|
render(
|
||||||
<MemoryRouter>
|
<MemoryRouter future={routerFuture}>
|
||||||
<WartungsAbo />
|
<WartungsAbo />
|
||||||
</MemoryRouter>,
|
</MemoryRouter>,
|
||||||
);
|
);
|
||||||
|
expect(screen.getAllByText("Beliebig viele Postfächer").length).toBeGreaterThan(0);
|
||||||
expect(screen.getAllByText(/beliebig viele Postfächer/).length).toBeGreaterThan(0);
|
expect(screen.getAllByText(/beliebig viele Postfächer/).length).toBeGreaterThan(0);
|
||||||
expect(screen.queryAllByText("1 E-Mail-Postfach").length).toBe(0);
|
expect(screen.queryAllByText("1 E-Mail-Postfach").length).toBe(0);
|
||||||
expect(screen.queryAllByText(/1 E-Mail-Postfach/).length).toBe(0);
|
expect(screen.queryAllByText(/1 E-Mail-Postfach/).length).toBe(0);
|
||||||
expect(screen.getAllByText(/1,00 €/).length).toBeGreaterThan(0);
|
expect(screen.getAllByText(/1,00 €/).length).toBeGreaterThan(0);
|
||||||
|
// Wechsel und Zusatzspeicher auch hier nur unter den Bedingungen des Portals.
|
||||||
|
const speicher = within(sectionOf("E-Mail-Postfächer und Zusatzspeicher"));
|
||||||
|
expect(speicher.getAllByText(/nicht gekündigt/).length).toBeGreaterThan(0);
|
||||||
|
expect(speicher.getAllByText(/keine Zahlung offen/).length).toBeGreaterThan(0);
|
||||||
|
const hosting = within(sectionOf("Hosting-Abo für statische Websites"));
|
||||||
|
expect(hosting.getAllByText(/nicht gekündigt/).length).toBeGreaterThan(0);
|
||||||
|
expect(hosting.getAllByText(/keine Zahlung offen/).length).toBeGreaterThan(0);
|
||||||
|
expect(hosting.getAllByText(/neue Mindestlaufzeit von 12 Monaten/).length).toBeGreaterThan(0);
|
||||||
|
expect(hosting.getByRole("link", { name: /§ 9 der Vertragsbedingungen/ })).toHaveAttribute(
|
||||||
|
"href",
|
||||||
|
"https://project.webklar.com/abo-bedingungen.html#wechsel",
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("AGB Modul C verweist auf das Hosting-Abo", () => {
|
it("AGB Modul C verweist auf das Hosting-Abo", () => {
|
||||||
render(
|
render(
|
||||||
<MemoryRouter>
|
<MemoryRouter future={routerFuture}>
|
||||||
<AGB />
|
<AGB />
|
||||||
</MemoryRouter>,
|
</MemoryRouter>,
|
||||||
);
|
);
|
||||||
expect(screen.getAllByText(/Hosting-Abo/).length).toBeGreaterThan(0);
|
const modulC = within(sectionOf(/Leistungsmodul C/));
|
||||||
|
expect(modulC.getAllByText(/Hosting-Abo/).length).toBeGreaterThan(0);
|
||||||
|
expect(modulC.getByRole("link", { name: "Vertragsbedingungen für die WEBklar-Abos" })).toHaveAttribute(
|
||||||
|
"href",
|
||||||
|
"https://project.webklar.com/abo-bedingungen.html",
|
||||||
|
);
|
||||||
expect(screen.queryAllByText(/verlängern sich automatisch/).length).toBe(0);
|
expect(screen.queryAllByText(/verlängern sich automatisch/).length).toBe(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
Reference in new issue
Block a user