Kaufabschluss funktioniert.

Kaufabschluss funktioniert einzeln, gesamter Durchgang geht auch. Input Validation ist der nächste große Schritt. Im Formular kommen immer noch viele Werte raus die wir nicht in der Datenbank haban wollen...
This commit is contained in:
Moritz Utcke
2024-01-11 13:41:40 +07:00
parent b20b857a7d
commit d9ac5cf69c
23 changed files with 489 additions and 90 deletions

View File

@@ -4,7 +4,7 @@
"license": "GPL V3.0", "license": "GPL V3.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "bun --bun astro dev", "dev": "pnpm astro dev",
"build": "bun --bun astro build", "build": "bun --bun astro build",
"preview": "bun --bun astro preview", "preview": "bun --bun astro preview",
"astro": "astro", "astro": "astro",
@@ -22,12 +22,15 @@
"@astrojs/svelte": "^2.2.0", "@astrojs/svelte": "^2.2.0",
"@astrojs/tailwind": "^3.1.3", "@astrojs/tailwind": "^3.1.3",
"@ibcornelsen/database": "link:@ibcornelsen/database", "@ibcornelsen/database": "link:@ibcornelsen/database",
"@ibcornelsen/api": "link:@ibcornelsen/api",
"@ibcornelsen/ui": "^0.0.2", "@ibcornelsen/ui": "^0.0.2",
"@mollie/api-client": "^3.7.0", "@mollie/api-client": "^3.7.0",
"@trpc/client": "^10.45.0", "@trpc/client": "^10.45.0",
"@trpc/server": "^10.45.0", "@trpc/server": "^10.45.0",
"@types/body-scroll-lock": "^3.1.2",
"astro": "^2.5.1", "astro": "^2.5.1",
"astro-i18next": "1.0.0-beta.21", "astro-i18next": "1.0.0-beta.21",
"body-scroll-lock": "^4.0.0-beta.0",
"buffer": "^6.0.3", "buffer": "^6.0.3",
"bun": "^1.0.2", "bun": "^1.0.2",
"cookiejs": "^2.1.2", "cookiejs": "^2.1.2",

View File

@@ -7,11 +7,9 @@
import HelpLabel from "#components/HelpLabel.svelte"; import HelpLabel from "#components/HelpLabel.svelte";
import ZipSearch from "#components/ZIPSearch.svelte"; import ZipSearch from "#components/ZIPSearch.svelte";
import { hotWaterProductionTypes } from "./HotWaterProductionTypes"; import { hotWaterProductionTypes } from "./HotWaterProductionTypes";
import { Bedarfsausweis } from "src/lib/Ausweis/Bedarfsausweis";
import BilderZusatzsysteme from "../Ausweis/BilderZusatzsysteme.svelte"; import BilderZusatzsysteme from "../Ausweis/BilderZusatzsysteme.svelte";
import moment from "moment"; import moment from "moment";
import { BitChecker } from "src/lib/BitChecker"; import { BitChecker } from "src/lib/BitChecker";
import { Dachgeschoss } from "src/lib/Ausweis/types";
let ausweis = new Bedarfsausweis(); let ausweis = new Bedarfsausweis();

View File

@@ -2,6 +2,6 @@
export let name: string = ""; export let name: string = "";
</script> </script>
<div class="flex flex-row justify-between mb-2"> <div class="flex flex-row justify-between items-center gap-4">
<label class="text-base font-medium" for={name}><slot></slot></label> <label class="text-base font-medium" for={name}><slot></slot></label>
</div> </div>

View File

@@ -0,0 +1,16 @@
<script lang="ts">
export let hidden: boolean = true;
import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock';
$: if (globalThis.window) {
if (hidden) {
enableBodyScroll(document.body);
} else {
disableBodyScroll(document.body);
}
}
</script>
<div class="fixed top-0 left-0 w-[100vw] h-[100vh] flex items-center justify-center bg-[rgba(0,0,0,0.8)] z-50" class:hidden={hidden}>
<slot></slot>
</div>

View File

