181 lines
9.2 KiB
Vue
181 lines
9.2 KiB
Vue
<template>
|
|
<div class="fixed inset-0 z-[110] flex items-center justify-center bg-slate-950/80 px-4 backdrop-blur-lg" @click.self="$emit('close')">
|
|
<div class="w-full max-w-6xl overflow-hidden rounded-[2.5rem] border border-white/10 bg-white/95 text-slate-900 shadow-[0_45px_85px_rgba(15,23,42,0.45)] ring-1 ring-slate-200 transition dark:bg-slate-900/95 dark:text-white">
|
|
<div class="flex flex-col gap-6 lg:flex-row">
|
|
<figure class="relative flex-1 overflow-hidden bg-slate-900/80">
|
|
<img
|
|
v-if="image?.path"
|
|
:src="image.path"
|
|
:alt="imageLabel"
|
|
class="h-full w-full object-contain"
|
|
/>
|
|
<div v-else class="flex h-full min-h-[320px] items-center justify-center text-slate-500">
|
|
Kein Bild geladen
|
|
</div>
|
|
<div class="pointer-events-none absolute inset-x-0 top-0 flex items-center justify-between p-6 text-xs uppercase tracking-[0.4em] text-white/70">
|
|
<span>{{ image?.name || 'Ausgewähltes Bild' }}</span>
|
|
<span>{{ image?.id }}</span>
|
|
</div>
|
|
</figure>
|
|
|
|
<div class="flex w-full flex-col gap-6 p-6 lg:w-[360px]">
|
|
<div class="flex items-start justify-between gap-4">
|
|
<div>
|
|
<p class="text-xs uppercase tracking-[0.4em] text-slate-400">Menü</p>
|
|
<h2 class="mt-1 text-2xl font-semibold leading-tight">{{ imageLabel }}</h2>
|
|
<p class="text-sm text-slate-500 dark:text-slate-400 truncate">
|
|
{{ image?.path }}
|
|
</p>
|
|
</div>
|
|
<button
|
|
type="button"
|
|
class="rounded-full border border-white/20 bg-white/10 p-2 text-slate-900 shadow-sm transition hover:border-rose-400 hover:text-rose-400 focus:outline-none focus-visible:ring-2 focus-visible:ring-rose-400 dark:text-white"
|
|
@click="$emit('close')"
|
|
aria-label="Kontextmenü schließen"
|
|
>
|
|
<svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="m6 6 12 12M6 18 18 6" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<div v-if="!showStyleSelectorView" class="space-y-3">
|
|
<button
|
|
type="button"
|
|
class="flex w-full items-center justify-between gap-3 rounded-2xl border border-white/20 bg-white/40 px-4 py-3 text-left font-semibold text-slate-900 transition hover:border-emerald-400 hover:bg-white/70 focus:outline-none focus-visible:ring-2 focus-visible:ring-emerald-400 dark:border-white/10 dark:bg-white/5 dark:text-white"
|
|
@click="showStyleSelectorView = true"
|
|
>
|
|
<div>
|
|
<p class="text-base">Stile anzeigen</p>
|
|
<p class="text-sm font-normal text-slate-500 dark:text-slate-400">Lass die KI dein Motiv verzaubern.</p>
|
|
</div>
|
|
<span class="flex h-12 w-12 items-center justify-center rounded-full bg-white/60 text-slate-900 shadow-md dark:bg-slate-800/70 dark:text-white">
|
|
<svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 3v3m0 12v3m9-9h-3M6 12H3m13.5-6 1.5 1.5M7.5 18 6 19.5M18 7.5 19.5 6M6 4.5 4.5 6m9.75 3.75-2.122 2.122a2.25 2.25 0 0 0 0 3.182l2.122 2.121a2.25 2.25 0 0 0 3.182 0l2.121-2.121a2.25 2.25 0 0 0 0-3.182l-2.121-2.122a2.25 2.25 0 0 0-3.182 0Z" />
|
|
</svg>
|
|
</span>
|
|
</button>
|
|
|
|
<button
|
|
v-if="showPrintButton"
|
|
type="button"
|
|
class="flex w-full items-center justify-between gap-3 rounded-2xl border border-white/10 bg-slate-900/5 px-4 py-3 text-left font-semibold text-slate-900 transition hover:border-cyan-300 hover:bg-cyan-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-cyan-300 dark:border-white/10 dark:bg-white/5 dark:text-white"
|
|
@click="$emit('print', image)"
|
|
>
|
|
<div>
|
|
<p class="text-base">Drucken</p>
|
|
<p class="text-sm font-normal text-slate-500 dark:text-slate-400">Sofort den Druckdialog öffnen</p>
|
|
</div>
|
|
<span class="flex h-12 w-12 items-center justify-center rounded-full bg-cyan-100 text-cyan-900 shadow-md dark:bg-cyan-400/20 dark:text-cyan-200">
|
|
<svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 9V4.5A1.5 1.5 0 0 1 7.5 3h9A1.5 1.5 0 0 1 18 4.5V9m-12 0h12m-12 0H4.5A1.5 1.5 0 0 0 3 10.5v6A1.5 1.5 0 0 0 4.5 18H6m12-9h1.5A1.5 1.5 0 0 1 21 10.5v6a1.5 1.5 0 0 1-1.5 1.5H18m-12 0v4.5A1.5 1.5 0 0 0 7.5 24h9a1.5 1.5 0 0 0 1.5-1.5V18m-12 0h12" />
|
|
</svg>
|
|
</span>
|
|
</button>
|
|
|
|
<button
|
|
v-if="shouldShowDownload"
|
|
type="button"
|
|
class="flex w-full items-center justify-between gap-3 rounded-2xl border border-white/10 bg-slate-900/5 px-4 py-3 text-left font-semibold text-slate-900 transition hover:border-indigo-300 hover:bg-indigo-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-300 dark:border-white/10 dark:bg-white/5 dark:text-white"
|
|
@click="$emit('download', image)"
|
|
>
|
|
<div>
|
|
<p class="text-base">Herunterladen</p>
|
|
<p class="text-sm font-normal text-slate-500 dark:text-slate-400">Datei lokal speichern</p>
|
|
</div>
|
|
<span class="flex h-12 w-12 items-center justify-center rounded-full bg-indigo-100 text-indigo-900 shadow-md dark:bg-indigo-400/20 dark:text-indigo-200">
|
|
<svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 3v12m0 0 4-4m-4 4-4-4m-5 7.5h18" />
|
|
</svg>
|
|
</span>
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
class="flex w-full items-center justify-between gap-3 rounded-2xl border border-white/10 bg-white/0 px-4 py-3 text-left font-semibold text-slate-900 transition hover:border-rose-300 hover:bg-rose-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-rose-300 dark:border-white/10 dark:bg-white/5 dark:text-white"
|
|
@click="$emit('close')"
|
|
>
|
|
<div>
|
|
<p class="text-base">Schließen</p>
|
|
<p class="text-sm font-normal text-slate-500 dark:text-slate-400">Zurück zur Galerie</p>
|
|
</div>
|
|
<span class="flex h-12 w-12 items-center justify-center rounded-full bg-rose-100 text-rose-900 shadow-md dark:bg-rose-400/20 dark:text-rose-200">
|
|
<svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
|
|
</svg>
|
|
</span>
|
|
</button>
|
|
</div>
|
|
|
|
<div v-else class="space-y-4">
|
|
<div class="flex items-center justify-between text-sm text-slate-400">
|
|
<button
|
|
type="button"
|
|
class="inline-flex items-center gap-2 rounded-full border border-white/20 px-3 py-1 text-xs uppercase tracking-[0.3em] text-white/80 transition hover:border-emerald-300"
|
|
@click="showStyleSelectorView = false"
|
|
>
|
|
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="m10 19-7-7 7-7m-7 7h18" />
|
|
</svg>
|
|
Zurück
|
|
</button>
|
|
<span>Stilauswahl</span>
|
|
</div>
|
|
<StyleSelector
|
|
class="max-h-[520px] flex-1"
|
|
:image_id="image?.id ?? image?.image_id"
|
|
@styleSelected="handleStyleSelected"
|
|
@close="$emit('close')"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed, ref, watch } from 'vue';
|
|
import { usePage } from '@inertiajs/vue3';
|
|
import StyleSelector from './StyleSelector.vue';
|
|
|
|
const page = usePage();
|
|
|
|
const props = defineProps({
|
|
image: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
});
|
|
|
|
const emits = defineEmits(['close', 'print', 'styleSelected', 'download']);
|
|
|
|
const settings = computed(() => page.props.settings || {});
|
|
const showPrintButton = computed(() => settings.value.show_print_button ?? true);
|
|
|
|
const shouldShowDownload = computed(() => {
|
|
const hostname = window.location.hostname;
|
|
return hostname !== 'localhost' &&
|
|
hostname !== '127.0.0.1' &&
|
|
!hostname.startsWith('192.168.') &&
|
|
!hostname.startsWith('10.') &&
|
|
!hostname.startsWith('172.');
|
|
});
|
|
|
|
const showStyleSelectorView = ref(false);
|
|
|
|
watch(
|
|
() => props.image,
|
|
() => {
|
|
showStyleSelectorView.value = false;
|
|
}
|
|
);
|
|
|
|
const imageLabel = computed(() => props.image?.name || 'Ausgewähltes Bild');
|
|
|
|
const handleStyleSelected = (style, imageId) => {
|
|
showStyleSelectorView.value = false;
|
|
emits('styleSelected', style, imageId);
|
|
};
|
|
</script>
|