WIP on dev-moritz
This commit is contained in:
@@ -5,12 +5,13 @@ import tailwind from "@astrojs/tailwind";
|
|||||||
import node from "@astrojs/node";
|
import node from "@astrojs/node";
|
||||||
import mdx from "@astrojs/mdx";
|
import mdx from "@astrojs/mdx";
|
||||||
import dsv from "@rollup/plugin-dsv"
|
import dsv from "@rollup/plugin-dsv"
|
||||||
|
import astroTypesafeAPI from "astro-typesafe-api"
|
||||||
|
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
integrations: [svelte(), tailwind(), mdx()],
|
integrations: [svelte(), tailwind(), mdx(), astroTypesafeAPI()],
|
||||||
outDir: "./dist",
|
outDir: "./dist",
|
||||||
output: "server",
|
output: "server",
|
||||||
vite: {
|
vite: {
|
||||||
|
|||||||
1
openapi.json
Normal file
1
openapi.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"openapi":"3.0.3","info":{"title":"Title","version":"1.0.0","description":""},"paths":{"[id]":{"patch":{"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{}}}}}}},"index":{"post":{"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{}}}}}}}}}
|
||||||
29
package.json
29
package.json
@@ -25,40 +25,41 @@
|
|||||||
"@ibcornelsen/database": "link:@ibcornelsen/database",
|
"@ibcornelsen/database": "link:@ibcornelsen/database",
|
||||||
"@ibcornelsen/ui": "^0.0.2",
|
"@ibcornelsen/ui": "^0.0.2",
|
||||||
"@mollie/api-client": "^3.7.0",
|
"@mollie/api-client": "^3.7.0",
|
||||||
"@pdfme/common": "^5.1.7",
|
"@pdfme/common": "^5.2.16",
|
||||||
"@pdfme/generator": "^5.2.11",
|
"@pdfme/generator": "^5.2.16",
|
||||||
"@pdfme/ui": "^5.1.7",
|
"@pdfme/ui": "^5.2.16",
|
||||||
"@trpc/client": "^10.45.2",
|
"@trpc/client": "^10.45.2",
|
||||||
"@trpc/server": "^10.45.2",
|
"@trpc/server": "^10.45.2",
|
||||||
"astro": "^4.16.10",
|
"astro": "^4.16.18",
|
||||||
"body-scroll-lock": "^4.0.0-beta.0",
|
"body-scroll-lock": "^4.0.0-beta.0",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"bun": "^1.1.34",
|
"bun": "^1.1.45",
|
||||||
"csvtojson": "^2.0.10",
|
"csvtojson": "^2.0.10",
|
||||||
"express": "^4.21.1",
|
"express": "^4.21.2",
|
||||||
"flag-icons": "^6.15.0",
|
"flag-icons": "^6.15.0",
|
||||||
"fontkit": "^2.0.4",
|
"fontkit": "^2.0.4",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"js-interpolate": "^1.3.2",
|
"js-interpolate": "^1.3.2",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"moment-timezone": "^0.5.46",
|
"moment-timezone": "^0.5.46",
|
||||||
"pdf-lib": "^1.17.1",
|
"pdf-lib": "^1.17.1",
|
||||||
"postcss-nested": "^7.0.2",
|
"postcss-nested": "^7.0.2",
|
||||||
"radix-svelte-icons": "^1.0.0",
|
"radix-svelte-icons": "^1.0.0",
|
||||||
"sass": "^1.80.6",
|
"sass": "^1.83.4",
|
||||||
"svelte": "^3.59.2",
|
"svelte": "^3.59.2",
|
||||||
"svelte-dialogs": "^1.2.2",
|
"svelte-dialogs": "^1.2.2",
|
||||||
"svelte-preprocess": "^5.1.4",
|
"svelte-preprocess": "^5.1.4",
|
||||||
"svelte-ripple-action": "^1.0.6",
|
"svelte-ripple-action": "^1.0.6",
|
||||||
"tailwindcss": "^3.4.14",
|
"tailwindcss": "^3.4.17",
|
||||||
"trpc-openapi": "^1.2.0",
|
"trpc-openapi": "^1.2.0",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
"zod": "^3.23.8"
|
"zod": "^3.24.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@faker-js/faker": "^8.4.1",
|
"@faker-js/faker": "^8.4.1",
|
||||||
"@rollup/plugin-dsv": "^3.0.5",
|
"@rollup/plugin-dsv": "^3.0.5",
|
||||||
"@tailwindcss/typography": "^0.5.15",
|
"@tailwindcss/typography": "^0.5.16",
|
||||||
"@types/body-scroll-lock": "^3.1.2",
|
"@types/body-scroll-lock": "^3.1.2",
|
||||||
"@types/express": "^5.0.0",
|
"@types/express": "^5.0.0",
|
||||||
"@types/fontkit": "^2.0.7",
|
"@types/fontkit": "^2.0.7",
|
||||||
@@ -67,13 +68,13 @@
|
|||||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||||
"@typescript-eslint/parser": "^5.62.0",
|
"@typescript-eslint/parser": "^5.62.0",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"bun-types": "^1.1.34",
|
"bun-types": "^1.1.45",
|
||||||
"cypress": "^13.15.2",
|
"cypress": "^13.17.0",
|
||||||
"cypress-file-upload": "^5.0.8",
|
"cypress-file-upload": "^5.0.8",
|
||||||
"daisyui": "^4.12.14",
|
"daisyui": "^4.12.23",
|
||||||
"eslint": "~8.15.0",
|
"eslint": "~8.15.0",
|
||||||
"eslint-config-prettier": "8.1.0",
|
"eslint-config-prettier": "8.1.0",
|
||||||
"postcss": "^8.4.49",
|
"postcss": "^8.5.1",
|
||||||
"postcss-import": "^16.1.0",
|
"postcss-import": "^16.1.0",
|
||||||
"postcss-nesting": "^13.0.1",
|
"postcss-nesting": "^13.0.1",
|
||||||
"prettier": "^2.8.8",
|
"prettier": "^2.8.8",
|
||||||
|
|||||||
16
src/astro-typesafe-api-caller.ts
Normal file
16
src/astro-typesafe-api-caller.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { createCallerFactory } from "astro-typesafe-api/server";
|
||||||
|
import { type AstroGlobal } from "astro";
|
||||||
|
|
||||||
|
export const createCaller = createCallerFactory({
|
||||||
|
"aufnahme/[id]": await import("../src/pages/api/aufnahme/[id].ts"),
|
||||||
|
"aufnahme": await import("../src/pages/api/aufnahme/index.ts"),
|
||||||
|
"auth/access-token": await import("../src/pages/api/auth/access-token.ts"),
|
||||||
|
"auth/refresh-token": await import("../src/pages/api/auth/refresh-token.ts"),
|
||||||
|
"user/self": await import("../src/pages/api/user/self.ts"),
|
||||||
|
"bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"),
|
||||||
|
"objekt/[id]": await import("../src/pages/api/objekt/[id].ts"),
|
||||||
|
"objekt": await import("../src/pages/api/objekt/index.ts"),
|
||||||
|
"verbrauchsausweis-gewerbe": await import("../src/pages/api/verbrauchsausweis-gewerbe/index.ts"),
|
||||||
|
"verbrauchsausweis-wohnen/[id]": await import("../src/pages/api/verbrauchsausweis-wohnen/[id].ts"),
|
||||||
|
"verbrauchsausweis-wohnen": await import("../src/pages/api/verbrauchsausweis-wohnen/index.ts"),
|
||||||
|
})
|
||||||
@@ -22,6 +22,8 @@ export async function verbrauchsausweisWohnenSpeichern(
|
|||||||
// Anscheinend wurde der Ausweis bereits erstellt und hat eine UID.
|
// Anscheinend wurde der Ausweis bereits erstellt und hat eine UID.
|
||||||
// Jetzt müssen wir ihn nun nur noch abspeichern.
|
// Jetzt müssen wir ihn nun nur noch abspeichern.
|
||||||
try {
|
try {
|
||||||
|
await client.v1.objekt.speichern.mutate()
|
||||||
|
|
||||||
await client.v1.verbrauchsausweisWohnen[2016].speichern.mutate({
|
await client.v1.verbrauchsausweisWohnen[2016].speichern.mutate({
|
||||||
...ausweis,
|
...ausweis,
|
||||||
gebaeude_aufnahme_allgemein: {
|
gebaeude_aufnahme_allgemein: {
|
||||||
@@ -41,7 +43,6 @@ export async function verbrauchsausweisWohnenSpeichern(
|
|||||||
|
|
||||||
return { uid: ausweis.uid, gebaeude_uid: gebaeude.uid, gebaeude_aufnahme_uid: gebaeude_aufnahme_allgemein.uid };
|
return { uid: ausweis.uid, gebaeude_uid: gebaeude.uid, gebaeude_aufnahme_uid: gebaeude_aufnahme_allgemein.uid };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// TODO: Ticket mit Fehldermeldung abschicken.
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Wir speichern den Ausweis ab und leiten auf die "ausweis-gespeichert" Seite weiter.
|
// Wir speichern den Ausweis ab und leiten auf die "ausweis-gespeichert" Seite weiter.
|
||||||
@@ -69,7 +70,6 @@ export async function verbrauchsausweisWohnenSpeichern(
|
|||||||
ausweis,
|
ausweis,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
// TODO: Ticket mit Fehldermeldung abschicken.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|
||||||
|
|
||||||
import HelpLabel from "#labels/HelpLabel.svelte";
|
import HelpLabel from "#components/labels/HelpLabel.svelte";
|
||||||
import Inputlabel from "#labels/InputLabel.svelte";
|
import Inputlabel from "#components/labels/InputLabel.svelte";
|
||||||
|
|
||||||
//import Label from "#components/Label.svelte";
|
//import Label from "#components/Label.svelte";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import HelpLabel from "#labels/HelpLabel.svelte";
|
import HelpLabel from "#components/labels/HelpLabel.svelte";
|
||||||
import Inputlabel from "#labels/InputLabel.svelte";
|
import Inputlabel from "#components/labels/InputLabel.svelte";
|
||||||
|
|
||||||
import HeizungImage from "./HeizungImage.svelte";
|
import HeizungImage from "./HeizungImage.svelte";
|
||||||
import AusweisPreviewContainer from "./AusweisPreviewContainer.svelte";
|
import AusweisPreviewContainer from "./AusweisPreviewContainer.svelte";
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|
||||||
import HelpLabel from "#labels/HelpLabel.svelte";
|
import HelpLabel from "#components/labels/HelpLabel.svelte";
|
||||||
import Inputlabel from "#labels/InputLabel.svelte";
|
import Inputlabel from "#components/labels/InputLabel.svelte";
|
||||||
|
|
||||||
import ZipSearch from "#components/PlzSuche.svelte";
|
import ZipSearch from "#components/PlzSuche.svelte";
|
||||||
import { Enums } from "@ibcornelsen/database/client"
|
import { Enums } from "@ibcornelsen/database/client"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|
||||||
import HelpLabel from "#labels/HelpLabel.svelte";
|
import HelpLabel from "#components/labels/HelpLabel.svelte";
|
||||||
import Inputlabel from "#labels/InputLabel.svelte";
|
import Inputlabel from "#components/labels/InputLabel.svelte";
|
||||||
|
|
||||||
export let gebaeude_aufnahme_allgemein: GebaeudeAufnahmeClient;
|
export let gebaeude_aufnahme_allgemein: GebaeudeAufnahmeClient;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import HelpLabel from "#labels/HelpLabel.svelte";
|
import HelpLabel from "#components/labels/HelpLabel.svelte";
|
||||||
|
|
||||||
export let checked: boolean | null | undefined;
|
export let checked: boolean | null | undefined;
|
||||||
export let name: string;
|
export let name: string;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import HelpLabel from "#labels/HelpLabel.svelte";
|
import HelpLabel from "#components/labels/HelpLabel.svelte";
|
||||||
import Inputlabel from "#labels/InputLabel.svelte";
|
import Inputlabel from "#components/labels/InputLabel.svelte";
|
||||||
|
|
||||||
import FensterImage from "./FensterImage.svelte";
|
import FensterImage from "./FensterImage.svelte";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import HelpLabel from "#labels/HelpLabel.svelte";
|
import HelpLabel from "#components/labels/HelpLabel.svelte";
|
||||||
import Inputlabel from "#labels/InputLabel.svelte";
|
import Inputlabel from "#components/labels/InputLabel.svelte";
|
||||||
|
|
||||||
import HeizungImage from "./HeizungImage.svelte";
|
import HeizungImage from "./HeizungImage.svelte";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import HelpLabel from "#labels/HelpLabel.svelte";
|
import HelpLabel from "#components/labels/HelpLabel.svelte";
|
||||||
import Inputlabel from "#labels/InputLabel.svelte";
|
import Inputlabel from "#components/labels/InputLabel.svelte";
|
||||||
|
|
||||||
import DaemmungImage from "./DaemmungImage.svelte";
|
import DaemmungImage from "./DaemmungImage.svelte";
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import HelpLabel from "#labels/HelpLabel.svelte";
|
import HelpLabel from "#components/labels/HelpLabel.svelte";
|
||||||
import Inputlabel from "#labels/InputLabel.svelte";
|
import Inputlabel from "#components/labels/InputLabel.svelte";
|
||||||
import Verbrauchslabel from "#labels/VerbrauchsLabel.svelte";
|
import Verbrauchslabel from "#components/labels/VerbrauchsLabel.svelte";
|
||||||
import VerbrauchsHelpLabel from "#labels/VerbrauchsHelpLabel.svelte";
|
import VerbrauchsHelpLabel from "#components/labels/VerbrauchsHelpLabel.svelte";
|
||||||
|
|
||||||
import Label from "../Label.svelte";
|
import Label from "../Label.svelte";
|
||||||
|
|
||||||
@@ -44,12 +44,12 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
const startDate = moment(
|
const startDate = moment(
|
||||||
ausweis.gebaeude_aufnahme_allgemein.erstellungsdatum || Date.now()
|
ausweis.aufnahme.erstellungsdatum || Date.now()
|
||||||
)
|
)
|
||||||
.subtract(4, "years")
|
.subtract(4, "years")
|
||||||
.subtract(6, "months");
|
.subtract(6, "months");
|
||||||
const endDate = moment(
|
const endDate = moment(
|
||||||
ausweis.gebaeude_aufnahme_allgemein.erstellungsdatum || Date.now()
|
ausweis.aufnahme.erstellungsdatum || Date.now()
|
||||||
).subtract(3, "years");
|
).subtract(3, "years");
|
||||||
|
|
||||||
for (let m = moment(startDate); m.isBefore(endDate); m.add(1, "month")) {
|
for (let m = moment(startDate); m.isBefore(endDate); m.add(1, "month")) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|
||||||
import HelpLabel from "#labels/HelpLabel.svelte";
|
import HelpLabel from "#components/labels/HelpLabel.svelte";
|
||||||
import Inputlabel from "#labels/InputLabel.svelte";
|
import Inputlabel from "#components/labels/InputLabel.svelte";
|
||||||
|
|
||||||
export let ausweis;
|
export let ausweis;
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { get_current_component } from "svelte/internal";
|
|
||||||
|
|
||||||
const component = get_current_component();
|
|
||||||
|
|
||||||
export let image: string;
|
export let image: string;
|
||||||
export let name: string;
|
export let name: string;
|
||||||
export let description: string;
|
export let description: string;
|
||||||
@@ -25,10 +21,6 @@
|
|||||||
<div class="join">
|
<div class="join">
|
||||||
<button class="p-3.5 border rounded-lg" disabled={!removable && quantity == 1} on:click={() => {
|
<button class="p-3.5 border rounded-lg" disabled={!removable && quantity == 1} on:click={() => {
|
||||||
quantity--
|
quantity--
|
||||||
|
|
||||||
if ((quantity == 0) && removable) {
|
|
||||||
component.$destroy();
|
|
||||||
}
|
|
||||||
}}>-</button>
|
}}>-</button>
|
||||||
<button class="p-3.5 border rounded-lg">{quantity}</button>
|
<button class="p-3.5 border rounded-lg">{quantity}</button>
|
||||||
<button class="p-3.5 border rounded-lg" disabled={quantity <= maxQuantity} on:click={() => quantity++}>+</button>
|
<button class="p-3.5 border rounded-lg" disabled={quantity <= maxQuantity} on:click={() => quantity++}>+</button>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
import HeaderLogin from "#header/HeaderLogin.svelte";
|
import HeaderLogin from "#components/design/header/HeaderLogin.svelte";
|
||||||
---
|
---
|
||||||
|
|
||||||
<header id="header">
|
<header id="header">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
import HeaderLogin from "#header/HeaderLogin.svelte";
|
import HeaderLogin from "#components/design/header/HeaderLogin.svelte";
|
||||||
---
|
---
|
||||||
|
|
||||||
<header id="header">
|
<header id="header">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { loginClient } from "#lib/login";
|
import { loginClient } from "#lib/login.js";
|
||||||
import { CrossCircled } from "radix-svelte-icons";
|
import { CrossCircled } from "radix-svelte-icons";
|
||||||
import { fade } from "svelte/transition";
|
import { fade } from "svelte/transition";
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
import CardNavigation from "#sidebarCards/cardNavigation.svelte";
|
import CardNavigation from "#components/design/sidebars/cards/cardNavigation.svelte";
|
||||||
import CardPriceiInfo from "#sidebarCards/cardPriceiInfo.svelte";
|
import CardPriceiInfo from "#components/design/sidebars/cards/cardPriceiInfo.svelte";
|
||||||
import CardProduktSidebar from "#sidebarCards/CardProduktSidebar.svelte";
|
import CardProduktSidebar from "#components/design/sidebars/cards/CardProduktSidebar.svelte";
|
||||||
|
|
||||||
import { PRICES } from "#lib/constants";
|
import { PRICES } from "#lib/constants";
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
import CardContact from "#sidebarCards/cardContact.svelte";
|
import CardContact from "#components/design/sidebars/cards/cardContact.svelte";
|
||||||
import CardPriceiInfo from "#sidebarCards/cardPriceiInfo.svelte";
|
import CardPriceiInfo from "#components/design/sidebars/cards/cardPriceiInfo.svelte";
|
||||||
import CardProduktSidebar from "#sidebarCards/CardProduktSidebar.svelte";
|
import CardProduktSidebar from "#components/design/sidebars/cards/CardProduktSidebar.svelte";
|
||||||
|
|
||||||
import { PRICES } from "#lib/constants";
|
import { PRICES } from "#lib/constants";
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
---
|
---
|
||||||
import Login from "#sidebarCards/cardlogin_1.svelte";
|
import Login from "#components/design/sidebars/cards/cardlogin_1.svelte";
|
||||||
import Contact from "#sidebarCards/cardcontact.svelte";
|
import Contact from "#components/design/sidebars/cards/cardcontact.svelte";
|
||||||
import Review from "#sidebarCards/cardreview.svelte";
|
import Review from "#components/design/sidebars/cards/cardreview.svelte";
|
||||||
import VApromo from "#sidebarCards/cardVApromo.svelte";
|
import VApromo from "#components/design/sidebars/cards/cardVApromo.svelte";
|
||||||
import VAGpromo from "#sidebarCards/cardVAGpromo.svelte";
|
import VAGpromo from "#components/design/sidebars/cards/cardVAGpromo.svelte";
|
||||||
import BApromo from "#sidebarCards/cardBApromo.svelte";
|
import BApromo from "#components/design/sidebars/cards/cardBApromo.svelte";
|
||||||
import BAGpromo from "#sidebarCards/cardBAGpromo.svelte";
|
import BAGpromo from "#components/design/sidebars/cards/cardBAGpromo.svelte";
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="hidden
|
<div class="hidden
|
||||||
|
|||||||
4
src/env.d.ts
vendored
4
src/env.d.ts
vendored
@@ -1,7 +1,11 @@
|
|||||||
/// <reference path="../.astro/types.d.ts" />
|
/// <reference path="../.astro/types.d.ts" />
|
||||||
/// <reference types="astro/client" />
|
/// <reference types="astro/client" />
|
||||||
|
/// <reference types="../.astro/astro-typesafe-api.d.ts" />
|
||||||
|
|
||||||
|
|
||||||
/// <reference path="../.astro-i18n/generated.d.ts" />
|
/// <reference path="../.astro-i18n/generated.d.ts" />
|
||||||
|
/// <reference path="../.astro/astro-typesafe-api.d.ts" />
|
||||||
|
|
||||||
|
|
||||||
declare module "*.csv" {
|
declare module "*.csv" {
|
||||||
export default <{ [key: string]: any }>Array;
|
export default <{ [key: string]: any }>Array;
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
import "../style/global.css";
|
import "../style/global.css";
|
||||||
import "../style/formular.css";
|
import "../style/formular.css";
|
||||||
import "../../svelte-dialogs.config"
|
import "../../svelte-dialogs.config"
|
||||||
import Header from "#header/AusweisHeader.astro";
|
import Header from "#components/design/header/AusweisHeader.astro";
|
||||||
import Footer from "#footer/Footer.astro";
|
import Footer from "#components/design/footer/Footer.astro";
|
||||||
import SidebarLeft from "#sidebarLeft/SidebarLeft.astro";
|
import SidebarLeft from "#components/design/sidebars/left/SidebarLeft.astro";
|
||||||
import { NotificationWrapper } from "@ibcornelsen/ui";
|
import { NotificationWrapper } from "@ibcornelsen/ui";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
---
|
---
|
||||||
import "../style/global.css";
|
import "../style/global.css";
|
||||||
import "../../svelte-dialogs.config"
|
import "../../svelte-dialogs.config"
|
||||||
import Header from "#header/Header.astro";
|
import Header from "#components/design/header/Header.astro";
|
||||||
import Footer from "#footer/Footer.astro";
|
import Footer from "#components/design/footer/Footer.astro";
|
||||||
import SidebarLeft from "#sidebarLeft/SidebarLeft.astro";
|
import SidebarLeft from "#components/design/sidebars/left/SidebarLeft.astro";
|
||||||
import SidebarRight from "#sidebarRight/SidebarRight.astro";
|
import SidebarRight from "#components/design/sidebars/right/SidebarRight.astro";
|
||||||
import { NotificationWrapper } from "@ibcornelsen/ui";
|
import { NotificationWrapper } from "@ibcornelsen/ui";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
---
|
---
|
||||||
import "../style/global.css";
|
import "../style/global.css";
|
||||||
import "../../svelte-dialogs.config"
|
import "../../svelte-dialogs.config"
|
||||||
import Header from "#header/Header_1.astro";
|
import Header from "#components/design/header/Header_1.astro";
|
||||||
import Footer from "#footer/Footer.astro";
|
import Footer from "#components/design/footer/Footer.astro";
|
||||||
import SidebarLeft from "#sidebarLeft/SidebarLeft.astro";
|
import SidebarLeft from "#components/design/sidebars/left/SidebarLeft.astro";
|
||||||
import SidebarRight from "#sidebarRight/SidebarRight_1.astro";
|
import SidebarRight from "#components/design/sidebars/right/SidebarRight_1.astro";
|
||||||
import { NotificationWrapper } from "@ibcornelsen/ui";
|
import { NotificationWrapper } from "@ibcornelsen/ui";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
---
|
---
|
||||||
import "../style/global.css";
|
import "../style/global.css";
|
||||||
import "../../svelte-dialogs.config"
|
import "../../svelte-dialogs.config"
|
||||||
import Header from "#header/Header.astro";
|
import Header from "#components/design/header/Header.astro";
|
||||||
import Footer from "#footer/Footer.astro";
|
import Footer from "#components/design/footer/Footer.astro";
|
||||||
import SidebarLeft from "#sidebarLeft/SidebarLeft.astro";
|
import SidebarLeft from "#components/design/sidebars/left/SidebarLeft.astro";
|
||||||
import SidebarRight from "#sidebarRight/SidebarRight.astro";
|
import SidebarRight from "#components/design/sidebars/right/SidebarRight.astro";
|
||||||
import { NotificationWrapper } from "@ibcornelsen/ui";
|
import { NotificationWrapper } from "@ibcornelsen/ui";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { BedarfsausweisWohnenClient, GebaeudeAufnahmeClient } from "#components/Ausweis/types.js";
|
import { BedarfsausweisWohnenClient, GebaeudeAufnahmeClient } from "#components/Ausweis/types.js";
|
||||||
import { berechnungNutzenergiebedarfTrinkwasser } from "./BerechnungNutzenergiebedarfTrinkwarmwasser.js";
|
import { berechnungNutzenergiebedarfTrinkwarmwasser } from "./BerechnungNutzenergiebedarfTrinkwarmwasser.js";
|
||||||
import { FixedLengthArray } from "./types.js";
|
import { FixedLengthArray } from "./types.js";
|
||||||
|
|
||||||
export function berechnungWaermequellenAusAnlagentechnikTrinkwasser(ausweis: BedarfsausweisWohnenClient, gebaeude_aufnahme: GebaeudeAufnahmeClient) {
|
export function berechnungWaermequellenAusAnlagentechnikTrinkwasser(ausweis: BedarfsausweisWohnenClient, gebaeude_aufnahme: GebaeudeAufnahmeClient) {
|
||||||
const trinkwasserWaermebedarf = berechnungNutzenergiebedarfTrinkwasser(ausweis, gebaeude_aufnahme);
|
const trinkwasserWaermebedarf = berechnungNutzenergiebedarfTrinkwarmwasser(ausweis, gebaeude_aufnahme);
|
||||||
|
|
||||||
const result = new Array(12).fill(0) as unknown as FixedLengthArray<number, 12>
|
const result = new Array(12).fill(0) as unknown as FixedLengthArray<number, 12>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// Funktion zur Berechnung der Bilanzinnentemperatur aus Tabelle 8 EFH oder Tabelle 10 MFH
|
// Funktion zur Berechnung der Bilanzinnentemperatur aus Tabelle 8 EFH oder Tabelle 10 MFH
|
||||||
|
|
||||||
import { cubicSplineInterpolation, nevillePolynomialInterpolation } from "js-interpolate";
|
import { cubicSplineInterpolation } from "js-interpolate";
|
||||||
import { any } from "node_modules/cypress/types/bluebird/index.js";
|
|
||||||
|
|
||||||
// aus Eingabeformular
|
// aus Eingabeformular
|
||||||
let wohneinheiten = 3;
|
let wohneinheiten = 3;
|
||||||
|
|||||||
22
src/lib/auth/token.ts
Normal file
22
src/lib/auth/token.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import jwt from "jsonwebtoken";
|
||||||
|
|
||||||
|
export enum TokenType {
|
||||||
|
Refresh,
|
||||||
|
Access,
|
||||||
|
Reset
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TokenData = { uid: string, typ: TokenType, exp: number }
|
||||||
|
|
||||||
|
export function encodeToken(data: TokenData) {
|
||||||
|
const token = jwt.sign(data, "yIvbgS$k7Bfc+mpV%TWDZAhje9#uJad4", {
|
||||||
|
algorithm: "HS256"
|
||||||
|
});
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function decodeToken(token: string): Partial<TokenData> {
|
||||||
|
return jwt.verify(token, "yIvbgS$k7Bfc+mpV%TWDZAhje9#uJad4", {
|
||||||
|
algorithms: ["HS256"]
|
||||||
|
}) as Partial<TokenData>;
|
||||||
|
}
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
import { AppRouter } from "@ibcornelsen/api";
|
|
||||||
import { inferProcedureOutput } from "@trpc/server";
|
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import { client } from "src/trpc"
|
import { API_ACCESS_TOKEN_COOKIE_NAME, API_REFRESH_TOKEN_COOKIE_NAME } from "./constants.js";
|
||||||
import { API_ACCESS_TOKEN_COOKIE_NAME, API_REFRESH_TOKEN_COOKIE_NAME } from "./constants";
|
import { API, api, inferOutput } from "astro-typesafe-api/client";
|
||||||
|
|
||||||
export async function loginClient(email: string, passwort: string): Promise<inferProcedureOutput<AppRouter["v1"]["benutzer"]["getRefreshToken"]> | null> {
|
export async function loginClient(email: string, passwort: string): Promise<inferOutput<API["auth"]["refresh-token"]["GET"]> | null> {
|
||||||
try {
|
try {
|
||||||
const response = await client.v1.benutzer.getRefreshToken.query({
|
const response = await api.auth["refresh-token"].GET.fetch({
|
||||||
email,
|
email,
|
||||||
passwort
|
passwort
|
||||||
})
|
})
|
||||||
|
|||||||
81
src/lib/middleware/authorization.ts
Normal file
81
src/lib/middleware/authorization.ts
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import { decodeToken } from "#lib/auth/token.js";
|
||||||
|
import { hashPassword } from "#lib/password.js";
|
||||||
|
import { prisma } from "@ibcornelsen/database/server";
|
||||||
|
import { APIError, TypesafeAPIContextWithRequest } from "astro-typesafe-api/server";
|
||||||
|
|
||||||
|
export async function authorizationMiddleware(input: any, context: TypesafeAPIContextWithRequest<any>) {
|
||||||
|
const authorization: string | undefined = context.request.headers.get("Authorization");
|
||||||
|
|
||||||
|
if (!context.request.headers.has("Authorization") || !authorization) {
|
||||||
|
throw new APIError({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "Request is missing an 'Authorization' header."
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authorization.startsWith("Basic")) {
|
||||||
|
const payload = btoa(authorization.split(" ")[1]).split(":");
|
||||||
|
|
||||||
|
if (payload.length !== 2) {
|
||||||
|
throw new APIError({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "Malformed 'Authorization' header."
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const [email, password] = payload;
|
||||||
|
|
||||||
|
const user = await prisma.benutzer.findUnique({
|
||||||
|
where: {
|
||||||
|
email
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!user || user.passwort !== hashPassword(password)) {
|
||||||
|
throw new APIError({
|
||||||
|
code: "UNAUTHORIZED",
|
||||||
|
message: "Unknown combination of email and password."
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
} else if (authorization.startsWith("Bearer")) {
|
||||||
|
const token = authorization.split(" ")[1]
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
throw new APIError({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "Malformed 'Authorization' header."
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = decodeToken(token)
|
||||||
|
|
||||||
|
if ((payload.exp || 0) < Date.now()) {
|
||||||
|
throw new APIError({
|
||||||
|
code: "UNAUTHORIZED",
|
||||||
|
message: "Access Token has expired."
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await prisma.benutzer.findUnique({
|
||||||
|
where: {
|
||||||
|
uid: payload.uid
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
throw new APIError({
|
||||||
|
code: "UNAUTHORIZED",
|
||||||
|
message: "Invalid Bearer Token."
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new APIError({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "Invalid authorization method in 'Authorization' header."
|
||||||
|
})
|
||||||
|
}
|
||||||
19
src/lib/password.ts
Normal file
19
src/lib/password.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import * as crypto from "crypto";
|
||||||
|
|
||||||
|
export function hashPassword(password: string): string {
|
||||||
|
const salt = crypto.randomBytes(16).toString("hex");
|
||||||
|
const hash = hashWithGivenSalt(password, salt) + salt;
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hashWithGivenSalt(password: string, salt: string): string {
|
||||||
|
const hash = crypto.scryptSync(password, salt, 32).toString("hex");
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validatePassword(known: string, unknown: string): boolean {
|
||||||
|
const salt = known.slice(64);
|
||||||
|
const originalPasswordHash = known.slice(0, 64);
|
||||||
|
const currentPasswordHash = hashWithGivenSalt(unknown, salt)
|
||||||
|
return originalPasswordHash == currentPasswordHash;
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import { PDFElement } from './PDFElement.js';
|
|||||||
export class Checkbox extends PDFElement {
|
export class Checkbox extends PDFElement {
|
||||||
private borderWidth: number = 1;
|
private borderWidth: number = 1;
|
||||||
|
|
||||||
constructor(protected _width: number, protected _height: number) {
|
constructor(protected _width: number, protected _height: number, public checked: boolean = false) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,5 +22,15 @@ export class Checkbox extends PDFElement {
|
|||||||
borderColor: rgb(0, 0, 0),
|
borderColor: rgb(0, 0, 0),
|
||||||
borderWidth: this.borderWidth
|
borderWidth: this.borderWidth
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (this.checked) {
|
||||||
|
page.drawSvgPath(`<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z"/></svg>`, {
|
||||||
|
x: x + this.borderWidth,
|
||||||
|
y: y - this.borderWidth * 1.5,
|
||||||
|
borderColor: rgb(0,0,0),
|
||||||
|
color: rgb(0,0,0),
|
||||||
|
scale: this._width / 24
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export function xml2pdf(xml: string, fonts: Record<string, PDFFont> & { "default
|
|||||||
throw new Error("Missing height or width property in Checkbox creation.")
|
throw new Error("Missing height or width property in Checkbox creation.")
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkbox = new Checkbox(parseFloat(child.attributes.width), parseFloat(child.attributes.height))
|
const checkbox = new Checkbox(parseFloat(child.attributes.width), parseFloat(child.attributes.height), (child.attributes.hasOwnProperty("checked") && child.attributes.checked !== "false") || false)
|
||||||
|
|
||||||
parent.addChild(checkbox);
|
parent.addChild(checkbox);
|
||||||
} else if (child.tagName === "layout") {
|
} else if (child.tagName === "layout") {
|
||||||
|
|||||||
@@ -1,176 +0,0 @@
|
|||||||
import { VerbrauchsausweisWohnenClient } from "#components/Ausweis/types.js";
|
|
||||||
import { endEnergieVerbrauchVerbrauchsausweis_2016 } from "#lib/Berechnungen/VerbrauchsausweisWohnen/VerbrauchsausweisWohnen_2016.js";
|
|
||||||
import * as fs from "fs"
|
|
||||||
import { PDFDocument, rgb, StandardFonts, TextAlignment } from "pdf-lib";
|
|
||||||
import { checkbox, flex, text } from "./elements/index.js";
|
|
||||||
import { xml2pdf } from "./elements/xml2pdf.js";
|
|
||||||
|
|
||||||
/* -------------------------------- Pdf Tools ------------------------------- */
|
|
||||||
|
|
||||||
export async function pdfDatenblatt(ausweis: VerbrauchsausweisWohnenClient) {
|
|
||||||
const VerbrauchsausweisWohnenGEG2024PDF = fs.readFileSync(new URL("./templates/Leerseite_Datenblatt.pdf", import.meta.url), "base64");
|
|
||||||
const pdf = await PDFDocument.load(VerbrauchsausweisWohnenGEG2024PDF)
|
|
||||||
const pages = pdf.getPages()
|
|
||||||
|
|
||||||
// const template = VerbrauchsausweisWohnen2016Template as Template;
|
|
||||||
|
|
||||||
const berechnungen = await endEnergieVerbrauchVerbrauchsausweis_2016(ausweis);
|
|
||||||
|
|
||||||
const height = pages[0].getHeight()
|
|
||||||
const width = pages[0].getWidth()
|
|
||||||
|
|
||||||
const font = await pdf.embedFont(StandardFonts.Helvetica)
|
|
||||||
const bold = await pdf.embedFont(StandardFonts.HelveticaBold)
|
|
||||||
|
|
||||||
const form = pdf.getForm()
|
|
||||||
form.updateFieldAppearances(font)
|
|
||||||
|
|
||||||
const marginX = 45;
|
|
||||||
const marginY = 150;
|
|
||||||
|
|
||||||
const benutzer: typeof ausweis.benutzer = ausweis.benutzer || {
|
|
||||||
vorname: "Max",
|
|
||||||
name: "Mustermann",
|
|
||||||
adresse: "Musterstraße 123",
|
|
||||||
plz: "12345",
|
|
||||||
ort: "Beispielhausen"
|
|
||||||
};
|
|
||||||
|
|
||||||
const layout = xml2pdf(`<layout height="${pages[0].getHeight()}" width="${pages[0].getWidth()}" marginTop="150" marginLeft="45" marginRight="45">
|
|
||||||
<text size="12" lineHeight="14">${benutzer.vorname} ${benutzer.name}</text>
|
|
||||||
<text size="12" lineHeight="14">${benutzer.adresse}</text>
|
|
||||||
<text size="12" lineHeight="14">${benutzer.plz} ${benutzer.ort}</text>
|
|
||||||
<flex direction="row" justify="space-between" marginTop="55" width="${pages[0].getWidth() - 90}">
|
|
||||||
<text size="12" font="bold">Datenblatt Energieausweis</text>
|
|
||||||
<text size="12">Ausweis ID: ${ausweis.uid}</text>
|
|
||||||
</flex>
|
|
||||||
<text size="12" lineHeight="14" font="bold" marginTop="10">Gebäudedaten</text>
|
|
||||||
<text size="12" lineHeight="14">Adresse: ${ausweis.gebaeude_aufnahme_allgemein.adresse}, ${ausweis.gebaeude_aufnahme_allgemein.plz} ${ausweis.gebaeude_aufnahme_allgemein.ort}</text>
|
|
||||||
|
|
||||||
<flex direction="row" justify="space-between" width="${pages[0].getWidth() - 90}" marginTop="25">
|
|
||||||
<flex direction="row" gap="5" align="center">
|
|
||||||
<checkbox width="8" height="8"></checkbox>
|
|
||||||
<text size="12">Neubau</text>
|
|
||||||
</flex>
|
|
||||||
<flex direction="row" gap="5" align="center">
|
|
||||||
<checkbox width="8" height="8"></checkbox>
|
|
||||||
<text size="12">Vermietung/Verkauf</text>
|
|
||||||
</flex>
|
|
||||||
<flex direction="row" gap="5" align="center">
|
|
||||||
<checkbox width="8" height="8"></checkbox>
|
|
||||||
<text size="12">Modernisierung</text>
|
|
||||||
</flex>
|
|
||||||
<flex direction="row" gap="5" align="center">
|
|
||||||
<checkbox width="8" height="8"></checkbox>
|
|
||||||
<text size="12">Sonstiges</text>
|
|
||||||
</flex>
|
|
||||||
</flex>
|
|
||||||
|
|
||||||
<flex direction="row" marginTop="25" gap="15">
|
|
||||||
<flex direction="column" width="${(pages[0].getWidth() - 90) / 2 - 7.5}">
|
|
||||||
<flex direction="row" align="center" justify="space-between" width="${(pages[0].getWidth() - 90) / 2 - 7.5}">
|
|
||||||
<text size="12" lineHeight="14">Gebäudetyp:</text>
|
|
||||||
<text size="12" lineHeight="14">${ausweis.gebaeude_aufnahme_allgemein.gebaeudetyp}</text>
|
|
||||||
</flex>
|
|
||||||
<flex direction="row" align="center" justify="space-between" width="${(pages[0].getWidth() - 90) / 2 - 7.5}">
|
|
||||||
<text size="12" lineHeight="14">Wohnfläche:</text>
|
|
||||||
<text size="12" lineHeight="14">DIN Wohnfläche innen ${ausweis.gebaeude_aufnahme_allgemein.flaeche} m²</text>
|
|
||||||
</flex>
|
|
||||||
<flex direction="row" align="center" justify="space-between" width="${(pages[0].getWidth() - 90) / 2 - 7.5}">
|
|
||||||
<text size="12" lineHeight="14">Leerstand:</text>
|
|
||||||
<text size="12" lineHeight="14">${ausweis.gebaeude_aufnahme_allgemein.leerstand || 0}%</text>
|
|
||||||
</flex>
|
|
||||||
<flex direction="row" align="center" justify="space-between" width="${(pages[0].getWidth() - 90) / 2 - 7.5}">
|
|
||||||
<text size="12" lineHeight="14">Wohnungen:</text>
|
|
||||||
<text size="12" lineHeight="14">${ausweis.gebaeude_aufnahme_allgemein.einheiten}</text>
|
|
||||||
</flex>
|
|
||||||
</flex>
|
|
||||||
<flex direction="column" width="${(pages[0].getWidth() - 90) / 2 - 7.5}">
|
|
||||||
<flex direction="row" align="center" justify="space-between" width="${(pages[0].getWidth() - 90) / 2 - 7.5}">
|
|
||||||
<text size="12" lineHeight="14">Dachgeschoss:</text>
|
|
||||||
<text size="12" lineHeight="14">${ausweis.gebaeude_aufnahme_allgemein.dachgeschoss}</text>
|
|
||||||
</flex>
|
|
||||||
<flex direction="row" align="center" justify="space-between" width="${(pages[0].getWidth() - 90) / 2 - 7.5}">
|
|
||||||
<text size="12" lineHeight="14">Keller:</text>
|
|
||||||
<text size="12" lineHeight="14">${ausweis.gebaeude_aufnahme_allgemein.keller}</text>
|
|
||||||
</flex>
|
|
||||||
</flex>
|
|
||||||
</flex>
|
|
||||||
</layout>`, {
|
|
||||||
"default": font,
|
|
||||||
bold: bold
|
|
||||||
})
|
|
||||||
|
|
||||||
layout.draw(pages[0], 0, pages[0].getHeight())
|
|
||||||
|
|
||||||
// const containerWidth = width - marginX;
|
|
||||||
|
|
||||||
// const layout = flex([
|
|
||||||
// flex([
|
|
||||||
// checkbox(8, 8), text("Neubau", {
|
|
||||||
// color: rgb(0,0,0),
|
|
||||||
// font,
|
|
||||||
// fontSize: 12
|
|
||||||
// })
|
|
||||||
// ], {
|
|
||||||
// align: "center",
|
|
||||||
// justify: "center",
|
|
||||||
// gap: 5,
|
|
||||||
// height: 12,
|
|
||||||
// page: pages[0]
|
|
||||||
// }),
|
|
||||||
// flex([
|
|
||||||
// checkbox(8, 8), text("Vermietung/Verkauf", {
|
|
||||||
// color: rgb(0,0,0),
|
|
||||||
// font,
|
|
||||||
// fontSize: 12
|
|
||||||
// })
|
|
||||||
// ], {
|
|
||||||
// align: "center",
|
|
||||||
// justify: "center",
|
|
||||||
// gap: 5,
|
|
||||||
// height: 12,
|
|
||||||
// page: pages[0]
|
|
||||||
// }),
|
|
||||||
// flex([
|
|
||||||
// checkbox(8, 8), text("Modernisierung", {
|
|
||||||
// color: rgb(0,0,0),
|
|
||||||
// font,
|
|
||||||
// fontSize: 12
|
|
||||||
// })
|
|
||||||
// ], {
|
|
||||||
// align: "center",
|
|
||||||
// justify: "center",
|
|
||||||
// gap: 5,
|
|
||||||
// height: 12,
|
|
||||||
// page: pages[0]
|
|
||||||
// }),
|
|
||||||
// flex([
|
|
||||||
// checkbox(8, 8), text("Sonstiges", {
|
|
||||||
// color: rgb(0,0,0),
|
|
||||||
// font,
|
|
||||||
// fontSize: 12
|
|
||||||
// })
|
|
||||||
// ], {
|
|
||||||
// align: "center",
|
|
||||||
// justify: "center",
|
|
||||||
// gap: 5,
|
|
||||||
// height: 12,
|
|
||||||
// page: pages[0]
|
|
||||||
// })
|
|
||||||
// ], {
|
|
||||||
// align: "center",
|
|
||||||
// justify: "space-between",
|
|
||||||
// gap: 15,
|
|
||||||
// x: marginX,
|
|
||||||
// y: height - marginY - 165,
|
|
||||||
// height: 12,
|
|
||||||
// width: containerWidth
|
|
||||||
// })
|
|
||||||
|
|
||||||
// layout.draw(pages[0])
|
|
||||||
|
|
||||||
// pdf.getForm().flatten()
|
|
||||||
|
|
||||||
return pdf.save();
|
|
||||||
}
|
|
||||||
366
src/lib/pdf/pdfDatenblattVerbrauchsausweisWohnen.ts
Normal file
366
src/lib/pdf/pdfDatenblattVerbrauchsausweisWohnen.ts
Normal file
@@ -0,0 +1,366 @@
|
|||||||
|
import { VerbrauchsausweisWohnenClient } from "#components/Ausweis/types.js";
|
||||||
|
import { endEnergieVerbrauchVerbrauchsausweis_2016 } from "#lib/Berechnungen/VerbrauchsausweisWohnen/VerbrauchsausweisWohnen_2016.js";
|
||||||
|
import * as fs from "fs"
|
||||||
|
import { PDFDocument, rgb, StandardFonts, TextAlignment } from "pdf-lib";
|
||||||
|
import { checkbox, flex, text } from "./elements/index.js";
|
||||||
|
import { xml2pdf } from "./elements/xml2pdf.js";
|
||||||
|
import moment from "moment";
|
||||||
|
import { Heizungsstatus } from "@ibcornelsen/database/server";
|
||||||
|
|
||||||
|
/* -------------------------------- Pdf Tools ------------------------------- */
|
||||||
|
|
||||||
|
export async function pdfDatenblattVerbrauchsausweisWohnen(ausweis: VerbrauchsausweisWohnenClient) {
|
||||||
|
const VerbrauchsausweisWohnenGEG2024PDF = fs.readFileSync(new URL("./templates/Leerseite_Datenblatt.pdf", import.meta.url), "base64");
|
||||||
|
const pdf = await PDFDocument.load(VerbrauchsausweisWohnenGEG2024PDF)
|
||||||
|
const pages = pdf.getPages()
|
||||||
|
|
||||||
|
// const template = VerbrauchsausweisWohnen2016Template as Template;
|
||||||
|
|
||||||
|
const berechnungen = await endEnergieVerbrauchVerbrauchsausweis_2016(ausweis);
|
||||||
|
|
||||||
|
const height = pages[0].getHeight()
|
||||||
|
const width = pages[0].getWidth()
|
||||||
|
|
||||||
|
const font = await pdf.embedFont(StandardFonts.Helvetica)
|
||||||
|
const bold = await pdf.embedFont(StandardFonts.HelveticaBold)
|
||||||
|
|
||||||
|
const form = pdf.getForm()
|
||||||
|
form.updateFieldAppearances(font)
|
||||||
|
|
||||||
|
const marginX = 60;
|
||||||
|
const marginY = 150;
|
||||||
|
|
||||||
|
const benutzer: typeof ausweis.benutzer = ausweis.benutzer || {
|
||||||
|
vorname: "Max",
|
||||||
|
name: "Mustermann",
|
||||||
|
adresse: "Musterstraße 123",
|
||||||
|
plz: "12345",
|
||||||
|
ort: "Beispielhausen"
|
||||||
|
};
|
||||||
|
|
||||||
|
const translateHeizungsstatus: Record<Heizungsstatus, string> = {
|
||||||
|
BEHEIZT: "beheizt",
|
||||||
|
NICHT_VORHANDEN: "nicht vorhanden",
|
||||||
|
UNBEHEIZT: "unbeheizt"
|
||||||
|
}
|
||||||
|
|
||||||
|
const innerWidth = pages[0].getWidth() - marginX * 2;
|
||||||
|
|
||||||
|
const layout = xml2pdf(`<layout height="${pages[0].getHeight()}" width="${pages[0].getWidth()}" marginTop="150" marginLeft="${marginX}" marginRight="${marginX}">
|
||||||
|
<text size="12" lineHeight="14">${benutzer.vorname} ${benutzer.name}</text>
|
||||||
|
<text size="12" lineHeight="14">${benutzer.adresse}</text>
|
||||||
|
<text size="12" lineHeight="14">${benutzer.plz} ${benutzer.ort}</text>
|
||||||
|
<flex direction="row" justify="space-between" marginTop="55" width="${innerWidth}">
|
||||||
|
<text size="12" font="bold">Datenblatt Energieausweis</text>
|
||||||
|
<text size="12">Ausweis ID: ${ausweis.uid}</text>
|
||||||
|
</flex>
|
||||||
|
<text size="12" lineHeight="14" font="bold" marginTop="10">Gebäudedaten</text>
|
||||||
|
<text size="12" lineHeight="14">Adresse: ${ausweis.gebaeude_aufnahme_allgemein.adresse}, ${ausweis.gebaeude_aufnahme_allgemein.plz} ${ausweis.gebaeude_aufnahme_allgemein.ort}</text>
|
||||||
|
|
||||||
|
<flex direction="row" justify="space-between" width="${innerWidth}" marginTop="25">
|
||||||
|
<flex direction="row" gap="5" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.ausstellgrund === "Neubau"}"></checkbox>
|
||||||
|
<text size="12">Neubau</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="5" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.ausstellgrund === "Verkauf" || ausweis.ausstellgrund === "Vermietung"}"></checkbox>
|
||||||
|
<text size="12">Vermietung/Verkauf</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="5" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.ausstellgrund === "Modernisierung"}"></checkbox>
|
||||||
|
<text size="12">Modernisierung</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="5" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.ausstellgrund === "Sonstiges"}"></checkbox>
|
||||||
|
<text size="12">Sonstiges</text>
|
||||||
|
</flex>
|
||||||
|
</flex>
|
||||||
|
|
||||||
|
<flex direction="row" marginTop="25" gap="15">
|
||||||
|
<flex direction="column" width="${(innerWidth) / 2 - 7.5}">
|
||||||
|
<flex direction="row" align="center" justify="space-between" width="${(innerWidth) / 2 - 7.5}">
|
||||||
|
<text size="12" lineHeight="14">Gebäudetyp:</text>
|
||||||
|
<text size="12" lineHeight="14">${ausweis.gebaeude_aufnahme_allgemein.gebaeudetyp}</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" align="center" justify="space-between" width="${(innerWidth) / 2 - 7.5}">
|
||||||
|
<text size="12" lineHeight="14">Wohnfläche:</text>
|
||||||
|
<text size="12" lineHeight="14">DIN Wohnfläche innen ${ausweis.gebaeude_aufnahme_allgemein.flaeche} m²</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" align="center" justify="space-between" width="${(innerWidth) / 2 - 7.5}">
|
||||||
|
<text size="12" lineHeight="14">Leerstand:</text>
|
||||||
|
<text size="12" lineHeight="14">${ausweis.gebaeude_aufnahme_allgemein.leerstand || 0}%</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" align="center" justify="space-between" width="${(innerWidth) / 2 - 7.5}">
|
||||||
|
<text size="12" lineHeight="14">Wohnungen:</text>
|
||||||
|
<text size="12" lineHeight="14">${ausweis.gebaeude_aufnahme_allgemein.einheiten}</text>
|
||||||
|
</flex>
|
||||||
|
</flex>
|
||||||
|
<flex direction="column" width="${(innerWidth) / 2 - 7.5}">
|
||||||
|
<flex direction="row" align="center" justify="space-between" width="${(innerWidth) / 2 - 7.5}">
|
||||||
|
<text size="12" lineHeight="14">Dachgeschoss:</text>
|
||||||
|
<text size="12" lineHeight="14">${translateHeizungsstatus[ausweis.gebaeude_aufnahme_allgemein.dachgeschoss || "NICHT_VORHANDEN"]}</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" align="center" justify="space-between" width="${(innerWidth) / 2 - 7.5}">
|
||||||
|
<text size="12" lineHeight="14">Keller:</text>
|
||||||
|
<text size="12" lineHeight="14">${translateHeizungsstatus[ausweis.gebaeude_aufnahme_allgemein.keller || "NICHT_VORHANDEN"]}</text>
|
||||||
|
</flex>
|
||||||
|
</flex>
|
||||||
|
</flex>
|
||||||
|
|
||||||
|
<text size="12" lineHeight="14" font="bold" marginTop="25">Verbrauch</text>
|
||||||
|
|
||||||
|
<flex direction="row" justify="space-between" align="center" width="${(innerWidth)}" marginTop="5">
|
||||||
|
<flex direction="column" gap="4">
|
||||||
|
<text></text>
|
||||||
|
<text></text>
|
||||||
|
<text size="12">Von: ${moment(ausweis.startdatum).format("DD.MM.YYYY")}</text>
|
||||||
|
<text size="12">Von: ${moment(ausweis.startdatum).add("1", "years").format("DD.MM.YYYY")}</text>
|
||||||
|
<text size="12">Von: ${moment(ausweis.startdatum).add("2", "years").format("DD.MM.YYYY")}</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="column" gap="4">
|
||||||
|
<text></text>
|
||||||
|
<text></text>
|
||||||
|
<text size="12">Bis: ${moment(ausweis.startdatum).add("1", "year").format("DD.MM.YYYY")}</text>
|
||||||
|
<text size="12">Bis: ${moment(ausweis.startdatum).add("2", "years").format("DD.MM.YYYY")}</text>
|
||||||
|
<text size="12">Bis: ${moment(ausweis.startdatum).add("3", "years").format("DD.MM.YYYY")}</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="column" gap="4">
|
||||||
|
<text></text>
|
||||||
|
<text size="12" font="bold">${ausweis.gebaeude_aufnahme_allgemein.brennstoff_1}</text>
|
||||||
|
<text size="12">${ausweis.verbrauch_1} ${ausweis.einheit_1}</text>
|
||||||
|
<text size="12">${ausweis.verbrauch_2} ${ausweis.einheit_1}</text>
|
||||||
|
<text size="12">${ausweis.verbrauch_3} ${ausweis.einheit_1}</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="column" gap="4">
|
||||||
|
<text size="12">zusätzliche Heizquelle</text>
|
||||||
|
<text size="12" font="bold">${ausweis.gebaeude_aufnahme_allgemein.brennstoff_2 || ""}</text>
|
||||||
|
<text size="12">${ausweis.verbrauch_4 || ""} ${ausweis.einheit_2 || ""}</text>
|
||||||
|
<text size="12">${ausweis.verbrauch_5 || ""} ${ausweis.einheit_2 || ""}</text>
|
||||||
|
<text size="12">${ausweis.verbrauch_6 || ""} ${ausweis.einheit_2 || ""}</text>
|
||||||
|
</flex>
|
||||||
|
</flex>
|
||||||
|
|
||||||
|
<text size="12" marginTop="5">Warmwasseranteil: ${ausweis.anteil_warmwasser_1}%</text>
|
||||||
|
</layout>`, {
|
||||||
|
"default": font,
|
||||||
|
bold: bold
|
||||||
|
})
|
||||||
|
|
||||||
|
const layoutPage2 = xml2pdf(`<layout height="${pages[1].getHeight()}" width="${pages[1].getWidth()}" marginTop="150" marginLeft="60" marginRight="60">
|
||||||
|
<text size="12" font="bold">Stand der Technik:</text>
|
||||||
|
<text size="12" marginTop="15">Heizungsanlage</text>
|
||||||
|
<flex direction="row" justify="space-between" width="${pages[1].getWidth() - 120}" marginTop="15">
|
||||||
|
<flex direction="column" gap="4">
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.zentralheizung || false}"></checkbox>
|
||||||
|
<text size="12">Zentralheizung</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.einzelofen || false}"></checkbox>
|
||||||
|
<text size="12">Einzelöfen</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.durchlauf_erhitzer || false}"></checkbox>
|
||||||
|
<text size="12">Durchlauferhitzer</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.standard_kessel || false}"></checkbox>
|
||||||
|
<text size="12">Standardkessel</text>
|
||||||
|
</flex>
|
||||||
|
</flex>
|
||||||
|
<flex direction="column" gap="4">
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.solarsystem_warmwasser || false}"></checkbox>
|
||||||
|
<text size="12">Solarsystem für Warmwasser</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.waermepumpe || false}"></checkbox>
|
||||||
|
<text size="12">Wärmepumpe</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.niedertemperatur_kessel || false}"></checkbox>
|
||||||
|
<text size="12">Niedertemperaturkessel</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.brennwert_kessel || false}"></checkbox>
|
||||||
|
<text size="12">Brennwertkessel</text>
|
||||||
|
</flex>
|
||||||
|
</flex>
|
||||||
|
<flex direction="column" gap="4">
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.warmwasser_rohre_gedaemmt || false}"></checkbox>
|
||||||
|
<text size="12">Warmwasserrohre gedämmt</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.heizungsrohre_gedaemmt || false}"></checkbox>
|
||||||
|
<text size="12">Heizungsrohre gedämmt</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.zirkulation || false}"></checkbox>
|
||||||
|
<text size="12">Zirkulation</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.raum_temperatur_regler || false}"></checkbox>
|
||||||
|
<text size="12">Raumtemperaturregelung</text>
|
||||||
|
</flex>
|
||||||
|
</flex>
|
||||||
|
</flex>
|
||||||
|
<text size="12" marginTop="15">Fenster/Dachfenster/Türen</text>
|
||||||
|
<flex direction="row" justify="space-between" width="${pages[1].getWidth() - 120}" marginTop="15">
|
||||||
|
<flex direction="column" gap="4">
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.einfach_verglasung || false}"></checkbox>
|
||||||
|
<text size="12">Einfachglas</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.doppel_verglasung || false}"></checkbox>
|
||||||
|
<text size="12">Doppelverglasung</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.isolier_verglasung || false}"></checkbox>
|
||||||
|
<text size="12">Isolierverglasung</text>
|
||||||
|
</flex>
|
||||||
|
</flex>
|
||||||
|
<flex direction="column" gap="4">
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${false}"></checkbox>
|
||||||
|
<text size="12">Passivhausfenster</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.fenster_dicht || false}"></checkbox>
|
||||||
|
<text size="12">Alle Fenster dicht</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.fenster_teilweise_undicht || false}"></checkbox>
|
||||||
|
<text size="12">Fenster teilweise undicht</text>
|
||||||
|
</flex>
|
||||||
|
</flex>
|
||||||
|
<flex direction="column" gap="4">
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.tueren_undicht || false}"></checkbox>
|
||||||
|
<text size="12">Türen teilweise undicht</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.tueren_dicht || false}"></checkbox>
|
||||||
|
<text size="12">Alle Türen dicht</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.rolllaeden_kaesten_gedaemmt || false}"></checkbox>
|
||||||
|
<text size="12">Rollladenkästen gedämmt</text>
|
||||||
|
</flex>
|
||||||
|
</flex>
|
||||||
|
</flex>
|
||||||
|
<text size="12" marginTop="15">Wärmedämmung</text>
|
||||||
|
<flex direction="row" justify="space-between" width="${pages[1].getWidth() - 120}" marginTop="15">
|
||||||
|
<flex direction="column" gap="4">
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.keller_wand_gedaemmt || false}"></checkbox>
|
||||||
|
<text size="12">Kelleraußenwand gedämmt</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.keller_decke_gedaemmt || false}"></checkbox>
|
||||||
|
<text size="12">Kellerdecke gedämmt</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.aussenwand_gedaemmt || false}"></checkbox>
|
||||||
|
<text size="12">Außenwand gedämmt</text>
|
||||||
|
</flex>
|
||||||
|
</flex>
|
||||||
|
<flex direction="column" gap="4">
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.dachgeschoss_min_12cm_gedaemmt || false}"></checkbox>
|
||||||
|
<text size="12">Dachgeschoss min. 12cm gedämmt</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.dachgeschoss_gedaemmt || false}"></checkbox>
|
||||||
|
<text size="12">Dachgeschoss gedämmt</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.oberste_geschossdecke_gedaemmt || false}"></checkbox>
|
||||||
|
<text size="12">Oberste Geschossdecke gedämmt</text>
|
||||||
|
</flex>
|
||||||
|
<flex direction="row" gap="4" align="center">
|
||||||
|
<checkbox width="8" height="8" checked="${ausweis.gebaeude_aufnahme_allgemein.oberste_geschossdecke_min_12cm_gedaemmt || false}"></checkbox>
|
||||||
|
<text size="12">Oberste Geschossdecke min. 12cm gedämmt</text>
|
||||||
|
</flex>
|
||||||
|
</flex>
|
||||||
|
</flex>
|
||||||
|
</layout>`, {
|
||||||
|
"default": font,
|
||||||
|
bold
|
||||||
|
})
|
||||||
|
|
||||||
|
layout.draw(pages[0], 0, pages[0].getHeight())
|
||||||
|
layoutPage2.draw(pages[1], 0, pages[1].getHeight())
|
||||||
|
|
||||||
|
// const containerWidth = width - marginX;
|
||||||
|
|
||||||
|
// const layout = flex([
|
||||||
|
// flex([
|
||||||
|
// checkbox(8, 8), text("Neubau", {
|
||||||
|
// color: rgb(0,0,0),
|
||||||
|
// font,
|
||||||
|
// fontSize: 12
|
||||||
|
// })
|
||||||
|
// ], {
|
||||||
|
// align: "center",
|
||||||
|
// justify: "center",
|
||||||
|
// gap: 5,
|
||||||
|
// height: 12,
|
||||||
|
// page: pages[0]
|
||||||
|
// }),
|
||||||
|
// flex([
|
||||||
|
// checkbox(8, 8), text("Vermietung/Verkauf", {
|
||||||
|
// color: rgb(0,0,0),
|
||||||
|
// font,
|
||||||
|
// fontSize: 12
|
||||||
|
// })
|
||||||
|
// ], {
|
||||||
|
// align: "center",
|
||||||
|
// justify: "center",
|
||||||
|
// gap: 5,
|
||||||
|
// height: 12,
|
||||||
|
// page: pages[0]
|
||||||
|
// }),
|
||||||
|
// flex([
|
||||||
|
// checkbox(8, 8), text("Modernisierung", {
|
||||||
|
// color: rgb(0,0,0),
|
||||||
|
// font,
|
||||||
|
// fontSize: 12
|
||||||
|
// })
|
||||||
|
// ], {
|
||||||
|
// align: "center",
|
||||||
|
// justify: "center",
|
||||||
|
// gap: 5,
|
||||||
|
// height: 12,
|
||||||
|
// page: pages[0]
|
||||||
|
// }),
|
||||||
|
// flex([
|
||||||
|
// checkbox(8, 8), text("Sonstiges", {
|
||||||
|
// color: rgb(0,0,0),
|
||||||
|
// font,
|
||||||
|
// fontSize: 12
|
||||||
|
// })
|
||||||
|
// ], {
|
||||||
|
// align: "center",
|
||||||
|
// justify: "center",
|
||||||
|
// gap: 5,
|
||||||
|
// height: 12,
|
||||||
|
// page: pages[0]
|
||||||
|
// })
|
||||||
|
// ], {
|
||||||
|
// align: "center",
|
||||||
|
// justify: "space-between",
|
||||||
|
// gap: 15,
|
||||||
|
// x: marginX,
|
||||||
|
// y: height - marginY - 165,
|
||||||
|
// height: 12,
|
||||||
|
// width: containerWidth
|
||||||
|
// })
|
||||||
|
|
||||||
|
// layout.draw(pages[0])
|
||||||
|
|
||||||
|
// pdf.getForm().flatten()
|
||||||
|
|
||||||
|
return pdf.save();
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { addNotification } from "@ibcornelsen/ui";
|
import { addNotification } from "@ibcornelsen/ui";
|
||||||
import { CrossCircled } from "radix-svelte-icons";
|
import { CrossCircled } from "radix-svelte-icons";
|
||||||
import {client} from "src/trpc";
|
import {client} from "src/trpc.js";
|
||||||
import { fade } from "svelte/transition";
|
import { fade } from "svelte/transition";
|
||||||
|
|
||||||
let passwort: string;
|
let passwort: string;
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import PerformanceScore from "#components/Ausweis/PerformanceScore.svelte";
|
import PerformanceScore from "#components/Ausweis/PerformanceScore.svelte";
|
||||||
import ProgressBar from "#components/Ausweis/Progressbar.svelte";
|
import Progressbar from "#components/Ausweis/Progressbar.svelte";
|
||||||
//import Hilfe from "#components/Ausweis/Hilfe.svelte";
|
import { PRICES } from "#lib/constants.js";
|
||||||
import { PRICES } from "#lib/constants";
|
|
||||||
|
|
||||||
import Bereich from "#labels/Bereich.svelte";
|
import Bereich from "#components/labels/Bereich.svelte";
|
||||||
//import HelpLabel from "#labels/HelpLabel.svelte";
|
|
||||||
//import Inputlabel from "#labels/InputLabel.svelte";
|
|
||||||
//import Label from "#components/Label.svelte";
|
|
||||||
|
|
||||||
import ButtonSpaeterHilfe from "#components/Ausweis/ButtonSpaeterHilfe.svelte";
|
import ButtonSpaeterHilfe from "#components/Ausweis/ButtonSpaeterHilfe.svelte";
|
||||||
import ButtonWeiterHilfe from "#components/Ausweis/ButtonWeiterHilfe.svelte";
|
import ButtonWeiterHilfe from "#components/Ausweis/ButtonWeiterHilfe.svelte";
|
||||||
@@ -24,13 +20,10 @@
|
|||||||
import SanierungszustandWaermedammung from "#components/Ausweis/SanierungszustandWaermedammung.svelte";
|
import SanierungszustandWaermedammung from "#components/Ausweis/SanierungszustandWaermedammung.svelte";
|
||||||
import AusweisPreviewContainer from "#components/Ausweis/AusweisPreviewContainer.svelte";
|
import AusweisPreviewContainer from "#components/Ausweis/AusweisPreviewContainer.svelte";
|
||||||
|
|
||||||
//import ZipSearch from "#components/PlzSuche.svelte";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
RawNotificationWrapper,
|
RawNotificationWrapper,
|
||||||
RawNotification,
|
RawNotification,
|
||||||
notifications,
|
notifications,
|
||||||
deleteNotification,
|
|
||||||
} from "#components/Notifications/index.js";
|
} from "#components/Notifications/index.js";
|
||||||
import { auditHeizungGebaeudeBaujahr } from "#components/Verbrauchsausweis/audits/HeizungGebaeudeBaujahr.js";
|
import { auditHeizungGebaeudeBaujahr } from "#components/Verbrauchsausweis/audits/HeizungGebaeudeBaujahr.js";
|
||||||
import { auditHeizungJuengerDreiJahre } from "#components/Verbrauchsausweis/audits/HeizungJuengerDreiJahre.js";
|
import { auditHeizungJuengerDreiJahre } from "#components/Verbrauchsausweis/audits/HeizungJuengerDreiJahre.js";
|
||||||
@@ -48,38 +41,33 @@
|
|||||||
import { auditVerbrauchAbweichung } from "#components/Verbrauchsausweis/audits/VerbrauchAbweichung.js";
|
import { auditVerbrauchAbweichung } from "#components/Verbrauchsausweis/audits/VerbrauchAbweichung.js";
|
||||||
import { auditEndEnergie } from "#components/Verbrauchsausweis/audits/EndEnergie.js";
|
import { auditEndEnergie } from "#components/Verbrauchsausweis/audits/EndEnergie.js";
|
||||||
import { auditWohnflaecheGroesserGesamtflaeche } from "#components/Verbrauchsausweis/audits/WohnflaecheGroesserGesamtflaeche.js";
|
import { auditWohnflaecheGroesserGesamtflaeche } from "#components/Verbrauchsausweis/audits/WohnflaecheGroesserGesamtflaeche.js";
|
||||||
//import { Enums } from "@ibcornelsen/database/client"
|
|
||||||
import Overlay from "#components/Overlay.svelte";
|
import Overlay from "#components/Overlay.svelte";
|
||||||
import AusweisGespeichertModule from "#modules/VerbrauchsausweisWohnen/AusweisGespeichertModule.svelte";
|
import AusweisGespeichertModule from "#modules/VerbrauchsausweisWohnen/AusweisGespeichertModule.svelte";
|
||||||
import {
|
import type {
|
||||||
VerbrauchsausweisWohnenClient,
|
VerbrauchsausweisWohnenClient,
|
||||||
BenutzerClient,
|
BenutzerClient,
|
||||||
UploadedGebaeudeBild,
|
UploadedGebaeudeBild,
|
||||||
} from "#components/Ausweis/types.js";
|
} from "#components/Ausweis/types.js";
|
||||||
import { verbrauchsausweisWohnenSpeichern } from "src/client/lib/verbrauchsausweisWohnenSpeichern.js";
|
import { verbrauchsausweisWohnenSpeichern } from "src/client/lib/verbrauchsausweisWohnenSpeichern.js";
|
||||||
//import AusweisWeiter from "./AusweisWeiter.svelte";
|
|
||||||
import { Enums } from "@ibcornelsen/database/client";
|
import { Enums } from "@ibcornelsen/database/client";
|
||||||
import { OpenInNewWindow } from "radix-svelte-icons";
|
|
||||||
|
|
||||||
// TODO: Vom Server sollte ein volles Objekt kommen, dass alle Subobjekte enthält, weil es sonst zu Problemen führen kann
|
// TODO: Vom Server sollte ein volles Objekt kommen, dass alle Subobjekte enthält, weil es sonst zu Problemen führen kann
|
||||||
// wenn gebaeude_aufnahme_allgemein oder gebaeude_stammdaten nicht existiert...
|
// wenn gebaeude_aufnahme_allgemein oder gebaeude_stammdaten nicht existiert...
|
||||||
export let ausweis: VerbrauchsausweisWohnenClient;
|
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||||
export let user: BenutzerClient = {} as BenutzerClient;
|
export let user: BenutzerClient = {} as BenutzerClient;
|
||||||
|
|
||||||
export let Energieausweis = "Verbrauchsausweis Wohngebäude";
|
let aufnahme = ausweis.aufnahme || {};
|
||||||
|
let objekt =
|
||||||
let gebaeude_aufnahme_allgemein = ausweis.gebaeude_aufnahme_allgemein || {};
|
ausweis.aufnahme?.objekt || {};
|
||||||
let gebaeude =
|
|
||||||
ausweis.gebaeude_aufnahme_allgemein?.gebaeude_stammdaten || {};
|
|
||||||
let images: (UploadedGebaeudeBild & { base64?: string })[] =
|
let images: (UploadedGebaeudeBild & { base64?: string })[] =
|
||||||
ausweis.gebaeude_aufnahme_allgemein?.gebaeude_stammdaten
|
ausweis.aufnahme?.objekt
|
||||||
?.gebaeude_bilder || [];
|
?.gebaeude_bilder || [];
|
||||||
|
|
||||||
async function spaeterWeitermachen() {
|
async function spaeterWeitermachen() {
|
||||||
const result = await verbrauchsausweisWohnenSpeichern(
|
const result = await verbrauchsausweisWohnenSpeichern(
|
||||||
ausweis,
|
ausweis,
|
||||||
gebaeude,
|
objekt,
|
||||||
gebaeude_aufnahme_allgemein,
|
aufnahme,
|
||||||
images,
|
images,
|
||||||
user
|
user
|
||||||
);
|
);
|
||||||
@@ -88,8 +76,8 @@
|
|||||||
// Falls der Nutzer zurück navigiert, sollte er wieder auf seinen Vorgang kommen.
|
// Falls der Nutzer zurück navigiert, sollte er wieder auf seinen Vorgang kommen.
|
||||||
// Sonst müsste er alles neu eingeben...
|
// Sonst müsste er alles neu eingeben...
|
||||||
ausweis.uid = result.uid;
|
ausweis.uid = result.uid;
|
||||||
gebaeude.uid = result.gebaeude_uid;
|
objekt.uid = result.gebaeude_uid;
|
||||||
gebaeude_aufnahme_allgemein.uid = result.gebaeude_aufnahme_uid;
|
aufnahme.uid = result.gebaeude_aufnahme_uid;
|
||||||
window.history.pushState(
|
window.history.pushState(
|
||||||
{},
|
{},
|
||||||
"",
|
"",
|
||||||
@@ -100,35 +88,35 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function automatischAusfüllen() {
|
function automatischAusfüllen() {
|
||||||
gebaeude_aufnahme_allgemein.baujahr_gebaeude = [1962];
|
aufnahme.baujahr_gebaeude = [1962];
|
||||||
gebaeude_aufnahme_allgemein.baujahr_heizung = [1952];
|
aufnahme.baujahr_heizung = [1952];
|
||||||
gebaeude_aufnahme_allgemein.saniert = true;
|
aufnahme.saniert = true;
|
||||||
gebaeude_aufnahme_allgemein.einheiten = 1;
|
aufnahme.einheiten = 1;
|
||||||
gebaeude_aufnahme_allgemein.gebaeudetyp = "Einfamilienhaus";
|
aufnahme.gebaeudetyp = "Einfamilienhaus";
|
||||||
gebaeude_aufnahme_allgemein.keller =
|
aufnahme.keller =
|
||||||
Enums.Heizungsstatus.NICHT_VORHANDEN;
|
Enums.Heizungsstatus.NICHT_VORHANDEN;
|
||||||
gebaeude_aufnahme_allgemein.dachgeschoss =
|
aufnahme.dachgeschoss =
|
||||||
Enums.Heizungsstatus.NICHT_VORHANDEN;
|
Enums.Heizungsstatus.NICHT_VORHANDEN;
|
||||||
gebaeude_aufnahme_allgemein.lueftung = "Fensterlüftung";
|
aufnahme.lueftung = "Fensterlueftung";
|
||||||
gebaeude_aufnahme_allgemein.kuehlung = "1";
|
aufnahme.kuehlung = "1";
|
||||||
ausweis.ausstellgrund = "Vermietung";
|
ausweis.ausstellgrund = "Vermietung";
|
||||||
ausweis.verbrauch_1 = 15000;
|
ausweis.verbrauch_1 = 15000;
|
||||||
ausweis.verbrauch_2 = 14000;
|
ausweis.verbrauch_2 = 14000;
|
||||||
ausweis.verbrauch_3 = 16000;
|
ausweis.verbrauch_3 = 16000;
|
||||||
gebaeude_aufnahme_allgemein.flaeche = 152;
|
aufnahme.flaeche = 152;
|
||||||
gebaeude_aufnahme_allgemein.nutzflaeche = 172;
|
aufnahme.nutzflaeche = 172;
|
||||||
ausweis.keller_beheizt = true;
|
ausweis.keller_beheizt = true;
|
||||||
|
|
||||||
gebaeude_aufnahme_allgemein.brennstoff_1 = "Erdgas H";
|
aufnahme.brennstoff_1 = "Erdgas H";
|
||||||
ausweis.einheit_1 = "kWh";
|
ausweis.einheit_1 = "kWh";
|
||||||
ausweis.anteil_warmwasser_1 = 18;
|
ausweis.anteil_warmwasser_1 = 18;
|
||||||
ausweis.startdatum = moment("01.01.2021").toDate();
|
ausweis.startdatum = moment("01.01.2021").toDate();
|
||||||
gebaeude_aufnahme_allgemein.plz = "21039";
|
objekt.plz = "21039";
|
||||||
gebaeude_aufnahme_allgemein.ort = "Hamburg";
|
objekt.ort = "Hamburg";
|
||||||
gebaeude_aufnahme_allgemein.adresse = "Curslacker Deich 170";
|
objekt.adresse = "Curslacker Deich 170";
|
||||||
gebaeude_aufnahme_allgemein.gebaeudeteil = "Gesamtgebäude";
|
aufnahme.gebaeudeteil = "Gesamtgebäude";
|
||||||
|
|
||||||
gebaeude = gebaeude;
|
objekt = objekt;
|
||||||
ausweis = ausweis;
|
ausweis = ausweis;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,8 +124,8 @@
|
|||||||
if (e && e.preventDefault) e.preventDefault();
|
if (e && e.preventDefault) e.preventDefault();
|
||||||
const result = await verbrauchsausweisWohnenSpeichern(
|
const result = await verbrauchsausweisWohnenSpeichern(
|
||||||
ausweis,
|
ausweis,
|
||||||
gebaeude,
|
objekt,
|
||||||
gebaeude_aufnahme_allgemein,
|
aufnahme,
|
||||||
images,
|
images,
|
||||||
user
|
user
|
||||||
);
|
);
|
||||||
@@ -146,8 +134,8 @@
|
|||||||
// Falls der Nutzer zurück navigiert, sollte er wieder auf seinen Vorgang kommen.
|
// Falls der Nutzer zurück navigiert, sollte er wieder auf seinen Vorgang kommen.
|
||||||
// Sonst müsste er alles neu eingeben...
|
// Sonst müsste er alles neu eingeben...
|
||||||
ausweis.uid = result.uid;
|
ausweis.uid = result.uid;
|
||||||
gebaeude.uid = result.gebaeude_uid;
|
objekt.uid = result.gebaeude_uid;
|
||||||
gebaeude_aufnahme_allgemein.uid = result.gebaeude_aufnahme_uid;
|
aufnahme.uid = result.gebaeude_aufnahme_uid;
|
||||||
window.history.pushState(
|
window.history.pushState(
|
||||||
{},
|
{},
|
||||||
"",
|
"",
|
||||||
@@ -162,13 +150,13 @@
|
|||||||
|
|
||||||
$: {
|
$: {
|
||||||
if (
|
if (
|
||||||
gebaeude_aufnahme_allgemein.saniert &&
|
aufnahme.saniert &&
|
||||||
gebaeude_aufnahme_allgemein.oberste_geschossdecke_gedaemmt ===
|
aufnahme.oberste_geschossdecke_gedaemmt ===
|
||||||
undefined &&
|
undefined &&
|
||||||
gebaeude_aufnahme_allgemein.dachgeschoss_gedaemmt === undefined
|
aufnahme.dachgeschoss_gedaemmt === undefined
|
||||||
) {
|
) {
|
||||||
gebaeude_aufnahme_allgemein.oberste_geschossdecke_gedaemmt = true;
|
aufnahme.oberste_geschossdecke_gedaemmt = true;
|
||||||
gebaeude_aufnahme_allgemein.dachgeschoss_gedaemmt = true;
|
aufnahme.dachgeschoss_gedaemmt = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,8 +186,8 @@
|
|||||||
<div id="performance-box" class="w-full box relative px-4 order-2 2xl:order-1 self-stretch grid grid-cols-1">
|
<div id="performance-box" class="w-full box relative px-4 order-2 2xl:order-1 self-stretch grid grid-cols-1">
|
||||||
<PerformanceScore
|
<PerformanceScore
|
||||||
bind:ausweis
|
bind:ausweis
|
||||||
bind:gebaeude_aufnahme_allgemein
|
bind:gebaeude_aufnahme_allgemein={aufnahme}
|
||||||
bind:gebaeude
|
bind:gebaeude={objekt}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -223,8 +211,8 @@
|
|||||||
|
|
||||||
<Bereich bereich="A" title="Prüfung der Ausweisart">
|
<Bereich bereich="A" title="Prüfung der Ausweisart">
|
||||||
<Ausweisart
|
<Ausweisart
|
||||||
bind:gebaeude
|
bind:gebaeude={objekt}
|
||||||
bind:gebaeude_aufnahme_allgemein
|
bind:gebaeude_aufnahme_allgemein={aufnahme}
|
||||||
bind:ausweis
|
bind:ausweis
|
||||||
{Energieausweis}
|
{Energieausweis}
|
||||||
/>
|
/>
|
||||||
@@ -235,7 +223,7 @@
|
|||||||
<Bereich
|
<Bereich
|
||||||
bereich="B"
|
bereich="B"
|
||||||
title="Eingabe der Gebäudeadresse - Angaben zu Wohnfläche, Keller und Dachgeschoss"
|
title="Eingabe der Gebäudeadresse - Angaben zu Wohnfläche, Keller und Dachgeschoss"
|
||||||
><GebaeudeDaten bind:gebaeude_aufnahme_allgemein /></Bereich
|
><GebaeudeDaten bind:gebaeude_aufnahme_allgemein={aufnahme} /></Bereich
|
||||||
>
|
>
|
||||||
|
|
||||||
<!-- C Eingabe von 3 zusammenhängenden Verbrauchsjahren -->
|
<!-- C Eingabe von 3 zusammenhängenden Verbrauchsjahren -->
|
||||||
@@ -244,8 +232,8 @@
|
|||||||
bereich="C"
|
bereich="C"
|
||||||
title="Eingabe von 3 zusammenhängenden Verbrauchsjahren"
|
title="Eingabe von 3 zusammenhängenden Verbrauchsjahren"
|
||||||
><Verbrauch
|
><Verbrauch
|
||||||
bind:gebaeude
|
bind:gebaeude={objekt}
|
||||||
bind:gebaeude_aufnahme_allgemein
|
bind:gebaeude_aufnahme_allgemein={aufnahme}
|
||||||
bind:ausweis
|
bind:ausweis
|
||||||
/></Bereich
|
/></Bereich
|
||||||
>
|
>
|
||||||
@@ -263,7 +251,7 @@
|
|||||||
<Bereich
|
<Bereich
|
||||||
bereich="E"
|
bereich="E"
|
||||||
title="Eingabe von Gebäudeteil, Lüftung, Kühlung und Leerstand"
|
title="Eingabe von Gebäudeteil, Lüftung, Kühlung und Leerstand"
|
||||||
><LueftungundLeerstand bind:gebaeude_aufnahme_allgemein /></Bereich
|
><LueftungundLeerstand bind:gebaeude_aufnahme_allgemein={aufnahme} /></Bereich
|
||||||
>
|
>
|
||||||
|
|
||||||
<!-- F Angaben zur Heizungsanlage -->
|
<!-- F Angaben zur Heizungsanlage -->
|
||||||
@@ -271,8 +259,8 @@
|
|||||||
<Bereich bereich="F" title="Angaben zur Heizunganlage"
|
<Bereich bereich="F" title="Angaben zur Heizunganlage"
|
||||||
><SanierungszustandHeizungsanlage
|
><SanierungszustandHeizungsanlage
|
||||||
bind:images
|
bind:images
|
||||||
bind:gebaeude
|
bind:gebaeude={objekt}
|
||||||
bind:gebaeude_aufnahme_allgemein
|
bind:gebaeude_aufnahme_allgemein={aufnahme}
|
||||||
bind:ausweis
|
bind:ausweis
|
||||||
/></Bereich
|
/></Bereich
|
||||||
>
|
>
|
||||||
@@ -282,8 +270,8 @@
|
|||||||
<Bereich bereich="G" title="Angaben zu Fenster, Dachfenster und Türen"
|
<Bereich bereich="G" title="Angaben zu Fenster, Dachfenster und Türen"
|
||||||
><SanierungszustandFensterTueren
|
><SanierungszustandFensterTueren
|
||||||
bind:images
|
bind:images
|
||||||
bind:gebaeude
|
bind:gebaeude={objekt}
|
||||||
bind:gebaeude_aufnahme_allgemein
|
bind:gebaeude_aufnahme_allgemein={aufnahme}
|
||||||
bind:ausweis
|
bind:ausweis
|
||||||
/></Bereich
|
/></Bereich
|
||||||
>
|
>
|
||||||
@@ -292,8 +280,8 @@
|
|||||||
<Bereich bereich="H" title="Angaben zur Wärmedämmung"
|
<Bereich bereich="H" title="Angaben zur Wärmedämmung"
|
||||||
><SanierungszustandWaermedammung
|
><SanierungszustandWaermedammung
|
||||||
bind:images
|
bind:images
|
||||||
bind:gebaeude
|
bind:gebaeude={objekt}
|
||||||
bind:gebaeude_aufnahme_allgemein
|
bind:gebaeude_aufnahme_allgemein={aufnahme}
|
||||||
bind:ausweis
|
bind:ausweis
|
||||||
/></Bereich
|
/></Bereich
|
||||||
>
|
>
|
||||||
@@ -304,7 +292,7 @@
|
|||||||
><AusweisPreviewContainer
|
><AusweisPreviewContainer
|
||||||
bind:images
|
bind:images
|
||||||
bind:ausweis
|
bind:ausweis
|
||||||
bind:gebaeude
|
bind:gebaeude={objekt}
|
||||||
/></Bereich
|
/></Bereich
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@@ -313,8 +301,8 @@
|
|||||||
bind:ausweis
|
bind:ausweis
|
||||||
bind:images
|
bind:images
|
||||||
bind:user
|
bind:user
|
||||||
bind:gebaeude
|
bind:gebaeude={objekt}
|
||||||
bind:gebaeude_aufnahme_allgemein
|
bind:gebaeude_aufnahme_allgemein={aufnahme}
|
||||||
>
|
>
|
||||||
</ButtonWeiterHilfe>
|
</ButtonWeiterHilfe>
|
||||||
|
|
||||||
@@ -330,7 +318,7 @@
|
|||||||
</RawNotification>
|
</RawNotification>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
{#if auditBedarfsausweisBenoetigt(ausweis, gebaeude_aufnahme_allgemein)}
|
{#if auditBedarfsausweisBenoetigt(ausweis, aufnahme)}
|
||||||
<RawNotification
|
<RawNotification
|
||||||
notification={{
|
notification={{
|
||||||
message: "Bedarfsausweis benötigt!",
|
message: "Bedarfsausweis benötigt!",
|
||||||
@@ -346,7 +334,7 @@
|
|||||||
</RawNotification>
|
</RawNotification>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if gebaeude_aufnahme_allgemein.nutzflaeche && gebaeude_aufnahme_allgemein.flaeche && gebaeude_aufnahme_allgemein.flaeche === gebaeude_aufnahme_allgemein.nutzflaeche}
|
{#if aufnahme.nutzflaeche && aufnahme.flaeche && aufnahme.flaeche === aufnahme.nutzflaeche}
|
||||||
<RawNotification
|
<RawNotification
|
||||||
notification={{
|
notification={{
|
||||||
message: "Plausibilitätsprüfung",
|
message: "Plausibilitätsprüfung",
|
||||||
@@ -361,7 +349,7 @@
|
|||||||
</RawNotification>
|
</RawNotification>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if typeof gebaeude_aufnahme_allgemein.einheiten === "number" && gebaeude_aufnahme_allgemein.einheiten < 1}
|
{#if typeof aufnahme.einheiten === "number" && aufnahme.einheiten < 1}
|
||||||
<RawNotification
|
<RawNotification
|
||||||
notification={{
|
notification={{
|
||||||
message: "Plausibilitätsprüfung",
|
message: "Plausibilitätsprüfung",
|
||||||
@@ -376,7 +364,7 @@
|
|||||||
</RawNotification>
|
</RawNotification>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#await auditPlzNichtErkannt(gebaeude_aufnahme_allgemein) then result}
|
{#await auditPlzNichtErkannt(aufnahme) then result}
|
||||||
{#if result}
|
{#if result}
|
||||||
<RawNotification
|
<RawNotification
|
||||||
notification={{
|
notification={{
|
||||||
@@ -394,7 +382,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{/await}
|
{/await}
|
||||||
|
|
||||||
{#if auditHeizungGebaeudeBaujahr(gebaeude_aufnahme_allgemein)}
|
{#if auditHeizungGebaeudeBaujahr(aufnahme)}
|
||||||
<RawNotification
|
<RawNotification
|
||||||
notification={{
|
notification={{
|
||||||
message: "Plausibilitätsprüfung",
|
message: "Plausibilitätsprüfung",
|
||||||
@@ -403,7 +391,7 @@
|
|||||||
dismissable: true,
|
dismissable: true,
|
||||||
onUserDismiss: () => {
|
onUserDismiss: () => {
|
||||||
hidden.add(AuditType.HEIZUNG_GEBAEUDE_BAUJAHR);
|
hidden.add(AuditType.HEIZUNG_GEBAEUDE_BAUJAHR);
|
||||||
gebaeude_aufnahme_allgemein = gebaeude_aufnahme_allgemein;
|
aufnahme = aufnahme;
|
||||||
},
|
},
|
||||||
type: "warning",
|
type: "warning",
|
||||||
}}
|
}}
|
||||||
@@ -413,7 +401,7 @@
|
|||||||
</RawNotification>
|
</RawNotification>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if auditHeizungJuengerDreiJahre(gebaeude_aufnahme_allgemein)}
|
{#if auditHeizungJuengerDreiJahre(aufnahme)}
|
||||||
<RawNotification
|
<RawNotification
|
||||||
notification={{
|
notification={{
|
||||||
message: "Plausibilitätsprüfung",
|
message: "Plausibilitätsprüfung",
|
||||||
@@ -422,7 +410,7 @@
|
|||||||
dismissable: true,
|
dismissable: true,
|
||||||
onUserDismiss: () => {
|
onUserDismiss: () => {
|
||||||
hidden.add(AuditType.HEIZUNG_JUENGER_DREI_JAHRE);
|
hidden.add(AuditType.HEIZUNG_JUENGER_DREI_JAHRE);
|
||||||
gebaeude = gebaeude;
|
objekt = objekt;
|
||||||
},
|
},
|
||||||
type: "warning",
|
type: "warning",
|
||||||
}}
|
}}
|
||||||
@@ -436,7 +424,7 @@
|
|||||||
</RawNotification>
|
</RawNotification>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if auditZeitraumAktuell(ausweis, gebaeude)}
|
{#if auditZeitraumAktuell(ausweis, objekt)}
|
||||||
<RawNotification
|
<RawNotification
|
||||||
notification={{
|
notification={{
|
||||||
message: "Plausibilitätsprüfung",
|
message: "Plausibilitätsprüfung",
|
||||||
@@ -445,7 +433,7 @@
|
|||||||
dismissable: true,
|
dismissable: true,
|
||||||
onUserDismiss: () => {
|
onUserDismiss: () => {
|
||||||
hidden.add(AuditType.ZEITRAUM_AKTUELL);
|
hidden.add(AuditType.ZEITRAUM_AKTUELL);
|
||||||
gebaeude = gebaeude;
|
objekt = objekt;
|
||||||
},
|
},
|
||||||
type: "warning",
|
type: "warning",
|
||||||
}}
|
}}
|
||||||
@@ -458,7 +446,7 @@
|
|||||||
</RawNotification>
|
</RawNotification>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#await auditKlimaFaktoren(ausweis, gebaeude) then result}
|
{#await auditKlimaFaktoren(ausweis, objekt) then result}
|
||||||
{#if result}
|
{#if result}
|
||||||
<RawNotification
|
<RawNotification
|
||||||
notification={{
|
notification={{
|
||||||
@@ -468,7 +456,7 @@
|
|||||||
dismissable: true,
|
dismissable: true,
|
||||||
onUserDismiss: () => {
|
onUserDismiss: () => {
|
||||||
hidden.add(AuditType.KLIMA_FAKTOREN);
|
hidden.add(AuditType.KLIMA_FAKTOREN);
|
||||||
gebaeude = gebaeude;
|
objekt = objekt;
|
||||||
},
|
},
|
||||||
type: "warning",
|
type: "warning",
|
||||||
}}
|
}}
|
||||||
@@ -483,7 +471,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{/await}
|
{/await}
|
||||||
|
|
||||||
{#if auditWohnFlaeche(gebaeude_aufnahme_allgemein)}
|
{#if auditWohnFlaeche(aufnahme)}
|
||||||
<RawNotification
|
<RawNotification
|
||||||
notification={{
|
notification={{
|
||||||
message: "Plausibilitätsprüfung",
|
message: "Plausibilitätsprüfung",
|
||||||
@@ -492,7 +480,7 @@
|
|||||||
dismissable: true,
|
dismissable: true,
|
||||||
onUserDismiss: () => {
|
onUserDismiss: () => {
|
||||||
hidden.add(AuditType.WOHN_FLAECHE);
|
hidden.add(AuditType.WOHN_FLAECHE);
|
||||||
gebaeude = gebaeude;
|
objekt = objekt;
|
||||||
},
|
},
|
||||||
type: "warning",
|
type: "warning",
|
||||||
}}
|
}}
|
||||||
@@ -512,7 +500,7 @@
|
|||||||
dismissable: true,
|
dismissable: true,
|
||||||
onUserDismiss: () => {
|
onUserDismiss: () => {
|
||||||
hidden.add(AuditType.WARM_WASSER);
|
hidden.add(AuditType.WARM_WASSER);
|
||||||
gebaeude = gebaeude;
|
objekt = objekt;
|
||||||
},
|
},
|
||||||
type: "warning",
|
type: "warning",
|
||||||
}}
|
}}
|
||||||
@@ -522,7 +510,7 @@
|
|||||||
</RawNotification>
|
</RawNotification>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if auditLeerStand(gebaeude_aufnahme_allgemein)}
|
{#if auditLeerStand(aufnahme)}
|
||||||
<RawNotification
|
<RawNotification
|
||||||
notification={{
|
notification={{
|
||||||
message: "Plausibilitätsprüfung",
|
message: "Plausibilitätsprüfung",
|
||||||
@@ -531,7 +519,7 @@
|
|||||||
dismissable: true,
|
dismissable: true,
|
||||||
onUserDismiss: () => {
|
onUserDismiss: () => {
|
||||||
hidden.add(AuditType.LEER_STAND);
|
hidden.add(AuditType.LEER_STAND);
|
||||||
gebaeude = gebaeude;
|
objekt = objekt;
|
||||||
},
|
},
|
||||||
type: "warning",
|
type: "warning",
|
||||||
}}
|
}}
|
||||||
@@ -542,7 +530,7 @@
|
|||||||
</RawNotification>
|
</RawNotification>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if auditVerbrauchAbweichung(ausweis, gebaeude_aufnahme_allgemein).length > 0}
|
{#if auditVerbrauchAbweichung(ausweis, aufnahme).length > 0}
|
||||||
<RawNotification
|
<RawNotification
|
||||||
notification={{
|
notification={{
|
||||||
message: "Plausibilitätsprüfung",
|
message: "Plausibilitätsprüfung",
|
||||||
@@ -551,23 +539,23 @@
|
|||||||
dismissable: true,
|
dismissable: true,
|
||||||
onUserDismiss: () => {
|
onUserDismiss: () => {
|
||||||
hidden.add(AuditType.VERBRAUCH_ABWEICHUNG);
|
hidden.add(AuditType.VERBRAUCH_ABWEICHUNG);
|
||||||
gebaeude = gebaeude;
|
objekt = objekt;
|
||||||
},
|
},
|
||||||
type: "warning",
|
type: "warning",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Die Abweichung der Verbräuche zwischen Zeitraum {auditVerbrauchAbweichung(
|
Die Abweichung der Verbräuche zwischen Zeitraum {auditVerbrauchAbweichung(
|
||||||
ausweis,
|
ausweis,
|
||||||
gebaeude_aufnahme_allgemein
|
aufnahme
|
||||||
)[0]} und {auditVerbrauchAbweichung(
|
)[0]} und {auditVerbrauchAbweichung(
|
||||||
ausweis,
|
ausweis,
|
||||||
gebaeude_aufnahme_allgemein
|
aufnahme
|
||||||
)[1]} beträgt mehr als 30% und sie haben keinen Leerstand angegeben.
|
)[1]} beträgt mehr als 30% und sie haben keinen Leerstand angegeben.
|
||||||
Sind sie sich sicher, dass das stimmt?
|
Sind sie sich sicher, dass das stimmt?
|
||||||
</RawNotification>
|
</RawNotification>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#await auditEndEnergie(ausweis, gebaeude, gebaeude_aufnahme_allgemein) then result}
|
{#await auditEndEnergie(ausweis, objekt, aufnahme) then result}
|
||||||
{#if result}
|
{#if result}
|
||||||
<RawNotification
|
<RawNotification
|
||||||
notification={{
|
notification={{
|
||||||
@@ -577,7 +565,7 @@
|
|||||||
dismissable: true,
|
dismissable: true,
|
||||||
onUserDismiss: () => {
|
onUserDismiss: () => {
|
||||||
hidden.add(AuditType.END_ENERGIE);
|
hidden.add(AuditType.END_ENERGIE);
|
||||||
gebaeude = gebaeude;
|
objekt = objekt;
|
||||||
},
|
},
|
||||||
type: "warning",
|
type: "warning",
|
||||||
}}
|
}}
|
||||||
@@ -589,7 +577,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{/await}
|
{/await}
|
||||||
|
|
||||||
{#if auditWohnflaecheGroesserGesamtflaeche(gebaeude_aufnahme_allgemein)}
|
{#if auditWohnflaecheGroesserGesamtflaeche(aufnahme)}
|
||||||
<RawNotification
|
<RawNotification
|
||||||
notification={{
|
notification={{
|
||||||
message: "Plausibilitätsprüfung",
|
message: "Plausibilitätsprüfung",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ layout: ../layouts/Layout.astro
|
|||||||
title: "Welcher Energieausweis?"
|
title: "Welcher Energieausweis?"
|
||||||
---
|
---
|
||||||
|
|
||||||
import WelcherAusweisWidget from "#widgets/WelcherAusweisWidget.svelte";
|
import WelcherAusweisWidget from "#components/widgets/WelcherAusweisWidget.svelte";
|
||||||
import TextboxCardTemplate from "#components/design/content/TextboxCardTemplate.svelte";
|
import TextboxCardTemplate from "#components/design/content/TextboxCardTemplate.svelte";
|
||||||
|
|
||||||
# Welcher Energieausweis ist der richtige?
|
# Welcher Energieausweis ist der richtige?
|
||||||
|
|||||||
46
src/pages/api/aufnahme/[id].ts
Normal file
46
src/pages/api/aufnahme/[id].ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
|
||||||
|
import { prisma } from "@ibcornelsen/database/server";
|
||||||
|
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||||
|
|
||||||
|
export const PATCH = defineApiRoute({
|
||||||
|
fetch(input, context) {},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const GET = defineApiRoute({
|
||||||
|
meta: {
|
||||||
|
description: "Gibt eine spezifische Aufnhame eines Objektes des Benutzers zurück.",
|
||||||
|
tags: ["Aufnahme"],
|
||||||
|
headers: {
|
||||||
|
"Authorization": {
|
||||||
|
description: "Ein gültiger Authentifizierungstoken",
|
||||||
|
required: true,
|
||||||
|
allowEmptyValue: false,
|
||||||
|
examples: {
|
||||||
|
Bearer: {
|
||||||
|
value: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
middleware: authorizationMiddleware,
|
||||||
|
async fetch(input, context, user) {
|
||||||
|
const { uid } = context.params;
|
||||||
|
|
||||||
|
const aufnahme = await prisma.aufnahme.findUnique({
|
||||||
|
where: {
|
||||||
|
uid,
|
||||||
|
benutzer_id: user.id
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!aufnahme) {
|
||||||
|
throw new APIError({
|
||||||
|
code: "NOT_FOUND",
|
||||||
|
message: "Aufnahme mit dieser UID existiert nicht oder gehört nicht dem aktuellen Benutzer."
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return aufnahme
|
||||||
|
},
|
||||||
|
});
|
||||||
0
src/pages/api/aufnahme/index.ts
Normal file
0
src/pages/api/aufnahme/index.ts
Normal file
125
src/pages/api/auth/access-token.ts
Normal file
125
src/pages/api/auth/access-token.ts
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
import moment from "moment";
|
||||||
|
import { prisma } from "@ibcornelsen/database/server";
|
||||||
|
import { TokenType, encodeToken } from "../../../lib/auth/token.js";
|
||||||
|
import { TRPCError } from "@trpc/server";
|
||||||
|
import { defineApiRoute } from "astro-typesafe-api/server";
|
||||||
|
|
||||||
|
export const tRPC_V1_BenutzerGetAccessTokenProcedure = defineApiRoute({
|
||||||
|
meta: {
|
||||||
|
description:
|
||||||
|
"Erstellt, basierend auf einem existierenden und gültigen Refresh Tokens, einen neuen Access Token, welcher zur Authentifizierung genutzt werden kann. Der resultierende Access Token ist nur 2 Tage gültig und muss danach neu generiert werden. Diese Funktion gibt ebenfalls einen neuen Refresh Token zurück, der alte wird dadurch invalidiert.",
|
||||||
|
tags: ["Benutzer"],
|
||||||
|
summary: "Access Token anfragen.",
|
||||||
|
},
|
||||||
|
input: z.object({
|
||||||
|
refreshToken: z.string(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
output: z.object({
|
||||||
|
accessToken: z.string(),
|
||||||
|
accessTokenExpiry: z.number(),
|
||||||
|
refreshToken: z.string(),
|
||||||
|
refreshTokenExpiry: z.number(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
async fetch(input, ctx) {
|
||||||
|
/**
|
||||||
|
* Wir benutzen rolling refresh tokens, also löschen wir den alten Token und stellen einen neuen aus,
|
||||||
|
* damit dieser nicht geklaut werden kann.
|
||||||
|
*/
|
||||||
|
const response = await prisma.refreshTokens.findUnique({
|
||||||
|
where: {
|
||||||
|
token: input.refreshToken,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "Der gegebene refresh token ist nicht gültig.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.expiry < new Date()) {
|
||||||
|
// Falls der Token abgelaufen ist, müssen wir ihn löschen.
|
||||||
|
await prisma.refreshTokens.delete({
|
||||||
|
where: {
|
||||||
|
id: response.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "Der gegebene refresh token ist nicht gültig.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Das können wir später implementieren, falls wir das wirklich brauchen.
|
||||||
|
// if (response.ip !== opts.ctx.ip) {
|
||||||
|
// // Falls der Token nicht von der selben IP Adresse kommt, müssen wir ihn löschen.
|
||||||
|
// await prisma.refreshTokens.delete({
|
||||||
|
// where: {
|
||||||
|
// id: response.id
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// throw new TRPCError({ code: "BAD_REQUEST", message: "Der gegebene refresh token wurde von einer anderen IP-Adresse ausgestellt, aus Sicherheitsgründen haben wir uns entschieden diesen zu invalidieren." });
|
||||||
|
// }
|
||||||
|
|
||||||
|
const user = await prisma.benutzer.findUnique({
|
||||||
|
where: {
|
||||||
|
id: response.benutzer_id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
// Falls der Nutzer nicht mehr existiert müssen wir den Refresh Token invalidieren.
|
||||||
|
await prisma.refreshTokens.delete({
|
||||||
|
where: {
|
||||||
|
id: response.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "Der gegebene refresh token ist nicht mehr gültig.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wir löschen den alten Token.
|
||||||
|
await prisma.refreshTokens.delete({
|
||||||
|
where: {
|
||||||
|
id: response.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const refreshTokenExpiry = moment().add(30, "days");
|
||||||
|
const refreshToken = encodeToken({
|
||||||
|
uid: user.uid,
|
||||||
|
typ: TokenType.Refresh,
|
||||||
|
exp: refreshTokenExpiry.unix(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Und erstellen einen neuen
|
||||||
|
await prisma.refreshTokens.create({
|
||||||
|
data: {
|
||||||
|
benutzer_id: user.id,
|
||||||
|
expiry: refreshTokenExpiry.toDate(),
|
||||||
|
ip: ctx.clientAddress ?? "",
|
||||||
|
token: refreshToken,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const accessTokenExpiry = moment().add(2, "days").unix();
|
||||||
|
const accessToken = encodeToken({
|
||||||
|
uid: user.uid,
|
||||||
|
typ: TokenType.Access,
|
||||||
|
exp: accessTokenExpiry,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
accessToken,
|
||||||
|
accessTokenExpiry: accessTokenExpiry,
|
||||||
|
refreshToken,
|
||||||
|
refreshTokenExpiry: refreshTokenExpiry.unix(),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
82
src/pages/api/auth/refresh-token.ts
Normal file
82
src/pages/api/auth/refresh-token.ts
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
import moment from "moment";
|
||||||
|
import { prisma } from "@ibcornelsen/database/server";
|
||||||
|
import { TokenType, encodeToken } from "../../../lib/auth/token.js";
|
||||||
|
import { hashPassword, validatePassword } from "../../../lib/password.js";
|
||||||
|
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||||
|
|
||||||
|
export const GET = defineApiRoute({
|
||||||
|
meta: {
|
||||||
|
description:
|
||||||
|
"Erstellt sowohl einen neuen Refresh Token als auch einen Access Token für den gegebenen Benutzer. Der Refresh Token kann später für die Erstellung neuer Access Token genutzt werden.",
|
||||||
|
tags: ["Benutzer"],
|
||||||
|
summary: "Refresh Token anfragen.",
|
||||||
|
},
|
||||||
|
input: z.object({
|
||||||
|
email: z.string().email(),
|
||||||
|
passwort: z.string().min(8).max(100),
|
||||||
|
}),
|
||||||
|
output: z.object({
|
||||||
|
uid: z.string().uuid(),
|
||||||
|
accessToken: z.string(),
|
||||||
|
refreshToken: z.string(),
|
||||||
|
refreshTokenBase64: z.string(),
|
||||||
|
accessTokenBase64: z.string(),
|
||||||
|
exp: z.number(),
|
||||||
|
}),
|
||||||
|
async fetch(input, ctx) {
|
||||||
|
console.log(input);
|
||||||
|
|
||||||
|
// Falls der Nutzer nicht existiert, wird eine Fehlermeldung zurückgegeben.
|
||||||
|
const user = await prisma.benutzer.findUnique({
|
||||||
|
where: {
|
||||||
|
email: input.email,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
throw new APIError({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "Benutzer konnte nicht gefunden werden.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Falls das Passwort nicht stimmt, wird eine Fehlermeldung zurückgegeben.
|
||||||
|
if (!validatePassword(user.passwort, input.passwort)) {
|
||||||
|
throw new APIError({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "Benutzer konnte nicht gefunden werden.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const refreshTokenExpiry = moment().add(30, "days");
|
||||||
|
const accessToken = encodeToken({
|
||||||
|
uid: user.uid,
|
||||||
|
typ: TokenType.Access,
|
||||||
|
exp: moment().add(30, "minutes").valueOf(),
|
||||||
|
});
|
||||||
|
const refreshToken = encodeToken({
|
||||||
|
uid: user.uid,
|
||||||
|
typ: TokenType.Refresh,
|
||||||
|
exp: refreshTokenExpiry.valueOf(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const { id } = await prisma.refreshTokens.create({
|
||||||
|
data: {
|
||||||
|
token: refreshToken,
|
||||||
|
benutzer_id: user.id,
|
||||||
|
ip: ctx.clientAddress ?? "",
|
||||||
|
expiry: refreshTokenExpiry.toDate(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
uid: user.uid,
|
||||||
|
accessToken,
|
||||||
|
refreshToken,
|
||||||
|
refreshTokenBase64: Buffer.from(refreshToken).toString("base64"),
|
||||||
|
accessTokenBase64: Buffer.from(accessToken).toString("base64"),
|
||||||
|
exp: refreshTokenExpiry.valueOf(),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
0
src/pages/api/bedarfsausweis-wohnen/index.ts
Normal file
0
src/pages/api/bedarfsausweis-wohnen/index.ts
Normal file
46
src/pages/api/objekt/[id].ts
Normal file
46
src/pages/api/objekt/[id].ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
|
||||||
|
import { prisma } from "@ibcornelsen/database/server";
|
||||||
|
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||||
|
|
||||||
|
export const PATCH = defineApiRoute({
|
||||||
|
fetch(input, context) {},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const GET = defineApiRoute({
|
||||||
|
meta: {
|
||||||
|
description: "Gibt ein spezifisches Gebäude des Benutzers zurück.",
|
||||||
|
tags: ["Gebäude"],
|
||||||
|
headers: {
|
||||||
|
"Authorization": {
|
||||||
|
description: "Ein gültiger Authentifizierungstoken",
|
||||||
|
required: true,
|
||||||
|
allowEmptyValue: false,
|
||||||
|
examples: {
|
||||||
|
Bearer: {
|
||||||
|
value: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
middleware: authorizationMiddleware,
|
||||||
|
async fetch(input, context, user) {
|
||||||
|
const { uid } = context.params;
|
||||||
|
|
||||||
|
const objekt = await prisma.objekt.findUnique({
|
||||||
|
where: {
|
||||||
|
uid,
|
||||||
|
benutzer_id: user.id
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!objekt) {
|
||||||
|
throw new APIError({
|
||||||
|
code: "NOT_FOUND",
|
||||||
|
message: "Objekt mit dieser UID existiert nicht oder gehört nicht dem aktuellen Benutzer."
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return objekt
|
||||||
|
},
|
||||||
|
});
|
||||||
30
src/pages/api/objekt/index.ts
Normal file
30
src/pages/api/objekt/index.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
|
||||||
|
import { ObjektSchema, prisma } from "@ibcornelsen/database/server";
|
||||||
|
import { defineApiRoute } from "astro-typesafe-api/server";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export const POST = defineApiRoute({
|
||||||
|
fetch(input, context) {
|
||||||
|
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export const GET = defineApiRoute({
|
||||||
|
input: z.object({
|
||||||
|
limit: z.number()
|
||||||
|
}),
|
||||||
|
output: z.array(ObjektSchema),
|
||||||
|
middleware: authorizationMiddleware,
|
||||||
|
async fetch(input, context, transfer) {
|
||||||
|
const objekte = await prisma.objekt.findMany({
|
||||||
|
take: input.limit,
|
||||||
|
where: {
|
||||||
|
benutzer: {
|
||||||
|
id: transfer.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return objekte
|
||||||
|
},
|
||||||
|
})
|
||||||
23
src/pages/api/user/self.ts
Normal file
23
src/pages/api/user/self.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { BenutzerSchema } from "@ibcornelsen/database/server";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { defineApiRoute } from "astro-typesafe-api/server";
|
||||||
|
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
|
||||||
|
|
||||||
|
export const GET = defineApiRoute({
|
||||||
|
meta: {
|
||||||
|
description:
|
||||||
|
"Gibt die Daten des momentan eingeloggten Benutzers zurück. Falls der Authorization Key invalid ist wird stattdessen null zurückgegeben.",
|
||||||
|
summary: "Gibt die Daten des eingeloggten Benutzers zurück.",
|
||||||
|
tags: ["Benutzer"],
|
||||||
|
},
|
||||||
|
|
||||||
|
input: z.void(),
|
||||||
|
output: BenutzerSchema.omit({
|
||||||
|
passwort: true,
|
||||||
|
id: true,
|
||||||
|
}).or(z.null()),
|
||||||
|
middleware: authorizationMiddleware,
|
||||||
|
async fetch(input, ctx, transfer) {
|
||||||
|
return transfer;
|
||||||
|
},
|
||||||
|
});
|
||||||
0
src/pages/api/verbrauchsausweis-gewerbe/index.ts
Normal file
0
src/pages/api/verbrauchsausweis-gewerbe/index.ts
Normal file
71
src/pages/api/verbrauchsausweis-wohnen/[id].ts
Normal file
71
src/pages/api/verbrauchsausweis-wohnen/[id].ts
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
|
||||||
|
import { prisma } from "@ibcornelsen/database/server";
|
||||||
|
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||||
|
|
||||||
|
export const PATCH = defineApiRoute({
|
||||||
|
fetch(input, context) {},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const GET = defineApiRoute({
|
||||||
|
meta: {
|
||||||
|
description: "Gibt ein spezifisches Gebäude des Benutzers zurück.",
|
||||||
|
tags: ["Gebäude"],
|
||||||
|
headers: {
|
||||||
|
"Authorization": {
|
||||||
|
description: "Ein gültiger Authentifizierungstoken",
|
||||||
|
required: true,
|
||||||
|
allowEmptyValue: false,
|
||||||
|
examples: {
|
||||||
|
Bearer: {
|
||||||
|
value: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
middleware: authorizationMiddleware,
|
||||||
|
async fetch(input, context, user) {
|
||||||
|
const { uid } = context.params;
|
||||||
|
|
||||||
|
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
|
||||||
|
where: {
|
||||||
|
uid: input.uid,
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
benutzer: true,
|
||||||
|
aufnahme: {
|
||||||
|
include: {
|
||||||
|
objekt: {
|
||||||
|
include: {
|
||||||
|
gebaeude_bilder: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rechnungen: true,
|
||||||
|
events: {
|
||||||
|
include: {
|
||||||
|
benutzer: {
|
||||||
|
select: {
|
||||||
|
uid: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
date: "asc"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!ausweis || (ausweis.benutzer_id !== null && ausweis.benutzer_id !== user.id)) {
|
||||||
|
// Falls wir den Ausweis nicht finden können, werfen wir einen Fehler
|
||||||
|
throw new APIError({
|
||||||
|
code: "NOT_FOUND",
|
||||||
|
message: "Ausweis konnte nicht gefunden werden.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return ausweis
|
||||||
|
},
|
||||||
|
});
|
||||||
71
src/pages/api/verbrauchsausweis-wohnen/index.ts
Normal file
71
src/pages/api/verbrauchsausweis-wohnen/index.ts
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import { authorizationMiddleware } from "#lib/middleware/authorization.js";
|
||||||
|
import { prisma } from "@ibcornelsen/database/server";
|
||||||
|
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||||
|
|
||||||
|
export const PATCH = defineApiRoute({
|
||||||
|
fetch(input, context) {},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const GET = defineApiRoute({
|
||||||
|
meta: {
|
||||||
|
description: "Gibt ein spezifisches Gebäude des Benutzers zurück.",
|
||||||
|
tags: ["Gebäude"],
|
||||||
|
headers: {
|
||||||
|
"Authorization": {
|
||||||
|
description: "Ein gültiger Authentifizierungstoken",
|
||||||
|
required: true,
|
||||||
|
allowEmptyValue: false,
|
||||||
|
examples: {
|
||||||
|
Bearer: {
|
||||||
|
value: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
middleware: authorizationMiddleware,
|
||||||
|
async fetch(input, context, user) {
|
||||||
|
const { uid } = context.params;
|
||||||
|
|
||||||
|
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
|
||||||
|
where: {
|
||||||
|
uid,
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
benutzer: true,
|
||||||
|
aufnahme: {
|
||||||
|
include: {
|
||||||
|
objekt: {
|
||||||
|
include: {
|
||||||
|
gebaeude_bilder: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rechnungen: true,
|
||||||
|
events: {
|
||||||
|
include: {
|
||||||
|
benutzer: {
|
||||||
|
select: {
|
||||||
|
uid: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
date: "asc"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!ausweis || (ausweis.benutzer_id !== null && ausweis.benutzer_id !== user.id)) {
|
||||||
|
// Falls wir den Ausweis nicht finden können, werfen wir einen Fehler
|
||||||
|
throw new APIError({
|
||||||
|
code: "NOT_FOUND",
|
||||||
|
message: "Ausweis konnte nicht gefunden werden.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return ausweis
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
---
|
---
|
||||||
import { createCaller } from "#lib/caller";
|
import { createCaller } from "../../astro-typesafe-api-caller.js";
|
||||||
import UserLayout from "../../layouts/UserLayout.astro";
|
import UserLayout from "../../layouts/UserLayout.astro";
|
||||||
import { validateAccessTokenServer } from "#server/lib/validateAccessToken";
|
import { validateAccessTokenServer } from "#server/lib/validateAccessToken";
|
||||||
import DashboardModule from "#modules/Dashboard/DashboardModule.svelte";
|
import DashboardModule from "#modules/Dashboard/DashboardModule.svelte";
|
||||||
|
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants";
|
||||||
|
|
||||||
const accessTokenValid = await validateAccessTokenServer(Astro);
|
const accessTokenValid = await validateAccessTokenServer(Astro);
|
||||||
|
|
||||||
@@ -12,8 +13,16 @@ if (!accessTokenValid) {
|
|||||||
|
|
||||||
const caller = createCaller(Astro);
|
const caller = createCaller(Astro);
|
||||||
|
|
||||||
const user = await caller.v1.benutzer.self(undefined);
|
const user = await caller.user.self.GET.fetch(undefined, {
|
||||||
const gebaeudeArray = await caller.v1.gebaeude.getMany({ limit: 5 });
|
headers: {
|
||||||
|
"Authorization": `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const gebaeudeArray = await caller.objekt.GET.fetch({ limit: 5 }, {
|
||||||
|
headers: {
|
||||||
|
"Authorization": `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||||
|
}
|
||||||
|
});
|
||||||
---
|
---
|
||||||
|
|
||||||
<UserLayout title="Dashboard">
|
<UserLayout title="Dashboard">
|
||||||
|
|||||||
@@ -2,23 +2,34 @@
|
|||||||
import AusweisLayout from "#layouts/AusweisLayoutDaten.astro";
|
import AusweisLayout from "#layouts/AusweisLayoutDaten.astro";
|
||||||
import VerbrauchsausweisWohnenModule from "#modules/VerbrauchsausweisWohnen/VerbrauchsausweisWohnenModule.svelte";
|
import VerbrauchsausweisWohnenModule from "#modules/VerbrauchsausweisWohnen/VerbrauchsausweisWohnenModule.svelte";
|
||||||
import { VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
import { VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||||
import { createCaller } from "#lib/caller";
|
import { createCaller } from "../../../astro-typesafe-api-caller.js";
|
||||||
|
|
||||||
const uid = Astro.url.searchParams.get("uid");
|
const uid = Astro.url.searchParams.get("uid");
|
||||||
let ausweis: VerbrauchsausweisWohnenClient = {
|
let ausweis: VerbrauchsausweisWohnenClient = {
|
||||||
gebaeude_aufnahme_allgemein: { gebaeude_stammdaten: {} },
|
aufnahme: { objekt: {} },
|
||||||
} as VerbrauchsausweisWohnenClient;
|
} as VerbrauchsausweisWohnenClient;
|
||||||
|
|
||||||
const caller = createCaller(Astro);
|
const caller = await createCaller(Astro);
|
||||||
|
|
||||||
if (uid) {
|
if (uid) {
|
||||||
ausweis = await caller.v1.verbrauchsausweisWohnen.get({
|
try {
|
||||||
uid: uid,
|
ausweis = await caller["verbrauchsausweis-wohnen"]._id.GET.fetch(null, {
|
||||||
});
|
headers: {
|
||||||
|
authorization: "Basic "
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
id: "123"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (!ausweis) {
|
if (!ausweis) {
|
||||||
// Der Ausweis scheint nicht zu existieren.
|
// Der Ausweis scheint nicht zu existieren.
|
||||||
// Wir leiten auf die generische Ausweisseite ohne UID weiter.
|
// Wir leiten auf die generische Ausweisseite ohne UID weiter.
|
||||||
|
return Astro.redirect(
|
||||||
|
"/energieausweis-erstellen/verbrauchsausweis-wohnen"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
return Astro.redirect(
|
return Astro.redirect(
|
||||||
"/energieausweis-erstellen/verbrauchsausweis-wohnen"
|
"/energieausweis-erstellen/verbrauchsausweis-wohnen"
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
import Layout from "#layouts/Layout.astro";
|
import Layout from "#layouts/Layout.astro";
|
||||||
import ProduktVergleich from "#content/ProduktVergleich.svelte";
|
import ProduktVergleich from "#components/design/content/ProduktVergleich.svelte";
|
||||||
import ProduktVergleichGewerbe from "#content/ProduktVergleichGewerbe.svelte";
|
import ProduktVergleichGewerbe from "#components/design/content/ProduktVergleichGewerbe.svelte";
|
||||||
import WelcherAusweisWidget from "#widgets/WelcherAusweisWidget.svelte";
|
import WelcherAusweisWidget from "#components/widgets/WelcherAusweisWidget.svelte";
|
||||||
import TextboxCardTemplate from "#components/design/content/TextboxCardTemplate.svelte";
|
import TextboxCardTemplate from "#components/design/content/TextboxCardTemplate.svelte";
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
import { BenutzerClient, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
import { BenutzerClient, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||||
import { createCaller } from "#lib/caller";
|
import { createCaller } from "#lib/caller";
|
||||||
import { pdfDatenblatt } from "#lib/pdf/pdfDatenblatt";
|
import { pdfDatenblattVerbrauchsausweisWohnen } from "#lib/pdf/pdfDatenblattVerbrauchsausweisWohnen";
|
||||||
|
|
||||||
const base64 = Astro.url.searchParams.get("base64");
|
const base64 = Astro.url.searchParams.get("base64");
|
||||||
let ausweis: VerbrauchsausweisWohnenClient | null = null;
|
let ausweis: VerbrauchsausweisWohnenClient | null = null;
|
||||||
@@ -23,7 +23,7 @@ if (base64) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const pdf = await pdfDatenblatt(ausweis);
|
const pdf = await pdfDatenblattVerbrauchsausweisWohnen(ausweis);
|
||||||
|
|
||||||
|
|
||||||
return new Response(pdf, {
|
return new Response(pdf, {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
import Layout from "#layouts/Layout.astro";
|
import Layout from "#layouts/Layout.astro";
|
||||||
import WelcherAusweisWidget from "#widgets/WelcherAusweisWidget.svelte";
|
import WelcherAusweisWidget from "#components/widgets/WelcherAusweisWidget.svelte";
|
||||||
import TextboxCardTemplate from "#components/design/content/TextboxCardTemplate.svelte";
|
import TextboxCardTemplate from "#components/design/content/TextboxCardTemplate.svelte";
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
|
|
||||||
import Layout from "#layouts/WidgetLayout_1.astro";
|
import WelcherAusweisWidget from "#components/widgets/WelcherAusweisWidget.svelte";
|
||||||
import WelcherAusweisWidget from "#widgets/WelcherAusweisWidget_1.svelte";
|
|
||||||
|
|
||||||
const { vermittler } = Astro.params;
|
const { vermittler } = Astro.params;
|
||||||
|
|
||||||
|
|||||||
@@ -27,20 +27,9 @@
|
|||||||
"#modules/*": ["./src/modules/*"],
|
"#modules/*": ["./src/modules/*"],
|
||||||
"#client/*": ["./src/client/*"],
|
"#client/*": ["./src/client/*"],
|
||||||
"#server/*": ["./src/server/*"],
|
"#server/*": ["./src/server/*"],
|
||||||
"#style/*": ["./src/style/*"],
|
"#style/*": ["./src/style/*"]
|
||||||
|
|
||||||
"#footer/*": ["./src/components/design/footer/*"],
|
|
||||||
"#header/*": ["./src/components/design/header/*"],
|
|
||||||
"#content/*": ["./src/components/design/content/*"],
|
|
||||||
"#sidebarCards/*": ["./src/components/design/sidebars/cards/*"],
|
|
||||||
"#sidebarLeft/*": ["./src/components/design/sidebars/left/*"],
|
|
||||||
"#sidebarRight/*": ["./src/components/design/sidebars/right/*"],
|
|
||||||
|
|
||||||
"#ausweise/*": ["./src/pages/energieausweis-erstellen/*"],
|
|
||||||
"#labels/*": ["./src/components/labels/*"],
|
|
||||||
"#widgets/*": ["./src/components/widgets/*"]
|
|
||||||
},
|
},
|
||||||
"types": ["cypress", "cypress-file-upload", "bun-types", "svelte"]
|
"types": ["cypress", "cypress-file-upload", "bun-types", "svelte"]
|
||||||
},
|
},
|
||||||
"exclude": ["node_modules"]
|
"include": ["src/**/*", "tests/**/*"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user