language files combined, settings fixed, "new" badge integrated

This commit is contained in:
2025-08-01 23:34:41 +02:00
parent b2968f203d
commit 80873877c1
44 changed files with 1319 additions and 358 deletions

View File

@@ -8,20 +8,31 @@
@click="$emit('imageTapped', image, $event)"
>
<img :src="image.path" :alt="'Image ' + image.name" />
<div v-if="image.is_new" class="new-badge">{{ __('new') }}</div>
</div>
</div>
</div>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';
const props = defineProps({
images: {
type: Array,
required: true,
},
translations: {
type: Object,
required: true,
},
});
const emits = defineEmits(['imageTapped']);
const __ = (key) => {
return props.translations[key] || key;
};
</script>
<style scoped>
@@ -46,6 +57,7 @@ const emits = defineEmits(['imageTapped']);
overflow: hidden;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
position: relative; /* Added for badge positioning */
}
.grid-item img {
@@ -54,4 +66,17 @@ const emits = defineEmits(['imageTapped']);
object-fit: cover; /* Bilder zuschneiden, um den Bereich zu füllen */
display: block;
}
.new-badge {
position: absolute;
top: 10px;
right: 10px;
background-color: red;
color: white;
padding: 5px 10px;
border-radius: 5px;
font-size: 0.8em;
font-weight: bold;
z-index: 10;
}
</style>

View File

