Files
online-energieausweis/src/modules/VerbrauchsausweisWohnen/VerbrauchsausweisWohnenModule.svelte
2025-02-17 11:39:48 +07:00

630 lines
18 KiB
Svelte

<script lang="ts">
import PerformanceScore from "#components/Ausweis/PerformanceScore.svelte";
import Progressbar from "#components/Ausweis/Progressbar.svelte";
import { PRICES } from "#lib/constants.js";
import Bereich from "#components/labels/Bereich.svelte";
import ButtonSpaeterHilfe from "#components/Ausweis/ButtonSpaeterHilfe.svelte";
import ButtonWeiterHilfe from "#components/Ausweis/ButtonWeiterHilfe.svelte";
import Ausweisart from "#components/Ausweis/Ausweisart.svelte";
import GebaeudeDaten from "#components/Ausweis/GebaeudeDaten.svelte";
import Warmwasseranteil from "#components/Ausweis/Warmwasseranteil.svelte";
import Verbrauch from "#components/Ausweis/Verbrauch.svelte";
import moment from "moment";
import LueftungundLeerstand from "#components/Ausweis/LueftungundLeerstand.svelte";
import SanierungszustandHeizungsanlage from "#components/Ausweis/SanierungszustandHeizungsanlage.svelte";
import SanierungszustandFensterTueren from "#components/Ausweis/SanierungszustandFensterTueren.svelte";
import SanierungszustandWaermedammung from "#components/Ausweis/SanierungszustandWaermedammung.svelte";
import AusweisPreviewContainer from "#components/Ausweis/AusweisPreviewContainer.svelte";
import {
RawNotificationWrapper,
RawNotification,
notifications,
} from "#components/Notifications/index.js";
import { auditHeizungGebaeudeBaujahr } from "#components/Verbrauchsausweis/audits/HeizungGebaeudeBaujahr.js";
import { auditHeizungJuengerDreiJahre } from "#components/Verbrauchsausweis/audits/HeizungJuengerDreiJahre.js";
import { auditZeitraumAktuell } from "#components/Verbrauchsausweis/audits/ZeitraumAktuell.js";
import { auditKlimaFaktoren } from "#components/Verbrauchsausweis/audits/KlimaFaktoren.js";
import { auditWohnFlaeche } from "#components/Verbrauchsausweis/audits/WohnFlaeche.js";
import { auditWarmWasser } from "#components/Verbrauchsausweis/audits/WarmWasser.js";
import { auditLeerStand } from "#components/Verbrauchsausweis/audits/LeerStand.js";
import { auditPlzNichtErkannt } from "#components/Verbrauchsausweis/audits/PlzNichtErkannt.js";
import {
AuditType,
hidden,
} from "#components/Verbrauchsausweis/audits/hidden.js";
import { auditBedarfsausweisBenoetigt } from "#components/Verbrauchsausweis/audits/BedarfsausweisBenoetigt.js";
import { auditVerbrauchAbweichung } from "#components/Verbrauchsausweis/audits/VerbrauchAbweichung.js";
import { auditEndEnergie } from "#components/Verbrauchsausweis/audits/EndEnergie.js";
import { auditWohnflaecheGroesserGesamtflaeche } from "#components/Verbrauchsausweis/audits/WohnflaecheGroesserGesamtflaeche.js";
import Overlay from "#components/Overlay.svelte";
import AusweisGespeichertModule from "#modules/VerbrauchsausweisWohnen/AusweisGespeichertModule.svelte";
import type {
VerbrauchsausweisWohnenClient,
BenutzerClient,
UploadedGebaeudeBild,
ObjektClient,
AufnahmeClient,
} from "#components/Ausweis/types.js";
import { Enums } from "@ibcornelsen/database/client";
import { onMount } from "svelte";
// TODO: Vom Server sollte ein volles Objekt kommen, dass alle Subobjekte enthält, weil es sonst zu Problemen führen kann
// wenn aufnahme oder objekt nicht existiert...
export let ausweis: VerbrauchsausweisWohnenClient;
export let objekt: ObjektClient
export let aufnahme: AufnahmeClient
export let user: BenutzerClient = {} as BenutzerClient;
export let bilder: UploadedGebaeudeBild[] = []
if (Object.keys(ausweis).length === 0) {
const localStorageAusweis = localStorage.getItem("ausweis");
if (localStorageAusweis) {
ausweis = JSON.parse(localStorageAusweis)
}
}
if (Object.keys(aufnahme).length === 0) {
const localStorageAufnahme = localStorage.getItem("aufnahme");
if (localStorageAufnahme) {
aufnahme = JSON.parse(localStorageAufnahme)
}
}
if (Object.keys(objekt).length === 0) {
const localStorageObjekt = localStorage.getItem("objekt");
if (localStorageObjekt) {
objekt = JSON.parse(localStorageObjekt)
}
}
async function spaeterWeitermachen() {
// TODO FIX
// const result = await ausweisSpeichern(
// ausweis,
// objekt,
// aufnahme,
// bilder
// );
// if (result !== null) {
// // Falls der Nutzer zurück navigiert, sollte er wieder auf seinen Vorgang kommen.
// // Sonst müsste er alles neu eingeben...
// ausweis.uid = result.uid_ausweis;
// objekt.uid = result.uid_objekt;
// aufnahme.uid = result.uid_aufnahme;
// window.history.pushState(
// {},
// "",
// `${location.pathname}?uid=${result.uid_ausweis}`
// );
// speichernOverlayHidden = false;
// }
}
function automatischAusfüllen() {
aufnahme.baujahr_gebaeude = [1962];
aufnahme.baujahr_heizung = [1952];
aufnahme.saniert = true;
aufnahme.einheiten = 1;
aufnahme.gebaeudetyp = "Einfamilienhaus";
aufnahme.keller =
Enums.Heizungsstatus.NICHT_VORHANDEN;
aufnahme.dachgeschoss =
Enums.Heizungsstatus.NICHT_VORHANDEN;
aufnahme.lueftung = "Fensterlueftung";
aufnahme.kuehlung = "1";
ausweis.ausstellgrund = "Vermietung";
ausweis.verbrauch_1 = 15000;
ausweis.verbrauch_2 = 14000;
ausweis.verbrauch_3 = 16000;
aufnahme.flaeche = 152;
aufnahme.nutzflaeche = 172;
ausweis.keller_beheizt = true;
aufnahme.brennstoff_1 = "Erdgas H";
ausweis.einheit_1 = "kWh";
ausweis.anteil_warmwasser_1 = 18;
ausweis.startdatum = moment("01.01.2021").toDate();
objekt.plz = "21039";
objekt.ort = "Hamburg";
objekt.adresse = "Curslacker Deich 170";
aufnahme.gebaeudeteil = "Gesamtgebäude";
objekt = objekt;
ausweis = ausweis;
}
async function ausweisAbschicken(e: SubmitEvent) {
// if (e && e.preventDefault) e.preventDefault();
// const result = await ausweisSpeichern(
// ausweis,
// objekt,
// aufnahme,
// bilder
// );
// if (result !== null) {
// // Falls der Nutzer zurück navigiert, sollte er wieder auf seinen Vorgang kommen.
// // Sonst müsste er alles neu eingeben...
// ausweis.uid = result.uid_ausweis;
// objekt.uid = result.uid_objekt;
// aufnahme.uid = result.uid_aufnahme;
// window.history.pushState(
// {},
// "",
// `${location.pathname}?uid=${result.uid_ausweis}`
// );
// // window.location.href = `/kundendaten?uid=${result.uid_ausweis}`;
// }
}
let waitOverlayHidden = true;
let speichernOverlayHidden = true;
$: {
if (ausweis.uid && objekt.uid && aufnahme.uid) {
localStorage.setItem(ausweis.uid, JSON.stringify(ausweis))
localStorage.setItem(objekt.uid, JSON.stringify(objekt))
localStorage.setItem(aufnahme.uid, JSON.stringify(aufnahme))
} else {
localStorage.setItem("ausweis", JSON.stringify(ausweis))
localStorage.setItem("aufnahme", JSON.stringify(aufnahme))
localStorage.setItem("objekt", JSON.stringify(objekt))
}
}
$: {
if (
aufnahme.saniert &&
aufnahme.oberste_geschossdecke_gedaemmt ===
undefined &&
aufnahme.dachgeschoss_gedaemmt === undefined
) {
aufnahme.oberste_geschossdecke_gedaemmt = true;
aufnahme.dachgeschoss_gedaemmt = true;
}
}
const ausweisart: Enums.Ausweisart = "VerbrauchsausweisWohnen"
</script>
<Overlay bind:hidden={speichernOverlayHidden}>
<div class="bg-white w-full max-w-screen-sm py-8 px-8">
<AusweisGespeichertModule uid={ausweis.uid}></AusweisGespeichertModule>
</div>
</Overlay>
<Overlay bind:hidden={waitOverlayHidden}>
<p class="text-white font-semibold text-4xl">
Bitte warten sie, ihr Ausweis wird nun erstellt.
</p>
</Overlay>
<div id="skala" class="bg-white grid grid-cols-1 p-4
lg:grid-cols-2 lg:gap-x-6
">
<div id="performance-box" class="w-full box relative px-4 order-1 self-stretch grid grid-cols-1">
<PerformanceScore
bind:ausweis
bind:aufnahme={aufnahme}
bind:objekt={objekt}
{ausweisart}
/>
</div>
<div id="progress-box" class="w-full box relative px-4 py-3 text-center order-2 self-stretch">
<h1 class="text-secondary text-3xl m-0">Energiesausweis erstellen</h1>
<h2 class="text-primary text-xl">{ausweisart} {PRICES.VerbrauchsausweisWohnen[0]}</h2>
<Progressbar step1={'step'}/>
</div>
</div>
<form id="formInput-1" on:submit={ausweisAbschicken} name="ausweis" data-test="ausweis">
<div id="formular-box" class="formular-boxen ring-0">
<ButtonSpaeterHilfe {automatischAusfüllen} {spaeterWeitermachen} />
<!-- A Prüfung der Ausweisart -->
<Bereich bereich="A" title="Prüfung der Ausweisart">
<Ausweisart
bind:objekt={objekt}
bind:aufnahme={aufnahme}
bind:ausweis
{ausweisart}
/>
</Bereich>
<!-- B Eingabe der Gebäudeadresse - Angaben zu Wohnfläche, Keller und Dachgeschoss -->
<Bereich
bereich="B"
title="Eingabe der Gebäudeadresse - Angaben zu Wohnfläche, Keller und Dachgeschoss"
><GebaeudeDaten
bind:aufnahme
bind:objekt
{ausweisart}/></Bereich
>
<!-- C Eingabe von 3 zusammenhängenden Verbrauchsjahren -->
<Bereich
bereich="C"
title="Eingabe von 3 zusammenhängenden Verbrauchsjahren"
><Verbrauch
bind:objekt={objekt}
bind:aufnahme={aufnahme}
bind:ausweis
/></Bereich
>
<!-- D Eingabe Warmwasseranteil und Verwendung von alternativen Energieversorgungssystemen -->
<Bereich
bereich="D"
title="Eingabe Warmwasseranteil und Verwendung von alternativen Energieversorgungssystemen"
><Warmwasseranteil bind:ausweis /></Bereich
>
<!-- E Eingabe von Gebäudeteil, Lüftung, Kühlung und Leerstand -->
<Bereich
bereich="E"
title="Eingabe von Gebäudeteil, Lüftung, Kühlung und Leerstand"
><LueftungundLeerstand bind:aufnahme={aufnahme} /></Bereich
>
<!-- F Angaben zur Heizungsanlage -->
<Bereich bereich="F" title="Angaben zur Heizunganlage"
><SanierungszustandHeizungsanlage
bind:images={bilder}
bind:objekt={objekt}
bind:aufnahme={aufnahme}
bind:ausweis
/></Bereich
>
<!-- G Angaben zur Fenster, Dachfenster und Türen -->
<Bereich bereich="G" title="Angaben zu Fenster, Dachfenster und Türen"
><SanierungszustandFensterTueren
bind:images={bilder}
bind:objekt={objekt}
bind:aufnahme={aufnahme}
bind:ausweis
/></Bereich
>
<!-- H Angaben zur Wärmedammung -->
<Bereich bereich="H" title="Angaben zur Wärmedämmung"
><SanierungszustandWaermedammung
bind:images={bilder}
bind:objekt={objekt}
bind:aufnahme={aufnahme}
bind:ausweis
/></Bereich
>
<!-- I Gebäudebild und Energieausweis PDF Vorschau -->
<Bereich bereich="I" title="Gebäudebild und Energieausweis PDF Vorschau"
><AusweisPreviewContainer
bind:images={bilder}
bind:ausweis
bind:objekt={objekt}
bind:aufnahme
{ausweisart}
/></Bereich
>
</div>
<ButtonWeiterHilfe
bind:ausweis
bind:bilder
bind:user
bind:objekt
bind:aufnahme
ausweisart={Enums.Ausweisart.VerbrauchsausweisWohnen}
>
</ButtonWeiterHilfe>
</form>
<RawNotificationWrapper class="fixed left-8 bottom-8 max-w-[400px] flex flex-col gap-4 z-50">
{#each Object.entries($notifications) as [uid, notification] (uid)}
<RawNotification notification={{ ...notification, uid }}>
{@html notification.subtext}
</RawNotification>
{/each}
{#if auditBedarfsausweisBenoetigt(ausweis, aufnahme)}
<RawNotification
notification={{
message: "Bedarfsausweis benötigt!",
timeout: 0,
uid: "BEDARFSAUSWEIS",
dismissable: false,
type: "info",
}}
>
Sie benötigen einen Bedarfsausweis. <a href="/bedarfsausweis"
>Bitte führen Sie hier Ihre Eingabe für den Bedarfsausweis fort</a
>.
</RawNotification>
{/if}
{#if aufnahme.nutzflaeche && aufnahme.flaeche && aufnahme.flaeche === aufnahme.nutzflaeche}
<RawNotification
notification={{
message: "Plausibilitätsprüfung",
timeout: 0,
uid: "WOHNFLAECHE_GLEICH_GESAMTFLAECHE",
dismissable: true,
type: "warning",
selector: "input[name='nutzflaeche']"
}}
>
Die angegebene Nutzfläche ist gleich der angegebenen Wohnfläche, in den meisten Fällen sollte die Nutzfläche größer sein.
</RawNotification>
{/if}
{#if typeof aufnahme.einheiten === "number" && aufnahme.einheiten < 1}
<RawNotification
notification={{
message: "Plausibilitätsprüfung",
timeout: 0,
uid: "ANZAHL_EINHEITEN",
dismissable: false,
type: "warning",
selector: "input[name='einheiten']"
}}
>
Die Anzahl der Wohneinheiten muss mindestens 1 betragen.
</RawNotification>
{/if}
{#await auditPlzNichtErkannt(objekt) then result}
{#if result}
<RawNotification
notification={{
message: "Plausibilitätsprüfung",
timeout: 0,
uid: "PLZ_NICHT_ERKANNT",
dismissable: false,
type: "warning",
}}
>
Die Postleitzahl konnte nicht zugeordnet werden. Bitte prüfen
Sie die Eingabe. Sollte die Postleitzahl korrekt eingegeben
sein, werden wir den Ort händisch zuordnen.
</RawNotification>
{/if}
{/await}
{#if auditHeizungGebaeudeBaujahr(aufnahme)}
<RawNotification
notification={{
message: "Plausibilitätsprüfung",
timeout: 0,
uid: "HEIZUNG_GEBAEUDE_BAUJAHR",
dismissable: true,
onUserDismiss: () => {
hidden.add(AuditType.HEIZUNG_GEBAEUDE_BAUJAHR);
aufnahme = aufnahme;
},
type: "warning",
}}
>
Sie haben angegeben, dass ihre Heizung vor ihrem Gebäude konstruiert
wurde. Sind sie sich sicher, dass das stimmt?
</RawNotification>
{/if}
{#if auditHeizungJuengerDreiJahre(aufnahme)}
<RawNotification
notification={{
message: "Plausibilitätsprüfung",
timeout: 0,
uid: "HEIZUNG_JUENGER_DREI_JAHRE",
dismissable: true,
onUserDismiss: () => {
hidden.add(AuditType.HEIZUNG_JUENGER_DREI_JAHRE);
aufnahme = aufnahme;
},
type: "warning",
}}
>
Ihre Heizungsanlage ist jünger als 3 Jahre. Für den
Verbrauchsausweis müssen Sie mindestens 3 Verbrauchsjahre eingeben
die den aktuellen Stand des Gebäudes abbilden. Ein Verbrauchsausweis
ist daher nicht möglich. Bitte klicken Sie
<a href="/bedarfsausweis">hier</a> um zum Eingabeformular für den Bedarfsausweis
zu gelangen.
</RawNotification>
{/if}
{#if auditZeitraumAktuell(ausweis, objekt)}
<RawNotification
notification={{
message: "Plausibilitätsprüfung",
timeout: 0,
uid: "ZEITRAUM_AKTUELL",
dismissable: true,
onUserDismiss: () => {
hidden.add(AuditType.ZEITRAUM_AKTUELL);
objekt = objekt;
ausweis = ausweis
},
type: "warning",
}}
>
Die Verbrauchszeiträume sind nicht aktuell genug. Das Ende des
letzten Verbrauchszeitraumes darf nicht mehr als 18 Monate
zurückliegen. Ein Verbrauchsausweis ist mit diesen Zeiträumen daher
nicht möglich. Bitte klicken Sie <a href="/bedarfsausweis">hier</a> um
zum Eingabeformular für den Bedarfsausweis zu gelangen.
</RawNotification>
{/if}
{#await auditKlimaFaktoren(ausweis, objekt) then result}
{#if result}
<RawNotification
notification={{
message: "Plausibilitätsprüfung",
timeout: 0,
uid: "KLIMA_FAKTOREN",
dismissable: true,
onUserDismiss: () => {
hidden.add(AuditType.KLIMA_FAKTOREN);
objekt = objekt;
ausweis = ausweis;
},
type: "warning",
}}
>
Die Verbrauchszeiträume sind zu aktuell und es liegen noch keine
Klimafaktoren dazu vor. Bitte verschieben Sie die
Verbrauchszeiträume 1 Jahr nach hinten. Wenn das nicht möglich
ist, klicken Sie
<a href="/bedarfsausweis">hier</a> um zum Eingabeformular für den
Bedarfsausweis zu gelangen.
</RawNotification>
{/if}
{/await}
{#if auditWohnFlaeche(aufnahme)}
<RawNotification
notification={{
message: "Plausibilitätsprüfung",
timeout: 0,
uid: "WOHN_FLAECHE",
dismissable: true,
onUserDismiss: () => {
hidden.add(AuditType.WOHN_FLAECHE);
aufnahme = aufnahme;
},
type: "warning",
}}
>
Die Wohnfläche ist viel zu klein. Bitte überprüfen Sie Ihre Eingabe
nochmal und stellen sicher, daß sich Ihre Angaben auf das gesamte
Gebäude beziehen.
</RawNotification>
{/if}
{#if auditWarmWasser(ausweis)}
<RawNotification
notification={{
message: "Plausibilitätsprüfung",
timeout: 0,
uid: "WARM_WASSER",
dismissable: true,
onUserDismiss: () => {
hidden.add(AuditType.WARM_WASSER);
ausweis = ausweis;
},
type: "warning",
}}
>
Bitte überprüfen Sie nochmal die Höhe des Warmwasseranteils. Dieser
scheint nicht ganz im Rahmen zu liegen.
</RawNotification>
{/if}
{#if auditLeerStand(aufnahme)}
<RawNotification
notification={{
message: "Plausibilitätsprüfung",
timeout: 0,
uid: "LEER_STAND",
dismissable: false,
type: "warning",
}}
>
Bei Leerstand größer als 30% darf kein Verbrauchsausweis ausgestellt
werden. Bitte klicken Sie <a href="/bedarfsausweis">hier</a> um zum Eingabeformular
für den Bedarfsausweis zu gelangen.
</RawNotification>
{/if}
{@const abweichung = auditVerbrauchAbweichung(ausweis, aufnahme)}
{#if abweichung.length > 0}
<RawNotification
notification={{
message: "Plausibilitätsprüfung",
timeout: 0,
uid: "VERBRAUCH_ABWEICHUNG",
dismissable: true,
onUserDismiss: () => {
hidden.add(AuditType.VERBRAUCH_ABWEICHUNG);
objekt = objekt;
ausweis = ausweis;
},
type: "warning",
}}
>
Die Abweichung der Verbräuche zwischen Zeitraum {abweichung[0]} und {abweichung[1]} beträgt mehr als 30% und sie haben keinen Leerstand angegeben.
Sind sie sich sicher, dass das stimmt?
</RawNotification>
{/if}
{#await auditEndEnergie(ausweis, objekt, aufnahme) then result}
{#if result}
<RawNotification
notification={{
message: "Plausibilitätsprüfung",
timeout: 0,
uid: "END_ENERGIE",
dismissable: true,
onUserDismiss: () => {
hidden.add(AuditType.END_ENERGIE);
objekt = objekt;
},
type: "warning",
}}
>
Die Endenergie liegt außerhalb des normalen Rahmens. Bitte
nochmal überprüfen. Bei Passivhäusern oder ganz alten
unsanierten Gebäuden ist so eine Abweichung durchaus möglich.
</RawNotification>
{/if}
{/await}
{#if auditWohnflaecheGroesserGesamtflaeche(aufnahme)}
<RawNotification
notification={{
message: "Plausibilitätsprüfung",
timeout: 0,
uid: "WOHNFLAECHE_GROESSER_GESAMTFLAECHE",
dismissable: false,
type: "error",
selector: "input[name='nutzflaeche']"
}}
>
Die Wohnfläche darf nicht größer als die Nutzfläche sein.
</RawNotification>
{/if}
</RawNotificationWrapper>