Bugfixes & Features

1. Wenn pdf hochgeladen wird und abgespeichert wird erscheint es nicht im Formular aber im Dashboard.

2. Loading Spinner beim Hochladen von Dateien damit man sieht das was passiert.

3. Bei Bedarfsausweis Gewerbe anfragen sind in der Liste bei Gebäudetyp nur Wohngebäude!!
This commit is contained in:
Moritz Utcke
2025-10-13 11:33:45 -04:00
parent d4793af2a4
commit 4381578205
8 changed files with 117 additions and 63 deletions

View File

@@ -1,14 +1,6 @@
import { api } from "astro-typesafe-api/client";
import Cookies from "js-cookie";
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
import {
AufnahmeClient,
BedarfsausweisWohnenClient,
BildClient,
ObjektClient,
VerbrauchsausweisGewerbeClient,
VerbrauchsausweisWohnenClient,
} from "#components/Ausweis/types.js";
import {
Aufnahme,
BedarfsausweisWohnen,

View File

@@ -75,7 +75,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
>
<option disabled selected value={null}>Bitte auswählen</option>
{#if ausweisart==Enums.Ausweisart.VerbrauchsausweisWohnen || ausweisart === Enums.Ausweisart.GEGNachweisWohnen || ausweisart === Enums.Ausweisart.BedarfsausweisWohnen || ausweisart === Enums.Ausweisart.BedarfsausweisGewerbe}
{#if ausweisart==Enums.Ausweisart.VerbrauchsausweisWohnen || ausweisart === Enums.Ausweisart.GEGNachweisWohnen || ausweisart === Enums.Ausweisart.BedarfsausweisWohnen}
<option value="Einfamilienhaus">Einfamilienhaus</option>
<option value="Freistehendes Einfamilienhaus">Freistehendes Einfamilienhaus</option>
<option value="Freistehendes Zweifamilienhaus">Freistehendes Zweifamilienhaus</option>
@@ -87,7 +87,7 @@ xl:grid-cols-3 xl:gap-x-8 xl:gap-y-8
<option value="Atrium-Bungalow">Atrium-Bungalow</option>
<option value="Winkelbungalow">Winkelbungalow</option>
{:else if ausweisart==Enums.Ausweisart.VerbrauchsausweisGewerbe || ausweisart=== Enums.Ausweisart.GEGNachweisGewerbe}
{:else if ausweisart==Enums.Ausweisart.VerbrauchsausweisGewerbe || ausweisart=== Enums.Ausweisart.GEGNachweisGewerbe || ausweisart === Enums.Ausweisart.BedarfsausweisGewerbe}
<option value="Verwaltungsgebäude (allgemein)">Verwaltungsgebäude (allgemein)</option>
<option value="Parlaments- und Gerichtsgebäude">Parlaments- und Gerichtsgebäude</option>
<option value="Ministerien u. Ämter u. Behörden">Ministerien u. Ämter u. Behörden</option>

View File

@@ -1,10 +1,10 @@
<script lang="ts">
import { BedarfsausweisWohnenClient, GEGNachweisWohnenClient, ObjektClient, UnterlageClient, VerbrauchsausweisGewerbeClient, VerbrauchsausweisWohnenClient } from "./Ausweis/types.js";
import { BedarfsausweisWohnenClient, ObjektClient, VerbrauchsausweisGewerbeClient, VerbrauchsausweisWohnenClient } from "./Ausweis/types.js";
import { Trash, Upload } from "radix-svelte-icons";
import HelpLabel from "#components/labels/HelpLabel.svelte";
export let kategorie: string = "";
export let files: Unterlage[] = [];
export let files: (Unterlage & { preview?: boolean })[] = [];
export let max: number = Infinity;
export let min: number = 1;
export let name: string = "";
@@ -26,6 +26,8 @@
for (let i = 0; i < fileArray.length; i++) {
const file = fileArray[i];
files.push({ preview: true, kategorie, name: file.name, mime: file.type, aufnahme_id: null, id: "" });
files = files;
if (i == max) {
break;
@@ -62,7 +64,13 @@
name: file.name
})
files.push({ id, kategorie, name: file.name, mime: mimeType, aufnahme_id: null });
const placeholder = files.find((f) => f.name === fileArray[i].name && f.preview === true && f.kategorie === kategorie);
if (!placeholder) {
return;
}
placeholder!.preview = false;
placeholder!.id = id;
placeholder!.aufnahme_id = ausweis.id;
files = files;
@@ -110,23 +118,37 @@
<div class="grid grid-cols-2 gap-2">
{#each files as file, i}
{#if file.kategorie == kategorie}
<div class="relative group">
<div
class="h-full max-h-96 w-full rounded-lg border-2 group-hover:contrast-50 object-cover transition-all text-center items-center flex p-4 text-opacity-75 text-black"
>{file.name}</div>
<div class="invisible group-hover:visible absolute left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] flex flex-row gap-2">
<button
type="button"
class="rounded-full w-[30px] h-[30px] flex items-center justify-center p-0 bg-[rgba(0,0,0,0.4)]"
on:click={() => {
delete files[i];
files = files.filter((x) => x);
}}
>
<Trash size={20} color="#fff"></Trash>
</button>
{#if file.preview === true}
<!-- Show loading spinner -->
<div class="relative group">
<div
class="h-full max-h-96 w-full rounded-lg border-2 group-hover:contrast-50 object-cover transition-all text-center items-center justify-center flex p-4 text-opacity-75 text-black"
>
<div class="flex flex-row gap-4">
<span>{file.name}</span>
<span class="loader"></span>
</div>
</div>
</div>
</div>
{:else}
<div class="relative group">
<div
class="h-full max-h-96 w-full rounded-lg border-2 group-hover:contrast-50 object-cover transition-all text-center items-center flex p-4 text-opacity-75 text-black"
>{file.name}</div>
<div class="invisible group-hover:visible absolute left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] flex flex-row gap-2">
<button
type="button"
class="rounded-full w-[30px] h-[30px] flex items-center justify-center p-0 bg-[rgba(0,0,0,0.4)]"
on:click={() => {
delete files[i];
files = files.filter((x) => x);
}}
>
<Trash size={20} color="#fff"></Trash>
</button>
</div>
</div>
{/if}
{/if}
{/each}

View File

@@ -7,7 +7,7 @@
import Cookies from "js-cookie";
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
export let images: BildClient[] = [];
export let images: (BildClient & { preview?: boolean })[] = [];
export let max: number = Infinity;
export let min: number = 1;
export let name: string = "";
@@ -35,40 +35,43 @@
<div class="grid grid-cols-2 gap-2">
{#each images as image, i}
{#if image.kategorie == kategorie}
<div class="relative group">
<img
src="/bilder/{image.id}.jpg"
alt={kategorie}
class="h-full max-h-96 w-full rounded-lg border-2 group-hover:contrast-50 object-cover transition-all"
/>
<div class="invisible group-hover:visible absolute left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] flex flex-row gap-2">
<button
type="button"
class="rounded-full w-[30px] h-[30px] flex items-center justify-center p-0 bg-[rgba(0,0,0,0.4)]"
on:click={() => {
deleteImage(images[i])
}}
>
<Trash size={20} color="#fff"></Trash>
</button>
<!-- <button
type="button"
class="rounded-full w-[30px] h-[30px] flex items-center justify-center p-0 bg-[rgba(0,0,0,0.4)]"
on:click={async () => {
let image = await rotateImage(images[i]);
images[i] = image;
images = images
}}
>
<RotateCounterClockwise size={20} color="#fff"></RotateCounterClockwise>
</button> -->
{#if image.preview === true}
<!-- Show loading spinner -->
<div class="relative group">
<div
class="h-full max-h-96 w-full rounded-lg border-2 group-hover:contrast-50 object-cover transition-all text-center items-center justify-center flex p-4 text-opacity-75 text-black"
>
<div class="flex flex-row gap-4">
<span class="loader"></span>
</div>
</div>
</div>
{:else}
<div class="relative group">
<img
src="/bilder/{image.id}.jpg"
alt={kategorie}
class="h-full max-h-96 w-full rounded-lg border-2 group-hover:contrast-50 object-cover transition-all"
/>
<div class="invisible group-hover:visible absolute left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] flex flex-row gap-2">
<button
type="button"
class="rounded-full w-[30px] h-[30px] flex items-center justify-center p-0 bg-[rgba(0,0,0,0.4)]"
on:click={() => {
deleteImage(images[i])
}}
>
<Trash size={20} color="#fff"></Trash>
</button>
</div>
</div>
</div>
{/if}
{/if}
{/each}
<!-- Wir zeigen Platzhalter an, damit der Nutzer sieht wie viele Bilder er hochladen soll -->
{#each { length: Math.max(0, Math.min(max, 4) - images.filter(image => image.kategorie === kategorie).length) } as _, i}
<div class="relative group">
<img
src="/placeholder.png"

View File

@@ -21,7 +21,7 @@
import { addNotification } from "./Notifications/shared.js";
import { API_ACCESS_TOKEN_COOKIE_NAME } from "#lib/constants.js";
export let images: BildClient[] = [];
export let images: (BildClient & { preview?: boolean })[] = [];
export let ausweis:
| VerbrauchsausweisWohnenClient
| VerbrauchsausweisGewerbeClient
@@ -39,8 +39,8 @@
for (let i = 0; i < files.length; i++) {
const file = files[i];
console.log(file);
images.push({ preview: true, benutzer_id: null, kategorie, created_at: new Date(), updated_at: new Date(), id: "" });
images = images;
if (file.type !== "image/jpeg" && file.type !== "image/png" && file.type !== "image/webp" && file.type !== "image/heif" && file.type !== "image/heic") {
continue;
@@ -119,7 +119,13 @@
dismissable: true
})
} else {
images.push({ id: result.id, kategorie });
const placeholder = images.find((f) => f.kategorie === kategorie && f.preview === true);
if (!placeholder) {
return;
}
placeholder!.preview = false;
placeholder!.id = result.id;
placeholder!.benutzer_id = ausweis.benutzer_id;
images = images;
if (i == Math.min(files.length, max) - 1) {

View File

@@ -53,5 +53,8 @@ if (user.rolle !== Enums.BenutzerRolle.ADMIN) {
if (result.length > 0) {
return Astro.redirect(`/dashboard/objekte/${result[0].id}?p=${page}`);
} else {
return Astro.redirect("/dashboard/objekte/leer");
}
---

View File

@@ -8,6 +8,7 @@ import {
Enums,
Objekt,
prisma,
Unterlage,
VerbrauchsausweisGewerbe,
VerbrauchsausweisWohnen,
} from "#lib/server/prisma";
@@ -16,6 +17,7 @@ import {
getBedarfsausweisWohnen,
getBilder,
getObjekt,
getUnterlagen,
getVerbrauchsausweisGewerbe,
getVerbrauchsausweisWohnen,
} from "#lib/server/db";
@@ -52,6 +54,7 @@ let ausweis:
let aufnahme: Aufnahme | null = {} as Aufnahme;
let objekt: Objekt | null = {} as Objekt;
let bilder: Bild[] = [];
let unterlagen: Unterlage[] = [];
let loadFromDatabase = false;
if (typ === AusstellungsTyp.Neuausstellung) {
@@ -147,6 +150,7 @@ if (typ === AusstellungsTyp.Neuausstellung) {
}
bilder = await getBilder(aufnahme.id);
unterlagen = await getUnterlagen(aufnahme.id);
loadFromDatabase = true;
} else if (typ === AusstellungsTyp.Alternativdokument) {
if (!user) {
@@ -249,6 +253,7 @@ if (typ === AusstellungsTyp.Neuausstellung) {
{aufnahme}
{bilder}
{ausweistyp}
{unterlagen}
{ausweis_id}
{user}
{loadFromDatabase}

View File

@@ -279,3 +279,26 @@ article {
/*SIDEBAR-RIGHT*/
/*FOOTER*/
/* LOADERS */
.loader {
width: 24px;
height: 24px;
border: 3px solid #444f94;
border-bottom-color: transparent;
border-radius: 50%;
display: inline-block;
box-sizing: border-box;
animation: rotation 1s linear infinite;
}
@keyframes rotation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}