Kaufabschluss Update

This commit is contained in:
Moritz Utcke
2024-02-17 16:34:12 +07:00
committed by Jens Cornelsen
parent 06b423a22e
commit cb7d78c867
9 changed files with 692 additions and 572 deletions

View File

@@ -244,7 +244,10 @@ describe("Verbrauchsausweis erstellen Schritt 1", () => {
// Der Ausweis sollte jetzt schon erstellt worden sein und wir sollten auf die kundendaten seite weitergeleitet worden sein.
cy.url().should("contain", "/kundendaten");
cy.wait(1000)
// Wir füllen jetzt die Kundendaten aus.
cy.get("select[name='anrede']").select(Math.random() > 0.5 ? "Herr" : "Frau");
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);

View File

@@ -4,8 +4,8 @@
<div class="flex flex-col relative">
<div class="progress-section">
<div class="w-[85%] left-9 bg-gray-100 absolute h-3 rounded-lg">
<div class="bg-green-600 left-2 h-3 absolute" style={`width: ${progress}%;`}></div>
<div class="w-full bg-gray-100 absolute h-3 rounded-lg">
<div class="bg-green-600 left-0 h-3 absolute" style={`width: ${progress}%;`}></div>
</div>
<span>1</span>
<span>2</span>
@@ -14,14 +14,14 @@
<div class="flex flex-row justify-between">
<p>Gebäudedaten</p>
<p>Kundendaten</p>
<p>Prüfung</p>
<p>Kaufabschluss</p>
</div>
</div>
<style>
.progress-section {
@apply relative items-center flex flex-row justify-between px-8;
@apply relative items-center flex flex-row justify-between px-0;
}
.progress-section span {

View File

@@ -0,0 +1,36 @@
<script lang="ts">
import { get_current_component } from "svelte/internal";
const component = get_current_component();
export let image: string;
export let name: string;
export let description: string;
export let price: number;
export let quantity: number;
export let removable: boolean = true;
export let maxQuantity: number = Infinity;
</script>
<div class="flex flex-row justify-between items-center">
<div class="flex flex-row gap-4">
<img src={image} class="w-24" alt="">
<div class="flex flex-col">
<h4 class="font-semibold">{name}</h4>
<span class="opacity-75">{description}</span>
<span class="font-semibold text-sm">{price * quantity}</span>
</div>
</div>
<div class="join">
<button class="btn btn-sm join-item" disabled={!removable && quantity == 1} on:click={() => {
quantity--
if ((quantity == 0) && removable) {
component.$destroy();
}
}}>-</button>
<button class="btn btn-sm join-item btn-ghost">{quantity}</button>
<button class="btn btn-sm join-item" disabled={quantity <= maxQuantity} on:click={() => quantity++}>+</button>
</div>
</div>

View File

@@ -1,204 +0,0 @@
<script lang="ts">
import { PRICES } from "#lib/constants";
import type { BedarfsausweisWohnen, Enums, VerbrauchsausweisGewerbe, VerbrauchsausweisWohnen } from "@ibcornelsen/database/client";
export let ausweis: VerbrauchsausweisWohnen | VerbrauchsausweisGewerbe | BedarfsausweisWohnen;
const prices = PRICES[ausweis.ausweisart];
export let services: { name: string, price: number, selected: boolean, id: Enums.Service }[] = [];
let basePrice: number = prices[0];
$: price =
basePrice + services.reduce((acc, service) => (service.selected && acc + service.price) || acc, 0)
</script>
<div>
<div class="yellow-box flex flex-col gap-4">
<div class="flex flex-col gap-2 test-box">
<strong>A - Prüfung der Ausweisart</strong>
<div>
<span>Vermietung, Verkauf oder sonstiges</span>
<span>Baujahr Heizung nicht kleiner als Baujahr Gebäude</span><span
>Baujahr nach 1977 oder saniert oder mehr als 4 Wohneinheiten</span
><span>Heizung min. 3 Jahre alt</span><span
>Verbrauchsausweis zulässig</span
>
</div>
</div>
<div class="flex flex-col gap-2 test-box">
<strong>B - Prüfung der Adresse, Wohnfläche, Keller und Dach</strong
>
<div>
<span>PLZ gültig</span><span>Klimafaktorern</span><span
>Wohnfläche passt zu Wohneinheiten</span
>
</div>
</div>
<div class="flex flex-col gap-2 test-box">
<strong>C - Prüfung der Verbrauchsangaben</strong>
<div>
<span>Verbrauchsmenge schlüssig</span><span
>Verbrauchsabweichung im Rahmen</span
><span>Endenergieverbrauch schlüssig</span>
</div>
</div>
<div class="flex flex-col gap-2 test-box">
<strong
>D - Prüfung Warmwasser und alternative Energieversorgung</strong
>
<div>
<span>Warmwasseranteil schlüssig</span>
</div>
</div>
<div class="flex flex-col gap-2 test-box">
<strong
>E - Prüfung von Gebäudetyp, Lüftung, Kühlung und Leerstand</strong
>
<div>
<span>Leerstand nicht größer als 30%</span>
</div>
</div>
<div class="flex flex-col gap-2 test-box">
<strong
>F - Prüfung des Sanierungsstandes und der Gebäudebilder</strong
>
<div>
<span>Mindestens ein Bild pro Abschnitt vorhanden</span><span
>Angaben zum Sanierungsstand vorhanden</span
><span
>Bei Baujahr vor 1978 Dach oder Geschossdecke min. 12 cm gedämmt</span
>
</div>
</div>
</div>
<hr />
<div class="yellow-box flex flex-col gap-4">
<table>
<tr>
<td><strong>Produkt:</strong></td>
<td
><div class="bg-white p-2 border border-gray-300">
Verbrauchsausweis
</div></td
>
</tr>
<tr>
<td><strong>Beschreibung:</strong></td>
<td>
<div class="bg-white p-2 border border-gray-300">
Registrierung beim DiBt<br />
Prüfung durch Diplom Ingenieur<br />
Energieausweis Vorschau als PDF<br />
</div>
</td>
</tr>
<tr>
<td>Netto-Preis</td>
<td
><div class="bg-white p-2 border border-gray-300">
{(price * 0.81).toFixed(2) + "€"}
</div></td
>
</tr>
<tr>
<td>19% gesetzl. MwSt.</td>
<td
><div class="bg-white p-2 border border-gray-300">
{(price * 0.19).toFixed(2) + "€"}
</div></td
>
</tr>
<tr>
<td>Preis inkl. MwSt.</td>
<td
><div class="bg-white p-2 border border-gray-300">
<strong>{price + "€"}</strong>
</div>
</td>
</tr>
</table>
</div>
<hr />
<div class="yellow-box flex flex-col gap-4">
<strong
>Hiermit bestelle ich folgende Version des Energieausweises:<br
/></strong
>
<table>
<tr>
<td
>Verbrauchsausweis online für {prices[0]} € inkl. MwSt. als PDF
per E-Mail</td
>
<td
><input
type="radio"
bind:group={basePrice}
value={prices[0]}
name="Preis"
checked
/>
</td>
</tr>
<tr>
<td
>Verbrauchsausweis online inkl. Beratung für {prices[1]}
€ inkl. MwSt. als PDF per E-Mail</td
>
<td
><input
type="radio"
bind:group={basePrice}
value={prices[1]}
name="Preis"
/>
</td>
</tr><tr>
<td
>Verbrauchsausweis offline für {prices[2]} € inkl. MwSt. als
PDF per E-Mail (Sie schicken uns 3 Verbrauchsabrechnungen)</td
>
<td
><input
type="radio"
bind:group={basePrice}
value={prices[2]}
name="Preis"
/></td
>
</tr>
</table>
</div>
<hr />
<div class="yellow-box flex flex-col gap-4">
<table>
<strong>Zusatzleistungen:<br /></strong>
{#each services as service}
<tr>
<td
>{service.name}</td
>
<td
><input
type="checkbox"
class="IGZusatzleistung"
bind:checked={service.selected}
/>
</td>
</tr>
{/each}
</table>
</div>
</div>
<style>
.test-box div {
@apply flex flex-col gap-1.5;
}
</style>

View File

@@ -86,7 +86,7 @@ const schema = JSON.stringify({
<Header />
<main class="grid gap-6 p-6 grid-cols-[2fr,8fr] max-w-[1920px] w-full bg-base-100">
<SidebarLeft></SidebarLeft>
<article class="bg-base-200 rounded-lg border border-base-300">
<article class="bg-base-200 rounded-lg border border-base-300 h-min">
<slot />
</article>
</main>

View File

@@ -1,7 +1,7 @@
<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 { validateAccessTokenClient } from "../../client/lib/validateAccessToken";
import { client } from "src/trpc";
import EmbeddedAuthFlowModule from "#modules/EmbeddedAuthFlowModule.svelte";
import Overlay from "#components/Overlay.svelte";

View File

@@ -0,0 +1,370 @@
<script lang="ts">
import HelpLabel from "#components/HelpLabel.svelte";
import ZipSearch from "../components/PlzSuche.svelte";
import Label from "../components/Label.svelte";
import type {
BedarfsausweisWohnen,
Benutzer,
Bezahlmethoden,
VerbrauchsausweisGewerbe,
VerbrauchsausweisWohnen,
} from "@ibcornelsen/database/client";
import { Enums } from "@ibcornelsen/database/client";
import PaymentOption from "#components/PaymentOption.svelte";
import { client } from "src/trpc";
import type { inferProcedureInput } from "@trpc/server";
import type { AppRouter } from "@ibcornelsen/api";
import CheckoutItem from "#components/CheckoutItem.svelte";
export let user: Benutzer;
export let ausweis:
| VerbrauchsausweisWohnen
| BedarfsausweisWohnen
| VerbrauchsausweisGewerbe;
let rechnung: inferProcedureInput<
AppRouter["v1"]["rechnungen"]["erstellen"]
> = {};
let services = [
{
name: "Qualitätsdruck per Post (zusätzlich zur PDF Version) für 9€ inkl. MwSt.",
id: Enums.Service.Qualitaetsdruck,
price: 9,
selected: false,
},
{
name: "Aushang (für öffentliche Gebäude gesetzlich vorgeschrieben) für 10€ inkl. MwSt.",
id: Enums.Service.Aushang,
price: 10,
selected: false,
},
{
name: "Same Day Service (Bestellung Werktags vor 12:00 Uhr - Ausstellung bis 18:00 Uhr am gleichen Tag) für 29€ inkl. MwSt.",
id: Enums.Service.SameDay,
price: 29,
selected: false,
},
{
name: "Telefonische Energieeffizienzberatung für 75€ inkl. MwSt.",
id: Enums.Service.Telefonberatung,
price: 75,
selected: false,
},
];
export let selectedPaymentType: Bezahlmethoden =
Enums.Bezahlmethoden.PAYPAL;
let agbAkzeptiert: boolean;
let datenschutzAkzeptiert: boolean;
async function createPayment(e: SubmitEvent) {
e.preventDefault();
const response = await client.v1.rechnungen.erstellen.mutate({
...rechnung,
ausweisart: ausweis.ausweisart,
uid: ausweis.uid,
bezahlmethode: selectedPaymentType,
services: services
.filter((service) => service.selected)
.map((service) => service.id),
});
window.location.href = response.checkout_url;
}
</script>
<div class="grid grid-cols-[2fr_1fr] gap-4 h-full">
<div>
<h3 class="font-semibold">Ansprechpartner</h3>
<div class="rounded-lg border p-4 border-base-300 bg-base-100">
<div class="grid grid-cols-3 gap-4">
<!-- Anrede -->
<div>
<Label>Anrede *</Label>
<div>
<select name="anrede" bind:value={user.anrede}>
<option>bitte auswählen</option>
<option value="Herr">Herr</option>
<option value="Frau">Frau</option>
</select>
</div>
</div>
<!-- Vorname -->
<div>
<Label>Vorname *</Label>
<input
name="vorname"
type="text"
bind:value={user.vorname}
required
/>
</div>
<!-- Nachname -->
<div>
<Label>Nachname *</Label>
<input
name="name"
type="text"
bind:value={user.name}
required
/>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<!-- Telefon -->
<div>
<Label>Telefon</Label>
<input
name="telefon"
bind:value={user.telefon}
type="text"
/>
</div>
<!-- Email -->
<div>
<Label>E-Mail *</Label>
<input
name="email"
type="email"
bind:value={user.email}
required
/>
</div>
</div>
</div>
<h3 class="mt-8 font-semibold">Rechnungsadresse</h3>
<div class="rounded-lg border p-4 border-base-300 bg-base-100">
<div class="grid grid-cols-2 gap-4">
<div>
<Label>Empfänger *</Label>
<input
name="rechnung_empfaenger"
type="text"
bind:value={rechnung.empfaenger}
required
data-rule-maxlength="100"
data-msg-maxlength="max. 100 Zeichen"
/>
</div>
<!-- Zusatzzeile -->
<div>
<Label>Zusatzzeile</Label>
<input
name="rechnung_zusatzzeile"
bind:value={rechnung.zusatzzeile}
type="text"
data-rule-maxlength="80"
data-msg-maxlength="max. 80 Zeichen"
/>
</div>
</div>
<div class="grid grid-cols-3 gap-4">
<!-- Strasse -->
<div>
<Label>Straße, Hausnummer *</Label>
<input
name="rechnung_strasse"
bind:value={rechnung.strasse}
type="text"
required
data-rule-maxlength="40"
data-msg-maxlength="max. 40 Zeichen"
/>
</div>
<!-- PLZ -->
<ZipSearch
name="rechnung_plz"
bind:zip={rechnung.plz}
bind:city={rechnung.ort}
/>
<!-- Ort -->
<div>
<Label>Ort *</Label>
<input
name="rechnung_ort"
readonly
type="text"
required
value={rechnung.ort}
/>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<!-- Telefon -->
<div>
<Label>Telefon</Label>
<input
name="rechnung_telefon"
bind:value={rechnung.telefon}
type="text"
/>
</div>
<!-- Email -->
<div>
<Label>E-Mail</Label>
<input
name="rechnung_email"
bind:value={rechnung.email}
type="email"
/>
</div>
</div>
</div>
<h3 class="mt-8 font-semibold">Versandadresse</h3>
<div class="rounded-lg border p-4 border-base-300 bg-base-100">
<div class="flex flex-row gap-2 items-center">
<input
class="w-[15px] h-[15px]"
type="checkbox"
name="abweichende_versand_adresse"
bind:checked={rechnung.abweichende_versand_adresse}
/>
<Label>Abweichende Versandadresse</Label>
</div>
<div class="grid grid-cols-2 gap-4">
<!-- Empfänger -->
<div>
<Label>Empfänger *</Label>
<input
name="versand_empfaenger"
type="text"
readonly={!rechnung.abweichende_versand_adresse}
bind:value={rechnung.versand_empfaenger}
required
data-rule-maxlength="100"
data-msg-maxlength="max. 100 Zeichen"
/>
</div>
<!-- Zusatzzeile -->
<div>
<Label>Zusatzzeile</Label>
<input
name="versand_zusatzzeile"
type="text"
readonly={!rechnung.abweichende_versand_adresse}
bind:value={rechnung.versand_zusatzzeile}
data-rule-maxlength="80"
data-msg-maxlength="max. 80 Zeichen"
/>
</div>
</div>
<div class="grid grid-cols-3 gap-4">
<!-- Strasse -->
<div>
<Label>Straße, Hausnummer *</Label>
<input
name="versand_strasse"
type="text"
readonly={!rechnung.abweichende_versand_adresse}
bind:value={rechnung.versand_strasse}
required
data-rule-maxlength="40"
data-msg-maxlength="max. 40 Zeichen"
/>
</div>
<!-- PLZ -->
<ZipSearch
name="versand_plz"
readonly={!rechnung.abweichende_versand_adresse}
bind:zip={rechnung.versand_plz}
bind:city={rechnung.versand_ort}
/>
<!-- Ort -->
<div>
<Label>Ort *</Label>
<input
name="versand_ort"
type="text"
readonly
required
bind:value={rechnung.versand_ort}
/>
</div>
</div>
</div>
<h3 class="mt-8 font-semibold">Bezahlmethode</h3>
<div
class="rounded-lg border p-4 border-base-300 bg-base-100 flex flex-row gap-4 justify-between"
>
<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>
<div>
<h3 class="font-semibold">Zusammenfassung</h3>
<div class="rounded-lg border p-4 border-base-300 bg-base-100">
<CheckoutItem
image={"https://www.gih.de/wp-content/uploads/2015/11/EnergieausweisW-E.jpg"}
name={"Energieausweis"}
description={"Verbrauchsausweis Wohnen"}
price={45}
quantity={1}
removable={false}
maxQuantity={1}
/>
<div class="mt-auto">
<hr />
<div class="flex flex-row items-center justify-between">
<span class="opacity-75 text-sm">Brutto</span>
<span class="font-semibold text-sm">75$</span>
</div>
<div class="flex flex-row items-center justify-between">
<span class="opacity-75 text-sm">Netto</span>
<span class="font-semibold text-sm">75$</span>
</div>
<hr />
<div class="flex flex-row items-center justify-between">
<span class="opacity-75 text-sm">Gesamt</span>
<span class="font-semibold text-sm">75$</span>
</div>
<button class="btn btn-secondary w-full mt-4" disabled
>Bestellung Bestätigen</button
>
</div>
</div>
</div>
</div>

View File

@@ -1,397 +1,271 @@
<script lang="ts">
import ProgressBar from "#components/Ausweis/Progressbar.svelte";
import HelpLabel from "#components/HelpLabel.svelte";
import ZipSearch from "../components/PlzSuche.svelte";
import Label from "../components/Label.svelte";
import PriceContainer from "#components/Kaufabschluss/PriceContainer.svelte";
import type { BedarfsausweisWohnen, Benutzer, Bezahlmethoden, Rechnungen, VerbrauchsausweisGewerbe, VerbrauchsausweisWohnen } from "@ibcornelsen/database/client";
import { Enums } from "@ibcornelsen/database/client"
import PaymentOption from "#components/PaymentOption.svelte";
import { client } from "src/trpc";
import type { inferProcedureInput } from "@trpc/server";
import type { AppRouter } from "@ibcornelsen/api";
import type {
BedarfsausweisWohnen,
Benutzer,
Bezahlmethoden,
VerbrauchsausweisGewerbe,
VerbrauchsausweisWohnen,
} from "@ibcornelsen/database/client";
import { Enums } from "@ibcornelsen/database/client";
export let user: Benutzer;
export let ausweis: VerbrauchsausweisWohnen | BedarfsausweisWohnen | VerbrauchsausweisGewerbe;
let rechnung: inferProcedureInput<AppRouter["v1"]["rechnungen"]["erstellen"]> = {};
export let ausweis:
| VerbrauchsausweisWohnen
| BedarfsausweisWohnen
| VerbrauchsausweisGewerbe;
let services = [{
let services = [
{
name: "Qualitätsdruck per Post (zusätzlich zur PDF Version) für 9€ inkl. MwSt.",
id: Enums.Service.Qualitaetsdruck,
price: 9,
selected: false
}, {
selected: false,
},
{
name: "Aushang (für öffentliche Gebäude gesetzlich vorgeschrieben) für 10€ inkl. MwSt.",
id: Enums.Service.Aushang,
price: 10,
selected: false
}, {
selected: false,
},
{
name: "Same Day Service (Bestellung Werktags vor 12:00 Uhr - Ausstellung bis 18:00 Uhr am gleichen Tag) für 29€ inkl. MwSt.",
id: Enums.Service.SameDay,
price: 29,
selected: false
}, {
selected: false,
},
{
name: "Telefonische Energieeffizienzberatung für 75€ inkl. MwSt.",
id: Enums.Service.Telefonberatung,
price: 75,
selected: false
}]
selected: false,
},
];
export let selectedPaymentType: Bezahlmethoden = Enums.Bezahlmethoden.PAYPAL;
export let selectedPaymentType: Bezahlmethoden =
Enums.Bezahlmethoden.paypal;
let agbAkzeptiert: boolean;
let datenschutzAkzeptiert: boolean;
import { PRICES } from "#lib/constants";
async function createPayment(e: SubmitEvent) {
e.preventDefault()
const prices = PRICES[ausweis.ausweisart];
const response = await client.v1.rechnungen.erstellen.mutate({
...rechnung,
ausweisart: ausweis.ausweisart,
uid: ausweis.uid,
bezahlmethode: selectedPaymentType,
services: services.filter(service => service.selected).map(service => service.id)
})
let basePrice: number = prices[0];
window.location.href = response.checkout_url
}
$: price =
basePrice +
services.reduce(
(acc, service) => (service.selected && acc + service.price) || acc,
0
);
</script>
<div class="w-full px-8">
<div class="flex flex-row gap-8 items-center mb-8 w-3/5">
<div class="flex flex-row gap-8 items-center mb-8 w-full">
<div class="flex flex-col w-full">
<h1>Verbrauchsausweis erstellen - 45€</h1>
<ProgressBar progress={50} />
</div>
</div>
<div
class="w-full"
<form>
<div class="grid grid-cols-[1.5fr_2fr] gap-4">
<div class="rounded-lg border p-4 border-base-300 bg-base-100 flex flex-col gap-4">
<div class="flex flex-col gap-2 test-box">
<strong>A - Prüfung der Ausweisart</strong>
<div>
<span>Vermietung, Verkauf oder sonstiges</span>
<span
>Baujahr Heizung nicht kleiner als Baujahr Gebäude</span
><span
>Baujahr nach 1977 oder saniert oder mehr als 4
Wohneinheiten</span
><span>Heizung min. 3 Jahre alt</span><span
>Verbrauchsausweis zulässig</span
>
</div>
</div>
<div class="flex flex-col gap-2 test-box">
<strong
>B - Prüfung der Adresse, Wohnfläche, Keller und Dach</strong
>
<form class="flex flex-row gap-8" on:submit={createPayment}>
<div class="w-3/5">
<div class="GRB3">
<HelpLabel title="Ansprechpartner" />
<hr />
<div class="grid grid-cols-3 gap-4">
<!-- Anrede -->
<div>
<Label>Anrede *</Label>
<span>PLZ gültig</span><span>Klimafaktorern</span><span
>Wohnfläche passt zu Wohneinheiten</span
>
</div>
</div>
<div class="flex flex-col gap-2 test-box">
<strong>C - Prüfung der Verbrauchsangaben</strong>
<div>
<select name="anrede" bind:value={user.anrede}>
<option>bitte auswählen</option>
<option value="Herr">Herr</option>
<option value="Frau">Frau</option>
</select>
<span>Verbrauchsmenge schlüssig</span><span
>Verbrauchsabweichung im Rahmen</span
><span>Endenergieverbrauch schlüssig</span>
</div>
</div>
<!-- Vorname -->
<div class="flex flex-col gap-2 test-box">
<strong
>D - Prüfung Warmwasser und alternative
Energieversorgung</strong
>
<div>
<Label>Vorname *</Label>
<input name="vorname" type="text" bind:value={user.vorname} required />
<span>Warmwasseranteil schlüssig</span>
</div>
<!-- Nachname -->
</div>
<div class="flex flex-col gap-2 test-box">
<strong
>E - Prüfung von Gebäudetyp, Lüftung, Kühlung und
Leerstand</strong
>
<div>
<Label>Nachname *</Label>
<input name="name" type="text" bind:value={user.name} required />
<span>Leerstand nicht größer als 30%</span>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<!-- Telefon -->
<div class="flex flex-col gap-2 test-box">
<strong
>F - Prüfung des Sanierungsstandes und der Gebäudebilder</strong
>
<div>
<Label>Telefon</Label>
<input name="telefon" bind:value={user.telefon} type="text" />
<span>Mindestens ein Bild pro Abschnitt vorhanden</span
><span>Angaben zum Sanierungsstand vorhanden</span><span
>Bei Baujahr vor 1978 Dach oder Geschossdecke min.
12 cm gedämmt</span
>
</div>
</div>
</div>
<!-- Email -->
<div>
<Label>E-Mail *</Label>
<input name="email" type="email" bind:value={user.email} required />
<div class="rounded-lg border p-4 border-base-300 bg-base-100 flex flex-col">
<table>
<tr>
<td><strong>Produkt:</strong></td>
<td
><div class="py-2">
Verbrauchsausweis
</div></td
>
</tr>
<tr>
<td><strong>Beschreibung:</strong></td>
<td>
<div class="py-2">
Registrierung beim DiBt<br />
Prüfung durch Diplom Ingenieur<br />
Energieausweis Vorschau als PDF<br />
</div>
</td>
</tr>
<tr>
<td>Netto-Preis</td>
<td
><div class="py-2">
{(price * 0.81).toFixed(2) + "€"}
</div></td
>
</tr>
<tr>
<td>19% gesetzl. MwSt.</td>
<td
><div class="py-2">
{(price * 0.19).toFixed(2) + "€"}
</div></td
>
</tr>
<hr>
<tr>
<td>Preis inkl. MwSt.</td>
<td
><div class="py-2">
<strong>{price + "€"}</strong>
</div>
</td>
</tr>
</table>
</div>
<hr />
<div class="GRB3">
<HelpLabel title="Rechnungsadresse" />
<hr />
<!-- Empfänger -->
<div class="grid grid-cols-2 gap-4">
<div>
<Label>Empfänger *</Label>
<input
name="rechnung_empfaenger"
type="text"
bind:value={rechnung.empfaenger}
required
data-rule-maxlength="100"
data-msg-maxlength="max. 100 Zeichen"
<h3 class="font-semibold mt-8">Hiermit bestelle ich folgende Version des Energieausweises:</h3>
<div class="rounded-lg border p-4 border-base-300 bg-base-100 flex flex-col">
<table>
<tr>
<td
>Verbrauchsausweis online für {prices[0]} € inkl. MwSt.
als PDF per E-Mail</td
>
<td
><input
type="radio"
class="radio radio-secondary"
bind:group={basePrice}
value={prices[0]}
name="Preis"
checked
/>
</div>
<!-- Zusatzzeile -->
<div>
<Label>Zusatzzeile</Label>
<input
name="rechnung_zusatzzeile"
bind:value={rechnung.zusatzzeile}
type="text"
data-rule-maxlength="80"
data-msg-maxlength="max. 80 Zeichen"
/>
</div>
</div>
<div class="grid grid-cols-3 gap-4">
<!-- Strasse -->
<div>
<Label>Straße, Hausnummer *</Label>
<input
name="rechnung_strasse"
bind:value={rechnung.strasse}
type="text"
required
data-rule-maxlength="40"
data-msg-maxlength="max. 40 Zeichen"
</td>
</tr>
<tr>
<td
>Verbrauchsausweis online inkl. Beratung für {prices[1]}
€ inkl. MwSt. als PDF per E-Mail</td
>
<td
><input
type="radio"
class="radio radio-secondary"
bind:group={basePrice}
value={prices[1]}
name="Preis"
/>
</td>
</tr><tr>
<td
>Verbrauchsausweis offline für {prices[2]} € inkl. MwSt.
als PDF per E-Mail (Sie schicken uns 3 Verbrauchsabrechnungen)</td
>
<td
><input
type="radio"
class="radio radio-secondary"
bind:group={basePrice}
value={prices[2]}
name="Preis"
/></td
>
</tr>
</table>
</div>
<!-- PLZ -->
<ZipSearch
name="rechnung_plz"
bind:zip={rechnung.plz}
bind:city={rechnung.ort}
/>
<!-- Ort -->
<div>
<Label>Ort *</Label>
<input
name="rechnung_ort"
readonly
type="text"
required
value={rechnung.ort}
/>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<!-- Telefon -->
<div>
<Label>Telefon</Label>
<input name="rechnung_telefon" bind:value={rechnung.telefon} type="text" />
</div>
<!-- Email -->
<div>
<Label>E-Mail</Label>
<input name="rechnung_email" bind:value={rechnung.email} type="email" />
</div>
</div>
</div>
<hr />
<div class="GRB3">
<HelpLabel title="Versandadresse" />
<hr />
<div class="flex flex-row gap-2 items-center">
<input
class="w-[15px] h-[15px]"
<h3 class="font-semibold mt-8">Zusatzleistungen</h3>
<div class="rounded-lg border p-4 border-base-300 bg-base-100 flex flex-col">
<table>
{#each services as service}
<tr>
<td>{service.name}</td>
<td
><input
type="checkbox"
name="abweichende_versand_adresse"
bind:checked={rechnung.abweichende_versand_adresse}
class="checkbox checkbox-secondary"
bind:checked={service.selected}
/>
<Label>Abweichende Versandadresse</Label>
</div>
<div class="grid grid-cols-2 gap-4">
<!-- Empfänger -->
<div>
<Label>Empfänger *</Label>
<input
name="versand_empfaenger"
type="text"
readonly={!rechnung.abweichende_versand_adresse}
bind:value={rechnung.versand_empfaenger}
required
data-rule-maxlength="100"
data-msg-maxlength="max. 100 Zeichen"
/>
</div>
<!-- Zusatzzeile -->
<div>
<Label>Zusatzzeile</Label>
<input
name="versand_zusatzzeile"
type="text"
readonly={!rechnung.abweichende_versand_adresse}
bind:value={rechnung.versand_zusatzzeile}
data-rule-maxlength="80"
data-msg-maxlength="max. 80 Zeichen"
/>
</div>
</div>
<div class="grid grid-cols-3 gap-4">
<!-- Strasse -->
<div>
<Label>Straße, Hausnummer *</Label>
<input
name="versand_strasse"
type="text"
readonly={!rechnung.abweichende_versand_adresse}
bind:value={rechnung.versand_strasse}
required
data-rule-maxlength="40"
data-msg-maxlength="max. 40 Zeichen"
/>
</div>
<!-- PLZ -->
<ZipSearch
name="versand_plz"
readonly={!rechnung.abweichende_versand_adresse}
bind:zip={rechnung.versand_plz}
bind:city={rechnung.versand_ort}
/>
<!-- Ort -->
<div>
<Label>Ort *</Label>
<input
name="versand_ort"
type="text"
readonly
required
bind:value={rechnung.versand_ort}
/>
</div>
</td>
</tr>
{/each}
</table>
</div>
</div>
<hr />
<div class="GRB3">
<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.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.creditcard
? 'mastercard'
: selectedPaymentType}.png"
class="payment-option-logo"
/>
<div class="flex flex-row justify-between">
<!-- TODO: Zurück implementieren -->
<button class="btn btn-secondary mt-4">Zurück</button>
<div class="flex flex-row gap-4">
<!-- TODO: Speichern implementieren -->
<button class="btn btn-secondary mt-4">Speichern</button>
<button class="btn btn-secondary mt-4">Zum Kaufabschluss</button>
</div>
{#if selectedPaymentType == Enums.Bezahlmethoden.rechnung}
<p>
Sobald sie AGB und Datenschutzerklärung
gelesen und akzeptiert haben können sie den
Kauf fortsetzen. Durch das Klicken auf
'Kostenpflichtig Bestellen' wird ihnen eine
Email mit weiteren Informationen über ihren
Kauf zugeschickt, von der aus sie den
Bezahlvorgang abschließen können.
</p>
{:else}
<p>
Sobald sie AGB und Datenschutzerklärung
gelesen und akzeptiert haben können sie den
Kauf fortsetzen. Durch das Klicken auf
'Kostenpflichtig Bestellen' werden sie zu <strong
>{selectedPaymentType}</strong
> weitergeleitet.
</p>
{/if}
<div class="column">
<div class="flex-row center">
<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
> vom Ingenieur-Büro Cornelsen einverstanden.</label
>
</div>
<div class="flex-row center">
<input
type="checkbox"
name="datenschutz-akzeptieren"
bind:checked={datenschutzAkzeptiert}
/>
<label for="datenschutz-akzeptieren"
>Ich erkläre mich mit der <a
href="https://online-energieausweis.org/impressum"
>Datenschutzerklärung</a
>
und
<a
href="https://online-energieausweis.org/agb#widerruf"
>Widerrufsbelehrung</a
> vom Ingenieur-Büro Cornelsen einverstanden.</label
>
</div>
</div>
<button type="submit" class="pay-button" disabled={!agbAkzeptiert || !datenschutzAkzeptiert}
>Kostenpflichtig Bestellen</button
>
</div>
</div>
<hr />
<div class="flex flex-row w-full justify-between">
<button class="button">Zurück</button>
</div>
</div>
<div class="w-2/5">
<PriceContainer {ausweis} bind:services />
</div>
</form>
</div>
</div>
<style>
input,
select {
display: block;
width: 100%;
height: calc(2.25rem + 2px);
padding: 0.375rem 0.75rem;
font-size: 1rem;
line-height: 1.5;
color: #495057;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #ced4da;
border-radius: 0.25rem;
}
.pay-button {
@apply w-full px-4 py-3 text-center flex items-center justify-center bg-gray-500 text-white rounded-md cursor-not-allowed mt-4 select-none no-underline font-semibold;
}
.pay-button:hover {
@apply no-underline;
}
.pay-button:not([disabled]) {
@apply cursor-pointer bg-yellow-500;
}
.pay-button:not([disabled]):hover {
@apply bg-yellow-600;
.test-box div {
@apply flex flex-col gap-1.5;
}
</style>

View File

@@ -0,0 +1,41 @@
---
import KaufabschlussModule from "#modules/KaufabschlussModule.svelte";
import AusweisLayout from "#layouts/AusweisLayout.astro";
import { Benutzer, Enums } from "@ibcornelsen/database/client";
import { prisma } from "@ibcornelsen/database/server";
// 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({
where: {
uid
},
}) as Benutzer;
const ausweis = await prisma.verbrauchsausweisWohnen.findUnique({
where: {
uid: uidAusweis,
},
});
if (!ausweis) {
return Astro.redirect("/404");
}
---
<AusweisLayout title="Kundendaten Aufnehmen - IBCornelsen">
<KaufabschlussModule user={user} ausweis={ausweis} selectedPaymentType={Enums.Bezahlmethoden.PAYPAL} client:load></KaufabschlussModule>
</AusweisLayout>