123 lines
6.0 KiB
PHP
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>
|