97 lines
3.5 KiB
Svelte
97 lines
3.5 KiB
Svelte
<script lang="ts">
|
|
import UploadImages from "./UploadImages.svelte";
|
|
import type { Enums } from "#lib/client/prisma";
|
|
import { BedarfsausweisWohnenClient, BildClient, ObjektClient, UploadedGebaeudeBild, VerbrauchsausweisGewerbeClient, VerbrauchsausweisWohnenClient } from "./Ausweis/types.js";
|
|
import { RotateCounterClockwise, Trash, Upload } from "radix-svelte-icons";
|
|
|
|
export let images: BildClient[] = [];
|
|
export let max: number = Infinity;
|
|
export let min: number = 1;
|
|
export let name: string = "";
|
|
export let ausweis: VerbrauchsausweisWohnenClient | VerbrauchsausweisGewerbeClient | BedarfsausweisWohnenClient;
|
|
export let objekt: ObjektClient;
|
|
export let kategorie: Enums.BilderKategorie
|
|
|
|
async function rotateImage(image: UploadedGebaeudeBild): Promise<UploadedGebaeudeBild> {
|
|
return new Promise((resolve, reject) => {
|
|
let img = new Image();
|
|
img.src = image.data ? image.data : `/bilder/${image.uid}.webp`;
|
|
img.onload = () => {
|
|
let canvas = document.createElement("canvas");
|
|
let ctx = canvas.getContext("2d");
|
|
canvas.width = img.height;
|
|
canvas.height = img.width;
|
|
ctx?.translate(img.height / 2, img.width / 2);
|
|
ctx?.rotate((-90 * Math.PI) / 180);
|
|
ctx?.drawImage(img, -img.width / 2, -img.height / 2);
|
|
const clone = Object.assign({}, image)
|
|
clone.data = canvas.toDataURL("image/webp");
|
|
clone.update = true;
|
|
resolve(clone)
|
|
};
|
|
})
|
|
}
|
|
|
|
let upload: () => void;
|
|
</script>
|
|
|
|
<div class="flex flex-col gap-4">
|
|
<UploadImages {name} {kategorie} {max} {min} bind:upload bind:objekt bind:images bind:ausweis><slot /></UploadImages>
|
|
<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.uid}.webp"
|
|
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={() => {
|
|
delete images[i];
|
|
images = images.filter((x) => x);
|
|
}}
|
|
>
|
|
<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>
|
|
</div>
|
|
</div>
|
|
{/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"
|
|
alt={kategorie}
|
|
class="h-full max-h-96 w-full rounded-lg border-2 group-hover:contrast-50 object-cover transition-all"
|
|
class:opacity-35={i >= min}
|
|
/>
|
|
<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={upload}
|
|
>
|
|
<Upload size={20} color="#fff"></Upload>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
{/each}
|
|
</div>
|
|
</div> |