Files
thetool/Layout/default/VueViews/WarehouseLoginOverride.php
2025-08-05 12:15:16 +00:00

123 lines
6.0 KiB
PHP

<!DOCTYPE html>
<html lang="de" class="h-full">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Lager-System Login</title>
<meta name="theme-color" content="#0055FF"/>
<link rel="manifest" href="/assets/pwa/shipping-note-tablet-manifest.json">
<script src="https://cdn.jsdelivr.net/npm/vue@3.4.27/dist/vue.global.min.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<script>
window.WAREHOUSE_CONFIG = { userOptions: <?= json_encode($userOptions) ?> };
tailwind.config = {
theme: { extend: { colors: { 'brand-blue': '#0055FF' } } }
};
</script>
<style>
body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
.user-list-container::-webkit-scrollbar { width: 5px; }
.user-list-container::-webkit-scrollbar-track { background: #f1f5f9; }
.user-list-container::-webkit-scrollbar-thumb { background: #a8b2c1; border-radius: 10px; }
.list-move, .list-enter-active, .list-leave-active { transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1); }
.list-enter-from, .list-leave-to { opacity: 0; transform: scale(0.95); }
.list-leave-active { position: absolute !important; }
.container-enter-active { transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1); }
.container-enter-from { opacity: 0; transform: translateY(20px); }
</style>
</head>
<body class="bg-slate-100 flex items-center justify-center min-h-full font-sans p-4">
<div id="app" class="w-full max-w-lg mx-auto"></div>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => navigator.serviceWorker.register('/assets/pwa/shipping-note-tablet-sw.js'));
}
const {createApp, ref, computed, onMounted} = Vue;
createApp({
setup() {
const excludedNames = ['cli', 'spitzer', 'test'];
const initialUsers = window.WAREHOUSE_CONFIG.userOptions.filter(user => {
const nameLower = user.text.toLowerCase();
return !excludedNames.some(ex => nameLower.includes(ex));
});
const selectedLetter = ref('All');
const selectedUserId = ref(null);
const isMounted = ref(false);
onMounted(() => isMounted.value = true);
const availableLetters = computed(() => {
const letters = new Set(initialUsers.map(u => u.text[0].toUpperCase()));
return ['All', ...Array.from(letters).sort()];
});
const filteredUsers = computed(() => {
if (selectedLetter.value === 'All') return initialUsers;
return initialUsers.filter(u => u.text.startsWith(selectedLetter.value));
});
function selectUser(userId) {
selectedUserId.value = userId;
}
return { isMounted, availableLetters, selectedLetter, filteredUsers, selectedUserId, selectUser };
},
template: `
<Transition name="container" appear>
<div v-if="isMounted" class="bg-white p-6 sm:p-8 rounded-2xl shadow-2xl shadow-slate-300/60 w-full text-center">
<header class="mb-6">
<img src="/assets/images/xinon-full.png" alt="Logo" class="h-12 w-auto mx-auto mb-4">
<h1 class="text-3xl sm:text-4xl font-bold text-slate-800 tracking-tight">Lager-System</h1>
</header>
<main>
<form action="/WarehouseShippingNote" method="POST">
<input type="hidden" name="wantedUserId" :value="selectedUserId"/>
<div class="mb-5 p-1.5 bg-slate-100 rounded-xl flex flex-wrap justify-center gap-1.5">
<button v-for="letter in availableLetters" :key="letter" type="button"
@click="selectedLetter = letter; selectedUserId = null;"
class="w-12 h-12 rounded-lg text-base font-bold transition-all duration-300"
:class="selectedLetter === letter ? 'bg-brand-blue text-white shadow' : 'bg-transparent text-slate-500 hover:bg-slate-200'">
{{ letter === 'All' ? 'Alle' : letter }}
</button>
</div>
<div class="user-list-container max-h-[35vh] min-h-[150px] overflow-y-auto relative p-1.5">
<TransitionGroup name="list" tag="div" class="relative overflow-x-hidden">
<button v-for="(user, index) in filteredUsers" :key="user.value" type="button"
@click="selectUser(user.value)"
class="w-full text-left p-4 rounded-xl transition-all duration-200 ease-in-out mb-2 last:mb-0"
:style="{ 'transition-delay': (index * 15) + 'ms' }"
:class="selectedUserId === user.value ? 'bg-brand-blue text-white shadow-lg' : 'bg-slate-50 hover:bg-slate-200 text-slate-700'">
<span class="text-lg font-medium">{{ user.text }}</span>
</button>
</TransitionGroup>
<div v-if="!filteredUsers.length" class="text-center text-slate-400 pt-10">
<p>Keine Mitarbeiter für diese Auswahl.</p>
</div>
</div>
<div class="mt-6">
<button type="submit" :disabled="!selectedUserId"
class="w-full text-white font-bold py-3.5 px-4 rounded-xl text-xl transition-all duration-300 bg-brand-blue hover:bg-blue-600 focus:outline-none focus:ring-4 focus:ring-blue-500/50 disabled:bg-slate-300 disabled:text-slate-500 disabled:cursor-not-allowed">
Anmelden
</button>
</div>
</form>
</main>
</div>
</Transition>
`
}).mount('#app');
</script>
</body>
</html>