Merge pull request #424 from IBCornelsen/main

getMain
This commit is contained in:
UMBENOMENA
2025-03-07 14:35:05 +01:00
committed by GitHub
58 changed files with 1667 additions and 1093 deletions

View File

@@ -40,6 +40,7 @@
"sharp": "^0.33.5",
"siema": "^1.5.1",
"soap": "^1.1.8",
"sqids": "^0.3.0",
"svelte": "^3.59.2",
"svelte-dialogs": "^1.2.2",
"svelte-preprocess": "^5.1.4",
@@ -2190,6 +2191,8 @@
"sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="],
"sqids": ["sqids@0.3.0", "", {}, "sha512-lOQK1ucVg+W6n3FhRwwSeUijxe93b51Bfz5PMRMihVf1iVkl82ePQG7V5vwrhzB11v0NtsR25PSZRGiSomJaJw=="],
"sshpk": ["sshpk@1.18.0", "", { "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", "bcrypt-pbkdf": "^1.0.0", "dashdash": "^1.12.0", "ecc-jsbn": "~0.1.1", "getpass": "^0.1.1", "jsbn": "~0.1.0", "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" }, "bin": { "sshpk-conv": "bin/sshpk-conv", "sshpk-sign": "bin/sshpk-sign", "sshpk-verify": "bin/sshpk-verify" } }, "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ=="],
"statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="],

View File

@@ -54,6 +54,7 @@
"sharp": "^0.33.5",
"siema": "^1.5.1",
"soap": "^1.1.8",
"sqids": "^0.3.0",
"svelte": "^3.59.2",
"svelte-dialogs": "^1.2.2",
"svelte-preprocess": "^5.1.4",

View File

