3 Commits

Author SHA1 Message Date
Moritz Utcke
9552a678c3 Style Update 2025-04-09 20:11:57 -04:00
Jens Cornelsen
856c194a02 Dashboard Mockup 2025-04-10 00:18:13 +02:00
Jens Cornelsen
afc561b701 Auto stash before rebase of "main" onto "origin/main" 2025-04-08 13:05:09 +02:00
15 changed files with 41170 additions and 481 deletions

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@@ -0,0 +1,45 @@
import { createCallerFactory } from "astro-typesafe-api/server";
export const createCaller = createCallerFactory({
"bild": await import("../src/pages/api/bild.ts"),
"klimafaktoren": await import("../src/pages/api/klimafaktoren.ts"),
"postleitzahlen": await import("../src/pages/api/postleitzahlen.ts"),
"unterlage": await import("../src/pages/api/unterlage.ts"),
"aufnahme": await import("../src/pages/api/aufnahme/index.ts"),
"admin/ausstellen": await import("../src/pages/api/admin/ausstellen.ts"),
"admin/bestellbestaetigung": await import("../src/pages/api/admin/bestellbestaetigung.ts"),
"admin/erinnern": await import("../src/pages/api/admin/erinnern.ts"),
"admin/nicht-ausstellen": await import("../src/pages/api/admin/nicht-ausstellen.ts"),
"admin/post-ausstellen": await import("../src/pages/api/admin/post-ausstellen.ts"),
"admin/registriernummer": await import("../src/pages/api/admin/registriernummer.ts"),
"admin/stornieren": await import("../src/pages/api/admin/stornieren.ts"),
"bedarfsausweis-gewerbe/[id]": await import("../src/pages/api/bedarfsausweis-gewerbe/[id].ts"),
"bedarfsausweis-gewerbe": await import("../src/pages/api/bedarfsausweis-gewerbe/index.ts"),
"ausweise": await import("../src/pages/api/ausweise/index.ts"),
"auth/access-token": await import("../src/pages/api/auth/access-token.ts"),
"auth/passwort-vergessen": await import("../src/pages/api/auth/passwort-vergessen.ts"),
"auth/refresh-token": await import("../src/pages/api/auth/refresh-token.ts"),
"bedarfsausweis-wohnen/[id]": await import("../src/pages/api/bedarfsausweis-wohnen/[id].ts"),
"bedarfsausweis-wohnen": await import("../src/pages/api/bedarfsausweis-wohnen/index.ts"),
"bilder/[id]": await import("../src/pages/api/bilder/[id].ts"),
"geg-nachweis-gewerbe/[id]": await import("../src/pages/api/geg-nachweis-gewerbe/[id].ts"),
"geg-nachweis-gewerbe": await import("../src/pages/api/geg-nachweis-gewerbe/index.ts"),
"geg-nachweis-wohnen/[id]": await import("../src/pages/api/geg-nachweis-wohnen/[id].ts"),
"geg-nachweis-wohnen": await import("../src/pages/api/geg-nachweis-wohnen/index.ts"),
"objekt": await import("../src/pages/api/objekt/index.ts"),
"user": await import("../src/pages/api/user/index.ts"),
"user/self": await import("../src/pages/api/user/self.ts"),
"rechnung/[id]": await import("../src/pages/api/rechnung/[id].ts"),
"rechnung/anfordern": await import("../src/pages/api/rechnung/anfordern.ts"),
"rechnung": await import("../src/pages/api/rechnung/index.ts"),
"ticket": await import("../src/pages/api/ticket/index.ts"),
"verbrauchsausweis-wohnen/[id]": await import("../src/pages/api/verbrauchsausweis-wohnen/[id].ts"),
"verbrauchsausweis-wohnen": await import("../src/pages/api/verbrauchsausweis-wohnen/index.ts"),
"verbrauchsausweis-gewerbe/[id]": await import("../src/pages/api/verbrauchsausweis-gewerbe/[id].ts"),
"verbrauchsausweis-gewerbe": await import("../src/pages/api/verbrauchsausweis-gewerbe/index.ts"),
"webhooks/mollie": await import("../src/pages/api/webhooks/mollie.ts"),
"aufnahme/[id]/bilder": await import("../src/pages/api/aufnahme/[id]/bilder.ts"),
"aufnahme/[id]": await import("../src/pages/api/aufnahme/[id]/index.ts"),
"aufnahme/[id]/unterlagen": await import("../src/pages/api/aufnahme/[id]/unterlagen.ts"),
"objekt/[id]": await import("../src/pages/api/objekt/[id]/index.ts"),
})

View File

