Compare commits
3
Commits
44fe30a781
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c5cbd8f3a | ||
|
|
7cfb7fd5ac | ||
|
|
467dae14a2 |
@@ -31,6 +31,15 @@ type ExpandingCard = {
|
||||
/** which side of the container the open card sits on – the rail takes the other */
|
||||
type Side = "left" | "right"
|
||||
|
||||
/**
|
||||
* Where the minimised cards are allowed to gather. `auto` mirrors the pointer –
|
||||
* the picked card keeps its half, so the rail changes sides as you browse.
|
||||
* Pinning it to one side trades that spatial cue for calm: picking out of the
|
||||
* rail then shifts the column by a single slot instead of sending every card
|
||||
* across the container.
|
||||
*/
|
||||
type RailSide = Side | "auto"
|
||||
|
||||
/** the face a card currently shows */
|
||||
type Face = "brief" | "rail" | "open"
|
||||
|
||||
@@ -567,9 +576,10 @@ function GridCard({
|
||||
/**
|
||||
* Card grid that unpacks in place. Clicking a card grows it to the full height
|
||||
* of the grid it was part of, while the remaining cards gather into a column of
|
||||
* a third of the width beside it – on the side the open card came *from*, so
|
||||
* the card you picked stays where you clicked it and everything else moves out
|
||||
* of its way. Opening a card out of the rail therefore flips the composition.
|
||||
* a third of the width beside it – by default on the side the open card came
|
||||
* *from*, so the card you picked stays where you clicked it and everything else
|
||||
* moves out of its way. Opening a card out of the rail therefore flips the
|
||||
* composition; pass `railSide` to pin the column and keep the travel short.
|
||||
*
|
||||
* Every card is absolutely positioned from measured geometry, which keeps a
|
||||
* state change to a transform plus a size: the faces are pre-laid out at the
|
||||
@@ -578,9 +588,12 @@ function GridCard({
|
||||
*/
|
||||
function ExpandingCardGrid({
|
||||
items,
|
||||
railSide = "auto",
|
||||
className,
|
||||
}: {
|
||||
items: ExpandingCard[]
|
||||
/** side the minimised cards stack on; `auto` follows the card you clicked */
|
||||
railSide?: RailSide
|
||||
className?: string
|
||||
}) {
|
||||
const [open, setOpen] = React.useState<{ id: string; side: Side } | null>(
|
||||
@@ -592,13 +605,18 @@ function ExpandingCardGrid({
|
||||
const uid = React.useId()
|
||||
|
||||
const active = open ? items.findIndex((item) => item.id === open.id) : -1
|
||||
/* a pinned rail decides the composition outright; the pointer-driven side
|
||||
stays in state either way, so switching back to `auto` resumes from the
|
||||
half the reader last picked instead of jumping */
|
||||
const pinned =
|
||||
railSide === "auto" ? null : railSide === "left" ? "right" : "left"
|
||||
const plan = planLayout({
|
||||
count: items.length,
|
||||
width: metrics.width,
|
||||
teaserHeights: metrics.teaser,
|
||||
copyHeights: metrics.copy,
|
||||
active,
|
||||
side: open?.side ?? "left",
|
||||
side: pinned ?? open?.side ?? "left",
|
||||
})
|
||||
|
||||
/* transitions only after the measured geometry has been painted once, and
|
||||
@@ -622,7 +640,8 @@ function ExpandingCardGrid({
|
||||
}
|
||||
const frame = plan.frames[index]
|
||||
/* the card keeps its side: whichever half it is sitting in when clicked is
|
||||
the half it opens into, so the rail always forms on the other one */
|
||||
the half it opens into, so the rail forms on the other one – unless a
|
||||
pinned `railSide` overrules it above */
|
||||
const onRight = frame
|
||||
? frame.x + frame.w / 2 > metrics.width / 2 + 1
|
||||
: false
|
||||
|
||||
@@ -26,8 +26,8 @@ function PriceCard({
|
||||
cadence: React.ReactNode
|
||||
price: React.ReactNode
|
||||
unit: React.ReactNode
|
||||
/** umlagefähig? tone drives soft-teal vs. soft-red pill */
|
||||
allocation: { label: React.ReactNode; tone: "positive" | "negative" }
|
||||
/** optional legal cost-allocation note, shown only after review */
|
||||
allocation?: { label: React.ReactNode; tone: "positive" | "negative" }
|
||||
description: React.ReactNode
|
||||
media?: React.ReactNode
|
||||
className?: string
|
||||
@@ -47,6 +47,7 @@ function PriceCard({
|
||||
{price}
|
||||
</div>
|
||||
<div className="mt-1.5 text-sm text-muted-foreground">{unit}</div>
|
||||
{allocation ? (
|
||||
<Badge
|
||||
variant={allocation.tone === "positive" ? "default" : "destructive"}
|
||||
className="mt-4"
|
||||
@@ -54,6 +55,7 @@ function PriceCard({
|
||||
{allocation.tone === "positive" ? <CircleCheck /> : <Ban />}
|
||||
{allocation.label}
|
||||
</Badge>
|
||||
) : null}
|
||||
<Separator className="mt-5 mb-4" />
|
||||
<p className="text-sm leading-relaxed text-muted-foreground">
|
||||
{description}
|
||||
|
||||
@@ -8,7 +8,7 @@ const COLUMNS: { title: string; links: { to: string; label: string }[] }[] = [
|
||||
title: "Produkt",
|
||||
links: [
|
||||
{ to: "/produkte", label: "Produkte" },
|
||||
{ to: "/produkte/uvi", label: "UVI" },
|
||||
{ to: "/produkte/uvi", label: "Verbrauchsinformation (UVI)" },
|
||||
{ to: "/produkte/heizkostenabrechnung", label: "Heizkostenabrechnung" },
|
||||
{ to: "/produkte/rauchwarnmelder", label: "Rauchwarnmelder" },
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from "react"
|
||||
import { ChevronDown, Menu } from "lucide-react"
|
||||
import { Check, ChevronDown, Menu } from "lucide-react"
|
||||
import { Link, NavLink, matchPath, useLocation } from "react-router-dom"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
@@ -24,7 +24,7 @@ const AUDIENCES = [
|
||||
|
||||
/** mirrors the product registry in `@/pages/products/product-page` */
|
||||
const PRODUCTS = [
|
||||
{ to: "/produkte/uvi", label: "UVI" },
|
||||
{ to: "/produkte/uvi", label: "Verbrauchsinformation (UVI)" },
|
||||
{ to: "/produkte/heizkostenabrechnung", label: "Heizkostenabrechnung" },
|
||||
{ to: "/produkte/rauchwarnmelder", label: "Rauchwarnmelder" },
|
||||
{
|
||||
@@ -131,7 +131,33 @@ function useActivePill(activeKey: string | undefined) {
|
||||
return { navRef, pill }
|
||||
}
|
||||
|
||||
function MenuLink({
|
||||
to,
|
||||
label,
|
||||
pathname,
|
||||
}: {
|
||||
to: string
|
||||
label: string
|
||||
pathname: string
|
||||
}) {
|
||||
const current = Boolean(matchPath({ path: to, end: true }, pathname))
|
||||
|
||||
return (
|
||||
<DropdownMenuItem
|
||||
asChild
|
||||
className={cn(current && "bg-accent font-bold text-brand-800")}
|
||||
>
|
||||
<Link to={to} aria-current={current ? "page" : undefined}>
|
||||
<span className="min-w-0 flex-1">{label}</span>
|
||||
{current ? <Check aria-hidden="true" className="size-4" /> : null}
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
)
|
||||
}
|
||||
|
||||
function NavMenu({ item, active }: { item: NavItem; active: boolean }) {
|
||||
const { pathname } = useLocation()
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger
|
||||
@@ -145,14 +171,10 @@ function NavMenu({ item, active }: { item: NavItem; active: boolean }) {
|
||||
<ChevronDown className="size-3.5 opacity-60" />
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start">
|
||||
<DropdownMenuItem asChild>
|
||||
<Link to={item.to}>Übersicht</Link>
|
||||
</DropdownMenuItem>
|
||||
<MenuLink to={item.to} label="Übersicht" pathname={pathname} />
|
||||
<DropdownMenuSeparator />
|
||||
{item.menu?.map((a) => (
|
||||
<DropdownMenuItem key={a.to} asChild>
|
||||
<Link to={a.to}>{a.label}</Link>
|
||||
</DropdownMenuItem>
|
||||
{item.menu?.map((link) => (
|
||||
<MenuLink key={link.to} {...link} pathname={pathname} />
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
@@ -200,6 +222,8 @@ function DesktopNav() {
|
||||
}
|
||||
|
||||
function MobileMenu() {
|
||||
const { pathname } = useLocation()
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
@@ -208,26 +232,25 @@ function MobileMenu() {
|
||||
<span className="sr-only">Menü öffnen</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-64">
|
||||
<DropdownMenuContent align="end" className="w-72">
|
||||
{NAV_ITEMS.map((item) =>
|
||||
item.menu ? (
|
||||
<React.Fragment key={item.to}>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuLabel>{item.label}</DropdownMenuLabel>
|
||||
<DropdownMenuItem asChild>
|
||||
<Link to={item.to}>Übersicht</Link>
|
||||
</DropdownMenuItem>
|
||||
{item.menu.map((a) => (
|
||||
<DropdownMenuItem key={a.to} asChild>
|
||||
<Link to={a.to}>{a.label}</Link>
|
||||
</DropdownMenuItem>
|
||||
<MenuLink to={item.to} label="Übersicht" pathname={pathname} />
|
||||
{item.menu.map((link) => (
|
||||
<MenuLink key={link.to} {...link} pathname={pathname} />
|
||||
))}
|
||||
<DropdownMenuSeparator />
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<DropdownMenuItem key={item.to} asChild>
|
||||
<Link to={item.to}>{item.label}</Link>
|
||||
</DropdownMenuItem>
|
||||
<MenuLink
|
||||
key={item.to}
|
||||
to={item.to}
|
||||
label={item.label}
|
||||
pathname={pathname}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
<DropdownMenuSeparator />
|
||||
@@ -257,9 +280,6 @@ function SiteHeader() {
|
||||
<DesktopNav />
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
{/* <Button asChild size="sm" className="hidden sm:inline-flex">
|
||||
<Link to="/konfigurator">Preis berechnen</Link>
|
||||
</Button> */}
|
||||
<Button asChild variant="ghost" size="sm" className="hidden sm:inline-flex">
|
||||
<a href="https://app.gebos.online">Login</a>
|
||||
</Button>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import * as React from "react"
|
||||
import { Link } from "react-router-dom"
|
||||
import { ArrowRight } from "lucide-react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { AssetRender, renders } from "@/components/solenos/site-assets"
|
||||
@@ -6,6 +8,7 @@ import { AssetRender, renders } from "@/components/solenos/site-assets"
|
||||
type TrustPanelItem = {
|
||||
icon: React.ReactNode
|
||||
label: React.ReactNode
|
||||
to?: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -14,6 +17,38 @@ type TrustPanelItem = {
|
||||
* so the labels stay on one line next to the security render, with the
|
||||
* follow-up link on the baseline underneath.
|
||||
*/
|
||||
function TrustProperty({ item }: { item: TrustPanelItem }) {
|
||||
const content = (
|
||||
<>
|
||||
<span className="flex shrink-0 text-brand-600 [&_svg]:size-7">
|
||||
{item.icon}
|
||||
</span>
|
||||
<span className="min-w-0 flex-1 text-[0.9375rem] leading-snug font-medium text-balance text-navy/75">
|
||||
{item.label}
|
||||
</span>
|
||||
{item.to ? (
|
||||
<ArrowRight
|
||||
aria-hidden="true"
|
||||
className="size-4 shrink-0 text-brand-600"
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
const className =
|
||||
"flex items-center gap-4 rounded-xl bg-card px-5 py-3.5 shadow-card"
|
||||
|
||||
return item.to ? (
|
||||
<Link
|
||||
to={item.to}
|
||||
className={`${className} outline-none transition-colors hover:bg-brand-50 focus-visible:ring-[3px] focus-visible:ring-ring/40`}
|
||||
>
|
||||
{content}
|
||||
</Link>
|
||||
) : (
|
||||
<div className={className}>{content}</div>
|
||||
)
|
||||
}
|
||||
|
||||
function TrustPanel({
|
||||
title,
|
||||
items,
|
||||
@@ -44,17 +79,7 @@ function TrustPanel({
|
||||
</h2>
|
||||
<div className="mt-6 grid gap-4 sm:grid-cols-2">
|
||||
{items.map((item, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="bg-card shadow-card flex items-center gap-5 rounded-xl px-5 py-3.5"
|
||||
>
|
||||
<span className="text-brand-600 flex shrink-0 [&_svg]:size-7">
|
||||
{item.icon}
|
||||
</span>
|
||||
<span className="text-navy/75 text-[0.9375rem] leading-snug font-medium text-balance">
|
||||
{item.label}
|
||||
</span>
|
||||
</div>
|
||||
<TrustProperty key={i} item={item} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -29,6 +29,7 @@ function AudienceBreadcrumb({ current }: { current: string }) {
|
||||
*/
|
||||
function AudiencePage({
|
||||
breadcrumb,
|
||||
eyebrow,
|
||||
title,
|
||||
tagline,
|
||||
lead,
|
||||
@@ -40,6 +41,7 @@ function AudiencePage({
|
||||
closing,
|
||||
}: {
|
||||
breadcrumb: string
|
||||
eyebrow?: React.ReactNode
|
||||
title: React.ReactNode
|
||||
/** short bold subline under the H1 (e.g. "Bestellen. Montieren. Fertig.") */
|
||||
tagline?: React.ReactNode
|
||||
@@ -60,6 +62,7 @@ function AudiencePage({
|
||||
<>
|
||||
<PageHero
|
||||
breadcrumb={<AudienceBreadcrumb current={breadcrumb} />}
|
||||
eyebrow={eyebrow}
|
||||
title={title}
|
||||
lead={
|
||||
<>
|
||||
|
||||
@@ -110,9 +110,9 @@ const SELF_INSTALL_STEPS = [
|
||||
media: (
|
||||
<AssetRender render={renders.houseSmallIso} imgClassName="w-28" />
|
||||
),
|
||||
title: "Gebäude angeben",
|
||||
title: "Gebäudedaten online erfassen",
|
||||
description:
|
||||
"Daten zu Ihrem Gebäude und den Wohneinheiten in wenigen Schritten erfassen.",
|
||||
"Daten zum Gebäude und zu den Wohneinheiten direkt online eingeben.",
|
||||
},
|
||||
{
|
||||
media: (
|
||||
@@ -121,29 +121,31 @@ const SELF_INSTALL_STEPS = [
|
||||
<AssetRender render={renders.smokeAlarm} imgClassName="w-20" />
|
||||
</>
|
||||
),
|
||||
title: "Passende Ausstattung zusammenstellen",
|
||||
description: "Wir empfehlen die benötigte Ausstattung – Sie wählen aus.",
|
||||
title: "Benötigte Ausstattung bestimmen lassen",
|
||||
description:
|
||||
"SolenOS ermittelt und konfiguriert aus den Objektdaten die passende notwendige beziehungsweise gesetzliche Mindestausstattung.",
|
||||
},
|
||||
{
|
||||
media: (
|
||||
<AssetRender render={renders.shippingBoxClosed} imgClassName="w-36" />
|
||||
),
|
||||
title: "Vorkonfiguriert erhalten",
|
||||
description: "Ihre Technik kommt vorkonfiguriert und einsatzbereit an.",
|
||||
description:
|
||||
"SolenOS prüft die Ausstattung vor dem Versand und ordnet die Geräte den vorgesehenen Wohnungen zu.",
|
||||
},
|
||||
{
|
||||
media: <AssetRender render={renders.drillTool} imgClassName="w-32" />,
|
||||
title: "Montieren",
|
||||
description:
|
||||
"Sie montieren mit Ihrem Handwerker oder selbst – flexibel und unkompliziert.",
|
||||
"Sie montieren selbst oder gemeinsam mit Ihrem eigenen Handwerker.",
|
||||
},
|
||||
{
|
||||
media: (
|
||||
<AssetRender render={renders.refreshLoopCloud} imgClassName="w-28" />
|
||||
),
|
||||
title: "SolenOS übernimmt",
|
||||
title: "Betrieb übernehmen lassen",
|
||||
description:
|
||||
"Wir übernehmen Ablesung, Übertragung und Auswertung automatisch.",
|
||||
"SolenOS übernimmt Einrichtung, Datenübertragung und laufenden Betrieb.",
|
||||
},
|
||||
]
|
||||
|
||||
@@ -165,13 +167,13 @@ const WHY_SOLENOS: BenefitGridItem[] = [
|
||||
},
|
||||
{
|
||||
icon: <PortalGaugeIcon />,
|
||||
title: "Alles an einem Ort",
|
||||
text: "UVI, Abrechnung, Geräte und weitere Gebäudedienstleistungen werden zentral verwaltet.",
|
||||
title: "Getrennte Portalrechte",
|
||||
text: "Sie sehen Gebäude, Wohnungen, Geräte, Status und Verbrauchswerte an einer Stelle. Bewohner sehen ausschließlich Daten ihrer eigenen Wohnung und ihres eigenen Nutzungszeitraums.",
|
||||
},
|
||||
{
|
||||
icon: <Clock strokeWidth={1.6} />,
|
||||
title: "Weniger laufender Aufwand",
|
||||
text: "Nach der Einrichtung werden Verbrauchsdaten automatisch erfasst und verarbeitet.",
|
||||
title: "Keine regelmäßigen Ablesebesuche",
|
||||
text: "Verbrauchsdaten werden fernabgelesen; Heizkostenabrechnungen werden im Portal erstellt und versandfertig bereitgestellt.",
|
||||
},
|
||||
]
|
||||
|
||||
@@ -187,7 +189,7 @@ const VARIANT_ROWS: ComparisonRow[] = [
|
||||
label: "Installation",
|
||||
cells: ["Kunde / eigener Fachbetrieb", "organisiert durch SolenOS"],
|
||||
},
|
||||
{ label: "Softwareeinrichtung", cells: ["vorbereitet durch SolenOS", "SolenOS"] },
|
||||
{ label: "Softwarekonfiguration vor Ort", cells: ["nicht erforderlich – durch SolenOS eingerichtet", "nicht erforderlich – durch SolenOS eingerichtet"] },
|
||||
{ label: "Laufender Betrieb", cells: ["SolenOS", "SolenOS"] },
|
||||
{
|
||||
label: "Kosten",
|
||||
@@ -199,12 +201,12 @@ const FAQS: FaqItem[] = [
|
||||
{
|
||||
question: "Kann ich die Geräte wirklich selbst installieren?",
|
||||
answer:
|
||||
"Ja. Die Technik kommt vorkonfiguriert und objektbezogen bei Ihnen an. Montiert wird von Ihnen, Ihrem Handwerker oder – wenn Sie die Komplettlösung wählen – von SolenOS. Eine aufwendige Softwarekonfiguration vor Ort ist in keinem Fall erforderlich.",
|
||||
"Ja. Die Technik kommt vorkonfiguriert und objektbezogen bei Ihnen an. Montiert wird von Ihnen, Ihrem Handwerker oder – bei der Komplettlösung – von SolenOS. Eine Softwarekonfiguration vor Ort ist in keinem Fall erforderlich.",
|
||||
},
|
||||
{
|
||||
question: "Was kostet SolenOS für mein Gebäude?",
|
||||
question: "Wann erhalte ich den verbindlichen Gesamtpreis?",
|
||||
answer:
|
||||
"Der Konfigurator gibt Ihnen mit wenigen Angaben zu Gebäude, Wohnungen und gewünschten Leistungen eine erste Preisindikation. Den genauen Preis erhalten Sie, sobald die tatsächlichen Gebäudedaten ergänzt sind.",
|
||||
"Nach dem Schnellkonfigurator ergänzen Sie die Gebäudedetails und Fotos vorhandener Einbausituationen. SolenOS prüft die notwendige Ausstattung und erstellt anschließend das verbindliche Gesamtangebot.",
|
||||
},
|
||||
{
|
||||
question: "Wer übernimmt Ablesung, Übertragung und Auswertung?",
|
||||
@@ -214,7 +216,7 @@ const FAQS: FaqItem[] = [
|
||||
{
|
||||
question: "Was sehe ich im SolenOS Portal?",
|
||||
answer:
|
||||
"Ihre Gebäude, Wohnungen und Geräte an einer Stelle – inklusive Status der Geräte und der laufenden Verbrauchswerte. Bewohner erhalten ihren eigenen Zugang zum Mieterportal.",
|
||||
"Sie sehen Gebäude, Wohnungen, Geräte, Gerätestatus und Verbrauchswerte an einer Stelle. Bewohner erhalten einen eigenen Zugang und sehen ausschließlich Daten ihrer eigenen Wohnung und ihres eigenen Nutzungszeitraums. Heizkostenabrechnungen werden im Portal erstellt und versandfertig bereitgestellt.",
|
||||
},
|
||||
{
|
||||
question: "Kann ich später weitere Gebäude oder Geräte ergänzen?",
|
||||
@@ -227,15 +229,16 @@ export default function HauseigentuemerPage() {
|
||||
return (
|
||||
<AudiencePage
|
||||
breadcrumb="Hauseigentümer"
|
||||
eyebrow="Für Hauseigentümer"
|
||||
title={
|
||||
<span className="block text-[2.25rem] text-pretty sm:text-[2.75rem]">
|
||||
Messdienstleistungen für Ihr Mehrfamilienhaus. Einfach organisiert.
|
||||
</span>
|
||||
}
|
||||
lead="UVI, Heizkostenabrechnung und Rauchwarnmelder mit vorkonfigurierter Technik – selbst installieren oder als Komplettlösung beauftragen."
|
||||
lead="Monatliche Verbrauchsinformation (UVI), Heizkostenabrechnung und Rauchwarnmelder mit vorkonfigurierter Technik – selbst installieren oder als Komplettlösung beauftragen."
|
||||
actions={
|
||||
<Button asChild size="lg">
|
||||
<Link to="/konfigurator">Preis für mein Gebäude berechnen</Link>
|
||||
<Link to="/konfigurator">Konfiguration für mein Gebäude starten</Link>
|
||||
</Button>
|
||||
}
|
||||
visual={<HomeownerArt />}
|
||||
@@ -267,12 +270,12 @@ export default function HauseigentuemerPage() {
|
||||
<CtaBanner
|
||||
icon={<Euro />}
|
||||
title="Welche Lösung passt zu Ihrem Gebäude?"
|
||||
description="Mit wenigen Angaben zur ersten Preisindikation – oder direkt die Komplettlösung anfragen."
|
||||
description="Leistungen und Gebäudedaten online erfassen – oder direkt die Komplettlösung anfragen."
|
||||
actions={
|
||||
<>
|
||||
<Button asChild variant="inverse" size="lg">
|
||||
<Link to="/konfigurator">
|
||||
Preis für mein Gebäude berechnen
|
||||
Konfiguration für mein Gebäude starten
|
||||
</Link>
|
||||
</Button>
|
||||
<Button asChild variant="inverse" size="lg">
|
||||
@@ -293,13 +296,7 @@ export default function HauseigentuemerPage() {
|
||||
<OptionCard
|
||||
title="Selbst installieren"
|
||||
lead="Sie erhalten vorkonfigurierte Technik und installieren mit Ihrem Handwerker oder in Eigenregie."
|
||||
takeaway={
|
||||
<>
|
||||
Sie organisieren die Montage.
|
||||
<br />
|
||||
SolenOS übernimmt den digitalen Betrieb.
|
||||
</>
|
||||
}
|
||||
takeaway="Sie montieren selbst oder mit Ihrem Handwerker. Sobald die Geräte installiert sind, übernimmt SolenOS Einrichtung, Datenübertragung und laufenden Betrieb."
|
||||
visual={
|
||||
<AssetRender
|
||||
render={renders.shippingBoxMeters}
|
||||
@@ -308,24 +305,18 @@ export default function HauseigentuemerPage() {
|
||||
}
|
||||
action={
|
||||
<Button asChild size="lg">
|
||||
<Link to="/konfigurator?installation=0">Preis berechnen</Link>
|
||||
<Link to="/konfigurator?installation=0">Konfiguration starten</Link>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
<OptionCard
|
||||
title="Komplett installieren lassen"
|
||||
lead="Lehnen Sie sich zurück. SolenOS übernimmt Planung, Installation und Einrichtung – inklusive Service."
|
||||
takeaway={
|
||||
<>
|
||||
Ein Ansprechpartner. Alles aus einer Hand.
|
||||
<br />
|
||||
Komplettlösung mit voller Betreuung.
|
||||
</>
|
||||
}
|
||||
lead="SolenOS übernimmt Installation und Einrichtung – inklusive Service."
|
||||
takeaway="Komplettlösung mit voller Betreuung."
|
||||
visual={<FullServiceArt />}
|
||||
action={
|
||||
<Button asChild size="lg" variant="outline">
|
||||
<Link to="/konfigurator?installation=1">Preis berechnen</Link>
|
||||
<Link to="/konfigurator?installation=1">Konfiguration starten</Link>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -67,9 +67,9 @@ const rolloutSteps = [
|
||||
"Die Geräte werden passend zum jeweiligen Gebäude beziehungsweise zur jeweiligen Nutzungseinheit ausgeliefert.",
|
||||
},
|
||||
{
|
||||
title: "Bestehende Monteure installieren",
|
||||
title: "Vor Ort nur montieren",
|
||||
description:
|
||||
"Eigene Mitarbeiter, Hausmeister oder bestehende Installationspartner können die Montage übernehmen. Eine umfangreiche Softwarekonfiguration vor Ort ist nicht erforderlich.",
|
||||
"Eigene Mitarbeiter, Hausmeister oder bestehende Installationspartner montieren ausschließlich die Geräte. SolenOS übernimmt die Softwarekonfiguration.",
|
||||
},
|
||||
{
|
||||
title: "Bewohner einladen",
|
||||
@@ -79,7 +79,7 @@ const rolloutSteps = [
|
||||
]
|
||||
|
||||
const noEffortItems = [
|
||||
{ icon: <Ban />, title: "Keine aufwendige Gerätekonfiguration." },
|
||||
{ icon: <Ban />, title: "Keine Softwarekonfiguration vor Ort." },
|
||||
{ icon: <X />, title: "Keine manuelle Anlage jedes einzelnen Gerätes." },
|
||||
{
|
||||
icon: <Unlock />,
|
||||
@@ -135,7 +135,7 @@ const faqs: FaqItem[] = [
|
||||
{
|
||||
question: "Wie viel Aufwand entsteht für unser Team?",
|
||||
answer:
|
||||
"Die Gebäude- und Wohnungsdaten werden bei der Auftragserstellung einmal erfasst und anschließend weiterverwendet. Es entfällt die aufwendige Gerätekonfiguration und die manuelle Anlage jedes einzelnen Gerätes.",
|
||||
"Die Gebäude- und Wohnungsdaten werden bei der Auftragserstellung einmal erfasst und anschließend weiterverwendet. Vor Ort werden nur die Geräte montiert; SolenOS übernimmt die Softwarekonfiguration und Geräteanlage.",
|
||||
},
|
||||
{
|
||||
question: "Können unsere bestehenden Monteure installieren?",
|
||||
@@ -188,12 +188,12 @@ export default function HausverwaltungenPage() {
|
||||
<AudiencePage
|
||||
breadcrumb="Hausverwaltungen"
|
||||
title="Für Hausverwaltungen"
|
||||
tagline="Skalieren Sie Ihre Bestände einfach."
|
||||
lead="Rollout über viele Gebäude mit minimalem Aufwand – von der Planung bis zum laufenden Betrieb."
|
||||
tagline="Wachsende Bestände einfach betreuen."
|
||||
lead="Gebäude strukturiert ausrollen und vor Ort ausschließlich die Geräte montieren. SolenOS übernimmt die Softwarekonfiguration und den laufenden Betrieb."
|
||||
actions={
|
||||
<>
|
||||
<Button asChild size="lg">
|
||||
<Link to="/konfigurator">Portfolio kalkulieren</Link>
|
||||
<Link to="/konfigurator">Portfolio konfigurieren</Link>
|
||||
</Button>
|
||||
<Button asChild size="lg" variant="outline">
|
||||
<Link to="/kontakt">Rollout besprechen</Link>
|
||||
@@ -204,11 +204,12 @@ export default function HausverwaltungenPage() {
|
||||
features={[
|
||||
{
|
||||
icon: <Package />,
|
||||
title: "Vorkonfigurierte Hardware",
|
||||
title: "Zum Einbau vorkonfigurierte Messeinrichtungen",
|
||||
},
|
||||
{
|
||||
icon: <Timer />,
|
||||
title: "Wenig Aufwand vor Ort",
|
||||
title: "Vor Ort nur montieren",
|
||||
sub: "Keine Softwarekonfiguration vor Ort",
|
||||
},
|
||||
{
|
||||
icon: <LayoutDashboard />,
|
||||
@@ -216,7 +217,7 @@ export default function HausverwaltungenPage() {
|
||||
},
|
||||
{
|
||||
icon: <TrendingUp />,
|
||||
title: "Skalierbar für wachsende Portfolios",
|
||||
title: "Für wachsende Portfolios",
|
||||
},
|
||||
]}
|
||||
closing={
|
||||
@@ -224,11 +225,11 @@ export default function HausverwaltungenPage() {
|
||||
<CtaBanner
|
||||
icon={<Euro />}
|
||||
title="Wie sieht Ihr Portfolio aus?"
|
||||
description="Erhalten Sie zunächst mit wenigen Angaben eine Preisindikation für mehrere Gebäude – oder sprechen Sie mit uns über vorhandene Messtechnik und den geplanten Rollout."
|
||||
description="Erfassen Sie Gebäude und Leistungen online – oder sprechen Sie mit uns über vorhandene Messtechnik und den geplanten Rollout."
|
||||
actions={
|
||||
<>
|
||||
<Button asChild variant="inverse" size="lg">
|
||||
<Link to="/konfigurator">Portfolio kalkulieren</Link>
|
||||
<Link to="/konfigurator">Portfolio konfigurieren</Link>
|
||||
</Button>
|
||||
<Button asChild variant="inverse" size="lg">
|
||||
<Link to="/kontakt">Rollout besprechen</Link>
|
||||
@@ -242,7 +243,7 @@ export default function HausverwaltungenPage() {
|
||||
<Section className="pt-0 sm:pt-0 lg:pt-0">
|
||||
<SectionHeading
|
||||
align="center"
|
||||
eyebrow="Skalierung"
|
||||
eyebrow="Wachsende Bestände"
|
||||
title="Weniger Projektaufwand pro Gebäude"
|
||||
lead="Bei einem einzelnen Gebäude sind manuelle Arbeitsschritte überschaubar. Bei dutzenden Gebäuden werden sie zum Problem. SolenOS reduziert genau diese wiederkehrenden Aufgaben."
|
||||
/>
|
||||
|
||||
@@ -21,7 +21,7 @@ import { AssetRender, renders, vectors } from "@/components/solenos/site-assets"
|
||||
import { AudiencePage, AudienceClosing } from "@/pages/audiences/audience-page"
|
||||
|
||||
const KUNDEN_BEDARFE = [
|
||||
"UVI",
|
||||
"Monatliche Verbrauchsinformation (UVI)",
|
||||
"Heizkostenabrechnung",
|
||||
"fernauslesbare Messtechnik",
|
||||
"Rauchwarnmelder",
|
||||
@@ -42,7 +42,7 @@ const KEINE_HUERDEN = [
|
||||
},
|
||||
{
|
||||
icon: <Wrench />,
|
||||
title: "Keine komplizierte Softwareeinrichtung auf der Baustelle",
|
||||
title: "Keinerlei Softwarekonfiguration vor Ort",
|
||||
},
|
||||
]
|
||||
|
||||
@@ -81,7 +81,7 @@ const FAQS: FaqItem[] = [
|
||||
{
|
||||
question: "Muss ich vor Ort Software konfigurieren?",
|
||||
answer:
|
||||
"Nein. Auf der Baustelle bleibt im Wesentlichen die Montage. Eine komplizierte Softwareeinrichtung am Gebäude ist nicht vorgesehen.",
|
||||
"Nein. Vor Ort montieren Sie ausschließlich die vorgesehenen Geräte. Die gesamte Softwarekonfiguration übernimmt SolenOS.",
|
||||
},
|
||||
{
|
||||
question: "Bleibt der Kunde mein Kunde?",
|
||||
@@ -102,7 +102,7 @@ export default function InstallateurePage() {
|
||||
</>
|
||||
}
|
||||
tagline="Bestellen. Montieren. Fertig."
|
||||
lead="SolenOS für Ihre Kunden installieren – ohne Partnerprogramm, verpflichtende Zertifizierung oder aufwendige Softwarekonfiguration."
|
||||
lead="SolenOS für Ihre Kunden installieren – ohne Partnerprogramm, verpflichtende Zertifizierung oder jegliche Softwarekonfiguration vor Ort."
|
||||
actions={
|
||||
<Button asChild size="lg">
|
||||
<Link to="/konfigurator">Gebäude für meinen Kunden konfigurieren</Link>
|
||||
@@ -140,12 +140,12 @@ export default function InstallateurePage() {
|
||||
},
|
||||
{
|
||||
icon: <Package />,
|
||||
title: "Vorkonfigurierte Hardware",
|
||||
title: "Zum Einbau vorkonfigurierte Messeinrichtungen",
|
||||
},
|
||||
{
|
||||
icon: <Wrench />,
|
||||
title: "Einfache Installation",
|
||||
sub: "Keine Softwarekonfiguration",
|
||||
title: "Vor Ort nur montieren",
|
||||
sub: "Keinerlei Softwarekonfiguration vor Ort",
|
||||
},
|
||||
{
|
||||
icon: <Users />,
|
||||
@@ -156,7 +156,7 @@ export default function InstallateurePage() {
|
||||
closing={
|
||||
<AudienceClosing
|
||||
title="SolenOS bei einem Kunden einsetzen?"
|
||||
lead="Stellen Sie mit wenigen Angaben zunächst die ungefähre Ausstattung und den Preis für das Gebäude zusammen."
|
||||
lead="Erfassen Sie Leistungen und Gebäudedaten online. SolenOS bestimmt daraus die notwendige Ausstattung für das geprüfte Gesamtangebot."
|
||||
actions={
|
||||
<Button asChild size="lg">
|
||||
<Link to="/konfigurator">
|
||||
|
||||
@@ -28,10 +28,10 @@ const platformRequirements = [
|
||||
]
|
||||
|
||||
const whiteLabelItems = [
|
||||
"eigenes Branding",
|
||||
"Optionen für Ihr eigenes Logo im abgestimmten Umfang",
|
||||
"eigene Kundenbeziehung",
|
||||
"mandantenfähige Verwaltung",
|
||||
"Endkundenportale",
|
||||
"klar vereinbarte SolenOS- und Anbieterkennzeichnung",
|
||||
"APIs und Datenexporte",
|
||||
"Geräteverwaltung",
|
||||
"technischer Support",
|
||||
@@ -40,7 +40,7 @@ const whiteLabelItems = [
|
||||
const platformCapabilities = [
|
||||
{
|
||||
title: "Gerätekompatibilität",
|
||||
sub: "Einbindung unterschiedlicher Zähler- und Gerätetypen auf Basis geeigneter Standards.",
|
||||
sub: "OMS-kompatible Geräte verschiedener Hersteller einbinden.",
|
||||
},
|
||||
{
|
||||
title: "Gateway-Infrastruktur",
|
||||
@@ -63,8 +63,8 @@ const platformCapabilities = [
|
||||
sub: "Kunden und Bestände getrennt innerhalb einer gemeinsamen Plattform verwalten.",
|
||||
},
|
||||
{
|
||||
title: "White Label",
|
||||
sub: "SolenOS-Infrastruktur unter der Marke des Messdienstleisters einsetzen.",
|
||||
title: "Eigenmarken-Option",
|
||||
sub: "Logo und Kennzeichnung im gemeinsam festgelegten Umfang einsetzen.",
|
||||
},
|
||||
]
|
||||
|
||||
@@ -73,7 +73,7 @@ const businessComponents = [
|
||||
"Plattformgebühren",
|
||||
"Mengenstaffeln",
|
||||
"wiederkehrende Gebühren",
|
||||
"White-Label-Konditionen",
|
||||
"Konditionen für Eigenmarken-Optionen",
|
||||
"Support- und Servicelevel",
|
||||
"mögliche Mindestmengen",
|
||||
]
|
||||
@@ -82,9 +82,9 @@ const stackFlow = ["Ihre Kunden", "Ihr Messdienst", "SolenOS Plattform"]
|
||||
|
||||
const faqs: FaqItem[] = [
|
||||
{
|
||||
question: "Können wir SolenOS unter unserer eigenen Marke anbieten?",
|
||||
question: "Können wir SolenOS mit unserem eigenen Logo anbieten?",
|
||||
answer:
|
||||
"Ja. SolenOS ist als technische Grundlage für Dienstleistungen unter Ihrer Marke vorgesehen – mit eigenem Branding, mandantenfähiger Verwaltung und Endkundenportalen in Ihrem Auftritt.",
|
||||
"Optional kann SolenOS mit Ihrem eigenen Logo beziehungsweise unter Ihrer Eigenmarke eingesetzt werden. Für welche Oberflächen das gilt und wie SolenOS dort gekennzeichnet wird, legen wir vorab gemeinsam fest.",
|
||||
},
|
||||
{
|
||||
question: "Behalten wir die Kundenbeziehung?",
|
||||
@@ -104,7 +104,7 @@ const faqs: FaqItem[] = [
|
||||
{
|
||||
question: "Wie werden die Konditionen festgelegt?",
|
||||
answer:
|
||||
"Individuell beziehungsweise mengenabhängig – mit anderen Geschäftsmodellen, Mengenstaffeln und gegebenenfalls White-Label-Konditionen als im öffentlichen Preiskonfigurator. Die konkreten Konditionen werden nicht öffentlich dargestellt.",
|
||||
"Die Konditionen werden passend zu Leistungsumfang, Bestandsgröße, Support und vereinbarten Eigenmarken-Optionen gemeinsam festgelegt. Unbestätigte Tarife oder Mindestmengen werden nicht vorab zugesagt.",
|
||||
},
|
||||
]
|
||||
|
||||
@@ -138,7 +138,7 @@ export default function MessdienstleisterPage() {
|
||||
breadcrumb="Messdienstleister"
|
||||
title="Für Messdienstleister"
|
||||
tagline="Ihre Services. Unsere Plattform."
|
||||
lead="Nutzen Sie SolenOS als technische Grundlage für Ihren eigenen Messdienst – skalierbar und zuverlässig."
|
||||
lead="Nutzen Sie SolenOS als technische Grundlage für Ihren eigenen Messdienst – für kleine Bestände und große Wohnungsportfolios."
|
||||
actions={
|
||||
<>
|
||||
<Button asChild size="lg">
|
||||
@@ -153,8 +153,8 @@ export default function MessdienstleisterPage() {
|
||||
features={[
|
||||
{
|
||||
icon: <Tag />,
|
||||
title: "White Label",
|
||||
sub: "Ihr Branding, Ihre Kunden",
|
||||
title: "Optional mit Ihrem eigenen Logo",
|
||||
sub: "Unter Ihrer Eigenmarke im vereinbarten Umfang",
|
||||
},
|
||||
{
|
||||
icon: <Code2 />,
|
||||
@@ -163,8 +163,8 @@ export default function MessdienstleisterPage() {
|
||||
},
|
||||
{
|
||||
icon: <Layers />,
|
||||
title: "Skalierbare Plattform",
|
||||
sub: "Für jedes Geschäftsmodell",
|
||||
title: "Für wachsende Bestände",
|
||||
sub: "Von kleinen Beständen bis zu großen Wohnungsportfolios",
|
||||
},
|
||||
{
|
||||
icon: <ShieldCheck />,
|
||||
@@ -233,8 +233,8 @@ export default function MessdienstleisterPage() {
|
||||
<Section className="pt-0 sm:pt-0 lg:pt-0">
|
||||
<SectionHeading
|
||||
eyebrow="Ihre Marke"
|
||||
title="White Label"
|
||||
lead="SolenOS kann als technische Grundlage für Dienstleistungen unter Ihrer eigenen Marke eingesetzt werden. Je nach Geschäftsmodell können unter anderem relevant sein:"
|
||||
title="Unter Ihrer Eigenmarke (White Label)"
|
||||
lead="SolenOS kann optional mit Ihrem eigenen Logo eingesetzt werden. Welche Oberflächen die Eigenmarke tragen und wie SolenOS gekennzeichnet wird, vereinbaren wir vorab verbindlich."
|
||||
/>
|
||||
<div className="mt-8 grid max-w-3xl gap-x-10 gap-y-2.5 sm:grid-cols-2">
|
||||
<Checklist items={whiteLabelItems.slice(0, 4)} />
|
||||
@@ -267,8 +267,8 @@ export default function MessdienstleisterPage() {
|
||||
<SectionHeading
|
||||
align="center"
|
||||
eyebrow="Konditionen"
|
||||
title="Das Geschäftsmodell muss funktionieren"
|
||||
lead="Eine Plattform für Messdienstleister ist nur interessant, wenn auch der wirtschaftliche Rahmen stimmt. Deshalb werden kommerzielle Konditionen individuell beziehungsweise mengenabhängig vereinbart – mit anderen Geschäftsmodellen, Mengenstaffeln und gegebenenfalls White-Label-Konditionen als im öffentlichen Preiskonfigurator."
|
||||
title="Konditionen passend zum vereinbarten Umfang"
|
||||
lead="Leistungsumfang, Bestandsgröße, Support und Eigenmarken-Optionen bestimmen den wirtschaftlichen Rahmen. Die konkreten Konditionen werden gemeinsam festgelegt; die Website macht dazu keine unbestätigten Zusagen."
|
||||
/>
|
||||
<div className="mx-auto mt-8 max-w-2xl text-center">
|
||||
<p className="text-xs font-bold text-muted-foreground">
|
||||
@@ -291,8 +291,8 @@ export default function MessdienstleisterPage() {
|
||||
<Section className="pt-0 sm:pt-0 lg:pt-0">
|
||||
<SectionHeading
|
||||
align="center"
|
||||
title="Gemeinsam skalieren"
|
||||
lead="SolenOS soll insbesondere Messdienstleistern ermöglichen, neue digitale Dienstleistungen anzubieten, ohne dafür eine vollständige eigene Hardware- und Softwareentwicklung aufbauen zu müssen. Der Messdienstleister behält dabei seine Kundenbeziehung und sein eigenes Geschäftsmodell."
|
||||
title="Mit Ihren Beständen wachsen"
|
||||
lead="SolenOS unterstützt kleine Bestände ebenso wie große Wohnungsportfolios. Messdienstleister können neue digitale Dienstleistungen anbieten, ohne dafür eine vollständige eigene Hardware- und Softwareentwicklung aufbauen zu müssen; die Kundenbeziehung bleibt bei ihnen."
|
||||
/>
|
||||
</Section>
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import * as React from "react"
|
||||
import { useSearchParams } from "react-router-dom"
|
||||
import { Link, useSearchParams } from "react-router-dom"
|
||||
import { Ban, Check, CircleCheck, Euro, Plus, X } from "lucide-react"
|
||||
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Card } from "@/components/ui/card"
|
||||
import { Checkbox } from "@/components/ui/checkbox"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||||
@@ -50,15 +49,14 @@ const INITIAL_BUILDING: Building = {
|
||||
zimmer: 3,
|
||||
}
|
||||
|
||||
/** Grundpreise je Wohnung / Monat – Selbstmontage, wie in der Klarpreis-Liste. */
|
||||
/** Grundpreise je Wohnung / Monat – wie in der Klarpreis-Liste. */
|
||||
const UVI_MONTHLY = 10.5
|
||||
const INSPECTION_MONTHLY = 2.2
|
||||
/** Aufschlag je Monatsposition, wenn SolenOS montiert – Platzhalter bis zum finalen Preismodell. */
|
||||
const INSTALL_MONTHLY_SURCHARGE = 2
|
||||
/** RWM-Hardware je Wohnung einmalig, inklusive Montage – wie in der Klarpreis-Liste. */
|
||||
const RWM_ONE_TIME_INSTALLED = 42
|
||||
/** Selbstmontage durch Kunde oder Fachbetrieb – Platzhalter bis zum finalen Preismodell. */
|
||||
const RWM_ONE_TIME_SELF = 30
|
||||
/** RWM-Hardware je Wohnung einmalig – ohne Montage, die eine eigene Position ist. */
|
||||
const RWM_ONE_TIME = 30
|
||||
/** Montage durch SolenOS: je neuem Melder und je Wohnung mit Messtechnik. */
|
||||
const INSTALL_PER_RWM = 10
|
||||
const INSTALL_PER_UNIT = 10
|
||||
|
||||
function formatEuro(value: number) {
|
||||
return value.toLocaleString("de-DE", {
|
||||
@@ -90,13 +88,14 @@ function settle(value: number | "", min: number) {
|
||||
/**
|
||||
* Deep-link preset. Pages elsewhere on the site link into the configurator with
|
||||
* parts of the form already answered, e.g. `/konfigurator?installation=0` for
|
||||
* the self-install route. Supported params: `installation`, `uvi`, `rwm`,
|
||||
* `adresse`, `heizung`, `wohnungen`, `zimmer`. Missing or unreadable values
|
||||
* keep the page defaults; numbers below the field minimum settle at it, just
|
||||
* as they do when typed into the form.
|
||||
* the self-install route. Supported params: `installation`, `uvi`,
|
||||
* `abrechnung`, `rwm`, `adresse`, `heizung`, `wohnungen`, `zimmer`. Missing or
|
||||
* unreadable values keep the page defaults; numbers below the field minimum
|
||||
* settle at it, just as they do when typed into the form.
|
||||
*/
|
||||
type Preset = {
|
||||
uvi?: boolean
|
||||
billing?: boolean
|
||||
rwm?: boolean
|
||||
install?: boolean
|
||||
/** Seeds the single building the configurator starts with. */
|
||||
@@ -149,6 +148,7 @@ function readPreset(params: URLSearchParams): Preset {
|
||||
|
||||
return {
|
||||
uvi: presetFlag(params.get("uvi")),
|
||||
billing: presetFlag(params.get("abrechnung")),
|
||||
rwm: presetFlag(params.get("rwm")),
|
||||
install: presetFlag(params.get("installation")),
|
||||
building,
|
||||
@@ -182,14 +182,17 @@ function StepCard({
|
||||
}
|
||||
|
||||
/**
|
||||
* Selectable service tile (step 1) — the active option carries a brand border.
|
||||
* Selectable service tile (step 1) — the whole tile is the toggle, the switch
|
||||
* mirrors the state. The active option carries a brand border.
|
||||
*/
|
||||
function ServiceOption({
|
||||
id,
|
||||
checked,
|
||||
onCheckedChange,
|
||||
title,
|
||||
description,
|
||||
}: {
|
||||
id: string
|
||||
checked: boolean
|
||||
onCheckedChange: (checked: boolean) => void
|
||||
title: string
|
||||
@@ -198,21 +201,44 @@ function ServiceOption({
|
||||
return (
|
||||
<label
|
||||
className={cn(
|
||||
"flex cursor-pointer items-start gap-3 rounded-xl border p-4 transition-colors",
|
||||
"flex cursor-pointer items-start justify-between gap-4 rounded-xl border p-4 transition-colors",
|
||||
checked
|
||||
? "border-primary bg-brand-50/60 shadow-pill"
|
||||
: "border-border bg-card hover:border-brand-200 hover:bg-brand-50/40"
|
||||
)}
|
||||
>
|
||||
<Checkbox
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<span
|
||||
id={`${id}-title`}
|
||||
className="text-sm font-bold leading-snug text-navy"
|
||||
>
|
||||
{title}
|
||||
</span>
|
||||
<Badge
|
||||
id={`${id}-state`}
|
||||
variant={checked ? "default" : "muted"}
|
||||
aria-live="polite"
|
||||
className="shrink-0"
|
||||
>
|
||||
{checked ? "Enthalten · abwählbar" : "Hinzufügen"}
|
||||
</Badge>
|
||||
</div>
|
||||
<p
|
||||
id={`${id}-description`}
|
||||
className="mt-1 text-sm leading-relaxed text-muted-foreground"
|
||||
>
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
id={id}
|
||||
checked={checked}
|
||||
onCheckedChange={(v) => onCheckedChange(v === true)}
|
||||
onCheckedChange={onCheckedChange}
|
||||
aria-labelledby={`${id}-title`}
|
||||
aria-describedby={`${id}-description ${id}-state`}
|
||||
className="mt-0.5"
|
||||
/>
|
||||
<span>
|
||||
<span className="block text-sm font-bold text-navy">{title}</span>
|
||||
<span className="block text-sm text-muted-foreground">{description}</span>
|
||||
</span>
|
||||
</label>
|
||||
)
|
||||
}
|
||||
@@ -282,23 +308,28 @@ function PackageCard({
|
||||
* position can be passed on to tenants (umlagefähig). Wording follows the
|
||||
* Klarpreis price list.
|
||||
*/
|
||||
type Position = {
|
||||
label: string
|
||||
amount: number
|
||||
unit: string
|
||||
note?: string
|
||||
allocatable: boolean
|
||||
/** A deselected position stays on the card as a faint zero. */
|
||||
active: boolean
|
||||
}
|
||||
|
||||
function PriceRow({
|
||||
label,
|
||||
amount,
|
||||
unit,
|
||||
note,
|
||||
allocatable,
|
||||
}: {
|
||||
label: string
|
||||
amount: number
|
||||
unit: string
|
||||
note?: string
|
||||
allocatable: boolean
|
||||
}) {
|
||||
active,
|
||||
}: Position) {
|
||||
const shown = useAnimatedNumber(amount)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={cn("transition-opacity", !active && "opacity-45")}>
|
||||
<p className="text-sm font-bold text-navy">{label}</p>
|
||||
<p className="mt-1 text-3xl font-extrabold tracking-tight text-navy tabular-nums">
|
||||
ca. {formatEuro(shown)}
|
||||
@@ -321,6 +352,7 @@ export default function ConfiguratorPage() {
|
||||
const preset = React.useMemo(() => readPreset(searchParams), [searchParams])
|
||||
|
||||
const [uvi, setUvi] = React.useState(preset.uvi ?? true)
|
||||
const [billing, setBilling] = React.useState(preset.billing ?? true)
|
||||
const [rwm, setRwm] = React.useState(preset.rwm ?? true)
|
||||
const [buildings, setBuildings] = React.useState<Building[]>(() => [
|
||||
{ ...INITIAL_BUILDING, ...preset.building },
|
||||
@@ -338,6 +370,7 @@ export default function ConfiguratorPage() {
|
||||
if (appliedPreset.current === preset) return
|
||||
appliedPreset.current = preset
|
||||
setUvi(preset.uvi ?? true)
|
||||
setBilling(preset.billing ?? true)
|
||||
setRwm(preset.rwm ?? true)
|
||||
setInstall(preset.install ?? true)
|
||||
setBuildings([{ ...INITIAL_BUILDING, ...preset.building }])
|
||||
@@ -360,15 +393,77 @@ export default function ConfiguratorPage() {
|
||||
}
|
||||
|
||||
const totalUnits = buildings.reduce((sum, b) => sum + (b.wohnungen || 0), 0)
|
||||
const installSurcharge = install ? INSTALL_MONTHLY_SURCHARGE : 0
|
||||
const uviMonthly = UVI_MONTHLY + installSurcharge
|
||||
const inspectionMonthly = INSPECTION_MONTHLY + installSurcharge
|
||||
const installNote = install
|
||||
? `inklusive ${formatEuro(INSTALL_MONTHLY_SURCHARGE)}\u00A0€ Installationsanteil`
|
||||
: undefined
|
||||
const rwmRatePerUnit = install ? RWM_ONE_TIME_INSTALLED : RWM_ONE_TIME_SELF
|
||||
/* RWM hardware is billed once per Wohnung – the estimate is the sum. */
|
||||
const rwmOneTimeTotal = rwm ? rwmRatePerUnit * totalUnits : 0
|
||||
const unitWord = totalUnits === 1 ? "Wohnung" : "Wohnungen"
|
||||
/*
|
||||
* Melder je Wohnung: einer je Zimmer plus einer im Flur als Rettungsweg
|
||||
* (DIN 14676). Die Hardware wird je Wohnung abgerechnet, die Montage je
|
||||
* Gerät; die endgültige Anzahl ergibt sich aus der Detailkonfiguration.
|
||||
*/
|
||||
const rwmDevices = rwm
|
||||
? Math.round(
|
||||
buildings.reduce(
|
||||
(sum, b) => sum + (b.wohnungen || 0) * ((b.zimmer || 0) + 1),
|
||||
0
|
||||
)
|
||||
)
|
||||
: 0
|
||||
/* UVI und Abrechnung teilen sich die Messtechnik – sie wird einmal montiert. */
|
||||
const meteringUnits = uvi || billing ? totalUnits : 0
|
||||
const installTotal =
|
||||
rwmDevices * INSTALL_PER_RWM + meteringUnits * INSTALL_PER_UNIT
|
||||
|
||||
const installNotes: string[] = []
|
||||
if (install && rwmDevices > 0) {
|
||||
installNotes.push(
|
||||
`${rwmDevices} Rauchwarnmelder × ${formatEuro(INSTALL_PER_RWM)}\u00A0€`
|
||||
)
|
||||
}
|
||||
if (install && meteringUnits > 0) {
|
||||
installNotes.push(
|
||||
`Messtechnik in ${meteringUnits} ${unitWord} × ${formatEuro(INSTALL_PER_UNIT)}\u00A0€`
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
* Every position stays on the card. A deselected one counts down to a faint
|
||||
* zero, so a toggle reads as a change in the price instead of a row that
|
||||
* vanishes.
|
||||
*/
|
||||
const positions: Position[] = [
|
||||
{
|
||||
label: "UVI-Komplettbetrieb",
|
||||
amount: uvi ? UVI_MONTHLY : 0,
|
||||
unit: "je Wohnung / Monat",
|
||||
allocatable: true,
|
||||
active: uvi,
|
||||
},
|
||||
{
|
||||
label: "Ferninspektion Rauchwarnmelder",
|
||||
amount: rwm ? INSPECTION_MONTHLY : 0,
|
||||
unit: "je Wohnung / Monat",
|
||||
allocatable: true,
|
||||
active: rwm,
|
||||
},
|
||||
{
|
||||
label: "Rauchwarnmelder-Geräte",
|
||||
/* Hardware is billed once per Wohnung – the estimate is the sum. */
|
||||
amount: rwm ? RWM_ONE_TIME * totalUnits : 0,
|
||||
unit: "einmalig gesamt",
|
||||
note: rwm
|
||||
? `${totalUnits} ${unitWord} × ${formatEuro(RWM_ONE_TIME)}\u00A0€`
|
||||
: undefined,
|
||||
allocatable: false,
|
||||
active: rwm,
|
||||
},
|
||||
{
|
||||
label: "Montage durch SolenOS",
|
||||
amount: install ? installTotal : 0,
|
||||
unit: "einmalig gesamt",
|
||||
note: installNotes.length > 0 ? installNotes.join(" · ") : undefined,
|
||||
allocatable: false,
|
||||
active: install && installTotal > 0,
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<Container>
|
||||
@@ -383,7 +478,7 @@ export default function ConfiguratorPage() {
|
||||
/>
|
||||
<SectionHeading
|
||||
title="Konfigurator"
|
||||
lead="In 3 Schritten zur Preisindikation."
|
||||
lead="Leistungen auswählen, Gebäudedaten erfassen und sofort eine Preisindikation erhalten."
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -393,50 +488,69 @@ export default function ConfiguratorPage() {
|
||||
<StepCard step={1} title="Leistungen wählen">
|
||||
<div className="flex flex-col gap-3">
|
||||
<ServiceOption
|
||||
id="service-uvi"
|
||||
checked={uvi}
|
||||
onCheckedChange={setUvi}
|
||||
title="UVI"
|
||||
description="Unterjährige Verbrauchsinformation inklusive Messtechnik"
|
||||
title="Monatliche Verbrauchsinformation (UVI)"
|
||||
description="Monatliche Verbrauchswerte und Vergleiche für jede Wohnung einschließlich der benötigten Messtechnik."
|
||||
/>
|
||||
<ServiceOption
|
||||
id="service-billing"
|
||||
checked={billing}
|
||||
onCheckedChange={setBilling}
|
||||
title="Heizkostenabrechnung"
|
||||
description="Jährliche Heizkostenabrechnung einschließlich der gesetzlich vorgeschriebenen Pflichtangaben und Dokumente."
|
||||
/>
|
||||
<ServiceOption
|
||||
id="service-smoke-alarms"
|
||||
checked={rwm}
|
||||
onCheckedChange={setRwm}
|
||||
title="Rauchwarnmelder"
|
||||
description="Rauchwarnmelder inklusive digitaler Dienstleistungen"
|
||||
description="Rauchwarnmelder mit Ferninspektion, Geräteverwaltung sowie Prüf- und Statusdokumentation."
|
||||
/>
|
||||
</div>
|
||||
<Separator className="my-6" />
|
||||
<div
|
||||
<label
|
||||
className={cn(
|
||||
"flex items-start justify-between gap-4 rounded-xl border p-4 transition-colors",
|
||||
"flex cursor-pointer items-start justify-between gap-4 rounded-xl border p-4 transition-colors",
|
||||
install
|
||||
? "border-primary bg-brand-50/60 shadow-pill"
|
||||
: "border-border bg-card"
|
||||
: "border-border bg-card hover:border-brand-200 hover:bg-brand-50/40"
|
||||
)}
|
||||
>
|
||||
<div className="min-w-0">
|
||||
<Label
|
||||
htmlFor="installation"
|
||||
className="cursor-pointer text-sm font-bold text-navy"
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<span
|
||||
id="installation-title"
|
||||
className="text-sm font-bold text-navy"
|
||||
>
|
||||
Montage durch SolenOS
|
||||
</span>
|
||||
<Badge variant={install ? "default" : "muted"}>
|
||||
{install ? "SolenOS montiert" : "Selbstmontage"}
|
||||
</Badge>
|
||||
</div>
|
||||
<p
|
||||
id="installation-description"
|
||||
className="mt-1 text-sm text-muted-foreground"
|
||||
>
|
||||
Installation durch SolenOS
|
||||
</Label>
|
||||
<p className="mt-1 text-sm text-muted-foreground">
|
||||
{install
|
||||
? "SolenOS organisiert die Montage – Geräte- und Monatspreise enthalten die Installation."
|
||||
: "Sie selbst, Ihr Hausmeister oder Ihr Fachbetrieb montiert die Geräte."}
|
||||
? "SolenOS übernimmt Montage und Softwarekonfiguration – die Montage erscheint als eigene Position."
|
||||
: "Sie, Ihr Hausmeister oder Ihr Fachbetrieb montieren. Eine Softwarekonfiguration vor Ort ist nicht erforderlich."}
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
id="installation"
|
||||
checked={install}
|
||||
onCheckedChange={setInstall}
|
||||
aria-labelledby="installation-title"
|
||||
aria-describedby="installation-description"
|
||||
className="mt-0.5"
|
||||
/>
|
||||
</div>
|
||||
</label>
|
||||
</StepCard>
|
||||
|
||||
<StepCard step={2} title="Gebäude angeben">
|
||||
<StepCard step={2} title="Gebäudedaten online erfassen">
|
||||
<div className="flex flex-col gap-5">
|
||||
{buildings.map((b, i) => (
|
||||
<div
|
||||
@@ -549,10 +663,37 @@ export default function ConfiguratorPage() {
|
||||
</div>
|
||||
</StepCard>
|
||||
|
||||
<StepCard step={3} title="Konfiguration speichern">
|
||||
<StepCard step={3} title="Persönlichen Link anfordern">
|
||||
<div className="rounded-xl border border-brand-200 bg-brand-50/60 p-4">
|
||||
<p className="text-sm font-bold text-navy">
|
||||
So geht es nach der E-Mail weiter
|
||||
</p>
|
||||
<ol className="mt-3 list-decimal space-y-2 pl-5 text-sm leading-relaxed text-muted-foreground">
|
||||
<li>
|
||||
Wir speichern Ihre bisherige Auswahl und senden Ihnen einen
|
||||
persönlichen Link.
|
||||
</li>
|
||||
<li>
|
||||
Über den Link ergänzen Sie die Gebäudedetails und laden im
|
||||
Portal Fotos vorhandener wasserführender Einbausituationen
|
||||
hoch. Fotos ersetzen Maße und Typangaben, soweit sie eine
|
||||
eindeutige Prüfung ermöglichen.
|
||||
</li>
|
||||
<li>
|
||||
SolenOS prüft die Angaben und Fotos manuell, bestimmt die
|
||||
endgültige Ausstattung und erstellt anschließend den genauen
|
||||
Gesamtpreis beziehungsweise ein verbindliches Angebot.
|
||||
</li>
|
||||
</ol>
|
||||
<p className="mt-3 text-xs leading-relaxed text-muted-foreground">
|
||||
Beispiel für spätere Detailfragen: Kinderzimmer und regelmäßig
|
||||
genutzte Gästezimmer zählen als Schlafräume; ein dauerhaftes
|
||||
Büro nicht.
|
||||
</p>
|
||||
</div>
|
||||
<form
|
||||
onSubmit={(e) => e.preventDefault()}
|
||||
className="flex flex-col gap-3"
|
||||
onSubmit={(event) => event.preventDefault()}
|
||||
className="mt-5 flex flex-col gap-3"
|
||||
>
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<Label htmlFor="config-email">E-Mail-Adresse</Label>
|
||||
@@ -561,18 +702,28 @@ export default function ConfiguratorPage() {
|
||||
type="email"
|
||||
placeholder="name@unternehmen.de"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
onChange={(event) => setEmail(event.target.value)}
|
||||
aria-describedby="config-email-privacy"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<Button type="submit" className="self-start">
|
||||
Konfiguration speichern & fortsetzen
|
||||
</Button>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Sie erhalten einen persönlichen Link
|
||||
zu Ihrer Konfiguration. Damit kannst du
|
||||
sofort weitermachen, später zurückkehren
|
||||
oder den Link intern weitergeben.
|
||||
<p
|
||||
id="config-email-privacy"
|
||||
className="text-xs leading-relaxed text-muted-foreground"
|
||||
>
|
||||
Wir verwenden Ihre E-Mail-Adresse, um den persönlichen Link
|
||||
zu versenden. Einzelheiten finden Sie in unseren{" "}
|
||||
<Link
|
||||
to="/wissen/datenschutz-sicherheit"
|
||||
className="font-semibold text-primary underline underline-offset-2"
|
||||
>
|
||||
Hinweisen zu Datenschutz & Sicherheit
|
||||
</Link>
|
||||
.
|
||||
</p>
|
||||
<Button type="submit" className="self-start">
|
||||
Persönlichen Link anfordern
|
||||
</Button>
|
||||
</form>
|
||||
</StepCard>
|
||||
</div>
|
||||
@@ -589,74 +740,61 @@ export default function ConfiguratorPage() {
|
||||
</IconBadge>
|
||||
</div>
|
||||
<div className="p-6 sm:p-7">
|
||||
{uvi || rwm ? (
|
||||
<div className="flex flex-col gap-5">
|
||||
{uvi ? (
|
||||
<PriceRow
|
||||
label="UVI-Komplettbetrieb"
|
||||
amount={uviMonthly}
|
||||
unit="je Wohnung / Monat"
|
||||
note={installNote}
|
||||
allocatable
|
||||
/>
|
||||
) : null}
|
||||
{rwm ? (
|
||||
<>
|
||||
{uvi ? <Separator /> : null}
|
||||
<PriceRow
|
||||
label="Ferninspektion Rauchwarnmelder"
|
||||
amount={inspectionMonthly}
|
||||
unit="je Wohnung / Monat"
|
||||
note={installNote}
|
||||
allocatable
|
||||
/>
|
||||
<Separator />
|
||||
<PriceRow
|
||||
label="Rauchwarnmelder-Geräte"
|
||||
amount={rwmOneTimeTotal}
|
||||
unit="einmalig gesamt"
|
||||
note={`${totalUnits} ${totalUnits === 1 ? "Wohnung" : "Wohnungen"} × ${formatEuro(rwmRatePerUnit)}\u00A0€ · ${install ? "inklusive Montage" : "Selbstmontage"}`}
|
||||
allocatable={false}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
<p className="text-sm font-bold text-navy">
|
||||
{buildings.length} Gebäude · {totalUnits} {unitWord}
|
||||
</p>
|
||||
<Separator className="my-5" />
|
||||
<div className="flex flex-col gap-5" aria-live="polite">
|
||||
{positions.map((position, index) => (
|
||||
<React.Fragment key={position.label}>
|
||||
{index > 0 ? <Separator /> : null}
|
||||
<PriceRow {...position} />
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Wählen Sie in Schritt 1 mindestens eine Leistung, um eine
|
||||
Preisindikation zu erhalten.
|
||||
<div className="mt-6 space-y-2 text-xs leading-relaxed text-muted-foreground">
|
||||
{billing ? (
|
||||
<p>
|
||||
Die Heizkostenabrechnung wird mit dem verbindlichen
|
||||
Angebot bepreist.
|
||||
</p>
|
||||
)}
|
||||
<p className="mt-6 text-xs leading-relaxed text-muted-foreground">
|
||||
{install
|
||||
? "Preise inklusive Montage durch SolenOS. "
|
||||
: "Preise ohne Montage – Installation durch Sie oder Ihren Fachbetrieb. "}
|
||||
Die erste Berechnung ist eine unverbindliche Preisindikation.
|
||||
Der genaue Preis ergibt sich aus der vollständigen
|
||||
Objektkonfiguration.
|
||||
) : null}
|
||||
<p>
|
||||
Die erste Berechnung ist eine unverbindliche
|
||||
Preisindikation. Der genaue Preis ergibt sich aus der
|
||||
vollständigen Objektkonfiguration.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
{/* Was ist in der Schätzung enthalten? */}
|
||||
{/* Was ist in dem Preis enthalten? */}
|
||||
<Section className="pt-0 sm:pt-0 lg:pt-0">
|
||||
<SectionHeading
|
||||
title="Was ist in dem Preis enthalten?"
|
||||
/>
|
||||
<div className="mt-8 grid gap-6 lg:grid-cols-2">
|
||||
<SectionHeading title="Was ist in dem Preis enthalten?" />
|
||||
<div className="mt-8 grid gap-6 lg:grid-cols-3">
|
||||
<PackageCard
|
||||
render={renders.gateway}
|
||||
title="UVI"
|
||||
title="Monatliche Verbrauchsinformation (UVI)"
|
||||
included={uvi}
|
||||
items={[
|
||||
"geschätzte benötigte Messtechnik",
|
||||
"SolenOS Plattform",
|
||||
"Datenerfassung",
|
||||
"Unterjährige Verbrauchsinformation",
|
||||
"laufender digitaler Betrieb",
|
||||
"von SolenOS ermittelte notwendige Messtechnik",
|
||||
"erforderliche Gateway- und Kommunikationsinfrastruktur",
|
||||
"SolenOS Plattform, Datenerfassung und laufender digitaler Betrieb",
|
||||
"monatliche Verbrauchswerte und Vergleiche für jede Wohnung",
|
||||
]}
|
||||
/>
|
||||
<PackageCard
|
||||
render={renders.glassMoney}
|
||||
title="Heizkostenabrechnung"
|
||||
included={billing}
|
||||
items={[
|
||||
"jährliche Heizkostenabrechnung im Online-Portal",
|
||||
"Verteilung nach den Vorgaben der HeizkostenV",
|
||||
"Berücksichtigung von Nutzerwechseln und Leerständen",
|
||||
"Pflichtangaben nach § 6a Absatz 3 HeizkostenV",
|
||||
]}
|
||||
/>
|
||||
<PackageCard
|
||||
@@ -664,12 +802,12 @@ export default function ConfiguratorPage() {
|
||||
title="Rauchwarnmelder"
|
||||
included={rwm}
|
||||
items={[
|
||||
"geschätzte Anzahl Rauchwarnmelder",
|
||||
"Verwaltung der Geräte",
|
||||
"gebuchte digitale Dienstleistungen",
|
||||
"von SolenOS ermittelte Anzahl Rauchwarnmelder",
|
||||
"Verwaltung und Ferninspektion der Geräte",
|
||||
"Prüf- und Statusdokumentation",
|
||||
install
|
||||
? "Montage und Eigentumsübertragung"
|
||||
: "Eigentumsübertragung – Montage durch Sie",
|
||||
? "Montage durch SolenOS als eigene Position"
|
||||
: "Montage durch Sie oder Ihren Fachbetrieb",
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -62,11 +62,11 @@ const AUDIENCES: Record<
|
||||
tab: "Hausverwaltungen",
|
||||
tabIcon: <Building2 />,
|
||||
headline: "Viele Gebäude. Ein einfacher Rollout.",
|
||||
text: "Erfassen Sie Ihre Objekte einmal, erhalten Sie vorkonfigurierte Hardware und nutzen Sie bestehende Mitarbeiter oder Installationspartner für die Montage.",
|
||||
text: "Erfassen Sie Ihre Objekte einmal, erhalten Sie vorkonfigurierte Messeinrichtungen und nutzen Sie bestehende Mitarbeiter oder Installationspartner ausschließlich für die Montage.",
|
||||
bullets: [
|
||||
"standardisierter Rollout",
|
||||
"vorkonfigurierte Geräte",
|
||||
"wenig Softwarearbeit vor Ort",
|
||||
"keine Softwarekonfiguration vor Ort",
|
||||
"zentrale Portfolioverwaltung",
|
||||
"geringer administrativer Aufwand",
|
||||
"schnelle Erweiterung um weitere Gebäude",
|
||||
@@ -79,14 +79,14 @@ const AUDIENCES: Record<
|
||||
tab: "Messdienstleister",
|
||||
tabIcon: <LineChart />,
|
||||
headline: "Ihre Messdienstleistung. Unsere Infrastruktur.",
|
||||
text: "Nutzen Sie SolenOS als technische Grundlage für Ihre eigenen Dienstleistungen – mit Hardware, Plattform, Gerätemanagement und optionalem White Label.",
|
||||
text: "Nutzen Sie SolenOS als technische Grundlage für Ihre eigenen Dienstleistungen – mit Hardware, Plattform, Gerätemanagement und optional mit Ihrem eigenen Logo (White Label).",
|
||||
bullets: [
|
||||
"technische Plattform",
|
||||
"Gerätekompatibilität",
|
||||
"Skalierbarkeit",
|
||||
"OMS-kompatible Geräte verschiedener Hersteller",
|
||||
"für kleine Bestände und große Wohnungsportfolios",
|
||||
"APIs und Integrationen",
|
||||
"White Label",
|
||||
"individuelles Geschäftsmodell",
|
||||
"Optionen für eigenes Logo und Eigenmarke",
|
||||
"individuell vereinbarte Konditionen",
|
||||
],
|
||||
cta: "SolenOS für Messdienstleister",
|
||||
href: "/fuer-wen/messdienstleister",
|
||||
@@ -100,8 +100,8 @@ const AUDIENCES: Record<
|
||||
bullets: [
|
||||
"kein verpflichtender Partnerstatus",
|
||||
"keine Mindestabnahme",
|
||||
"vorkonfigurierte Hardware",
|
||||
"keine aufwendige Softwarekonfiguration",
|
||||
"zum Einbau vorkonfigurierte Messeinrichtungen",
|
||||
"keinerlei Softwarekonfiguration vor Ort",
|
||||
"bestehende Kundenbeziehung bleibt erhalten",
|
||||
],
|
||||
cta: "SolenOS für Installateure",
|
||||
|
||||
@@ -104,11 +104,12 @@ const operationsScope: ExpandingCard[] = [
|
||||
/>
|
||||
),
|
||||
title: "Heizkostenabrechnung",
|
||||
text: "Die erfassten Verbrauchsdaten bilden die Grundlage für die jährliche Heizkostenabrechnung.",
|
||||
text: "Aus den erfassten Verbrauchsdaten wird die jährliche Heizkostenabrechnung im Online-Portal erstellt und bereitgestellt.",
|
||||
points: [
|
||||
"Verteilung der Wärme- und Warmwasserkosten nach HeizkostenV",
|
||||
"Berücksichtigung von Nutzerwechseln und Leerständen",
|
||||
"Einzelabrechnung je Wohnung mit den Pflichtangaben nach § 6a Absatz 3",
|
||||
"versandfertige Einzelabrechnung je Wohnung im Online-Portal",
|
||||
"Pflichtangaben nach § 6a Absatz 3 HeizkostenV",
|
||||
],
|
||||
to: "/produkte/heizkostenabrechnung",
|
||||
},
|
||||
@@ -171,7 +172,7 @@ const operationsScope: ExpandingCard[] = [
|
||||
title: "Gateway und Datenübertragung",
|
||||
text: "Die Messdaten werden zentral gesammelt und an SolenOS übertragen.",
|
||||
points: [
|
||||
"ein Gateway je Gebäude empfängt die Funkpakete aller angebundenen Geräte",
|
||||
"die erforderliche Gateway-Infrastruktur wird passend zum Objekt bestimmt",
|
||||
"Übertragung per Mobilfunk, ohne Internetanschluss im Gebäude",
|
||||
"TLS-verschlüsselte Übertragung an die Plattform",
|
||||
],
|
||||
@@ -191,11 +192,11 @@ const operationsScope: ExpandingCard[] = [
|
||||
/>
|
||||
),
|
||||
title: "Portale und Verwaltung",
|
||||
text: "Gebäude, Wohnungen, Geräte und Verbrauchsdaten werden zentral verwaltet. Bewohner erhalten Zugriff auf die für sie vorgesehenen Informationen.",
|
||||
text: "Eigentümer betreuen Gebäude, Wohnungen, Geräte und Verbrauchsdaten zentral. Bewohner haben ihre persönliche Übersicht im Mieterportal.",
|
||||
points: [
|
||||
"Portalzugang für Eigentümer und Verwaltung",
|
||||
"Bewohner rufen ihre Information im Mieterportal ab",
|
||||
"rollenbasierte Zugriffsrechte",
|
||||
"eigener Mieterportal-Zugang für jede Wohnung",
|
||||
"ausschließlich Daten der eigenen Wohnung und des eigenen Nutzungszeitraums sichtbar",
|
||||
],
|
||||
},
|
||||
]
|
||||
@@ -203,52 +204,42 @@ const operationsScope: ExpandingCard[] = [
|
||||
const processSteps = [
|
||||
{
|
||||
media: <AssetRender render={renders.building} imgClassName="w-52" />,
|
||||
title: "Gebäude erfassen",
|
||||
description: "Adresse, Wohnungen und Heizart angeben.",
|
||||
},
|
||||
{
|
||||
media: (
|
||||
<>
|
||||
<AssetRender render={renders.heatMeter} imgClassName="w-32" />
|
||||
<AssetRender
|
||||
render={renders.smokeAlarm}
|
||||
className="-ml-3 self-start"
|
||||
imgClassName="w-24"
|
||||
/>
|
||||
</>
|
||||
),
|
||||
title: "Ausstattung bestimmen",
|
||||
description: "SolenOS ermittelt passende Geräte und Mengen.",
|
||||
title: "Gebäudedaten online erfassen",
|
||||
description:
|
||||
"Adresse, Wohnungen und Heizart online angeben. SolenOS ermittelt daraus die notwendige Ausstattung und prüft sie vor dem Versand.",
|
||||
},
|
||||
{
|
||||
media: (
|
||||
<AssetRender render={renders.shippingBoxMeters} imgClassName="w-36" />
|
||||
),
|
||||
title: "Vorkonfiguriert erhalten",
|
||||
description: "Geräte bereits jeder Wohnung zugeordnet geliefert.",
|
||||
description:
|
||||
"Die geprüften Geräte werden bereits den vorgesehenen Wohnungen zugeordnet geliefert.",
|
||||
},
|
||||
{
|
||||
media: <AssetRender render={renders.drillTool} imgClassName="w-32" />,
|
||||
title: "Geräte montieren",
|
||||
description: "Selbst installieren oder Montage beauftragen.",
|
||||
title: "Vor Ort montieren",
|
||||
description:
|
||||
"Selbst, mit dem eigenen Fachbetrieb oder durch SolenOS montieren lassen. Eine Softwarekonfiguration vor Ort ist nicht erforderlich.",
|
||||
},
|
||||
{
|
||||
media: (
|
||||
<AssetRender render={renders.laptopDashboard} imgClassName="w-44" />
|
||||
),
|
||||
title: "Betrieb starten",
|
||||
description: "Bewohner einladen und digital verwalten.",
|
||||
title: "Betrieb übernehmen lassen",
|
||||
description:
|
||||
"SolenOS übernimmt Einrichtung, Datenübertragung und laufenden Betrieb; Bewohner erhalten ihren Portalzugang.",
|
||||
},
|
||||
]
|
||||
|
||||
const lessEffort = [
|
||||
{
|
||||
title: "Vorkonfigurierte Hardware",
|
||||
text: "Geräte werden passend zum jeweiligen Gebäude und zur vorgesehenen Nutzung vorbereitet.",
|
||||
title: "Zum Einbau vorkonfigurierte Messeinrichtungen",
|
||||
text: "SolenOS bestimmt die Ausstattung aus den Objektdaten, prüft sie und ordnet die Geräte vor dem Versand zu.",
|
||||
},
|
||||
{
|
||||
title: "Keine aufwendige Einrichtung auf der Baustelle",
|
||||
text: "Der Installateur kann sich auf die fachgerechte Montage konzentrieren.",
|
||||
title: "Keine Softwarekonfiguration vor Ort",
|
||||
text: "Vor Ort wird nur montiert. Eine Softwarekonfiguration ist nicht erforderlich.",
|
||||
},
|
||||
{
|
||||
title: "Bestehende Fachbetriebe nutzen",
|
||||
@@ -308,7 +299,7 @@ const audiences = [
|
||||
"Ausstattung aus Gebäudedaten ermitteln",
|
||||
"vorkonfigurierte Geräte erhalten",
|
||||
"eigenen Fachbetrieb nutzen",
|
||||
"laufenden Messbetrieb digital verwalten",
|
||||
"laufenden Messbetrieb digital betreuen",
|
||||
],
|
||||
cta: "SolenOS für Hauseigentümer",
|
||||
to: "/fuer-wen/hauseigentuemer",
|
||||
@@ -353,7 +344,7 @@ const audiences = [
|
||||
"Geräte- und Verbrauchsdaten",
|
||||
"UVI",
|
||||
"Heizkostenabrechnungsprozesse",
|
||||
"White-Label-Optionen",
|
||||
"Optionen für eigenes Logo und Eigenmarke",
|
||||
],
|
||||
cta: "SolenOS für Messdienstleister",
|
||||
to: "/fuer-wen/messdienstleister",
|
||||
@@ -409,11 +400,11 @@ const portfolioScopes = [
|
||||
]
|
||||
|
||||
const priceFlow = [
|
||||
{ title: "Wenige Angaben" },
|
||||
{ title: "Erste Preisindikation" },
|
||||
{ title: "Konfiguration speichern" },
|
||||
{ title: "Gebäude vollständig konfigurieren" },
|
||||
{ title: "Genauer Preis" },
|
||||
{ title: "Leistungen auswählen" },
|
||||
{ title: "Gebäudedaten online erfassen" },
|
||||
{ title: "Persönlichen Link erhalten" },
|
||||
{ title: "Details und Fotos im Portal ergänzen" },
|
||||
{ title: "Geprüftes Gesamtangebot erhalten" },
|
||||
]
|
||||
|
||||
const faqs: FaqItem[] = [
|
||||
@@ -429,19 +420,19 @@ const faqs: FaqItem[] = [
|
||||
"In vielen Fällen kann ein vorhandener geeigneter Fachbetrieb eingesetzt werden. Welche Arbeiten erforderlich sind, hängt von der jeweiligen Messtechnik und Einbausituation ab.",
|
||||
},
|
||||
{
|
||||
question: "Muss vor Ort jedes Gerät einzeln in SolenOS eingerichtet werden?",
|
||||
question: "Muss vor Ort Software konfiguriert werden?",
|
||||
answer:
|
||||
"Die Geräte werden soweit vorgesehen bereits vor dem Versand dem Gebäude und den geplanten Einheiten zugeordnet. Dadurch reduziert sich die Softwareeinrichtung vor Ort deutlich.",
|
||||
"Nein. SolenOS ordnet die Geräte vor dem Versand dem Gebäude und den vorgesehenen Einheiten zu. Vor Ort wird nur montiert; eine Softwarekonfiguration ist nicht erforderlich.",
|
||||
},
|
||||
{
|
||||
question: "Wie genau ist die erste Preisschätzung?",
|
||||
question: "Wann erhalte ich den verbindlichen Gesamtpreis?",
|
||||
answer:
|
||||
"Die erste Schätzung basiert auf wenigen Gebäudedaten und Annahmen zur benötigten Ausstattung. Die vollständige Gebäudekonfiguration bestimmt anschließend die konkreten Geräte und den finalen Preis.",
|
||||
"Nach dem Schnellkonfigurator ergänzen Sie Gebäudedetails und Fotos vorhandener Einbausituationen im Portal. SolenOS prüft die Angaben manuell, bestimmt die konkrete Ausstattung und erstellt anschließend das verbindliche Gesamtangebot.",
|
||||
},
|
||||
{
|
||||
question: "Kann ich nur UVI buchen?",
|
||||
question: "Welche Leistungen kann ich auswählen?",
|
||||
answer:
|
||||
"Ja. UVI und Rauchwarnmelder sind einzeln oder gemeinsam wählbar. Das UVI-Paket umfasst die dafür benötigte Messtechnik und die zugehörigen digitalen Dienstleistungen; die Heizkostenabrechnung baut auf denselben erfassten Verbrauchsdaten auf. Rauchwarnmelder können auch später ergänzt werden – die bereits erfasste Gebäudestruktur wird dabei weiterverwendet.",
|
||||
"Monatliche Verbrauchsinformation, Heizkostenabrechnung und Rauchwarnmelder lassen sich im Schnellkonfigurator unabhängig voneinander hinzufügen oder abwählen."
|
||||
},
|
||||
{
|
||||
question: "Kann ich bestehende Messtechnik weiterverwenden?",
|
||||
@@ -461,10 +452,27 @@ const faqs: FaqItem[] = [
|
||||
]
|
||||
|
||||
const trustProperties = [
|
||||
{ icon: <GermanyIcon />, label: "Hosting in Deutschland" },
|
||||
{ icon: <ShieldCheck />, label: "AES-geschützte Messdaten" },
|
||||
{ icon: <Lock />, label: "TLS-verschlüsselte Übertragung" },
|
||||
{ icon: <Users />, label: "Rollenbasierte Zugriffsrechte" },
|
||||
{
|
||||
icon: <GermanyIcon />,
|
||||
label: "Daten ausschließlich in Deutschland gehostet",
|
||||
to: "/wissen/datenschutz-sicherheit",
|
||||
},
|
||||
{
|
||||
icon: <ShieldCheck />,
|
||||
label: "AES-Verschlüsselung schützt gespeicherte Messdaten",
|
||||
to: "/wissen/datenschutz-sicherheit",
|
||||
},
|
||||
{
|
||||
icon: <Lock />,
|
||||
label: "TLS schützt Daten während der Übertragung",
|
||||
to: "/wissen/datenschutz-sicherheit",
|
||||
},
|
||||
{
|
||||
icon: <Users />,
|
||||
label:
|
||||
"Bewohner sehen nur Daten ihrer eigenen Wohnung und ihres eigenen Nutzungszeitraums",
|
||||
to: "/wissen/datenschutz-sicherheit",
|
||||
},
|
||||
]
|
||||
|
||||
export default function HomePage() {
|
||||
@@ -478,18 +486,18 @@ export default function HomePage() {
|
||||
<span className="text-primary">einfach</span> gemacht.
|
||||
</>
|
||||
}
|
||||
lead="Fernauslesbare Messtechnik, monatliche UVI, Heizkostenabrechnung und Rauchwarnmelder – vorkonfiguriert geliefert, digital verwaltet und auf Wunsch komplett installiert."
|
||||
lead="Fernauslesbare Messtechnik, monatliche Verbrauchsinformation (UVI), Heizkostenabrechnung und Rauchwarnmelder – vorkonfiguriert geliefert, digital betreut und auf Wunsch komplett installiert."
|
||||
actions={
|
||||
<>
|
||||
<Button asChild size="lg">
|
||||
<Link to="/konfigurator">Preis berechnen</Link>
|
||||
<Link to="/konfigurator">Konfiguration starten</Link>
|
||||
</Button>
|
||||
<Button asChild variant="outline" size="lg">
|
||||
<Link to="/so-funktionierts">So funktioniert SolenOS</Link>
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
note="Wenige Angaben · unverbindliche Kostenschätzung"
|
||||
note="Wenige Angaben · vollständige Prüfung im Folgeprozess"
|
||||
visual={<HeroArt />}
|
||||
/>
|
||||
|
||||
@@ -529,17 +537,21 @@ export default function HomePage() {
|
||||
align="center"
|
||||
eyebrow="Das System"
|
||||
title="Alles, was für den laufenden Messbetrieb benötigt wird"
|
||||
lead="SolenOS verbindet Messtechnik, Datenerfassung und Software zu einem durchgängigen System. Statt einzelne Komponenten selbst zusammenzustellen und miteinander zu verbinden, erhalten Sie eine Lösung, bei der Bestellung, Hardware, Konfiguration und laufender Betrieb zusammenspielen."
|
||||
lead="SolenOS verbindet Messtechnik, Datenerfassung und Software in einem durchgängigen System. Bestellung, Hardware, Konfiguration und laufender Betrieb greifen dabei ineinander."
|
||||
/>
|
||||
<ExpandingCardGrid
|
||||
items={operationsScope}
|
||||
railSide="right"
|
||||
className="mt-12"
|
||||
/>
|
||||
<ExpandingCardGrid items={operationsScope} className="mt-12" />
|
||||
</Section>
|
||||
|
||||
<Section>
|
||||
<div className="rounded-3xl bg-gradient-to-b from-secondary to-card px-6 py-10 sm:px-10 sm:py-12 lg:px-12">
|
||||
<SectionHeading
|
||||
eyebrow="So funktioniert's"
|
||||
title="In fünf Schritten zum laufenden Messbetrieb"
|
||||
lead="Statt Geräte, Software und Messdienst getrennt zu organisieren, verbindet SolenOS die einzelnen Schritte zu einem durchgängigen Ablauf."
|
||||
title="Online in vier Schritten zum laufenden Messbetrieb"
|
||||
lead="Sie starten ohne Erstgespräch: Objektdaten online erfassen, die passende Ausstattung von SolenOS bestimmen lassen, vorkonfiguriert erhalten und montieren."
|
||||
/>
|
||||
</div>
|
||||
<StepFlow steps={processSteps} className="mt-4" />
|
||||
@@ -549,8 +561,8 @@ export default function HomePage() {
|
||||
<SectionHeading
|
||||
align="center"
|
||||
eyebrow="Installation"
|
||||
title="Weniger Aufwand vor Ort"
|
||||
lead="Die Installation eines Messsystems sollte nicht daran scheitern, dass vor Ort komplizierte Software eingerichtet oder jedes Gerät manuell zugeordnet werden muss. SolenOS bereitet die digitale Struktur bereits vor der Installation vor."
|
||||
title="Vor Ort nur montieren"
|
||||
lead="Vor Ort wird nur montiert. Eine Softwarekonfiguration ist nicht erforderlich. SolenOS bereitet Gebäudestruktur und Gerätezuordnung vor dem Versand vor."
|
||||
/>
|
||||
<div className="mt-12 grid gap-5 sm:grid-cols-2 lg:grid-cols-4">
|
||||
{lessEffort.map((item) => (
|
||||
@@ -666,11 +678,11 @@ export default function HomePage() {
|
||||
<div>
|
||||
<SectionHeading
|
||||
eyebrow="Preis"
|
||||
title="Was kostet SolenOS?"
|
||||
lead="Mit dem SolenOS-Konfigurator erhalten Sie schnell einen ersten Preis und können sofort bestellen."
|
||||
title="Wie entsteht der Gesamtpreis?"
|
||||
lead="Im Konfigurator wählen Sie Leistungen und erfassen die grundlegenden Gebäudedaten online. Der verbindliche Gesamtpreis folgt nach der vollständigen Konfiguration und manuellen Prüfung."
|
||||
/>
|
||||
<p className="mt-10 text-sm leading-relaxed text-muted-foreground">
|
||||
Für einen ersten Preis brauchen wir Grundlegende Informationen:
|
||||
Für die erste Ermittlung der Ausstattung benötigen wir:
|
||||
</p>
|
||||
<Checklist
|
||||
className="mt-4"
|
||||
@@ -683,11 +695,12 @@ export default function HomePage() {
|
||||
]}
|
||||
/>
|
||||
<p className="mt-4 text-sm leading-relaxed text-muted-foreground">
|
||||
Auf Basis dieser Angaben schätzt SolenOS die voraussichtlich
|
||||
benötigte Geräteanzahl und berechnet einen ungefähren Preis.
|
||||
SolenOS bestimmt daraus den voraussichtlichen Gerätebedarf. Im
|
||||
Folgeprozess ergänzen Sie Details und Fotos; danach erhalten Sie
|
||||
den geprüften Gesamtpreis.
|
||||
</p>
|
||||
<Button asChild size="lg" className="mt-6">
|
||||
<Link to="/konfigurator">Preis berechnen</Link>
|
||||
<Link to="/konfigurator">Konfiguration starten</Link>
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
@@ -695,16 +708,16 @@ export default function HomePage() {
|
||||
<CardContent className="p-0">
|
||||
<div>
|
||||
<h3 className="text-base font-bold text-navy">
|
||||
In fünf Schritten zum genauen Preis
|
||||
In fünf Schritten zum verbindlichen Gesamtangebot
|
||||
</h3>
|
||||
</div>
|
||||
<NumberedList steps={priceFlow} className="mt-6" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
<p className="mt-5 text-xs leading-relaxed text-muted-foreground italic">
|
||||
Die erste Berechnung ist eine unverbindliche Preisindikation.
|
||||
Die tatsächliche Ausstattung und der genaue Preis ergeben sich
|
||||
aus der vollständigen Objektkonfiguration.
|
||||
SolenOS veröffentlicht keine ungeprüften Preiswerte. Das
|
||||
Gesamtangebot enthält die gewählten Leistungen, erforderliche
|
||||
Gateway-Infrastruktur und die gewählte Montagevariante.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -783,7 +796,7 @@ export default function HomePage() {
|
||||
actions={
|
||||
<>
|
||||
<Button asChild variant="inverse" size="lg">
|
||||
<Link to="/konfigurator">Preis berechnen</Link>
|
||||
<Link to="/konfigurator">Konfiguration starten</Link>
|
||||
</Button>
|
||||
<Button asChild variant="inverseOutline" size="lg">
|
||||
<Link to="/so-funktionierts">So funktioniert SolenOS</Link>
|
||||
|
||||
@@ -30,9 +30,9 @@ const steps = [
|
||||
<img src={vectors.uviBadge} alt="" className="w-9" />
|
||||
</StepMedia>
|
||||
),
|
||||
title: "Gebäude anlegen und bestellen",
|
||||
title: "Gebäudedaten online erfassen",
|
||||
description:
|
||||
"Bei der Konfiguration werden Gebäude, Wohnungen und die benötigten Leistungen erfasst. Auf Basis dieser Daten wird automatisch ermittelt, welche Messtechnik, Rauchwarnmelder und weiteren Komponenten benötigt werden.",
|
||||
"Sie erfassen Gebäude, Wohnungen und Leistungen online. SolenOS ermittelt daraus die notwendige Ausstattung und prüft sie vor dem Versand.",
|
||||
},
|
||||
{
|
||||
media: (
|
||||
@@ -51,13 +51,12 @@ const steps = [
|
||||
<AssetRender render={renders.gateway} imgClassName="w-9" />
|
||||
</StepMedia>
|
||||
),
|
||||
title: "Geräte montieren",
|
||||
title: "Vor Ort nur montieren",
|
||||
description: (
|
||||
<>
|
||||
Die Geräte müssen vor Ort im Wesentlichen nur noch fachgerecht montiert
|
||||
werden.{" "}
|
||||
Die vorgesehenen Geräte werden vor Ort fachgerecht montiert.{" "}
|
||||
<strong className="font-bold text-navy">
|
||||
Keine aufwendige Softwarekonfiguration bei der Installation.
|
||||
Eine Softwarekonfiguration vor Ort ist nicht erforderlich.
|
||||
</strong>
|
||||
</>
|
||||
),
|
||||
@@ -86,13 +85,15 @@ const steps = [
|
||||
const journey = [
|
||||
"Besucher versteht SolenOS",
|
||||
"identifiziert seinen Anwendungsfall",
|
||||
"berechnet einen ungefähren Preis",
|
||||
"speichert seine Konfiguration",
|
||||
"ergänzt die tatsächlichen Gebäudedaten",
|
||||
"erhält den genauen Preis",
|
||||
"wählt Leistungen aus",
|
||||
"erfasst Gebäudedaten online",
|
||||
"erhält einen persönlichen Link",
|
||||
"ergänzt Details und Fotos",
|
||||
"SolenOS prüft die Ausstattung",
|
||||
"erhält ein verbindliches Gesamtangebot",
|
||||
"erteilt den Auftrag",
|
||||
"SolenOS bereitet Gebäude und Geräte vor",
|
||||
"vorkonfigurierte Hardware wird geliefert",
|
||||
"vorkonfigurierte Technik wird geliefert",
|
||||
"Montage vor Ort",
|
||||
"automatischer laufender Betrieb",
|
||||
]
|
||||
@@ -101,22 +102,22 @@ const faqs: FaqItem[] = [
|
||||
{
|
||||
question: "Wo fange ich an?",
|
||||
answer:
|
||||
"Im Konfigurator. Dort erfassen Sie Gebäude, Wohnungen und die benötigten Leistungen und erhalten eine erste Preisindikation. Aus denselben Daten wird anschließend der Auftrag aufgebaut.",
|
||||
"Im Konfigurator. Dort wählen Sie Leistungen und erfassen Gebäude sowie Wohnungen online. Die Angaben werden in die anschließende Detailkonfiguration übernommen.",
|
||||
},
|
||||
{
|
||||
question: "Wie verbindlich ist der Preis aus dem Konfigurator?",
|
||||
question: "Wann erhalte ich den verbindlichen Gesamtpreis?",
|
||||
answer:
|
||||
"Er ist eine Preisschätzung auf Basis Ihrer Angaben. Den genauen Preis erhalten Sie, sobald die tatsächlichen Gebäudedaten ergänzt und geprüft sind – erst danach wird der Auftrag erteilt.",
|
||||
"Nach dem Schnellkonfigurator ergänzen Sie Gebäudedetails und Fotos im Portal. SolenOS prüft die Einbausituationen und die notwendige Ausstattung manuell und erstellt anschließend das verbindliche Gesamtangebot.",
|
||||
},
|
||||
{
|
||||
question: "Muss ich meine Gebäudedaten mehrfach erfassen?",
|
||||
answer:
|
||||
"Nein. Die einmal eingegebenen Gebäudedaten werden durch den gesamten Prozess weiterverwendet: von der Preisschätzung über die Gerätevorbereitung bis in den laufenden Betrieb.",
|
||||
"Nein. Die einmal eingegebenen Gebäudedaten werden von der ersten Online-Erfassung über Gerätevorbereitung und Montage bis in den laufenden Betrieb weiterverwendet.",
|
||||
},
|
||||
{
|
||||
question: "Wer montiert die Geräte?",
|
||||
answer:
|
||||
"Das entscheiden Sie: Sie selbst, Ihr Fachbetrieb oder SolenOS als Komplettlösung. Die Hardware kommt objektbezogen vorkonfiguriert an, eine aufwendige Softwarekonfiguration vor Ort entfällt.",
|
||||
"Das entscheiden Sie: Sie selbst, Ihr Fachbetrieb oder SolenOS als Komplettlösung. Die Technik kommt objektbezogen vorkonfiguriert an; eine Softwarekonfiguration vor Ort ist nicht erforderlich.",
|
||||
},
|
||||
{
|
||||
question: "Was passiert nach der Installation?",
|
||||
@@ -182,8 +183,8 @@ export default function HowItWorksPage() {
|
||||
sondern durch den gesamten Prozess weiterverwendet.
|
||||
</p>
|
||||
<p className="mt-6 font-mono text-xs tracking-wide text-muted-foreground uppercase">
|
||||
Preisschätzung → Konfiguration → Bestellung → Gerätevorbereitung →
|
||||
Installation → Betrieb
|
||||
Online-Erfassung → Detailkonfiguration → Gesamtangebot →
|
||||
Gerätevorbereitung → Installation → Betrieb
|
||||
</p>
|
||||
</div>
|
||||
</Section>
|
||||
@@ -194,7 +195,7 @@ export default function HowItWorksPage() {
|
||||
align="center"
|
||||
eyebrow="Häufige Fragen"
|
||||
title="Fragen zum Ablauf"
|
||||
lead="Von der ersten Preisindikation bis zum laufenden Betrieb – die häufigsten Fragen zum SolenOS-Prozess."
|
||||
lead="Von der Online-Erfassung bis zum laufenden Betrieb – die häufigsten Fragen zum SolenOS-Prozess."
|
||||
/>
|
||||
<FaqAccordion className="mt-10" items={faqs} />
|
||||
</Section>
|
||||
@@ -203,11 +204,11 @@ export default function HowItWorksPage() {
|
||||
<Section className="pt-0">
|
||||
<CtaBanner
|
||||
icon={<Calculator />}
|
||||
title="Was kostet SolenOS für Ihr Gebäude?"
|
||||
description="Mit wenigen Angaben erhalten Sie eine erste Preisindikation."
|
||||
title="Konfiguration für Ihr Gebäude starten"
|
||||
description="Leistungen auswählen, Gebäudedaten online erfassen und die geprüfte Ausstattung vorbereiten."
|
||||
actions={
|
||||
<Button variant="inverse" size="lg" asChild>
|
||||
<Link to="/konfigurator">Preis berechnen</Link>
|
||||
<Link to="/konfigurator">Konfiguration starten</Link>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -13,9 +13,9 @@ import {
|
||||
} from "@/components/solenos/illustrations"
|
||||
|
||||
const trustItems = [
|
||||
{ icon: ClipboardCheck, label: ["Klare", "Vertragsstruktur"] },
|
||||
{ icon: ShieldCheck, label: ["Keine versteckten", "Gebühren"] },
|
||||
{ icon: Users2, label: ["Rabatte für", "große Objekte"] },
|
||||
{ icon: ClipboardCheck, label: ["Geprüfter", "Leistungsumfang"] },
|
||||
{ icon: ShieldCheck, label: ["Verbindliches", "Gesamtangebot"] },
|
||||
{ icon: Users2, label: ["Passend zum", "konkreten Objekt"] },
|
||||
] as const
|
||||
|
||||
export default function KlarpreisPage() {
|
||||
@@ -35,7 +35,7 @@ export default function KlarpreisPage() {
|
||||
SolenOS <span className="text-primary">Klarpreis</span>
|
||||
</>
|
||||
}
|
||||
lead="Drei sauber getrennte Leistungen. Einfache Preise. Keine Überraschungen."
|
||||
lead="Ein vollständiger Leistungsumfang und ein verbindlicher Gesamtpreis nach Prüfung der konkreten Objektdaten."
|
||||
extra={
|
||||
<div className="inline-flex items-center gap-3 rounded-full border border-border bg-card px-4 py-2 text-sm text-muted-foreground shadow-pill">
|
||||
<IconBadge variant="soft" size="sm">
|
||||
@@ -57,20 +57,18 @@ export default function KlarpreisPage() {
|
||||
<Section className="pt-0">
|
||||
<div className="grid gap-6 lg:grid-cols-3">
|
||||
<PriceCard
|
||||
title="RWM-Hardware"
|
||||
cadence="Einmalig"
|
||||
price="42,00 €"
|
||||
unit="je Wohnung einmalig"
|
||||
allocation={{ label: "Nicht umlagefähig", tone: "negative" }}
|
||||
description="Rauchwarnmelder inklusive Montage und Eigentumsübertragung."
|
||||
title="Rauchwarnmelder"
|
||||
cadence="Gesamtangebot"
|
||||
price="Nach Prüfung"
|
||||
unit="Geräteanzahl und Montagevariante"
|
||||
description="Benötigte Rauchwarnmelder, vereinbarte Montage und Eigentumsübertragung."
|
||||
media={<SmokeDetectorIllustration />}
|
||||
/>
|
||||
<PriceCard
|
||||
title="Ferninspektion"
|
||||
cadence="Monatlich"
|
||||
price="2,20 €"
|
||||
unit="je Wohnung / Monat"
|
||||
allocation={{ label: "Grundsätzlich umlagefähig", tone: "positive" }}
|
||||
cadence="Gesamtangebot"
|
||||
price="Nach Prüfung"
|
||||
unit="passend zum vereinbarten Leistungsumfang"
|
||||
description="Regelmäßige Prüfung, Nachweise, Meldungen und Support."
|
||||
media={
|
||||
<div className="relative">
|
||||
@@ -80,16 +78,11 @@ export default function KlarpreisPage() {
|
||||
}
|
||||
/>
|
||||
<PriceCard
|
||||
title={
|
||||
<span className="text-[1.15rem] whitespace-nowrap">
|
||||
UVI-Komplettbetrieb
|
||||
</span>
|
||||
}
|
||||
cadence="Monatlich"
|
||||
price="10,50 €"
|
||||
unit="je Wohnung / Monat"
|
||||
allocation={{ label: "Grundsätzlich umlagefähig", tone: "positive" }}
|
||||
description="Sensoren, Daten, Portal und Verbrauchsinformation inklusive."
|
||||
title="Messbetrieb und Abrechnung"
|
||||
cadence="Gesamtangebot"
|
||||
price="Nach Prüfung"
|
||||
unit="nach vollständiger Objektkonfiguration"
|
||||
description="Je nach Auswahl: Messtechnik, erforderliche Gateway-Infrastruktur, Daten, Portale, Heizkostenabrechnung und monatliche Verbrauchsinformation (UVI)."
|
||||
media={<SensorCubesIllustration />}
|
||||
/>
|
||||
</div>
|
||||
@@ -102,16 +95,13 @@ export default function KlarpreisPage() {
|
||||
</IconBadge>
|
||||
<div>
|
||||
<div className="font-semibold text-white/80">
|
||||
Gesamtkosten laufend
|
||||
</div>
|
||||
<div className="mt-1 flex flex-wrap items-baseline gap-x-3">
|
||||
<span className="text-4xl font-extrabold tracking-tight text-white">
|
||||
12,70 €
|
||||
</span>
|
||||
<span className="text-sm text-white/75">
|
||||
je Wohnung / Monat
|
||||
</span>
|
||||
Verbindlicher Gesamtpreis
|
||||
</div>
|
||||
<p className="mt-1 max-w-md text-sm leading-relaxed text-white/85">
|
||||
Nach der vollständigen Objektkonfiguration und manuellen
|
||||
Prüfung erhalten Sie ein Gesamtangebot statt ungeprüfter
|
||||
Einzelpreise.
|
||||
</p>
|
||||
</div>
|
||||
<Separator
|
||||
orientation="vertical"
|
||||
@@ -121,9 +111,9 @@ export default function KlarpreisPage() {
|
||||
<IconBadge variant="glass" size="sm">
|
||||
<Tag />
|
||||
</IconBadge>
|
||||
<p className="max-w-56 text-sm leading-snug text-white/80">
|
||||
Alle laufenden Leistungen klar gebündelt – ohne versteckte
|
||||
Zusatzkosten.
|
||||
<p className="max-w-64 text-sm leading-snug text-white/80">
|
||||
Gewählte Leistungen, erforderliche Gateway-Infrastruktur und
|
||||
Montagevariante werden gemeinsam ausgewiesen.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -194,18 +194,18 @@ export default function HeizkostenabrechnungProductPage() {
|
||||
eyebrow="Produkt"
|
||||
title={<>Heizkosten­abrechnung</>}
|
||||
tagline="Aus den Daten, die ohnehin laufen."
|
||||
lead="Die jährliche Abrechnung der Heiz- und Warmwasserkosten entsteht aus denselben fernabgelesenen Verbrauchswerten wie die monatliche UVI – verteilt nach den Maßstäben der Heizkostenverordnung, ohne Ablesetermin im Gebäude."
|
||||
lead="Die jährliche Abrechnung der Heiz- und Warmwasserkosten entsteht aus denselben fernabgelesenen Verbrauchswerten wie die monatliche Verbrauchsinformation (UVI) – verteilt nach den Maßstäben der Heizkostenverordnung, ohne Ablesetermin im Gebäude."
|
||||
actions={
|
||||
<>
|
||||
<Button asChild size="lg">
|
||||
<Link to="/konfigurator">Preis für mein Gebäude berechnen</Link>
|
||||
<Link to="/konfigurator">Konfiguration für mein Gebäude starten</Link>
|
||||
</Button>
|
||||
<Button asChild variant="outline" size="lg">
|
||||
<Link to="/produkte/uvi">UVI ansehen</Link>
|
||||
<Link to="/produkte/uvi">Verbrauchsinformation ansehen</Link>
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
note="Wenige Angaben · unverbindliche Kostenschätzung"
|
||||
note="Wenige Angaben · vollständige Prüfung im Folgeprozess"
|
||||
visual={<BillingHeroArt />}
|
||||
features={[
|
||||
{
|
||||
@@ -238,7 +238,7 @@ export default function HeizkostenabrechnungProductPage() {
|
||||
actions={
|
||||
<>
|
||||
<Button asChild variant="inverse" size="lg">
|
||||
<Link to="/konfigurator">Preis berechnen</Link>
|
||||
<Link to="/konfigurator">Konfiguration starten</Link>
|
||||
</Button>
|
||||
<Button asChild variant="inverseOutline" size="lg">
|
||||
<Link to="/kontakt">Kontakt aufnehmen</Link>
|
||||
|
||||
@@ -101,11 +101,11 @@ export default function ProductsPage() {
|
||||
<Section className="pt-0">
|
||||
<CtaBanner
|
||||
icon={<Euro />}
|
||||
title="Jetzt Preis für Ihr Gebäude berechnen"
|
||||
description="In wenigen Minuten zur ersten Preisindikation."
|
||||
title="Ausstattung für Ihr Gebäude konfigurieren"
|
||||
description="Leistungen auswählen, Gebäudedaten online erfassen und die Prüfung vorbereiten."
|
||||
actions={
|
||||
<Button variant="inverse" size="lg" asChild>
|
||||
<Link to="/konfigurator">Preis berechnen</Link>
|
||||
<Link to="/konfigurator">Konfiguration starten</Link>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -100,7 +100,7 @@ const DATA_PATH = [
|
||||
media: <AssetRender render={renders.gateway} imgClassName="w-28" />,
|
||||
title: "Gateway sammelt",
|
||||
description:
|
||||
"Ein Gateway je Gebäude empfängt die Funkpakete aller angebundenen Geräte.",
|
||||
"Die erforderliche Gateway-Infrastruktur empfängt die Funkpakete der angebundenen Geräte und wird von SolenOS passend zum Objekt bestimmt.",
|
||||
},
|
||||
{
|
||||
media: (
|
||||
@@ -167,7 +167,7 @@ const FAQS: FaqItem[] = [
|
||||
{
|
||||
question: "Was kostet die Messtechnik?",
|
||||
answer:
|
||||
"Die für den Messbetrieb benötigten Sensoren sind im UVI-Komplettbetrieb enthalten: 10,50 € je Wohnung und Monat, grundsätzlich umlagefähig. Welche Geräte in welcher Anzahl erforderlich sind, ergibt sich aus der Gebäudekonfiguration.",
|
||||
"SolenOS bestimmt die benötigten Sensoren und die erforderliche Gateway-Infrastruktur aus der vollständigen Gebäudekonfiguration. Beides wird im geprüften Gesamtangebot gemeinsam mit den gewählten Leistungen ausgewiesen; ungeprüfte Einzelpreise veröffentlichen wir nicht.",
|
||||
},
|
||||
{
|
||||
question: "Kann ich vorhandene Zähler weiterverwenden?",
|
||||
@@ -202,11 +202,11 @@ export default function MesstechnikProductPage() {
|
||||
</span>
|
||||
}
|
||||
tagline="Die Grundlage für alles andere."
|
||||
lead="Zähler, Heizkostenverteiler und Gateway erfassen und übertragen die Werte, aus denen UVI und Heizkostenabrechnung entstehen – fernablesbar, interoperabel und objektbezogen vorkonfiguriert geliefert."
|
||||
lead="Zähler, Heizkostenverteiler und Gateway erfassen und übertragen die Werte, aus denen monatliche Verbrauchsinformation (UVI) und Heizkostenabrechnung entstehen – fernablesbar, interoperabel und objektbezogen vorkonfiguriert geliefert."
|
||||
actions={
|
||||
<>
|
||||
<Button asChild size="lg">
|
||||
<Link to="/konfigurator">Ausstattung und Preis ermitteln</Link>
|
||||
<Link to="/konfigurator">Ausstattung ermitteln</Link>
|
||||
</Button>
|
||||
<Button asChild variant="outline" size="lg">
|
||||
<Link to="/wissen/datenschutz-sicherheit">
|
||||
@@ -215,7 +215,7 @@ export default function MesstechnikProductPage() {
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
note="Wenige Angaben · unverbindliche Kostenschätzung"
|
||||
note="Wenige Angaben · vollständige Prüfung im Folgeprozess"
|
||||
visual={<InfrastructureHeroArt />}
|
||||
features={[
|
||||
{
|
||||
|
||||
@@ -30,9 +30,9 @@ type Product = {
|
||||
const PRODUCTS: Product[] = [
|
||||
{
|
||||
to: "/produkte/uvi",
|
||||
label: "UVI",
|
||||
title: "UVI",
|
||||
sub: "Monatliche Verbrauchsinformation",
|
||||
label: "Verbrauchsinformation (UVI)",
|
||||
title: "Verbrauchsinformation (UVI)",
|
||||
sub: "Monatlich für Bewohner",
|
||||
summary:
|
||||
"Verbrauchsdaten werden automatisch erfasst und die monatliche Verbrauchsinformation für die Bewohner erzeugt und bereitgestellt – ohne Ablesetermin in der Wohnung.",
|
||||
icon: icons.uvi,
|
||||
@@ -102,6 +102,7 @@ function ProductPage({
|
||||
lead,
|
||||
actions,
|
||||
note,
|
||||
extra,
|
||||
visual,
|
||||
features,
|
||||
children,
|
||||
@@ -116,6 +117,7 @@ function ProductPage({
|
||||
lead?: React.ReactNode
|
||||
actions?: React.ReactNode
|
||||
note?: React.ReactNode
|
||||
extra?: React.ReactNode
|
||||
visual?: React.ReactNode
|
||||
features: FeatureBandItem[]
|
||||
/** the product's spec sections between feature band and closing */
|
||||
@@ -140,6 +142,7 @@ function ProductPage({
|
||||
}
|
||||
actions={actions}
|
||||
note={note}
|
||||
extra={extra}
|
||||
visual={visual}
|
||||
/>
|
||||
<Container>
|
||||
|
||||
@@ -199,14 +199,14 @@ export default function RauchwarnmelderProductPage() {
|
||||
actions={
|
||||
<>
|
||||
<Button asChild size="lg">
|
||||
<Link to="/konfigurator">Preis für mein Gebäude berechnen</Link>
|
||||
<Link to="/konfigurator">Konfiguration für mein Gebäude starten</Link>
|
||||
</Button>
|
||||
<Button asChild variant="outline" size="lg">
|
||||
<Link to="/klarpreis">Preise ansehen</Link>
|
||||
<Link to="/klarpreis">Gesamtangebot ansehen</Link>
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
note="Wenige Angaben · unverbindliche Kostenschätzung"
|
||||
note="Wenige Angaben · vollständige Prüfung im Folgeprozess"
|
||||
visual={<SmokeAlarmHeroArt />}
|
||||
features={[
|
||||
{
|
||||
@@ -239,7 +239,7 @@ export default function RauchwarnmelderProductPage() {
|
||||
actions={
|
||||
<>
|
||||
<Button asChild variant="inverse" size="lg">
|
||||
<Link to="/konfigurator">Preis berechnen</Link>
|
||||
<Link to="/konfigurator">Konfiguration starten</Link>
|
||||
</Button>
|
||||
<Button asChild variant="inverseOutline" size="lg">
|
||||
<Link to="/kontakt">Kontakt aufnehmen</Link>
|
||||
@@ -283,29 +283,24 @@ export default function RauchwarnmelderProductPage() {
|
||||
|
||||
<Section className="pt-0 sm:pt-0 lg:pt-0">
|
||||
<SectionHeading
|
||||
eyebrow="Preis"
|
||||
title="Hardware einmalig, Betrieb monatlich"
|
||||
lead="Die Rauchwarnmelder werden einmalig abgerechnet und gehen in Ihr Eigentum über. Die laufende Ferninspektion wird monatlich je Wohnung berechnet."
|
||||
eyebrow="Gesamtangebot"
|
||||
title="Hardware, Ferninspektion und Montage transparent zusammenführen"
|
||||
lead="Geräteanzahl, Inspektionsumfang und gewählte Montagevariante werden nach der vollständigen Objektkonfiguration geprüft und gemeinsam angeboten."
|
||||
/>
|
||||
<div className="mt-10 grid gap-6 lg:grid-cols-[1fr_1fr_1.1fr]">
|
||||
<PriceCard
|
||||
title="RWM-Hardware"
|
||||
cadence="Einmalig"
|
||||
price="42,00 €"
|
||||
unit="je Wohnung einmalig"
|
||||
allocation={{ label: "Nicht umlagefähig", tone: "negative" }}
|
||||
description="Rauchwarnmelder inklusive Montage und Eigentumsübertragung."
|
||||
title="Rauchwarnmelder"
|
||||
cadence="Gesamtangebot"
|
||||
price="Nach Prüfung"
|
||||
unit="Geräteanzahl und Montagevariante"
|
||||
description="Benötigte Rauchwarnmelder, vereinbarte Montage und Eigentumsübertragung."
|
||||
media={<SmokeDetectorIllustration />}
|
||||
/>
|
||||
<PriceCard
|
||||
title="Ferninspektion"
|
||||
cadence="Monatlich"
|
||||
price="2,20 €"
|
||||
unit="je Wohnung / Monat"
|
||||
allocation={{
|
||||
label: "Grundsätzlich umlagefähig",
|
||||
tone: "positive",
|
||||
}}
|
||||
cadence="Gesamtangebot"
|
||||
price="Nach Prüfung"
|
||||
unit="passend zum vereinbarten Leistungsumfang"
|
||||
description="Regelmäßige Prüfung, Nachweise, Meldungen und Support."
|
||||
media={
|
||||
<div className="relative">
|
||||
@@ -322,8 +317,8 @@ export default function RauchwarnmelderProductPage() {
|
||||
variant="link"
|
||||
className="mt-6 h-auto self-start p-0 font-bold"
|
||||
>
|
||||
<Link to="/klarpreis">
|
||||
Alle Preise im SolenOS Klarpreis
|
||||
<Link to="/konfigurator">
|
||||
Gesamtangebot konfigurieren
|
||||
<ArrowRight />
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
@@ -149,11 +149,11 @@ const FAQS: FaqItem[] = [
|
||||
export default function UviProductPage() {
|
||||
return (
|
||||
<ProductPage
|
||||
breadcrumb="UVI"
|
||||
breadcrumb="Verbrauchsinformation (UVI)"
|
||||
eyebrow="Produkt"
|
||||
title={
|
||||
<span className="block text-[2.25rem] text-pretty sm:text-[2.75rem]">
|
||||
Unterjährige Verbrauchs­information
|
||||
Unterjährige Verbrauchs­information (UVI)
|
||||
</span>
|
||||
}
|
||||
tagline="Monatlich. Automatisch. Nachweisbar."
|
||||
@@ -161,7 +161,7 @@ export default function UviProductPage() {
|
||||
actions={
|
||||
<>
|
||||
<Button asChild size="lg">
|
||||
<Link to="/konfigurator">Preis für mein Gebäude berechnen</Link>
|
||||
<Link to="/konfigurator">Konfiguration für mein Gebäude starten</Link>
|
||||
</Button>
|
||||
<Button asChild variant="outline" size="lg">
|
||||
<Link to="/wissen/gesetzliche-anforderungen">
|
||||
@@ -170,7 +170,45 @@ export default function UviProductPage() {
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
note="Wenige Angaben · unverbindliche Kostenschätzung"
|
||||
note="Wenige Angaben · vollständige Prüfung im Folgeprozess"
|
||||
extra={
|
||||
<div
|
||||
role="note"
|
||||
className="rounded-2xl border border-brand-300 bg-brand-50/80 p-4 shadow-card"
|
||||
>
|
||||
<div className="flex items-start gap-3">
|
||||
<Euro
|
||||
aria-hidden="true"
|
||||
className="mt-0.5 size-6 shrink-0 text-brand-700"
|
||||
/>
|
||||
<div>
|
||||
<p className="font-extrabold text-navy">
|
||||
Bis zu 3 % Kürzungsrecht
|
||||
</p>
|
||||
<p className="mt-1 text-sm leading-relaxed text-muted-foreground">
|
||||
Fehlt die monatliche Verbrauchsinformation oder ist sie
|
||||
unvollständig, können Nutzer ihren Kostenanteil um 3 %
|
||||
kürzen.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-3 flex flex-wrap items-center gap-x-4 gap-y-2 text-sm font-semibold">
|
||||
<Link
|
||||
to="/wissen/gesetzliche-anforderungen"
|
||||
className="inline-flex items-center gap-1 text-brand-800 underline decoration-brand-400 underline-offset-4"
|
||||
>
|
||||
Anforderungen im Detail
|
||||
<ArrowRight className="size-4" />
|
||||
</Link>
|
||||
<a
|
||||
href={heizkostenv("6a")}
|
||||
className="text-muted-foreground underline underline-offset-4"
|
||||
>
|
||||
Quelle: § 6a HeizkostenV
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
visual={<UviHeroArt />}
|
||||
features={[
|
||||
{
|
||||
@@ -198,12 +236,12 @@ export default function UviProductPage() {
|
||||
<Section className="pt-0 sm:pt-0 lg:pt-0">
|
||||
<CtaBanner
|
||||
icon={<Euro />}
|
||||
title="Was kostet die UVI für Ihr Gebäude?"
|
||||
description="Mit wenigen Angaben zu Gebäude, Wohnungen und Wärmeverteilung erhalten Sie eine erste Preisindikation."
|
||||
title="Verbrauchsinformation für Ihr Gebäude konfigurieren"
|
||||
description="Gebäude und Leistungen online erfassen; SolenOS prüft anschließend Ausstattung und Gesamtpreis."
|
||||
actions={
|
||||
<>
|
||||
<Button asChild variant="inverse" size="lg">
|
||||
<Link to="/konfigurator">Preis berechnen</Link>
|
||||
<Link to="/konfigurator">Konfiguration starten</Link>
|
||||
</Button>
|
||||
<Button asChild variant="inverseOutline" size="lg">
|
||||
<Link to="/kontakt">Kontakt aufnehmen</Link>
|
||||
@@ -302,19 +340,11 @@ export default function UviProductPage() {
|
||||
</Card>
|
||||
<div>
|
||||
<PriceCard
|
||||
title={
|
||||
<span className="text-[1.15rem] whitespace-nowrap">
|
||||
UVI-Komplettbetrieb
|
||||
</span>
|
||||
}
|
||||
cadence="Monatlich"
|
||||
price="10,50 €"
|
||||
unit="je Wohnung / Monat"
|
||||
allocation={{
|
||||
label: "Grundsätzlich umlagefähig",
|
||||
tone: "positive",
|
||||
}}
|
||||
description="Sensoren, Daten, Portal und Verbrauchsinformation inklusive."
|
||||
title="Monatliche Verbrauchsinformation (UVI)"
|
||||
cadence="Gesamtangebot"
|
||||
price="Nach Prüfung"
|
||||
unit="nach vollständiger Objektkonfiguration"
|
||||
description="Messtechnik, erforderliche Gateway-Infrastruktur, Daten, Portal und Verbrauchsinformation werden gemeinsam angeboten."
|
||||
media={
|
||||
<AssetRender
|
||||
render={renders.uviGlassPane}
|
||||
@@ -324,8 +354,8 @@ export default function UviProductPage() {
|
||||
}
|
||||
/>
|
||||
<Button asChild variant="link" className="mt-4 h-auto p-0 font-bold">
|
||||
<Link to="/klarpreis">
|
||||
Alle Preise im SolenOS Klarpreis
|
||||
<Link to="/konfigurator">
|
||||
Gesamtangebot konfigurieren
|
||||
<ArrowRight />
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
@@ -101,7 +101,7 @@ export default function DatenschutzSicherheitPage() {
|
||||
<Link to="/kontakt">Kontakt aufnehmen</Link>
|
||||
</Button>
|
||||
<Button asChild variant="inverseOutline" size="lg">
|
||||
<Link to="/konfigurator">Preis berechnen</Link>
|
||||
<Link to="/konfigurator">Konfiguration starten</Link>
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ export default function GesetzlicheAnforderungenPage() {
|
||||
<Link to="/kontakt">Kontakt aufnehmen</Link>
|
||||
</Button>
|
||||
<Button asChild variant="inverseOutline" size="lg">
|
||||
<Link to="/konfigurator">Preis berechnen</Link>
|
||||
<Link to="/konfigurator">Konfiguration starten</Link>
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user