@@ -4,16 +4,45 @@
<div class="context-menu-image-preview">
<img :src="image.path" :alt="'Selected Image ' + image.name" />
</div>
<ul>
<li @click="$emit('print', image)">Drucken</li>
<li @click="$emit('changeStyle', image)">Stil ändern</li>
<li @click="$emit('close')">Schließen</li>
</ul>
<div class="context-menu-options">
<ul v-if="!showStyleSelectorView">
<li @click="$emit('print', image)">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-5 h-5 inline-block align-middle mr-2">
<path fill-rule="evenodd" d="M7.875 1.5C6.839 1.5 6 2.34 6 3.375v2.25a.75.75 0 0 0 1.5 0V3.375c0-.39.315-.75.75-.75h6.75c.39 0 .75.36.75.75v2.25a.75.75 0 0 0 1.5 0V3.375c0-1.036-.84-1.875-1.875-1.875H7.875Z" clip-rule="evenodd" />
<path fill-rule="evenodd" d="M19.875 9a.75.75 0 0 0-.75-.75H4.875a.75.75 0 0 0-.75.75v6.75c0 1.036.84 1.875 1.875 1.875h11.25c1.036 0 1.875-.84 1.875-1.875V9ZM12 12.75a.75.75 0 0 0 0 1.5h.007a.75.75 0 0 0 0-1.5H12Z" clip-rule="evenodd" />
<path d="M2.25 17.75a.75.75 0 0 0 0 1.5h19.5a.75.75 0 0 0 0-1.5H2.25Z" />
</svg>
Drucken
</li>
<li @click="showStyleSelectorView = true">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-5 h-5 inline-block align-middle mr-2">
<path fill-rule="evenodd" d="M10.788 3.212a.75.75 0 0 0-1.06 0L7.212 5.788a.75.75 0 0 0 0 1.06l1.59 1.59a.75.75 0 0 0 1.06 0l2.576-2.576a.75.75 0 0 0 0-1.06L10.788 3.212ZM15.75 10.5a.75.75 0 0 1 .75-.75h.75a.75.75 0 0 1 0 1.5h-.75a.75.75 0 0 1-.75-.75ZM12 12a.75.75 0 0 1 .75-.75h.75a.75.75 0 0 1 0 1.5H12a.75.75 0 0 1-.75-.75ZM18.75 10.5a.75.75 0 0 1 .75-.75h.75a.75.75 0 0 1 0 1.5h-.75a.75.75 0 0 1-.75-.75ZM12 15a.75.75 0 0 1 .75-.75h.75a.75.75 0 0 1 0 1.5H12a.75.75 0 0 1-.75-.75ZM15.75 15a.75.75 0 0 1 .75-.75h.75a.75.75 0 0 1 0 1.5h-.75a.75.75 0 0 1-.75-.75ZM18.75 15a.75.75 0 0 1 .75-.75h.75a.75.75 0 0 1 0 1.5h-.75a.75.75 0 0 1-.75-.75ZM12 18a.75.75 0 0 1 .75-.75h.75a.75.75 0 0 1 0 1.5H12a.75.75 0 0 1-.75-.75ZM15.75 18a.75.75 0 0 1 .75-.75h.75a.75.75 0 0 1 0 1.5h-.75a.75.75 0 0 1-.75-.75ZM18.75 18a.75.75 0 0 1 .75-.75h.75a.75.75 0 0 1 0 1.5h-.75a.75.75 0 0 1-.75-.75ZM12 21a.75.75 0 0 1 .75-.75h.75a.75.75 0 0 1 0 1.5H12a.75.75 0 0 1-.75-.75Z" clip-rule="evenodd" />
</svg>
Stil ändern
</li>
<li @click="$emit('close')">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-5 h-5 inline-block align-middle mr-2">
<path fill-rule="evenodd" d="M5.47 5.47a.75.75 0 0 1 1.06 0L12 10.94l5.47-5.47a.75.75 0 1 1 1.06 1.06L13.06 12l5.47 5.47a.75.75 0 1 1-1.06 1.06L12 13.06l-5.47 5.47a.75.75 0 0 1-1.06-1.06L10.94 12 5.47 6.53a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" />
</svg>
Schließen
</li>
</ul>
<StyleSelector
v-else
:image_id="image.image_id"
@styleSelected="(style, imageId) => $emit('styleSelected', style, imageId)"
@back="showStyleSelectorView = false"
@close="$emit('close')"
/>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
import StyleSelector from './StyleSelector.vue';
const props = defineProps({
position: {
type: Object,
@@ -25,7 +54,9 @@ const props = defineProps({
},
});
const emits = defineEmits(['close', 'print', 'changeStyle']);
const emits = defineEmits(['close', 'print', 'changeStyle', 'styleSelected']);
const showStyleSelectorView = ref(false);
</script>
<style scoped>
@@ -43,19 +74,19 @@ const emits = defineEmits(['close', 'print', 'changeStyle']);
}
.context-menu {
background: white;
border: 1px solid #ccc;
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.1);
background: var(--color-background);
border: 1px solid var(--color-text);
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.5);
z-index: 1000;
display: flex;
flex-direction: row; /* Bild und Menü nebeneinander */
max-width: 80%;
max-height: 80%;
max-width: 90%;
height: 80vh; /* 80% of viewport height */
overflow: hidden;
}
.context-menu-image-preview {
flex: 1; /* Nimmt den verfügbaren Platz ein */
flex: 7; /* Takes 70% of the space (7 out of 10 parts) */
display: flex;
justify-content: center;
align-items: center;
@@ -65,14 +96,21 @@ const emits = defineEmits(['close', 'print', 'changeStyle']);
.context-menu-image-preview img {
max-width: 100%;
max-height: 100%;
width: 80%; /* 80% width of its container */
object-fit: contain;
}
.context-menu-options {
flex: 3; /* Takes 30% of the space (3 out of 10 parts) */
display: flex;
flex-direction: column;
}
.context-menu ul {
list-style: none;
padding: 0;
margin: 0;
border-left: 1px solid #eee; /* Trennlinie zwischen Bild und Menü */
border-left: 1px solid var(--color-text); /* Trennlinie zwischen Bild und Menü */
min-width: 150px; /* Mindestbreite für das Menü */
}
@@ -80,7 +118,7 @@ const emits = defineEmits(['close', 'print', 'changeStyle']);
padding: 15px;
cursor: pointer;
font-size: 1.1em;
border-bottom: 1px solid #eee;
border-bottom: 1px solid var(--color-text);
}
.context-menu li:last-child {
@@ -88,6 +126,7 @@ const emits = defineEmits(['close', 'print', 'changeStyle']);
}
.context-menu li:hover {
background: #f0f0f0;
background: var(--color-text); /* Adjust hover background for dark mode */
color: var(--color-background); /* Adjust hover text color for dark mode */
}
</style>