@@ -0,0 +1,125 @@
---
import i18next from "i18next";
import "../style/global.scss";
import { NotificationWrapper } from "@ibcornelsen/ui";
export interface Props {
title: string;
}
const { title } = Astro.props;
const schema = JSON.stringify({
"@context": "http://schema.org",
"@type": "Corporation",
name: "IB Cornelsen",
alternateName: "online-energieausweis.org",
url: "https://online-energieausweis.org",
logo: "https://online-energieausweis.org/ib-cornelsen.png",
address: {
"@type": "PostalAddress",
streetAddress: "Katendeich 5A",
addressLocality: "Hamburg",
postalCode: "21035",
addressCountry: "Deutschland",
email: "info@online-energieausweis.org",
},
contactPoint: {
"@type": "ContactPoint",
telephone: "+49-040-209339850",
faxNumber: "+49-040-209339859",
contactType: "customer service",
areaServed: "DE",
availableLanguage: "German",
},
});
---
<!DOCTYPE html>
<html lang={i18next.language}>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<script type="application/ld+json" set:html={schema} />
<link rel="icon" type="image/svg+xml" href="/favicon.jpg" />
<meta
name="description"
content="✅ Jetzt Ihren Energieausweis online erstellen. Erhalten Sie Ihren online Energieausweis rechtssicher und nach aktueller GEG (vormals EnEV) vom Diplom Ingenieur geprüft."
/>
<link rel="canonical" href="https://online-energieausweis.org/" />
<meta property="og:locale" content="de_DE" />
<meta property="og:type" content="website" />
<meta
property="og:title"
content="Energieausweis online erstellen - Online Energieausweis"
/>
<meta
property="og:description"
content="✅ Jetzt Ihren Energieausweis online erstellen. Erhalten Sie Ihren online Energieausweis rechtssicher und nach aktueller GEG (vormals EnEV) vom Diplom Ingenieur geprüft."
/>
<meta property="og:url" content="https://online-energieausweis.org/" />
<meta
property="og:site_name"
content="Energieausweis online erstellen"
/>
<meta name="twitter:card" content="summary_large_image" />
<meta
name="twitter:description"
content="✅ Jetzt Ihren Energieausweis online erstellen. Erhalten Sie Ihren online Energieausweis rechtssicher und nach aktueller GEG (vormals EnEV) vom Diplom Ingenieur geprüft."
/>
<meta
name="twitter:title"
content="Energieausweis online erstellen - Online Energieausweis"
/>
<meta
name="twitter:image"
content="https://online-energieausweis.org/images/energieausweis-online-erstellen.jpg"
/>
<title>
{title || "Energieausweis online erstellen - Online Energieausweis"}
</title>
</head>
<body>
<article>
<slot />
</article>
<NotificationWrapper client:load />
</body>
</html>
<style is:global>
article {
@apply rounded-lg w-full shadow-md border;
}
body {
min-height: 100vh;
}
.button {
@apply px-8 py-2 bg-secondary rounded-lg text-white font-medium hover:shadow-lg transition-all hover:underline active:bg-blue-900 text-center cursor-pointer;
color: #fff !important;
}
h3 {
@apply text-xl font-medium mt-6 mb-4;
}
input {
@apply py-1.5 px-4 w-full rounded-lg outline-none text-lg text-slate-700 border bg-gray-50 transition-colors;
}
input:hover,
input:focus {
@apply bg-gray-100;
}
label {
@apply text-base font-semibold;
}
</style>

View File

@@ -28,12 +28,18 @@ export async function endEnergieVerbrauchVerbrauchsausweis_2016(
return null return null
} }
const klimafaktoren = await client.v1.klimafaktoren.query({ try {
plz: ausweis.gebaeude_stammdaten.plz, const klimafaktoren = await client.v1.klimafaktoren.query({
genauigkeit: "years", plz: ausweis.gebaeude_stammdaten.plz,
startdatum: ausweis.startdatum, genauigkeit: "years",
enddatum: moment(ausweis.startdatum).add(2, "years").toDate() startdatum: ausweis.startdatum,
}) enddatum: moment(ausweis.startdatum).add(2, "years").toDate()
})
} catch (e) {
return null
}
// Endenergieverbrauch // Endenergieverbrauch
// Um den EEV auszurechnen, müssen die Verbräuche zu kWh konvertiert werden. // Um den EEV auszurechnen, müssen die Verbräuche zu kWh konvertiert werden.

