save
This commit is contained in:
@@ -3,6 +3,7 @@ import * as React from "react"
|
||||
import { Container, Section, SectionHeading } from "@/components/gebos/section"
|
||||
import { PageBreadcrumb } from "@/components/gebos/page-breadcrumb"
|
||||
import { PageHero } from "@/components/gebos/page-hero"
|
||||
import { FeatureBand } from "@/components/gebos/feature-band"
|
||||
import { FeatureTile } from "@/components/gebos/icon-tile"
|
||||
|
||||
type AudienceFeature = {
|
||||
@@ -34,6 +35,7 @@ function AudiencePage({
|
||||
actions,
|
||||
visual,
|
||||
features,
|
||||
featureLayout = "tiles",
|
||||
children,
|
||||
closing,
|
||||
}: {
|
||||
@@ -45,6 +47,11 @@ function AudiencePage({
|
||||
actions?: React.ReactNode
|
||||
visual?: React.ReactNode
|
||||
features: AudienceFeature[]
|
||||
/**
|
||||
* `tiles` — bare icon-over-label tiles on the page background.
|
||||
* `band` — one divided white card (larger line icons, two-line subs).
|
||||
*/
|
||||
featureLayout?: "tiles" | "band"
|
||||
/** additional full-width spec sections between feature row and closing */
|
||||
children?: React.ReactNode
|
||||
closing?: React.ReactNode
|
||||
@@ -69,17 +76,21 @@ function AudiencePage({
|
||||
/>
|
||||
<Container>
|
||||
<Section className="pt-2 sm:pt-4 lg:pt-6">
|
||||
<div className="grid grid-cols-2 gap-x-6 gap-y-10 sm:grid-cols-4">
|
||||
{features.map((feature, i) => (
|
||||
<FeatureTile
|
||||
key={i}
|
||||
icon={feature.icon}
|
||||
media={feature.media}
|
||||
title={feature.title}
|
||||
sub={feature.sub}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
{featureLayout === "band" ? (
|
||||
<FeatureBand items={features} />
|
||||
) : (
|
||||
<div className="grid grid-cols-2 gap-x-6 gap-y-10 sm:grid-cols-4">
|
||||
{features.map((feature, i) => (
|
||||
<FeatureTile
|
||||
key={i}
|
||||
icon={feature.icon}
|
||||
media={feature.media}
|
||||
title={feature.title}
|
||||
sub={feature.sub}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</Section>
|
||||
{children}
|
||||
{closing}
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
import { Link } from "react-router-dom"
|
||||
import { Euro, Handshake, ReceiptText, ShieldCheck, Wrench } from "lucide-react"
|
||||
import { Clock, Euro, HardHat, Network } from "lucide-react"
|
||||
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Card } from "@/components/ui/card"
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table"
|
||||
BenefitGrid,
|
||||
type BenefitGridItem,
|
||||
} from "@/components/gebos/benefit-grid"
|
||||
import {
|
||||
ComparisonTable,
|
||||
type ComparisonColumn,
|
||||
type ComparisonRow,
|
||||
} from "@/components/gebos/comparison-table"
|
||||
import { Section, SectionHeading } from "@/components/gebos/section"
|
||||
import { CtaBanner } from "@/components/gebos/cta-banner"
|
||||
import { NumberedList } from "@/components/gebos/process-steps"
|
||||
import { StepRail } from "@/components/gebos/process-steps"
|
||||
import {
|
||||
CloudAutomationIcon,
|
||||
CrossedToolsIcon,
|
||||
EuroCircleIcon,
|
||||
PortalGaugeIcon,
|
||||
PreconfiguredIcon,
|
||||
} from "@/components/gebos/line-icons"
|
||||
import { OptionCard } from "@/components/gebos/option-card"
|
||||
import { AssetRender, renders } from "@/components/gebos/site-assets"
|
||||
import { AudiencePage } from "@/pages/audiences/audience-page"
|
||||
|
||||
@@ -31,7 +39,7 @@ function HomeownerArt() {
|
||||
imgClassName="w-full"
|
||||
loading="eager"
|
||||
/>
|
||||
<AssetRender
|
||||
{/* <AssetRender
|
||||
render={renders.smokeAlarm}
|
||||
className="absolute top-[8%] left-[2%] w-[26%]"
|
||||
imgClassName="w-full"
|
||||
@@ -50,69 +58,140 @@ function HomeownerArt() {
|
||||
render={renders.cubesRound}
|
||||
alt=""
|
||||
className="absolute top-[50%] right-[30%] w-[16%] scale-200 z-30"
|
||||
/> */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Page-local scene for the full-service route: the fitter drilling the gateway
|
||||
* onto the drywall panel. 4:3 frame to match the shipping-box render next door.
|
||||
* The render is a self-contained scene whose subject occupies the middle 79%
|
||||
* of its 4:5 canvas, so it is scaled past the frame and dropped below it: the
|
||||
* subject then fills the frame's height while the surrounding matte — invisible
|
||||
* on the card — is what overflows.
|
||||
*/
|
||||
function FullServiceArt() {
|
||||
return (
|
||||
<div className="relative w-full aspect-[4/3]">
|
||||
<AssetRender
|
||||
render={renders.workerDrillingGateway2}
|
||||
className="absolute inset-x-0 -bottom-[15%] mx-auto w-[74%]"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Portal laptop for the benefit grid's centre cell. Measured on the master,
|
||||
* the laptop occupies 11.0–88.5 % of the canvas height and 7.7–83.9 % of its
|
||||
* width, i.e. 77.4 % of each with clear air around it. Fitting the *canvas*
|
||||
* to the cell would therefore leave the laptop floating small in the middle,
|
||||
* so the canvas is inflated past the cell by exactly that air (11.04 % /
|
||||
* 0.7744 above, 11.52 % / 0.7744 below): the laptop then fills the cell's
|
||||
* height, flush with the flanking cards' floor and a grid gap clear of the
|
||||
* row above — it never crosses into a card. `object-contain` keeps that true
|
||||
* whatever height the row settles at; the wider right inset cancels the
|
||||
* laptop's own leftward bias inside the canvas so it reads centred.
|
||||
*/
|
||||
function PortalLaptopArt() {
|
||||
return (
|
||||
<AssetRender
|
||||
render={renders.laptopDashboard}
|
||||
className="mx-auto block w-full max-w-md lg:absolute lg:-top-[14.3%] lg:-right-[12.3%] lg:-bottom-[14.9%] lg:-left-[3%] lg:mx-0 lg:w-auto lg:max-w-none"
|
||||
imgClassName="h-full w-full object-contain"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const SELF_INSTALL_STEPS = [
|
||||
{
|
||||
media: (
|
||||
<AssetRender render={renders.houseSmallIso} imgClassName="w-28" />
|
||||
),
|
||||
title: "Gebäude angeben",
|
||||
description:
|
||||
"Sie teilen uns die grundlegenden Informationen zum Gebäude und den Wohnungen mit.",
|
||||
"Daten zu Ihrem Gebäude und den Wohneinheiten in wenigen Schritten erfassen.",
|
||||
},
|
||||
{
|
||||
media: (
|
||||
<>
|
||||
<AssetRender render={renders.heatMeter} imgClassName="w-24" />
|
||||
<AssetRender render={renders.smokeAlarm} imgClassName="w-20" />
|
||||
</>
|
||||
),
|
||||
title: "Passende Ausstattung zusammenstellen",
|
||||
description:
|
||||
"Die benötigten Zähler, Kommunikationskomponenten und gegebenenfalls Rauchwarnmelder werden zusammengestellt.",
|
||||
description: "Wir empfehlen die benötigte Ausstattung – Sie wählen aus.",
|
||||
},
|
||||
{
|
||||
media: (
|
||||
<AssetRender render={renders.shippingBoxClosed} imgClassName="w-36" />
|
||||
),
|
||||
title: "Vorkonfiguriert erhalten",
|
||||
description:
|
||||
"Die Geräte werden bereits für Ihr Gebäude vorbereitet geliefert.",
|
||||
description: "Ihre Technik kommt vorkonfiguriert und einsatzbereit an.",
|
||||
},
|
||||
{
|
||||
media: <AssetRender render={renders.drillTool} imgClassName="w-32" />,
|
||||
title: "Montieren",
|
||||
description:
|
||||
"Sie selbst, Ihr Hausmeister oder Ihr Fachbetrieb installiert die Geräte.",
|
||||
"Sie montieren mit Ihrem Handwerker oder selbst – flexibel und unkompliziert.",
|
||||
},
|
||||
{
|
||||
media: (
|
||||
<AssetRender render={renders.refreshLoopCloud} imgClassName="w-28" />
|
||||
),
|
||||
title: "GebOS übernimmt",
|
||||
description:
|
||||
"Nach der Inbetriebnahme laufen Datenerfassung und die gebuchten Dienstleistungen über GebOS.",
|
||||
"Wir übernehmen Ablesung, Übertragung und Auswertung automatisch.",
|
||||
},
|
||||
]
|
||||
|
||||
const WHY_GEBOS = [
|
||||
const WHY_GEBOS: BenefitGridItem[] = [
|
||||
{
|
||||
icon: <EuroCircleIcon />,
|
||||
title: "Kosten kontrollieren",
|
||||
text: "Entscheiden Sie selbst, welche Arbeiten Sie übernehmen und welche Sie abgeben möchten.",
|
||||
},
|
||||
{
|
||||
icon: <Network strokeWidth={1.6} />,
|
||||
title: "Keine unnötige technische Komplexität",
|
||||
text: "Die Hardware wird für das jeweilige Gebäude vorbereitet.",
|
||||
},
|
||||
{
|
||||
icon: <HardHat strokeWidth={1.6} />,
|
||||
title: "Bestehenden Handwerker nutzen",
|
||||
text: "Sie benötigen keinen speziellen GebOS-Installateur.",
|
||||
},
|
||||
{
|
||||
icon: <PortalGaugeIcon />,
|
||||
title: "Alles an einem Ort",
|
||||
text: "UVI, Abrechnung, Geräte und weitere Gebäudedienstleistungen werden zentral verwaltet.",
|
||||
},
|
||||
{
|
||||
icon: <Clock strokeWidth={1.6} />,
|
||||
title: "Weniger laufender Aufwand",
|
||||
text: "Nach der Einrichtung werden Verbrauchsdaten automatisch erfasst und verarbeitet.",
|
||||
},
|
||||
]
|
||||
|
||||
const VARIANT_ROWS = [
|
||||
["Planung", "gemeinsam mit GebOS", "GebOS"],
|
||||
["Hardware", "GebOS", "GebOS"],
|
||||
["Installation", "Kunde / eigener Fachbetrieb", "organisiert durch GebOS"],
|
||||
["Softwareeinrichtung", "vorbereitet durch GebOS", "GebOS"],
|
||||
["Laufender Betrieb", "GebOS", "GebOS"],
|
||||
["Kosten", "möglichst niedrig", "höhere Planungssicherheit und Komfort"],
|
||||
const VARIANT_COLUMNS: ComparisonColumn[] = [
|
||||
{ title: "Selbst installieren", highlight: true },
|
||||
{ title: "Komplettlösung" },
|
||||
]
|
||||
|
||||
const VARIANT_ROWS: ComparisonRow[] = [
|
||||
{ label: "Planung", cells: ["gemeinsam mit GebOS", "GebOS"] },
|
||||
{ label: "Hardware", cells: ["GebOS", "GebOS"] },
|
||||
{
|
||||
label: "Installation",
|
||||
cells: ["Kunde / eigener Fachbetrieb", "organisiert durch GebOS"],
|
||||
},
|
||||
{ label: "Softwareeinrichtung", cells: ["vorbereitet durch GebOS", "GebOS"] },
|
||||
{ label: "Laufender Betrieb", cells: ["GebOS", "GebOS"] },
|
||||
{
|
||||
label: "Kosten",
|
||||
cells: ["möglichst niedrig", "höhere Planungssicherheit und Komfort"],
|
||||
},
|
||||
]
|
||||
|
||||
export default function HauseigentuemerPage() {
|
||||
@@ -131,26 +210,27 @@ export default function HauseigentuemerPage() {
|
||||
</Button>
|
||||
}
|
||||
visual={<HomeownerArt />}
|
||||
featureLayout="band"
|
||||
features={[
|
||||
{
|
||||
icon: <Wrench />,
|
||||
title: "Selbst installieren",
|
||||
sub: "Kosten sparen, flexibel bleiben",
|
||||
icon: <PreconfiguredIcon />,
|
||||
title: "Vorkonfigurierte Technik",
|
||||
sub: "Einsatzbereit, perfekt aufeinander abgestimmt.",
|
||||
},
|
||||
{
|
||||
icon: <ShieldCheck />,
|
||||
title: "Komplettlösung",
|
||||
sub: "Wir kümmern uns um alles",
|
||||
icon: <CrossedToolsIcon />,
|
||||
title: "Flexibel installieren",
|
||||
sub: "Selbst übernehmen oder vom Profi montieren lassen.",
|
||||
},
|
||||
{
|
||||
icon: <ReceiptText />,
|
||||
title: "Transparente Preise",
|
||||
sub: "Keine versteckten Kosten",
|
||||
icon: <CloudAutomationIcon />,
|
||||
title: "Automatischer Betrieb",
|
||||
sub: "GebOS übernimmt Ablesung, Übertragung und Auswertung.",
|
||||
},
|
||||
{
|
||||
icon: <Handshake />,
|
||||
title: "Bestehende Partner",
|
||||
sub: "Ihre Handwerker bleiben",
|
||||
icon: <PortalGaugeIcon />,
|
||||
title: "Alles zentral verwaltet",
|
||||
sub: "Alle Daten, Geräte und Gebäude im Blick.",
|
||||
},
|
||||
]}
|
||||
closing={
|
||||
@@ -181,51 +261,45 @@ export default function HauseigentuemerPage() {
|
||||
title="Zwei Wege zu GebOS"
|
||||
/>
|
||||
<div className="mt-10 grid gap-6 md:grid-cols-2">
|
||||
<Card className="relative gap-0 overflow-hidden p-7">
|
||||
<AssetRender
|
||||
render={renders.drillTool}
|
||||
className="pointer-events-none absolute -top-2 -right-3 w-28 opacity-90"
|
||||
/>
|
||||
<h3 className="pr-24 text-lg font-extrabold tracking-tight text-navy">
|
||||
Selbst installieren
|
||||
</h3>
|
||||
<p className="mt-3 text-sm leading-relaxed text-pretty text-muted-foreground">
|
||||
Sie möchten Kosten niedrig halten und können die Installation
|
||||
selbst oder über einen vertrauten Heizungsbauer, Hausmeister
|
||||
oder anderen Fachbetrieb organisieren? GebOS liefert die
|
||||
benötigte Technik passend zu Ihrem Gebäude vorkonfiguriert.
|
||||
</p>
|
||||
<p className="mt-3 text-sm font-bold leading-relaxed text-navy">
|
||||
Sie organisieren die Montage. GebOS übernimmt den digitalen
|
||||
Betrieb.
|
||||
</p>
|
||||
<div className="mt-6">
|
||||
<Button asChild size="sm">
|
||||
<OptionCard
|
||||
title="Selbst installieren"
|
||||
lead="Sie erhalten vorkonfigurierte Technik und installieren mit Ihrem Handwerker oder in Eigenregie."
|
||||
takeaway={
|
||||
<>
|
||||
Sie organisieren die Montage.
|
||||
<br />
|
||||
GebOS übernimmt den digitalen Betrieb.
|
||||
</>
|
||||
}
|
||||
visual={
|
||||
<AssetRender
|
||||
render={renders.shippingBoxMeters}
|
||||
className="block w-full"
|
||||
/>
|
||||
}
|
||||
action={
|
||||
<Button asChild size="lg">
|
||||
<Link to="/konfigurator">Preis berechnen</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
<Card className="relative gap-0 overflow-hidden p-7">
|
||||
<AssetRender
|
||||
render={renders.shippingBoxMeters}
|
||||
className="pointer-events-none absolute -top-1 -right-4 w-32"
|
||||
/>
|
||||
<h3 className="pr-28 text-lg font-extrabold tracking-tight text-navy">
|
||||
Komplett installieren lassen
|
||||
</h3>
|
||||
<p className="mt-3 text-sm leading-relaxed text-pretty text-muted-foreground">
|
||||
Sie möchten sich möglichst wenig mit Planung, Beschaffung und
|
||||
Installation beschäftigen? GebOS organisiert die komplette
|
||||
Umsetzung für Sie. Von der Ermittlung der benötigten Geräte
|
||||
über die Installation bis zum laufenden Betrieb erhalten Sie
|
||||
eine durchgängige Lösung.
|
||||
</p>
|
||||
<div className="mt-6">
|
||||
<Button asChild size="sm" variant="outline">
|
||||
}
|
||||
/>
|
||||
<OptionCard
|
||||
title="Komplett installieren lassen"
|
||||
lead="Lehnen Sie sich zurück. GebOS übernimmt Planung, Installation und Einrichtung – inklusive Service."
|
||||
takeaway={
|
||||
<>
|
||||
Ein Ansprechpartner. Alles aus einer Hand.
|
||||
<br />
|
||||
Komplettlösung mit voller Betreuung.
|
||||
</>
|
||||
}
|
||||
visual={<FullServiceArt />}
|
||||
action={
|
||||
<Button asChild size="lg" variant="outline">
|
||||
<Link to="/kontakt">Komplettlösung anfragen</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
@@ -234,7 +308,7 @@ export default function HauseigentuemerPage() {
|
||||
eyebrow="Schritt für Schritt"
|
||||
title="So funktioniert die Selbstinstallation"
|
||||
/>
|
||||
<NumberedList steps={SELF_INSTALL_STEPS} className="mt-10 max-w-2xl" />
|
||||
<StepRail steps={SELF_INSTALL_STEPS} className="mt-10" />
|
||||
</Section>
|
||||
|
||||
<Section className="pt-0 sm:pt-0 lg:pt-0">
|
||||
@@ -242,16 +316,11 @@ export default function HauseigentuemerPage() {
|
||||
eyebrow="Ihre Vorteile"
|
||||
title="Warum GebOS für Hauseigentümer?"
|
||||
/>
|
||||
<div className="mt-10 grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{WHY_GEBOS.map((item) => (
|
||||
<Card key={item.title} className="gap-0 p-6">
|
||||
<h3 className="text-sm font-bold text-navy">{item.title}</h3>
|
||||
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">
|
||||
{item.text}
|
||||
</p>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
<BenefitGrid
|
||||
className="mt-10"
|
||||
items={WHY_GEBOS}
|
||||
visual={<PortalLaptopArt />}
|
||||
/>
|
||||
</Section>
|
||||
|
||||
<Section className="pt-0 sm:pt-0 lg:pt-0">
|
||||
@@ -259,32 +328,11 @@ export default function HauseigentuemerPage() {
|
||||
eyebrow="Im Vergleich"
|
||||
title="Welche Variante passt zu mir?"
|
||||
/>
|
||||
<Card className="mt-10 gap-0 overflow-hidden p-2 sm:p-4">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-[30%]" />
|
||||
<TableHead>Selbst installieren</TableHead>
|
||||
<TableHead>Komplettlösung</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{VARIANT_ROWS.map(([label, self, full]) => (
|
||||
<TableRow key={label}>
|
||||
<TableCell className="font-bold text-navy">
|
||||
{label}
|
||||
</TableCell>
|
||||
<TableCell className="text-muted-foreground">
|
||||
{self}
|
||||
</TableCell>
|
||||
<TableCell className="text-muted-foreground">
|
||||
{full}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</Card>
|
||||
<ComparisonTable
|
||||
className="mt-10"
|
||||
columns={VARIANT_COLUMNS}
|
||||
rows={VARIANT_ROWS}
|
||||
/>
|
||||
</Section>
|
||||
</AudiencePage>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user