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

@@ -1,3 +1,23 @@
@import '@fortawesome/fontawesome-svg-core/styles.css';
@tailwind base;
@tailwind components;
@tailwind utilities;
/* Theme variables */
:root {
--color-background: #ffffff;
--color-text: #000000;
}
html.dark {
--color-background: #333333; /* Dark grey */
--color-text: #ffffff;
}
/* Apply theme to body */
body {
background-color: var(--color-background);
color: var(--color-text);
transition: background-color 0.3s ease, color 0.3s ease;
}

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 {

View File

@@ -2,8 +2,13 @@
<div class="home">
<div class="main-content">
<div class="gallery-container" @touchstart="handleTouchStart" @touchend="handleTouchEnd">
<h1 class="text-2xl font-bold text-center my-4">Style Gallery</h1>
<GalleryGrid :images="paginatedImages" @imageTapped="showContextMenu" />
<h1 class="text-2xl font-bold text-center my-4">{{ props.galleryHeading }}</h1>
<div class="absolute top-4 right-4">
<button @click="toggleTheme" class="theme-toggle-button">
{{ currentTheme === 'light' ? __('api.dark_mode') : __('api.light_mode') }}
</button>
</div>
<GalleryGrid :images="paginatedImages" @imageTapped="showContextMenu" :translations="props.translations" />
<Navigation
:currentPage="currentPage"
:totalPages="totalPages"
@@ -17,18 +22,10 @@
v-if="currentOverlayComponent === 'contextMenu'"
:position="contextMenuPosition"
:image="selectedImage"
@close="currentOverlayComponent = null"
@close="currentOverlayComponent = null; selectedImage = null"
@print="printImage"
@changeStyle="showStyleSelector"
/>
<StyleSelector
v-if="currentOverlayComponent === 'styleSelector'"
:position="contextMenuPosition"
:image_id="selectedImage.image_id"
@styleSelected="applyStyle"
@back="goBackToContextMenu"
@close="currentOverlayComponent = null"
/>
<div v-if="errorMessage" class="fixed bottom-4 right-4 bg-red-500 text-white p-4 rounded-lg shadow-lg z-50">
@@ -46,38 +43,15 @@
</template>
<script setup>
import Navigation from '../Components/Navigation.vue';
import GalleryGrid from '../Components/GalleryGrid.vue';
import ImageContextMenu from '../Components/ImageContextMenu.vue';
import StyleSelector from '../Components/StyleSelector.vue';
import StyledImageDisplay from '../Components/StyledImageDisplay.vue'; // Import the new component
import LoadingSpinner from '../Components/LoadingSpinner.vue'; // Import the new component
import axios from 'axios';
import { ref, computed, onMounted, onUnmounted } from 'vue';
import { defineProps } from 'vue';
const props = defineProps({
galleryHeading: String,
translations: Object,
});
const images = ref([]);
const imagesPerPage = 12;
const currentPage = ref(1);
const currentOverlayComponent = ref(null); // null, 'contextMenu', 'styleSelector', 'styledImageDisplay'
const contextMenuPosition = ref({ x: 0, y: 0 });
const selectedImage = ref(null);
const styledImage = ref(null); // To store the newly styled image
const errorMessage = ref(null); // New ref for error messages
const isLoading = ref(false); // New ref for loading state
let fetchInterval = null;
let touchStartX = 0;
let touchEndX = 0;
const totalPages = computed(() => {
return Math.ceil(images.value.length / imagesPerPage);
});
const paginatedImages = computed(() => {
const start = (currentPage.value - 1) * imagesPerPage;
const end = start + imagesPerPage;
return images.value.slice(start, end);
});
const fetchImages = () => {
axios.get('/api/images')
@@ -90,6 +64,50 @@ const fetchImages = () => {
});
};
import Navigation from '../Components/Navigation.vue';
import GalleryGrid from '../Components/GalleryGrid.vue';
import ImageContextMenu from '../Components/ImageContextMenu.vue';
import StyleSelector from '../Components/StyleSelector.vue';
import StyledImageDisplay from '../Components/StyledImageDisplay.vue'; // Import the new component
import LoadingSpinner from '../Components/LoadingSpinner.vue'; // Import the new component
import axios from 'axios';
import { ref, computed, onMounted, onUnmounted } from 'vue';
const imagesPerPage = 12;
const currentPage = ref(1);
const currentOverlayComponent = ref(null); // null, 'contextMenu', 'styleSelector', 'styledImageDisplay'
const contextMenuPosition = ref({ x: 0, y: 0 });
const selectedImage = ref(null);
const styledImage = ref(null); // To store the newly styled image
const errorMessage = ref(null); // New ref for error messages
const isLoading = ref(false); // New ref for loading state
const currentTheme = ref('light'); // New ref for current theme
let touchStartX = 0;
let touchEndX = 0;
const applyTheme = (theme) => {
document.documentElement.classList.remove('light', 'dark');
document.documentElement.classList.add(theme);
localStorage.setItem('theme', theme);
currentTheme.value = theme;
};
const toggleTheme = () => {
const newTheme = currentTheme.value === 'light' ? 'dark' : 'light';
applyTheme(newTheme);
};
const totalPages = computed(() => {
return Math.ceil(images.value.length / imagesPerPage);
});
const paginatedImages = computed(() => {
const start = (currentPage.value - 1) * imagesPerPage;
const end = start + imagesPerPage;
return images.value.slice(start, end);
});
const showError = (message) => {
errorMessage.value = message;
setTimeout(() => {
@@ -142,8 +160,6 @@ const applyStyle = (style, imageId) => {
const keepStyledImage = (imageToKeep) => {
console.log('Keeping styled image:', imageToKeep);
// Implement API call to mark image as kept/permanent if needed
// For now, just refresh the image list to show the new image
fetchImages();
currentOverlayComponent.value = null; // Close the display
};
@@ -186,6 +202,16 @@ const handleSwipeGesture = () => {
};
onMounted(() => {
// Apply theme from localStorage on mount
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
applyTheme(savedTheme);
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
applyTheme('dark');
} else {
applyTheme('light');
}
fetchImages();
fetchInterval = setInterval(fetchImages, 5000);
});
@@ -216,4 +242,35 @@ onUnmounted(() => {
align-items: center;
padding: 20px;
}
.theme-toggle-button {
margin-top: 10px;
padding: 8px 15px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 0.9em;
}
.theme-toggle-button:hover {
background-color: #0056b3;
}
.image-visibility-toggle-button {
margin-top: 10px;
padding: 8px 15px;
background-color: #28a745;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 0.9em;
margin-left: 10px;
}
.image-visibility-toggle-button:hover {
background-color: #218838;
}
</style>

View File

@@ -6,15 +6,25 @@ import { createInertiaApp } from '@inertiajs/vue3';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { ZiggyVue } from '../../vendor/tightenco/ziggy';
/* Font Awesome imports */
import { library } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import { faPrint, faMagicWandSparkles, faXmark } from '@fortawesome/free-solid-svg-icons';
// Add icons to the library
library.add(faPrint, faMagicWandSparkles, faXmark);
const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
setup({ el, App, props, plugin }) {
console.log('Inertia Page Props (app.js):', props.initialPage.props);
return createApp({ render: () => h(App, props) })
.use(plugin)
.use(ZiggyVue)
.component('font-awesome-icon', FontAwesomeIcon) // Register Font Awesome component
.mixin({
methods: {
__: (key, replace = {}) => {

View File

@@ -0,0 +1,83 @@
document.addEventListener('DOMContentLoaded', () => {
const navigation = document.querySelector('.fi-main-nav');
if (!navigation) return;
const KEY = 'navigation_state';
const TABLE_PAGES_KEY = 'table_pages_state';
// Function to get the state from session via a custom endpoint
const getState = () => {
return JSON.parse(sessionStorage.getItem(KEY)) || {};
};
// Function to save the state to session via a custom endpoint
const saveState = (state) => {
sessionStorage.setItem(KEY, JSON.stringify(state));
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
fetch('/api/admin/navigation-state', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': csrfToken,
},
body: JSON.stringify({ groups: state }),
});
};
// Function to get table page state
const getTablePageState = () => {
return JSON.parse(sessionStorage.getItem(TABLE_PAGES_KEY)) || {};
};
// Function to save table page state
const saveTablePageState = (tableId, page) => {
let tablePages = getTablePageState();
tablePages[tableId] = page;
sessionStorage.setItem(TABLE_PAGES_KEY, JSON.stringify(tablePages));
};
let currentState = getState();
let currentTablePages = getTablePageState();
// Apply the saved navigation state on page load
const groups = navigation.querySelectorAll('.fi-nav-group');
groups.forEach(group => {
const label = group.querySelector('.fi-nav-group-label').textContent.trim();
if (currentState[label] === 'collapsed') {
group.classList.add('collapsed');
}
});
// Add event listeners to save navigation state on click
navigation.addEventListener('click', (e) => {
const labelElement = e.target.closest('.fi-nav-group-label');
if (!labelElement) return;
const group = labelElement.closest('.fi-nav-group');
const label = labelElement.textContent.trim();
if (group.classList.contains('collapsed')) {
currentState[label] = 'expanded';
group.classList.remove('collapsed');
} else {
currentState[label] = 'collapsed';
group.classList.add('collapsed');
}
saveState(currentState);
});
// Livewire hook to save table page when pagination changes
Livewire.hook('component.initialized', (component) => {
if (component.name.includes('table')) {
const tableId = component.el.id;
if (currentTablePages[tableId]) {
component.set('tablePage', currentTablePages[tableId], false);
}
}
});
Livewire.on('table-pagination-updated', (tableId, page) => {
saveTablePageState(tableId, page);
});
});

View File

@@ -8,4 +8,10 @@ return [
'image_deleted_successfully' => 'Bild erfolgreich gelöscht.',
'image_or_provider_not_found' => 'Bild oder API-Anbieter nicht gefunden.',
'no_styles_available' => 'Keine Stile oder API-Anbieter aktiviert/verfügbar.',
'api.dark_mode' => 'Dunkler Modus',
'api.light_mode' => 'Heller Modus',
'gallery_title' => 'Eure Bilder aus der Fotobox',
'navigation.previous' => 'Zurück',
'navigation.next' => 'Weiter',
'navigation.page_of' => 'Seite :currentPage von :totalPages',
];

View File

@@ -1,11 +0,0 @@
<?php
return [
'gallery_title' => 'Eure Bilder aus der Fotobox',
'api.image_uploaded_successfully' => 'Bild erfolgreich hochgeladen',
'api.style_or_provider_not_found' => 'Stil oder API-Anbieter nicht gefunden',
'api.image_or_provider_not_found' => 'Bild oder API-Anbieter nicht gefunden',
'navigation.previous' => 'Zurück',
'navigation.next' => 'Weiter',
'navigation.page_of' => 'Seite :currentPage von :totalPages',
];

View File

@@ -1,7 +1,8 @@
<?php
return [
'gallery_heading' => 'Galerie Überschrift',
'saved_successfully' => 'Einstellungen erfolgreich gespeichert.',
'save_button' => 'Speichern',
'new' => 'Neu',
];

View File

@@ -8,4 +8,10 @@ return [
'image_deleted_successfully' => 'Image deleted successfully.',
'image_or_provider_not_found' => 'Image or API provider not found.',
'no_styles_available' => 'No styles or API providers enabled/available.',
'dark_mode' => 'Dark Mode',
'light_mode' => 'Light Mode',
'gallery_title' => 'Your images from the photobooth',
'navigation.previous' => 'Previous',
'navigation.next' => 'Next',
'navigation.page_of' => 'Page :currentPage of :totalPages',
];

View File

@@ -1,11 +0,0 @@
<?php
return [
'gallery_title' => 'Your images from the photobooth',
'api.image_uploaded_successfully' => 'Image uploaded successfully',
'api.style_or_provider_not_found' => 'Style or API Provider not found',
'api.image_or_provider_not_found' => 'Image or API Provider not found',
'navigation.previous' => 'Previous',
'navigation.next' => 'Next',
'navigation.page_of' => 'Page :currentPage of :totalPages',
];

View File

@@ -1,7 +1,8 @@
<?php
return [
'gallery_heading' => 'Gallery Heading',
'saved_successfully' => 'Settings saved successfully.',
'save_button' => 'Save',
'new' => 'New',
];