@@ -5,6 +5,9 @@ export const createCaller = createCallerFactory({
"klimafaktoren": await import("../src/pages/api/klimafaktoren.ts"),
"postleitzahlen": await import("../src/pages/api/postleitzahlen.ts"),
"unterlage": await import("../src/pages/api/unterlage.ts"),
"ausweise": await import("../src/pages/api/ausweise/index.ts"),
"bedarfsausweis-wohnen/[uid]": await import("../src/pages/api/bedarfsausweis-wohnen/[uid].ts"),
"bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"),
"admin/ausstellen": await import("../src/pages/api/admin/ausstellen.ts"),
"admin/bestellbestaetigung": await import("../src/pages/api/admin/bestellbestaetigung.ts"),
"admin/erinnern": await import("../src/pages/api/admin/erinnern.ts"),
@@ -13,25 +16,22 @@ export const createCaller = createCallerFactory({
"admin/registriernummer": await import("../src/pages/api/admin/registriernummer.ts"),
"admin/stornieren": await import("../src/pages/api/admin/stornieren.ts"),
"aufnahme": await import("../src/pages/api/aufnahme/index.ts"),
"ausweise": await import("../src/pages/api/ausweise/index.ts"),
"bilder/[uid]": await import("../src/pages/api/bilder/[uid].ts"),
"auth/access-token": await import("../src/pages/api/auth/access-token.ts"),
"auth/forgot-password": await import("../src/pages/api/auth/forgot-password.ts"),
"auth/refresh-token": await import("../src/pages/api/auth/refresh-token.ts"),
"bedarfsausweis-wohnen/[uid]": await import("../src/pages/api/bedarfsausweis-wohnen/[uid].ts"),
"bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"),
"bilder/[uid]": await import("../src/pages/api/bilder/[uid].ts"),
"objekt": await import("../src/pages/api/objekt/index.ts"),
"geg-nachweis-gewerbe/[uid]": await import("../src/pages/api/geg-nachweis-gewerbe/[uid].ts"),
"geg-nachweis-gewerbe": await import("../src/pages/api/geg-nachweis-gewerbe/index.ts"),
"geg-nachweis-wohnen/[uid]": await import("../src/pages/api/geg-nachweis-wohnen/[uid].ts"),
"geg-nachweis-wohnen": await import("../src/pages/api/geg-nachweis-wohnen/index.ts"),
"objekt": await import("../src/pages/api/objekt/index.ts"),
"rechnung/anfordern": await import("../src/pages/api/rechnung/anfordern.ts"),
"rechnung": await import("../src/pages/api/rechnung/index.ts"),
"ticket": await import("../src/pages/api/ticket/index.ts"),
"user": await import("../src/pages/api/user/index.ts"),
"user/self": await import("../src/pages/api/user/self.ts"),
"verbrauchsausweis-gewerbe/[uid]": await import("../src/pages/api/verbrauchsausweis-gewerbe/[uid].ts"),
"verbrauchsausweis-gewerbe": await import("../src/pages/api/verbrauchsausweis-gewerbe/index.ts"),
"rechnung/anfordern": await import("../src/pages/api/rechnung/anfordern.ts"),
"rechnung": await import("../src/pages/api/rechnung/index.ts"),
"user": await import("../src/pages/api/user/index.ts"),
"user/self": await import("../src/pages/api/user/self.ts"),
"verbrauchsausweis-wohnen/[uid]": await import("../src/pages/api/verbrauchsausweis-wohnen/[uid].ts"),
"verbrauchsausweis-wohnen": await import("../src/pages/api/verbrauchsausweis-wohnen/index.ts"),
"webhooks/mollie": await import("../src/pages/api/webhooks/mollie.ts"),

View File

@@ -4,7 +4,7 @@ import { exclude } from "#lib/exclude.js";
import Cookies from "js-cookie";
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
import { AufnahmeClient, BedarfsausweisWohnenClient, BildClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisGewerbeClient, VerbrauchsausweisWohnenClient, } from "#components/Ausweis/types.js";
import { Enums } from "#lib/client/prisma";
import { Enums } from "#lib/client/prisma.js";
export async function ausweisSpeichern(
ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbeClient | BedarfsausweisWohnenClient,

View File

@@ -1,7 +1,22 @@
import { writable, Writable } from "svelte/store";
import { ZodEffects, ZodNullable, ZodOptional, ZodType } from "zod";
export function localStorageSync<T>(initial: T, name: string, modifier: (stored: any) => T = (stored) => JSON.parse(stored), reverseModifier: (value: T) => string = (value) => JSON.stringify(value)): Writable<T> {
/**
* Synchronisiert den ersten Writable in den zweiten.
*/
export function writableSync<T>(source: Writable<T>) {
let $val;
source.subscribe($ => $val = $)();
const target = writable<T>($val)
source.subscribe((value) => {
target.set(value);
})
return target;
}
export function localStorageSync<T>(initial: T, name: string, modifier: (stored: any) => T = (stored) => stored, reverseModifier: (value: T) => string = (value) => value as string): Writable<T> {
const stored = localStorage.getItem(name) as T
let value = initial;
if (stored) {
@@ -29,7 +44,7 @@ export function isZodInstanceOf<T extends ZodType<any>>(
if (schema instanceof ZodOptional || schema instanceof ZodNullable) {
return isZodInstanceOf(schema._def.innerType, targetType);
}else if (schema instanceof ZodEffects) {
return getZodBaseType(schema._def.schema)
return isZodInstanceOf(getZodBaseType(schema._def.schema), targetType)
}
return false;

View File

@@ -1,91 +0,0 @@
<script lang="ts">
import HelpLabel from "#components/labels/HelpLabel.svelte";
import Inputlabel from "#components/labels/InputLabel.svelte";
import { BenutzerClient } from "./types.js";
export let user: BenutzerClient;
</script>
<div id="ansprechpartner" class="bereich-box grid
grid-cols-1 gap-x-4 gap-y-8
sm:grid-cols-2 sm:gap-x-6 sm:gap-y-8
xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
">
<!-- Anrede * -->
<!--
<div class="input-standard order-3 md:order-3 xl:order-3">
<Inputlabel title="Anrede *"></Inputlabel>
<select name="anrede" bind:value={user.anrede}>
<option disabled selected>bitte auswählen</option>
<option value="Herr">Herr</option>
<option value="Frau">Frau</option>
</select>
</div> -->
<!-- Vorname * -->
<div class="input-standard order-1 md:order-1 xl:order-1">
<Inputlabel title="Vorname *"></Inputlabel>
<input
name="vorname"
type="text"
bind:value={user.vorname}
required
/>
<div class="help-label">
<HelpLabel>
Bitte Geben Sie hier den Vornamen des Ansprechpartners&nbsp;ein.
</HelpLabel>
</div>
</div>
<!-- Nachname * -->
<div class="input-standard order-2 md:order-2 xl:order-2">
<Inputlabel title="Nachname *"></Inputlabel>
<input
name="name"
type="text"
bind:value={user.name}
required
/>
<div class="help-label">
<HelpLabel>
Bitte Geben Sie hier den Nachnamen des Ansprechpartners&nbsp;ein.
</HelpLabel>
</div>
</div>
<!-- Telefon & Email * -->
<div class="input-standard order-3 md:order-3 xl:order-3">
<Inputlabel title="Telefonnummer *"></Inputlabel>
<input
name="telefon"
bind:value={user.telefon}
type="text"
/>
<div class="help-label">
<HelpLabel>
Bitte Geben Sie hier die Telefonnummer des Ansprechpartners&nbsp;ein.
</HelpLabel>
</div>
</div>
</div>

View File

@@ -48,7 +48,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
required
data-cy="ausstellgrund"
>
<option disabled selected value={null}>Bitte auswählen</option>
<option disabled selected value>Bitte auswählen</option>
{#each Object.entries(Enums.Ausstellgrund) as [name, ausstellgrund]}
<option value={ausstellgrund}>{name}</option>
{/each}
@@ -72,9 +72,9 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
required
bind:value={aufnahme.gebaeudetyp}
>
<option disabled selected value={null}>Bitte auswählen</option>
<option disabled selected value>Bitte auswählen</option>
{#if ausweisart==Enums.Ausweisart.VerbrauchsausweisWohnen || ausweisart === Enums.Ausweisart.GEGNachweisWohnen}
{#if ausweisart==Enums.Ausweisart.VerbrauchsausweisWohnen || ausweisart === Enums.Ausweisart.GEGNachweisWohnen || ausweisart === Enums.Ausweisart.BedarfsausweisWohnen}
<option value="Einfamilienhaus">Einfamilienhaus</option>
<option value="Freistehendes Einfamilienhaus">Freistehendes Einfamilienhaus</option>
<option value="Freistehendes Zweifamilienhaus">Freistehendes Zweifamilienhaus</option>
@@ -224,7 +224,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
required
bind:value={aufnahme.saniert}
>
<option disabled selected value={null}>Bitte auswählen</option>
<option disabled selected value>Bitte auswählen</option>
<option value={true}>saniert</option>
<option value={false}>unsaniert</option>
</select>

View File

@@ -17,12 +17,20 @@
export let objekt: ObjektClient;
export let aufnahme: AufnahmeClient;
export let ausweisart: Enums.Ausweisart
export let form: HTMLFormElement;
export let skala: HTMLDivElement;
export let showWeiter: boolean = true;
export let ausweistyp: AusweisTyp = Enums.AusweisTyp.Standard;
async function ausweisAbschicken() {
if (!form.checkValidity()) {
skala.classList.add("no-scroll")
form.reportValidity()
return
}
openWindowWithPost("/kundendaten", {
ausweis,
objekt,
@@ -170,7 +178,7 @@ grid-cols-1 gap-x-2 gap-y-4
<hr class="m-0" />
<button class="button" on:click={hilfeBestellen}>jetzt Hilfe bestellen</button>
<button class="button" type="button" on:click={hilfeBestellen}>jetzt Hilfe bestellen</button>
<button
class="button absolute top-2 right-2 w-[30px] h-[30px] text-sm p-0"

View File

@@ -1,10 +1,9 @@
<script lang="ts">
import HelpLabel from "#components/labels/HelpLabel.svelte";
import Inputlabel from "#components/labels/InputLabel.svelte";
import ZipSearch from "#components/PlzSuche.svelte";
import { Enums } from "#lib/client/prisma.js"
import { Enums } from "#lib/client/prisma.js";
import { AufnahmeClient, ObjektClient } from "./types.js";
export let aufnahme: AufnahmeClient;
@@ -13,15 +12,17 @@
export let ausweisart: Enums.Ausweisart;
</script>
<div id="gebaeudedaten" class="bereich-box grid
<div
id="gebaeudedaten"
class="bereich-box grid
grid-cols-1 gap-x-4 gap-y-8
sm:grid-cols-2 sm:gap-x-6 sm:gap-y-8
xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
">
"
>
<!-- Straße, Hausnummer * -->
<!-- Straße, Hausnummer * -->
<div class="input-standard order-1 md:order-1 xl:order-1">
<div class="input-standard order-1 md:order-1 xl:order-1">
<Inputlabel title="Straße, Hausnummer *"></Inputlabel>
<input
@@ -37,16 +38,18 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
<div class="help-label">
<HelpLabel>
Straße und Hausnummer des betrachteten Gebäudes. Die Angaen werden auf dem Energieausweis vermerkt.
Straße und Hausnummer des betrachteten Gebäudes. Die Angaen
werden auf dem Energieausweis vermerkt.
</HelpLabel>
</div>
</div>
</div>
<!-- PLZ / ORT -->
<!-- PLZ / ORT -->
<div class="grid grid-cols-[2fr_6fr] gap-x-4 order-2 md:order-2 xl:order-2 relative">
<div class="input-noHelp">
<div
class="grid grid-cols-[2fr_6fr] gap-x-4 order-2 md:order-2 xl:order-2 relative"
>
<div class="input-noHelp">
<Inputlabel title="PLZ *"></Inputlabel>
<ZipSearch
@@ -54,36 +57,34 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
bind:city={objekt.ort}
name="plz"
/>
</div>
</div>
<div class="input-standard">
<div class="input-standard">
<Inputlabel title="Ort *"></Inputlabel>
<input
name="ort"
data-test="ort"
readonly={false}
required
bind:value={objekt.ort}
type="text"
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie die PLZ des betrachteten Gebäudes ein, der Ort wird dann angezeigt und kann ausgewählt werden.
Die Angaen werden auf dem Energieausweis vermerkt.
Bitte geben Sie die PLZ des betrachteten Gebäudes ein, der
Ort wird dann angezeigt und kann ausgewählt werden. Die
Angaen werden auf dem Energieausweis vermerkt.
</HelpLabel>
</div>
</div>
</div>
</div>
{#if ausweisart == "VerbrauchsausweisWohnen"}
<!-- Wohnfläche m² * -->
</div>
{#if ausweisart=="VerbrauchsausweisWohnen"}
<!-- Wohnfläche m² * -->
<div class="input-standard order-3 md:order-3 xl:order-3">
<div class="input-standard order-3 md:order-3 xl:order-3">
<Inputlabel title="Wohnfläche m² *"></Inputlabel>
<input
@@ -106,13 +107,12 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
befinden. (Balkone, Terassen,etc.).
</HelpLabel>
</div>
</div>
</div>
{/if}
{/if}
<!-- Dachgeschoss *-->
<!-- Dachgeschoss *-->
<div class="input-standard order-4 md:order-2 xl:order-4">
<div class="input-standard order-4 md:order-2 xl:order-4">
<Inputlabel title="Dachgeschoss *"></Inputlabel>
<select
@@ -121,23 +121,27 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
bind:value={aufnahme.dachgeschoss}
required
>
<option disabled selected value={null}>Bitte auswählen</option>
<option value={Enums.Heizungsstatus.NICHT_VORHANDEN}>nicht vorhanden</option>
<option disabled selected value>Bitte auswählen</option>
<option value={Enums.Heizungsstatus.NICHT_VORHANDEN}
>nicht vorhanden</option
>
<option value={Enums.Heizungsstatus.UNBEHEIZT}>unbeheizt</option>
<option value={Enums.Heizungsstatus.BEHEIZT}>beheizt</option>
</select>
<div class="help-label">
<HelpLabel>
Bei Obergeschoss mit vorhandenen Dachschrägen oder ausgebautem Dachgeschoss beheizt auswählen.
Bei Kaltdächern oder unausgebautem Dachgeschoss bitte unbeheizt auswählen. Bei Flachdächern wird nicht vorhanden ausgewählt.
Bei Obergeschoss mit vorhandenen Dachschrägen oder ausgebautem
Dachgeschoss beheizt auswählen. Bei Kaltdächern oder
unausgebautem Dachgeschoss bitte unbeheizt auswählen. Bei
Flachdächern wird nicht vorhanden ausgewählt.
</HelpLabel>
</div>
</div>
</div>
<!-- Keller * -->
<!-- Keller * -->
<div class="input-standard order-4 md:order-2 xl:order-4">
<div class="input-standard order-4 md:order-2 xl:order-4">
<Inputlabel title="Keller *"></Inputlabel>
<select
@@ -146,25 +150,28 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
required
bind:value={aufnahme.keller}
>
<option disabled selected value={false}>Bitte auswählen</option>
<option value={Enums.Heizungsstatus.NICHT_VORHANDEN}>nicht vorhanden</option>
<option disabled selected value>Bitte auswählen</option>
<option value={Enums.Heizungsstatus.NICHT_VORHANDEN}
>nicht vorhanden</option
>
<option value={Enums.Heizungsstatus.UNBEHEIZT}>unbeheizt</option>
<option value={Enums.Heizungsstatus.BEHEIZT}>beheizt</option>
</select>
<div class="help-label">
<HelpLabel>
Diese Angabe hat folgenden Einfluss.<br>
<b>Keller beheizt:<br>Nutzfläche = Wohnfläche x 1,35.</b>
<b>Keller unbeheizt:<br>Nutzfläche = Wohnfläche x 1,2.</b>
Dies ist nur zulässig wenn die Nutzfläche unbekannt ist. Geben Sie diese daher unbedingt im nächsten Feld ein wenn bekannt.
Diese Angabe hat folgenden Einfluss.<br />
<b>Keller beheizt:<br />Nutzfläche = Wohnfläche x 1,35.</b>
<b>Keller unbeheizt:<br />Nutzfläche = Wohnfläche x 1,2.</b>
Dies ist nur zulässig wenn die Nutzfläche unbekannt ist. Geben Sie
diese daher unbedingt im nächsten Feld ein wenn bekannt.
</HelpLabel>
</div>
</div>
</div>
<!-- Gesamtfläche * -->
<!-- Gesamtfläche * -->
<div class="input-standard order-6 md:order-6 xl:order-6">
<div class="input-standard order-6 md:order-6 xl:order-6">
<Inputlabel title="Nutzfläche m² *"></Inputlabel>
<input
@@ -173,24 +180,19 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
maxlength="4"
type="number"
required
autocomplete="off"
data-rule-minlength="2"
data-msg-minlength="min. 2 Zeichen"
bind:value={aufnahme.nutzflaeche}
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie hier die beheizte Gesamtfläche in m² ein
(wenn bekannt). Dabei handelt es sich um die Wohnfläche +
weiterer Flächen innerhalb des Gebäudes (z.B. Fläche des
beheizten Kellers). <b>Diese Fläche wird dann im Energieausweis
als energetische Nutzfläche (An) ausgewiesen.</b>
Bitte geben Sie hier die beheizte Gesamtfläche in m² ein (wenn
bekannt). Dabei handelt es sich um die Wohnfläche + weiterer
Flächen innerhalb des Gebäudes (z.B. Fläche des beheizten
Kellers). <b
>Diese Fläche wird dann im Energieausweis als energetische
Nutzfläche (An) ausgewiesen.</b
>
</HelpLabel>
</div>
</div>
</div>
</div>

View File

@@ -1,25 +1,22 @@
<script lang="ts">
import HelpLabel from "#components/labels/HelpLabel.svelte";
import Inputlabel from "#components/labels/InputLabel.svelte";
import { AufnahmeClient } from "./types.js";
export let aufnahme: AufnahmeClient;
</script>
<div id="lueftungundleerstand" class="bereich-box grid
<div
id="lueftungundleerstand"
class="bereich-box grid
grid-cols-1 gap-x-4 gap-y-8
sm:grid-cols-2 sm:gap-x-6 sm:gap-y-8
xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
">
<!-- Gebäudeteil -->
<div class="grid grid-cols-2 gap-x-4 order-2 md:order-2 xl:order-2">
"
>
<!-- Gebäudeteil -->
<div class="grid grid-cols-2 gap-x-4 order-2 md:order-2 xl:order-2">
<div class="input-standard">
<Inputlabel title="Gebäudeteil *"></Inputlabel>
@@ -29,7 +26,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
bind:value={aufnahme.gebaeudeteil}
required
>
<option disabled selected value={null}>Bitte auswählen</option>
<option disabled selected value>Bitte auswählen</option>
<option value="Gesamtgebäude">Gesamtgebäude</option>
<option value="Wohnen">Wohnen</option>
</select>
@@ -46,7 +43,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
</div>
</div>
<div class="input-standard">
<div class="input-standard">
<Inputlabel title="Leerstand in %"></Inputlabel>
<input
@@ -55,7 +52,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
maxlength="2"
type="number"
bind:value={aufnahme.leerstand}
/>
/>
<div class="help-label">
<HelpLabel>
@@ -64,13 +61,12 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
wären dann ca. 11%.
</HelpLabel>
</div>
</div>
</div>
</div>
</div>
<!-- Lüftung -->
<!-- Lüftung -->
<div class="input-standard order-2 md:order-2 xl:order-2">
<div class="input-standard order-2 md:order-2 xl:order-2">
<Inputlabel title="Lüftung durch *"></Inputlabel>
<select
@@ -79,7 +75,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
required
bind:value={aufnahme.lueftung}
>
<option disabled selected value={null}>Bitte auswählen</option>
<option disabled selected value>Bitte auswählen</option>
<option value="Fensterlueftung">Fensterlüftung</option>
<option value="Schachtlueftung">Schachtlüftung</option>
<option value="LueftungsanlageOhneWaermerueckgewinnung"
@@ -88,22 +84,22 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
<option value="LueftungsanlageMitWaermerueckgewinnung"
>Lüftungsanlage mit Wärmerückgewinnung</option
>
</select>
</select>
<div class="help-label">
<HelpLabel>
Bitte geben Sie hier den Gebäudeteil ein. In den meisten
Fällen handelt es sich um das Gesamtgebäude. Sollte es sich
allerdings um ein Gebäude mit mehr als 10% Gewerbeanteil
Bitte geben Sie hier ein ob über die Fenster natürlich
belüftet wird oder über eine Lüftungsanlage.
Bitte geben Sie hier den Gebäudeteil ein. In den meisten Fällen
handelt es sich um das Gesamtgebäude. Sollte es sich allerdings
um ein Gebäude mit mehr als 10% Gewerbeanteil Bitte geben Sie
hier ein ob über die Fenster natürlich belüftet wird oder über
eine Lüftungsanlage.
</HelpLabel>
</div>
</div>
</div>
<!-- Kühlung -->
<!-- Kühlung -->
<div class="input-standard order-2 md:order-2 xl:order-2">
<div class="input-standard order-2 md:order-2 xl:order-2">
<Inputlabel title="Anlage Kühlung *"></Inputlabel>
<select
@@ -112,26 +108,16 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
required
bind:value={aufnahme.kuehlung}
>
<option disabled selected value={null}>Bitte auswählen</option>
<option disabled selected value>Bitte auswählen</option>
<option value="1">vorhanden</option>
<option value="0">nicht vorhanden</option>
</select>
<div class="help-label">
<HelpLabel>
Bitte geben Sie an ob das Gebäude im Sommer zusätzlich
gekühlt wird.
Bitte geben Sie an ob das Gebäude im Sommer zusätzlich gekühlt
wird.
</HelpLabel>
</div>
</div>
</div>
</div>

View File

@@ -1,297 +0,0 @@
<script lang="ts">
import HelpLabel from "#components/labels/HelpLabel.svelte";
import Inputlabel from "#components/labels/InputLabel.svelte";
import ZipSearch from "#components/PlzSuche.svelte";
import { BenutzerClient, RechnungClient } from "./types.js";
export let rechnung: Partial<RechnungClient>;
$: {
if (!rechnung.abweichende_versand_adresse) {
rechnung.versand_empfaenger = rechnung.empfaenger
rechnung.versand_ort = rechnung.ort
rechnung.versand_plz = rechnung.plz
rechnung.versand_strasse = rechnung.strasse
rechnung.versand_zusatzzeile = rechnung.zusatzzeile
}
}
</script>
<div
id="rechnungsadresse"
class="bereich-box grid
grid-cols-1 gap-x-4 gap-y-8
sm:grid-cols-2 sm:gap-x-6 sm:gap-y-8
xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
">
<!-- Empfänger * -->
<div class="input-standard order-1 md:order-1 xl:order-1">
<Inputlabel title="Rechnungs-Empfänger *"></Inputlabel>
<input
name="rechnung_empfaenger"
type="text"
bind:value={rechnung.empfaenger}
required
data-rule-maxlength="100"
data-msg-maxlength="max. 100 Zeichen"
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie den Empfänger ein, auf den die Rechnung
ausgestellt wird.
</HelpLabel>
</div>
</div>
<!-- Straße, Hausnummer * -->
<div class="input-standard order-2 md:order-2 xl:order-2">
<Inputlabel title="Straße, Hausnummer *"></Inputlabel>
<input
name="rechnung_strasse"
bind:value={rechnung.strasse}
type="text"
required
data-rule-maxlength="40"
data-msg-maxlength="max. 40 Zeichen"
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie die Strasse und Hausnummer, so wie Sie auf der
Rechnung erscheinen soll, ein.
</HelpLabel>
</div>
</div>
<!-- PLZ / ORT -->
<div class="grid grid-cols-[2fr_4fr] gap-x-4 order-3 md:order-3 xl:order-3">
<div class="input-noHelp">
<Inputlabel title="PLZ *"></Inputlabel>
<ZipSearch
name="rechnung_plz"
bind:zip={rechnung.plz}
bind:city={rechnung.ort}
/>
</div>
<div class="input-standard">
<Inputlabel title="Ort *"></Inputlabel>
<input
name="rechnung_ort"
type="text"
required
bind:value={rechnung.ort}
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie die PLZ des Ortes, so wie Sie auf der
Rechnung erscheinen soll, ein.
</HelpLabel>
</div>
</div>
</div>
<!-- Zusatzzeile -->
<div class="input-standard order-4 md:order-4 xl:order-4">
<Inputlabel title="Zusatzzeile"></Inputlabel>
<input
name="rechnung_zusatzzeile"
bind:value={rechnung.zusatzzeile}
type="text"
data-rule-maxlength="80"
data-msg-maxlength="max. 80 Zeichen"
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie, falls erforderlich, zusätzliche nformationen
ein.
</HelpLabel>
</div>
</div>
<!-- E-mail -->
<div class="input-standard order-5 md:order-5 xl:order-5">
<Inputlabel title="E-mail *"></Inputlabel>
<input name="rechnung_email" bind:value={rechnung.email} type="email" />
<div class="help-label">
<HelpLabel>
Bitte geben Sie die E-Mail Adresse des Rechnungsempfängers ein.
</HelpLabel>
</div>
</div>
<div class="sm:col-span-3 order-7 md:order-7 xl:order-7">
<div
class="grid grid-cols-[25px_max-content] items-center justify-items-start"
>
<input
id="abweichende_versand_adresse"
class="w-[15px] h-[15px]"
type="checkbox"
name="abweichende_versand_adresse"
bind:checked={rechnung.abweichende_versand_adresse}
/>
<label for="abweichende_versand_adresse" class="cursor-pointer"
>abweichende Versandadresse</label
>
</div>
</div>
{#if rechnung.abweichende_versand_adresse}
<!-- Versand Empfänger * -->
<div class="input-standard order-8 md:order-8 xl:order-8">
<Inputlabel title="Versand-Empfänger *"></Inputlabel>
<input
name="versand_empfaenger"
type="text"
readonly={!rechnung.abweichende_versand_adresse}
bind:value={rechnung.versand_empfaenger}
required
data-rule-maxlength="100"
data-msg-maxlength="max. 100 Zeichen"
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie den Namen des Versand-Empfängers ein.
</HelpLabel>
</div>
</div>
<!-- Versand Straße, Hausnummer * -->
<div class="input-standard order-9 md:order-9 xl:order-9">
<Inputlabel title="Straße, Hausnummer *"></Inputlabel>
<input
name="versand_strasse"
type="text"
readonly={!rechnung.abweichende_versand_adresse}
bind:value={rechnung.versand_strasse}
required
data-rule-maxlength="40"
data-msg-maxlength="max. 40 Zeichen"
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie die Versand-Empfänger Strasse und Hausnummer
ein, an die die Rechnung versandt wird.
</HelpLabel>
</div>
</div>
<!-- PLZ / ORT -->
<div
class="grid grid-cols-[2fr_4fr] gap-x-4 order-10 md:order-10 xl:order-10"
>
<div class="input-noHelp">
<Inputlabel title="PLZ *"></Inputlabel>
<ZipSearch
name="versand_plz"
readonly={!rechnung.abweichende_versand_adresse}
bind:zip={rechnung.versand_plz}
bind:city={rechnung.versand_ort}
/>
</div>
<div class="input-standard">
<Inputlabel title="Ort *"></Inputlabel>
<input
name="versand_ort"
type="text"
readonly
required
bind:value={rechnung.versand_ort}
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie die Versand-Empfänger PLZ des Ortes ein,
an den die Rechnung versandt wird.
</HelpLabel>
</div>
</div>
</div>
<!-- Zusatzzeile -->
<div class="input-standard order-11 md:order-11 xl:order-11">
<Inputlabel title="Zusatzzeile"></Inputlabel>
<input
name="versand_zusatzzeile"
type="text"
readonly={!rechnung.abweichende_versand_adresse}
bind:value={rechnung.versand_zusatzzeile}
data-rule-maxlength="80"
data-msg-maxlength="max. 80 Zeichen"
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie, falls erforderlich, zusätzliche
nformationen ein.
</HelpLabel>
</div>
</div>
<!-- E-mail -->
<div class="input-standard order-12 md:order-12 xl:order-12">
<Inputlabel title="E-mail *"></Inputlabel>
<input
name="rechnung_email"
bind:value={rechnung.email}
type="email"
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie die E-Mail Adresse des Versand-Empfängers
ein.
</HelpLabel>
</div>
</div>
<!-- Telefon
<div class="input-standard order-[13] md:order-[13] xl:order-[13]">
<Inputlabel title="Telefon *"></Inputlabel>
<input
name="rechnung_telefon"
bind:value={rechnung.telefon}
type="text"
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie die Telefonnummer des Versand-Empfängers ein.
</HelpLabel>
</div>
</div>
-->
{/if}
</div>

View File

@@ -236,7 +236,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
bind:value={aufnahme.brennstoff_1}
required
>
<option disabled selected >Bitte auswählen</option>
<option disabled selected value>Bitte auswählen</option>
{#each Object.keys(fuelMap) as fuel}
<option value={fuel}>{fuel}</option>
{/each}
@@ -276,7 +276,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
disabled={!aufnahme.brennstoff_1}
required
>
<option disabled selected>Bitte auswählen</option>
<option disabled selected value>Bitte auswählen</option>
{#each fuelMap.hasOwnProperty(aufnahme.brennstoff_1) ? fuelMap[aufnahme.brennstoff_1] : [] as unit}
<option value={unit}>{unit}</option>
{/each}

View File

@@ -1,32 +1,31 @@
<script lang="ts">
import HelpLabel from "#components/labels/HelpLabel.svelte";
import Inputlabel from "#components/labels/InputLabel.svelte";
import HelpLabel from "#components/labels/HelpLabel.svelte";
import Inputlabel from "#components/labels/InputLabel.svelte";
export let ausweis;
export let ausweis;
$: {
$: {
if (!ausweis.warmwasser_enthalten) {
ausweis.warmwasser_anteil_bekannt = false;
}
}
}
</script>
<div id="warmwasser" class="bereich-box grid
<div
id="warmwasser"
class="bereich-box grid
grid-cols-1 gap-x-4 gap-y-8
sm:grid-cols-2 sm:gap-x-6 sm:gap-y-8
xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
">
"
>
<div class="input-standard order-1 md:order-1 xl:order-1">
<Inputlabel title="Warmwasser im Verbrauch enthalten"></Inputlabel>
<div class="input-row items-center gap-2">
<div class="grid grid-cols-[25px_max-content] items-center justify-items-start">
<div
class="grid grid-cols-[25px_max-content] items-center justify-items-start"
>
<input
id="warmwasser_enthalten"
type="checkbox"
@@ -35,10 +34,14 @@ $: {
data-test="warmwasser_enthalten"
bind:checked={ausweis.warmwasser_enthalten}
/>
<label for="warmwasser_enthalten" class="cursor-pointer">Ja</label>
</div>
<label for="warmwasser_enthalten" class="cursor-pointer"
>Ja</label
>
</div>
<div class="grid grid-cols-[25px_max-content] items-center justify-items-start">
<div
class="grid grid-cols-[25px_max-content] items-center justify-items-start"
>
<input
id="warmwasser_anteil_bekannt"
type="checkbox"
@@ -47,24 +50,21 @@ $: {
data-test="warmwasser_anteil_bekannt"
bind:checked={ausweis.warmwasser_anteil_bekannt}
disabled={!ausweis.warmwasser_enthalten}
/>
<label for="warmwasser_anteil_bekannt" class="cursor-pointer">Anteil bekannt</label>
</div>
/>
<label for="warmwasser_anteil_bekannt" class="cursor-pointer"
>Anteil bekannt</label
>
</div>
</div>
</div>
<div class="help-label">
<HelpLabel>TEXT FEHLT</HelpLabel>
</div>
</div>
<div class="help-label">
<HelpLabel>
TEXT FEHLT
</HelpLabel>
</div>
<!-- % Anteil Warmwasser -->
</div>
<!-- % Anteil Warmwasser -->
<div class="input-standard order-2 md:order-2 xl:order-2">
<div class="input-standard order-2 md:order-2 xl:order-2">
<Inputlabel title="% Anteil Warmwasser"></Inputlabel>
<input
@@ -80,16 +80,15 @@ $: {
<div class="help-label">
<HelpLabel>
Wenn bekannt geben Sie den Anteil der Warmwasser-Versorgung
hier ein. Standardmäßig wird ein Anteil von 18% angenommen.
Wenn bekannt geben Sie den Anteil der Warmwasser-Versorgung hier
ein. Standardmäßig wird ein Anteil von 18% angenommen.
</HelpLabel>
</div>
</div>
</div>
<!--zusätzliche Heizquelle -->
<!--zusätzliche Heizquelle -->
<div class="input-standard order-3 md:order-3 xl:order-3">
<div class="input-standard order-3 md:order-3 xl:order-3">
<Inputlabel title="zusätzliche Heizquelle"></Inputlabel>
<input
@@ -106,22 +105,22 @@ $: {
<div class="help-label">
<HelpLabel>
Wenn bekannt geben Sie den Anteil der Warmwasser-Versorgung
von der zusätzlichen Heizquelle hier ein. Standardmäßig wird
ein Anteil von 18% angenommen.
Wenn bekannt geben Sie den Anteil der Warmwasser-Versorgung von
der zusätzlichen Heizquelle hier ein. Standardmäßig wird ein
Anteil von 18% angenommen.
</HelpLabel>
</div>
</div>
</div>
<!--Alternative Energieversorgungssyteme -->
<!--Alternative Energieversorgungssyteme -->
<div class="input-standard order-4 md:order-4 xl:order-4 sm:col-span-2 items-center">
<div
class="input-standard order-4 md:order-4 xl:order-4 sm:col-span-2 items-center"
>
<Inputlabel title="Alternative Energieversorgungssyteme"></Inputlabel>
<div class="input-row items-center gap-2 lg:gap-20 xl:gap-24">
<div class="grid grid-cols-[max-content_40px] gap-2 items-center">
<div class="input-row items-center gap-2 lg:gap-20 xl:gap-24">
<div class="grid grid-cols-[max-content_40px] gap-2 items-center">
<input
id="alternative_heizung"
type="checkbox"
@@ -130,12 +129,14 @@ $: {
bind:checked={ausweis.alternative_heizung}
value="Heizung"
/>
<label for="alternative_heizung" class="checkbox-inline cursor-pointer">Heizung</label>
</div>
<label
for="alternative_heizung"
class="checkbox-inline cursor-pointer">Heizung</label
>
</div>
<div class="grid grid-cols-[max-content_40px] gap-2 items-center">
<input
<div class="grid grid-cols-[max-content_40px] gap-2 items-center">
<input
id="alternative_warmwasser"
type="checkbox"
name="alternative_warmwasser"
@@ -143,61 +144,45 @@ $: {
bind:checked={ausweis.alternative_warmwasser}
value="Warmwasser"
/>
<label for="alternative_warmwasser" class="checkbox-inline cursor-pointer">Warmwasser</label>
</div>
<label
for="alternative_warmwasser"
class="checkbox-inline cursor-pointer">Warmwasser</label
>
</div>
<div class="grid grid-cols-[max-content_40px] gap-2 items-center">
<input
<div class="grid grid-cols-[max-content_40px] gap-2 items-center">
<input
id="alternative_lueftung"
type="checkbox"
name="alternative_lueftung"
data-test="alternative_lueftung"
bind:checked={ausweis.alternative_lueftung}
value="Lüftung"
/>
<label for="alternative_lueftung" class="checkbox-inline cursor-pointer">Lüftung</label>
</div>
/>
<label
for="alternative_lueftung"
class="checkbox-inline cursor-pointer">Lüftung</label
>
</div>
<div class="grid grid-cols-[max-content_40px] gap-2 items-center">
<input
<div class="grid grid-cols-[max-content_40px] gap-2 items-center">
<input
id="alternative_kuehlung"
type="checkbox"
name="alternative_kuehlung"
data-test="alternative_kuehlung"
bind:checked={ausweis.alternative_kuehlung}
value="Kühlung"
/>
<label for="alternative_kuehlung" class="checkbox-inline cursor-pointer">Kühlung</label>
/>
<label
for="alternative_kuehlung"
class="checkbox-inline cursor-pointer">Kühlung</label
>
</div>
</div>
<div class="help-label">
<HelpLabel></HelpLabel>
</div>
</div>
</div>
</div>
<div class="help-label">
<HelpLabel>
</HelpLabel>
</div>
</div>
</div>

View File

@@ -12,7 +12,7 @@ import {
VerbrauchsausweisGewerbe,
VerbrauchsausweisWohnen,
GEGNachweisWohnen,
} from "#lib/client/prisma";
} from "#lib/client/prisma.js";
import { z, ZodSchema } from "zod";
export type OmitKeys<T, K extends keyof T> = Omit<T, K>;
@@ -101,7 +101,7 @@ export type TicketClient = OmitKeys<Tickets, "bearbeiter_id" | "benutzer_id" | "
export type BenutzerClient = OmitKeys<Benutzer, "id" | "passwort">;
export type RechnungClient = OmitKeys<Rechnung, "aufnahme_id" | "benutzer_id" | "id">
export type RechnungClient = OmitKeys<Rechnung, "id">
export function ZodOverlap<T, S = z.ZodType<T, z.ZodTypeDef, T>>(arg: S): S {
return arg;

View File

@@ -1,14 +1,12 @@
<script lang="ts">
import { ripple } from "svelte-ripple-action";
import type { RippleOptions } from "svelte-ripple-action/dist/constants.js";
import { Home, Reader, EnvelopeClosed, Cube, Bell, Gear, LockClosed, HamburgerMenu, CaretDown } from "radix-svelte-icons"
import { Reader, Bell, Gear, LockClosed, CaretDown } from "radix-svelte-icons"
import NotificationProvider from "#components/NotificationProvider/NotificationProvider.svelte";
import DashboardNotification from "./DashboardNotification.svelte";
import { notifications } from "#components/NotificationProvider/shared.js";
import ThemeController from "#components/ThemeController.svelte";
import { BenutzerClient } from "#components/Ausweis/types.js";
import Cross1 from "radix-svelte-icons/src/lib/icons/Cross1.svelte";
import { flex } from "#lib/pdf/elements/index.js";
export let lightTheme: boolean;
export let benutzer: BenutzerClient;
@@ -21,7 +19,7 @@
let headerOpen = false;
</script>
<aside class:hidden={!headerOpen} class="fixed left-0 top-16 w-full h-[calc(100%-4rem)] flex z-30 md:relative md:h-auto md:w-auto md:top-0 md:flex bg-base-200 border-r border-r-base-300 flex-col py-4">
<aside class:hidden={!headerOpen} class="fixed left-0 top-16 w-full h-[calc(100%-4rem)] flex md:relative md:h-auto md:w-auto md:top-0 md:flex bg-base-200 border-r border-r-base-300 flex-col py-4">
<div class="flex flex-row items-center px-4">
@@ -33,6 +31,7 @@
<div class="text-base-content font-semibold text-left flex"
>{benutzer.vorname} {benutzer.name}</div>
<div class="text-base-content text-sm flex">{benutzer.email}</div>
<a href="/auth/logout" class="text-xs">Logout</a>
</div>
</div>

View File

@@ -47,7 +47,7 @@
<div use:clickOutside={() => {
hideZipDropdown = true;
}}>
}} class="relative">
<input
name={name}
@@ -55,6 +55,7 @@
type="text"
required
readonly={readonly}
{...$$restProps}
bind:value={zip}
on:input={fetchZipCodeInformation}
on:focus={() => {

View File

@@ -6,25 +6,28 @@
async function showTicketPopup() {
const success = await dialogs.modal(TicketPopup);
if (success) {
console.log(success);
if (success === true) {
dialogs.alert({
title: "Ticket erstellt",
text: "Ihr Support Ticket wurde erfolgreich erstellt. Wir werden uns schnellstmöglich um ihre Angelegenheit kümmern. Vielen Dank für ihre Geduld.",
dismissButtonText: "Schließen",
dismissButtonClass: "btn btn-primary",
dialogClass: "modal-box",
dismissButtonClass: "button",
dialogClass: "bg-white rounded-lg p-4",
headerClass: "bg-base-100 text-center",
titleClass: "text-base-content text-xl font-medium",
dividerClass: "hidden",
footerClass: "bg-base-100 justify-center gap-4 mt-4",
});
} else {
} else if (success === false) {
dialogs.alert({
title: "Ticket erstellen fehlgeschlagen",
text: "Leider ist beim erstellen des Tickets ein Fehler aufgetreten. Bitte versuchen sie es später erneut oder kontaktieren sie uns direkt per email unter info@ib-cornelsen.de.",
dismissButtonText: "Schließen",
dismissButtonClass: "btn btn-error",
dialogClass: "modal-box",
dismissButtonClass: "button",
dialogClass: "bg-white rounded-lg p-4",
headerClass: "bg-base-100 text-center",
titleClass: "text-base-content text-xl font-medium",
dividerClass: "hidden",
@@ -35,7 +38,7 @@
</script>
<button
class="btn btn-primary fixed bottom-0 right-8 rounded-b-none rounded-t-xl w-48 h-12 text-xl hover:h-14 transition-all"
class="fixed bottom-0 right-8 rounded-b-none rounded-t-xl w-48 h-12 text-xl hover:h-14 transition-all bg-primary text-primary-content font-bold"
on:click={showTicketPopup}
>Support Ticket</button
>

View File

@@ -44,9 +44,7 @@
<h4>Kategorie *</h4>
<select class="select select-bordered" bind:value={category}>
<option value={null} disabled selected>Bitte Auswählen</option>
<option value="Verständnisproblem">Verständnisproblem</option>
<option value="Technischer Fehler">Technischer Fehler</option>
<option value="Feature anfordern">Feature anfordern</option>
<option value="Fehlende Funktionalität"
>Fehlende Funktionalität</option
>

View File

@@ -13,7 +13,6 @@
["persönlicher&nbsp;Support",true, true],
["Dokumentensichtung<br>",false, true],
["telefonische Beratung<br>persönlicher Energieberater",false, true],
["Vor-Ort Termin",false, true],
]
@@ -72,7 +71,7 @@
.bullet{@apply text-[0.75rem] sm:text-[1rem] md:text-[1.25rem]}
.bullet:nth-child(even){@apply bg-blue-100/40}
.bullet:nth-child(2){@apply !border-t-[6px]}
.bullet:nth-child(9){@apply !border-b-[6px]}
.bullet:nth-child(8){@apply !border-b-[6px]}
.check {
@apply text-[1.25rem] sm:text-[1.5rem] font-bold text-green-700;

View File

@@ -10,13 +10,13 @@
["Originalausweis als&nbsp;PDF per&nbsp;<span class='text-nowrap'>E-Mail</span><br>Originalausweis per&nbsp;Post (zubuchbar)",true, true, true],
["Bearbeitung innerhalb 24&nbsp;Stunden<br>Selbsteingabe",true, true, false],
["Same&nbsp;day&nbsp;service (zubuchbar)",true, true, false],
["Fotoupload<br>Dokumentenupload (Pläne, Bauunterlagen)",true, true, true],
["Fotoupload",true, true, true],
["automatische Vorprüfung<br>Live&nbsp;Vorschau direkt bei&nbsp;Eingabe<br>Live&nbsp;Vorschauausweis vorab<br>Vorschauausweis per&nbsp;E-Mail<br>dynamische&nbsp;Eingabehilfe",true, true, false],
["Prüfanmerkungen per&nbsp;<span class='text-nowrap'>E-Mail</span>",true, true, false],
["persönlicher&nbsp;Support",true, true, true],
["persönlicher&nbsp;Support",false, true, true],
["telefonische&nbsp;Beratung<br>persönlicher&nbsp;Energieberater",false, true, true],
["Vor-Ort Termin",false, false, true],
]
["Dokumentenupload (Pläne, Bauunterlagen)",false, false, true],
["Eingabe durch Dipl.&nbsp;Ing.",false, false, true],]
</script>
@@ -76,7 +76,7 @@
.bullet{@apply text-[0.75rem] sm:text-[1rem] md:text-[1.25rem]}
.bullet:nth-child(even){@apply bg-blue-100/40}
.bullet:nth-child(2){@apply !border-t-[6px]}
.bullet:nth-child(11){@apply !border-b-[6px]}
.bullet:nth-child(12){@apply !border-b-[6px]}
.check {
@apply text-[1.25rem] sm:text-[1.5rem] font-bold text-green-700;

View File

@@ -13,8 +13,10 @@
["Fotoupload",true, true, true],
["automatische Vorprüfung<br>Live&nbsp;Vorschau direkt bei&nbsp;Eingabe<br>Live&nbsp;Vorschauausweis vorab<br>Vorschauausweis per&nbsp;E-Mail<br>dynamische&nbsp;Eingabehilfe",true, true, false],
["Prüfanmerkungen per&nbsp;<span class='text-nowrap'>E-Mail</span>",true, true, false],
["persönlicher&nbsp;Support",true, true, true],
["telefonische&nbsp;Beratung<br>persönlicher&nbsp;Energieberater",false, true, true]
["persönlicher&nbsp;Support",false, true, true],
["telefonische&nbsp;Beratung<br>persönlicher&nbsp;Energieberater",false, true, true],
["Dokumentenupload (Verbrauchsabrechnungen)",false, false, true],
["Eingabe durch Dipl.&nbsp;Ing.",false, false, true],
]
@@ -76,7 +78,7 @@
.bullet{@apply text-[0.75rem] sm:text-[1rem] md:text-[1.25rem]}
.bullet:nth-child(even){@apply bg-blue-100/40}
.bullet:nth-child(2){@apply !border-t-[6px]}
.bullet:nth-child(10){@apply !border-b-[6px]}
.bullet:nth-child(12){@apply !border-b-[6px]}
.check {
@apply text-[1.25rem] sm:text-[1.5rem] font-bold text-green-700;

View File

@@ -15,7 +15,9 @@ bullets = [
["automatische Vorprüfung<br>Live&nbsp;Vorschau direkt bei&nbsp;Eingabe<br>Live&nbsp;Vorschauausweis vorab<br>Vorschauausweis per&nbsp;E-Mail<br>dynamische&nbsp;Eingabehilfe",true, true, false],
["Prüfanmerkungen per&nbsp;<span class='text-nowrap'>E-Mail</span>",true, true, false],
["persönlicher&nbsp;Support",false, true, true],
["telefonische&nbsp;Beratung<br>persönlicher&nbsp;Energieberater",false, true, true]
["telefonische&nbsp;Beratung<br>persönlicher&nbsp;Energieberater",false, true, true],
["Dokumentenupload (Verbrauchsabrechnungen)",false, false, true],
["Eingabe durch Dipl.&nbsp;Ing.",false, false, true],
]
@@ -77,7 +79,7 @@ bullets = [
.bullet{@apply text-[0.75rem] sm:text-[1rem] md:text-[1.25rem]}
.bullet:nth-child(even){@apply bg-blue-100/40}
.bullet:nth-child(2){@apply !border-t-[6px]}
.bullet:nth-child(10){@apply !border-b-[6px]}
.bullet:nth-child(12){@apply !border-b-[6px]}
.check {
@apply text-[1.25rem] sm:text-[1.5rem] font-bold text-green-700;

View File

@@ -1,5 +1,12 @@
---
import { BenutzerClient } from "#components/Ausweis/types";
import HeaderLogin from "#components/design/header/HeaderLogin.svelte";
export type Props = {
user: BenutzerClient | null
}
const { user } = Astro.props;
---
<header id="header" class="hidden sm:block">
@@ -63,7 +70,7 @@ lg:px-0 lg:gap-x-4">
<div class="w-full justify-self-center">
<HeaderLogin client:load />
<HeaderLogin {user} client:load />
</div>

View File

@@ -1,8 +1,11 @@
<script lang="ts">
import { BenutzerClient } from "#components/Ausweis/types.js";
import { loginClient } from "#lib/login.js";
import { CrossCircled } from "radix-svelte-icons";
import { fade } from "svelte/transition";
export let user: BenutzerClient | null;
let email: string;
let passwort: string;
@@ -24,6 +27,7 @@
id="card-login"
class="rounded-none lg:rounded-lg lg:card lg:box lg:ring-2 border-t-2 lg:border-none border-gray-500/50 ring-gray-500/50 xs:px-2 md:px-4 py-2"
>
{#if !user}
<form on:submit={login}>
<div class="grid grid-cols-[1fr] xs:grid-cols-[2fr_2fr_1fr] gap-2">
<input
@@ -82,6 +86,19 @@
</div>
</div>
</form>
{:else}
<div class="flex flex-row gap-4 items-center">
<img src={user.profilbild || "/images/profile-placeholder.png"} class="w-14 h-14 rounded-full border">
<div class="flex flex-col">
<span class="text-base font-bold">{user.vorname} {user.name}</span>
<span class="text-black text-opacity-50">{user.email}</span>
<div class="flex flex-row gap-4">
<a href="/dashboard" class="text-sm">Dashboard</a>
<a href="/auth/logout" class="text-sm">Ausloggen</a>
</div>
</div>
</div>
{/if}
</div>
<style lang="postcss">

View File

@@ -1,23 +1,23 @@
export * from "./anteilshaber"
export * from "./apirequests"
export * from "./aufnahme"
export * from "./bedarfsausweisgewerbe"
export * from "./bedarfsausweiswohnen"
export * from "./benutzer"
export * from "./bild"
export * from "./event"
export * from "./gegeinpreisung"
export * from "./gegnachweisgewerbe"
export * from "./gegnachweiswohnen"
export * from "./klimafaktoren"
export * from "./objekt"
export * from "./postleitzahlen"
export * from "./rechnung"
export * from "./refreshtokens"
export * from "./tickets"
export * from "./unterlage"
export * from "./verbrauchsausweisgewerbe"
export * from "./verbrauchsausweiswohnen"
export * from "./documenttemplates"
export * from "./documenttypes"
export * from "./tokens"
export * from "./anteilshaber.js"
export * from "./apirequests.js"
export * from "./aufnahme.js"
export * from "./bedarfsausweisgewerbe.js"
export * from "./bedarfsausweiswohnen.js"
export * from "./benutzer.js"
export * from "./bild.js"
export * from "./event.js"
export * from "./gegeinpreisung.js"
export * from "./gegnachweisgewerbe.js"
export * from "./gegnachweiswohnen.js"
export * from "./klimafaktoren.js"
export * from "./objekt.js"
export * from "./postleitzahlen.js"
export * from "./rechnung.js"
export * from "./refreshtokens.js"
export * from "./tickets.js"
export * from "./unterlage.js"
export * from "./verbrauchsausweisgewerbe.js"
export * from "./verbrauchsausweiswohnen.js"
export * from "./documenttemplates.js"
export * from "./documenttypes.js"
export * from "./tokens.js"

View File

@@ -6,6 +6,9 @@ import Header from "#components/design/header/Header.astro";
import Footer from "#components/design/footer/Footer.astro";
import SidebarLeft from "#components/design/sidebars/SidebarLeft.astro";
import { NotificationWrapper } from "@ibcornelsen/ui";
import { getCurrentUser } from "#lib/server/user";
const user = await getCurrentUser(Astro)
export interface Props {
title: string;
@@ -19,6 +22,20 @@ const { title } = Astro.props;
const skala = document.getElementById("skala");
if (skala?.classList.contains("no-scroll")) {
if (skala) {
skala.classList.remove(
"2xl:fixed",
"2xl:py-4",
"2xl:top-0",
"2xl:z-20"
);
skala.classList.add("w-full");
skala.style.borderBottom = "none";
}
document
.getElementById("formInput-1")
?.classList.remove("2xl:mt-[370px]");
return;
}
@@ -115,7 +132,7 @@ const { title } = Astro.props;
</head>
<body>
<Header />
<Header {user} />
<main
class="w-full p-0 grid

View File

@@ -1,7 +1,7 @@
---
// import "svelte-ripple-action/ripple.css";
import "../style/global.css";
import "../../svelte-dialogs.config";
import "../../svelte-dialogs.config.js";
import DashboardSidebar from "../components/Dashboard/DashboardSidebar.svelte";
import { validateAccessTokenServer } from "#server/lib/validateAccessToken";
import { BenutzerClient } from "#components/Ausweis/types";

View File

@@ -6,6 +6,10 @@ import Footer from "#components/design/footer/Footer.astro";
import SidebarLeft from "#components/design/sidebars/SidebarLeft.astro";
import SidebarRight from "#components/design/sidebars/SidebarRight.astro";
import { NotificationWrapper } from "@ibcornelsen/ui";
import TicketButton from "#components/Tickets/TicketButton.svelte";
import { getCurrentUser } from "#lib/server/user";
const user = await getCurrentUser(Astro);
export interface Props {
title: string;
@@ -94,7 +98,7 @@ window.addEventListener("scroll", (event) => {
<body>
<Header />
<Header {user} />
<main id="main"
class="w-full p-0 grid
@@ -119,6 +123,7 @@ window.addEventListener("scroll", (event) => {
<Footer />
<NotificationWrapper client:load />
<TicketButton client:load></TicketButton>
</body>
</html>

View File

@@ -2,7 +2,7 @@ import { funktionEinfacheInterpolation } from "./funktionEinfacheInterpolation.j
export function funktionAufwandszahlVerteilungWohnungsLueftungThermischT47(System: string, NettoGrundFlaeche: number) {
if (NettoGrundFlaeche < 100) { NettoGrundFlaeche = 100; }
if (NettoGrundFlaeche > 5000) { NettoGrundFlaeche = 5000; }
if (NettoGrundFlaeche > 500) { NettoGrundFlaeche = 500; }
const dataset = [
{SuchSpalte: ["Nettogrundfläche"], DatenSpalte: [100, 150, 200, 300, 400, 500]},

View File

@@ -9,7 +9,7 @@ export function funktionEinfacheInterpolation(gegebenerWert: number, gegebeneZei
const systemValues = dataset.find(item => item.SuchSpalte.includes(gegebeneZeile))?.DatenSpalte;
if (!systemValues) {
throw new Error(`Leitungssystem ${gegebeneZeile} nicht gefunden`);
throw new Error(`${gegebeneZeile} nicht gefunden`);
}
for (let i = 0; i < SuchZeile.length - 1; i++) {
@@ -18,7 +18,7 @@ export function funktionEinfacheInterpolation(gegebenerWert: number, gegebeneZei
}
}
throw new Error(`LeitungsLaenge ${gegebenerWert} außerhalb des Bereichs`);
throw new Error(`${gegebenerWert} außerhalb des Bereichs`);
}
const interpolierterWert = getInterpolatedValue(gegebenerWert, gegebeneZeile);

View File

@@ -0,0 +1,35 @@
import { funktionEinfacheInterpolation } from "./funktionEinfacheInterpolation.js";
import { A13BerechnungRechnerischeLaufzeitHeizung } from "#lib/Berechnungen/BedarfsausweisWohnen/A13BerechnungRechnerischeLaufzeitHeizung.js";
export function funktionHilfsenergiePufferspeicherHeizungLadepumpeT53(LeistungHilfsenergie: string, NettoGrundFlaeche: number) {
const resultRechnerischeLaufzeitHeizung = A13BerechnungRechnerischeLaufzeitHeizung();
const rechnerischeLaufzeitGesamt = resultRechnerischeLaufzeitHeizung.rechnerischeLaufzeitGesamt;
let HilfsenergiePufferspeicherHeizungLadepumpe = 0;
if (NettoGrundFlaeche < 50) { NettoGrundFlaeche = 50; }
const dataset = [
{SuchSpalte: ["Nettogrundfläche"], DatenSpalte: [50, 100, 150, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 2000, 3000, 4000, 5000, 5000]},
{SuchSpalte: ["Pumpenleistung"], DatenSpalte: [42, 43, 45, 46, 49, 52, 55, 58, 61, 64, 67, 70, 85, 100, 130, 160, 190]},
{SuchSpalte: ["Hilfsenergieaufwand"], DatenSpalte: [208, 215, 223, 230, 245, 260, 275, 290, 305, 320, 335, 350, 425, 500, 650, 800, 950]}
];
if (NettoGrundFlaeche > 5000) {
if (LeistungHilfsenergie === "Hilfsenergieaufwand") {
HilfsenergiePufferspeicherHeizungLadepumpe = (0.15 * NettoGrundFlaeche + 200) * (rechnerischeLaufzeitGesamt / 5000);
return HilfsenergiePufferspeicherHeizungLadepumpe;
}
else {
NettoGrundFlaeche = 5000;
HilfsenergiePufferspeicherHeizungLadepumpe = funktionEinfacheInterpolation(NettoGrundFlaeche, LeistungHilfsenergie, dataset);
return HilfsenergiePufferspeicherHeizungLadepumpe;
}
}
else {
HilfsenergiePufferspeicherHeizungLadepumpe = funktionEinfacheInterpolation(NettoGrundFlaeche, LeistungHilfsenergie, dataset);
return HilfsenergiePufferspeicherHeizungLadepumpe;
}
}

View File

@@ -0,0 +1,17 @@
import { funktionEinfacheInterpolation } from "./funktionEinfacheInterpolation.js";
export function funktionHilfsenergieTrinkwarmWasserSpeicherLadepumpeT58(LeistungHilfsenergie: string, SpeicherVolumen: number) {
if (SpeicherVolumen < 5) { SpeicherVolumen = 5; }
if (SpeicherVolumen > 1500) { SpeicherVolumen = 1500; }
const dataset = [
{SuchSpalte: ["Nettogrundfläche"], DatenSpalte: [5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 150, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1500]},
{SuchSpalte: ["Pumpenleistung"], DatenSpalte: [44, 44, 44, 45, 45, 45, 46, 46, 47, 47, 48, 50, 54, 61, 70, 80, 91, 103, 115, 128, 141, 218]},
{SuchSpalte: ["Hilfsenergieaufwand"], DatenSpalte: [386, 387, 389, 391, 394, 397, 401, 404, 409, 413, 417, 442, 471, 538, 616, 702, 797, 898, 1006, 1120, 1239, 1910]}
];
const HilfsenergieTrinkwarmWasserSpeicherLadepumpe = funktionEinfacheInterpolation(SpeicherVolumen, LeistungHilfsenergie, dataset);
return HilfsenergieTrinkwarmWasserSpeicherLadepumpe;
}

View File

@@ -0,0 +1,34 @@
import { funktionEinfacheInterpolation } from "./funktionEinfacheInterpolation.js";
import { linearInterpolation } from "js-interpolate";
export function funktionHilfsenergieVentilatorenWohnungsLueftungT48(System: string, NennLeistung: number) {
if (NennLeistung < 10) { NennLeistung = 10; }
let HilfsenergieVentilatorenWohnungsLueftung = 0;
const dataset = [
{SuchSpalte: ["NennLeistung"], DatenSpalte: [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]},
{SuchSpalte: ["Hilfsenergie Ventilatoren"], DatenSpalte: [88, 175, 263, 350, 438, 525, 613, 701, 788, 876]}
];
if (NennLeistung > 100) {
HilfsenergieVentilatorenWohnungsLueftung =linearInterpolation([{
x: 10,
y: 88
}, {
x: 100,
y: 876
}], NennLeistung);
}
else
{
HilfsenergieVentilatorenWohnungsLueftung = funktionEinfacheInterpolation(NennLeistung, System, dataset);
}
return HilfsenergieVentilatorenWohnungsLueftung;
}
console.log(funktionHilfsenergieVentilatorenWohnungsLueftungT48("Hilfsenergie Ventilatoren", 120)); // 438

View File

@@ -0,0 +1,43 @@
import { funktionEinfacheInterpolation } from "./funktionEinfacheInterpolation.js";
export function funktionKennzahlenErzeugungTrinkwarmWasserSolarT59T62(System: string, NettoGrundFlaeche: number) {
if (NettoGrundFlaeche < 100) { NettoGrundFlaeche = 100; }
if (NettoGrundFlaeche > 5000) { NettoGrundFlaeche = 5000; }
const dataset = [
{SuchSpalte: ["Nettogrundfläche"], DatenSpalte: [100, 150, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 2000, 3000, 4000, 5000]},
{SuchSpalte: ["Speichernenninhalt - Solar - Verteilung im unbeheizten Bereich - mit Zirkulation"], DatenSpalte: [185, 241, 298, 414, 530, 648, 766, 885, 1005, 1124, 1244, 2454, 3677, 4904, 6130]},
{SuchSpalte: ["Speichernenninhalt - Bereitschaft - Verteilung im unbeheizten Bereich - mit Zirkulation"], DatenSpalte: [173, 191, 209, 244, 277, 308, 338, 366, 393, 418, 443, 653, 825, 975, 1109]},
{SuchSpalte: ["Speichernenninhalt - Gesammt - Verteilung im unbeheizten Bereich - mit Zirkulation"], DatenSpalte: [359, 432, 507, 658, 808, 956, 1104, 1251, 1397, 1542, 1686, 3107, 4502, 5878, 7239]},
{SuchSpalte: ["Standard Flachkollektoren - Aperturfläche - Verteilung im unbeheizten Bereich - mit Zirkulation"], DatenSpalte: [4.80, 6.26, 7.73, 10.72, 13.74, 16.79, 19.85, 22.94, 26.03, 29.12, 32.23, 63.60, 95.29, 127.07, 158.84]},
{SuchSpalte: ["Standard Flachkollektoren - Energieertrag - Verteilung im unbeheizten Bereich - mit Zirkulation"], DatenSpalte: [1851, 2412, 2981, 4133, 5298, 6473, 7653, 8843, 10036, 11225, 12426, 24519, 36733, 48985, 61232]},
{SuchSpalte: ["Standard Röhrenkollektoren - Aperturfläche - Verteilung im unbeheizten Bereich - mit Zirkulation"], DatenSpalte: [2.91, 3.79, 4.68, 6.49, 8.32, 10.16, 12.01, 13.88, 15.76, 17.62, 19.51, 38.49, 57.67, 76.90, 96.12]},
{SuchSpalte: ["Standard Röhrenkollektoren - Energieertrag - Verteilung im unbeheizten Bereich - mit Zirkulation"], DatenSpalte: [1986, 2587, 3198, 4433, 5683, 6943, 8209, 9486, 10766, 12041, 13329, 26301, 39403, 52546, 65682]},
{SuchSpalte: ["Speichernenninhalt - Solar - Verteilung im beheizten Bereich - mit Zirkulation"], DatenSpalte: [173, 229, 286, 400, 516, 633, 750, 869, 989, 1107, 1227, 2433, 3650, 4870, 6099]},
{SuchSpalte: ["Speichernenninhalt - Bereitschaft - Verteilung im beheizten Bereich - mit Zirkulation"], DatenSpalte: [162, 181, 200, 236, 270, 301, 331, 359, 386, 412, 436, 647, 819, 968, 1104]},
{SuchSpalte: ["Speichernenninhalt - Gesammt - Verteilung im beheizten Bereich - mit Zirkulation"], DatenSpalte: [335, 410, 485, 637, 786, 934, 1081, 1229, 1375, 1519, 1663, 3081, 4469, 5838, 7202]},
{SuchSpalte: ["Standard Flachkollektoren - Aperturfläche - Verteilung im beheizten Bereich - mit Zirkulation"], DatenSpalte: [4.48, 5.94, 7.40, 10.38, 13.38, 16.40, 19.44, 22.53, 25.62, 28.70, 31.79, 63.06, 94.58, 126.21, 158.04]},
{SuchSpalte: ["Standard Flachkollektoren - Energieertrag - Verteilung im beheizten Bereich - mit Zirkulation"], DatenSpalte: [1729, 2290, 2853, 4000, 5158, 6324, 7495, 8684, 9876, 11063, 12254, 24310, 36462, 48653, 60923]},
{SuchSpalte: ["Standard Röhrenkollektoren - Aperturfläche - Verteilung im beheizten Bereich - mit Zirkulation"], DatenSpalte: [2.71, 3.59, 4.48, 6.28, 8.10, 9.93, 11.77, 13.63, 15.50, 17.37, 19.24, 38.16, 57.24, 76.38, 95.64]},
{SuchSpalte: ["Standard Röhrenkollektoren - Energieertrag - Verteilung im beheizten Bereich - mit Zirkulation"], DatenSpalte: [1854, 2456, 3061, 4291, 5533, 6784, 8040, 9315, 10594, 11867, 13144, 26076, 39112, 52189, 65351]},
{SuchSpalte: ["Speichernenninhalt - Solar - Verteilung im unbeheizten Bereich - ohne Zirkulation"], DatenSpalte: [130, 174, 219, 308, 396, 486, 575, 664, 752, 841, 930, 1819, 2703, 3592, 4486]},
{SuchSpalte: ["Speichernenninhalt - Bereitschaft - Verteilung im unbeheizten Bereich - ohne Zirkulation"], DatenSpalte: [121, 137, 153, 182, 207, 231, 253, 274, 294, 313, 331, 484, 606, 714, 812]},
{SuchSpalte: ["Speichernenninhalt - Gesammt - Verteilung im unbeheizten Bereich - ohne Zirkulation"], DatenSpalte: [251, 312, 372, 489, 604, 717, 828, 938, 1046, 1154, 1261, 2303, 3309, 4306, 5298]},
{SuchSpalte: ["Standard Flachkollektoren - Aperturfläche - Verteilung im unbeheizten Bereich - ohne Zirkulation"], DatenSpalte: [3.36, 4.51, 5.67, 7.98, 10.27, 12.59, 14.89, 17.20, 19.49, 21.79, 24.11, 47.14, 70.04, 93.08, 116.25]},
{SuchSpalte: ["Standard Flachkollektoren - Energieertrag - Verteilung im unbeheizten Bereich - ohne Zirkulation"], DatenSpalte: [1296, 1740, 2186, 3075, 3961, 4853, 5740, 6629, 7512, 8400, 9293, 18172, 27001, 35881, 44815]},
{SuchSpalte: ["Standard Röhrenkollektoren - Aperturfläche - Verteilung im unbeheizten Bereich - ohne Zirkulation"], DatenSpalte: [2.04, 2.73, 3.43, 4.83, 6.22, 7.62, 9.01, 10.41, 11.79, 13.19, 14.59, 28.53, 42.39, 56.33, 70.35]},
{SuchSpalte: ["Standard Röhrenkollektoren - Energieertrag - Verteilung im unbeheizten Bereich - ohne Zirkulation"], DatenSpalte: [1391, 1866, 2345, 3299, 4249, 5205, 6157, 7111, 8057, 9010, 9969, 19493, 28964, 38489, 48073]},
{SuchSpalte: ["Speichernenninhalt - Solar - Verteilung im beheizten Bereich - ohne Zirkulation"], DatenSpalte: [121, 165, 209, 298, 387, 475, 565, 653, 741, 830, 919, 1806, 2687, 3574, 4464]},
{SuchSpalte: ["Speichernenninhalt - Bereitschaft - Verteilung im beheizten Bereich - ohne Zirkulation"], DatenSpalte: [113, 130, 146, 176, 202, 226, 249, 270, 290, 309, 327, 480, 603, 710, 808]},
{SuchSpalte: ["Speichernenninhalt - Gesammt - Verteilung im beheizten Bereich - ohne Zirkulation"], DatenSpalte: [234, 295, 356, 474, 590, 702, 814, 922, 1031, 1139, 1246, 2286, 3290, 4284, 5272]},
{SuchSpalte: ["Standard Flachkollektoren - Aperturfläche - Verteilung im beheizten Bereich - ohne Zirkulation"], DatenSpalte: [3.13, 4.28, 5.43, 7.72, 10.03, 12.32, 14.63, 16.91, 19.21, 21.52, 23.81, 46.79, 69.64, 92.62, 115.68]},
{SuchSpalte: ["Standard Flachkollektoren - Energieertrag - Verteilung im beheizten Bereich - ohne Zirkulation"], DatenSpalte: [1206, 1649, 2092, 2977, 3868, 4750, 5641, 6519, 7406, 8296, 9178, 18037, 26847, 35703, 44593]},
{SuchSpalte: ["Standard Röhrenkollektoren - Aperturfläche - Verteilung im beheizten Bereich - ohne Zirkulation"], DatenSpalte: [1.89, 2.59, 3.28, 4.67, 6.07, 7.46, 8.56, 10.23, 11.63, 13.02, 14.41, 28.31, 42.15, 56.05, 70.01]},
{SuchSpalte: ["Standard Röhrenkollektoren - Energieertrag - Verteilung im beheizten Bereich - ohne Zirkulation"], DatenSpalte: [1293, 1768, 2244, 3194, 4149, 5095, 6051, 6993, 7944, 8899, 9845, 19348, 28798, 38298, 47835]}
];
const KennzahlenErzeugungTrinkwarmWasserSolar = funktionEinfacheInterpolation(NettoGrundFlaeche, System, dataset);
return KennzahlenErzeugungTrinkwarmWasserSolar;
}

View File

@@ -0,0 +1,120 @@
import { funktionEinfacheInterpolation } from "./funktionEinfacheInterpolation.js";
export function funktionKorrekturfaktorErzeugungTrinkwarmWasserSolarT63T65(System: string, Orientierung: number, BaujahrKollektoren: number) {
if (BaujahrKollektoren > 1998) {
const dataset = [
{SuchSpalte: ["Orientierung"], DatenSpalte: [0, 30, 45, 60, 90]},
{SuchSpalte: ["Standard Flachkollektoren - Nord-West - Faktor Aperturfläche"], DatenSpalte: [0.984,1.147,1.598,2.200,4.156]},
{SuchSpalte: ["Standard Flachkollektoren - Nord-West - Faktor Energieertrag"], DatenSpalte: [0.885,0.867,0.892,0.899,0.837]},
{SuchSpalte: ["Standard Flachkollektoren - West - Faktor Aperturfläche"], DatenSpalte: [0.984,1.184,1.417,1.700,2.968]},
{SuchSpalte: ["Standard Flachkollektoren - West - Faktor Energieertrag"], DatenSpalte: [0.885,0.961,0.987,0.962,0.808]},
{SuchSpalte: ["Standard Flachkollektoren - Süd-West - Faktor Aperturfläche"], DatenSpalte: [0.984,1.045,1.140,1.299,2.429]},
{SuchSpalte: ["Standard Flachkollektoren - Süd-West - Faktor Energieertrag"], DatenSpalte: [0.885,0.973,0.997,0.979,0.912]},
{SuchSpalte: ["Standard Flachkollektoren - Süd - Faktor Aperturfläche"], DatenSpalte: [0.984,0.917,1.000,1.120,1.989]},
{SuchSpalte: ["Standard Flachkollektoren - Süd - Faktor Energieertrag"], DatenSpalte: [0.885,0.943,1.000,0.990,0.890]},
{SuchSpalte: ["Standard Flachkollektoren - Süd-Ost - Faktor Aperturfläche"], DatenSpalte: [0.984,0.935,1.033,1.140,1.948]},
{SuchSpalte: ["Standard Flachkollektoren - Süd-Ost - Faktor Energieertrag"], DatenSpalte: [0.885,0.923,0.989,0.963,0.881]},
{SuchSpalte: ["Standard Flachkollektoren - Ost - Faktor Aperturfläche"], DatenSpalte: [0.984,0.995,1.120,1.355,2.562]},
{SuchSpalte: ["Standard Flachkollektoren - Ost - Faktor Energieertrag"], DatenSpalte: [0.885,0.803,0.806,0.819,0.799]},
{SuchSpalte: ["Standard Flachkollektoren - Nord-Ost - Faktor Aperturfläche"], DatenSpalte: [0.984,1.107,1.450,1.989,4.349]},
{SuchSpalte: ["Standard Flachkollektoren - Nord-Ost - Faktor Energieertrag"], DatenSpalte: [0.885,0.852,0.844,0.864,0.911]},
{SuchSpalte: ["Standard Flachkollektoren - Nord - Faktor Aperturfläche"], DatenSpalte: [0.984,1.161,1.731,3.463,4.675]},
{SuchSpalte: ["Standard Flachkollektoren - Nord - Faktor Energieertrag"], DatenSpalte: [0.885,0.950,0.957,1.215,0.892]},
{SuchSpalte: ["Standard Röhrenkollektoren - Nord-West - Faktor Aperturfläche"], DatenSpalte: [0.936,1.112,1.367,1.679,2.255]},
{SuchSpalte: ["Standard Röhrenkollektoren - Nord-West - Faktor Energieertrag"], DatenSpalte: [0.84,0.777,0.785,0.964,0.740]},
{SuchSpalte: ["Standard Röhrenkollektoren - West - Faktor Aperturfläche"], DatenSpalte: [0.936,1.044,1.162,1.332,1.956]},
{SuchSpalte: ["Standard Röhrenkollektoren - West - Faktor Energieertrag"], DatenSpalte: [0.84,0.854,0.866,0.882,0.970]},
{SuchSpalte: ["Standard Röhrenkollektoren - Süd-West - Faktor Aperturfläche"], DatenSpalte: [0.936,0.969,0.981,1.104,1.746]},
{SuchSpalte: ["Standard Röhrenkollektoren - Süd-West - Faktor Energieertrag"], DatenSpalte: [0.84,0.891,0.917,1.009,0.928]},
{SuchSpalte: ["Standard Röhrenkollektoren - Süd - Faktor Aperturfläche"], DatenSpalte: [0.936,0.912,1.000,1.100,1.601]},
{SuchSpalte: ["Standard Röhrenkollektoren - Süd - Faktor Energieertrag"], DatenSpalte: [0.84,0.928,1.000,1.019,1.023]},
{SuchSpalte: ["Standard Röhrenkollektoren - Süd-Ost - Faktor Aperturfläche"], DatenSpalte: [0.936,0.914,0.981,1.104,1.507]},
{SuchSpalte: ["Standard Röhrenkollektoren - Süd-Ost - Faktor Energieertrag"], DatenSpalte: [0.84,0.903,0.951,0.991,0.872]},
{SuchSpalte: ["Standard Röhrenkollektoren - Ost - Faktor Aperturfläche"], DatenSpalte: [0.936,0.963,1.037,1.166,1.661]},
{SuchSpalte: ["Standard Röhrenkollektoren - Ost - Faktor Energieertrag"], DatenSpalte: [0.84,0.824,0.829,0.844,0.861]},
{SuchSpalte: ["Standard Röhrenkollektoren - Nord-Ost - Faktor Aperturfläche"], DatenSpalte: [0.936,1.066,1.261,1.515,2.255]},
{SuchSpalte: ["Standard Röhrenkollektoren - Nord-Ost - Faktor Energieertrag"], DatenSpalte: [0.84,0.781,0.776,0.788,0.816]},
{SuchSpalte: ["Standard Röhrenkollektoren - Nord - Faktor Aperturfläche"], DatenSpalte: [0.936,1.124,1.437,2.146,3.396]},
{SuchSpalte: ["Standard Röhrenkollektoren - Nord - Faktor Energieertrag"], DatenSpalte: [0.84,0.766,0.745,0.835,0.937]}
];
}
else if (BaujahrKollektoren > 1989 && BaujahrKollektoren < 1999) {
const dataset = [
{SuchSpalte: ["Orientierung"], DatenSpalte: [0, 30, 45, 60, 90]},
{SuchSpalte: ["Standard Flachkollektoren - Nord-West - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Nord-West - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - West - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - West - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Süd-West - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Süd-West - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Süd - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Süd - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Süd-Ost - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Süd-Ost - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Ost - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Ost - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Nord-Ost - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Nord-Ost - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Nord - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Nord - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Nord-West - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Nord-West - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - West - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - West - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Süd-West - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Süd-West - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Süd - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Süd - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Süd-Ost - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Süd-Ost - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Ost - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Ost - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Nord-Ost - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Nord-Ost - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Nord - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Nord - Faktor Energieertrag"], DatenSpalte: []}
];
}
else {
const dataset = [
{SuchSpalte: ["Orientierung"], DatenSpalte: [0, 30, 45, 60, 90]},
{SuchSpalte: ["Standard Flachkollektoren - Nord-West - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Nord-West - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - West - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - West - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Süd-West - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Süd-West - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Süd - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Süd - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Süd-Ost - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Süd-Ost - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Ost - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Ost - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Nord-Ost - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Nord-Ost - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Nord - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Flachkollektoren - Nord - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Nord-West - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Nord-West - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - West - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - West - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Süd-West - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Süd-West - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Süd - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Süd - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Süd-Ost - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Süd-Ost - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Ost - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Ost - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Nord-Ost - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Nord-Ost - Faktor Energieertrag"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Nord - Faktor Aperturfläche"], DatenSpalte: []},
{SuchSpalte: ["Standard Röhrenkollektoren - Nord - Faktor Energieertrag"], DatenSpalte: []}
];
}
const KorrekturfaktorErzeugungTrinkwarmWasserSolar = funktionEinfacheInterpolation(Orientierung, System, dataset);
return KorrekturfaktorErzeugungTrinkwarmWasserSolar;
}

View File

@@ -0,0 +1,21 @@
import { funktionEinfacheInterpolation } from "./funktionEinfacheInterpolation.js";
export function funktionKorrekturfaktorMittlereBelastungPufferspeicherHeizungT52(System: string, MittlereBelastung: number) {
if (MittlereBelastung < 0.1) { MittlereBelastung = 0.1; }
if (MittlereBelastung > 1) { MittlereBelastung = 1; }
const dataset = [
{SuchSpalte: ["Mittlere Belastung"], DatenSpalte: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]},
{SuchSpalte: ["Speicher im unbeheizten Bereich - Auslegungsvorlauftemperatur 90°C"], DatenSpalte: [0.43, 0.73, 1.00, 1.25, 1.48, 1.70, 1.92, 2.13, 2.33, 2.52]},
{SuchSpalte: ["Speicher im unbeheizten Bereich - Auslegungsvorlauftemperatur 70°C"], DatenSpalte: [0.43, 0.73, 1.00, 1.25, 1.48, 1.70, 1.92, 2.13, 2.33, 2.52]},
{SuchSpalte: ["Speicher im unbeheizten Bereich - Auslegungsvorlauftemperatur 55°C"], DatenSpalte: [0.43, 0.73, 1.00, 1.25, 1.48, 1.70, 1.92, 2.13, 2.33, 2.52]},
{SuchSpalte: ["Speicher im unbeheizten Bereich - Auslegungsvorlauftemperatur 35°C"], DatenSpalte: [0.37, 0.69, 1.00, 1.30, 1.59, 1.88, 2.16, 2.44, 2.71, 2.99]},
{SuchSpalte: ["Speicher im beheizten Bereich - Auslegungsvorlauftemperatur 90°C"], DatenSpalte: [0.56, 0.79, 1.00, 1.19, 1.37, 1.54, 1.71, 1.87, 2.03, 2.18]},
{SuchSpalte: ["Speicher im beheizten Bereich - Auslegungsvorlauftemperatur 70°C"], DatenSpalte: [0.60, 0.81, 1.00, 1.17, 1.34, 1.50, 1.65, 1.80, 1.94, 2.08]},
{SuchSpalte: ["Speicher im beheizten Bereich - Auslegungsvorlauftemperatur 55°C"], DatenSpalte: [0.64, 0.83, 1.00, 1.16, 1.30, 1.44, 1.58, 1.71, 1.84, 1.96]},
{SuchSpalte: ["Speicher im beheizten Bereich - Auslegungsvorlauftemperatur 35°C"], DatenSpalte: [0.78, 0.89, 1.00, 1.11, 1.21, 1.31, 1.41, 1.51, 1.61, 1.71]}
];
const KorrekturfaktorMittlereBelastungPufferspeicherHeizung = funktionEinfacheInterpolation(MittlereBelastung, System, dataset);
return KorrekturfaktorMittlereBelastungPufferspeicherHeizung;
}

View File

@@ -0,0 +1,38 @@
import { funktionEinfacheInterpolation } from "./funktionEinfacheInterpolation.js";
export function funktionVolumenPufferspeicherHeizungT49(Leistung: number, WaermeErzeuger: string) {
let VolumenPufferspeicherHeizung = 0;
let dataset: any = [];
if (WaermeErzeuger === "Wärmepumpe") {
if (Leistung < 4.2) { Leistung = 4.2; }
dataset = [
{SuchSpalte: ["Wärmepumpe"], DatenSpalte: [4.2, 7.9, 10.5, 21.1, 31.6, 42.1, 52.6, 63.2, 73.7, 84.2, 94.7, 105.3, 115.8, 126.3, 136.8, 147.4, 157.9]},
{SuchSpalte: ["Volumen Pufferspeicher"], DatenSpalte: [40, 75, 100, 200, 200, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500]}
];
}
else if (WaermeErzeuger === "Biomasse") {
if (Leistung < 2) { Leistung = 2; }
dataset = [
{SuchSpalte: ["Biomasse"], DatenSpalte: [2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0, 26.0, 28.0, 30.0]},
{SuchSpalte: ["Volumen Pufferspeicher"], DatenSpalte: [100, 200, 200, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500]}
];
}
if (Leistung > 157.9)
{
if (WaermeErzeuger === "Wärmepumpe") { VolumenPufferspeicherHeizung = 9.5 * Leistung; }
else if (WaermeErzeuger === "Biomasse") { VolumenPufferspeicherHeizung = 50 * Leistung; }
}
else
{
VolumenPufferspeicherHeizung = funktionEinfacheInterpolation(Leistung, "Volumen Pufferspeicher", dataset);
}
return VolumenPufferspeicherHeizung;
}

View File

@@ -0,0 +1,24 @@
import { funktionEinfacheInterpolation } from "./funktionEinfacheInterpolation.js";
import { A9BerechnungNutzenergiebedarfTrinkwarmwasser } from "#lib/Berechnungen/BedarfsausweisWohnen/A9BerechnungNutzenergiebedarfTrinkwarmwasser.js";
export function funktionVolumenSpeicherTrinkwarmWasserT54(System: string, NettoGrundFlaeche: number) {
const result = A9BerechnungNutzenergiebedarfTrinkwarmwasser();
const flaechenBezogenerWaermebedarf = result.flaechenBezogenerWaermebedarf;
if (NettoGrundFlaeche < 50) { NettoGrundFlaeche = 50; }
if (NettoGrundFlaeche > 5000) { NettoGrundFlaeche = 5000; }
const dataset = [
{SuchSpalte: ["Nettogrundfläche"], DatenSpalte: [50, 100, 150, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 2000, 3000, 4000, 5000]},
{SuchSpalte: ["indirekt beheizt"], DatenSpalte: [78, 116, 147, 173, 219, 259, 295, 328, 359, 388, 415, 441, 660, 834, 986, 1122]},
{SuchSpalte: ["elektrisch beheizt - Nachtaufladung"], DatenSpalte: [110, 165, 208, 246, 312, 368, 419, 466, 509, 550, 589, 627, 937, 1185, 1400, 1593]},
{SuchSpalte: ["elektrisch beheizt - ständige Aufladung"], DatenSpalte: [52, 78, 98, 116, 147, 174, 198, 220, 240, 260, 278, 296, 442, 559, 661, 752]},
{SuchSpalte: ["gasbeheizt"], DatenSpalte: [52, 78, 98, 116, 147, 174, 198, 220, 240, 260, 278, 296, 442, 559, 661, 752]}
];
const VolumenSpeicherTrinkwarmWasser = funktionEinfacheInterpolation(NettoGrundFlaeche, System, dataset);
const VolumenSpeicherTrinkwarmWasserAngepasst = VolumenSpeicherTrinkwarmWasser * (flaechenBezogenerWaermebedarf/12.5);
return VolumenSpeicherTrinkwarmWasserAngepasst;
}

View File

@@ -0,0 +1,21 @@
import { funktionEinfacheInterpolation } from "./funktionEinfacheInterpolation.js";
export function funktionWaermeVerlustePufferspeicherHeizungT50T51(System: string, SpeicherVolumen: number) {
if (SpeicherVolumen < 40) { SpeicherVolumen = 40; }
if (SpeicherVolumen > 1500) { SpeicherVolumen = 1500; }
const dataset = [
{SuchSpalte: ["Speichervolumen"], DatenSpalte: [40, 75, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500]},
{SuchSpalte: ["Speicher im unbeheizten Bereich - Auslegungsvorlauftemperatur 90°C"], DatenSpalte: [220, 276, 308, 407, 483, 547, 603, 654, 701, 745, 786, 825, 862, 897, 931, 964, 995]},
{SuchSpalte: ["Speicher im unbeheizten Bereich - Auslegungsvorlauftemperatur 70°C"], DatenSpalte: [170, 213, 238, 315, 374, 424, 467, 507, 543, 577, 609, 639, 668, 695, 721, 747, 771]},
{SuchSpalte: ["Speicher im unbeheizten Bereich - Auslegungsvorlauftemperatur 55°C"], DatenSpalte: [135, 169, 189, 250, 296, 336, 370, 402, 431, 457, 483, 506, 529, 551, 571, 591, 611]},
{SuchSpalte: ["Speicher im unbeheizten Bereich - Auslegungsvorlauftemperatur 35°C"], DatenSpalte: [77, 97, 108, 143, 170, 193, 213, 231, 247, 263, 277, 291, 304, 316, 328, 340, 351]},
{SuchSpalte: ["Speicher im beheizten Bereich - Auslegungsvorlauftemperatur 90°C"], DatenSpalte: [170, 213, 238, 314, 373, 422, 466, 506, 542, 576, 607, 637, 666, 693, 719, 744, 769]},
{SuchSpalte: ["Speicher im beheizten Bereich - Auslegungsvorlauftemperatur 70°C"], DatenSpalte: [120, 151, 168, 223, 264, 299, 330, 358, 384, 408, 430, 451, 472, 491, 509, 527, 544]},
{SuchSpalte: ["Speicher im beheizten Bereich - Auslegungsvorlauftemperatur 55°C"], DatenSpalte: [85, 106, 119, 157, 186, 211, 233, 253, 271, 288, 304, 319, 333, 347, 360, 372, 384]},
{SuchSpalte: ["Speicher im beheizten Bereich - Auslegungsvorlauftemperatur 35°C"], DatenSpalte: [27, 34, 38, 51, 60, 68, 75, 82, 88, 93, 98, 103, 108, 112, 116, 121, 124]}
];
const WaermeVerlustePufferspeicherHeizung = funktionEinfacheInterpolation(SpeicherVolumen, System, dataset);
return WaermeVerlustePufferspeicherHeizung;
}

View File

@@ -0,0 +1,39 @@
import { funktionEinfacheInterpolation } from "./funktionEinfacheInterpolation.js";
export function funktionWaermeVerlusteTrinkwarmwasserSpeicherT55T56(System: string, SpeicherVolumen: number, BaujahrTrinkwarmwasserSpeicher: number) {
if (SpeicherVolumen < 5) { SpeicherVolumen = 5; }
if (SpeicherVolumen > 1500) { SpeicherVolumen = 1500; }
const dataset = [
{SuchSpalte: ["Speichervolumen"], DatenSpalte: [5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 150, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1500]},
{SuchSpalte: ["indirekt beheizt - Aufstellort beheizt - mit Zirkulation"], DatenSpalte: [296, 313, 341, 366, 389, 411, 432, 452, 471, 490, 509, 595, 675, 823, 960, 1088, 1211, 1330, 1444, 1555, 1664, 1888]},
{SuchSpalte: ["indirekt beheizt - Aufstellort beheizt - ohne Zirkulation"], DatenSpalte: [254, 268, 292, 314, 334, 352, 370, 387, 404, 420, 436, 510, 579, 705, 822, 933, 1038, 1140, 1238, 1333, 1426, 1619]},
{SuchSpalte: ["indirekt beheizt - Aufstellort unbeheizt - mit Zirkulation"], DatenSpalte: [355, 375, 409, 439, 467, 493, 518, 542, 566, 588, 611, 714, 810, 988, 1151, 1306, 1454, 1595, 1733, 1866, 1996, 2266]},
{SuchSpalte: ["indirekt beheizt - Aufstellort unbeheizt - ohne Zirkulation"], DatenSpalte: [313, 331, 360, 387, 411, 435, 457, 478, 498, 518, 538, 629, 714, 870, 1014, 1150, 1280, 1406, 1527, 1644, 1759, 1996]},
{SuchSpalte: ["elektrisch beheizt - Aufstellort beheizt - mit Zirkulation"], DatenSpalte: [116, 133, 162, 188, 212, 235, 257, 279, 299, 320, 339, 434, 521, 685, 838, 983, 1123, 1258, 1389, 1517, 1643, 2236]},
{SuchSpalte: ["elektrisch beheizt - Aufstellort beheizt - ohne Zirkulation"], DatenSpalte: [102, 116, 142, 164, 185, 206, 225, 244, 262, 280, 297, 379, 456, 599, 733, 861, 983, 1101, 1216, 1328, 1437, 1956]},
{SuchSpalte: ["elektrisch beheizt - Aufstellort unbeheizt - mit Zirkulation"], DatenSpalte: [137, 156, 190, 221, 249, 276, 302, 327, 352, 376, 399, 509, 613, 805, 985, 1156, 1320, 1478, 1633, 1783, 1930, 2627]},
{SuchSpalte: ["elektrisch beheizt - Aufstellort unbeheizt - ohne Zirkulation"], DatenSpalte: [122, 140, 170, 197, 223, 247, 270, 293, 314, 336, 356, 455, 547, 719, 880, 1033, 1179, 1321, 1459, 1593, 1725, 2348]},
{SuchSpalte: ["gasbeheizt - Aufstellort beheizt - mit Zirkulation"], DatenSpalte: [712, 784, 938, 1100, 1268, 1441, 1616, 1795, 1976, 2160, 2346, 3300, 4286, 6331, 8446, 10615, 12828, 15079, 17362, 19674, 22011, 34019]},
{SuchSpalte: ["gasbeheizt - Aufstellort beheizt - ohne Zirkulation"], DatenSpalte: [623, 686, 821, 963, 1110, 1260, 1414, 1571, 1729, 1890, 2053, 2887, 3750, 5539, 7390, 9288, 11225, 13194, 15192, 17215, 19260, 29766]},
{SuchSpalte: ["gasbeheizt - Aufstellort unbeheizt - mit Zirkulation"], DatenSpalte: [836, 921, 1102, 1293, 1490, 1693, 1899, 2109, 2322, 2538, 2756, 3877, 5036, 7439, 9924, 12473, 15073, 17718, 20400, 23117, 25864, 39972]},
{SuchSpalte: ["gasbeheizt - Aufstellort unbeheizt - ohne Zirkulation"], DatenSpalte: [747, 823, 985, 1155, 1332, 1513, 1697, 1885, 2075, 2268, 2463, 3465, 4501, 6647, 8868, 11146, 13470, 15833, 18230, 20657, 23112, 35720]}
];
const WaermeVerlusteTrinkwarmwasserSpeicher = funktionEinfacheInterpolation(SpeicherVolumen, System, dataset);
let WaermeVerlusteTrinkwarmwasserSpeicherAngepasst = 0;
if (System.includes("gasbeheizt")) {
WaermeVerlusteTrinkwarmwasserSpeicherAngepasst = WaermeVerlusteTrinkwarmwasserSpeicher * 1;
}
else {
if (BaujahrTrinkwarmwasserSpeicher > 1994) { WaermeVerlusteTrinkwarmwasserSpeicherAngepasst = WaermeVerlusteTrinkwarmwasserSpeicher * 1; }
else if (BaujahrTrinkwarmwasserSpeicher > 1988 && BaujahrTrinkwarmwasserSpeicher <= 1994) { WaermeVerlusteTrinkwarmwasserSpeicherAngepasst = WaermeVerlusteTrinkwarmwasserSpeicher * 1.25; }
else if (BaujahrTrinkwarmwasserSpeicher <= 1988) { WaermeVerlusteTrinkwarmwasserSpeicherAngepasst = WaermeVerlusteTrinkwarmwasserSpeicher * 1.32; }
}
return WaermeVerlusteTrinkwarmwasserSpeicherAngepasst;
}

View File

@@ -5,15 +5,21 @@ import {
Enums,
Rechnung,
VerbrauchsausweisWohnen,
} from "#lib/client/prisma";
import { prisma } from "#lib/server/prisma";
} from "#lib/client/prisma.js";
import { prisma } from "#lib/server/prisma.js";
import { getAnsichtsausweis } from "../ausweis.js";
import Sqids from "sqids";
export async function sendPaymentSuccessMail(
ausweis: VerbrauchsausweisWohnen,
rechnung: Rechnung,
user: Benutzer
) {
const sqids = new Sqids({
alphabet: "0123456789abcdefghijklmnopqrstuvw",
minLength: 8
})
const aufnahme = await prisma.aufnahme.findUnique({
where: {
id: ausweis.aufnahme_id,
@@ -64,7 +70,7 @@ export async function sendPaymentSuccessMail(
attachments,
from: `"IBCornelsen" <info@online-energieausweis.org>`,
to: user.email,
subject: `Bestellbestätigung vom IBCornelsen (ID: ${ausweis.uid})`,
subject: `Bestellbestätigung vom IBCornelsen (ID: ${sqids.encode([ausweis.id])})`,
cc: {
address: rechnung.email || "",
name: rechnung.empfaenger || "",

View File

@@ -2,7 +2,7 @@
import { AufnahmeKomplettClient, BenutzerClient } from "#components/Ausweis/types.js";
import Carousel from "#components/Carousel.svelte";
import DashboardAusweis from "#components/Dashboard/DashboardAusweis.svelte";
import { Objekt } from "#lib/client/prisma";
import { Objekt } from "#lib/client/prisma.js";
import { ChevronLeft, ChevronRight } from "radix-svelte-icons";
export let user: BenutzerClient;

View File

@@ -5,21 +5,20 @@
Cube,
Person,
} from "radix-svelte-icons";
import { Tabs, Tab, TabList, TabPanel } from "../../components/Tabs";
import { dialogs } from "../../../svelte-dialogs.config";
import { BenutzerClient } from "#components/Ausweis/types";
// import { client } from "src/trpc";
import { exclude } from "#lib/exclude";
import { Tabs, Tab, TabList, TabPanel } from "../../components/Tabs/index.js";
import { dialogs } from "../../../svelte-dialogs.config.js";
import { BenutzerClient } from "#components/Ausweis/types.js";
import { exclude } from "#lib/exclude.js";
import { api } from "astro-typesafe-api/client";
import Cookies from "js-cookie";
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
export let benutzer: BenutzerClient;
let passwort: string | undefined = undefined;
let passwortVerify: string | undefined = undefined;
let passwort: string = "";
let passwortVerify: string = "";
async function profilSpeichern(e: SubmitEvent) {
e.preventDefault()
if (!passwort) {
passwort = undefined
} else {
if (passwort.length < 8) {
dialogs.alert({
title: "Passwort zu kurz",
@@ -33,7 +32,6 @@
})
return
}
}
const response = await dialogs.confirm({
title: "Profil speichern",
@@ -51,7 +49,11 @@
// Wir wollen die Rolle nicht mit übertragen.
// Diese wird zwar sowieso rausgeschmissen aber sonst kommen wir nicht durch die Validation durch...
await client.v1.benutzer.update.mutate(benutzerObjekt)
await api.user.POST.fetch(benutzerObjekt, {
headers: {
Authorization: `Bearer ${Cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)}`
}
})
dialogs.success({
title: "Profil gespeichert",
@@ -175,7 +177,7 @@
}
:global(.tab) {
@apply rounded-none px-8 justify-start outline-0 gap-4 items-center text-base font-normal text-base-content;
@apply flex flex-row py-4 rounded-none px-8 justify-start outline-0 gap-4 items-center text-base font-normal text-base-content;
}
:global(.tab:hover) {

View File

@@ -1,24 +1,121 @@
<script lang="ts">
import { BenutzerClient, ObjektKomplettClient } from "#components/Ausweis/types.js";
import DashboardAusweis from "#components/Dashboard/DashboardAusweis.svelte";
import "../../style/formular.css";
import {
BenutzerClient,
ObjektClient,
ObjektKomplettClient,
} from "#components/Ausweis/types.js";
import DashboardObjekt from "#components/Dashboard/DashboardObjekt.svelte";
import Overlay from "#components/Overlay.svelte";
import PlzSuche from "#components/PlzSuche.svelte";
import TagInput from "#components/TagInput.svelte";
import { api } from "astro-typesafe-api/client";
import NotificationProvider from "#components/NotificationProvider/NotificationProvider.svelte";
import NotificationWrapper from "#components/Notifications/NotificationWrapper.svelte";
import { addNotification } from "#components/Notifications/shared.js";
import Cookies from "js-cookie";
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
export let user: BenutzerClient;
export let objekte: ObjektKomplettClient[];
let objektOverlayHidden = true;
let objekt: Omit<ObjektClient, "uid"> = {
adresse: "",
erstellungsdatum: new Date(),
latitude: 0,
longitude: 0,
ort: "",
plz: ""
};
async function objektErstellen() {
if (!objekt.adresse || !objekt.ort || !objekt.plz) {
addNotification({
message: "Daten unvollständig.",
subtext: "Ihre eingegebenen Daten sind unvollständig, bitte vervollständigen sie diese und versuchen sie es erneut..",
timeout: 3000,
dismissable: true,
type: "error"
})
return;
}
const result = await api.objekt.PUT.fetch({
adresse: objekt.adresse,
erstellungsdatum: new Date(),
latitude: 0,
longitude: 0,
ort: objekt.ort,
plz: objekt.plz
}, {
headers: {
Authorization: `Bearer ${Cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)}`
}
})
if (!result) {
addNotification({
message: "Etwas ist schiefgelaufen.",
subtext: "Das Objekt konnte nicht erstellt werden.",
timeout: 3000,
dismissable: true,
type: "error"
})
return;
}
objektOverlayHidden = true;
objekte.push({
...objekt,
aufnahmen: [],
uid: result.uid
})
objekt = {
adresse: "",
erstellungsdatum: new Date(),
latitude: 0,
longitude: 0,
ort: "",
plz: ""
}
objekte = objekte
}
</script>
<h1>Gebäudeübersicht</h1>
<hr>
<hr />
<div class="relative mb-6">
<button class="button flex flex-row rounded-lg gap-2 bg-secondary text-white text-center">
Gebäude anlegen +
</button>
<button class="button" on:click={() => {
objektOverlayHidden = false
}}> Gebäude anlegen + </button>
</div>
<div class="columns columns-1 md:columns-2 lg:columns-3 gap-4">
<div class="columns columns-1 md:columns-2 lg:columns-3 gap-4">
{#each objekte as objekt}
<DashboardObjekt {objekt}></DashboardObjekt>
{/each}
</div>
<Overlay bind:hidden={objektOverlayHidden}>
<div class="bg-white w-full max-w-screen-sm px-4 py-6 flex flex-col gap-4">
<h2 class="p-0 m-0">Gebäude erstellen</h2>
<input type="text" placeholder="Adresse" bind:value={objekt.adresse}>
<div class="flex flex-row gap-4 justify-between">
<PlzSuche bind:city={objekt.ort} bind:zip={objekt.plz} name="" placeholder="PLZ"></PlzSuche>
<input type="text" bind:value={objekt.ort} placeholder="Ort">
</div>
<button class="button mt-4" on:click={objektErstellen}>Gebäude Erstellen</button>
</div>
</Overlay>
<NotificationWrapper></NotificationWrapper>

View File

@@ -2,12 +2,8 @@
import PerformanceScore from "#components/Ausweis/PerformanceScore.svelte";
import Progressbar from "#components/Ausweis/Progressbar.svelte";
import Bereich from "#components/labels/Bereich.svelte";
import Ansprechpartner from "#components/Ausweis/Ansprechpartner.svelte";
import Rechnungsadresse from "#components/Ausweis/Rechnungsadresse.svelte";
import type { Bezahlmethoden } from "#lib/client/prisma.js";
import { Enums } from "#lib/client/prisma.js";
import { dialogs } from "svelte-dialogs";
import LoginDialog from "#components/LoginDialog.svelte";
import {
API_ACCESS_TOKEN_COOKIE_NAME,
PRICES,
@@ -18,7 +14,6 @@
BenutzerClient,
BildClient,
ObjektClient,
RechnungClient,
UnterlageClient,
VerbrauchsausweisWohnenClient,
} from "#components/Ausweis/types.js";
@@ -31,7 +26,11 @@
import { addNotification } from "#components/Notifications/shared.js";
import NotificationWrapper from "#components/Notifications/NotificationWrapper.svelte";
import { nachweisSpeichern } from "#client/lib/nachweisSpeichern.js";
import { EnterFullScreen } from "radix-svelte-icons";
import { localStorageSync, writableSync } from "#client/lib/helpers.js";
import HelpLabel from "#components/labels/HelpLabel.svelte";
import InputLabel from "#components/labels/InputLabel.svelte";
import PlzSuche from "#components/PlzSuche.svelte";
import { writable } from "svelte/store";
export let user: Partial<BenutzerClient>;
export let ausweis: VerbrauchsausweisWohnenClient;
@@ -43,18 +42,41 @@
export let aktiveBezahlmethode: Bezahlmethoden = Enums.Bezahlmethoden.paypal;
export let ausweistyp: Enums.AusweisTyp = Enums.AusweisTyp.Standard;
let rechnung: Partial<RechnungClient> = {
email: user.email,
empfaenger: user.vorname + " " + user.name,
strasse: user.adresse,
plz: user.plz,
ort: user.ort,
versand_empfaenger: user.vorname + " " + user.name,
versand_strasse: user.adresse,
versand_plz: user.plz,
versand_ort: user.ort,
telefon: user.telefon,
};
const email = localStorageSync(user.email || "", "kundendaten.email")
const vorname = localStorageSync(user.vorname || "", "kundendaten.vorname")
const name = localStorageSync(user.name || "", "kundendaten.name")
const empfaenger = localStorageSync(`${user.vorname} ${user.name}`, "kundendaten.empfaenger", JSON.parse, JSON.stringify)
const strasse = localStorageSync(user.adresse || "", "kundendaten.strasse")
const plz = localStorageSync(user.plz || "", "kundendaten.plz")
const ort = localStorageSync(user.ort || "", "kundendaten.ort")
const zusatzzeile = localStorageSync("", "kundendaten.zusatzzeile")
const telefon = localStorageSync(user.telefon || "", "kundendaten.telefon")
const abweichende_versand_adresse = localStorageSync(false, "kundendaten.abweichende_versand_adresse", JSON.parse, JSON.stringify)
let versand_email,
versand_zusatzzeile,
versand_empfaenger,
versand_strasse,
versand_plz,
versand_ort;
$: {
if ($abweichende_versand_adresse) {
versand_email = writable($email)
versand_zusatzzeile = writable($zusatzzeile)
versand_empfaenger = writable($empfaenger)
versand_strasse = writable($strasse)
versand_plz = writable($plz)
versand_ort = writable($ort)
} else {
versand_email = writableSync(email)
versand_zusatzzeile = writableSync(zusatzzeile)
versand_empfaenger = writableSync(empfaenger)
versand_strasse = writableSync(strasse)
versand_plz = writableSync(plz)
versand_ort = writableSync(ort)
}
}
let services: {
name: string;
@@ -116,29 +138,6 @@
`/angebot-anfragen/bedarfsausweis-gewerbe-anfragen?uid=${ausweis.uid}`,
}[ausweisart];
async function speichern(e: SubmitEvent) {
e.preventDefault();
// Um einen Ausweis zu speichern müssen wir eingeloggt sein, andernfalls wird die API den call ablehnen.
// Wir prüfen also ob wir eingeloggt sind und leiten den Nutzer ggf. auf die Login Seite weiter.
if (!(await validateAccessTokenClient())) {
// TOOD: Auf Dialog umstellen.
const loggedIn = await dialogs.modal(LoginDialog);
if (!loggedIn) {
return false;
}
}
// Falls der Ausweis noch keine benutzer_id hat müssen wir ihn claimen, damit er dem jetzigen Nutzer zugewiesen wird...
// await client.v1.verbrauchsausweisWohnen.claim.mutate({
// uid: ausweis.uid,
// });
localStorage.clear();
window.location.href = `/kaufabschluss?uid=${ausweis.uid}`;
}
async function anfordern() {
if (!form.checkValidity()) {
addNotification({
@@ -153,7 +152,6 @@
if (!await validateAccessTokenClient()) {
loginAction = bestellen
rechnung = rechnung
loginOverlayHidden = false;
return
}
@@ -161,33 +159,34 @@
loginOverlayHidden = true
let result: Awaited<ReturnType<typeof ausweisSpeichern>> | null = null;
try {
if (ausweisart === Enums.Ausweisart.GEGNachweisWohnen) {
result = await nachweisSpeichern(ausweis, objekt, aufnahme, bilder, unterlagen, ausweisart)
} else {
result = await ausweisSpeichern(ausweis, objekt, aufnahme, bilder, ausweisart)
}
if (result === null) {
} catch(e) {
addNotification({
dismissable: true,
message: "Ups... Das hat nicht geklappt.",
subtext: "Der Nachweis konnte nicht gespeichert werden, bitte versuchen sie es erneut oder kontaktieren sie unseren Support."
subtext: "Speichern ist fehlgeschlagen, bitte versuchen sie es erneut oder kontaktieren sie unseren Support."
})
}
try {
const { uid } = await api.rechnung.anfordern.PUT.fetch(
{
email: rechnung.email,
empfaenger: rechnung.empfaenger,
strasse: rechnung.strasse,
plz: rechnung.plz,
ort: rechnung.ort,
versand_empfaenger: rechnung.versand_empfaenger,
versand_strasse: rechnung.versand_strasse,
versand_plz: rechnung.versand_plz,
versand_ort: rechnung.versand_ort,
telefon: rechnung.telefon,
email: $email,
empfaenger: $empfaenger,
strasse: $strasse,
plz: $plz,
ort: $ort,
versand_empfaenger: $versand_empfaenger,
versand_strasse: $versand_strasse,
versand_plz: $versand_plz,
versand_ort: $versand_ort,
telefon: $telefon,
nachweis_uid: ausweis.uid,
},
{
@@ -210,6 +209,42 @@
}
}
async function speichern() {
loginAction = speichern;
if (!await validateAccessTokenClient()) {
loginOverlayHidden = false;
return
}
loginOverlayHidden = true
let result: Awaited<ReturnType<typeof ausweisSpeichern>> | null = null;
try {
if (ausweisart === Enums.Ausweisart.GEGNachweisWohnen) {
result = await nachweisSpeichern(ausweis, objekt, aufnahme, bilder, unterlagen, ausweisart)
} else {
result = await ausweisSpeichern(ausweis, objekt, aufnahme, bilder, ausweisart)
}
} catch(e) {
addNotification({
dismissable: true,
message: "Ups... Das hat nicht geklappt.",
subtext: "Speichern ist fehlgeschlagen, bitte versuchen sie es erneut oder kontaktieren sie unseren Support."
})
}
if (result !== null) {
window.history.pushState(
{},
"",
`${location.pathname}?uid=${ausweis.uid}`
);
localStorage.clear();
window.location.href = `/speichern-erfolgreich?uid=${ausweis.uid}`
}
}
async function bestellen() {
if (!form.checkValidity()) {
addNotification({
@@ -224,7 +259,6 @@
if (!await validateAccessTokenClient()) {
loginAction = bestellen
rechnung = rechnung
loginOverlayHidden = false;
return
}
@@ -262,16 +296,16 @@
services: services
.filter((service) => service.selected)
.map((service) => service.id),
email: rechnung.email,
empfaenger: rechnung.empfaenger,
strasse: rechnung.strasse,
plz: rechnung.plz,
ort: rechnung.ort,
versand_empfaenger: rechnung.versand_empfaenger,
versand_strasse: rechnung.versand_strasse,
versand_plz: rechnung.versand_plz,
versand_ort: rechnung.versand_ort,
telefon: rechnung.telefon,
email: $email,
empfaenger: $empfaenger,
strasse: $strasse,
plz: $plz,
ort: $ort,
versand_empfaenger: $versand_empfaenger,
versand_strasse: $versand_strasse,
versand_plz: $versand_plz,
versand_ort: $versand_ort,
telefon: $telefon,
ausweis_uid: ausweis.uid,
ausweistyp,
},
@@ -371,13 +405,344 @@
<div id="formular-box" class="formular-boxen ring-0">
<Bereich
bereich="1"
title="Eingabe des Ansprechpartners -> {user.email}"
title="Eingabe des Ansprechpartners"
>
<Ansprechpartner bind:user /></Bereich
<div
id="ansprechpartner"
class="bereich-box grid
grid-cols-1 gap-x-4 gap-y-8
sm:grid-cols-2 sm:gap-x-6 sm:gap-y-8
xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
"
>
<!-- Vorname * -->
<div class="input-standard order-1 md:order-1 xl:order-1">
<InputLabel title="Vorname *"></InputLabel>
<input name="vorname" type="text" bind:value={$vorname} required />
<div class="help-label">
<HelpLabel>
Bitte Geben Sie hier den Vornamen des Ansprechpartners&nbsp;ein.
</HelpLabel>
</div>
</div>
<!-- Nachname * -->
<div class="input-standard order-2 md:order-2 xl:order-2">
<InputLabel title="Nachname *"></InputLabel>
<input name="name" type="text" bind:value={$name} required />
<div class="help-label">
<HelpLabel>
Bitte Geben Sie hier den Nachnamen des
Ansprechpartners&nbsp;ein.
</HelpLabel>
</div>
</div>
<!-- Telefon & Email * -->
<div class="input-standard order-3 md:order-3 xl:order-3">
<InputLabel title="Telefonnummer *"></InputLabel>
<input name="telefon" bind:value={$telefon} type="text" />
<div class="help-label">
<HelpLabel>
Bitte Geben Sie hier die Telefonnummer des
Ansprechpartners&nbsp;ein.
</HelpLabel>
</div>
</div>
</div>
</Bereich
>
<Bereich bereich="2" title="Rechnungsadresse">
<Rechnungsadresse bind:rechnung /></Bereich
<div
id="rechnungsadresse"
class="bereich-box grid
grid-cols-1 gap-x-4 gap-y-8
sm:grid-cols-2 sm:gap-x-6 sm:gap-y-8
xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
">
<!-- Empfänger * -->
<div class="input-standard order-1 md:order-1 xl:order-1">
<InputLabel title="Rechnungs-Empfänger *"></InputLabel>
<input
name="rechnung_empfaenger"
type="text"
bind:value={$empfaenger}
required
data-rule-maxlength="100"
data-msg-maxlength="max. 100 Zeichen"
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie den Empfänger ein, auf den die Rechnung
ausgestellt wird.
</HelpLabel>
</div>
</div>
<!-- Straße, Hausnummer * -->
<div class="input-standard order-2 md:order-2 xl:order-2">
<InputLabel title="Straße, Hausnummer *"></InputLabel>
<input
name="rechnung_strasse"
bind:value={$strasse}
type="text"
required
data-rule-maxlength="40"
data-msg-maxlength="max. 40 Zeichen"
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie die Strasse und Hausnummer, so wie Sie auf der
Rechnung erscheinen soll, ein.
</HelpLabel>
</div>
</div>
<!-- PLZ / ORT -->
<div class="grid grid-cols-[2fr_4fr] gap-x-4 order-3 md:order-3 xl:order-3">
<div class="input-noHelp">
<InputLabel title="PLZ *"></InputLabel>
<PlzSuche
name="rechnung_plz"
bind:zip={$plz}
bind:city={$ort}
/>
</div>
<div class="input-standard">
<InputLabel title="Ort *"></InputLabel>
<input
name="rechnung_ort"
type="text"
required
bind:value={$ort}
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie die PLZ des Ortes, so wie Sie auf der
Rechnung erscheinen soll, ein.
</HelpLabel>
</div>
</div>
</div>
<!-- Zusatzzeile -->
<div class="input-standard order-4 md:order-4 xl:order-4">
<InputLabel title="Zusatzzeile"></InputLabel>
<input
name="rechnung_zusatzzeile"
bind:value={$zusatzzeile}
type="text"
data-rule-maxlength="80"
data-msg-maxlength="max. 80 Zeichen"
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie, falls erforderlich, zusätzliche nformationen
ein.
</HelpLabel>
</div>
</div>
<!-- E-mail -->
<div class="input-standard order-5 md:order-5 xl:order-5">
<InputLabel title="E-mail *"></InputLabel>
<input name="rechnung_email" bind:value={$email} type="email" />
<div class="help-label">
<HelpLabel>
Bitte geben Sie die E-Mail Adresse des Rechnungsempfängers ein.
</HelpLabel>
</div>
</div>
<div class="sm:col-span-3 order-7 md:order-7 xl:order-7">
<div
class="grid grid-cols-[25px_max-content] items-center justify-items-start"
>
<input
id="abweichende_versand_adresse"
class="w-[15px] h-[15px]"
type="checkbox"
name="abweichende_versand_adresse"
bind:checked={$abweichende_versand_adresse}
/>
<label for="abweichende_versand_adresse" class="cursor-pointer"
>abweichende Versandadresse</label
>
</div>
</div>
{#if $abweichende_versand_adresse}
<!-- Versand Empfänger * -->
<div class="input-standard order-8 md:order-8 xl:order-8">
<InputLabel title="Versand-Empfänger *"></InputLabel>
<input
name="versand_empfaenger"
type="text"
readonly={!$abweichende_versand_adresse}
bind:value={$versand_empfaenger}
required
data-rule-maxlength="100"
data-msg-maxlength="max. 100 Zeichen"
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie den Namen des Versand-Empfängers ein.
</HelpLabel>
</div>
</div>
<!-- Versand Straße, Hausnummer * -->
<div class="input-standard order-9 md:order-9 xl:order-9">
<InputLabel title="Straße, Hausnummer *"></InputLabel>
<input
name="versand_strasse"
type="text"
readonly={!$abweichende_versand_adresse}
bind:value={$versand_strasse}
required
data-rule-maxlength="40"
data-msg-maxlength="max. 40 Zeichen"
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie die Versand-Empfänger Strasse und Hausnummer
ein, an die die Rechnung versandt wird.
</HelpLabel>
</div>
</div>
<!-- PLZ / ORT -->
<div
class="grid grid-cols-[2fr_4fr] gap-x-4 order-10 md:order-10 xl:order-10"
>
<div class="input-noHelp">
<InputLabel title="PLZ *"></InputLabel>
<PlzSuche
name="versand_plz"
readonly={!$abweichende_versand_adresse}
bind:zip={$versand_plz}
bind:city={$versand_ort}
/>
</div>
<div class="input-standard">
<InputLabel title="Ort *"></InputLabel>
<input
name="versand_ort"
type="text"
readonly
required
bind:value={$versand_ort}
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie die Versand-Empfänger PLZ des Ortes ein,
an den die Rechnung versandt wird.
</HelpLabel>
</div>
</div>
</div>
<!-- Zusatzzeile -->
<div class="input-standard order-11 md:order-11 xl:order-11">
<InputLabel title="Zusatzzeile"></InputLabel>
<input
name="versand_zusatzzeile"
type="text"
readonly={!$abweichende_versand_adresse}
bind:value={$versand_zusatzzeile}
data-rule-maxlength="80"
data-msg-maxlength="max. 80 Zeichen"
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie, falls erforderlich, zusätzliche
nformationen ein.
</HelpLabel>
</div>
</div>
<!-- E-mail -->
<div class="input-standard order-12 md:order-12 xl:order-12">
<InputLabel title="E-mail *"></InputLabel>
<input
name="versand_email"
bind:value={$versand_email}
type="email"
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie die E-Mail Adresse des Versand-Empfängers
ein.
</HelpLabel>
</div>
</div>
<!-- Telefon
<div class="input-standard order-[13] md:order-[13] xl:order-[13]">
<Inputlabel title="Telefon *"></Inputlabel>
<input
name="rechnung_telefon"
bind:value={rechnung.telefon}
type="text"
/>
<div class="help-label">
<HelpLabel>
Bitte geben Sie die Telefonnummer des Versand-Empfängers ein.
</HelpLabel>
</div>
</div>
-->
{/if}
</div>
</Bereich
>
{#if !gegAnfrage}
@@ -498,7 +863,7 @@ sm:grid-cols-[min-content_min-content_min-content] sm:justify-self-end sm:mt-8"
<button class="order-2 button" type="button">Speichern</button>
<button class="order-2 button" type="button" on:click={speichern}>Speichern</button>
{#if gegAnfrage}
<button
@@ -520,7 +885,7 @@ sm:grid-cols-[min-content_min-content_min-content] sm:justify-self-end sm:mt-8"
<Overlay bind:hidden={loginOverlayHidden}>
<div class="bg-white w-full max-w-screen-sm py-8">
<EmbeddedAuthFlowModule onLogin={loginAction} email={rechnung.email}></EmbeddedAuthFlowModule>
<EmbeddedAuthFlowModule onLogin={loginAction} email={$email}></EmbeddedAuthFlowModule>
</div>
</Overlay>

View File

@@ -146,6 +146,9 @@
const ausweisart = Enums.Ausweisart.VerbrauchsausweisWohnen
const anliegen = "Energieausweis erstellen";
let form: HTMLFormElement;
let skala: HTMLDivElement;
</script>
<Overlay bind:hidden={speichernOverlayHidden}>
@@ -164,7 +167,7 @@ const anliegen = "Energieausweis erstellen";
<div id="skala" class="bg-white grid grid-cols-1 px-0 sm:p-4 lg:grid-cols-2 lg:gap-x-6">
<div id="skala" bind:this={skala} class="bg-white grid grid-cols-1 px-0 sm:p-4 lg:grid-cols-2 lg:gap-x-6">
<PerformanceScore
bind:ausweis
@@ -179,7 +182,7 @@ const anliegen = "Energieausweis erstellen";
<div id="formInput-1" data-test="ausweis">
<form id="formInput-1" data-test="ausweis" bind:this={form}>
<div id="formular-box" class="formular-boxen ring-0">
<ButtonWeiterHilfe
@@ -190,6 +193,8 @@ const anliegen = "Energieausweis erstellen";
bind:aufnahme
ausweisart={Enums.Ausweisart.VerbrauchsausweisWohnen}
showWeiter={false}
{form}
{skala}
>
</ButtonWeiterHilfe>
@@ -295,15 +300,17 @@ const anliegen = "Energieausweis erstellen";
bind:user
bind:objekt
bind:aufnahme
{form}
ausweisart={Enums.Ausweisart.VerbrauchsausweisWohnen}
{ausweistyp}
{skala}
>
</ButtonWeiterHilfe>
</div>
</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)}
@@ -582,3 +589,9 @@ const anliegen = "Energieausweis erstellen";
</RawNotification>
{/if}
</RawNotificationWrapper>
<style>
:global(input:invalid, select:invalid) {
@apply border-red-600 border-2;
}
</style>

View File

@@ -1,7 +1,7 @@
import { AufnahmeClient, OptionalNullable, UUidWithPrefix, ZodOverlap } from "#components/Ausweis/types.js";
import { exclude } from "#lib/exclude.js";
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
import { AufnahmeSchema, prisma } from "#lib/server/prisma";
import { AufnahmeSchema, prisma } from "#lib/server/prisma.js";
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
import { z } from "zod";
@@ -11,6 +11,7 @@ export const PATCH = defineApiRoute({
uid: true,
benutzer_id: true,
objekt_id: true,
erstellungsdatum: true
}),
output: z.void(),
middleware: authorizationMiddleware,

View File

@@ -1,7 +1,7 @@
import { ObjektClient, OptionalNullable, ZodOverlap } from "#components/Ausweis/types.js";
import { exclude } from "#lib/exclude.js";
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
import { ObjektSchema, prisma } from "#lib/server/prisma";
import { ObjektSchema, prisma } from "#lib/server/prisma.js";
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
import { z } from "zod";
@@ -9,7 +9,8 @@ export const PATCH = defineApiRoute({
input: ObjektSchema.omit({
uid: true,
id: true,
benutzer_id: true
benutzer_id: true,
erstellungsdatum: true
}),
output: z.void(),
headers: {

View File

@@ -1,7 +1,8 @@
import { UUidWithPrefix } from "#components/Ausweis/types.js";
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
import { ObjektSchema, prisma } from "#lib/server/prisma";
import { prisma } from "#lib/server/prisma.js";
import { defineApiRoute } from "astro-typesafe-api/server";
import { ObjektSchema } from "src/generated/zod/index.js";
import { z } from "zod";
export const PUT = defineApiRoute({

View File

@@ -1,7 +1,6 @@
import { z } from "zod";
import { TicketsSchema, prisma } from "#lib/server/prisma";
import { TicketsSchema, prisma } from "#lib/server/prisma.js";
import { defineApiRoute } from "astro-typesafe-api/server";
import { maybeAuthorizationMiddleware } from "#lib/middleware/authorization.js";
import { UUidWithPrefix } from "#components/Ausweis/types.js";
export const PUT = defineApiRoute({
@@ -26,11 +25,7 @@ export const PUT = defineApiRoute({
output: z.object({
uid: UUidWithPrefix,
}),
middleware: maybeAuthorizationMiddleware,
async fetch(input, ctx, user) {
if (user === null) {
// Der Benutzer ist nicht authentifiziert.
// Wir erstellen das Ticket anonym.
async fetch(input, ctx) {
const ticket = await prisma.tickets.create({
data: {
beschreibung: input.beschreibung,
@@ -43,30 +38,6 @@ export const PUT = defineApiRoute({
},
});
return {
uid: ticket.uid,
};
}
// Der Benutzer ist authentifiziert.
// Wir verlinken den Benutzer und das Ticket.
const ticket = await prisma.tickets.create({
data: {
benutzer: {
connect: {
id: user.id,
},
},
beschreibung: input.beschreibung,
email: input.email,
titel: input.titel,
metadata: input.metadata,
},
select: {
uid: true,
},
});
return {
uid: ticket.uid,
};

View File

@@ -1,9 +1,44 @@
import { UUidWithPrefix } from "#components/Ausweis/types.js";
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
import { hashPassword } from "#lib/password.js";
import { prisma } from "#lib/server/prisma";
import { BenutzerSchema, prisma } from "#lib/server/prisma.js";
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
import { z } from "zod";
export const POST = defineApiRoute({
input: BenutzerSchema.omit({
id: true,
lex_office_id: true,
uid: true,
rolle: true
}),
middleware: authorizationMiddleware,
async fetch(input, context, user) {
if (user.email !== input.email) {
// TODO: Email wurde geändert, neue Bestätigunsmail schicken.
}
await prisma.benutzer.update({
where: {
id: user.id
},
data: {
adresse: input.adresse,
anrede: input.anrede,
email: input.email,
firma: input.firma,
name: input.name,
vorname: input.vorname,
ort: input.ort,
passwort: hashPassword(input.passwort),
plz: input.plz,
profilbild: input.profilbild,
telefon: input.telefon,
}
})
},
})
export const PUT = defineApiRoute({
input: z.object({
email: z.string().email(),

View File

@@ -1,7 +1,7 @@
import { OptionalNullable, UUidWithPrefix, VerbrauchsausweisWohnenClient, ZodOverlap } from "#components/Ausweis/types.js";
import { exclude } from "#lib/exclude.js";
import { authorizationHeaders, authorizationMiddleware } from "#lib/middleware/authorization.js";
import { prisma, VerbrauchsausweisWohnenSchema } from "#lib/server/prisma";
import { prisma, VerbrauchsausweisWohnenSchema } from "#lib/server/prisma.js";
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
import { z } from "zod";
@@ -10,8 +10,10 @@ export const PATCH = defineApiRoute({
uid: true,
id: true,
benutzer_id: true,
aufnahme_id: true,
}),
aufnahme_id: true
}).merge(z.object({
startdatum: z.coerce.date()
})),
output: z.void(),
headers: {
"Authorization": z.string()

View File

@@ -1,8 +1,36 @@
---
import { API_ACCESS_TOKEN_COOKIE_NAME, API_REFRESH_TOKEN_COOKIE_NAME, API_UID_COOKIE_NAME } from "#lib/constants";
Astro.cookies.delete(API_ACCESS_TOKEN_COOKIE_NAME);
Astro.cookies.delete(API_REFRESH_TOKEN_COOKIE_NAME);
Astro.cookies.delete(API_UID_COOKIE_NAME);
return Astro.redirect("/auth/login");
Astro.cookies.delete(API_ACCESS_TOKEN_COOKIE_NAME, {
domain: `.${Astro.url.hostname}`,
path: "/",
});
Astro.cookies.delete(API_REFRESH_TOKEN_COOKIE_NAME, {
domain: `.${Astro.url.hostname}`,
path: "/",
});
Astro.cookies.delete(API_UID_COOKIE_NAME, {
domain: `.${Astro.url.hostname}`,
path: "/",
});
---
<script>
localStorage.clear()
window.location.href = "/"
</script>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
</head>
<body>
</body>
</html>

View File

@@ -1,9 +1,7 @@
---
import { createCaller } from "../../../astro-typesafe-api-caller.js";
import { validateAccessTokenServer } from "#server/lib/validateAccessToken";
import DashboardModule from "#modules/Dashboard/DashboardModule.svelte";
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
import Layout from "#layouts/Layout.astro";
import { prisma } from "#lib/server/prisma";
import UserLayout from "#layouts/DashboardLayout.astro";
import DashboardAufnahmeModule from "#modules/Dashboard/DashboardAufnahmeModule.svelte";

View File

@@ -4,7 +4,7 @@ import { getCurrentUser } from "#lib/server/user";
import DashboardEinstellungenModule from "#modules/Dashboard/DashboardEinstellungenModule.svelte";
import { validateAccessTokenServer } from "#server/lib/validateAccessToken";
const user = getCurrentUser(Astro)
const user = await getCurrentUser(Astro)
if (!user) {
return Astro.redirect("/auth/login", 302);

View File

@@ -46,5 +46,5 @@ const objekte = await prisma.objekt.findMany({
---
<DashboardLayout title="Dashboard" {user}>
<DashboardModule {user} {objekte} />
<DashboardModule {user} {objekte} client:load />
</DashboardLayout>

View File

@@ -34,6 +34,6 @@ try {
---
<AusweisLayout title="Kundendaten Aufnehmen - IBCornelsen">
<KundendatenModule {user} {ausweis} {objekt} {aufnahme} {bilder} {ausweisart} {ausweistyp} aktiveBezahlmethode={Enums.Bezahlmethoden.paypal} client:load></KundendatenModule>
<KundendatenModule {user} {ausweis} {objekt} {aufnahme} {bilder} {ausweisart} {ausweistyp} aktiveBezahlmethode={Enums.Bezahlmethoden.paypal} client:only></KundendatenModule>
</AusweisLayout>

View File

@@ -2,16 +2,16 @@ import { dialogs } from "svelte-dialogs";
dialogs.config({
global: {
confirmButtonClass: "btn btn-primary",
declineButtonClass: "btn btn-bordered",
dialogClass: "modal-box",
headerClass: "bg-base-100 text-center",
confirmButtonClass: "button",
declineButtonClass: "button",
dialogClass: "bg-white px-6 py-4 rounded-lg",
headerClass: "text-center",
titleClass: "text-base-content text-xl font-medium",
dividerClass: "hidden",
footerClass: "bg-base-100 justify-center gap-4 mt-4",
closeButtonClass: "btn btn-primary",
footerClass: "justify-center gap-4 mt-4",
closeButtonClass: "button",
closeButtonText: "Schließen",
dismissButtonClass: "btn btn-primary",
dismissButtonClass: "button",
dismissButtonText: "Schließen",
closeOnBg: true,
closeOnEsc: true