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

@@ -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 = [{
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
}]
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;
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 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>
<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>
<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>
<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"
/>
</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 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>
<hr />
<div class="GRB3">
<HelpLabel title="Versandadresse" />
<hr />
<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 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>
<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 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 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>
{#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 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>
<div>
<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
>
</div>
</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="flex flex-row w-full justify-between">
<button class="button">Zurück</button>
<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
/>
</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>
<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"
class="checkbox checkbox-secondary"
bind:checked={service.selected}
/>
</td>
</tr>
{/each}
</table>
</div>
</div>
<div class="w-2/5">
<PriceContainer {ausweis} bind:services />
</div>
<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>
</form>
</div>
</div>
</form>
</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>