Verbesserungen

1. Info Box direkt beim Login anzeigen anstatt kleine Box unten in der Ecke

2. Pflichtfelder bei Schritt 2 noch nicht in rot markiert
This commit is contained in:
Moritz Utcke
2025-10-17 13:13:43 -04:00
parent 38386ed830
commit 946a991176
15 changed files with 92 additions and 63 deletions

View File

@@ -44,8 +44,6 @@
// Wir holen uns die Daten aus dem Formular // Wir holen uns die Daten aus dem Formular
const data = new FormData(form); const data = new FormData(form);
// Und gleichen diese mit allen Feldern ab die "required" sind, damit stellen wir sicher, dass alles richtig ausgefüllt wurde. // Und gleichen diese mit allen Feldern ab die "required" sind, damit stellen wir sicher, dass alles richtig ausgefüllt wurde.
console.log(form.querySelectorAll("select[name][required], input[name][required]"));
(form.querySelectorAll("select[name][required], input[name][required]") as NodeListOf<HTMLInputElement | HTMLSelectElement>).forEach((element) => { (form.querySelectorAll("select[name][required], input[name][required]") as NodeListOf<HTMLInputElement | HTMLSelectElement>).forEach((element) => {
const value = data.get(element.getAttribute("name") as string) const value = data.get(element.getAttribute("name") as string)

View File

@@ -58,7 +58,6 @@
{...$$restProps} {...$$restProps}
bind:value={zip} bind:value={zip}
on:input={fetchZipCodeInformation} on:input={fetchZipCodeInformation}
on:change={onchange}
on:focus={() => { on:focus={() => {
if (zipCodes.length > 0) { if (zipCodes.length > 0) {
hideZipDropdown = false hideZipDropdown = false

View File

@@ -12,7 +12,7 @@ export async function sendAutoRegisterMail(
to: user.email, to: user.email,
subject: `Ihre Registrierung bei IBCornelsen`, subject: `Ihre Registrierung bei IBCornelsen`,
bcc: "info@online-energieausweis.org", bcc: "info@online-energieausweis.org",
html: `<p>Sehr geehrte*r ${user.vorname} ${user.name},</p> html: `<p>Sehr geehrte/r Kund/in,</p>
<p>vielen Dank für Ihre Registrierung bei IBCornelsen. Ihr Benutzerkonto wurde erfolgreich erstellt.<br><br> <p>vielen Dank für Ihre Registrierung bei IBCornelsen. Ihr Benutzerkonto wurde erfolgreich erstellt.<br><br>
Nachfolgend finden Sie Ihre Zugangsdaten:<br><br> Nachfolgend finden Sie Ihre Zugangsdaten:<br><br>

View File

@@ -75,6 +75,6 @@ export async function sendInvoiceMail(
name: rechnung.empfaenger || "", name: rechnung.empfaenger || "",
}, },
bcc: "info@online-energieausweis.org", bcc: "info@online-energieausweis.org",
html: `<p>Sehr geehrte*r ${user.vorname} ${user.name},</p>` + getPaymentInvoiceBody(ausweis, rechnung, ausweisart), html: `<p>Sehr geehrte/r ${user.vorname} ${user.name},</p>` + getPaymentInvoiceBody(ausweis, rechnung, ausweisart),
}); });
} }

View File

@@ -80,6 +80,6 @@ export async function sendPaymentSuccessMail(
name: rechnung.empfaenger || "", name: rechnung.empfaenger || "",
}, },
bcc: "info@online-energieausweis.org", bcc: "info@online-energieausweis.org",
html: `<p>Sehr geehrte*r ${user.vorname} ${user.name},</p>` + getPaymentSuccessBody(ausweis, rechnung, ausweisart), html: `<p>Sehr geehrte/r ${user.vorname} ${user.name},</p>` + getPaymentSuccessBody(ausweis, rechnung, ausweisart),
}); });
} }

View File