View File

@@ -27,9 +27,10 @@ const emits = defineEmits(['prevPage', 'nextPage']);
justify-content: center;
align-items: center;
padding: 20px;
background-color: #f0f0f0;
background-color: var(--color-background);
width: 100%;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
color: var(--color-text);
}
.navigation button {
@@ -51,6 +52,6 @@ const emits = defineEmits(['prevPage', 'nextPage']);
.navigation span {
font-size: 1.2em;
font-weight: bold;
color: #333;
color: var(--color-text);
}
</style>

View File

@@ -1,22 +1,24 @@
<template>
<div class="context-menu-overlay" @click.self="$emit('close')">
<div class="style-selector" :style="{ top: `${position.y}px`, left: `${position.x}px` }">
<div class="style-selector-header">
<span class="back-arrow" @click="$emit('back')">&larr;</span>
<h3>Verfügbare Stile</h3>
</div>
<div class="styles-list">
<div
v-for="style in styles"
:key="style.id"
class="style-item"
@click="selectStyle(style)"
>
<img :src="'/storage/' + style.preview_image" :alt="style.title" class="style-thumbnail" />
<div class="style-details">
<h4>{{ style.title }}</h4>
<p>{{ style.description }}</p>
</div>
<div class="style-selector">
<div class="style-selector-header">
<span class="back-arrow" @click="$emit('back')">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-6 h-6">
<path fill-rule="evenodd" d="M11.03 4.272a.75.75 0 0 1 0 1.06L6.31 10.5H20.25a.75.75 0 0 1 0 1.5H6.31l4.72 5.168a.75.75 0 0 1-1.06 1.06l-6-6a.75.75 0 0 1 0-1.06l6-6a.75.75 0 0 1 1.06 0Z" clip-rule="evenodd" />
</svg>
</span>
<h3>Verfügbare Stile</h3>
</div>
<div class="styles-list">
<div
v-for="style in styles"
:key="style.id"
class="style-item"
@click="selectStyle(style)"
>
<img :src="'/storage/' + style.preview_image" :alt="style.title" class="style-thumbnail" />
<div class="style-details">
<h4>{{ style.title }}</h4>
<p>{{ style.description }}</p>
</div>
</div>
</div>
@@ -30,10 +32,6 @@ import { ref, onMounted } from 'vue';
const styles = ref([]);
const props = defineProps({
position: {
type: Object,
required: true,
},
image_id: {
type: Number,
required: true,
@@ -63,19 +61,6 @@ onMounted(() => {
</script>
<style scoped>
.context-menu-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5); /* Halbdurchsichtiger Hintergrund */
display: flex;
justify-content: center;
align-items: center;
z-index: 999;
}
.style-selector {
background: white;
border: 1px solid #ccc;
@@ -83,10 +68,9 @@ onMounted(() => {
z-index: 1000;
display: flex;
flex-direction: column;
max-width: 80%;
max-height: 80%;
max-width: 100%; /* Adjusted to fit parent */
max-height: 100%; /* Adjusted to fit parent */
overflow: hidden;
position: absolute; /* Positionierung innerhalb des Overlays */
}
.style-selector-header {
@@ -106,14 +90,16 @@ onMounted(() => {
.back-arrow {
position: absolute;
left: 10px;
font-size: 1.5em;
left: 5px; /* Adjusted position */
font-size: 2em; /* Slightly larger */
cursor: pointer;
padding: 5px;
padding: 10px; /* Larger clickable area */
color: var(--color-text); /* Adapt to theme */
}
.back-arrow:hover {
color: #007bff;
color: var(--color-background); /* Adjust hover color for dark mode */
background: var(--color-text); /* Adjust hover background for dark mode */
}
.styles-list {