@@ -16,6 +16,7 @@
import { Enums, Objekt } from "#lib/client/prisma.js"; import { Enums, Objekt } from "#lib/client/prisma.js";
import { endEnergieVerbrauchVerbrauchsausweisGewerbe_2016 } from "#lib/Berechnungen/VerbrauchsausweisGewerbe/VerbrauchsausweisGewerbe_2016.js"; import { endEnergieVerbrauchVerbrauchsausweisGewerbe_2016 } from "#lib/Berechnungen/VerbrauchsausweisGewerbe/VerbrauchsausweisGewerbe_2016.js";
import { addNotification } from "#components/Notifications/shared.js"; import { addNotification } from "#components/Notifications/shared.js";
import moment from "moment";
export let ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbeClient | BedarfsausweisWohnenClient; export let ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbeClient | BedarfsausweisWohnenClient;
export let aufnahme: AufnahmeKomplettClient; export let aufnahme: AufnahmeKomplettClient;
@@ -161,261 +162,405 @@
} }
</script> </script>
<div class="relative bg-base-200 border border-base-300 rounded-lg p-4 mr-4"> <div class="mx-auto py-6 px-4 box bg-white">
{#if ausweis.storniert}
<div <!-- Obere Zeile: Titel -->
class="absolute top-0 left-0 w-full h-full bg-[rgba(0,0,0,0.7)] z-[5] rounded-lg select-none" <div class="border-b flex flex-row pb-2">
> <div class="text-xl font-bold">
<h1 Verbrauchsausweis Wohnen mit Beratung (Post, Same Day)
class="absolute -rotate-[25deg] text-5xl md:text-7xl tracking-wide uppercase text-red-500 border-4 border-red-500 rounded-lg top-[50%] translate-y-[-50%] left-[50%] translate-x-[-50%]" </div>
> <div class="bg-red-600 ml-auto px-2 py-0.5 text-sm font-semibold rounded-lg text-white">Gespeichert</div>
Storniert
</h1>
</div> </div>
{/if}
<div class="card-body"> <!-- Navigation (1/3) -->
<div <div class="border-b pt-4 mb-4 flex justify-between items-center">
class="flex justify-end mb-2 dropdown dropdown-bottom absolute top-4 right-4" <button class="bg-gray-300 text-gray-700 px-2 py-1 rounded hover:bg-gray-400">
> &laquo;
<button class="rounded-full p-2.5 hover:bg-base-100">
<DotsVertical size={15} />
</button> </button>
<ul <p class="text-gray-700 font-medium">
tabindex="-1" Ausweis 1/3
class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-64 gap-2" </p>
> <button class="bg-gray-300 text-gray-700 px-2 py-1 rounded hover:bg-gray-400">
<li> &raquo;
<button on:click={ausweisStornieren} </button>
><CrossCircled size={15} />Ausweis Stornieren</button </div>
>
</li> <!-- Erster Block: Drei Spalten -->
<li> <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4">
<button><Pencil2 size={15} /> Als Vorlage benutzen</button> <!-- Linke Spalte: Bild + ID -->
</li> <div class="flex-shrink-0 bg-gray-100 flex flex-col items-center border text-2xl rounded-b-lg pb-2">
<li> <img
<button on:click={() => hilfeModal.showModal()} src="../../images/placeholder.png"
><QuestionMarkCircled size={15} /> Hilfe Erhalten</button alt="Gebäudevorschau"
> class="rounded-t-lg mb-2"
</li> />
</ul> <div class="grid grid-cols-1 md:grid-cols-2 gap-2 bg-white">
</div> <!-- PDF-Icon / Ausweis -->
<div class="flex flex-row flex-wrap items-center gap-2"> <div class="m-4">
<div class="text-lg font-semibold"> <img
{#if ausweisart == Enums.Ausweisart.VerbrauchsausweisWohnen} src="../../images/dashboard/AusweisKreuz.svg"
Verbrauchsausweis Wohnen alt="PDF Symbol für Verbrauchsausweis"
{:else if ausweisart == Enums.Ausweisart.BedarfsausweisWohnen} class="h-auto w-auto p-2 border border-black rounded-lg"
Bedarfsausweis Wohnen />
{:else if ausweisart == Enums.Ausweisart.VerbrauchsausweisGewerbe} <span class="text-sm font-medium ml-4">Verbrauchsausweis</span>
Verbrauchsausweis Gewerbe </div>
{:else if ausweisart == Enums.Ausweisart.GEGNachweisWohnen} <!-- PDF-Icon / Datenblatt -->
GEG Nachweis Wohnen <div class="m-4">
{:else if ausweisart == Enums.Ausweisart.GEGNachweisGewerbe} <img
GEG Nachweis Gewerbe src="../../images/dashboard/DatenblattKreuz.svg"
{:else if ausweisart == Enums.Ausweisart.BedarfsausweisGewerbe} alt="PDF Symbol für Datenblatt"
Bedarfsausweis Gewerbe class="h-auto w-auto p-2 border border-black rounded-lg"
{/if} />
<span class="text-sm font-medium ml-4">Datenblatt</span>
</div>
</div>
<div class="p-4">Ausweis ID: <b>BWWICR32</b></div>
</div>
{#if ausweis.ausweistyp === Enums.AusweisTyp.Beratung || ausweis.ausweistyp === Enums.AusweisTyp.BeratungXL} <div class="relative bg-base-200 border border-base-300 rounded-lg p-4">
(Beratung) {#if ausweis.storniert}
{:else if ausweis.ausweistyp === Enums.AusweisTyp.Offline || ausweis.ausweistyp === Enums.AusweisTyp.OfflineXL} <div
(Offline) class="absolute top-0 left-0 w-full h-full bg-[rgba(0,0,0,0.7)] z-[5] rounded-lg select-none"
>
<h1
class="absolute -rotate-[25deg] text-5xl md:text-7xl tracking-wide uppercase text-red-500 border-4 border-red-500 rounded-lg top-[50%] translate-y-[-50%] left-[50%] translate-x-[-50%]"
>
Storniert
</h1>
</div>
{/if}
<div class="card-body">
<div
class="flex justify-end mb-2 dropdown dropdown-bottom absolute top-4 right-4"
>
<button class="rounded-full p-2.5 hover:bg-base-100">
<DotsVertical size={15} />
</button>
<ul
tabindex="-1"
class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-64 gap-2"
>
<li>
<button on:click={ausweisStornieren}
><CrossCircled size={15} />Ausweis Stornieren</button
>
</li>
<li>
<button><Pencil2 size={15} /> Als Vorlage benutzen</button>
</li>
<li>
<button on:click={() => hilfeModal.showModal()}
><QuestionMarkCircled size={15} /> Hilfe Erhalten</button
>
</li>
</ul>
</div>
<div class="flex flex-row flex-wrap items-center gap-2">
<div class="text-lg font-semibold">
{#if ausweisart == Enums.Ausweisart.VerbrauchsausweisWohnen}
Verbrauchsausweis Wohnen
{:else if ausweisart == Enums.Ausweisart.BedarfsausweisWohnen}
Bedarfsausweis Wohnen
{:else if ausweisart == Enums.Ausweisart.VerbrauchsausweisGewerbe}
Verbrauchsausweis Gewerbe
{:else if ausweisart == Enums.Ausweisart.GEGNachweisWohnen}
GEG Nachweis Wohnen
{:else if ausweisart == Enums.Ausweisart.GEGNachweisGewerbe}
GEG Nachweis Gewerbe
{:else if ausweisart == Enums.Ausweisart.BedarfsausweisGewerbe}
Bedarfsausweis Gewerbe
{/if}
{#if ausweis.ausweistyp === Enums.AusweisTyp.Beratung || ausweis.ausweistyp === Enums.AusweisTyp.BeratungXL}
(Beratung)
{:else if ausweis.ausweistyp === Enums.AusweisTyp.Offline || ausweis.ausweistyp === Enums.AusweisTyp.OfflineXL}
(Offline)
{/if}
</div>
{#if ausweis.ausgestellt}
<span class="bg-green-600 px-2 py-0.5 text-sm font-semibold rounded-lg text-white">Ausgestellt</span>
{:else if ausweis.bestellt}
<span class="bg-primary px-2 py-0.5 text-sm font-semibold rounded-lg text-white">Bestellt</span>
{:else}
<span class="bg-red-600 px-2 py-0.5 text-sm font-semibold rounded-lg text-white">Gespeichert</span>
{/if}
</div>
<div class="badge badge-accent font-semibold text-black text-m">{objekt.adresse}</div>
<div class="mb-4 flex flex-row items-center gap-4">
<div class="w-full border rounded-lg my-2">
<div class="bg-green-600 h-4 rounded-lg" class:bg-red-600={progress == 33} class:bg-primary={progress == 66} style="width: {progress}%;"></div>
</div>
<span class="text-sm font-semibold text-base-content"
>{progress}%</span
>
</div>
{#if ausweis.bestellt}
{#if ausweis.ausweistyp === Enums.AusweisTyp.Beratung || ausweis.ausweistyp === Enums.AusweisTyp.BeratungXL}
<p class="text-sm font-semibold">Sie haben Hilfe zu diesem Ausweis angefordert. Sie werden innerhalb der nächsten 48 Stunden über die hinterlegte Telefonnummer vom IB Cornelsen kontaktiert.</p>
{:else if ausweis.ausweistyp === Enums.AusweisTyp.Offline || ausweis.ausweistyp === Enums.AusweisTyp.OfflineXL}
<p class="text-sm font-semibold">Sie haben die offline Variant zu diesem Ausweis angefordert. Bitte übermitteln Sie uns die letzten drei Jahre der Energieabrechnungen Ihres Energieversorgers.</p>
{:else}
<p class="text-sm font-semibold">Der Ausweis wurde von Ihnen freigegeben und befindet sich in Prüfung vom IB Cornelsen</p>
{/if}
{/if} {/if}
</div> {#await calculations then calculations}
<div class="flex flex-col gap-2">
{#if ausweis.ausgestellt} <div class="flex flex-row justify-between">
<span class="bg-green-600 px-2 py-0.5 text-sm font-semibold rounded-lg text-white">Ausgestellt</span> <span>Energieverbrauch</span>
{:else if ausweis.bestellt} <span class="font-bold text-base-content"
<span class="bg-primary px-2 py-0.5 text-sm font-semibold rounded-lg text-white">Bestellt</span> >{calculations?.endEnergieVerbrauchGesamt}kWh/A</span
{:else} >
<span class="bg-red-600 px-2 py-0.5 text-sm font-semibold rounded-lg text-white">Gespeichert</span> </div>
{/if} <div class="flex flex-row justify-between">
</div> <span>CO2 Ausstoß</span>
<div class="badge badge-accent font-semibold text-black text-m">{objekt.adresse}</div> <span class="font-bold text-base-content"
<div class="mb-4 flex flex-row items-center gap-4"> >{calculations?.co2EmissionenGesamt}Kg/A</span
<div class="w-full border rounded-lg my-2"> >
<div class="bg-green-600 h-4 rounded-lg" class:bg-red-600={progress == 33} class:bg-primary={progress == 66} style="width: {progress}%;"></div> </div>
</div> <div class="flex flex-row justify-between">
<span class="text-sm font-semibold text-base-content" <span>Erstellungsdatum</span>
>{progress}%</span <span class="font-bold text-base-content"
> >{moment(aufnahme.erstellungsdatum).format(
</div> "DD.MM.YYYY"
{#if ausweis.bestellt} )}</span
{#if ausweis.ausweistyp === Enums.AusweisTyp.Beratung || ausweis.ausweistyp === Enums.AusweisTyp.BeratungXL} >
<p class="text-sm font-semibold">Sie haben Hilfe zu diesem Ausweis angefordert. Sie werden innerhalb der nächsten 48 Stunden über die hinterlegte Telefonnummer vom IB Cornelsen kontaktiert.</p> </div>
{:else if ausweis.ausweistyp === Enums.AusweisTyp.Offline || ausweis.ausweistyp === Enums.AusweisTyp.OfflineXL} <div class="flex flex-row justify-between">
<p class="text-sm font-semibold">Sie haben die offline Variant zu diesem Ausweis angefordert. Bitte übermitteln Sie uns die letzten drei Jahre der Energieabrechnungen Ihres Energieversorgers.</p> <span>Baujahr</span>
{:else} <span
<p class="text-sm font-semibold">Der Ausweis wurde von Ihnen freigegeben und befindet sich in Prüfung vom IB Cornelsen</p> class="font-bold text-base-content"
{/if} title="Gebäude / Heizung"
{/if} >{aufnahme.baujahr_gebaeude[0] || "N/A"} /
{#await calculations then calculations} {aufnahme.baujahr_heizung[0] || "N/A"}</span
<div class="flex flex-col gap-2"> >
<div class="flex flex-row justify-between"> </div>
<span>Energieverbrauch</span> <div class="flex flex-row justify-between">
<span class="font-bold text-base-content" <span>Wohnfläche</span>
>{calculations?.endEnergieVerbrauchGesamt}kWh/A</span <span class="font-bold text-base-content"
>{aufnahme.flaeche
? `${aufnahme.flaeche}m²`
: "N/A"}</span
>
</div>
<div class="flex flex-row justify-between">
<span>ID</span>
<span class="font-bold text-base-content"
>{id}</span
>
</div>
</div>
{/await}
<div class="flex flex-row justify-end items-center gap-4 mt-4">
{#if !ausweis.storniert && !ausweis.ausgestellt}
<!--
<a
class="button text-sm"
href="/energieausweis-erstellen/verbrauchsausweis-wohngebaeude?uid={ausweis.id}"
>Stornieren</a>
-->
{/if}
{#if ausweis.bestellt && (!rechnung || rechnung.bezahlmethode === Enums.Bezahlmethoden.rechnung)}
<!-- <a href="/energieausweis-erstellen/bezahlung?uid={ausweis.id}" class="button text-sm">Bezahlen</a> -->
{/if}
{#if !ausweis.ausgestellt && (!ausweis.bestellt || (ausweis.ausweistyp === Enums.AusweisTyp.Beratung || ausweis.ausweistyp === Enums.AusweisTyp.Offline || ausweis.ausweistyp === Enums.AusweisTyp.OfflineXL || ausweis.ausweistyp === Enums.AusweisTyp.BeratungXL))}
{#if ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen}
<a
class="button text-sm"
href="/energieausweis-erstellen/verbrauchsausweis-wohngebaeude?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe}
<a
class="button text-sm"
href="/energieausweis-erstellen/verbrauchsausweis-gewerbe?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.BedarfsausweisWohnen}
<a
class="button text-sm"
href="/energieausweis-erstellen/bedarfsausweis-wohngebaeude?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.GEGNachweisWohnen}
<a
class="button text-sm"
href="/angebot-anfragen/geg-nachweis-wohnen-anfragen?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.GEGNachweisGewerbe}
<a
class="button text-sm"
href="/angebot-anfragen/geg-nachweis-gewerbe-anfragen?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.BedarfsausweisGewerbe}
<a
class="button text-sm"
href="/angebot-anfragen/bedarfsausweis-gewerbe-anfragen?id={ausweis.id}"
>Bearbeiten</a>
{/if}
{#if ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen}
<a
class="button text-sm"
href="/energieausweis-erstellen/verbrauchsausweis-wohngebaeude?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe}
<a
class="button text-sm"
href="/energieausweis-erstellen/verbrauchsausweis-gewerbe?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.BedarfsausweisWohnen}
<a
class="button text-sm"
href="/energieausweis-erstellen/bedarfsausweis-wohngebaeude?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.GEGNachweisWohnen}
<a
class="button text-sm"
href="/angebot-anfragen/geg-nachweis-wohnen-anfragen?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.GEGNachweisGewerbe}
<a
class="button text-sm"
href="/angebot-anfragen/geg-nachweis-gewerbe-anfragen?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.BedarfsausweisGewerbe}
<a
class="button text-sm"
href="/angebot-anfragen/bedarfsausweis-gewerbe-anfragen?id={ausweis.id}"
>Bearbeiten</a>
{/if}
{/if}
{#if benutzer.rolle === Enums.BenutzerRolle.ADMIN}
<!-- TODO -->
{#if ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen}
<a
class="button text-sm"
href="/energieausweis-erstellen/verbrauchsausweis-wohngebaeude?id={ausweis.id}"
>Formular</a>
{:else if ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe}
<a
class="button text-sm"
href="/energieausweis-erstellen/verbrauchsausweis-gewerbe?id={ausweis.id}"
>Formular</a>
{/if}
{/if}
{#if benutzer.rolle === Enums.BenutzerRolle.ADMIN}
<button class="button text-sm" on:click={ausweisAusstellen}>A</button>
<button class="button text-sm" on:click={stornieren}>S</button>
<button class="button text-sm" on:click={registriernummerAnfordern}>R</button>
{/if}
<a
class="p-2 rounded-lg hover:bg-gray-200"
title="PDF Herunterladen"
target="_blank"
href="/pdf/ansichtsausweis?id={ausweis.id}"
> >
</div> <img src="/images/ausweis.webp" width="32" alt="Energieausweis">
<div class="flex flex-row justify-between"> </a>
<span>CO2 Ausstoß</span> <a
<span class="font-bold text-base-content" class="p-2 rounded-lg hover:bg-gray-200"
>{calculations?.co2EmissionenGesamt}Kg/A</span title="PDF Herunterladen"
> target="_blank"
</div> href="/pdf/datenblatt?id={ausweis.id}"
<div class="flex flex-row justify-between">
<span>Erstellungsdatum</span>
<span class="font-bold text-base-content"
>{moment(aufnahme.erstellungsdatum).format(
"DD.MM.YYYY"
)}</span
>
</div>
<div class="flex flex-row justify-between">
<span>Baujahr</span>
<span
class="font-bold text-base-content"
title="Gebäude / Heizung"
>{aufnahme.baujahr_gebaeude[0] || "N/A"} /
{aufnahme.baujahr_heizung[0] || "N/A"}</span
>
</div>
<div class="flex flex-row justify-between">
<span>Wohnfläche</span>
<span class="font-bold text-base-content"
>{aufnahme.flaeche
? `${aufnahme.flaeche}m²`
: "N/A"}</span
>
</div>
<div class="flex flex-row justify-between">
<span>ID</span>
<span class="font-bold text-base-content"
>{id}</span
> >
<img src="/images/datenblatt.webp" width="32" alt="Datenblatt">
</a>
</div> </div>
</div> </div>
{/await}
<div class="flex flex-row justify-end items-center gap-4 mt-4">
{#if !ausweis.storniert && !ausweis.ausgestellt}
<!--
<a
class="button text-sm"
href="/energieausweis-erstellen/verbrauchsausweis-wohngebaeude?uid={ausweis.id}"
>Stornieren</a>
-->
{/if}
{#if ausweis.bestellt && (!rechnung || rechnung.bezahlmethode === Enums.Bezahlmethoden.rechnung)}
<!-- <a href="/energieausweis-erstellen/bezahlung?uid={ausweis.id}" class="button text-sm">Bezahlen</a> -->
{/if}
{#if !ausweis.ausgestellt && (!ausweis.bestellt || (ausweis.ausweistyp === Enums.AusweisTyp.Beratung || ausweis.ausweistyp === Enums.AusweisTyp.Offline || ausweis.ausweistyp === Enums.AusweisTyp.OfflineXL || ausweis.ausweistyp === Enums.AusweisTyp.BeratungXL))}
{#if ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen}
<a
class="button text-sm"
href="/energieausweis-erstellen/verbrauchsausweis-wohngebaeude?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe}
<a
class="button text-sm"
href="/energieausweis-erstellen/verbrauchsausweis-gewerbe?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.BedarfsausweisWohnen}
<a
class="button text-sm"
href="/energieausweis-erstellen/bedarfsausweis-wohngebaeude?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.GEGNachweisWohnen}
<a
class="button text-sm"
href="/angebot-anfragen/geg-nachweis-wohnen-anfragen?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.GEGNachweisGewerbe}
<a
class="button text-sm"
href="/angebot-anfragen/geg-nachweis-gewerbe-anfragen?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.BedarfsausweisGewerbe}
<a
class="button text-sm"
href="/angebot-anfragen/bedarfsausweis-gewerbe-anfragen?id={ausweis.id}"
>Bearbeiten</a>
{/if}
{#if ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen}
<a
class="button text-sm"
href="/energieausweis-erstellen/verbrauchsausweis-wohngebaeude?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe}
<a
class="button text-sm"
href="/energieausweis-erstellen/verbrauchsausweis-gewerbe?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.BedarfsausweisWohnen}
<a
class="button text-sm"
href="/energieausweis-erstellen/bedarfsausweis-wohngebaeude?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.GEGNachweisWohnen}
<a
class="button text-sm"
href="/angebot-anfragen/geg-nachweis-wohnen-anfragen?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.GEGNachweisGewerbe}
<a
class="button text-sm"
href="/angebot-anfragen/geg-nachweis-gewerbe-anfragen?id={ausweis.id}"
>Bearbeiten</a>
{:else if ausweisart === Enums.Ausweisart.BedarfsausweisGewerbe}
<a
class="button text-sm"
href="/angebot-anfragen/bedarfsausweis-gewerbe-anfragen?id={ausweis.id}"
>Bearbeiten</a>
{/if}
{/if}
{#if benutzer.rolle === Enums.BenutzerRolle.ADMIN}
<!-- TODO -->
{#if ausweisart === Enums.Ausweisart.VerbrauchsausweisWohnen}
<a
class="button text-sm"
href="/energieausweis-erstellen/verbrauchsausweis-wohngebaeude?id={ausweis.id}"
>Formular</a>
{:else if ausweisart === Enums.Ausweisart.VerbrauchsausweisGewerbe}
<a
class="button text-sm"
href="/energieausweis-erstellen/verbrauchsausweis-gewerbe?id={ausweis.id}"
>Formular</a>
{/if}
{/if}
{#if benutzer.rolle === Enums.BenutzerRolle.ADMIN}
<button class="button text-sm" on:click={ausweisAusstellen}>A</button>
<button class="button text-sm" on:click={stornieren}>S</button>
<button class="button text-sm" on:click={registriernummerAnfordern}>R</button>
{/if}
<a
class="p-2 rounded-lg hover:bg-gray-200"
title="PDF Herunterladen"
target="_blank"
href="/pdf/ansichtsausweis?id={ausweis.id}"
>
<img src="/images/ausweis.webp" width="32" alt="Energieausweis">
</a>
<a
class="p-2 rounded-lg hover:bg-gray-200"
title="PDF Herunterladen"
target="_blank"
href="/pdf/datenblatt?id={ausweis.id}"
>
<img src="/images/datenblatt.webp" width="32" alt="Datenblatt">
</a>
</div> </div>
<div class="flex-shrink-0 bg-gray-100 flex flex-col border text-xl rounded-lg p-4">
<h3 class="font-bold">Ausweisdaten</h3>
<table>
<tr>
<td>Anlass</td>
<td>{ausweis.ausstellgrund}</td>
</tr>
<tr>
<td>Gebäudetyp</td>
<td>{aufnahme.gebaeudetyp}</td>
</tr>
<tr>
<td>Anzahl Wohneinheiten</td>
<td>{aufnahme.einheiten}</td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td>Gebäudeteil</td>
<td>{aufnahme.gebaeudeteil}</td>
</tr>
</table>
<h3 class="font-bold">Heizverbräuche ({ausweis.einheit_1}, {ausweis.einheit_2})</h3>
<table>
<tr>
<td>{ausweis.brennstoff_1}<br>{ausweis.brennstoff_2}</td>
<td>{ausweis.verbrauch_1}, {ausweis.verbrauch_2}, {ausweis.verbrauch_3}<br>{ausweis.verbrauch_4}, {ausweis.verbrauch_5}, {ausweis.verbrauch_6}</td>
</tr>
<tr>
<td>{ausweis.warmwasser_enthalten ? "Warmwasser enthalten" : "Warmwasser nicht enthalten"}</td>
<td>{ausweis.anteil_warmwasser}</td>
</tr>
<tr>
<td>Alternative Energieversorgung</td>
<td>{aufnahme.alternative_heizung ? "Heizung" : ""}, {aufnahme.alternative_warmwasser ? "Warmwasser" : ""} {aufnahme.alternative_lueftung ? "Lüftung" : ""} {aufnahme.alternative_kuehlung ? "Kühlung" : ""}</td>
</tr>
<tr>
<td>Leerstand</td>
<td>{aufnahme.leerstand}</td>
</tr>
<!-- <tr>
<td>{aufnahme.lueftung}</td>
<td>{aufnahme.kuehlung}</td>
</tr> -->
<!-- <tr>
<td>Sanierungszustand: Zentralheizung</td>
</tr> -->
</table>
</div>
</div> </div>
</div>
<!-- Zweiter Block: Ansprechpartner und Ausweisdaten in zwei Spalten -->
<div class="flex flex-row md:flex-row gap-4 mb-4">
<p class="text-lg text-gray-700 mb-1">
<strong>Besteller:</strong> {benutzer.vorname} {benutzer.name}
</p>
<p class="text-lg text-gray-700">
<strong>Telefon:</strong> {benutzer.telefon}
</p>
<p class="text-lg text-gray-700">
<strong>E-Mail:</strong> {benutzer.email}
</p>
<p class="text-lg text-gray-700">
<strong>Erstelldatum:</strong> {moment(ausweis.created_at).format("DD.MM.YYYY")}
</p>
</div>
<!-- Fußzeile: Navigation (1/3) -->
<div class="border-t pt-4 flex justify-between items-center">
<button class="bg-gray-300 text-gray-700 px-2 py-1 rounded hover:bg-gray-400">
&laquo;
</button>
<p class="text-gray-700 font-medium">
Ausweis 1/3
</p>
<button class="bg-gray-300 text-gray-700 px-2 py-1 rounded hover:bg-gray-400">
&raquo;
</button>
</div>
</div>
<dialog bind:this={hilfeModal} class="modal"> <dialog bind:this={hilfeModal} class="modal">
<div class="modal-box"> <div class="modal-box">

View File

@@ -126,10 +126,7 @@ let lightTheme = Astro.cookies.get("theme")?.value === "light";
<DashboardSidebar lightTheme={lightTheme} benutzer={user} client:load> <DashboardSidebar lightTheme={lightTheme} benutzer={user} client:load>
</DashboardSidebar> </DashboardSidebar>
<article class="box rounded-tl-none
xl:px-10 py-8">
<slot /> <slot />
</article>
</main> </main>

View File

@@ -3,7 +3,6 @@
import AusweisPruefenNotification from "#components/AusweisPruefenNotification.svelte"; import AusweisPruefenNotification from "#components/AusweisPruefenNotification.svelte";
import Carousel from "#components/Carousel.svelte"; import Carousel from "#components/Carousel.svelte";
import DashboardAusweis from "#components/Dashboard/DashboardAusweis.svelte"; import DashboardAusweis from "#components/Dashboard/DashboardAusweis.svelte";
import DashboardNachweis from "#components/Dashboard/DashboardNachweis.svelte";
import NotificationProvider from "#components/NotificationProvider/NotificationProvider.svelte"; import NotificationProvider from "#components/NotificationProvider/NotificationProvider.svelte";
import { Objekt } from "#lib/client/prisma.js"; import { Objekt } from "#lib/client/prisma.js";
import mime from "mime" import mime from "mime"
@@ -26,7 +25,7 @@
<hr> <hr>
<div class="relative mb-6"> <div class="relative mb-6 hidden">
<button class="button flex flex-row rounded-lg gap-2 bg-secondary text-white text-center" on:click={toggleDropdown}> <button class="button flex flex-row rounded-lg gap-2 bg-secondary text-white text-center" on:click={toggleDropdown}>
Ausweis erstellen + Ausweis erstellen +
</button> </button>
@@ -47,7 +46,7 @@
{#if aufnahme.bilder.length > 0} {#if aufnahme.bilder.length > 0}
<Carousel perPage={3}> <Carousel perPage={3}>
{#each aufnahme.bilder as bild, i (i)} {#each aufnahme.bilder as bild, i (i)}
<img src="/bilder/{bild.id}.jpg" alt={bild.kategorie} class="max-h-[25vh] h-full w-full object-contain"> <img src="/bilder/{bild.id}.jpg" alt={bild.kategorie} class="max-h-[15vh] h-full w-full object-contain">
{/each} {/each}
<span slot="left-control" class="p-2.5 bg-opacity-50 bg-white block rounded-full"><ChevronLeft size={24}></ChevronLeft></span> <span slot="left-control" class="p-2.5 bg-opacity-50 bg-white block rounded-full"><ChevronLeft size={24}></ChevronLeft></span>
<span slot="right-control" class="p-2.5 bg-opacity-50 bg-white block rounded-full"><ChevronRight size={24}></ChevronRight></span> <span slot="right-control" class="p-2.5 bg-opacity-50 bg-white block rounded-full"><ChevronRight size={24}></ChevronRight></span>
@@ -74,7 +73,7 @@
} }
</style> </style>
<div class="my-4 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3"> <div class="my-4 grid grid-cols-1 md:grid-cols-1 lg:grid-cols-1">
{#each aufnahme.verbrauchsausweise_wohnen as ausweis} {#each aufnahme.verbrauchsausweise_wohnen as ausweis}
<DashboardAusweis {benutzer} {ausweis} {aufnahme} {objekt} rechnung={ausweis.rechnung}></DashboardAusweis> <DashboardAusweis {benutzer} {ausweis} {aufnahme} {objekt} rechnung={ausweis.rechnung}></DashboardAusweis>
{/each} {/each}

View File

@@ -2,140 +2,28 @@
import "../../style/formular.css"; import "../../style/formular.css";
import { import {
BenutzerClient, BenutzerClient,
ObjektClient,
ObjektKomplettClient, ObjektKomplettClient,
} from "#components/Ausweis/types.js"; } from "#components/Ausweis/types.js";
import DashboardObjekt from "#components/Dashboard/DashboardObjekt.svelte";
import Overlay from "#components/Overlay.svelte";
import PlzSuche from "#components/PlzSuche.svelte";
import { api } from "astro-typesafe-api/client";
import NotificationWrapper from "#components/Notifications/NotificationWrapper.svelte"; import NotificationWrapper from "#components/Notifications/NotificationWrapper.svelte";
import { addNotification } from "#components/Notifications/shared.js";
import Cookies from "js-cookie";
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
import Pagination from "#components/Pagination.svelte";
import AusweisePruefenFilter from "#components/Dashboard/AusweisePruefenFilter.svelte";
import { filterAusweise } from "#lib/filters.js";
import { z, ZodTypeAny } from "zod";
import { Enums } from "#lib/client/prisma.js"; import { Enums } from "#lib/client/prisma.js";
import DashboardAusweis from "#components/Dashboard/DashboardAusweis.svelte";
export let user: BenutzerClient; export let user: BenutzerClient;
export let objekte: ObjektKomplettClient[]; export let objekt: ObjektKomplettClient;
export let page: number; export let page: number;
export let totalPages: number; export let totalPages: number;
let objektOverlayHidden = true;
let objekt: Omit<ObjektClient, "uid"> = {
adresse: "",
erstellungsdatum: new Date(),
latitude: 0,
longitude: 0,
ort: "",
plz: ""
};
async function objektErstellen() {
if (!objekt.adresse || !objekt.ort || !objekt.plz) {
addNotification({
message: "Daten unvollständig.",
subtext: "Ihre eingegebenen Daten sind unvollständig, bitte vervollständigen sie diese und versuchen sie es erneut..",
timeout: 3000,
dismissable: true,
type: "error"
})
return;
}
const result = await api.objekt.PUT.fetch({
adresse: objekt.adresse,
latitude: 0,
longitude: 0,
ort: objekt.ort,
plz: objekt.plz
}, {
headers: {
Authorization: `Bearer ${Cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)}`
}
})
if (!result) {
addNotification({
message: "Etwas ist schiefgelaufen.",
subtext: "Das Objekt konnte nicht erstellt werden.",
timeout: 3000,
dismissable: true,
type: "error"
})
return;
}
objektOverlayHidden = true;
objekte.push({
...objekt,
aufnahmen: [],
id: result.id
})
objekt = {
adresse: "",
erstellungsdatum: new Date(),
latitude: 0,
longitude: 0,
ort: "",
plz: ""
}
objekte = objekte
}
let filters: { name: keyof z.infer<typeof filterAusweise>, type: ZodTypeAny, value: any }[] = []
export let id: string = ""; export let id: string = "";
</script> </script>
<h1>Ihre aktuellen Vorgänge</h1>
<hr />
{#if user.rolle === Enums.BenutzerRolle.ADMIN} {#if user.rolle === Enums.BenutzerRolle.ADMIN}
<!-- <div class="flex flex-col mb-4">
<AusweisePruefenFilter bind:filters={filters}></AusweisePruefenFilter>
</div> -->
<form action="" class="flex flex-row gap-2 my-2"> <form action="" class="flex flex-row gap-2 my-2">
<input type="text" bind:value={id} name="id" placeholder="ID"> <input type="text" bind:value={id} name="id" placeholder="ID">
<button class="button text-sm">Suchen</button> <button class="button text-sm">Suchen</button>
</form> </form>
{/if} {/if}
<!-- <div class="relative mb-6">
<button class="button" on:click={() => {
objektOverlayHidden = false
}}> Gebäude anlegen + </button>
</div> -->
<div class="grid grid-cols-1 md:grid-cols-1 lg:grid-cols-1 gap-4"> <DashboardAusweis objekt={objekt} ausweis={objekt.aufnahmen[0].verbrauchsausweise_wohnen[0]} aufnahme={objekt.aufnahmen[0]} rechnung={objekt.aufnahmen[0].verbrauchsausweise_wohnen[0].rechnung} benutzer={user}></DashboardAusweis>
{#each objekte as objekt}
<DashboardObjekt {objekt}></DashboardObjekt>
{/each}
</div>
<Pagination pages={totalPages} current={page} prev="/dashboard/objekte/{page - 1}" next="/dashboard/objekte/{page + 1}"></Pagination>
<Overlay bind:hidden={objektOverlayHidden}>
<div class="bg-white w-full max-w-screen-sm px-4 py-6 flex flex-col gap-4">
<h2 class="p-0 m-0">Gebäude erstellen</h2>
<input type="text" placeholder="Adresse" bind:value={objekt.adresse}>
<div class="flex flex-row gap-4 justify-between">
<PlzSuche bind:city={objekt.ort} bind:zip={objekt.plz} name="" placeholder="PLZ"></PlzSuche>
<input type="text" bind:value={objekt.ort} placeholder="Ort">
</div>
<button class="button mt-4" on:click={objektErstellen}>Gebäude Erstellen</button>
</div>
</Overlay>
<NotificationWrapper></NotificationWrapper> <NotificationWrapper></NotificationWrapper>

View File

@@ -229,4 +229,8 @@
Ja Ja
</li> </li>
</ul> </ul>
</div> </div>

View File

@@ -2,7 +2,7 @@ import { z } from "zod";
import moment from "moment"; import moment from "moment";
import { prisma } from "#lib/server/prisma.js"; import { prisma } from "#lib/server/prisma.js";
import { encodeToken } from "../../../lib/auth/token.js"; import { encodeToken } from "../../../lib/auth/token.js";
import { validatePassword } from "../../../lib/password.js"; import { hashPassword, validatePassword } from "../../../lib/password.js";
import { APIError, defineApiRoute } from "astro-typesafe-api/server"; import { APIError, defineApiRoute } from "astro-typesafe-api/server";
import { TokenType } from "#lib/auth/types.js"; import { TokenType } from "#lib/auth/types.js";
import { UUidWithPrefix } from "#components/Ausweis/types.js"; import { UUidWithPrefix } from "#components/Ausweis/types.js";

View File

@@ -51,7 +51,7 @@ export const PUT = defineApiRoute({
} }
const id = generatePrefixedId( const id = generatePrefixedId(
9, 6,
VALID_UUID_PREFIXES.BedarfsausweisWohnen VALID_UUID_PREFIXES.BedarfsausweisWohnen
); );

View File

@@ -1,5 +1,42 @@
--- ---
return Astro.redirect("/dashboard/objekte/1", 301); import { Enums, prisma } from "#lib/server/prisma";
import { getCurrentUser } from "#lib/server/user";
const user = await getCurrentUser(Astro)
if (!user) {
return Astro.redirect("/auth/login")
}
const options: any = {
where: user.rolle === Enums.BenutzerRolle.ADMIN ? {} : {
benutzer: {
id: user.id
}
},
orderBy: {
created_at: "desc"
}
}
const lastVerbrauchsausweisWohnen = await prisma.verbrauchsausweisWohnen.findFirst(options)
if (lastVerbrauchsausweisWohnen) {
return Astro.redirect(`/dashboard/objekte/${lastVerbrauchsausweisWohnen.id}`)
}
const lastVerbrauchsausweisGewerbe = await prisma.verbrauchsausweisGewerbe.findFirst(options)
if (lastVerbrauchsausweisGewerbe) {
return Astro.redirect(`/dashboard/objekte/${lastVerbrauchsausweisGewerbe.id}`)
}
const lastBedarfsausweisWohnen = await prisma.bedarfsausweisWohnen.findFirst(options)
if (lastBedarfsausweisWohnen) {
return Astro.redirect(`/dashboard/objekte/${lastBedarfsausweisWohnen.id}`)
}
--- ---
<script></script> <script></script>

View File

@@ -0,0 +1,81 @@
---
import UserLayout from "#layouts/DashboardLayout.astro";
import { Enums, prisma } from "#lib/server/prisma";
import DashboardModule from "#modules/Dashboard/DashboardModule.svelte";
import { getCurrentUser } from "#lib/server/user";
import { getPrismaAusweisAdapter } from "#lib/server/ausweis";
const id = Astro.params.id as string;
const user = await getCurrentUser(Astro);
if (!user) {
return Astro.redirect("/auth/login");
}
const adapter = getPrismaAusweisAdapter(id);
if (!adapter) {
return Astro.redirect("/dashboard");
}
const objekt = await prisma.objekt.findFirst({
where: {
OR: [
{
aufnahmen: {
every: {
verbrauchsausweise_gewerbe: {
some: {
id,
},
},
},
},
},
{
aufnahmen: {
every: {
verbrauchsausweise_wohnen: {
some: {
id,
},
},
},
},
},
{
aufnahmen: {
every: {
bedarfsausweise_wohnen: {
some: {
id,
},
},
},
},
},
],
},
include: {
aufnahmen: {
include: {
bilder: true,
unterlagen: true,
bedarfsausweise_wohnen: true,
verbrauchsausweise_gewerbe: true,
verbrauchsausweise_wohnen: true
}
}
}
});
---
<UserLayout title="Objekte" {user}>
<DashboardModule
{user}
{objekt}
client:load
/>
</UserLayout>

View File

@@ -1,102 +0,0 @@
---
import UserLayout from "#layouts/DashboardLayout.astro";
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants";
import { Enums, prisma } from "#lib/server/prisma";
import { createCaller } from "src/astro-typesafe-api-caller";
import DashboardModule from "#modules/Dashboard/DashboardModule.svelte";
const caller = createCaller(Astro)
const params = Astro.params;
const page = Number(params.page)
const id = Astro.url.searchParams.get("id") || undefined;
const user = await caller.user.self.GET.fetch(undefined, {
headers: {
"Authorization": `Bearer ${Astro.cookies.get(API_ACCESS_TOKEN_COOKIE_NAME)?.value}`
}
});
if (!user) {
return Astro.redirect("/auth/login")
}
const totalPages = await prisma.objekt.count({
where: user.rolle === Enums.BenutzerRolle.USER ? {
benutzer: {
id: user.id
}
} : {}
})
const objekte = await prisma.objekt.findMany({
where: user.rolle === Enums.BenutzerRolle.USER ? {
benutzer: {
id: user.id
},
} : {
...(id ? {OR: [
{
aufnahmen: {
every: {
verbrauchsausweise_gewerbe: {
some: {
id: {
contains: id
}
}
},
}
}
},
{
aufnahmen: {
every: {
verbrauchsausweise_wohnen: {
some: {
id: {
contains: id
}
}
},
}
}
},
{
aufnahmen: {
every: {
bedarfsausweise_wohnen: {
some: {
id: {
contains: id
}
}
},
}
}
},]} : {})
},
orderBy: {
erstellungsdatum: "desc"
},
include: {
aufnahmen: {
include: {
bilder: true,
unterlagen: true,
bedarfsausweise_wohnen: true,
verbrauchsausweise_gewerbe: true,
verbrauchsausweise_wohnen: true
}
}
},
take: 25,
skip: (page - 1) * 25
})
---
<UserLayout title="Objekte" {user}>
<DashboardModule {user} {objekte} totalPages={Math.ceil(totalPages / 25)} page={page} {id} client:load />
</UserLayout>

View File

@@ -138,11 +138,11 @@ Papa.parse(file, {
} }
const aufnahme_id = generatePrefixedId( const aufnahme_id = generatePrefixedId(
9, 6,
VALID_UUID_PREFIXES.Aufnahme VALID_UUID_PREFIXES.Aufnahme
); );
const [aufnahme, aufnahme_error] = await tryCatch(prisma.aufnahme.create({ const aufnahme = await prisma.aufnahme.create({
data: { data: {
id: aufnahme_id, id: aufnahme_id,
alternative_heizung: dataset.alheizung == "1", alternative_heizung: dataset.alheizung == "1",
@@ -243,12 +243,7 @@ Papa.parse(file, {
zentralheizung: dataset.zentralheizung == "1", zentralheizung: dataset.zentralheizung == "1",
zirkulation: dataset.zirkulation == "1", zirkulation: dataset.zirkulation == "1",
}, },
})); });
if (aufnahme_error) {
console.log(aufnahme_error);
continue;
}
/* -------------------------------- Bilder ------------------------------- */ /* -------------------------------- Bilder ------------------------------- */
try { try {