Verbrauchsausweis Test Vollständig, Besserer Login angefangen
This commit is contained in:
2
.vscode/tasks.json
vendored
2
.vscode/tasks.json
vendored
@@ -6,7 +6,7 @@
|
||||
{
|
||||
"label": "Docker Container Starten",
|
||||
"type": "shell",
|
||||
"command": "docker-compose up"
|
||||
"command": "docker compose up"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -241,6 +241,34 @@ describe("Verbrauchsausweis erstellen Schritt 1", () => {
|
||||
|
||||
cy.get("form[name='login'] button[type='submit']").click();
|
||||
|
||||
// Der Ausweis sollte jetzt schon erstellt worden sein.
|
||||
// Der Ausweis sollte jetzt schon erstellt worden sein und wir sollten auf die kundendaten seite weitergeleitet worden sein.
|
||||
cy.url().should("contain", "/kundendaten");
|
||||
|
||||
// Wir füllen jetzt die Kundendaten aus.
|
||||
cy.get("input[name='vorname']").should("contain.value", vorname);
|
||||
cy.get("input[name='name']").should("contain.value", nachname);
|
||||
cy.get("input[name='email']").should("contain.value", email);
|
||||
cy.get("input[name='telefon']").type(faker.phone.number());
|
||||
|
||||
cy.get("input[name='rechnung_empfaenger']").type(`${vorname} ${nachname}`);
|
||||
cy.get("input[name='rechnung_strasse']").type(faker.location.streetAddress());
|
||||
// TODO: Random Plz generieren, allerdings muss die auch in der Datenbank vorhanden sein...
|
||||
cy.get("input[name='rechnung_plz']").type("2103");
|
||||
// Jetzt sollte der PLZ Container erscheinen, dort klicken wir einfach das erste Element an.
|
||||
cy.get("div[data-test='plz-container']").children().first().click();
|
||||
cy.get("input[name='rechnung_telefon']").type(faker.phone.number());
|
||||
cy.get("input[name='rechnung_email']").type(faker.internet.email());
|
||||
cy.get("button[data-test='paypal']").click();
|
||||
|
||||
// Datenschutz und AGB akzeptieren, dann schicken wir das Formular ab.
|
||||
cy.get("input[name='agb-akzeptieren']").check()
|
||||
cy.get("input[name='datenschutz-akzeptieren']").check()
|
||||
cy.get("button[type='submit']").click();
|
||||
|
||||
cy.origin('https://www.mollie.com', () => {
|
||||
// Jetzt sind wir auf der Mollie Seite, dort wählen wir den "paid" status aus
|
||||
cy.get("input[type='radio'][name='final_state'][value='paid']").check();
|
||||
// Da wird unser Test fehlschlagen, da die localhost domain von Mollie aus nicht erreichbar ist.
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
"pg": "^8.11.0",
|
||||
"sass": "^1.62.1",
|
||||
"svelte": "^3.59.1",
|
||||
"svelte-dialogs": "^1.2.2",
|
||||
"svelte-preprocess": "^5.0.3",
|
||||
"tailwindcss": "^3.3.2",
|
||||
"trpc-openapi": "^1.2.0",
|
||||
|
||||
49
src/client/lib/spawnLoginPrompt.ts
Normal file
49
src/client/lib/spawnLoginPrompt.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { dialogs } from "../../../svelte-dialogs.config";
|
||||
import { loginClient } from "#lib/login";
|
||||
import { addNotification } from "#components/Notifications/shared";
|
||||
|
||||
export async function spawnLoginPrompt() {
|
||||
const result = await dialogs.prompt(
|
||||
[
|
||||
{
|
||||
label: "Email",
|
||||
type: "email",
|
||||
required: true,
|
||||
placeholder: "Email",
|
||||
name: "email"
|
||||
},
|
||||
{
|
||||
label: "Passwort",
|
||||
type: "password",
|
||||
name: "passwort",
|
||||
required: true,
|
||||
placeholder: "********",
|
||||
},
|
||||
],
|
||||
{
|
||||
title: "Login",
|
||||
submitButtonText: "Einloggen",
|
||||
cancelButtonText: "Abbrechen",
|
||||
}
|
||||
);
|
||||
|
||||
if (!result) return false;
|
||||
|
||||
const [email, passwort] = result;
|
||||
|
||||
const loginResult = await loginClient(email, passwort);
|
||||
|
||||
if (loginResult === null) {
|
||||
addNotification({
|
||||
type: "error",
|
||||
message: "Einloggen fehlgeschlagen",
|
||||
dismissable: true,
|
||||
subtext: "Bitte überprüfen Sie ihre Eingaben und versuchen es erneut.",
|
||||
timeout: 5000,
|
||||
})
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
67
src/client/lib/spawnSignupPrompt.ts
Normal file
67
src/client/lib/spawnSignupPrompt.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { dialogs } from "../../../svelte-dialogs.config";
|
||||
import { addNotification } from "#components/Notifications/shared";
|
||||
import { client } from "src/trpc";
|
||||
|
||||
export async function spawnSignupPrompt() {
|
||||
const result = await dialogs.prompt(
|
||||
[
|
||||
{
|
||||
label: "Vorname",
|
||||
type: "text",
|
||||
required: true,
|
||||
placeholder: "Vorname",
|
||||
name: "vorname"
|
||||
},
|
||||
{
|
||||
label: "Name",
|
||||
type: "text",
|
||||
required: true,
|
||||
placeholder: "Name",
|
||||
name: "name"
|
||||
},
|
||||
{
|
||||
label: "Email",
|
||||
type: "email",
|
||||
required: true,
|
||||
placeholder: "Email",
|
||||
name: "email"
|
||||
},
|
||||
{
|
||||
label: "Passwort",
|
||||
type: "password",
|
||||
name: "passwort",
|
||||
required: true,
|
||||
placeholder: "********",
|
||||
},
|
||||
],
|
||||
{
|
||||
title: "Registrieren",
|
||||
submitButtonText: "Registrieren",
|
||||
cancelButtonText: "Abbrechen",
|
||||
}
|
||||
);
|
||||
|
||||
if (!result) return false;
|
||||
|
||||
const [vorname, name, email, passwort] = result;
|
||||
|
||||
try {
|
||||
const response = await client.v1.benutzer.erstellen.mutate({
|
||||
email,
|
||||
passwort,
|
||||
vorname,
|
||||
name,
|
||||
});
|
||||
|
||||
return true;
|
||||
} catch(e) {
|
||||
addNotification({
|
||||
type: "error",
|
||||
message: "Registrieren fehlgeschlagen",
|
||||
dismissable: true,
|
||||
subtext: "Ein Fehler ist aufgetreten, vielleicht wird die angegebene Email bereits verwendet.",
|
||||
timeout: 5000,
|
||||
})
|
||||
return false;
|
||||
}
|
||||
}
|
||||
7
src/client/tickets/createTicket.ts
Normal file
7
src/client/tickets/createTicket.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { AppRouter } from "@ibcornelsen/api";
|
||||
import { inferProcedureInput } from "@trpc/server";
|
||||
import { client } from "src/trpc";
|
||||
|
||||
export async function createTicket(info: inferProcedureInput<AppRouter["v1"]["tickets"]["erstellen"]>) {
|
||||
return await client.v1.tickets.erstellen.mutate(info)
|
||||
}
|
||||
0
src/client/tickets/index.ts
Normal file
0
src/client/tickets/index.ts
Normal file
@@ -1,6 +1,6 @@
|
||||
import { AppRouter } from "@ibcornelsen/api";
|
||||
import { GebaeudeBilder } from "@ibcornelsen/database/client";
|
||||
import { inferProcedureInput } from "@trpc/server";
|
||||
import { Benutzer, GebaeudeBilder } from "@ibcornelsen/database/client";
|
||||
import { inferProcedureInput, inferProcedureOutput } from "@trpc/server";
|
||||
|
||||
export type UploadedGebaeudeBild = Omit<
|
||||
GebaeudeBilder,
|
||||
@@ -66,3 +66,5 @@ export type BedarfsausweisWohnenClient = inferProcedureInput<
|
||||
export type GebaeudeClient = inferProcedureInput<
|
||||
AppRouter["v1"]["verbrauchsausweisWohnen"]["2016"]["speichern"]
|
||||
>["gebaeude"];
|
||||
|
||||
export type BenutzerClient = inferProcedureOutput<AppRouter["v1"]["benutzer"]["fromPublicId"]>
|
||||
@@ -7,7 +7,7 @@
|
||||
export let selectedPaymentType: Bezahlmethoden;
|
||||
</script>
|
||||
|
||||
<button type="button" class="flex flex-col items-center cursor-pointer" class:bg-gray-100={paymentType == selectedPaymentType} on:click={() => selectedPaymentType = paymentType}>
|
||||
<button type="button" data-test={paymentType} class="flex flex-col items-center cursor-pointer" class:bg-gray-100={paymentType == selectedPaymentType} on:click={() => selectedPaymentType = paymentType}>
|
||||
<img src={icon} alt={name} />
|
||||
<span aria-label={name}>
|
||||
{name}
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
maxlength="5"
|
||||
/>
|
||||
|
||||
<div class="absolute top-[calc(100%+4px)] left-0 w-full bg-white py-2 shadow-md rounded-lg" hidden={hideZipDropdown}>
|
||||
<div data-test="plz-container" class="absolute top-[calc(100%+4px)] left-0 w-full bg-white py-2 shadow-md rounded-lg" hidden={hideZipDropdown}>
|
||||
{#each zipCodes as zipCode}
|
||||
<div class="hover:bg-gray-100 cursor-pointer px-2 py-0.5" tabindex="-1" on:click={() => {
|
||||
zip = zipCode.plz;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
---
|
||||
import "../style/global.scss"
|
||||
import "../../svelte-dialogs.config"
|
||||
import Footer from '../components/Footer.astro';
|
||||
import Header from '../components/Header.astro';
|
||||
import SidebarLeft from '../components/SidebarLeft.astro';
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import i18next from "i18next";
|
||||
|
||||
import "../style/global.scss";
|
||||
import "../../svelte-dialogs.config"
|
||||
import Footer from "../components/Footer.astro";
|
||||
import Header from "../components/Header.astro";
|
||||
import SidebarLeft from "../components/SidebarLeft.astro";
|
||||
|
||||
137
src/modules/Ausweise/AusweisWeiter.svelte
Normal file
137
src/modules/Ausweise/AusweisWeiter.svelte
Normal file
@@ -0,0 +1,137 @@
|
||||
<script lang="ts">
|
||||
import { BenutzerClient, GebaeudeClient, UploadedGebaeudeBild, VerbrauchsausweisWohnenClient } from "#components/Ausweis/types";
|
||||
import { addNotification, updateNotification } from "@ibcornelsen/ui";
|
||||
import { validateAccessTokenClient } from "#client/lib/validateAccessToken";
|
||||
import { client } from "src/trpc";
|
||||
import EmbeddedAuthFlowModule from "#modules/EmbeddedAuthFlowModule.svelte";
|
||||
import Overlay from "#components/Overlay.svelte";
|
||||
|
||||
export let gebaeude: GebaeudeClient;
|
||||
export let images: UploadedGebaeudeBild[];
|
||||
export let ausweis: VerbrauchsausweisWohnenClient;
|
||||
export let user: BenutzerClient;
|
||||
|
||||
async function bilderHochladen() {
|
||||
// Alle Bilder hochladen
|
||||
const notification = addNotification({
|
||||
dismissable: false,
|
||||
message: "Bilder hochladen.",
|
||||
subtext: `${images.length} Bilder werden hochgeladen, bitte haben sie Geduld.`,
|
||||
timeout: 0,
|
||||
type: "info"
|
||||
})
|
||||
for (let i = 0; i < images.length; i++) {
|
||||
const image = images[i];
|
||||
if (image.uid) {
|
||||
// Bild wurde bereits hochgeladen, wir müssen es also nicht nochmal hochladen.
|
||||
continue
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await client.v1.bilder.upload.mutate({
|
||||
base64: image.base64,
|
||||
kategorie: image.kategorie,
|
||||
gebaeude_uid: gebaeude.uid
|
||||
})
|
||||
|
||||
image.uid = response.uid
|
||||
|
||||
updateNotification(notification, {
|
||||
dismissable: true,
|
||||
message: "Bild hochgeladen.",
|
||||
subtext: `${i + 1}/${images.length} Bildern wurden erfolgreich hochgeladen, bitte haben sie Geduld.`,
|
||||
timeout: 4000
|
||||
})
|
||||
} catch (e) {
|
||||
updateNotification(notification, {
|
||||
dismissable: true,
|
||||
message: "Bild konnte nicht hochgeladen werden.",
|
||||
subtext: `Bild ${i + 1}/${images.length} konnte nicht hochgeladen werden, wir haben bereits ein Ticket erstellt und melden uns so schnell wie möglich bei ihnen.`,
|
||||
timeout: 150000,
|
||||
type: "error"
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function ausweisSpeichern() {
|
||||
// Um einen Ausweis zu speichern müssen wir eingeloggt sein, andernfalls wird die API den call ablehnen.
|
||||
// Wir prüfen also ob wir eingeloggt sind und leiten den Nutzer ggf. auf die Login Seite weiter.
|
||||
if (!await validateAccessTokenClient()) {
|
||||
loginOverlayHidden = false;
|
||||
return
|
||||
}
|
||||
|
||||
loginOverlayHidden = true;
|
||||
|
||||
if (ausweis.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
|
||||
})
|
||||
|
||||
await bilderHochladen();
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
// TODO: Ticket mit Fehldermeldung abschicken.
|
||||
}
|
||||
} else {
|
||||
// Wir speichern den Ausweis ab und leiten auf die "ausweis-gespeichert" Seite weiter.
|
||||
try {
|
||||
const response = await client.v1.verbrauchsausweisWohnen[2016].erstellen.mutate({
|
||||
ausweis,
|
||||
gebaeude
|
||||
})
|
||||
ausweis.uid = response.uid;
|
||||
gebaeude.uid = response.gebaeude_uid;
|
||||
|
||||
await bilderHochladen();
|
||||
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
await client.v1.tickets.erstellen.mutate({
|
||||
titel: "Ausweis konnte nicht gespeichert werden",
|
||||
beschreibung: e.stack,
|
||||
email: user.email ?? "",
|
||||
metadata: JSON.stringify({
|
||||
ausweis,
|
||||
gebaeude
|
||||
})
|
||||
})
|
||||
// TODO: Ticket mit Fehldermeldung abschicken.
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
async function ausweisAbschicken(e: SubmitEvent) {
|
||||
e.preventDefault()
|
||||
const result = await ausweisSpeichern();
|
||||
|
||||
if (result === true) {
|
||||
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 type="submit" class="button">Weiter</button>
|
||||
@@ -20,14 +20,22 @@
|
||||
import EmbeddedAuthFlowModule from "#modules/EmbeddedAuthFlowModule.svelte";
|
||||
import AusweisGespeichertModule from "./AusweisGespeichertModule.svelte";
|
||||
import { validateAccessTokenClient } from "src/client/lib/validateAccessToken";
|
||||
import { UploadedGebaeudeBild, VerbrauchsausweisWohnenClient, GebaeudeClient } from "#components/Ausweis/types";
|
||||
import { UploadedGebaeudeBild, VerbrauchsausweisWohnenClient, GebaeudeClient, BenutzerClient } from "#components/Ausweis/types";
|
||||
|
||||
export let gebaeude: GebaeudeClient = {} as GebaeudeClient;
|
||||
export let images: UploadedGebaeudeBild[] = [];
|
||||
export let ausweis: VerbrauchsausweisWohnenClient = {} as VerbrauchsausweisWohnenClient;
|
||||
export let user: BenutzerClient = {} as BenutzerClient;
|
||||
|
||||
async function uploadImages() {
|
||||
async function bilderHochladen() {
|
||||
// Alle Bilder hochladen
|
||||
const notification = addNotification({
|
||||
dismissable: false,
|
||||
message: "Bilder hochladen.",
|
||||
subtext: `${images.length} Bilder werden hochgeladen, bitte haben sie Geduld.`,
|
||||
timeout: 0,
|
||||
type: "info"
|
||||
})
|
||||
for (let i = 0; i < images.length; i++) {
|
||||
const image = images[i];
|
||||
if (image.uid) {
|
||||
@@ -35,14 +43,6 @@
|
||||
continue
|
||||
}
|
||||
|
||||
const notification = addNotification({
|
||||
dismissable: false,
|
||||
message: "Bilder hochladen.",
|
||||
subtext: `Bild ${i + 1}/${images.length} wird hochgeladen, bitte haben sie Geduld.`,
|
||||
timeout: 0,
|
||||
type: "info"
|
||||
})
|
||||
|
||||
try {
|
||||
const response = await client.v1.bilder.upload.mutate({
|
||||
base64: image.base64,
|
||||
@@ -55,7 +55,7 @@
|
||||
updateNotification(notification, {
|
||||
dismissable: true,
|
||||
message: "Bild hochgeladen.",
|
||||
subtext: `Bild ${i + 1}/${images.length} wurde erfolgreich hochgeladen.`,
|
||||
subtext: `${i + 1}/${images.length} Bildern wurden erfolgreich hochgeladen, bitte haben sie Geduld.`,
|
||||
timeout: 4000
|
||||
})
|
||||
} catch (e) {
|
||||
@@ -74,6 +74,8 @@
|
||||
// Um einen Ausweis zu speichern müssen wir eingeloggt sein, andernfalls wird die API den call ablehnen.
|
||||
// Wir prüfen also ob wir eingeloggt sind und leiten den Nutzer ggf. auf die Login Seite weiter.
|
||||
if (!await validateAccessTokenClient()) {
|
||||
// TOOD: Auf Dialog umstellen.
|
||||
//await spawnLoginPrompt();
|
||||
loginOverlayHidden = false;
|
||||
return
|
||||
}
|
||||
@@ -89,23 +91,14 @@
|
||||
gebaeude
|
||||
})
|
||||
|
||||
await uploadImages();
|
||||
await bilderHochladen();
|
||||
|
||||
return true;
|
||||
} 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"
|
||||
})
|
||||
return false
|
||||
// TODO: Ticket mit Fehldermeldung abschicken.
|
||||
}
|
||||
} else {
|
||||
// Wir speichern den Ausweis ab und leiten auf die "ausweis-gespeichert" Seite weiter.
|
||||
console.log(ausweis, gebaeude);
|
||||
|
||||
try {
|
||||
const response = await client.v1.verbrauchsausweisWohnen[2016].erstellen.mutate({
|
||||
ausweis,
|
||||
@@ -114,10 +107,23 @@
|
||||
ausweis.uid = response.uid;
|
||||
gebaeude.uid = response.gebaeude_uid;
|
||||
|
||||
await uploadImages();
|
||||
await bilderHochladen();
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
} catch (e: any) {
|
||||
await client.v1.tickets.erstellen.mutate({
|
||||
titel: "Ausweis konnte nicht gespeichert werden",
|
||||
beschreibung: e.stack,
|
||||
email: user.email ?? "",
|
||||
metadata: JSON.stringify({
|
||||
ausweis,
|
||||
gebaeude
|
||||
})
|
||||
})
|
||||
// TODO: Ticket mit Fehldermeldung abschicken.
|
||||
}
|
||||
}
|
||||
|
||||
addNotification({
|
||||
dismissable: false,
|
||||
message: "Ausweis konnte nicht gespeichert werden, bitte versuchen sie es erneut.",
|
||||
@@ -125,9 +131,7 @@
|
||||
timeout: 6000,
|
||||
type: "error"
|
||||
})
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
async function spaeterWeitermachen() {
|
||||
@@ -165,7 +169,7 @@
|
||||
|
||||
|
||||
async function ausweisAbschicken(e: SubmitEvent) {
|
||||
e.preventDefault()
|
||||
if (e && e.preventDefault) e.preventDefault();
|
||||
const result = await ausweisSpeichern();
|
||||
|
||||
if (result === true) {
|
||||
@@ -180,7 +184,7 @@
|
||||
|
||||
<Overlay bind:hidden={loginOverlayHidden}>
|
||||
<div class="bg-white w-full max-w-screen-sm py-8">
|
||||
<EmbeddedAuthFlowModule onLogin={spaeterWeitermachen}></EmbeddedAuthFlowModule>
|
||||
<EmbeddedAuthFlowModule onLogin={ausweisAbschicken}></EmbeddedAuthFlowModule>
|
||||
</div>
|
||||
</Overlay>
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { loginClient } from "#lib/login";
|
||||
import EmbeddedLoginModule from "./EmbeddedLoginModule.svelte"
|
||||
import EmbeddedRegisterModule from "./EmbeddedRegisterModule.svelte"
|
||||
|
||||
export let onLogin: () => void
|
||||
export let onLogin: (response: Awaited<ReturnType<typeof loginClient>>) => any;
|
||||
|
||||
let route: "login" | "signup" = "login"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
export let navigate: (target: string) => void;
|
||||
export let data: { email: string; passwort: string };
|
||||
|
||||
export let onLogin: (response: Awaited<ReturnType<typeof loginClient>>) => void;
|
||||
export let onLogin: (response: Awaited<ReturnType<typeof loginClient>>) => any;
|
||||
|
||||
async function login(e: SubmitEvent) {
|
||||
e.preventDefault()
|
||||
|
||||
@@ -44,10 +44,6 @@
|
||||
|
||||
async function createPayment(e: SubmitEvent) {
|
||||
e.preventDefault()
|
||||
if (form.checkValidity() === false) {
|
||||
form.reportValidity();
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await client.v1.rechnungen.erstellen.mutate({
|
||||
...rechnung,
|
||||
@@ -57,10 +53,8 @@
|
||||
services: services.filter(service => service.selected).map(service => service.id)
|
||||
})
|
||||
|
||||
//window.location.href = response.checkout_url
|
||||
window.location.href = response.checkout_url
|
||||
}
|
||||
|
||||
let form: HTMLFormElement;
|
||||
</script>
|
||||
|
||||
<div class="w-full px-8">
|
||||
@@ -74,7 +68,7 @@
|
||||
<div
|
||||
class="w-full"
|
||||
>
|
||||
<form class="flex flex-row gap-8" bind:this={form}>
|
||||
<form class="flex flex-row gap-8" on:submit={createPayment}>
|
||||
<div class="w-3/5">
|
||||
<div class="GRB3">
|
||||
<HelpLabel title="Ansprechpartner" />
|
||||
@@ -101,7 +95,7 @@
|
||||
<!-- Nachname -->
|
||||
<div>
|
||||
<Label>Nachname *</Label>
|
||||
<input name="nachname" type="text" bind:value={user.name} required />
|
||||
<input name="name" type="text" bind:value={user.name} required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
@@ -130,7 +124,7 @@
|
||||
<div>
|
||||
<Label>Empfänger *</Label>
|
||||
<input
|
||||
name="Rempfaenger"
|
||||
name="rechnung_empfaenger"
|
||||
type="text"
|
||||
bind:value={rechnung.empfaenger}
|
||||
required
|
||||
@@ -143,7 +137,8 @@
|
||||
<div>
|
||||
<Label>Zusatzzeile</Label>
|
||||
<input
|
||||
name="Rzusatzzeile"
|
||||
name="rechnung_zusatzzeile"
|
||||
bind:value={rechnung.zusatzzeile}
|
||||
type="text"
|
||||
data-rule-maxlength="80"
|
||||
data-msg-maxlength="max. 80 Zeichen"
|
||||
@@ -155,7 +150,7 @@
|
||||
<div>
|
||||
<Label>Straße, Hausnummer *</Label>
|
||||
<input
|
||||
name="Rstrasse"
|
||||
name="rechnung_strasse"
|
||||
bind:value={rechnung.strasse}
|
||||
type="text"
|
||||
required
|
||||
@@ -166,7 +161,7 @@
|
||||
|
||||
<!-- PLZ -->
|
||||
<ZipSearch
|
||||
name="versand_plz"
|
||||
name="rechnung_plz"
|
||||
bind:zip={rechnung.plz}
|
||||
bind:city={rechnung.ort}
|
||||
/>
|
||||
@@ -187,13 +182,13 @@
|
||||
<!-- Telefon -->
|
||||
<div>
|
||||
<Label>Telefon</Label>
|
||||
<input name="Rtelefon" bind:value={rechnung.telefon} type="text" />
|
||||
<input name="rechnung_telefon" bind:value={rechnung.telefon} type="text" />
|
||||
</div>
|
||||
|
||||
<!-- Email -->
|
||||
<div>
|
||||
<Label>E-Mail</Label>
|
||||
<input name="Remail" bind:value={rechnung.email} type="email" />
|
||||
<input name="rechnung_email" bind:value={rechnung.email} type="email" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -207,7 +202,7 @@
|
||||
<input
|
||||
class="w-[15px] h-[15px]"
|
||||
type="checkbox"
|
||||
id="deliveryAddress"
|
||||
name="abweichende_versand_adresse"
|
||||
bind:checked={rechnung.abweichende_versand_adresse}
|
||||
/>
|
||||
<Label>Abweichende Versandadresse</Label>
|
||||
@@ -217,7 +212,7 @@
|
||||
<div>
|
||||
<Label>Empfänger *</Label>
|
||||
<input
|
||||
name="Vempfaenger"
|
||||
name="versand_empfaenger"
|
||||
type="text"
|
||||
readonly={!rechnung.abweichende_versand_adresse}
|
||||
bind:value={rechnung.versand_empfaenger}
|
||||
@@ -231,7 +226,7 @@
|
||||
<div>
|
||||
<Label>Zusatzzeile</Label>
|
||||
<input
|
||||
name="Vzusatzzeile"
|
||||
name="versand_zusatzzeile"
|
||||
type="text"
|
||||
readonly={!rechnung.abweichende_versand_adresse}
|
||||
bind:value={rechnung.versand_zusatzzeile}
|
||||
@@ -245,10 +240,10 @@
|
||||
<div>
|
||||
<Label>Straße, Hausnummer *</Label>
|
||||
<input
|
||||
name="Vstrasse"
|
||||
name="versand_strasse"
|
||||
type="text"
|
||||
readonly={!rechnung.abweichende_versand_adresse}
|
||||
bind:value={rechnung.strasse}
|
||||
bind:value={rechnung.versand_strasse}
|
||||
required
|
||||
data-rule-maxlength="40"
|
||||
data-msg-maxlength="max. 40 Zeichen"
|
||||
@@ -257,7 +252,7 @@
|
||||
|
||||
<!-- PLZ -->
|
||||
<ZipSearch
|
||||
name="rplz"
|
||||
name="versand_plz"
|
||||
readonly={!rechnung.abweichende_versand_adresse}
|
||||
bind:zip={rechnung.versand_plz}
|
||||
bind:city={rechnung.versand_ort}
|
||||
@@ -267,7 +262,7 @@
|
||||
<div>
|
||||
<Label>Ort *</Label>
|
||||
<input
|
||||
name="Vort"
|
||||
name="versand_ort"
|
||||
type="text"
|
||||
readonly
|
||||
required
|
||||
@@ -283,24 +278,24 @@
|
||||
<HelpLabel title="Bezahlmethode" />
|
||||
<hr />
|
||||
<div class="flex flex-row justify-between gap-4">
|
||||
<PaymentOption paymentType={Enums.Bezahlmethoden.PAYPAL} bind:selectedPaymentType name={"PayPal"} icon={"/images/paypal.png"}></PaymentOption>
|
||||
<PaymentOption paymentType={Enums.Bezahlmethoden.SOFORT} bind:selectedPaymentType name={"Sofort"} icon={"/images/sofort.png"}></PaymentOption>
|
||||
<PaymentOption paymentType={Enums.Bezahlmethoden.GIROPAY} bind:selectedPaymentType name={"Giropay"} icon={"/images/giropay.png"}></PaymentOption>
|
||||
<PaymentOption paymentType={Enums.Bezahlmethoden.KREDITKARTE} bind:selectedPaymentType name={"Kreditkarte"} icon={"/images/mastercard.png"}></PaymentOption>
|
||||
<PaymentOption paymentType={Enums.Bezahlmethoden.RECHNUNG} bind:selectedPaymentType name={"Rechnung"} icon={"/images/rechnung.png"}></PaymentOption>
|
||||
<PaymentOption paymentType={Enums.Bezahlmethoden.paypal} bind:selectedPaymentType name={"PayPal"} icon={"/images/paypal.png"}></PaymentOption>
|
||||
<PaymentOption paymentType={Enums.Bezahlmethoden.sofort} bind:selectedPaymentType name={"Sofort"} icon={"/images/sofort.png"}></PaymentOption>
|
||||
<PaymentOption paymentType={Enums.Bezahlmethoden.giropay} bind:selectedPaymentType name={"Giropay"} icon={"/images/giropay.png"}></PaymentOption>
|
||||
<PaymentOption paymentType={Enums.Bezahlmethoden.creditcard} bind:selectedPaymentType name={"Kreditkarte"} icon={"/images/mastercard.png"}></PaymentOption>
|
||||
<PaymentOption paymentType={Enums.Bezahlmethoden.rechnung} bind:selectedPaymentType name={"Rechnung"} icon={"/images/rechnung.png"}></PaymentOption>
|
||||
</div>
|
||||
<div class="w-1/2">
|
||||
<div class="flex-row justify-between">
|
||||
<h5>{selectedPaymentType}</h5>
|
||||
<img
|
||||
src="../../images/{selectedPaymentType ==
|
||||
Enums.Bezahlmethoden.KREDITKARTE
|
||||
Enums.Bezahlmethoden.creditcard
|
||||
? 'mastercard'
|
||||
: selectedPaymentType}.png"
|
||||
class="payment-option-logo"
|
||||
/>
|
||||
</div>
|
||||
{#if selectedPaymentType == Enums.Bezahlmethoden.RECHNUNG}
|
||||
{#if selectedPaymentType == Enums.Bezahlmethoden.rechnung}
|
||||
<p>
|
||||
Sobald sie AGB und Datenschutzerklärung
|
||||
gelesen und akzeptiert haben können sie den
|
||||
@@ -322,8 +317,8 @@
|
||||
{/if}
|
||||
<div class="column">
|
||||
<div class="flex-row center">
|
||||
<input type="checkbox" bind:checked={agbAkzeptiert} />
|
||||
<label for="accept-agb"
|
||||
<input type="checkbox" name="agb-akzeptieren" bind:checked={agbAkzeptiert} />
|
||||
<label for="agb-akzeptieren"
|
||||
>Ich erkläre mich mit den <a
|
||||
href="https://online-energieausweis.org/agb"
|
||||
>AGB</a
|
||||
@@ -333,9 +328,10 @@
|
||||
<div class="flex-row center">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="datenschutz-akzeptieren"
|
||||
bind:checked={datenschutzAkzeptiert}
|
||||
/>
|
||||
<label for="accept-datenschutz"
|
||||
<label for="datenschutz-akzeptieren"
|
||||
>Ich erkläre mich mit der <a
|
||||
href="https://online-energieausweis.org/impressum"
|
||||
>Datenschutzerklärung</a
|
||||
@@ -349,7 +345,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="pay-button" disabled={!agbAkzeptiert || !datenschutzAkzeptiert}
|
||||
on:click={createPayment}
|
||||
>Kostenpflichtig Bestellen</button
|
||||
>
|
||||
</div>
|
||||
|
||||
@@ -8,21 +8,22 @@
|
||||
export let redirect: string | null = null;
|
||||
|
||||
async function login(e: SubmitEvent) {
|
||||
e.preventDefault()
|
||||
const response = await loginClient(email, passwort)
|
||||
e.preventDefault();
|
||||
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?",
|
||||
subtext:
|
||||
"Das hat leider nicht geklappt, haben sie ihr Passwort und ihre Email Adresse richtig eingegeben?",
|
||||
type: "error",
|
||||
timeout: 6000,
|
||||
dismissable: true
|
||||
})
|
||||
dismissable: true,
|
||||
});
|
||||
} else {
|
||||
if (redirect) {
|
||||
window.location.href = redirect
|
||||
return
|
||||
window.location.href = redirect;
|
||||
return;
|
||||
}
|
||||
|
||||
window.location.href = "/user";
|
||||
@@ -55,10 +56,12 @@
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<button type="submit" >Einloggen</button>
|
||||
<button type="submit">Einloggen</button>
|
||||
<div class="flex-row justify-between" style="margin-top: 10px">
|
||||
<a href="/auth/signup?redirect={redirect}">Registrieren</a>
|
||||
<a href="/user/passwort_vergessen?redirect={redirect}">Passwort Vergessen?</a>
|
||||
<a href="/user/passwort_vergessen?redirect={redirect}"
|
||||
>Passwort Vergessen?</a
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -4,8 +4,9 @@ import AusweisLayout from "#layouts/AusweisLayout.astro";
|
||||
import VerbrauchsausweisWohnenModule from "#modules/Ausweise/VerbrauchsausweisWohnenModule.svelte";
|
||||
import { prisma } from "@ibcornelsen/database/server";
|
||||
import { exclude } from "#lib/exclude";
|
||||
import { UploadedGebaeudeBild, VerbrauchsausweisWohnenClient, GebaeudeClient } from "#components/Ausweis/types";
|
||||
import { UploadedGebaeudeBild, VerbrauchsausweisWohnenClient, GebaeudeClient, BenutzerClient } from "#components/Ausweis/types";
|
||||
import { createCaller } from "#lib/caller";
|
||||
import { API_UID_COOKIE_NAME } from "#lib/constants";
|
||||
|
||||
const uid = Astro.url.searchParams.get("uid");
|
||||
let ausweis: VerbrauchsausweisWohnenClient = {} as VerbrauchsausweisWohnenClient;
|
||||
@@ -44,6 +45,14 @@ if (uid) {
|
||||
}
|
||||
}
|
||||
|
||||
const benutzerUid = Astro.cookies.get(API_UID_COOKIE_NAME).value
|
||||
let user: BenutzerClient = {} as BenutzerClient;
|
||||
if (benutzerUid) {
|
||||
user = await createCaller(Astro).v1.benutzer.fromPublicId({
|
||||
uid: benutzerUid
|
||||
})
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
<AusweisLayout title="Verbrauchsausweis erstellen">
|
||||
|
||||
20
svelte-dialogs.config.ts
Normal file
20
svelte-dialogs.config.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { dialogs } from "svelte-dialogs";
|
||||
|
||||
dialogs.config({
|
||||
global: {
|
||||
inputClass: "px-2.5 py-1.5 rounded-lg border bg-white",
|
||||
inputLabelClass: "text-gray-500 bg-white ml-2 w-fit",
|
||||
bodyClass: "bg-white flex flex-col gap-4",
|
||||
dialogClass: "bg-white rounded-md px-8 py-8",
|
||||
cancelButtonClass: "button",
|
||||
footerClass: "flex justify-end bg-white mt-4 gap-4",
|
||||
resetButton: false,
|
||||
submitButtonClass: "button",
|
||||
titleClass: "text-2xl font-bold mb-4",
|
||||
dividerClass: "border-b border-gray-200",
|
||||
closeOnBg: true,
|
||||
closeOnEsc: true
|
||||
}
|
||||
});
|
||||
|
||||
export { dialogs }
|
||||
@@ -25,6 +25,8 @@
|
||||
"#components/*": ["./src/components/*"],
|
||||
"#layouts/*": ["./src/layouts/*"],
|
||||
"#modules/*": ["./src/modules/*"],
|
||||
"#client/*": ["./src/modules/*"],
|
||||
"#server/*": ["./src/modules/*"],
|
||||
},
|
||||
"types": ["cypress", "cypress-file-upload", "bun-types"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user