@@ -12,7 +12,7 @@ export async function sendRegisterMail(
to: user.email, to: user.email,
subject: `Ihre Registrierung bei IBCornelsen`, subject: `Ihre Registrierung bei IBCornelsen`,
bcc: "info@online-energieausweis.org", bcc: "info@online-energieausweis.org",
html: `<p>Sehr geehrte*r ${user.vorname} ${user.name},</p> html: `<p>Sehr geehrte/r ${user.vorname} ${user.name},</p>
<p>vielen Dank für Ihre Registrierung bei IBCornelsen. Ihr Benutzerkonto wurde erfolgreich erstellt.<br><br> <p>vielen Dank für Ihre Registrierung bei IBCornelsen. Ihr Benutzerkonto wurde erfolgreich erstellt.<br><br>
Nachfolgend finden Sie Ihre Zugangsdaten:<br><br> Nachfolgend finden Sie Ihre Zugangsdaten:<br><br>

View File

@@ -7,7 +7,7 @@ export async function sendAusweisGespeichertMail(user: Benutzer, ausweis_id: str
from: `"IBCornelsen" <info@online-energieausweis.org>`, from: `"IBCornelsen" <info@online-energieausweis.org>`,
to: user.email, to: user.email,
subject: `Ihr Ausweis wurde gespeichert - IBCornelsen - (ID: ${ausweis_id})`, subject: `Ihr Ausweis wurde gespeichert - IBCornelsen - (ID: ${ausweis_id})`,
html: `<p>Sehr geehrte*r ${user.vorname} ${user.name},</p> html: `<p>Sehr geehrte/r ${user.vorname} ${user.name},</p>
<p>Ihr Energieausweis wurde erfolgreich in Ihrem Konto gespeichert. Sie können ihn jederzeit in Ihrem Kundenbereich abrufen.<br><br> <p>Ihr Energieausweis wurde erfolgreich in Ihrem Konto gespeichert. Sie können ihn jederzeit in Ihrem Kundenbereich abrufen.<br><br>
Ihre Vorgänge und Ausweise können Sie in Ihrem Kundenkonto einsehen und bearbeiten:<br><br> Ihre Vorgänge und Ausweise können Sie in Ihrem Kundenkonto einsehen und bearbeiten:<br><br>

View File

@@ -1,5 +1,4 @@
<script lang="ts"> <script lang="ts">
import { addNotification } from "@ibcornelsen/ui";
import { loginClient } from "#lib/login.js"; import { loginClient } from "#lib/login.js";
export let navigate: (target: string) => void; export let navigate: (target: string) => void;
@@ -15,17 +14,15 @@
const response = await loginClient(email, password) const response = await loginClient(email, password)
if (response === null) { if (response === null) {
addNotification({ error = true;
message: "Ups...", errorMessage = "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
})
} else { } else {
onLogin(response); onLogin(response);
} }
} }
let error = false;
let errorMessage = "";
</script> </script>
<form class="max-w-md mx-auto" on:submit={login} name="login"> <form class="max-w-md mx-auto" on:submit={login} name="login">
@@ -39,6 +36,7 @@
placeholder="Email" placeholder="Email"
name="email" name="email"
bind:value={email} bind:value={email}
on:focus={() => (error = false)}
required required
/> />
</div> </div>
@@ -50,9 +48,15 @@
placeholder="********" placeholder="********"
name="passwort" name="passwort"
bind:value={password} bind:value={password}
on:focus={() => (error = false)}
required required
/> />
</div> </div>
{#if error}
<div class="bg-red-200 p-4 rounded-lg w-full">
<p class="text-red-800">{errorMessage}</p>
</div>
{/if}
<button class="button" type="submit">{buttonText}</button> <button class="button" type="submit">{buttonText}</button>
<div class="flex flex-row justify-between" style="margin-top: 10px"> <div class="flex flex-row justify-between" style="margin-top: 10px">
<a on:click={() => navigate("signup")} class="cursor-pointer" data-cy="registrieren">Registrieren</a> <a on:click={() => navigate("signup")} class="cursor-pointer" data-cy="registrieren">Registrieren</a>

View File

@@ -1,6 +1,5 @@
<script lang="ts"> <script lang="ts">
import { loginClient } from "#lib/login.js"; import { loginClient } from "#lib/login.js";
import { addNotification } from "@ibcornelsen/ui";
import { api } from "astro-typesafe-api/client"; import { api } from "astro-typesafe-api/client";
export let navigate: (target: string) => void; export let navigate: (target: string) => void;
@@ -14,12 +13,8 @@
e.preventDefault() e.preventDefault()
if (email !== repeatEmail) { if (email !== repeatEmail) {
addNotification({ error = true;
message: "Die eingegebenen Email Adressen stimmen nicht überein.", errorMessage = "Die eingegebenen Email Adressen stimmen nicht überein.";
dismissable: true,
timeout: 3000,
type: "error"
})
return; return;
} }
@@ -31,17 +26,14 @@
const response = await loginClient(email, passwort) const response = await loginClient(email, passwort)
onRegister(response); onRegister(response);
} catch (e) { } catch (e) {
addNotification({ error = true;
message: "Ups...", errorMessage = "Sie besitzen bereits ein Konto bei IBC. Bitte loggen Sie sich mit Ihrem Passwort ein oder vergeben sich über “Passwort vergessen” ein neues."
subtext:
`Sie besitzen bereits ein Konto bei IBC. Bitte loggen Sie sich mit Ihrem Passwort ein oder vergeben sich über “Passwort vergessen” ein neues.`,
type: "error",
timeout: 0,
dismissable: true,
});
navigate("login"); navigate("login");
} }
} }
let error: boolean = false;
let errorMessage: string = "";
</script> </script>
<form class="max-w-md mx-auto" name="signup" on:submit={signup}> <form class="max-w-md mx-auto" name="signup" on:submit={signup}>
@@ -73,6 +65,11 @@
required required
/> />
</div> </div>
{#if error}
<div class="bg-red-200 p-4 rounded-lg w-full">
<p class="text-red-800">{errorMessage}</p>
</div>
{/if}
<button class="button" type="submit">{buttonText}</button> <button class="button" type="submit">{buttonText}</button>
<div class="flex flex-row justify-between" style="margin-top: 10px"> <div class="flex flex-row justify-between" style="margin-top: 10px">
<button on:click={() => navigate("login")}>Einloggen</button> <button on:click={() => navigate("login")}>Einloggen</button>

View File

@@ -170,6 +170,7 @@
async function anfordern() { async function anfordern() {
if (!form.checkValidity()) { if (!form.checkValidity()) {
displayFormValidity()
addNotification({ addNotification({
dismissable: true, dismissable: true,
message: "Fehlende Daten.", message: "Fehlende Daten.",
@@ -344,8 +345,30 @@
} }
} }
function displayFormValidity() {
(form.querySelectorAll("select[name][required], input[name][required]") as NodeListOf<HTMLInputElement | HTMLSelectElement>).forEach((element) => {
if (element.willValidate && !element.checkValidity()) {
element.dataset["isinvalid"] = "true"
const onChange = () => {
console.log(element, element.value, element.checkValidity());
if (!element.checkValidity()) {
return;
}
element.dataset["isinvalid"] = "false"
element.removeEventListener("change", onChange)
}
element.addEventListener("change", onChange)
}
})
}
async function bestellen(authuser = null) { async function bestellen(authuser = null) {
if (!form.checkValidity()) { if (!form.checkValidity()) {
displayFormValidity()
addNotification({ addNotification({
dismissable: true, dismissable: true,
message: "Fehlende Daten.", message: "Fehlende Daten.",
@@ -503,6 +526,14 @@
let loginOverlayHidden = true; let loginOverlayHidden = true;
let loginAction = () => {}; let loginAction = () => {};
let form: HTMLFormElement; let form: HTMLFormElement;
let ortInput: HTMLInputElement;
$: {
if (ort && ortInput) {
ortInput.value = ort
ortInput.dispatchEvent(new Event("change"))
}
}
</script> </script>
{#if !nurRechnungsadresseUpdate} {#if !nurRechnungsadresseUpdate}
@@ -661,6 +692,9 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
name="rechnung_plz" name="rechnung_plz"
bind:zip={plz} bind:zip={plz}
bind:city={ort} bind:city={ort}
onchange={(e) => {
ortInput.dispatchEvent(new Event('change'));
}}
/> />
</div> </div>
@@ -672,6 +706,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
type="text" type="text"
required required
bind:value={ort} bind:value={ort}
bind:this={ortInput}
/> />
<div class="help-label"> <div class="help-label">

View File

@@ -1,8 +1,6 @@
<script lang="ts"> <script lang="ts">
import { loginClient } from "#lib/login.js"; import { loginClient } from "#lib/login.js";
import CrossCircled from "radix-svelte-icons/src/lib/icons/CrossCircled.svelte";
import { fade } from "svelte/transition";
let email: string; let email: string;
let passwort: string; let passwort: string;
@@ -13,7 +11,8 @@
const response = await loginClient(email, passwort); const response = await loginClient(email, passwort);
if (response === null) { if (response === null) {
errorHidden = false; error = true
errorMessage = "Das hat leider nicht geklappt, haben sie ihr Passwort und ihre Email Adresse richtig eingegeben?"
} else { } else {
if (redirect) { if (redirect) {
window.location.href = redirect; window.location.href = redirect;
@@ -24,7 +23,8 @@
} }
} }
let errorHidden = true; let error = false;
let errorMessage = "";
</script> </script>
<div class="mx-auto w-1/3 bg-base-200 p-8 border border-base-300 rounded-lg"> <div class="mx-auto w-1/3 bg-base-200 p-8 border border-base-300 rounded-lg">
@@ -38,7 +38,7 @@
placeholder="nutzer@email.com" placeholder="nutzer@email.com"
name="email" name="email"
bind:value={email} bind:value={email}
on:focus={() => (errorHidden = true)} on:focus={() => (error = false)}
required required
/> />
</div> </div>
@@ -51,15 +51,14 @@
placeholder="********" placeholder="********"
name="passwort" name="passwort"
bind:value={passwort} bind:value={passwort}
on:focus={() => (errorHidden = true)} on:focus={() => (error = false)}
required required
/> />
</div> </div>
{#if !errorHidden} {#if error}
<div role="alert" class="alert alert-error" in:fade out:fade={{delay: 400}}> <div class="bg-red-200 p-4 rounded-lg w-full">
<CrossCircled size={24} /> <p class="text-red-800">{errorMessage}</p>
<span class="font-semibold">Das hat leider nicht geklappt, haben sie ihr Passwort und ihre Email Adresse richtig eingegeben?</span> </div>
</div>
{/if} {/if}
<button class="button" type="submit">Einloggen</button> <button class="button" type="submit">Einloggen</button>
<div class="flex flex-row justify-between" style="margin-top: 10px"> <div class="flex flex-row justify-between" style="margin-top: 10px">

View File

@@ -1,5 +1,4 @@
<script lang="ts"> <script lang="ts">
import { addNotification } from "#components/Notifications/shared.js";
import { api } from "astro-typesafe-api/client"; import { api } from "astro-typesafe-api/client";
import NotificationWrapper from "#components/Notifications/NotificationWrapper.svelte"; import NotificationWrapper from "#components/Notifications/NotificationWrapper.svelte";
import { loginClient } from "#lib/login.js"; import { loginClient } from "#lib/login.js";
@@ -19,12 +18,8 @@
e.preventDefault() e.preventDefault()
if (email !== repeatEmail) { if (email !== repeatEmail) {
addNotification({ error = true;
message: "Die eingegebenen Email Adressen stimmen nicht überein.", errorMessage = "Die eingegebenen Email Adressen stimmen nicht überein.";
dismissable: true,
timeout: 3000,
type: "error"
})
return; return;
} }
@@ -44,16 +39,13 @@
window.location.href = "/dashboard"; window.location.href = "/dashboard";
} catch (e) { } catch (e) {
addNotification({ error = true
message: "Ups...", errorMessage = "Sie besitzen bereits ein Konto bei IBC. Bitte loggen Sie sich mit Ihrem Passwort ein oder vergeben sich über “Passwort vergessen” ein neues."
subtext:
"Da ist wohl etwas schiefgelaufen. Diese Email Adresse ist bereits in Benutzung, haben sie vielleicht bereits ein Konto bei uns?",
type: "error",
timeout: 0,
dismissable: true,
});
} }
} }
let error = false;
let errorMessage = "";
</script> </script>
<div class="mx-auto w-1/3 bg-base-200 p-8 border border-base-300 rounded-lg"> <div class="mx-auto w-1/3 bg-base-200 p-8 border border-base-300 rounded-lg">
@@ -137,6 +129,11 @@
required required
/> />
</div> </div>
{#if error}
<div class="bg-red-200 p-4 rounded-lg w-full">
<p class="text-red-800">{errorMessage}</p>
</div>
{/if}
<button type="submit" class="button" <button type="submit" class="button"
>Registrieren</button> >Registrieren</button>
<div class="flex flex-row justify-between" style="margin-top: 10px"> <div class="flex flex-row justify-between" style="margin-top: 10px">

View File

@@ -294,7 +294,7 @@ export const GET = defineApiRoute({
if (rechnung.status === Enums.Rechnungsstatus.paid) { if (rechnung.status === Enums.Rechnungsstatus.paid) {
html = ` html = `
<p>Sehr geehrte*r ${rechnung.empfaenger},</p> <p>Sehr geehrte/r ${rechnung.empfaenger},</p>
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${ <p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${
post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : "" post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : ""
@@ -323,7 +323,7 @@ export const GET = defineApiRoute({
</p>`; </p>`;
} else { } else {
html = ` html = `
<p>Sehr geehrte*r ${rechnung.empfaenger},</p> <p>Sehr geehrte/r ${rechnung.empfaenger},</p>
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${ <p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${
post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : "" post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : ""

View File

@@ -303,7 +303,7 @@ export const POST = defineApiRoute({
if (rechnung.status === Enums.Rechnungsstatus.paid) { if (rechnung.status === Enums.Rechnungsstatus.paid) {
html = ` html = `
<p>Sehr geehrte*r ${rechnung.empfaenger},</p> <p>Sehr geehrte/r ${rechnung.empfaenger},</p>
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${ <p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${
post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : "" post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : ""
@@ -332,7 +332,7 @@ export const POST = defineApiRoute({
</p>`; </p>`;
} else { } else {
html = ` html = `
<p>Sehr geehrte*r ${rechnung.empfaenger},</p> <p>Sehr geehrte/r ${rechnung.empfaenger},</p>
<p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${ <p>im Anhang finden Sie Ihren geprüften Energieusweis inkl. Rechnung als PDF-Datei. ${
post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : "" post ? "Zusätzlich haben wir Ihren Ausweis per Post verschickt" : ""

View File

@@ -120,7 +120,7 @@ export const PUT = defineApiRoute({
to: rechnung.email || user.email, to: rechnung.email || user.email,
bcc: "info@online-energieausweis.org", bcc: "info@online-energieausweis.org",
subject: `Stornierung des Energieausweises vom Ingenieurbüro Cornelsen (ID: ${ausweis.id})`, subject: `Stornierung des Energieausweises vom Ingenieurbüro Cornelsen (ID: ${ausweis.id})`,
html: `<p>Sehr geehrte*r ${user.vorname} ${user.name},</p> html: `<p>Sehr geehrte/r ${user.vorname} ${user.name},</p>
<p>Ihr Energieausweis wurde soeben storniert. <p>Ihr Energieausweis wurde soeben storniert.
<br> <br>