Dashboard, Datenblatt usw.
This commit is contained in:
15
bun.lock
15
bun.lock
@@ -38,6 +38,7 @@
|
||||
"postcss-nested": "^7.0.2",
|
||||
"radix-svelte-icons": "^1.0.0",
|
||||
"sass": "^1.83.4",
|
||||
"siema": "^1.5.1",
|
||||
"svelte": "^3.59.2",
|
||||
"svelte-dialogs": "^1.2.2",
|
||||
"svelte-preprocess": "^5.1.4",
|
||||
@@ -59,6 +60,7 @@
|
||||
"@types/jsonwebtoken": "^9.0.7",
|
||||
"@types/mime-types": "^2.1.4",
|
||||
"@types/nodemailer": "^6.4.17",
|
||||
"@types/siema": "^1.4.11",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||
"@typescript-eslint/parser": "^5.62.0",
|
||||
@@ -67,7 +69,6 @@
|
||||
"cypress": "^13.17.0",
|
||||
"cypress-file-upload": "^5.0.8",
|
||||
"cypress-vite": "^1.6.0",
|
||||
"daisyui": "^4.12.23",
|
||||
"eslint": "~8.15.0",
|
||||
"eslint-config-prettier": "8.1.0",
|
||||
"postcss": "^8.5.1",
|
||||
@@ -566,6 +567,8 @@
|
||||
|
||||
"@types/serve-static": ["@types/serve-static@1.15.7", "", { "dependencies": { "@types/http-errors": "*", "@types/node": "*", "@types/send": "*" } }, "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw=="],
|
||||
|
||||
"@types/siema": ["@types/siema@1.4.11", "", {}, "sha512-bPazsNVnMryrzZx2HiAeDXEpgaO98ToQk0cYJ/7yomLlVNHsn4IYPrLoQ50tQt11FGvkkNoepRyKcTNUhqjj+g=="],
|
||||
|
||||
"@types/sinonjs__fake-timers": ["@types/sinonjs__fake-timers@8.1.1", "", {}, "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g=="],
|
||||
|
||||
"@types/sizzle": ["@types/sizzle@2.3.9", "", {}, "sha512-xzLEyKB50yqCUPUJkIsrVvoWNfFUbIZI+RspLWt8u+tIW/BetMBZtgV2LY/2o+tYH8dRvQ+eoPf3NdhQCcLE2w=="],
|
||||
@@ -848,8 +851,6 @@
|
||||
|
||||
"css-animation": ["css-animation@1.6.1", "", { "dependencies": { "babel-runtime": "6.x", "component-classes": "^1.2.5" } }, "sha512-/48+/BaEaHRY6kNQ2OIPzKf9A6g8WjZYjhiNDNuIVbsm5tXCGIAsHDjB4Xu1C4vXJtUWZo26O68OQkDpNBaPog=="],
|
||||
|
||||
"css-selector-tokenizer": ["css-selector-tokenizer@0.8.0", "", { "dependencies": { "cssesc": "^3.0.0", "fastparse": "^1.1.2" } }, "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg=="],
|
||||
|
||||
"css-styled": ["css-styled@1.0.8", "", { "dependencies": { "@daybrush/utils": "^1.13.0" } }, "sha512-tCpP7kLRI8dI95rCh3Syl7I+v7PP+2JYOzWkl0bUEoSbJM+u8ITbutjlQVf0NC2/g4ULROJPi16sfwDIO8/84g=="],
|
||||
|
||||
"css-to-mat": ["css-to-mat@1.1.1", "", { "dependencies": { "@daybrush/utils": "^1.13.0", "@scena/matrix": "^1.0.0" } }, "sha512-kvpxFYZb27jRd2vium35G7q5XZ2WJ9rWjDUMNT36M3Hc41qCrLXFM5iEKMGXcrPsKfXEN+8l/riB4QzwwwiEyQ=="],
|
||||
@@ -860,8 +861,6 @@
|
||||
|
||||
"csvtojson": ["csvtojson@2.0.10", "", { "dependencies": { "bluebird": "^3.5.1", "lodash": "^4.17.3", "strip-bom": "^2.0.0" }, "bin": { "csvtojson": "./bin/csvtojson" } }, "sha512-lUWFxGKyhraKCW8Qghz6Z0f2l/PqB1W3AO0HKJzGIQ5JRSlR651ekJDiGJbBT4sRNNv5ddnSGVEnsxP9XRCVpQ=="],
|
||||
|
||||
"culori": ["culori@3.3.0", "", {}, "sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ=="],
|
||||
|
||||
"cypress": ["cypress@13.17.0", "", { "dependencies": { "@cypress/request": "^3.0.6", "@cypress/xvfb": "^1.2.4", "@types/sinonjs__fake-timers": "8.1.1", "@types/sizzle": "^2.3.2", "arch": "^2.2.0", "blob-util": "^2.0.2", "bluebird": "^3.7.2", "buffer": "^5.7.1", "cachedir": "^2.3.0", "chalk": "^4.1.0", "check-more-types": "^2.24.0", "ci-info": "^4.0.0", "cli-cursor": "^3.1.0", "cli-table3": "~0.6.1", "commander": "^6.2.1", "common-tags": "^1.8.0", "dayjs": "^1.10.4", "debug": "^4.3.4", "enquirer": "^2.3.6", "eventemitter2": "6.4.7", "execa": "4.1.0", "executable": "^4.1.1", "extract-zip": "2.0.1", "figures": "^3.2.0", "fs-extra": "^9.1.0", "getos": "^3.2.1", "is-installed-globally": "~0.4.0", "lazy-ass": "^1.6.0", "listr2": "^3.8.3", "lodash": "^4.17.21", "log-symbols": "^4.0.0", "minimist": "^1.2.8", "ospath": "^1.2.2", "pretty-bytes": "^5.6.0", "process": "^0.11.10", "proxy-from-env": "1.0.0", "request-progress": "^3.0.0", "semver": "^7.5.3", "supports-color": "^8.1.1", "tmp": "~0.2.3", "tree-kill": "1.2.2", "untildify": "^4.0.0", "yauzl": "^2.10.0" }, "bin": { "cypress": "bin/cypress" } }, "sha512-5xWkaPurwkIljojFidhw8lFScyxhtiFHl/i/3zov+1Z5CmY4t9tjIdvSXfu82Y3w7wt0uR9KkucbhkVvJZLQSA=="],
|
||||
|
||||
"cypress-file-upload": ["cypress-file-upload@5.0.8", "", { "peerDependencies": { "cypress": ">3.0.0" } }, "sha512-+8VzNabRk3zG6x8f8BWArF/xA/W0VK4IZNx3MV0jFWrJS/qKn8eHfa5nU73P9fOQAgwHFJx7zjg4lwOnljMO8g=="],
|
||||
@@ -870,8 +869,6 @@
|
||||
|
||||
"d3-dsv": ["d3-dsv@2.0.0", "", { "dependencies": { "commander": "2", "iconv-lite": "0.4", "rw": "1" }, "bin": { "csv2json": "bin/dsv2json", "csv2tsv": "bin/dsv2dsv", "dsv2dsv": "bin/dsv2dsv", "dsv2json": "bin/dsv2json", "json2csv": "bin/json2dsv", "json2dsv": "bin/json2dsv", "json2tsv": "bin/json2dsv", "tsv2csv": "bin/dsv2dsv", "tsv2json": "bin/dsv2json" } }, "sha512-E+Pn8UJYx9mViuIUkoc93gJGGYut6mSDKy2+XaPwccwkRGlR+LO97L2VCCRjQivTwLHkSnAJG7yo00BWY6QM+w=="],
|
||||
|
||||
"daisyui": ["daisyui@4.12.23", "", { "dependencies": { "css-selector-tokenizer": "^0.8", "culori": "^3", "picocolors": "^1", "postcss-js": "^4" } }, "sha512-EM38duvxutJ5PD65lO/AFMpcw+9qEy6XAZrTpzp7WyaPeO/l+F/Qiq0ECHHmFNcFXh5aVoALY4MGrrxtCiaQCQ=="],
|
||||
|
||||
"dashdash": ["dashdash@1.14.1", "", { "dependencies": { "assert-plus": "^1.0.0" } }, "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g=="],
|
||||
|
||||
"date-fns": ["date-fns@4.1.0", "", {}, "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg=="],
|
||||
@@ -1046,8 +1043,6 @@
|
||||
|
||||
"fast-xml-parser": ["fast-xml-parser@4.5.1", "", { "dependencies": { "strnum": "^1.0.5" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-y655CeyUQ+jj7KBbYMc4FG01V8ZQqjN+gDYGJ50RtfsUB8iG9AmwmwoAgeKLJdmueKKMrH1RJ7yXHTSoczdv5w=="],
|
||||
|
||||
"fastparse": ["fastparse@1.1.2", "", {}, "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ=="],
|
||||
|
||||
"fastq": ["fastq@1.19.0", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA=="],
|
||||
|
||||
"fd-slicer": ["fd-slicer@1.1.0", "", { "dependencies": { "pend": "~1.2.0" } }, "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g=="],
|
||||
@@ -1968,6 +1963,8 @@
|
||||
|
||||
"side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="],
|
||||
|
||||
"siema": ["siema@1.5.1", "", {}, "sha512-BUNFdTSbC9/2gA6r6teBY9B8O/XZOUz8kVyttpsbq4gbHF9PidUDzs6aPtiObhV4KoEuPQdhRvK5hPPi9lgSTg=="],
|
||||
|
||||
"signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
||||
|
||||
"simple-concat": ["simple-concat@1.0.1", "", {}, "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="],
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"postcss-nested": "^7.0.2",
|
||||
"radix-svelte-icons": "^1.0.0",
|
||||
"sass": "^1.83.4",
|
||||
"siema": "^1.5.1",
|
||||
"svelte": "^3.59.2",
|
||||
"svelte-dialogs": "^1.2.2",
|
||||
"svelte-preprocess": "^5.1.4",
|
||||
@@ -73,6 +74,7 @@
|
||||
"@types/jsonwebtoken": "^9.0.7",
|
||||
"@types/mime-types": "^2.1.4",
|
||||
"@types/nodemailer": "^6.4.17",
|
||||
"@types/siema": "^1.4.11",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||
"@typescript-eslint/parser": "^5.62.0",
|
||||
@@ -81,7 +83,6 @@
|
||||
"cypress": "^13.17.0",
|
||||
"cypress-file-upload": "^5.0.8",
|
||||
"cypress-vite": "^1.6.0",
|
||||
"daisyui": "^4.12.23",
|
||||
"eslint": "~8.15.0",
|
||||
"eslint-config-prettier": "8.1.0",
|
||||
"postcss": "^8.5.1",
|
||||
|
||||
@@ -4,13 +4,13 @@ export const createCaller = createCallerFactory({
|
||||
"klimafaktoren": await import("../src/pages/api/klimafaktoren.ts"),
|
||||
"postleitzahlen": await import("../src/pages/api/postleitzahlen.ts"),
|
||||
"admin/ausstellen": await import("../src/pages/api/admin/ausstellen.ts"),
|
||||
"aufnahme/[uid]": await import("../src/pages/api/aufnahme/[uid].ts"),
|
||||
"aufnahme": await import("../src/pages/api/aufnahme/index.ts"),
|
||||
"bedarfsausweis-wohnen/[uid]": await import("../src/pages/api/bedarfsausweis-wohnen/[uid].ts"),
|
||||
"bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"),
|
||||
"auth/access-token": await import("../src/pages/api/auth/access-token.ts"),
|
||||
"auth/forgot-password": await import("../src/pages/api/auth/forgot-password.ts"),
|
||||
"auth/refresh-token": await import("../src/pages/api/auth/refresh-token.ts"),
|
||||
"bedarfsausweis-wohnen/[uid]": await import("../src/pages/api/bedarfsausweis-wohnen/[uid].ts"),
|
||||
"bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"),
|
||||
"aufnahme/[uid]": await import("../src/pages/api/aufnahme/[uid].ts"),
|
||||
"aufnahme": await import("../src/pages/api/aufnahme/index.ts"),
|
||||
"bilder/[uid]": await import("../src/pages/api/bilder/[uid].ts"),
|
||||
"geg-nachweis-verbrauchsausweis-wohnen/[uid]": await import("../src/pages/api/geg-nachweis-verbrauchsausweis-wohnen/[uid].ts"),
|
||||
"geg-nachweis-verbrauchsausweis-wohnen": await import("../src/pages/api/geg-nachweis-verbrauchsausweis-wohnen/index.ts"),
|
||||
@@ -19,8 +19,6 @@ export const createCaller = createCallerFactory({
|
||||
"ticket": await import("../src/pages/api/ticket/index.ts"),
|
||||
"user": await import("../src/pages/api/user/index.ts"),
|
||||
"user/self": await import("../src/pages/api/user/self.ts"),
|
||||
"verbrauchsausweis-wohnen/[uid]": await import("../src/pages/api/verbrauchsausweis-wohnen/[uid].ts"),
|
||||
"verbrauchsausweis-wohnen": await import("../src/pages/api/verbrauchsausweis-wohnen/index.ts"),
|
||||
"verbrauchsausweis-gewerbe/[uid]": await import("../src/pages/api/verbrauchsausweis-gewerbe/[uid].ts"),
|
||||
"verbrauchsausweis-gewerbe": await import("../src/pages/api/verbrauchsausweis-gewerbe/index.ts"),
|
||||
"verbrauchsausweis-wohnen/[uid]": await import("../src/pages/api/verbrauchsausweis-wohnen/[uid].ts"),
|
||||
|
||||
@@ -2,31 +2,13 @@
|
||||
import { Buffer } from "buffer";
|
||||
import { AufnahmeClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisWohnenClient } from "./Ausweis/types.js";
|
||||
import { Enums } from "@ibcornelsen/database/client";
|
||||
import { openWindowWithPost } from "#lib/helpers/window.js";
|
||||
|
||||
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||
export let objekt: ObjektClient;
|
||||
export let aufnahme: AufnahmeClient;
|
||||
export let bilder: UploadedGebaeudeBild[];
|
||||
export let ausweisart: Enums.Ausweisart
|
||||
|
||||
function openWindowWithPost(url: string, data: Record<string, any>) {
|
||||
var form = document.createElement("form");
|
||||
form.target = "_blank";
|
||||
form.method = "POST";
|
||||
form.action = url;
|
||||
form.style.display = "none";
|
||||
|
||||
for (var key in data) {
|
||||
var input = document.createElement("input");
|
||||
input.type = "hidden";
|
||||
input.name = key;
|
||||
input.value = data[key];
|
||||
form.appendChild(input);
|
||||
}
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
document.body.removeChild(form);
|
||||
}
|
||||
</script>
|
||||
|
||||
<button class="border-2 rounded-lg bg-white text-center hover:shadow-md no-underline p-3 cursor-pointer" on:click={() => {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
export let progress: number = 0;
|
||||
export let steps: string[] = [
|
||||
"Gebäudedaten",
|
||||
"Kundendaten",
|
||||
"Kaufbestätigung",
|
||||
];
|
||||
export let active: number;
|
||||
export let progress: number = active / (steps.length - 1) * 100;
|
||||
</script>
|
||||
|
||||
<div class="grid grid-cols-3 self-start justify-between">
|
||||
|
||||
@@ -151,3 +151,20 @@ export function getAusweisartFromUUID(uid: string): Enums.Ausweisart | null {
|
||||
}
|
||||
|
||||
export type UnterlageClient = Omit<Unterlage, "id" | "objekt_id">
|
||||
export type BildClient = Omit<Bild, "id" | "objekt_id">
|
||||
|
||||
export type ObjektKomplettClient = ObjektClient & {
|
||||
bilder: BildClient[],
|
||||
unterlagen: UnterlageClient[],
|
||||
aufnahmen: (AufnahmeClient & {
|
||||
bedarfsausweis_wohnen?: BedarfsausweisWohnenClient,
|
||||
verbrauchsausweis_wohnen?: VerbrauchsausweisWohnenClient,
|
||||
verbrauchsausweis_gewerbe?: VerbrauchsausweisGewerbeClient
|
||||
})[]
|
||||
}
|
||||
|
||||
export type AufnahmeKomplettClient = AufnahmeClient & {
|
||||
bedarfsausweis_wohnen: BedarfsausweisWohnenClient[],
|
||||
verbrauchsausweis_wohnen: VerbrauchsausweisWohnenClient[],
|
||||
verbrauchsausweis_gewerbe: VerbrauchsausweisGewerbeClient[]
|
||||
}
|
||||
174
src/components/Carousel.svelte
Normal file
174
src/components/Carousel.svelte
Normal file
@@ -0,0 +1,174 @@
|
||||
<script lang="ts">
|
||||
import Siema from 'siema'
|
||||
import { onMount, createEventDispatcher } from 'svelte'
|
||||
|
||||
export let perPage = 3
|
||||
export let loop = true
|
||||
export let autoplay = 0
|
||||
export let duration = 200
|
||||
export let easing = 'ease-out'
|
||||
export let startIndex = 0
|
||||
export let draggable = true
|
||||
export let multipleDrag = true
|
||||
export let dots = true
|
||||
export let controls = true
|
||||
export let threshold = 20
|
||||
export let rtl = false
|
||||
let currentIndex = startIndex;
|
||||
|
||||
let siema: Siema
|
||||
let controller: Siema
|
||||
let timer: Timer
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
$: pips = controller ? controller.innerElements : []
|
||||
$: currentPerPage = controller ? controller.perPage : perPage
|
||||
$: totalDots = controller ? Math.ceil(controller.innerElements.length / currentPerPage) : []
|
||||
|
||||
onMount(() => {
|
||||
controller = new Siema({
|
||||
selector: siema,
|
||||
perPage: typeof perPage === 'object' ? perPage : Number(perPage),
|
||||
loop,
|
||||
duration,
|
||||
easing,
|
||||
startIndex,
|
||||
draggable,
|
||||
multipleDrag,
|
||||
threshold,
|
||||
rtl,
|
||||
onChange: handleChange
|
||||
})
|
||||
|
||||
if(autoplay) {
|
||||
timer = setInterval(right, autoplay);
|
||||
}
|
||||
return () => {
|
||||
autoplay && clearInterval(timer)
|
||||
controller.destroy()
|
||||
}
|
||||
})
|
||||
|
||||
export function isDotActive (currentIndex: number, dotIndex: number) {
|
||||
if (currentIndex < 0) currentIndex = pips.length + currentIndex;
|
||||
return currentIndex >= dotIndex*currentPerPage && currentIndex < (dotIndex*currentPerPage)+currentPerPage
|
||||
}
|
||||
|
||||
export function left () {
|
||||
controller.prev()
|
||||
}
|
||||
|
||||
export function right () {
|
||||
controller.next()
|
||||
}
|
||||
|
||||
export function go (index: number) {
|
||||
controller.goTo(index)
|
||||
}
|
||||
|
||||
export function pause() {
|
||||
clearInterval(timer);
|
||||
}
|
||||
|
||||
export function resume() {
|
||||
if (autoplay) {
|
||||
timer = setInterval(right, autoplay);
|
||||
}
|
||||
}
|
||||
|
||||
function handleChange (event: Event) {
|
||||
currentIndex = controller.currentSlide
|
||||
dispatch('change', {
|
||||
currentSlide: controller.currentSlide,
|
||||
slideCount: controller.innerElements.length
|
||||
} )
|
||||
}
|
||||
|
||||
function resetInterval(node, condition) {
|
||||
function handleReset(event) {
|
||||
pause();
|
||||
resume();
|
||||
}
|
||||
|
||||
if(condition) {
|
||||
node.addEventListener('click', handleReset);
|
||||
}
|
||||
|
||||
return {
|
||||
destroy() {
|
||||
node.removeEventListener('click', handleReset);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="carousel">
|
||||
<div class="slides" bind:this={siema}>
|
||||
<slot></slot>
|
||||
</div>
|
||||
{#if controls}
|
||||
<button class="left" on:click={left} use:resetInterval={autoplay} aria-label="left">
|
||||
<slot name="left-control"></slot>
|
||||
</button>
|
||||
<button class="right" on:click={right} use:resetInterval={autoplay} aria-label="right">
|
||||
<slot name="right-control"></slot>
|
||||
</button>
|
||||
{/if}
|
||||
{#if dots}
|
||||
<ul>
|
||||
{#each {length: totalDots} as _, i}
|
||||
<li on:click={() => go(i*currentPerPage)} class={isDotActive(currentIndex, i) ? "active" : ""}></li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.carousel {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
button {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
z-index: 50;
|
||||
margin-top: -20px;
|
||||
}
|
||||
button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.left {
|
||||
left: 2vw;
|
||||
}
|
||||
|
||||
.right {
|
||||
right: 2vw;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
margin-top: -30px;
|
||||
padding: 0;
|
||||
}
|
||||
ul li {
|
||||
margin: 6px;
|
||||
border-radius: 100%;
|
||||
background-color: rgba(255,255,255,0.5);
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
}
|
||||
ul li:hover {
|
||||
background-color: rgba(255,255,255,0.85);
|
||||
}
|
||||
ul li.active {
|
||||
background-color: rgba(255,255,255,1);
|
||||
}
|
||||
</style>
|
||||
@@ -1,10 +1,5 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
AufnahmeClient,
|
||||
ObjektClient,
|
||||
UploadedGebaeudeBild,
|
||||
VerbrauchsausweisWohnenClient,
|
||||
} from "#components/Ausweis/types.js";
|
||||
import { AufnahmeKomplettClient, getAusweisartFromUUID, ObjektKomplettClient, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types.js";
|
||||
import moment from "moment";
|
||||
import { dialogs } from "svelte-dialogs";
|
||||
import {
|
||||
@@ -18,13 +13,15 @@
|
||||
import { api } from "astro-typesafe-api/client";
|
||||
import Cookies from "js-cookie";
|
||||
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
||||
import { Enums } from "@ibcornelsen/database/client";
|
||||
|
||||
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||
export let aufnahme: AufnahmeClient;
|
||||
export let bilder: UploadedGebaeudeBild[];
|
||||
export let objekt: ObjektClient;
|
||||
export let aufnahme: AufnahmeKomplettClient;
|
||||
export let objekt: ObjektKomplettClient;
|
||||
export let progress: number;
|
||||
|
||||
const ausweisart = getAusweisartFromUUID(ausweis.uid);
|
||||
|
||||
async function ausweisStornieren() {
|
||||
const result = await dialogs.confirm({
|
||||
title: "Ausweis Stornieren",
|
||||
@@ -43,14 +40,14 @@
|
||||
if (result === true) {
|
||||
await api["verbrauchsausweis-wohnen"]._uid.DELETE.fetch(undefined, {
|
||||
params: {
|
||||
uid: ausweis.uid
|
||||
uid: ausweis.uid,
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Bearer ${Cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)}`
|
||||
}
|
||||
})
|
||||
Authorization: `Bearer ${Cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)}`,
|
||||
},
|
||||
});
|
||||
|
||||
aufnahme.storniert = true;
|
||||
ausweis.storniert
|
||||
ausweis = ausweis;
|
||||
|
||||
dialogs.alert({
|
||||
@@ -70,21 +67,30 @@
|
||||
let hilfeModal: HTMLDialogElement;
|
||||
</script>
|
||||
|
||||
<div class="card lg:card-side bg-base-200 card-bordered border-base-300">
|
||||
{#if aufnahme.storniert}
|
||||
<div class="absolute top-0 left-0 w-full h-full bg-[rgba(0,0,0,0.7)] z-[5] rounded-lg select-none">
|
||||
<h1 class="absolute -rotate-[25deg] text-5xl md:text-7xl tracking-wide uppercase text-red-500 border-4 border-red-500 rounded-lg top-[50%] translate-y-[-50%] left-[50%] translate-x-[-50%]">Storniert</h1>
|
||||
<div class="card lg:card-side relative bg-base-200 card-bordered border-base-300">
|
||||
{#if ausweis.storniert}
|
||||
<div
|
||||
class="absolute top-0 left-0 w-full h-full bg-[rgba(0,0,0,0.7)] z-[5] rounded-lg select-none"
|
||||
>
|
||||
<h1
|
||||
class="absolute -rotate-[25deg] text-5xl md:text-7xl tracking-wide uppercase text-red-500 border-4 border-red-500 rounded-lg top-[50%] translate-y-[-50%] left-[50%] translate-x-[-50%]"
|
||||
>
|
||||
Storniert
|
||||
</h1>
|
||||
</div>
|
||||
{/if}
|
||||
<figure class="lg:w-1/2">
|
||||
<!-- <figure class="lg:w-1/2">
|
||||
<img
|
||||
src={(bilder.length > 0 && `/bilder/${bilder[0].uid}.webp`) || "/images/placeholder.jpg"}
|
||||
src={(bilder.length > 0 && `/bilder/${bilder[0].uid}.webp`) ||
|
||||
"/images/placeholder.jpg"}
|
||||
class="object-cover w-full h-full"
|
||||
alt="Gebäudebild"
|
||||
/>
|
||||
</figure>
|
||||
<div class="card-body lg:w-1/2">
|
||||
<div class="flex justify-end mb-2 dropdown dropdown-bottom absolute top-4 right-4">
|
||||
</figure> -->
|
||||
<div class="card-body">
|
||||
<div
|
||||
class="flex justify-end mb-2 dropdown dropdown-bottom absolute top-4 right-4"
|
||||
>
|
||||
<button class="rounded-full p-2.5 hover:bg-base-100">
|
||||
<DotsVertical size={15} />
|
||||
</button>
|
||||
@@ -108,41 +114,46 @@
|
||||
</ul>
|
||||
</div>
|
||||
<div class="flex flex-row flex-wrap gap-2">
|
||||
{#if aufnahme.ausweisart == "VerbrauchsausweisWohnen"}
|
||||
{#if ausweisart == Enums.Ausweisart.VerbrauchsausweisWohnen}
|
||||
<div class="badge badge-accent font-semibold">
|
||||
Verbrauchsausweis Wohnen
|
||||
</div>
|
||||
{:else if aufnahme.ausweisart == "BedarfsausweisWohnen"}
|
||||
{:else if ausweisart == Enums.Ausweisart.BedarfsausweisWohnen}
|
||||
<div class="badge badge-accent font-semibold">
|
||||
Bedarfsausweis Wohnen
|
||||
</div>
|
||||
{:else if aufnahme.ausweisart == "VerbrauchsausweisGewerbe"}
|
||||
{:else if ausweisart == Enums.Ausweisart.VerbrauchsausweisGewerbe}
|
||||
<div class="badge badge-accent font-semibold">
|
||||
Verbrauchsausweis Gewerbe
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if aufnahme.erledigt}
|
||||
{#if ausweis.ausgestellt}
|
||||
<div class="badge badge-success font-semibold">Ausgestellt</div>
|
||||
{/if}
|
||||
</div>
|
||||
<h2 class="card-title">{objekt.adresse}</h2>
|
||||
<div class="mb-4 flex flex-row items-center gap-4">
|
||||
<progress class="progress w-full" value={progress} max="100"></progress>
|
||||
<progress class="progress w-full" value={progress} max="100"
|
||||
></progress>
|
||||
<!-- TODO: Metrics für den Fortschritt festlegen -->
|
||||
<span class="text-sm font-semibold text-base-content">{progress}%</span>
|
||||
<span class="text-sm font-semibold text-base-content"
|
||||
>{progress}%</span
|
||||
>
|
||||
</div>
|
||||
{#await endEnergieVerbrauchVerbrauchsausweis_2016(ausweis, aufnahme, objekt)}
|
||||
|
||||
{:then calculations}
|
||||
{#await endEnergieVerbrauchVerbrauchsausweis_2016(ausweis, aufnahme, objekt) then calculations}
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex flex-row justify-between">
|
||||
<span>Energieverbrauch</span>
|
||||
<span class="font-bold text-base-content">{calculations?.endEnergieVerbrauchGesamt}kWh/A</span>
|
||||
<span class="font-bold text-base-content"
|
||||
>{calculations?.endEnergieVerbrauchGesamt}kWh/A</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex flex-row justify-between">
|
||||
<span>CO2 Ausstoß</span>
|
||||
<span class="font-bold text-base-content">{calculations?.co2EmissionenGesamt}Kg/A</span>
|
||||
<span class="font-bold text-base-content"
|
||||
>{calculations?.co2EmissionenGesamt}Kg/A</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex flex-row justify-between">
|
||||
<span>Erstellungsdatum</span>
|
||||
@@ -158,8 +169,7 @@
|
||||
class="font-bold text-base-content"
|
||||
title="Gebäude / Heizung"
|
||||
>{aufnahme.baujahr_gebaeude[0] || "N/A"} /
|
||||
{aufnahme.baujahr_heizung[0] ||
|
||||
"N/A"}</span
|
||||
{aufnahme.baujahr_heizung[0] || "N/A"}</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex flex-row justify-between">
|
||||
@@ -179,8 +189,17 @@
|
||||
</div>
|
||||
{/await}
|
||||
<div class="card-actions justify-end mt-8">
|
||||
<a class="btn btn-primary" href="/energieausweis-erstellen/verbrauchsausweis-wohnen?uid={ausweis.uid}">Bearbeiten</a>
|
||||
<a class="btn btn-ghost" title="PDF Herunterladen" target="_blank" href="/pdf/ansichtsausweis?uid={ausweis.uid}">
|
||||
<a
|
||||
class="btn btn-primary"
|
||||
href="/energieausweis-erstellen/verbrauchsausweis-wohnen?uid={ausweis.uid}"
|
||||
>Bearbeiten</a
|
||||
>
|
||||
<a
|
||||
class="btn btn-ghost"
|
||||
title="PDF Herunterladen"
|
||||
target="_blank"
|
||||
href="/pdf/ansichtsausweis?uid={ausweis.uid}"
|
||||
>
|
||||
<Download size={22} />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
27
src/components/Dashboard/DashboardObjekt.svelte
Normal file
27
src/components/Dashboard/DashboardObjekt.svelte
Normal file
@@ -0,0 +1,27 @@
|
||||
<script lang="ts">
|
||||
import { ObjektKomplettClient } from "#components/Ausweis/types.js";
|
||||
import { Enums } from "@ibcornelsen/database/server";
|
||||
import moment from "moment";
|
||||
import { File, OpenInNewWindow } from "radix-svelte-icons";
|
||||
|
||||
export let objekt: ObjektKomplettClient;
|
||||
|
||||
const objektBild = objekt.bilder.find(bild => bild.kategorie === Enums.BilderKategorie.Gebaeude);
|
||||
</script>
|
||||
|
||||
<div class="border rounded-lg border-base-300 bg-white">
|
||||
{#if objektBild}
|
||||
<img src="/bilder/{objektBild.uid}.webp" class="w-full max-h-72 object-cover rounded-t-lg" alt="Gebäude">
|
||||
{/if}
|
||||
|
||||
<div class="p-4">
|
||||
<div class="flex flex-row justify-between">
|
||||
<h3 class="text-lg font-medium">{objekt.adresse}</h3>
|
||||
<span class="text-sm opacity-70 font-medium">{moment(objekt.erstellungsdatum).format("DD.MM.YYYY")}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row justify-end">
|
||||
<a href="/dashboard/objekt/{objekt.uid}" class="rounded-lg p-2.5 hover:bg-gray-200" target="_blank"><OpenInNewWindow size={20}></OpenInNewWindow></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { ripple } from "svelte-ripple-action";
|
||||
import type { RippleOptions } from "svelte-ripple-action/dist/constants.js";
|
||||
import { Home, Reader, EnvelopeClosed, Cube, Bell, Gear, LockClosed, HamburgerMenu } from "radix-svelte-icons"
|
||||
import { Home, Reader, EnvelopeClosed, Cube, Bell, Gear, LockClosed, HamburgerMenu, CaretDown } from "radix-svelte-icons"
|
||||
import NotificationProvider from "#components/NotificationProvider/NotificationProvider.svelte";
|
||||
import DashboardNotification from "./DashboardNotification.svelte";
|
||||
import { notifications } from "#components/NotificationProvider/shared.js";
|
||||
@@ -20,7 +20,7 @@
|
||||
let headerOpen = false;
|
||||
</script>
|
||||
|
||||
<header class="fixed top-0 left-0 w-full h-16 flex items-center justify-between px-4 border-b z-20">
|
||||
<header class="fixed top-0 left-0 w-full h-16 flex items-center justify-between px-4 border-b z-10 bg-base-200">
|
||||
<button on:click={() => headerOpen = !headerOpen}>
|
||||
{#if headerOpen}
|
||||
<Cross1 size={28}></Cross1>
|
||||
@@ -37,11 +37,11 @@
|
||||
>
|
||||
</header>
|
||||
|
||||
<aside class:hidden={!headerOpen} class="fixed left-0 top-16 w-full h-[calc(100%-4rem)] flex z-30 md:relative md:h-auto md:w-auto md:top-0 md:flex bg-base-100 border-r border-r-base-300 flex-col py-8">
|
||||
<aside class:hidden={!headerOpen} class="fixed left-0 top-16 w-full h-[calc(100%-4rem)] flex z-30 md:relative md:h-auto md:w-auto md:top-0 md:flex bg-base-200 border-r border-r-base-300 flex-col py-4">
|
||||
<a href="/" class="px-8 hidden md:block"
|
||||
><img
|
||||
src="/images/header/logo-big.svg"
|
||||
class="w-36"
|
||||
class="w-24"
|
||||
alt="IBCornelsen - Logo"
|
||||
/></a
|
||||
>
|
||||
@@ -59,10 +59,10 @@
|
||||
<EnvelopeClosed width={22} height={22} />
|
||||
Kontakt
|
||||
</button>
|
||||
<li><details>
|
||||
<li><details class="[&_.caret]:open:rotate-180">
|
||||
<summary class="button-tab w-full outline-0 hover:outline-0">
|
||||
<Cube width={22} height={22} />
|
||||
Services</summary>
|
||||
Services <CaretDown size={24} class="caret ml-auto transition-transform"></CaretDown></summary>
|
||||
<ul>
|
||||
<li>
|
||||
<button use:ripple={rippleOptions} class="button-tab">
|
||||
@@ -77,10 +77,10 @@
|
||||
</ul>
|
||||
</details></li>
|
||||
{#if benutzer.rolle === "ADMIN"}
|
||||
<li><details>
|
||||
<summary class="button-tab w-full outline-0 hover:outline-0">
|
||||
<li><details class="[&_.caret]:open:rotate-180">
|
||||
<summary class="button-tab w-full outline-0 hover:outline-0 cursor-pointer">
|
||||
<LockClosed width={22} height={22} />
|
||||
Admin</summary>
|
||||
Admin <CaretDown size={24} class="caret ml-auto transition-transform"></CaretDown></summary>
|
||||
<ul>
|
||||
<li>
|
||||
<a use:ripple={rippleOptions} class="button-tab" href="/dashboard/admin/ausweise-pruefen">
|
||||
@@ -109,7 +109,7 @@
|
||||
{#if Object.keys($notifications).length > 0}
|
||||
<span class="indicator-item badge badge-accent text-xs">{Object.keys($notifications).length}</span>
|
||||
{/if}
|
||||
<button tabindex="0" class="button btn-square btn-ghost hover:bg-base-200">
|
||||
<button tabindex="0" class="hover:bg-gray-200 p-3 rounded-lg">
|
||||
<Bell size={24} />
|
||||
</button>
|
||||
</div>
|
||||
@@ -119,7 +119,7 @@
|
||||
</div>
|
||||
|
||||
<a href="/dashboard/einstellungen"
|
||||
class="button btn-square btn-ghost hover:bg-base-200"
|
||||
class="hover:bg-gray-200 p-3 rounded-lg"
|
||||
>
|
||||
<Gear size={24} />
|
||||
</a>
|
||||
@@ -129,7 +129,7 @@
|
||||
<a
|
||||
href="/dashboard/einstellungen"
|
||||
use:ripple={rippleOptions}
|
||||
class="button btn-ghost no-animation focus:shadow-none justify-start py-4 h-auto hover:bg-base-200 px-8 rounded-none w-full flex flex-row gap-4"
|
||||
class="hover:bg-gray-200 no-animation focus:shadow-none justify-start py-4 h-auto px-8 rounded-none w-full flex flex-row gap-4"
|
||||
>
|
||||
<div class="avatar">
|
||||
<div class="w-12 rounded-full">
|
||||
@@ -138,34 +138,15 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex flex-col">
|
||||
<span class="text-base-content font-semibold text-left"
|
||||
>{benutzer.vorname} {benutzer.name}</span
|
||||
>
|
||||
<span class="text-base-content">{benutzer.email}</span>
|
||||
<span class="text-base-content text-sm">{benutzer.email}</span>
|
||||
</div>
|
||||
</a>
|
||||
</aside>
|
||||
|
||||
<!--<header class="md:hidden flex flex-row justify-between items-center px-8 sticky top-0 z-50 h-20 bg-base-100 border-b border-b-base-300">
|
||||
<a href="/"
|
||||
><img
|
||||
src="/images/header/logo-big.png"
|
||||
class="w-36"
|
||||
alt="IBCornelsen - Logo"
|
||||
/></a
|
||||
>
|
||||
<div class="dropdown dropdown-end">
|
||||
<button tabindex="0" role="button">
|
||||
<svg width="25" height="25" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M2 4.5C2 4.22386 2.22386 4 2.5 4H12.5C12.7761 4 13 4.22386 13 4.5C13 4.77614 12.7761 5 12.5 5H2.5C2.22386 5 2 4.77614 2 4.5ZM7 7.5C7 7.22386 7.22386 7 7.5 7H12.5C12.7761 7 13 7.22386 13 7.5C13 7.77614 12.7761 8 12.5 8H7.5C7.22386 8 7 7.77614 7 7.5ZM4 10.5C4 10.2239 4.22386 10 4.5 10H12.5C12.7761 10 13 10.2239 13 10.5C13 10.7761 12.7761 11 12.5 11H4.5C4.22386 11 4 10.7761 4 10.5Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg>
|
||||
</button>
|
||||
<ul tabindex="0" class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52">
|
||||
<li><a class="text-base-content">Item 1</a></li>
|
||||
<li><a class="text-base-content">Item 2</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</header>-->
|
||||
|
||||
<style>
|
||||
@import url("https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,200;0,300;0,400;0,500;0,600;0,700;1,400&display=swap");
|
||||
|
||||
@@ -178,7 +159,15 @@
|
||||
} */
|
||||
|
||||
.button-tab:hover {
|
||||
@apply bg-base-200 outline-0;
|
||||
@apply bg-gray-200 outline-0;
|
||||
}
|
||||
|
||||
li {
|
||||
@apply list-none;
|
||||
}
|
||||
|
||||
.button-tab {
|
||||
@apply flex flex-row gap-4 py-2.5 px-4 cursor-pointer items-center;
|
||||
}
|
||||
|
||||
.button-tab:focus {
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
<script lang="ts">
|
||||
import { Buffer } from "buffer";
|
||||
import { AufnahmeClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisWohnenClient } from "./Ausweis/types.js";
|
||||
import { Enums } from "@ibcornelsen/database/client";
|
||||
import { openWindowWithPost } from "#lib/helpers/window.js";
|
||||
|
||||
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||
export let objekt: ObjektClient;
|
||||
export let aufnahme: AufnahmeClient;
|
||||
export let bilder: UploadedGebaeudeBild[];
|
||||
export let ausweisart: Enums.Ausweisart
|
||||
|
||||
|
||||
$: base64Ausweis = Buffer.from(JSON.stringify(ausweis), "utf-8").toString("base64")
|
||||
$: base64Aufnahme = Buffer.from(JSON.stringify(aufnahme), "utf-8").toString("base64")
|
||||
$: base64Objekt = Buffer.from(JSON.stringify(objekt), "utf-8").toString("base64")
|
||||
$: base64Bilder = Buffer.from(JSON.stringify(bilder), "utf-8").toString("base64")
|
||||
</script>
|
||||
|
||||
<a class="border-2 rounded-lg bg-white text-center hover:shadow-md no-underline p-3 cursor-pointer" target="_blank" href="/pdf/datenblatt?ausweis={base64Ausweis}&objekt=${base64Objekt}&aufnahme={base64Aufnahme}&bilder={base64Bilder}">
|
||||
<button class="border-2 rounded-lg bg-white text-center hover:shadow-md no-underline p-3 cursor-pointer" on:click={() => {
|
||||
openWindowWithPost("/pdf/datenblatt", {
|
||||
ausweis: JSON.stringify(ausweis),
|
||||
aufnahme: JSON.stringify(aufnahme),
|
||||
objekt: JSON.stringify(objekt),
|
||||
bilder: JSON.stringify(bilder),
|
||||
ausweisart
|
||||
})
|
||||
}}>
|
||||
<img src="/images/datenblatt.webp" alt="Datenblatt" />
|
||||
<span class="text-black font-medium text-lg">Datenblatt</span>
|
||||
</a>
|
||||
</button>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
export let lightTheme: boolean = Cookies.get("theme") === "light" ? true : false;
|
||||
</script>
|
||||
|
||||
<label class="swap swap-rotate btn btn-square btn-ghost hover:bg-base-200">
|
||||
<label class="hover:bg-gray-200 rounded-lg p-3 cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="theme-controller hidden"
|
||||
@@ -16,6 +16,9 @@
|
||||
}}
|
||||
/>
|
||||
|
||||
<Sun class="swap-on fill-current" size={24} />
|
||||
{#if lightTheme}
|
||||
<Sun class="fill-current" size={24} />
|
||||
{:else}
|
||||
<Moon class="swap-off fill-current" size={24} />
|
||||
{/if}
|
||||
</label>
|
||||
@@ -183,17 +183,17 @@
|
||||
{/if}
|
||||
<li>
|
||||
<a
|
||||
href="/energieausweis-erstellen/verbrauchsausweis-wohngebaeude/"
|
||||
href="/angebot-anfragen/bedarfsausweis-gewerbe-anfragen"
|
||||
>Bedarfsausweis Gewerbe anfragen</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/energieausweis-erstellen/bedarfsausweis-wohngebaeude/"
|
||||
<a href="/angebot-anfragen/geg-nachweis-wohnen-anfragen"
|
||||
>GEG Nachweis Wohnen anfragen</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/energieausweis-erstellen/verbrauchsausweis-gewerbe/"
|
||||
<a href="/angebot-anfragen/geg-nachweis-gewerbe-anfragen"
|
||||
>GEG Nachweis Gewerbe anfragen</a
|
||||
>
|
||||
</li>
|
||||
|
||||
@@ -5,8 +5,6 @@ import "../../svelte-dialogs.config"
|
||||
import "svelte-ripple-action/ripple.css"
|
||||
import DashboardSidebar from "../components/Dashboard/DashboardSidebar.svelte"
|
||||
import { validateAccessTokenServer } from "#server/lib/validateAccessToken";
|
||||
import { createCaller } from "src/astro-typesafe-api-caller";
|
||||
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants";
|
||||
import { BenutzerClient } from "#components/Ausweis/types";
|
||||
|
||||
const valid = validateAccessTokenServer(Astro)
|
||||
@@ -100,7 +98,7 @@ let lightTheme = Astro.cookies.get("theme")?.value === "light";
|
||||
|
||||
<body class="min-h-screen grid md:grid-cols-[300px_1fr]">
|
||||
<DashboardSidebar lightTheme={lightTheme} benutzer={user} client:load></DashboardSidebar>
|
||||
<main class="p-4 md:p-8 overflow-auto h-screen bg-base-100 pt-20 md:!pt-24">
|
||||
<main class="overflow-auto h-screen bg-base-100 pt-24 px-6 w-full">
|
||||
<slot />
|
||||
</main>
|
||||
</body>
|
||||
@@ -62,3 +62,5 @@ export const SERVICES: Record<
|
||||
};
|
||||
|
||||
export const BASE_URI = process.env.NODE_ENV == "production" ? "https://online-energieausweis.org" : "http://localhost:3000";
|
||||
|
||||
export const LEX_OFFICE_API_KEY = process.env.NODE_ENV == "production" ? "iwQLCU_ZAq6bVV7hmR8RO8MiC8Q" : "znjmkmbA3Hbx9dC7wdKp7TnOf1pcRl_tCUwEBZys7bj-QRPG"
|
||||
12
src/lib/helpers.ts
Normal file
12
src/lib/helpers.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export function omit<T extends Record<string, any>, K extends keyof T>(
|
||||
obj: T,
|
||||
keys: K[]
|
||||
): Omit<T, K> {
|
||||
const result: Partial<T> = {};
|
||||
for (const key of Object.keys(obj) as (keyof T)[]) {
|
||||
if (!keys.includes(key as K)) {
|
||||
result[key] = obj[key];
|
||||
}
|
||||
}
|
||||
return result as Omit<T, K>;
|
||||
}
|
||||
18
src/lib/helpers/window.ts
Normal file
18
src/lib/helpers/window.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export function openWindowWithPost(url: string, data: Record<string, any>) {
|
||||
var form = document.createElement("form");
|
||||
form.target = "_blank";
|
||||
form.method = "POST";
|
||||
form.action = url;
|
||||
form.style.display = "none";
|
||||
|
||||
for (var key in data) {
|
||||
var input = document.createElement("input");
|
||||
input.type = "hidden";
|
||||
input.name = key;
|
||||
input.value = data[key];
|
||||
form.appendChild(input);
|
||||
}
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
document.body.removeChild(form);
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
<div class="flex flex-row justify-between">
|
||||
<h1 class="underline font-bold">Datenblatt Energieausweis</h1>
|
||||
<p><span class="font-bold">Ausweis ID:</span> 1225432</p>
|
||||
</div>
|
||||
<h2 class="font-bold">Gebäudedaten</h2>
|
||||
<p>Adresse: Beispielstraße 15, 22587 Beispielnese</p>
|
||||
|
||||
<div class="flex flex-row justify-between">
|
||||
<div class="flex flex-row gap-2">
|
||||
<input type="checkbox">
|
||||
<p>Neubau</p>
|
||||
</div>
|
||||
<div class="flex flex-row gap-2">
|
||||
<input type="checkbox">
|
||||
<p>Vermietung/Verkauf</p>
|
||||
</div>
|
||||
<div class="flex flex-row gap-2">
|
||||
<input type="checkbox">
|
||||
<p>Modernisierung</p>
|
||||
</div>
|
||||
<div class="flex flex-row gap-2">
|
||||
<input type="checkbox">
|
||||
<p>Sonstiges</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="font-bold">Gebäudetyp</td>
|
||||
<td class="font-bold">Wohnfläche</td>
|
||||
<td class="font-bold">Leerstand</td>
|
||||
<td class="font-bold">Wohnungen</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Doppelhaushälfte</td>
|
||||
<td>DIN Wohnfläche innen 141m2</td>
|
||||
<td>0%</td>
|
||||
<td>2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>Dachgeschoss</td>
|
||||
<td>Keller</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>unbeheizt</td>
|
||||
<td>nein</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2 class="font-bold">Verbrauch</h2>
|
||||
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Von: 01.01.2014</td>
|
||||
<td>Von: 01.01.2015</td>
|
||||
<td>Von: 01.01.2016</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Bis: 31.12.2014</td>
|
||||
<td>Bis: 31.12.2015</td>
|
||||
<td>Bis: 31.12.2016</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Heizöl EL</td>
|
||||
<td>1947 l</td>
|
||||
<td>1907 l</td>
|
||||
<td>2248 l</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Brennholz</td>
|
||||
<td>6 m3</td>
|
||||
<td>6 m3</td>
|
||||
<td>6 m3</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>Warmwasseranteil: 18%</p>
|
||||
424
src/lib/pdf/pdfDatenblattVerbrauchsausweisGewerbe.ts
Normal file
424
src/lib/pdf/pdfDatenblattVerbrauchsausweisGewerbe.ts
Normal file
@@ -0,0 +1,424 @@
|
||||
import { AufnahmeClient, BenutzerClient, ObjektClient, VerbrauchsausweisGewerbeClient, 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 { xml2pdf } from "./elements/xml2pdf.js";
|
||||
import moment from "moment";
|
||||
import { Heizungsstatus } from "@ibcornelsen/database/server";
|
||||
import { endEnergieVerbrauchVerbrauchsausweisGewerbe_2016 } from "#lib/Berechnungen/VerbrauchsausweisGewerbe/VerbrauchsausweisGewerbe_2016.js";
|
||||
|
||||
/* -------------------------------- Pdf Tools ------------------------------- */
|
||||
|
||||
export async function pdfDatenblattVerbrauchsausweisGewerbe(ausweis: VerbrauchsausweisGewerbeClient, aufnahme: AufnahmeClient, objekt: ObjektClient, benutzer: BenutzerClient) {
|
||||
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 endEnergieVerbrauchVerbrauchsausweisGewerbe_2016(ausweis, aufnahme, objekt);
|
||||
|
||||
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;
|
||||
|
||||
benutzer = 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 stromverbrauchEnthaelt = []
|
||||
|
||||
if (ausweis.stromverbrauch_enthaelt_beleuchtung) {
|
||||
stromverbrauchEnthaelt.push("Beleuchtung")
|
||||
}
|
||||
if (ausweis.stromverbrauch_enthaelt_heizung) {
|
||||
stromverbrauchEnthaelt.push("Heizung")
|
||||
}
|
||||
if (ausweis.stromverbrauch_enthaelt_kuehlung) {
|
||||
stromverbrauchEnthaelt.push("Kühlung")
|
||||
}
|
||||
if (ausweis.stromverbrauch_enthaelt_lueftung) {
|
||||
stromverbrauchEnthaelt.push("Lüftung")
|
||||
}
|
||||
if (ausweis.stromverbrauch_enthaelt_warmwasser) {
|
||||
stromverbrauchEnthaelt.push("Warmwasser")
|
||||
}
|
||||
if (ausweis.stromverbrauch_enthaelt_sonstige) {
|
||||
stromverbrauchEnthaelt.push("Sonstige")
|
||||
}
|
||||
|
||||
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: ${objekt.adresse}, ${objekt.plz} ${objekt.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">Baujahr Gebäude:</text>
|
||||
<text size="12" lineHeight="14">${aufnahme.baujahr_gebaeude.join(", ")}</text>
|
||||
</flex>
|
||||
<flex direction="row" align="center" justify="space-between" width="${(innerWidth) / 2 - 7.5}">
|
||||
<text size="12" lineHeight="14">Baujahr Heizung:</text>
|
||||
<text size="12" lineHeight="14">${aufnahme.baujahr_heizung.join(", ")}</text>
|
||||
</flex>
|
||||
<flex direction="row" align="center" justify="space-between" width="${(innerWidth) / 2 - 7.5}">
|
||||
<text size="12" lineHeight="14">Nutzfläche:</text>
|
||||
<text size="12" lineHeight="14">Beheizte Nutzfläche ${aufnahme.nutzflaeche} m²</text>
|
||||
</flex>
|
||||
<flex direction="row" align="center" justify="space-between" width="${(innerWidth) / 2 - 7.5}">
|
||||
<text size="12" lineHeight="14">Lüftungskonzept:</text>
|
||||
<text size="12" lineHeight="14">${aufnahme.lueftung}</text>
|
||||
</flex>
|
||||
<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">${aufnahme.gebaeudetyp}</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[aufnahme.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[aufnahme.keller || "NICHT_VORHANDEN"]}</text>
|
||||
</flex>
|
||||
<flex direction="row" align="center" justify="space-between" width="${(innerWidth) / 2 - 7.5}">
|
||||
<text size="12" lineHeight="14">Baujahr Klimaanlage:</text>
|
||||
<text size="12" lineHeight="14">${aufnahme.baujahr_klima.join(", ")}</text>
|
||||
</flex>
|
||||
<flex direction="row" align="center" justify="space-between" width="${(innerWidth) / 2 - 7.5}">
|
||||
<text size="12" lineHeight="14">Anlage zur Kühlung:</text>
|
||||
<text size="12" lineHeight="14">${ausweis.wird_gekuehlt ? "Ja" : "Nein"}</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">${aufnahme.leerstand || 0}%</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">${aufnahme.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">${aufnahme.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" lineHeight="14" font="bold" marginTop="25">Stromverbrauch</text>
|
||||
|
||||
<flex direction="row" justify="space-between" align="center" width="${(innerWidth)}" marginTop="5">
|
||||
<flex direction="column" gap="4">
|
||||
<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 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 size="12">${ausweis.strom_1}</text>
|
||||
<text size="12">${ausweis.strom_2}</text>
|
||||
<text size="12">${ausweis.strom_3}</text>
|
||||
</flex>
|
||||
</flex>
|
||||
<text size="12">Im Stromverbrauch enthalten: ${stromverbrauchEnthaelt.join(", ")}</text>
|
||||
|
||||
<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="${aufnahme.zentralheizung || false}"></checkbox>
|
||||
<text size="12">Zentralheizung</text>
|
||||
</flex>
|
||||
<flex direction="row" gap="4" align="center">
|
||||
<checkbox width="8" height="8" checked="${aufnahme.einzelofen || false}"></checkbox>
|
||||
<text size="12">Einzelöfen</text>
|
||||
</flex>
|
||||
<flex direction="row" gap="4" align="center">
|
||||
<checkbox width="8" height="8" checked="${aufnahme.durchlauf_erhitzer || false}"></checkbox>
|
||||
<text size="12">Durchlauferhitzer</text>
|
||||
</flex>
|
||||
<flex direction="row" gap="4" align="center">
|
||||
<checkbox width="8" height="8" checked="${aufnahme.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="${aufnahme.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="${aufnahme.waermepumpe || false}"></checkbox>
|
||||
<text size="12">Wärmepumpe</text>
|
||||
</flex>
|
||||
<flex direction="row" gap="4" align="center">
|
||||
<checkbox width="8" height="8" checked="${aufnahme.niedertemperatur_kessel || false}"></checkbox>
|
||||
<text size="12">Niedertemperaturkessel</text>
|
||||
</flex>
|
||||
<flex direction="row" gap="4" align="center">
|
||||
<checkbox width="8" height="8" checked="${aufnahme.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="${aufnahme.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="${aufnahme.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="${aufnahme.zirkulation || false}"></checkbox>
|
||||
<text size="12">Zirkulation</text>
|
||||
</flex>
|
||||
<flex direction="row" gap="4" align="center">
|
||||
<checkbox width="8" height="8" checked="${aufnahme.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="${aufnahme.einfach_verglasung || false}"></checkbox>
|
||||
<text size="12">Einfachglas</text>
|
||||
</flex>
|
||||
<flex direction="row" gap="4" align="center">
|
||||
<checkbox width="8" height="8" checked="${aufnahme.doppel_verglasung || false}"></checkbox>
|
||||
<text size="12">Doppelverglasung</text>
|
||||
</flex>
|
||||
<flex direction="row" gap="4" align="center">
|
||||
<checkbox width="8" height="8" checked="${aufnahme.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="${aufnahme.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="${aufnahme.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="${aufnahme.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="${aufnahme.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="${aufnahme.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="${aufnahme.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="${aufnahme.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="${aufnahme.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="${aufnahme.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="${aufnahme.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="${aufnahme.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="${aufnahme.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();
|
||||
}
|
||||
294
src/lib/server/lexoffice.ts
Normal file
294
src/lib/server/lexoffice.ts
Normal file
@@ -0,0 +1,294 @@
|
||||
import { VerbrauchsausweisWohnenClient } from "#components/Ausweis/types.js";
|
||||
import { LEX_OFFICE_API_KEY } from "#lib/constants.js";
|
||||
import { Aufnahme, BedarfsausweisWohnen, Benutzer, Rechnung, VerbrauchsausweisGewerbe, VerbrauchsausweisWohnen } from "@ibcornelsen/database/client";
|
||||
import { prisma } from "@ibcornelsen/database/server";
|
||||
import moment from "moment";
|
||||
|
||||
export function lexOfficeAnfrageSenden(ausweis: VerbrauchsausweisWohnen | BedarfsausweisWohnen | VerbrauchsausweisGewerbe, options: {
|
||||
bezeichnung: string,
|
||||
positionstext: string,
|
||||
preis: number,
|
||||
anschreiben: string
|
||||
}, aufnahme: Aufnahme, rechnung: Rechnung, user: Benutzer) {;
|
||||
if (!user.lex_office_id) {
|
||||
const lex_office_id = await createLexOfficeCustomer(user);
|
||||
|
||||
if (!lex_office_id) {
|
||||
throw new Error("Beim erstellen der Lex Office ID ist etwas schiefgelaufen.")
|
||||
}
|
||||
|
||||
user.lex_office_id = lex_office_id
|
||||
|
||||
await prisma.benutzer.update({
|
||||
where: {
|
||||
id: user.id
|
||||
},
|
||||
data: {
|
||||
lex_office_id
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let response: Response;
|
||||
response = await fetch("https://api.lexoffice.io/v1/quotations?finalize=true", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
Authorization: `Bearer ${LEX_OFFICE_API_KEY}`,
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
"voucherDate": moment(aufnahme.erstellungsdatum).format("YYYY-MM-DDTHH:mm:ss.SSSZ"),
|
||||
"expirationDate": moment(aufnahme.erstellungsdatum).add(1, "month").format("YYYY-MM-DDTHH:mm:ss.SSSZ"),
|
||||
"taxConditions": {
|
||||
"taxType": "gross"
|
||||
},
|
||||
"shippingConditions": {
|
||||
"shippingType": "none"
|
||||
},
|
||||
"address": {
|
||||
"contactId": user.lex_office_id,
|
||||
"name": `${user.vorname} ${user.name}`,
|
||||
"street": rechnung.strasse,
|
||||
"city": rechnung.ort,
|
||||
"zip": rechnung.plz,
|
||||
"countryCode": "DE",
|
||||
"supplement": rechnung.zusatzzeile
|
||||
},
|
||||
"lineItems": [
|
||||
{
|
||||
"type": "custom",
|
||||
"name": options.bezeichnung,
|
||||
"description": options.positionstext,
|
||||
"quantity": 1,
|
||||
"lineItemAmount": options.preis,
|
||||
"unitName": options.bezeichnung,
|
||||
"unitPrice": {
|
||||
"currency": "EUR",
|
||||
"grossAmount": options.preis,
|
||||
"taxRatePercentage": 19
|
||||
}
|
||||
}
|
||||
],
|
||||
"totalPrice": {
|
||||
"currency": "EUR",
|
||||
"totalGrossAmount": options.preis,
|
||||
},
|
||||
"introduction": options.anschreiben,
|
||||
"remark": "Wir freuen uns auf Ihre Auftragserteilung und sichern eine einwandfreie Ausführung zu."
|
||||
})
|
||||
})
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (!result.id) {
|
||||
throw new Error(`Ein Fehler ist aufgetreten: ${result.message}`);
|
||||
}
|
||||
|
||||
// Rechnung PDF Holen
|
||||
|
||||
const lex_office_id = result.id;
|
||||
|
||||
response = await fetch(`https://api.lexoffice.io/v1/quotations/${lex_office_id}/document`, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
Authorization: `Bearer ${LEX_OFFICE_API_KEY}`,
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
})
|
||||
|
||||
const pdfResult = await response.json()
|
||||
|
||||
if (!pdfResult.documentFileId) {
|
||||
throw new Error(`Ein Fehler ist aufgetreten: ${pdfResult.message}`);
|
||||
}
|
||||
|
||||
$pdf_id = $render_response["documentFileId"];
|
||||
|
||||
db()->execute("UPDATE Angebotsanfragen SET
|
||||
Adresse_Objekt = :Adresse_Objekt,
|
||||
PLZ_Objekt = :PLZ_Objekt,
|
||||
Ort_Objekt = :Ort_Objekt,
|
||||
Dienstleistung = :Dienstleistung,
|
||||
Empfaengerrechnung = :Empfaengerrechnung,
|
||||
Zusatzzeilerechnung = :Zusatzzeilerechnung,
|
||||
Adresse = :Adresse,
|
||||
PLZ = :PLZ,
|
||||
Ort = :Ort,
|
||||
Anlass = :Anlass,
|
||||
Baujahrheizung = :Baujahrheizung,
|
||||
Baujahrgebaeude = :Baujahrgebaeude,
|
||||
Baujahrklima = :Baujahrklima,
|
||||
Gebaeudetyp = :Gebaeudetyp,
|
||||
Nutzflaeche = :Nutzflaeche,
|
||||
Sanierungsstatus = :Sanierungsstatus,
|
||||
Nachricht = :Nachricht,
|
||||
Datei = :Datei,
|
||||
Rolle = :Rolle,
|
||||
Email = :Email,
|
||||
Angebotspreis = :Angebotspreis,
|
||||
Rabatt = :Rabatt,
|
||||
`Status` = 'Verschickt',
|
||||
lex_office_id = :lex_office_id,
|
||||
Textanschreiben = :Textanschreiben,
|
||||
Positionstext = :Positionstext
|
||||
WHERE Auftragsnummer = :Auftragsnummer", [
|
||||
"Adresse_Objekt": $_POST["gebaeude_strasse"],
|
||||
"PLZ_Objekt": $_POST["gebaeude_plz"],
|
||||
"Ort_Objekt": $_POST["gebaeude_ort"],
|
||||
"Dienstleistung": $_POST["dienstleistung"],
|
||||
"Empfaengerrechnung": $_POST["rechnung_empfaenger"],
|
||||
"Zusatzzeilerechnung": $_POST["rechnung_zusatzzeile"],
|
||||
"Adresse": $_POST["rechnung_strasse"],
|
||||
"PLZ": $_POST["rechnung_plz"],
|
||||
"Ort": $_POST["rechnung_ort"],
|
||||
"Anlass": $_POST["anlass"],
|
||||
"Baujahrheizung": $_POST["baujahr_heizung"],
|
||||
"Baujahrgebaeude": $_POST["baujahr_gebaeude"],
|
||||
"Baujahrklima": $_POST["baujahr_klimaanlage"],
|
||||
"Gebaeudetyp": $_POST["gebaeudetyp"],
|
||||
"Nutzflaeche": $_POST["nutzflaeche"],
|
||||
"Sanierungsstatus": $_POST["sanierungsstatus"],
|
||||
"Nachricht": $_POST["nachricht"],
|
||||
"Datei": $dateien,
|
||||
"Rolle": $_POST["rolle"],
|
||||
"Email": $_POST["email"],
|
||||
"Angebotspreis": $_POST["Angebotspreis"],
|
||||
"Rabatt": $_POST["Rabatt"],
|
||||
"lex_office_id": $lex_office_id,
|
||||
"Textanschreiben": $_POST["Textanschreiben"],
|
||||
"Positionstext": $_POST["Positionstext"],
|
||||
"Auftragsnummer": $_POST["Auftragsnummer"]
|
||||
]);
|
||||
|
||||
// Die Auftragsnummer abfragen
|
||||
|
||||
$curl_nummer = curl_init();
|
||||
|
||||
curl_setopt_array($curl_nummer, [
|
||||
CURLOPT_URL: "https://api.lexoffice.io/v1/quotations/$lex_office_id",
|
||||
CURLOPT_RETURNTRANSFER: true,
|
||||
CURLOPT_ENCODING: "",
|
||||
CURLOPT_MAXREDIRS: 10,
|
||||
CURLOPT_TIMEOUT: 30,
|
||||
CURLOPT_HTTP_VERSION: CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST: "GET",
|
||||
CURLOPT_HTTPHEADER: [
|
||||
"Accept: application/json",
|
||||
"Authorization: Bearer " . LEX_OFFICE_API_KEY
|
||||
]
|
||||
]);
|
||||
|
||||
$nummer_response = curl_exec($curl_nummer);
|
||||
$nummer_response = json_decode($nummer_response, true);
|
||||
$err = curl_error($curl_nummer);
|
||||
|
||||
curl_close($curl_nummer);
|
||||
|
||||
// Und die Mail verschicken
|
||||
|
||||
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
|
||||
|
||||
$mail->IsSMTP();
|
||||
$mail->Host = "smtp.ionos.de";
|
||||
$mail->SMTPAuth = true;
|
||||
$mail->Username = 'info@online-energieausweis.org';
|
||||
$mail->Password = 'Katendeich5a2024!';
|
||||
|
||||
$mail->CharSet = 'UTF-8';
|
||||
$mail->Encoding = 'base64';
|
||||
$mail->setFrom("info@online-energieausweis.org", "IB Cornelsen",0);
|
||||
$mail->addAddress($_POST["email"], $_POST["vorname"] . " " . $_POST["name"]);
|
||||
$mail->addCC("jens.cornelsen@ib-cornelsen.de", "Jens Cornelsen");
|
||||
$mail->isHTML(true);
|
||||
$mail->Subject = "{$nummer_response["voucherNumber"]} - {$_POST["Angebotsbezeichnung"]}";
|
||||
|
||||
|
||||
// carriage return type (RFC)
|
||||
$eol = "<br>";
|
||||
$anrede = "Sehr geehrte" . ($_POST["anrede"] == "Herr" ? "r " : " ") . $_POST["anrede"];
|
||||
|
||||
$message = "$anrede {$_POST["name"]},{$eol}{$eol}";
|
||||
$message .= "vielen Dank für Ihre Anfrage. Im Anhang finden Sie das ausgearbeitete Angebot als PDF-Dokument.{$eol}{$eol}";
|
||||
$message .= "Mit freundlichen Grüßen,$eol";
|
||||
$message .= "Jens Cornelsen$eol";
|
||||
$message .= "--{$eol}IB Cornelsen{$eol}Katendeich 5A{$eol}21035 Hamburg{$eol}{$eol}www.ib-cornelsen.de{$eol}{$eol}Fon 040 209339858{$eol}Fax 040 209339859";
|
||||
$mail->Body = $message;
|
||||
|
||||
$curl_pdf = curl_init();
|
||||
|
||||
curl_setopt_array($curl_pdf, [
|
||||
CURLOPT_URL: "https://api.lexoffice.io/v1/files/$pdf_id",
|
||||
CURLOPT_RETURNTRANSFER: true,
|
||||
CURLOPT_ENCODING: "",
|
||||
CURLOPT_MAXREDIRS: 10,
|
||||
CURLOPT_TIMEOUT: 30,
|
||||
CURLOPT_HTTP_VERSION: CURL_HTTP_VERSION_1_1,
|
||||
CURLOPT_CUSTOMREQUEST: "GET",
|
||||
CURLOPT_HTTPHEADER: [
|
||||
"Accept: application/pdf",
|
||||
"Authorization: Bearer " . LEX_OFFICE_API_KEY
|
||||
]
|
||||
]);
|
||||
|
||||
$response = curl_exec($curl_pdf);
|
||||
$err = curl_error($curl_pdf);
|
||||
|
||||
$HOME = dirname($ROOT);
|
||||
|
||||
curl_close($curl_pdf);
|
||||
$fp = fopen("$HOME/{$PERSISTENT_FOLDER}/angebote/$pdf_id.pdf", "w+");
|
||||
fwrite($fp, $response);
|
||||
fclose($fp);
|
||||
|
||||
$mail->addAttachment("$HOME/{$PERSISTENT_FOLDER}/angebote/$pdf_id.pdf", "Angebot.pdf");
|
||||
|
||||
$mail->send();
|
||||
|
||||
echo "Alles wurde abgesendet! Du kannst die Webseite nun verlassen.";
|
||||
}
|
||||
|
||||
export async function createLexOfficeCustomer(user: Benutzer) {
|
||||
if (!user.adresse) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const response = await fetch("https://api.lexoffice.io/v1/contacts", {
|
||||
body: JSON.stringify({
|
||||
"version": "0",
|
||||
"company": {
|
||||
"name": `${user.vorname} ${user.name}`
|
||||
},
|
||||
"note": "",
|
||||
"roles": {
|
||||
"customer": {}
|
||||
},
|
||||
"addresses": {
|
||||
"billing": [{
|
||||
"street": user.adresse,
|
||||
"zip": user.plz,
|
||||
"city": user.ort,
|
||||
"countryCode": "DE"
|
||||
}]
|
||||
},
|
||||
"emailAddresses": {
|
||||
"business": user.email
|
||||
}
|
||||
}),
|
||||
method: "POST",
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
Authorization: `Bearer ${LEX_OFFICE_API_KEY}`,
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
})
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (!result.id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return result.id;
|
||||
}
|
||||
52
src/lib/server/objekt.ts
Normal file
52
src/lib/server/objekt.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { ObjektKomplettClient } from "#components/Ausweis/types.js";
|
||||
import { omit } from "#lib/helpers.js";
|
||||
import { prisma } from "@ibcornelsen/database/server";
|
||||
|
||||
export async function getObjektKomplettClient(uid: string): Promise<ObjektKomplettClient | null> {
|
||||
const objekt = await prisma.objekt.findUnique({
|
||||
where: {
|
||||
uid
|
||||
},
|
||||
include: {
|
||||
bilder: true,
|
||||
aufnahmen: {
|
||||
include: {
|
||||
bedarfsausweis_wohnen: true,
|
||||
verbrauchsausweis_gewerbe: true,
|
||||
verbrauchsausweis_wohnen: true,
|
||||
events: true
|
||||
}
|
||||
},
|
||||
unterlagen: true
|
||||
}
|
||||
})
|
||||
|
||||
if (!objekt) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
...omit(objekt, ["benutzer_id", "id", "aufnahmen", "bilder"]),
|
||||
aufnahmen: objekt.aufnahmen.map(aufnahme => ({
|
||||
...omit(aufnahme, ["id", "objekt_id", "benutzer_id", "bedarfsausweis_wohnen", "verbrauchsausweis_gewerbe", "verbrauchsausweis_wohnen"]),
|
||||
bedarfsausweis_wohnen: (aufnahme.bedarfsausweis_wohnen && {
|
||||
...omit(aufnahme.bedarfsausweis_wohnen, ["id", "aufnahme_id", "benutzer_id"]),
|
||||
uid_aufnahme: aufnahme.uid,
|
||||
uid_objekt: objekt.uid
|
||||
}) || undefined,
|
||||
verbrauchsausweis_wohnen: (aufnahme.verbrauchsausweis_wohnen && {
|
||||
...omit(aufnahme.verbrauchsausweis_wohnen, ["id", "aufnahme_id", "benutzer_id"]),
|
||||
uid_aufnahme: aufnahme.uid,
|
||||
uid_objekt: objekt.uid
|
||||
}) || undefined,
|
||||
verbrauchsausweis_gewerbe: (aufnahme.verbrauchsausweis_gewerbe && {
|
||||
...omit(aufnahme.verbrauchsausweis_gewerbe, ["id", "aufnahme_id", "benutzer_id"]),
|
||||
uid_aufnahme: aufnahme.uid,
|
||||
uid_objekt: objekt.uid
|
||||
}) || undefined,
|
||||
uid_objekt: objekt.uid,
|
||||
})),
|
||||
bilder: objekt.bilder.map(bild => omit(bild, ["id", "objekt_id"])),
|
||||
unterlagen: objekt.unterlagen.map(unterlage => omit(unterlage, ["id", "objekt_id"]))
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,20 @@
|
||||
<script lang="ts">
|
||||
import { BenutzerClient, ObjektClient, UploadedGebaeudeBild } from "#components/Ausweis/types.js";
|
||||
import { Enums } from "@ibcornelsen/database/server";
|
||||
import { BenutzerClient, ObjektKomplettClient } from "#components/Ausweis/types.js";
|
||||
import DashboardAusweis from "#components/Dashboard/DashboardAusweis.svelte";
|
||||
import DashboardObjekt from "#components/Dashboard/DashboardObjekt.svelte";
|
||||
|
||||
export let user: BenutzerClient;
|
||||
export let objekte: (ObjektClient & {bilder: UploadedGebaeudeBild[]})[];
|
||||
|
||||
console.log(objekte);
|
||||
|
||||
export let objekte: ObjektKomplettClient[];
|
||||
</script>
|
||||
|
||||
<h1 class="text-4xl font-medium my-8">Willkommen zurück, {user.vorname}!</h1>
|
||||
<h1 class="text-4xl font-medium">Willkommen zurück, {user.vorname}!</h1>
|
||||
<p class="text-lg">
|
||||
Hier finden Sie eine Übersicht über all ihre Ausweise und Gebäude.
|
||||
</p>
|
||||
|
||||
<h1 class="text-4xl font-medium my-8">Gebäude</h1>
|
||||
<div class="grid grid-cols-1 gap-4 lg:grid-cols-2">
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
{#each objekte as objekt}
|
||||
<div class="card lg:card-side bg-base-200 card-bordered border-base-300">
|
||||
<figure class="lg:w-1/2">
|
||||
<img
|
||||
src={(objekt.bilder && `/bilder/${objekt.bilder.find(bild => bild.kategorie === Enums.BilderKategorie.Gebaeude)?.uid}.webp`) || "/images/placeholder.jpg"}
|
||||
class="object-cover w-full h-full"
|
||||
alt="Gebäudebild"
|
||||
/>
|
||||
</figure>
|
||||
<div class="card-body lg:w-1/2 p-4">
|
||||
<h4 class="text-lg font-semibold">{objekt.adresse}, {objekt.plz} {objekt.ort}</h4>
|
||||
</div>
|
||||
</div>
|
||||
<DashboardObjekt {objekt}></DashboardObjekt>
|
||||
{/each}
|
||||
</div>
|
||||
31
src/modules/Dashboard/DashboardObjektModule.svelte
Normal file
31
src/modules/Dashboard/DashboardObjektModule.svelte
Normal file
@@ -0,0 +1,31 @@
|
||||
<script lang="ts">
|
||||
import { BenutzerClient, ObjektKomplettClient } from "#components/Ausweis/types.js";
|
||||
import Carousel from "#components/Carousel.svelte";
|
||||
import DashboardAusweis from "#components/Dashboard/DashboardAusweis.svelte";
|
||||
import { ChevronLeft, ChevronRight } from "radix-svelte-icons";
|
||||
|
||||
export let user: BenutzerClient;
|
||||
export let objekt: ObjektKomplettClient;
|
||||
</script>
|
||||
|
||||
<h1 class="text-4xl font-medium mb-8">{objekt.adresse}</h1>
|
||||
|
||||
<Carousel perPage={1}>
|
||||
{#each objekt.bilder as bild, i (i)}
|
||||
<img src="/bilder/{bild.uid}.webp" alt={bild.kategorie} class="max-h-[60vh] h-full w-full object-contain">
|
||||
{/each}
|
||||
|
||||
<span slot="left-control" class="p-2.5 bg-opacity-50 bg-white block rounded-full"><ChevronLeft size={24}></ChevronLeft></span>
|
||||
<span slot="right-control" class="p-2.5 bg-opacity-50 bg-white block rounded-full"><ChevronRight size={24}></ChevronRight></span>
|
||||
</Carousel>
|
||||
|
||||
<div class="my-8 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
|
||||
{#each objekt.aufnahmen as aufnahme}
|
||||
{@const ausweis = aufnahme.verbrauchsausweis_wohnen ?? aufnahme.verbrauchsausweis_gewerbe ?? aufnahme.bedarfsausweis_wohnen}
|
||||
{#if !ausweis}
|
||||
<p>Diese Aufnahme hat noch keinen Ausweis.</p>
|
||||
{:else}
|
||||
<DashboardAusweis {ausweis} {aufnahme} {objekt} progress={0}></DashboardAusweis>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
@@ -115,6 +115,10 @@
|
||||
window.location.href = `/kaufabschluss?uid=${ausweis.uid}`;
|
||||
}
|
||||
|
||||
async function anfordern() {
|
||||
// TODO Angebot anfordern
|
||||
}
|
||||
|
||||
async function bestellen() {
|
||||
const ausweisart = getAusweisartFromUUID(ausweis.uid) as Enums.Ausweisart;
|
||||
|
||||
@@ -174,6 +178,7 @@
|
||||
2xl:grid-cols-2 2xl:gap-x-8
|
||||
"
|
||||
>
|
||||
{#if !ausweis.geg_anfrage}
|
||||
<div id="performance-box" class="w-full box relative px-4 order-1 self-stretch grid grid-cols-1">
|
||||
<PerformanceScore
|
||||
bind:ausweis
|
||||
@@ -182,6 +187,7 @@
|
||||
{ausweisart}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div
|
||||
id="progress-box"
|
||||
@@ -191,7 +197,11 @@
|
||||
<h2 class="text-primary text-xl">
|
||||
Verbrauchsausweis Wohnen {PRICES.VerbrauchsausweisWohnen[0]} €
|
||||
</h2>
|
||||
{#if ausweis.geg_anfrage}
|
||||
<Progressbar active={1} steps={["Gebäudedaten", "Kundendaten", "Bestätigung"]}/>
|
||||
{:else}
|
||||
<Progressbar active={1}/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -208,10 +218,10 @@
|
||||
<Rechnungsadresse bind:user bind:rechnung /></Bereich
|
||||
>
|
||||
|
||||
{#if !ausweis.geg_anfrage}
|
||||
<Bereich bereich="3" title="Bezahlmethode">
|
||||
<Bezahlung bind:selectedPaymentType={bezahlmethode} /></Bereich
|
||||
>
|
||||
|
||||
<div class="grid grid-cols-2 gap-x-6 my-6">
|
||||
<div class="zusaetze bereich-box bg-white">
|
||||
<h3>Zusatzleistungen:</h3>
|
||||
@@ -275,6 +285,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div
|
||||
class="w-full grid grid-cols-[min-content_1fr_min-content_min-content] grid-rows-[min_content_1fr] gap-x-2 self-start justify-self-end mt-8"
|
||||
@@ -285,7 +296,11 @@
|
||||
|
||||
<button class="button">Speichern</button>
|
||||
|
||||
{#if ausweis.geg_anfrage}
|
||||
<button class="button cursor-pointer" data-cy="bestellen" on:click={anfordern} >Angebot anfordern</button>
|
||||
{:else}
|
||||
<button class="button cursor-pointer" data-cy="bestellen" on:click={bestellen} >Kostenpflichtig bestellen</button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbeClient | BedarfsausweisWohnenClient,
|
||||
objekt: ObjektClient,
|
||||
aufnahme: AufnahmeClient,
|
||||
unterlagen: (UnterlageClient & { data?: string | ArrayBuffer })[],
|
||||
unterlagen: (UnterlageClient & { data?: string })[],
|
||||
ausweisart: Enums.Ausweisart
|
||||
) {
|
||||
if (objekt.uid) {
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
if (aufnahme.uid) {
|
||||
await api.aufnahme._uid.PATCH.fetch({
|
||||
...exclude(aufnahme, ["uid"])
|
||||
...exclude({...aufnahme, baujahr_klima: []}, ["uid"])
|
||||
}, {
|
||||
params: {
|
||||
uid: aufnahme.uid
|
||||
@@ -71,7 +71,7 @@
|
||||
})
|
||||
} else {
|
||||
const { uid } = await api.aufnahme.PUT.fetch({
|
||||
aufnahme,
|
||||
aufnahme: {...aufnahme, baujahr_klima: []},
|
||||
uid_objekt: objekt.uid
|
||||
}, {
|
||||
headers: {
|
||||
@@ -123,7 +123,7 @@
|
||||
}
|
||||
|
||||
for (const unterlage of unterlagen) {
|
||||
if (unterlage.uid) {
|
||||
if (unterlage.uid || !unterlage.data) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -158,7 +158,16 @@
|
||||
return;
|
||||
}
|
||||
|
||||
ausweisSpeichern(ausweis, objekt, aufnahme, unterlagen, Enums.Ausweisart.VerbrauchsausweisGewerbe)
|
||||
const result = await ausweisSpeichern(ausweis, objekt, aufnahme, unterlagen, Enums.Ausweisart.GEGNachweisVerbrauchsausweisWohnen)
|
||||
|
||||
if (result !== null) {
|
||||
window.history.pushState(
|
||||
{},
|
||||
"",
|
||||
`${location.pathname}?uid=${result.uid_ausweis}`
|
||||
);
|
||||
window.location.href = `/kundendaten?uid=${result.uid_ausweis}`;
|
||||
}
|
||||
|
||||
loginOverlayHidden = true;
|
||||
}
|
||||
@@ -179,10 +188,10 @@
|
||||
export let aufnahme: AufnahmeClient;
|
||||
export let user: BenutzerClient = {} as BenutzerClient;
|
||||
export let bilder: UploadedGebaeudeBild[] = [];
|
||||
export let plaene: (UnterlageClient & { data: string | ArrayBuffer })[] =
|
||||
export let plaene: (UnterlageClient & { data: string })[] =
|
||||
[];
|
||||
export let unterlagen: (UnterlageClient & {
|
||||
data: string | ArrayBuffer;
|
||||
data: string;
|
||||
})[] = [];
|
||||
|
||||
|
||||
@@ -270,7 +279,7 @@
|
||||
title="Angaben zur Heizung, Lüftung, Energieerezugung, Qualität und Aufbau der Gebäudehülle usw."
|
||||
></InputLabel>
|
||||
|
||||
<textarea class="rounded-e-none" rows="10"></textarea>
|
||||
<textarea class="rounded-e-none" rows="10" bind:value={ausweis.beschreibung}></textarea>
|
||||
|
||||
<div class="help-label">
|
||||
<HelpLabel>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
import AusweisLayout from "#layouts/AusweisLayoutDaten.astro";
|
||||
import { AufnahmeClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import { createCaller } from "../../../astro-typesafe-api-caller.js";
|
||||
import { createCaller } from "../../astro-typesafe-api-caller.js";
|
||||
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
||||
import { validateAccessTokenServer } from "#server/lib/validateAccessToken.js";
|
||||
import GEGNachweisVerbrauchsausweisWohnenModule from "#modules/angebot-anfragen/GEGNachweisVerbrauchsausweisWohnenModule.svelte";
|
||||
@@ -54,6 +54,7 @@ export const PUT = defineApiRoute({
|
||||
uid: aufnahme.uid,
|
||||
},
|
||||
},
|
||||
geg_anfrage: true
|
||||
},
|
||||
select: {
|
||||
uid: true,
|
||||
|
||||
@@ -2,28 +2,26 @@
|
||||
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
||||
import { validateAccessTokenServer } from "#server/lib/validateAccessToken.js";
|
||||
import { prisma } from "@ibcornelsen/database/server";
|
||||
import { APIRoute } from "astro";
|
||||
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||
import * as fs from "fs";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
export const GET = defineApiRoute({
|
||||
async fetch(input, context, transfer) {
|
||||
const { uid } = context.params
|
||||
const token = context.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value;
|
||||
export const GET: APIRoute = async (Astro) => {
|
||||
const { uid } = Astro.params
|
||||
const token = Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value;
|
||||
|
||||
if (!token) {
|
||||
throw new APIError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Invalid access token"
|
||||
return new Response(null, {
|
||||
status: 400
|
||||
})
|
||||
}
|
||||
|
||||
const valid = validateAccessTokenServer(context);
|
||||
const valid = validateAccessTokenServer(Astro);
|
||||
|
||||
if (!valid) {
|
||||
throw new APIError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Invalid access token"
|
||||
return new Response(null, {
|
||||
status: 401
|
||||
})
|
||||
}
|
||||
|
||||
@@ -34,21 +32,18 @@ export const GET = defineApiRoute({
|
||||
})
|
||||
|
||||
if (!image) {
|
||||
throw new APIError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Image could not be found."
|
||||
return new Response(null, {
|
||||
status: 404
|
||||
})
|
||||
}
|
||||
|
||||
const path = fileURLToPath(new URL(`../../../persistent/images/${image.uid}.webp`, import.meta.url))
|
||||
const base64 = fs.readFileSync(path, "base64")
|
||||
|
||||
const buffer = Buffer.from(base64, "base64");
|
||||
const buffer = fs.readFileSync(path)
|
||||
|
||||
return new Response(buffer, {
|
||||
status: 200,
|
||||
headers: {
|
||||
"Content-Type": "image/webp"
|
||||
}
|
||||
});
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
import { AufnahmeClient, BenutzerClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import UserLayout from "#layouts/UserLayout.astro";
|
||||
import UserLayout from "#layouts/DashboardLayout.astro";
|
||||
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants";
|
||||
import { omit } from "#lib/helpers";
|
||||
import DashboardAusweisePruefenModule from "#modules/Dashboard/DashboardAusweisePruefenModule.svelte";
|
||||
import { Enums, prisma } from "@ibcornelsen/database/server";
|
||||
import { createCaller } from "src/astro-typesafe-api-caller";
|
||||
@@ -44,15 +45,10 @@ const ausweise = await prisma.verbrauchsausweisWohnen.findMany({
|
||||
}
|
||||
})
|
||||
|
||||
function omit(key: string, obj: Record<string, any>) {
|
||||
const { [key]: omitted, ...rest } = obj;
|
||||
return rest;
|
||||
}
|
||||
|
||||
const reformedAusweise = ausweise.map(ausweis => ({
|
||||
ausweis: omit("aufnahme", ausweis) as VerbrauchsausweisWohnenClient,
|
||||
aufnahme: omit("objekt", omit("events", ausweis.aufnahme)) as AufnahmeClient,
|
||||
objekt: omit("bilder", ausweis.aufnahme.objekt) as ObjektClient,
|
||||
ausweis: omit(ausweis, ["aufnahme"]) as VerbrauchsausweisWohnenClient,
|
||||
aufnahme: omit(omit(ausweis.aufnahme, ["events"]), ["objekt"]) as AufnahmeClient,
|
||||
objekt: omit(ausweis.aufnahme.objekt, ["bilder"]) as ObjektClient,
|
||||
bilder: ausweis.aufnahme.objekt.bilder as unknown as UploadedGebaeudeBild[],
|
||||
events: ausweis.aufnahme.events
|
||||
}))
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
import UserLayout from "../../../layouts/UserLayout.astro";
|
||||
import UserLayout from "../../../layouts/DashboardLayout.astro";
|
||||
import DashboardPDFDesignerModule from "../../../modules/Dashboard/DashboardPDFDesignerModule.svelte";
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import { createCaller } from "#lib/caller";
|
||||
import UserLayout from "../../../layouts/UserLayout.astro";
|
||||
import UserLayout from "../../../layouts/DashboardLayout.astro";
|
||||
import DashboardPDFViewerModule from "../../../modules/Dashboard/DashboardPDFViewerModule.svelte";
|
||||
import { prisma } from "@ibcornelsen/database/server";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
import UserLayout from "../../../layouts/UserLayout.astro";
|
||||
import UserLayout from "../../../layouts/DashboardLayout.astro";
|
||||
import DashboardAusweiseModule from "#modules/Dashboard/DashboardAusweiseModule.svelte";
|
||||
|
||||
import { validateAccessTokenServer } from "#server/lib/validateAccessToken";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
import UserLayout from "#layouts/UserLayout.astro";
|
||||
import UserLayout from "#layouts/DashboardLayout.astro";
|
||||
import { createCaller } from "#lib/caller";
|
||||
import DashboardEinstellungenModule from "#modules/Dashboard/DashboardEinstellungenModule.svelte";
|
||||
import { validateAccessTokenServer } from "#server/lib/validateAccessToken";
|
||||
|
||||
@@ -3,8 +3,8 @@ import { createCaller } from "../../astro-typesafe-api-caller.js";
|
||||
import { validateAccessTokenServer } from "#server/lib/validateAccessToken";
|
||||
import DashboardModule from "#modules/Dashboard/DashboardModule.svelte";
|
||||
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants";
|
||||
import Layout from "#layouts/Layout.astro";
|
||||
import { prisma } from "@ibcornelsen/database/server";
|
||||
import DashboardLayout from "#layouts/DashboardLayout.astro";
|
||||
|
||||
const accessTokenValid = await validateAccessTokenServer(Astro);
|
||||
|
||||
@@ -33,10 +33,18 @@ const objekte = await prisma.objekt.findMany({
|
||||
take: 10,
|
||||
include: {
|
||||
bilder: true,
|
||||
unterlagen: true,
|
||||
aufnahmen: {
|
||||
include: {
|
||||
bedarfsausweis_wohnen: true,
|
||||
verbrauchsausweis_gewerbe: true,
|
||||
verbrauchsausweis_wohnen: true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
---
|
||||
|
||||
<Layout title="Dashboard">
|
||||
<DashboardLayout title="Dashboard" {user}>
|
||||
<DashboardModule {user} {objekte} />
|
||||
</Layout>
|
||||
</DashboardLayout>
|
||||
54
src/pages/dashboard/objekt/[uid].astro
Normal file
54
src/pages/dashboard/objekt/[uid].astro
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
import { createCaller } from "../../../astro-typesafe-api-caller.js";
|
||||
import { validateAccessTokenServer } from "#server/lib/validateAccessToken";
|
||||
import DashboardModule from "#modules/Dashboard/DashboardModule.svelte";
|
||||
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants";
|
||||
import Layout from "#layouts/Layout.astro";
|
||||
import { prisma } from "@ibcornelsen/database/server";
|
||||
import DashboardObjektModule from "#modules/Dashboard/DashboardObjektModule.svelte";
|
||||
import UserLayout from "#layouts/DashboardLayout.astro";
|
||||
|
||||
const { uid } = Astro.params;
|
||||
|
||||
const accessTokenValid = await validateAccessTokenServer(Astro);
|
||||
|
||||
if (!accessTokenValid) {
|
||||
return Astro.redirect("/auth/login")
|
||||
}
|
||||
|
||||
const caller = createCaller(Astro);
|
||||
|
||||
const user = await caller.user.self.GET.fetch(undefined, {
|
||||
headers: {
|
||||
"Authorization": `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||
}
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return Astro.redirect("/auth/login")
|
||||
}
|
||||
|
||||
const objekt = await prisma.objekt.findUnique({
|
||||
where: {
|
||||
benutzer: {
|
||||
uid: user.uid
|
||||
},
|
||||
uid
|
||||
},
|
||||
include: {
|
||||
bilder: true,
|
||||
unterlagen: true,
|
||||
aufnahmen: {
|
||||
include: {
|
||||
bedarfsausweis_wohnen: true,
|
||||
verbrauchsausweis_gewerbe: true,
|
||||
verbrauchsausweis_wohnen: true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
---
|
||||
|
||||
<UserLayout title="Dashboard" {user}>
|
||||
<DashboardObjektModule {user} {objekt} client:only/>
|
||||
</UserLayout>
|
||||
@@ -1,92 +0,0 @@
|
||||
---
|
||||
import { AufnahmeClient, BenutzerClient, getAusweisartFromUUID, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisGewerbeClient, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants";
|
||||
import { pdfDatenblattVerbrauchsausweisWohnen } from "#lib/pdf/pdfDatenblattVerbrauchsausweisWohnen";
|
||||
import { pdfVerbrauchsausweisWohnen } from "#lib/pdf/pdfVerbrauchsausweisWohnen";
|
||||
import { Enums } from "@ibcornelsen/database/client";
|
||||
import { createCaller } from "src/astro-typesafe-api-caller";
|
||||
|
||||
const base64Ausweis = Astro.url.searchParams.get("ausweis");
|
||||
const base64Aufnahme = Astro.url.searchParams.get("aufnahme");
|
||||
const base64Objekt = Astro.url.searchParams.get("objekt");
|
||||
const base64Bilder = Astro.url.searchParams.get("bilder");
|
||||
let ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbeClient | null = null;
|
||||
let aufnahme: AufnahmeClient = {} as AufnahmeClient;
|
||||
let objekt: ObjektClient = {} as ObjektClient;
|
||||
let benutzer: BenutzerClient = {} as BenutzerClient;
|
||||
let bilder: UploadedGebaeudeBild[] = []
|
||||
if (base64Ausweis && base64Aufnahme && base64Objekt && base64Bilder) {
|
||||
ausweis = JSON.parse(Buffer.from(base64Ausweis, "base64").toString("utf-8")) as VerbrauchsausweisWohnenClient;
|
||||
objekt = JSON.parse(Buffer.from(base64Objekt, "base64").toString("utf-8")) as ObjektClient;
|
||||
aufnahme = JSON.parse(Buffer.from(base64Aufnahme, "base64").toString("utf-8")) as AufnahmeClient;
|
||||
bilder = JSON.parse(Buffer.from(base64Bilder, "base64").toString("utf-8")) as UploadedGebaeudeBild[];
|
||||
} else {
|
||||
const uidAusweis = Astro.url.searchParams.get("uid");
|
||||
|
||||
if (!uidAusweis) {
|
||||
return Astro.redirect("/404");
|
||||
}
|
||||
|
||||
const ausweisart = getAusweisartFromUUID(uidAusweis)
|
||||
|
||||
const caller = createCaller(Astro);
|
||||
|
||||
if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) {
|
||||
ausweis = await caller["verbrauchsausweis-wohnen"]._uid.GET.fetch(undefined, {
|
||||
params: {
|
||||
uid: uidAusweis
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||
}
|
||||
});
|
||||
} else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) {
|
||||
ausweis = await caller["verbrauchsausweis-gewerbe"]._uid.GET.fetch(undefined, {
|
||||
params: {
|
||||
uid: uidAusweis
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (!ausweis) {
|
||||
return Astro.redirect("/");
|
||||
}
|
||||
|
||||
aufnahme = await caller.aufnahme._uid.GET.fetch(undefined, {
|
||||
params: {
|
||||
uid: ausweis.uid_aufnahme
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||
}
|
||||
});
|
||||
|
||||
objekt = await caller.objekt._uid.GET.fetch(undefined, {
|
||||
params: {
|
||||
uid: ausweis.uid_objekt
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||
}
|
||||
});
|
||||
|
||||
benutzer = await caller.user.self.GET.fetch(undefined, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const pdf = await pdfDatenblattVerbrauchsausweisWohnen(ausweis, aufnahme, objekt, benutzer);
|
||||
|
||||
|
||||
return new Response(pdf, {
|
||||
headers: {
|
||||
"Content-Type": "application/pdf",
|
||||
},
|
||||
});
|
||||
---
|
||||
127
src/pages/pdf/datenblatt.ts
Normal file
127
src/pages/pdf/datenblatt.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
import { AufnahmeClient, BenutzerClient, getAusweisartFromUUID, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisGewerbeClient, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types.js";
|
||||
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
|
||||
import { pdfDatenblattVerbrauchsausweisGewerbe } from "#lib/pdf/pdfDatenblattVerbrauchsausweisGewerbe.js";
|
||||
import { pdfDatenblattVerbrauchsausweisWohnen } from "#lib/pdf/pdfDatenblattVerbrauchsausweisWohnen.js";
|
||||
import { pdfVerbrauchsausweisGewerbe } from "#lib/pdf/pdfVerbrauchsausweisGewerbe.js";
|
||||
import { pdfVerbrauchsausweisWohnen } from "#lib/pdf/pdfVerbrauchsausweisWohnen.js";
|
||||
import { Enums } from "@ibcornelsen/database/client";
|
||||
import { APIRoute } from "astro";
|
||||
import { createCaller } from "src/astro-typesafe-api-caller.js";
|
||||
|
||||
export const GET: APIRoute = async (Astro) => {
|
||||
const uidAusweis = Astro.url.searchParams.get("uid");
|
||||
|
||||
if (!uidAusweis) {
|
||||
return Astro.redirect("/404")
|
||||
}
|
||||
|
||||
const ausweisart = getAusweisartFromUUID(uidAusweis)
|
||||
|
||||
const caller = createCaller(Astro);
|
||||
|
||||
let ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbeClient | null = null;
|
||||
let aufnahme: AufnahmeClient = {} as AufnahmeClient;
|
||||
let objekt: ObjektClient = {} as ObjektClient;
|
||||
let user: BenutzerClient = {} as BenutzerClient;
|
||||
let bilder: UploadedGebaeudeBild[] = []
|
||||
|
||||
if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) {
|
||||
ausweis = await caller["verbrauchsausweis-wohnen"]._uid.GET.fetch(undefined, {
|
||||
params: {
|
||||
uid: uidAusweis
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||
}
|
||||
});
|
||||
} else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) {
|
||||
ausweis = await caller["verbrauchsausweis-gewerbe"]._uid.GET.fetch(undefined, {
|
||||
params: {
|
||||
uid: uidAusweis
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (!ausweis) {
|
||||
return Astro.redirect("/");
|
||||
}
|
||||
|
||||
aufnahme = await caller.aufnahme._uid.GET.fetch(undefined, {
|
||||
params: {
|
||||
uid: ausweis.uid_aufnahme
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||
}
|
||||
});
|
||||
|
||||
objekt = await caller.objekt._uid.GET.fetch(undefined, {
|
||||
params: {
|
||||
uid: ausweis.uid_objekt
|
||||
},
|
||||
headers: {
|
||||
Authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||
}
|
||||
});
|
||||
|
||||
user = await caller.user.self.GET.fetch(undefined, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||
}
|
||||
});
|
||||
|
||||
let pdf: Uint8Array<ArrayBufferLike> | null = null;
|
||||
if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) {
|
||||
pdf = await pdfVerbrauchsausweisWohnen(ausweis as VerbrauchsausweisWohnenClient, aufnahme, objekt, bilder, user);
|
||||
} else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) {
|
||||
pdf = await pdfVerbrauchsausweisGewerbe(ausweis as VerbrauchsausweisGewerbeClient, aufnahme, objekt, bilder, user);
|
||||
}
|
||||
|
||||
return new Response(pdf, {
|
||||
headers: {
|
||||
"Content-Type": "application/pdf",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export const POST: APIRoute = async (Astro) => {
|
||||
const body = await Astro.request.text();
|
||||
const params = new URLSearchParams(body);
|
||||
|
||||
const caller = createCaller(Astro);
|
||||
|
||||
const ausweis = JSON.parse(params.get("ausweis") || "{}");
|
||||
const aufnahme = JSON.parse(params.get("aufnahme") || "{}");
|
||||
const objekt = JSON.parse(params.get("objekt") || "{}");
|
||||
const bilder = JSON.parse(params.get("bilder") || "{}");
|
||||
const ausweisart: Enums.Ausweisart = params.get("ausweisart")
|
||||
|
||||
let user: BenutzerClient = {};
|
||||
|
||||
try {
|
||||
user = await caller.user.self.GET.fetch(undefined, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
||||
let pdf: Uint8Array<ArrayBufferLike> | null = null;
|
||||
if (ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen) {
|
||||
pdf = await pdfDatenblattVerbrauchsausweisWohnen(ausweis, aufnahme, objekt, bilder);
|
||||
} else if (ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe) {
|
||||
pdf = await pdfDatenblattVerbrauchsausweisGewerbe(ausweis, aufnahme, objekt, bilder);
|
||||
}
|
||||
|
||||
return new Response(pdf, {
|
||||
headers: {
|
||||
"Content-Type": "application/pdf",
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user