View File

@@ -11,6 +11,7 @@ export function energetischeNutzflaecheVerbrauchsausweisWohnen_2023(ausweis: Ver
export async function endEnergieVerbrauchVerbrauchsausweis_2023(ausweis: VerbrauchsausweisWohnen & { gebaeude_stammdaten: GebaeudeStammdaten }): Promise<number> { export async function endEnergieVerbrauchVerbrauchsausweis_2023(ausweis: VerbrauchsausweisWohnen & { gebaeude_stammdaten: GebaeudeStammdaten }): Promise<number> {
const date = ausweis.startdatum; const date = ausweis.startdatum;
const klimafaktoren = await getKlimafaktoren( const klimafaktoren = await getKlimafaktoren(
date, date,
ausweis.gebaeude_stammdaten.plz ausweis.gebaeude_stammdaten.plz

View File

@@ -7,16 +7,15 @@ export const getKlimafaktoren = memoize(async (date: Date, plz: string) => {
return null; return null;
} }
const response = await client.v1.klimafaktoren.query({ try {
plz, const response = await client.v1.klimafaktoren.query({
genauigkeit: "years", plz,
startdatum: date, genauigkeit: "years",
enddatum: moment(date).add(2, "years").toDate() startdatum: date,
}) enddatum: moment(date).add(2, "years").toDate(),
});
if (!response) { return response;
} catch (e) {
return null; return null;
} }
});
return response;
});

14
src/lib/caller.ts Normal file
View File

@@ -0,0 +1,14 @@
import { appRouter, t } from "@ibcornelsen/api";
import { API_ACCESS_TOKEN_COOKIE_NAME } from "./constants";
export const createCaller = function (opts: any) {
// 1. create a caller-function for your router
const createCaller = t.createCallerFactory(appRouter);
// 2. create a caller using your `Context`
return createCaller({
authorization: opts.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME).value ?? "",
ip: opts.clientAddress,
req: opts.request
});
}

7
src/lib/constants.ts Normal file
View File

@@ -0,0 +1,7 @@
import { createMollieClient } from "@mollie/api-client";
export const API_ACCESS_TOKEN_COOKIE_NAME = "accessToken";
// Mollie Payments
export const TEST_MOLLIE_API_TOKEN = "test_jenmp2Pq3j3N6HeQxwx7qbHasWMdnx";
export const mollieClient = createMollieClient({ apiKey: TEST_MOLLIE_API_TOKEN })

27
src/lib/login.ts Normal file
View File

@@ -0,0 +1,27 @@
import { AppRoute } from "@ibcornelsen/api";
import { inferProcedureOutput } from "@trpc/server";
import Cookies from "js-cookie";
import { client } from "src/trpc"
export async function loginClient(email: string, passwort: string): Promise<inferProcedureOutput<AppRouter["v1"]["benutzer"]["getRefreshToken"]> | null> {
try {
const response = await client.v1.benutzer.getRefreshToken.query({
email,
passwort
})
const options = {
domain: `.${window.location.hostname}`,
path: "/",
expires: response.exp
}
Cookies.set("accessToken", response.accessToken, options);
Cookies.set("refreshToken", response.refreshToken, options);
Cookies.set("uid", response.uid, options);
return response;
} catch (e) {
return null;
}
}

View File

