getMain #334
4
bun.lock
4
bun.lock
@@ -17,7 +17,7 @@
|
||||
"@trpc/client": "^10.45.2",
|
||||
"@trpc/server": "^10.45.2",
|
||||
"astro": "^4.16.17",
|
||||
"astro-typesafe-api": "^0.2.1",
|
||||
"astro-typesafe-api": "^0.2.2",
|
||||
"body-scroll-lock": "^4.0.0-beta.0",
|
||||
"buffer": "^6.0.3",
|
||||
"bun": "^1.1.45",
|
||||
@@ -656,7 +656,7 @@
|
||||
|
||||
"astro": ["astro@4.16.18", "", { "dependencies": { "@astrojs/compiler": "^2.10.3", "@astrojs/internal-helpers": "0.4.1", "@astrojs/markdown-remark": "5.3.0", "@astrojs/telemetry": "3.1.0", "@babel/core": "^7.26.0", "@babel/plugin-transform-react-jsx": "^7.25.9", "@babel/types": "^7.26.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.1.3", "@types/babel__core": "^7.20.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.0", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "boxen": "8.0.1", "ci-info": "^4.1.0", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", "cookie": "^0.7.2", "cssesc": "^3.0.0", "debug": "^4.3.7", "deterministic-object-hash": "^2.0.2", "devalue": "^5.1.1", "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^1.5.4", "esbuild": "^0.21.5", "estree-walker": "^3.0.3", "fast-glob": "^3.3.2", "flattie": "^1.1.1", "github-slugger": "^2.0.0", "gray-matter": "^4.0.3", "html-escaper": "^3.0.3", "http-cache-semantics": "^4.1.1", "js-yaml": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.14", "magicast": "^0.3.5", "micromatch": "^4.0.8", "mrmime": "^2.0.0", "neotraverse": "^0.6.18", "ora": "^8.1.1", "p-limit": "^6.1.0", "p-queue": "^8.0.1", "preferred-pm": "^4.0.0", "prompts": "^2.4.2", "rehype": "^13.0.2", "semver": "^7.6.3", "shiki": "^1.23.1", "tinyexec": "^0.3.1", "tsconfck": "^3.1.4", "unist-util-visit": "^5.0.0", "vfile": "^6.0.3", "vite": "^5.4.11", "vitefu": "^1.0.4", "which-pm": "^3.0.0", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", "zod": "^3.23.8", "zod-to-json-schema": "^3.23.5", "zod-to-ts": "^1.2.0" }, "optionalDependencies": { "sharp": "^0.33.3" }, "bin": { "astro": "astro.js" } }, "sha512-G7zfwJt9BDHEZwlaLNvjbInIw2hPryyD654314KV/XT34pJU6SfN1S+mWa8RAkALcZNJnJXCJmT3JXLQStD3Lw=="],
|
||||
|
||||
"astro-typesafe-api": ["astro-typesafe-api@0.2.1", "", { "dependencies": { "es-codec": "^0.5.0", "globby": "^14.0.2" }, "peerDependencies": { "astro": "^4.16.17", "typescript": "^5.0.0", "zod": "^3.24.1" }, "bin": { "astro-typesafe-api": "src/cli.ts" } }, "sha512-8f0McZj9fWIzT19njJ2z/1zETnbper3ejuba93t72Xvsy6aMTEDXaIGDG3xc9KWUQ9zEcNg+VS52JNWGfYm6CQ=="],
|
||||
"astro-typesafe-api": ["astro-typesafe-api@0.2.2", "", { "dependencies": { "es-codec": "^0.5.0", "globby": "^14.0.2" }, "peerDependencies": { "astro": "^4.16.17", "typescript": "^5.0.0", "zod": "^3.24.1" }, "bin": { "astro-typesafe-api": "src/cli.ts" } }, "sha512-SEHV2iPyIrdpYdYb0mIN1WmcvC61bvsCQqb/X+R4EOcFjuozJ9fJhSiFGxJMvNoxJ9S3P3GKLyDnxXvFlKq0mw=="],
|
||||
|
||||
"async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="],
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"@trpc/client": "^10.45.2",
|
||||
"@trpc/server": "^10.45.2",
|
||||
"astro": "^4.16.17",
|
||||
"astro-typesafe-api": "^0.2.1",
|
||||
"astro-typesafe-api": "^0.2.2",
|
||||
"body-scroll-lock": "^4.0.0-beta.0",
|
||||
"buffer": "^6.0.3",
|
||||
"bun": "^1.1.45",
|
||||
|
||||
@@ -3,12 +3,13 @@ import { createCallerFactory } from "astro-typesafe-api/server";
|
||||
export const createCaller = createCallerFactory({
|
||||
"klimafaktoren": await import("../src/pages/api/klimafaktoren.ts"),
|
||||
"postleitzahlen": await import("../src/pages/api/postleitzahlen.ts"),
|
||||
"aufnahme/[uid]": await import("../src/pages/api/aufnahme/[uid].ts"),
|
||||
"aufnahme": await import("../src/pages/api/aufnahme/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"),
|
||||
"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"),
|
||||
"bedarfsausweis-wohnen/[uid]": await import("../src/pages/api/bedarfsausweis-wohnen/[uid].ts"),
|
||||
"bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"),
|
||||
"objekt": await import("../src/pages/api/objekt/index.ts"),
|
||||
"rechnung": await import("../src/pages/api/rechnung/index.ts"),
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
<script lang="ts">
|
||||
import AusweisWeiter from "#modules/VerbrauchsausweisWohnen/AusweisWeiter.svelte";
|
||||
import Hilfe from "#components/Ausweis/Hilfe.svelte";
|
||||
import {
|
||||
AufnahmeClient,
|
||||
BedarfsausweisWohnenClient,
|
||||
BenutzerClient,
|
||||
ObjektClient,
|
||||
UploadedGebaeudeBild,
|
||||
VerbrauchsausweisGewerbeClient,
|
||||
VerbrauchsausweisWohnenClient,
|
||||
} from "./types.js";
|
||||
import { ausweisSpeichern } from "#client/lib/ausweisSpeichern.js";
|
||||
import { validateAccessTokenClient } from "#client/lib/validateAccessToken.js";
|
||||
import { AufnahmeClient, BedarfsausweisWohnenClient, BenutzerClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisGewerbeClient, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types.js";
|
||||
import Overlay from "#components/Overlay.svelte";
|
||||
import EmbeddedAuthFlowModule from "#modules/EmbeddedAuthFlowModule.svelte";
|
||||
|
||||
import { Enums } from "@ibcornelsen/database/client";
|
||||
|
||||
export let ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbeClient | BedarfsausweisWohnenClient;
|
||||
@@ -19,7 +15,46 @@
|
||||
export let aufnahme: AufnahmeClient;
|
||||
export let ausweisart: Enums.Ausweisart
|
||||
|
||||
export let spaeterWeitermachen;
|
||||
async function ausweisAbschicken() {
|
||||
if (!await validateAccessTokenClient()) {
|
||||
loginOverlayHidden = false;
|
||||
return
|
||||
}
|
||||
|
||||
loginOverlayHidden = true
|
||||
|
||||
const result = await ausweisSpeichern(ausweis, objekt, aufnahme, bilder, ausweisart);
|
||||
|
||||
if (result !== null) {
|
||||
window.history.pushState(
|
||||
{},
|
||||
"",
|
||||
`${location.pathname}?uid=${ausweis.uid}`
|
||||
);
|
||||
window.location.href = `/kundendaten?uid=${ausweis.uid}`;
|
||||
}
|
||||
}
|
||||
|
||||
async function spaeterWeitermachen() {
|
||||
if (!await validateAccessTokenClient()) {
|
||||
loginOverlayHidden = false;
|
||||
return
|
||||
}
|
||||
|
||||
loginOverlayHidden = true
|
||||
|
||||
const result = await ausweisSpeichern(ausweis, objekt, aufnahme, bilder, ausweisart);
|
||||
|
||||
if (result !== null) {
|
||||
window.history.pushState(
|
||||
{},
|
||||
"",
|
||||
`${location.pathname}?uid=${ausweis.uid}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let loginOverlayHidden = true;
|
||||
</script>
|
||||
|
||||
<div
|
||||
@@ -33,14 +68,13 @@
|
||||
>Später Weitermachen
|
||||
</button>
|
||||
|
||||
<div class="">
|
||||
<AusweisWeiter
|
||||
bind:ausweis
|
||||
bind:bilder
|
||||
bind:user
|
||||
bind:objekt
|
||||
bind:aufnahme
|
||||
{ausweisart}
|
||||
></AusweisWeiter>
|
||||
<div>
|
||||
<Overlay bind:hidden={loginOverlayHidden}>
|
||||
<div class="bg-white w-full max-w-screen-sm py-8">
|
||||
<EmbeddedAuthFlowModule onLogin={ausweisAbschicken}></EmbeddedAuthFlowModule>
|
||||
</div>
|
||||
</Overlay>
|
||||
|
||||
<button on:click={ausweisAbschicken} type="button" class="button" data-cy="weiter">Weiter</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { ripple } from "svelte-ripple-action";
|
||||
import type { RippleOptions } from "svelte-ripple-action/dist/constants";
|
||||
import type { RippleOptions } from "svelte-ripple-action/dist/constants.js";
|
||||
import { Home, Reader, EnvelopeClosed, Cube, Bell, Gear, LockClosed, HamburgerMenu } from "radix-svelte-icons"
|
||||
import NotificationProvider from "#components/NotificationProvider/NotificationProvider.svelte";
|
||||
import DashboardNotification from "./DashboardNotification.svelte";
|
||||
import { notifications } from "#components/NotificationProvider/shared";
|
||||
import { notifications } from "#components/NotificationProvider/shared.js";
|
||||
import ThemeController from "#components/ThemeController.svelte";
|
||||
import { BenutzerClient } from "#components/Ausweis/types";
|
||||
import { BenutzerClient } from "#components/Ausweis/types.js";
|
||||
import Cross1 from "radix-svelte-icons/src/lib/icons/Cross1.svelte";
|
||||
|
||||
export let lightTheme: boolean;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await api.postleitzahlen.GET.fetch({ plz: zip });
|
||||
const result = await api.postleitzahlen.GET.fetch({ plz: zip, limit: 10 });
|
||||
|
||||
if (result.length > 0) {
|
||||
zipCodes = result;
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
</script>
|
||||
|
||||
<div class="" use:clickOutside={() => {
|
||||
<div use:clickOutside={() => {
|
||||
hideZipDropdown = true;
|
||||
}}>
|
||||
|
||||
@@ -65,13 +65,19 @@
|
||||
maxlength="5"
|
||||
/>
|
||||
|
||||
<div data-test="plz-container" class="absolute top-[calc(100%+4px)] left-0 w-full bg-white py-2 shadow-md rounded-lg z-50" hidden={hideZipDropdown}>
|
||||
<div data-test="plz-container" class="absolute top-[calc(100%+4px)] flex flex-col left-0 bg-white py-1 shadow-md rounded-lg z-10" class:hidden={hideZipDropdown}>
|
||||
{#each zipCodes as zipCode}
|
||||
<div class="hover:bg-gray-100 cursor-pointer px-2 py-0.5 text-nowrap" tabindex="-1" on:click={() => {
|
||||
<button class="hover:bg-gray-100 cursor-pointer px-2 py-1 text-nowrap" tabindex="-1" on:click={() => {
|
||||
zip = zipCode.plz;
|
||||
city = zipCode.stadt;
|
||||
hideZipDropdown = true;
|
||||
}}>{zipCode.plz}, {zipCode.stadt}</div>
|
||||
}}>{zipCode.plz}, {zipCode.stadt}</button>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
button:not(:last-of-type) {
|
||||
@apply border-b border-b-gray-200;
|
||||
}
|
||||
</style>
|
||||
@@ -6,6 +6,8 @@ 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)
|
||||
|
||||
@@ -16,7 +18,11 @@ if (!valid) {
|
||||
|
||||
const caller = createCaller(Astro)
|
||||
|
||||
const benutzer = await caller.v1.benutzer.self()
|
||||
const benutzer = (await caller.user.self.GET.fetch(undefined, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
|
||||
}
|
||||
})) || {} as BenutzerClient;
|
||||
|
||||
export interface Props {
|
||||
title: string;
|
||||
@@ -101,7 +107,7 @@ let lightTheme = Astro.cookies.get("theme")?.value === "light";
|
||||
</head>
|
||||
|
||||
<body class="min-h-screen grid md:grid-cols-[300px_1fr]">
|
||||
<DashboardSidebar lightTheme={lightTheme} benutzer={benutzer} client:load></DashboardSidebar>
|
||||
<DashboardSidebar lightTheme={lightTheme} {benutzer} client:load></DashboardSidebar>
|
||||
<main class="p-4 md:p-8 overflow-auto h-screen bg-base-100 pt-20 md:!pt-24">
|
||||
<slot />
|
||||
</main>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { getEmpfehlungen } from "#lib/XML/getEmpfehlungen.js";
|
||||
import { Enums } from "@ibcornelsen/database/server";
|
||||
import * as fs from "fs"
|
||||
import moment from "moment";
|
||||
import { PDFDocument, PDFFont, PDFName, PDFNumber, PDFPage, StandardFonts, TextAlignment } from "pdf-lib";
|
||||
import { PDFDocument, PDFFont, PDFPage, RotationTypes, StandardFonts, TextAlignment } from "pdf-lib";
|
||||
|
||||
/* -------------------------------- Pdf Tools ------------------------------- */
|
||||
|
||||
@@ -82,7 +82,6 @@ export async function pdfVerbrauchsausweisWohnen(ausweis: VerbrauchsausweisWohne
|
||||
|
||||
/* -------------------------------- Seite 2 -------------------------------- */
|
||||
|
||||
const co2Emissionen = fillFormField("co2emissionen", berechnungen?.co2EmissionenGesamt.toString(), 8, TextAlignment.Center)
|
||||
|
||||
const addEnergieverbrauchSkalaPfeile = async (page: PDFPage) => {
|
||||
const pfeilNachUnten = await pdf.embedPng(fs.readFileSync(new URL("../../../public/images/pfeil-nach-unten.png", import.meta.url), "base64"))
|
||||
@@ -172,11 +171,7 @@ export async function pdfVerbrauchsausweisWohnen(ausweis: VerbrauchsausweisWohne
|
||||
}
|
||||
}
|
||||
|
||||
addEnergieverbrauchSkalaPfeile(pages[1])
|
||||
addEnergieverbrauchSkalaPfeile(pages[2])
|
||||
|
||||
const primaerenergiebedarfIst = fillFormField("primaerenergiebedarf_ist", berechnungen?.primaerEnergieVerbrauchGesamt.toString())
|
||||
|
||||
addEnergieverbrauchSkalaPfeile(pages[2])
|
||||
|
||||
/* -------------------------------- Seite 3 -------------------------------- */
|
||||
|
||||
@@ -369,6 +364,22 @@ export async function pdfVerbrauchsausweisWohnen(ausweis: VerbrauchsausweisWohne
|
||||
}
|
||||
|
||||
|
||||
function addAnsichtsausweisLabel(page: PDFPage, font: PDFFont) {
|
||||
page.drawText("Ansichtsausweis", {
|
||||
x: page.getWidth() / 2 - font.heightAtSize(112) * 2.2, y: page.getHeight() - font.heightAtSize(112) / 2,
|
||||
size: 112,
|
||||
font,
|
||||
rotate: {
|
||||
type: RotationTypes.Degrees,
|
||||
angle: -60
|
||||
},
|
||||
opacity: 0.3
|
||||
})
|
||||
}
|
||||
|
||||
for (const page of pages) {
|
||||
addAnsichtsausweisLabel(page, font)
|
||||
}
|
||||
|
||||
// pdf.getForm().flatten()
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
export let user: BenutzerClient;
|
||||
export let objekte: ObjektClient[];
|
||||
|
||||
console.log(objekte);
|
||||
|
||||
</script>
|
||||
|
||||
<h1 class="text-4xl font-medium my-8">Willkommen zurück, {user.vorname}!</h1>
|
||||
@@ -12,7 +15,7 @@
|
||||
|
||||
<h1 class="text-4xl font-medium my-8">Gebäude</h1>
|
||||
<div class="grid grid-cols-1 gap-4 lg:grid-cols-2">
|
||||
{#each objekte as objekt}
|
||||
<!-- {#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
|
||||
@@ -25,5 +28,5 @@
|
||||
<h4 class="text-lg font-semibold">{objekt.adresse}, {objekt.plz} {objekt.ort}</h4>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
{/each} -->
|
||||
</div>
|
||||
@@ -30,6 +30,7 @@
|
||||
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||
export let aufnahme: AufnahmeClient;
|
||||
export let objekt: ObjektClient;
|
||||
export let ausweisart: Enums.Ausweisart;
|
||||
|
||||
let rechnung: Partial<RechnungClient> = {
|
||||
email: user.email,
|
||||
@@ -89,6 +90,13 @@
|
||||
0
|
||||
);
|
||||
|
||||
const zurueck = {
|
||||
[Enums.Ausweisart.VerbrauchsausweisWohnen]: `/energieausweis-erstellen/verbrauchsausweis-wohngebaeude?uid=${ausweis.uid}`,
|
||||
[Enums.Ausweisart.VerbrauchsausweisGewerbe]: `/energieausweis-erstellen/verbrauchsausweis-gewerbe?uid=${ausweis.uid}`,
|
||||
[Enums.Ausweisart.BedarfsausweisWohnen]: `/energieausweis-erstellen/bedarfsausweis-wohnen?uid=${ausweis.uid}`,
|
||||
[Enums.Ausweisart.BedarfsausweisGewerbe]: `/energieausweis-erstellen/bedarfsausweis-gewerbe?uid=${ausweis.uid}`,
|
||||
}[ausweisart]
|
||||
|
||||
async function speichern(e: SubmitEvent) {
|
||||
e.preventDefault();
|
||||
|
||||
@@ -254,7 +262,7 @@
|
||||
<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"
|
||||
>
|
||||
<button class="button justify-self-start">Zurück</button>
|
||||
<a class="button justify-self-start" href={zurueck}>Zurück</a>
|
||||
|
||||
<div></div>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { loginClient } from "#lib/login";
|
||||
import { loginClient } from "#lib/login.js";
|
||||
import CrossCircled from "radix-svelte-icons/src/lib/icons/CrossCircled.svelte";
|
||||
import { fade } from "svelte/transition";
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
<span class="font-semibold">Das hat leider nicht geklappt, haben sie ihr Passwort und ihre Email Adresse richtig eingegeben?</span>
|
||||
</div>
|
||||
{/if}
|
||||
<button class="btn btn-primary" type="submit">Einloggen</button>
|
||||
<button class="button" type="submit">Einloggen</button>
|
||||
<div class="flex-row justify-between" style="margin-top: 10px">
|
||||
<a class="link link-hover" href="/auth/signup{redirect ? `?redirect=${redirect}` : ""}">Registrieren</a>
|
||||
<a class="link link-hover" href="/auth/passwort-vergessen{redirect ? `?redirect=${redirect}` : ""}"
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { ausweisSpeichern } from "#client/lib/ausweisSpeichern.js";
|
||||
import { validateAccessTokenClient } from "#client/lib/validateAccessToken.js";
|
||||
import { AufnahmeClient, BedarfsausweisWohnenClient, BenutzerClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisGewerbeClient, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types.js";
|
||||
import Overlay from "#components/Overlay.svelte";
|
||||
import EmbeddedAuthFlowModule from "#modules/EmbeddedAuthFlowModule.svelte";
|
||||
|
||||
import { Enums } from "@ibcornelsen/database/client";
|
||||
|
||||
export let objekt: ObjektClient;
|
||||
export let bilder: UploadedGebaeudeBild[];
|
||||
export let ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbeClient | BedarfsausweisWohnenClient;
|
||||
export let user: BenutzerClient;
|
||||
export let aufnahme: AufnahmeClient;
|
||||
export let ausweisart: Enums.Ausweisart
|
||||
|
||||
async function ausweisAbschicken() {
|
||||
if (!await validateAccessTokenClient()) {
|
||||
loginOverlayHidden = false;
|
||||
return
|
||||
}
|
||||
|
||||
loginOverlayHidden = true
|
||||
|
||||
const result = await ausweisSpeichern(ausweis, objekt, aufnahme, bilder, ausweisart);
|
||||
|
||||
if (result !== null) {
|
||||
window.history.pushState(
|
||||
{},
|
||||
"",
|
||||
`${location.pathname}?uid=${ausweis.uid}`
|
||||
);
|
||||
window.location.href = `/kundendaten?uid=${ausweis.uid}`;
|
||||
}
|
||||
}
|
||||
|
||||
let loginOverlayHidden = true;
|
||||
</script>
|
||||
|
||||
<Overlay bind:hidden={loginOverlayHidden}>
|
||||
<div class="bg-white w-full max-w-screen-sm py-8">
|
||||
<EmbeddedAuthFlowModule onLogin={ausweisAbschicken}></EmbeddedAuthFlowModule>
|
||||
</div>
|
||||
</Overlay>
|
||||
|
||||
<button on:click={ausweisAbschicken} type="button" class="button" data-cy="weiter">Weiter</button>
|
||||
217
src/pages/api/bedarfsausweis-wohnen/[uid].ts
Normal file
217
src/pages/api/bedarfsausweis-wohnen/[uid].ts
Normal file
@@ -0,0 +1,217 @@
|
||||
import { BedarfsausweisWohnenClient, OptionalNullable, UUidWithPrefix, ZodOverlap } from "#components/Ausweis/types.js";
|
||||
import { exclude } from "#lib/exclude.js";
|
||||
import { authorizationHeaders, authorizationMiddleware } from "#lib/middleware/authorization.js";
|
||||
import { BedarfsausweisWohnenSchema, prisma } from "@ibcornelsen/database/server";
|
||||
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||
import { z } from "zod";
|
||||
|
||||
export const PATCH = defineApiRoute({
|
||||
input: BedarfsausweisWohnenSchema.omit({
|
||||
uid: true,
|
||||
id: true,
|
||||
benutzer_id: true,
|
||||
aufnahme_id: true,
|
||||
}),
|
||||
output: z.void(),
|
||||
headers: {
|
||||
"Authorization": z.string()
|
||||
},
|
||||
middleware: authorizationMiddleware,
|
||||
async fetch(input, ctx, user) {
|
||||
const objekt = await prisma.bedarfsausweisWohnen.findUnique({
|
||||
where: {
|
||||
uid: ctx.params.uid,
|
||||
benutzer: {
|
||||
id: user.id
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (!objekt) {
|
||||
throw new APIError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Ausweis konnte nicht gefunden werden oder gehört einem anderen Benutzer."
|
||||
})
|
||||
}
|
||||
|
||||
await prisma.bedarfsausweisWohnen.update({
|
||||
where: {
|
||||
uid: ctx.params.uid
|
||||
},
|
||||
data: input
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
export const DELETE = defineApiRoute({
|
||||
meta: {
|
||||
description: "Storniert einen Ausweis"
|
||||
},
|
||||
headers: authorizationHeaders,
|
||||
middleware: authorizationMiddleware,
|
||||
async fetch(input, ctx, user) {
|
||||
const { uid } = ctx.params;
|
||||
|
||||
if (!UUidWithPrefix.safeParse(uid).success) {
|
||||
throw new APIError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "UID konnte nicht verifiziert werden."
|
||||
})
|
||||
}
|
||||
|
||||
// Wir holen uns den Bedarfsausweis
|
||||
// Dieser MUSS mit dem Nutzer verknüpft sein.
|
||||
const ausweis = await prisma.bedarfsausweisWohnen.findUnique({
|
||||
where: {
|
||||
uid,
|
||||
},
|
||||
include: {
|
||||
aufnahme: {
|
||||
select: {
|
||||
storniert: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!ausweis) {
|
||||
// Falls wir den Ausweis nicht finden können, werfen wir einen Fehler
|
||||
throw new APIError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Ausweis konnte nicht gefunden werden.",
|
||||
});
|
||||
}
|
||||
|
||||
// Wir dürfen den Ausweis nur stornieren, wenn er noch nicht ausgestellt wurde
|
||||
// Außerdem müssen wir schauen, ob wir Admin oder der Besitzer des Ausweises sind.
|
||||
if ((ausweis.benutzer_id !== user.id) && user.rolle !== "ADMIN") {
|
||||
// Falls der Ausweis nicht dem Nutzer gehört, werfen wir einen Fehler
|
||||
throw new APIError({
|
||||
code: "FORBIDDEN",
|
||||
message: "Ausweis gehört nicht dem Nutzer.",
|
||||
});
|
||||
}
|
||||
|
||||
// if (ausweis.erledigt) {
|
||||
// // Falls der Ausweis bereits ausgestellt wurde, werfen wir einen Fehler
|
||||
// throw new TRPCError({
|
||||
// code: "BAD_REQUEST",
|
||||
// message: "Ausweis wurde bereits ausgestellt.",
|
||||
// });
|
||||
// }
|
||||
|
||||
if (ausweis.aufnahme.storniert) {
|
||||
// Falls der Ausweis bereits storniert ist, werfen wir einen Fehler
|
||||
throw new APIError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Ausweis wurde bereits storniert.",
|
||||
});
|
||||
}
|
||||
|
||||
await prisma.aufnahme.update({
|
||||
where: {
|
||||
id: ausweis.aufnahme_id
|
||||
},
|
||||
data: {
|
||||
storniert: true
|
||||
}
|
||||
})
|
||||
|
||||
// Wir erstellen ein Event, dass der Ausweis storniert wurde
|
||||
// Dann können wir das in der Historie anzeigen
|
||||
await prisma.event.create({
|
||||
data: {
|
||||
title: "Ausweis storniert",
|
||||
description: ((user.rolle === "ADMIN") && (ausweis.benutzer_id !== user.id)) ? "Ausweis wurde von einem Administrator storniert." : "Ausweis wurde vom Besitzer storniert.",
|
||||
benutzer: {
|
||||
connect: {
|
||||
id: user.id
|
||||
}
|
||||
},
|
||||
aufnahme: {
|
||||
connect: {
|
||||
id: ausweis.aufnahme_id
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
export const GET = defineApiRoute({
|
||||
meta: {
|
||||
description: "Gibt ein spezifisches Gebäude des Benutzers zurück.",
|
||||
tags: ["Gebäude"],
|
||||
headers: {
|
||||
"Authorization": {
|
||||
description: "Ein gültiger Authentifizierungstoken",
|
||||
required: true,
|
||||
allowEmptyValue: false,
|
||||
examples: {
|
||||
Bearer: {
|
||||
value: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
output: ZodOverlap<OptionalNullable<BedarfsausweisWohnenClient>>(BedarfsausweisWohnenSchema.merge(z.object({
|
||||
uid_aufnahme: UUidWithPrefix,
|
||||
uid_objekt: UUidWithPrefix,
|
||||
uid_benutzer: UUidWithPrefix.optional()
|
||||
})).omit({
|
||||
id: true,
|
||||
aufnahme_id: true,
|
||||
benutzer_id: true
|
||||
})),
|
||||
middleware: authorizationMiddleware,
|
||||
async fetch(input, context, user) {
|
||||
const { uid } = context.params;
|
||||
|
||||
if (!uid) {
|
||||
throw new APIError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Missing uid in request params"
|
||||
})
|
||||
}
|
||||
|
||||
const ausweis = await prisma.bedarfsausweisWohnen.findUnique({
|
||||
where: {
|
||||
uid,
|
||||
benutzer_id: user.id
|
||||
},
|
||||
include: {
|
||||
benutzer: {
|
||||
select: {
|
||||
uid: true
|
||||
}
|
||||
},
|
||||
aufnahme: {
|
||||
select: {
|
||||
uid: true,
|
||||
objekt: {
|
||||
select: {
|
||||
uid: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!ausweis) {
|
||||
// Falls wir den Ausweis nicht finden können, werfen wir einen Fehler
|
||||
throw new APIError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Ausweis konnte nicht gefunden werden.",
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
uid_aufnahme: ausweis.aufnahme.uid,
|
||||
uid_objekt: ausweis.aufnahme.objekt.uid,
|
||||
uid_benutzer: ausweis.benutzer?.uid,
|
||||
...exclude(ausweis, ["id", "aufnahme_id", "benutzer_id", "aufnahme"])
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,146 @@
|
||||
import { UUidWithPrefix } from "#components/Ausweis/types.js";
|
||||
import { authorizationHeaders, authorizationMiddleware } from "#lib/middleware/authorization.js";
|
||||
import { BedarfsausweisWohnenSchema, prisma } from "@ibcornelsen/database/server";
|
||||
import { APIError, defineApiRoute } from "astro-typesafe-api/server";
|
||||
import { z } from "zod";
|
||||
|
||||
export const PUT = defineApiRoute({
|
||||
meta: {
|
||||
contentTypes: ["application/json"],
|
||||
description:
|
||||
"Erstellt einen neuen Bedarfsausweis für Wohngebäude nach dem Schema der EnEV von 2016. Als Input wird ein bestehendes Gebäude benötigt. Falls keine UID einer bestehenden Gebäudeaufnahme mitgegeben wird, wird automatisch eine erstellt.",
|
||||
tags: ["Bedarfsausweis Wohnen"],
|
||||
},
|
||||
input: z.object({
|
||||
ausweis: BedarfsausweisWohnenSchema.omit({
|
||||
id: true,
|
||||
benutzer_id: true,
|
||||
uid: true,
|
||||
aufnahme_id: true
|
||||
}),
|
||||
uid_aufnahme: UUidWithPrefix
|
||||
}),
|
||||
output: z.object({
|
||||
uid: UUidWithPrefix,
|
||||
objekt_uid: UUidWithPrefix,
|
||||
aufnahme_uid: UUidWithPrefix,
|
||||
}),
|
||||
headers: authorizationHeaders,
|
||||
middleware: authorizationMiddleware,
|
||||
async fetch(input, ctx, user) {
|
||||
const aufnahme = await prisma.aufnahme.findUnique({
|
||||
where: {
|
||||
uid: input.uid_aufnahme
|
||||
}
|
||||
})
|
||||
|
||||
if (!aufnahme || aufnahme.benutzer_id !== user.id) {
|
||||
throw new APIError({
|
||||
code: "FORBIDDEN",
|
||||
message: "Aufnahme konnte nicht gefunden werden oder gehört nicht zu diesem Benutzer."
|
||||
})
|
||||
}
|
||||
|
||||
const createdAusweis = await prisma.bedarfsausweisWohnen.create({
|
||||
data: {
|
||||
...input.ausweis,
|
||||
benutzer: {
|
||||
connect: {
|
||||
id: user.id,
|
||||
},
|
||||
},
|
||||
aufnahme: {
|
||||
connect: {
|
||||
uid: aufnahme.uid,
|
||||
},
|
||||
},
|
||||
},
|
||||
select: {
|
||||
uid: true,
|
||||
aufnahme: {
|
||||
select: {
|
||||
uid: true,
|
||||
objekt: {
|
||||
select: {
|
||||
uid: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
uid: createdAusweis.uid,
|
||||
objekt_uid: createdAusweis.aufnahme.objekt.uid,
|
||||
aufnahme_uid: createdAusweis.aufnahme.uid,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const GET = defineApiRoute({
|
||||
meta: {
|
||||
description: "Gibt ein spezifisches Gebäude des Benutzers zurück.",
|
||||
tags: ["Gebäude"],
|
||||
headers: {
|
||||
Authorization: {
|
||||
description: "Ein gültiger Authentifizierungstoken",
|
||||
required: true,
|
||||
allowEmptyValue: false,
|
||||
examples: {
|
||||
Bearer: {
|
||||
value: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
middleware: authorizationMiddleware,
|
||||
async fetch(input, context, user) {
|
||||
const { uid } = context.params;
|
||||
|
||||
const ausweis = await prisma.bedarfsausweisWohnen.findUnique({
|
||||
where: {
|
||||
uid,
|
||||
},
|
||||
include: {
|
||||
benutzer: true,
|
||||
aufnahme: {
|
||||
include: {
|
||||
objekt: {
|
||||
include: {
|
||||
gebaeude_bilder: true,
|
||||
},
|
||||
},
|
||||
rechnungen: true,
|
||||
events: {
|
||||
include: {
|
||||
benutzer: {
|
||||
select: {
|
||||
uid: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: {
|
||||
date: "asc",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (
|
||||
!ausweis ||
|
||||
(ausweis.benutzer_id !== null && ausweis.benutzer_id !== user.id)
|
||||
) {
|
||||
// Falls wir den Ausweis nicht finden können, werfen wir einen Fehler
|
||||
throw new APIError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Ausweis konnte nicht gefunden werden.",
|
||||
});
|
||||
}
|
||||
|
||||
return ausweis;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -59,10 +59,10 @@ export const GET = defineApiRoute({
|
||||
}
|
||||
}
|
||||
},
|
||||
output: ZodOverlap<OptionalNullable<ObjektClient>>(ObjektSchema.omit({
|
||||
output: ObjektSchema.omit({
|
||||
benutzer_id: true,
|
||||
id: true
|
||||
})),
|
||||
}),
|
||||
middleware: authorizationMiddleware,
|
||||
async fetch(input, ctx, user) {
|
||||
const { uid } = ctx.params;
|
||||
|
||||
@@ -88,6 +88,6 @@ if (!ausweis || !user) {
|
||||
---
|
||||
|
||||
<AusweisLayout title="Kundendaten Aufnehmen - IBCornelsen">
|
||||
<KundendatenModule {user} {ausweis} {objekt} {aufnahme} selectedPaymentType={Enums.Bezahlmethoden.paypal} client:load></KundendatenModule>
|
||||
<KundendatenModule {user} {ausweis} {objekt} {aufnahme} {ausweisart} selectedPaymentType={Enums.Bezahlmethoden.paypal} client:load></KundendatenModule>
|
||||
</AusweisLayout>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user