import * as React from "react" import { Link } from "react-router-dom" import { ArrowRight, Euro, Plus, X } from "lucide-react" import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion" 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" import { Separator } from "@/components/ui/separator" import { Checklist } from "@/components/gebos/checklist" import { DonutIllustration } from "@/components/gebos/illustrations" import { IconBadge } from "@/components/gebos/icon-tile" import { Container, Section, SectionHeading } from "@/components/gebos/section" import { PageBreadcrumb } from "@/components/gebos/page-breadcrumb" import { icons, vectors } from "@/components/gebos/site-assets" type Heat = "heizkoerper" | "fussbodenheizung" | "gemischt" | "unbekannt" type Building = { id: number adresse: string heat: Heat wohnungen: number zimmer: number } const HEAT_OPTIONS: { value: Heat; label: string }[] = [ { value: "heizkoerper", label: "Heizkörper" }, { value: "fussbodenheizung", label: "Fußbodenheizung" }, { value: "gemischt", label: "Gemischt" }, { value: "unbekannt", label: "Weiß ich nicht" }, ] const INITIAL_BUILDINGS: Building[] = [ { id: 1, adresse: "", heat: "heizkoerper", wohnungen: 12, zimmer: 3 }, { id: 2, adresse: "", heat: "heizkoerper", wohnungen: 8, zimmer: 3 }, { id: 3, adresse: "", heat: "heizkoerper", wohnungen: 6, zimmer: 3 }, ] const UVI_MONTHLY = 10.5 const INSPECTION_MONTHLY = 2.2 const RWM_ONE_TIME = 42 function formatEuro(value: number) { return value.toLocaleString("de-DE", { minimumFractionDigits: 2, maximumFractionDigits: 2, }) } function StepCard({ step, title, children, }: { step: number title: string children: React.ReactNode }) { return (
{step}

{title}

{children}
) } export default function ConfiguratorPage() { const [uvi, setUvi] = React.useState(true) const [rwm, setRwm] = React.useState(true) const [buildings, setBuildings] = React.useState(INITIAL_BUILDINGS) const [email, setEmail] = React.useState("") const nextId = React.useRef(INITIAL_BUILDINGS.length + 1) const updateBuilding = (id: number, patch: Partial) => { setBuildings((prev) => prev.map((b) => (b.id === id ? { ...b, ...patch } : b))) } const addBuilding = () => { setBuildings((prev) => [ ...prev, { id: nextId.current++, adresse: "", heat: "heizkoerper", wohnungen: 8, zimmer: 3 }, ]) } const removeBuilding = (id: number) => { setBuildings((prev) => (prev.length > 1 ? prev.filter((b) => b.id !== id) : prev)) } const totalBuildings = buildings.length const totalUnits = buildings.reduce((sum, b) => sum + (b.wohnungen || 0), 0) const sensors = buildings.reduce( (sum, b) => sum + Math.round((b.wohnungen || 0) * (b.zimmer || 0) * 0.92), 0 ) const smokeDetectors = buildings.reduce( (sum, b) => sum + Math.round((b.wohnungen || 0) * ((b.zimmer || 0) + 0.7)), 0 ) const monthly = (uvi ? UVI_MONTHLY : 0) + (uvi || rwm ? INSPECTION_MONTHLY : 0) return (
{/* Left column: steps */}
{buildings.map((b, i) => (
Gebäude {i + 1}
{buildings.length > 1 ? ( ) : null}
updateBuilding(b.id, { adresse: e.target.value }) } />
updateBuilding(b.id, { wohnungen: Math.max( 0, Math.round(Number(e.target.value) || 0) ), }) } />
updateBuilding(b.id, { zimmer: Math.max(0, Number(e.target.value) || 0), }) } />
))}

Sofortige erste Preisindikation.

Wie wurde dieser Preis berechnet?

Für diese Schätzung gehen wir aufgrund Ihrer Angaben von ungefähr{" "} {sensors} Heizsensoren und {smokeDetectors}{" "} Rauchwarnmeldern {" "} aus.

Bei Gebäuden mit durchschnittlich drei Zimmern verwenden wir eine typische Geräteausstattung als Berechnungsgrundlage.

Die endgültige Anzahl wird bei der detaillierten Konfiguration der Wohnungen bestimmt und ersetzt diese Schätzwerte.

e.preventDefault()} className="flex flex-col gap-3" >
setEmail(e.target.value)} />

Sie erhalten einen persönlichen Link (gebos.de/konfiguration/…) zu Ihrer Konfiguration – sofort weitermachen, später zurückkehren oder den Link intern weitergeben.

{/* Right column: sticky summary */}

Ihre vorläufige Konfiguration

{totalBuildings}{" "} {totalBuildings === 1 ? "Gebäude" : "Gebäude"}
{totalUnits} {totalUnits === 1 ? "Wohnung" : "Wohnungen"}
{uvi || rwm ? ( <>

Voraussichtlich benötigt

    {uvi ? (
  • ca. {sensors} Heizsensoren
  • ) : null} {rwm ? (
  • ca. {smokeDetectors} Rauchwarnmelder
  • ) : null}
) : null}
ca. {formatEuro(monthly)}{"\u00A0"}€
je Wohnung / Monat
{rwm ? (
+ {formatEuro(RWM_ONE_TIME)}{"\u00A0"}€ je Wohnung einmalig (RWM-Hardware)
) : null}

Die erste Berechnung ist eine unverbindliche Preisindikation. Der genaue Preis ergibt sich aus der vollständigen Objektkonfiguration.

{/* Was ist in der Schätzung enthalten? */}

UVI

Rauchwarnmelder

{/* Stufe 2 – So geht es weiter */}
Geschätzt: 72 Heizsensoren
Geschätzt: 96 Rauchwarnmelder

Finales Ergebnis

Ihre GebOS-Konfiguration

3 Gebäude · 26 Wohnungen

UVI
68 Heizsensoren / Messgeräte, weitere benötigte Messtechnik
Rauchwarnmelder
103 Rauchwarnmelder
Infrastruktur
technisch ausgelegte Gateway- und Kommunikationsinfrastruktur

Ihr Preis ist dann keine grobe Hochrechnung auf Basis von Durchschnittswerten mehr, sondern ein Preis auf Grundlage der tatsächlichen Objektkonfiguration.

Ihre Daten werden im gesamten Prozess weiterverwendet: Preisschätzung → Konfiguration → Bestellung → Gerätevorbereitung → Installation → laufender Betrieb.

) }