@@ -9,18 +9,79 @@
import ZipSearch from "#components/ZIPSearch.svelte"; import ZipSearch from "#components/ZIPSearch.svelte";
import moment from "moment"; import moment from "moment";
import BilderZusatzsysteme from "#components/Ausweis/BilderZusatzsysteme.svelte"; import BilderZusatzsysteme from "#components/Ausweis/BilderZusatzsysteme.svelte";
import { RawNotificationWrapper, RawNotification, notifications } from "@ibcornelsen/ui"; import { RawNotificationWrapper, RawNotification, notifications, addNotification } from "@ibcornelsen/ui";
import { auditHeizungGebaeudeBaujahr } from "#components/Verbrauchsausweis/audits/HeizungGebaeudeBaujahr"; import { auditHeizungGebaeudeBaujahr } from "#components/Verbrauchsausweis/audits/HeizungGebaeudeBaujahr";
import { AuditType, hidden } from "#components/Verbrauchsausweis/audits/hidden"; import { AuditType, hidden } from "#components/Verbrauchsausweis/audits/hidden";
import { auditBedarfsausweisBenoetigt } from "#components/Verbrauchsausweis/audits/BedarfsausweisBenoetigt"; import { auditBedarfsausweisBenoetigt } from "#components/Verbrauchsausweis/audits/BedarfsausweisBenoetigt";
import { auditVerbrauchAbweichung } from "#components/Verbrauchsausweis/audits/VerbrauchAbweichung"; import { auditVerbrauchAbweichung } from "#components/Verbrauchsausweis/audits/VerbrauchAbweichung";
import { GebaeudeStammdaten, VerbrauchsausweisWohnen } from "@ibcornelsen/database"; import { GebaeudeStammdaten, VerbrauchsausweisWohnen } from "@ibcornelsen/database";
import { client } from "src/trpc"; import { client } from "src/trpc";
import Cookies from "js-cookie";
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants";
import Overlay from "#components/Overlay.svelte";
export let uid: string = ""; export let uid: string | null = null;
let gebaeude: GebaeudeStammdaten = {} as GebaeudeStammdaten; async function spaeterWeitermachen() {
let ausweis: VerbrauchsausweisWohnen = {} as VerbrauchsausweisWohnen;
// Um einen Ausweis zu speichern müssen wir eingeloggt sein, andernfalls wird die API den call ablehnen.
// Wir prüfen also ob wir eingeloggt sind und leiten den Nutzer ggf. auf die Login Seite weiter.
if (!Cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)) {
loginOverlayHidden = false;
const getEvent = (event: MessageEvent) => {
if (event.data == "AUTHORIZED") {
spaeterWeitermachen();
window.removeEventListener("message", getEvent)
loginOverlayHidden = true;
}
}
window.addEventListener("message", getEvent)
return
}
if (uid) {
// Anscheinend wurde der Ausweis bereits erstellt und hat eine UID.
// Jetzt müssen wir ihn nun nur noch abspeichern.
try {
await client.v1.verbrauchsausweisWohnen[2016].speichern.mutate({
...ausweis,
gebaeude_stammdaten: gebaeude,
uid
})
window.location.href = `/ausweis-gespeichert?uid=${uid}`;
} catch (e) {
addNotification({
dismissable: false,
message: "Ausweis konnte nicht gespeichert werden, bitte versuchen sie es erneut.",
subtext: "Sollte das Problem weiterhin bestehen, kontaktieren sie bitte den Support.",
timeout: 6000,
type: "error"
})
}
} else {
// Wir speichern den Ausweis ab und leiten auf die "ausweis-gespeichert" Seite weiter.
try {
const { uid } = await client.v1.verbrauchsausweisWohnen[2016].erstellen.mutate({
...ausweis,
gebaeude_stammdaten: gebaeude
})
window.location.href = `/ausweis-gespeichert?uid=${uid}`;
} catch (e) {
addNotification({
dismissable: false,
message: "Ausweis konnte nicht gespeichert werden, bitte versuchen sie es erneut.",
subtext: "Sollte das Problem weiterhin bestehen, kontaktieren sie bitte den Support.",
timeout: 6000,
type: "error"
})
}
}
}
export let gebaeude: GebaeudeStammdaten = {} as GebaeudeStammdaten;
export let ausweis: VerbrauchsausweisWohnen = {} as VerbrauchsausweisWohnen;
if (uid) { if (uid) {
// NOTE: Funktioniert nicht mehr // NOTE: Funktioniert nicht mehr
async () => { async () => {
@@ -63,7 +124,7 @@
async function ausweisAbschicken() { async function ausweisAbschicken() {
overlay.ariaHidden = "false"; waitOverlayHidden = false;
const response = await client.v1.verbrauchsausweisWohnen[2016].erstellen.mutate({ const response = await client.v1.verbrauchsausweisWohnen[2016].erstellen.mutate({
...ausweis, ...ausweis,
gebaeude_stammdaten: gebaeude gebaeude_stammdaten: gebaeude
@@ -72,13 +133,17 @@
window.location.href = `/kundendaten?uid=${response.uid}`; window.location.href = `/kundendaten?uid=${response.uid}`;
} }
let overlay: HTMLDivElement; let waitOverlayHidden = true;
let loginOverlayHidden = true;
</script> </script>
<div bind:this={overlay} aria-hidden="true" class="aria-hidden:hidden fixed top-0 left-0 w-[100vw] h-[100vh] flex items-center justify-center bg-[rgba(0,0,0,0.8)] z-50"> <Overlay hidden={loginOverlayHidden}>
<iframe src="/auth/embedded-login" frameborder="0" width="600" height="400"></iframe>
</Overlay>
<Overlay hidden={waitOverlayHidden}>
<p class="text-white font-semibold text-4xl">Bitte warten sie, ihr Ausweis wird nun erstellt.</p> <p class="text-white font-semibold text-4xl">Bitte warten sie, ihr Ausweis wird nun erstellt.</p>
</div> </Overlay>
<div class="flex flex-row gap-8 items-center mb-8"> <div class="flex flex-row gap-8 items-center mb-8">
<div class="flex flex-col w-full"> <div class="flex flex-col w-full">
@@ -94,7 +159,7 @@
class="bg-[rgba(252,234,187,0.2)] border-2 p-4 rounded-lg border-[#ffcc03]" class="bg-[rgba(252,234,187,0.2)] border-2 p-4 rounded-lg border-[#ffcc03]"
> >
<div class="flex flex-row justify-between"> <div class="flex flex-row justify-between">
<a class="button" href="/speichern">Später Weitermachen</a> <button class="button" on:click={spaeterWeitermachen}>Später Weitermachen</button>
<div class="flex gap-4"> <div class="flex gap-4">
<Hilfe /> <Hilfe />
<button <button
@@ -231,15 +296,22 @@
<div class="GRB"> <div class="GRB">
<!-- Anteil WW enthalten --> <!-- Anteil WW enthalten -->
<div class="flex flex-col"> <div class="flex flex-col">
<div class="flex flex-row gap-6"> <div class="flex flex-row gap-4 items-center">
<label class="radio-inline" <Label>Warmwasser im Verbrauch enthalten</Label>
><input <input
type="checkbox" type="checkbox"
name="warmwasser_enthalten" name="warmwasser_enthalten"
bind:checked={ausweis bind:checked={ausweis.warmwasser_enthalten}
.warmwasser_enthalten} />
/>Warmwasser im Verbrauch enthalten</label </div>
> <div class="flex flex-row gap-4 items-center">
<Label>Anteil bekannt</Label>
<input
type="checkbox"
name="warmwasser_anteil_bekannt"
bind:checked={ausweis.warmwasser_anteil_bekannt}
disabled={!ausweis.warmwasser_enthalten}
/>
</div> </div>
</div> </div>
@@ -255,7 +327,7 @@
maxlength="2" maxlength="2"
type="number" type="number"
bind:value={ausweis.anteil_warmwasser_1} bind:value={ausweis.anteil_warmwasser_1}
disabled={!ausweis.warmwasser_enthalten} disabled={!ausweis.warmwasser_anteil_bekannt}
autocomplete="off" autocomplete="off"
/> />
</div> </div>
@@ -273,7 +345,7 @@
autocomplete="off" autocomplete="off"
bind:value={ausweis.anteil_warmwasser_2} bind:value={ausweis.anteil_warmwasser_2}
disabled={!ausweis.zusaetzliche_heizquelle || disabled={!ausweis.zusaetzliche_heizquelle ||
!ausweis.warmwasser_enthalten} !ausweis.warmwasser_anteil_bekannt}
/> />
</div> </div>

View File

@@ -0,0 +1,56 @@
<script lang="ts">
import { addNotification } from "@ibcornelsen/ui";
import { loginClient } from "#lib/login";
let email: string;
let passwort: string;
async function login() {
const response = await loginClient(email, passwort)
if (response === null) {
addNotification({
message: "Ups...",
subtext: "Das hat leider nicht geklappt, haben sie ihr Passwort und ihre Email Adresse richtig eingegeben?",
type: "error",
timeout: 6000,
dismissable: true
})
} else {
parent.postMessage("AUTHORIZED", "*");
}
}
</script>
<div style="width:50%;margin: 0 auto">
<h1>Login</h1>
<div class="flex flex-col gap-4">
<div>
<h4>Email</h4>
<input
class="px-2.5 py-1.5 rounded-lg border bg-gray-50"
type="text"
placeholder="Email"
name="email"
bind:value={email}
required
/>
</div>
<div>
<h4>Passwort</h4>
<input
class="px-2.5 py-1.5 rounded-lg border bg-gray-50"
type="password"
placeholder="********"
name="password"
bind:value={passwort}
required
/>
</div>
<button class="button" on:click={login}>Einloggen</button>
<div class="flex-row justify-between" style="margin-top: 10px">
<a href="/signup">Registrieren</a>
<a href="/user/passwort_vergessen">Passwort Vergessen?</a>
</div>
</div>
</div>

View File

@@ -6,6 +6,7 @@
import PriceContainer from "#components/Kaufabschluss/PriceContainer.svelte"; import PriceContainer from "#components/Kaufabschluss/PriceContainer.svelte";
import { Benutzer, Bezahlmethoden, Enums, Rechnungen, VerbrauchsausweisWohnen } from "@ibcornelsen/database"; import { Benutzer, Bezahlmethoden, Enums, Rechnungen, VerbrauchsausweisWohnen } from "@ibcornelsen/database";
import PaymentOption from "#components/PaymentOption.svelte"; import PaymentOption from "#components/PaymentOption.svelte";
import { client } from "src/trpc";
export let user: Benutzer; export let user: Benutzer;
export let ausweis: VerbrauchsausweisWohnen export let ausweis: VerbrauchsausweisWohnen
@@ -15,6 +16,17 @@
let agbAkzeptiert: boolean; let agbAkzeptiert: boolean;
let datenschutzAkzeptiert: boolean; let datenschutzAkzeptiert: boolean;
async function createPayment() {
const response = await client.v1.payments.create.mutate({
ausweisart: "VerbrauchsausweisWohnen",
uid: ausweis.uid,
payment_method: selectedPaymentType,
services: []
})
window.location.href = response.checkout_url
}
</script> </script>
<div class="w-full px-8"> <div class="w-full px-8">
@@ -303,6 +315,7 @@
</div> </div>
</div> </div>
<button class="pay-button" disabled={!agbAkzeptiert || !datenschutzAkzeptiert} <button class="pay-button" disabled={!agbAkzeptiert || !datenschutzAkzeptiert}
on:click={createPayment}
>Kostenpflichtig Bestellen</button >Kostenpflichtig Bestellen</button
> >
</div> </div>

View File

@@ -1,26 +1,16 @@
<script lang="ts"> <script lang="ts">
import Cookies from "js-cookie"
import { addNotification } from "@ibcornelsen/ui"; import { addNotification } from "@ibcornelsen/ui";
import { client } from "src/trpc"; import { loginClient } from "#lib/login";
let email: string; let email: string;
let passwort: string; let passwort: string;
export let redirect: string | null = null;
async function login() { async function login() {
try { const response = await loginClient(email, passwort)
const response = await client.v1.benutzer.getRefreshToken.query({
email, if (response === null) {
passwort
})
const options = {
domain: `.${window.location.hostname}`,
path: "/",
expires: response.exp
}
Cookies.set("accessToken", response.accessToken, options);
Cookies.set("refreshToken", response.refreshToken, options);
window.location.href = "/user";
} catch (e) {
addNotification({ addNotification({
message: "Ups...", message: "Ups...",
subtext: "Das hat leider nicht geklappt, haben sie ihr Passwort und ihre Email Adresse richtig eingegeben?", subtext: "Das hat leider nicht geklappt, haben sie ihr Passwort und ihre Email Adresse richtig eingegeben?",
@@ -28,6 +18,13 @@
timeout: 6000, timeout: 6000,
dismissable: true dismissable: true
}) })
} else {
if (redirect) {
window.location.href = redirect
return
}
window.location.href = "/user";
} }
} }
</script> </script>
@@ -59,8 +56,8 @@
</div> </div>
<button class="button" on:click={login}>Einloggen</button> <button class="button" on:click={login}>Einloggen</button>
<div class="flex-row justify-between" style="margin-top: 10px"> <div class="flex-row justify-between" style="margin-top: 10px">
<a href="/signup">Registrieren</a> <a href="/signup?redirect={redirect}">Registrieren</a>
<a href="/user/passwort_vergessen">Passwort Vergessen?</a> <a href="/user/passwort_vergessen?redirect={redirect}">Passwort Vergessen?</a>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -7,14 +7,22 @@
let vorname: string; let vorname: string;
let name: string; let name: string;
export let redirect: string | null = null;
async function login() { async function login() {
try { try {
const response = await client.v1.benutzer.erstellen.query({ const response = await client.v1.benutzer.erstellen.mutate({
email, email,
passwort, passwort,
vorname, vorname,
name name
}) })
if (redirect) {
window.location.href = redirect
return
}
window.location.href = "/login"; window.location.href = "/login";
} catch (e) { } catch (e) {
addNotification({ addNotification({
@@ -78,9 +86,9 @@
> >
<div class="flex-row justify-between" style="margin-top: 10px"> <div class="flex-row justify-between" style="margin-top: 10px">
<a <a
href="/login">Einloggen</a href="/login?redirect={redirect}">Einloggen</a
> >
<a href="/user/passwort_vergessen">Passwort Vergessen?</a> <a href="/user/passwort_vergessen?redirect={redirect}">Passwort Vergessen?</a>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -0,0 +1,29 @@
---
import AusweisLayout from "#layouts/AusweisLayout.astro";
import { prisma } from "@ibcornelsen/database";
const uid = Astro.url.searchParams.get("uid");
if (!uid) {
return Astro.redirect("/404");
}
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
where: {
uid,
},
});
if (!ausweis) {
return Astro.redirect("/404");
}
const url = `https://ibcornelsen.de/verbrauchsausweis?uid=${uid}`
---
<AusweisLayout title="Ausweis Gespeichert">
<h1>Ausweis Gespeichert</h1>
<p>
Der Ausweis wurde erfolgreich gespeichert. Sie können ihn nun unter <a href={url}>{url}</a> fortsetzen.
</p>
</AusweisLayout>

View File

@@ -0,0 +1,9 @@
---
import BlankLayout from "#layouts/BlankLayout.astro";
import EmbeddedLoginModule from "#modules/EmbeddedLoginModule.svelte";
---
<BlankLayout title="Login - IBCornelsen">
<EmbeddedLoginModule client:only></EmbeddedLoginModule>
</BlankLayout>

View File

@@ -4,34 +4,34 @@ import KundendatenModule from "#modules/KundendatenModule.svelte";
import AusweisLayout from "#layouts/AusweisLayout.astro"; import AusweisLayout from "#layouts/AusweisLayout.astro";
import { Benutzer, Enums, prisma } from "@ibcornelsen/database"; import { Benutzer, Enums, prisma } from "@ibcornelsen/database";
// Man sollte nur auf diese Seite kommen, wenn ein Ausweis bereits vorliegt und in der Datenbank abgespeichert wurde.
const uidAusweis = Astro.url.searchParams.get("uid");
if (!uidAusweis) {
return Astro.redirect("/404");
}
const uid = Astro.cookies.get("uid").value;
if (!uid) {
return Astro.redirect("/401");
}
const user = await prisma.benutzer.findUnique({ const user = await prisma.benutzer.findUnique({
where: { where: {
id: 1, uid
}, },
}) as Benutzer; }) as Benutzer;
// Man sollte nur auf diese Seite kommen, wenn ein Ausweis bereits vorliegt und in der Datenbank abgespeichert wurde.
const uid = Astro.url.searchParams.get("uid");
if (!uid) {
return Astro.redirect("/");
}
// NOTE: Muss umgestellt werden, wir brauchen einen Kundendaten Abschluss für jede Ausweisart.
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({ const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
where: { where: {
uid, uid: uidAusweis,
}, },
}); });
if (!ausweis) { if (!ausweis) {
return Astro.redirect("/"); return Astro.redirect("/404");
} }
--- ---
<AusweisLayout title="Kundendaten Aufnehmen - IBCornelsen"> <AusweisLayout title="Kundendaten Aufnehmen - IBCornelsen">

View File

@@ -2,8 +2,10 @@
import moment from "moment"; import moment from "moment";
import LoginModule from "../modules/LoginModule.svelte"; import LoginModule from "../modules/LoginModule.svelte";
import Layout from "../layouts/Layout.astro"; import Layout from "../layouts/Layout.astro";
const redirect = Astro.url.searchParams.get("redirect")
--- ---
<Layout title="Login"> <Layout title="Login">
<LoginModule client:only></LoginModule> <LoginModule client:only redirect={redirect}></LoginModule>
</Layout> </Layout>

View File

@@ -1,16 +1,10 @@
--- ---
import moment from "moment"; import RegisterModule from "../modules/RegisterModule.svelte";
import RegisterView from "../modules/RegisterModule.svelte";
import Layout from "../layouts/Layout.astro"; import Layout from "../layouts/Layout.astro";
const token = Astro.cookies.get("token").value; const redirect = Astro.url.searchParams.get("redirect");
const expires = Astro.cookies.get("expires").number();
const now = moment().unix();
if (token && now < expires) {
return Astro.redirect("/user");
}
--- ---
<Layout title="Registrieren - IBCornelsen"> <Layout title="Registrieren - IBCornelsen">
<RegisterView client:only></RegisterView> <RegisterModule client:only redirect={redirect}></RegisterModule>
</Layout> </Layout>

View File

@@ -2,12 +2,28 @@
import AusweisLayout from "#layouts/AusweisLayout.astro"; import AusweisLayout from "#layouts/AusweisLayout.astro";
import VerbrauchsausweisWohnenModule from "#modules/Ausweise/VerbrauchsausweisWohnenModule.svelte"; import VerbrauchsausweisWohnenModule from "#modules/Ausweise/VerbrauchsausweisWohnenModule.svelte";
import { GebaeudeStammdaten, VerbrauchsausweisWohnen, prisma } from "@ibcornelsen/database";
const uid = Astro.cookies.get("ausweis_uid").value; const uid = Astro.url.searchParams.get("uid");
let ausweis: VerbrauchsausweisWohnen = {} as VerbrauchsausweisWohnen;
let gebaeude: GebaeudeStammdaten = {} as GebaeudeStammdaten;
if (uid) {
const request = await prisma.verbrauchsausweisWohnen.findUnique({
where: { uid },
include: { gebaeude_stammdaten: true },
})
if (request) {
ausweis = request;
gebaeude = request.gebaeude_stammdaten;
}
}
--- ---
<AusweisLayout title="Verbrauchsausweis erstellen"> <AusweisLayout title="Verbrauchsausweis erstellen">
<VerbrauchsausweisWohnenModule client:load uid={uid} /> <VerbrauchsausweisWohnenModule client:load uid={uid} ausweis={ausweis} gebaeude={gebaeude} />
</AusweisLayout> </AusweisLayout>

View File

@@ -1,14 +1,21 @@
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client'; import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import cookies from 'js-cookie'; import cookies from 'js-cookie';
import type { AppRouter } from '@ibcornelsen/api'; import type { AppRouter } from '@ibcornelsen/api';
import { Buffer } from 'buffer';
export const client = createTRPCProxyClient<AppRouter>({ export const client = createTRPCProxyClient<AppRouter>({
links: [ links: [
httpBatchLink({ httpBatchLink({
url: 'http://localhost:3001/', url: 'http://localhost:3001/',
headers() { headers() {
const accessToken = cookies.get('accessToken');
if (!accessToken) return {};
const buffer = Buffer.from(accessToken, 'utf-8');
const base64 = buffer.toString('base64')
return { return {
'Authorization': `Bearer ${cookies.get('accessToken')}`, 'Authorization': `Bearer ${base64}`,
}; };
}, },
}), }),