Fortsetzen
{{ lastWorkflow?.module }} › {{ lastWorkflow.submodule }}
import { authState, checkAuth, login, logout } from '/mobile/shared/auth.js'; import LoginScreen from '/mobile/components/LoginScreen.js'; import MainMenu from '/mobile/components/MainMenu.js'; import LagerModule from '/mobile/modules/lager/LagerModule.js'; import ShippingNoteModule from '/mobile/modules/lager/shippingnote/ShippingNoteModule.js'; import WorkorderModule from '/mobile/modules/workorder/WorkorderModule.js'; const { createApp, ref, computed, onMounted, onUnmounted, watch } = Vue; const isPWAInstalled = () => { if (window.matchMedia('(display-mode: standalone)').matches) return true; if (window.navigator.standalone === true) return true; if (document.referrer.includes('android-app://')) return true; return false; }; const shouldRequirePWA = () => { return window.location.hostname === 'thetool.xinon.at'; }; const parseInitialRoute = () => { const initialPath = window.TT_CONFIG?.INITIAL_PATH || '/MobileApp'; const parts = initialPath.replace('/MobileApp', '').split('/').filter(Boolean); return { module: parts[0] || null, submodule: parts[1] || null }; }; const App = { components: { LoginScreen, MainMenu, LagerModule, ShippingNoteModule, WorkorderModule }, setup() { const currentView = ref('loading'); const user = ref(null); const toast = ref({ show: false, message: '', type: 'success' }); const theme = ref('system'); const showSettings = ref(false); const lagerSimpleMode = ref(false); const currentModule = ref(null); const currentSubmodule = ref(null); const lastWorkflow = ref(null); const showContinuePrompt = ref(false); const showInstallPrompt = ref(false); const deferredInstallPrompt = ref(null); const isIOS = ref(/iPad|iPhone|iPod/.test(navigator.userAgent)); const isAndroid = ref(/Android/.test(navigator.userAgent)); const canGoBack = computed(() => currentModule.value !== null || workorderDetailOpen.value); const workorderDetailOpen = ref(false); const workorderRef = ref(null); const applyTheme = () => { const isDark = localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches); document.documentElement.classList.toggle('dark', isDark); const metaThemeColor = document.querySelector('meta[name="theme-color"]'); if (metaThemeColor) { metaThemeColor.setAttribute('content', isDark ? '#0f172a' : '#005384'); } }; const setTheme = (newTheme) => { theme.value = newTheme; if (newTheme === 'system') { localStorage.removeItem('theme'); } else { localStorage.setItem('theme', newTheme); } applyTheme(); }; const handleInstallPrompt = (e) => { e.preventDefault(); deferredInstallPrompt.value = e; }; const triggerInstall = async () => { if (!deferredInstallPrompt.value) return; deferredInstallPrompt.value.prompt(); const { outcome } = await deferredInstallPrompt.value.userChoice; if (outcome === 'accepted') { showInstallPrompt.value = false; window.location.reload(); } deferredInstallPrompt.value = null; }; const loadLagerSettings = () => { try { const saved = localStorage.getItem('movement_settings'); if (saved) { const settings = JSON.parse(saved); lagerSimpleMode.value = settings.simpleMode || false; } } catch (e) {} }; const setLagerSimpleMode = (value) => { lagerSimpleMode.value = value; try { const saved = localStorage.getItem('movement_settings'); const settings = saved ? JSON.parse(saved) : {}; settings.simpleMode = value; localStorage.setItem('movement_settings', JSON.stringify(settings)); } catch (e) {} }; const saveLastWorkflow = (module, submodule) => { if (module) { const workflow = { module, submodule: submodule || null, timestamp: Date.now() }; localStorage.setItem('lastWorkflow', JSON.stringify(workflow)); lastWorkflow.value = workflow; } }; const loadLastWorkflow = () => { try { const saved = localStorage.getItem('lastWorkflow'); if (saved) { const workflow = JSON.parse(saved); if (Date.now() - workflow.timestamp < 24 * 60 * 60 * 1000) { return workflow; } } } catch (e) {} return null; }; const navigate = (module, submodule = null) => { currentModule.value = module; currentSubmodule.value = submodule; showContinuePrompt.value = false; saveLastWorkflow(module, submodule); let path = '/MobileApp'; if (module) path += '/' + module; if (submodule) path += '/' + submodule; history.pushState({ module, submodule }, '', path); }; const continueLastWorkflow = () => { if (lastWorkflow.value) { navigate(lastWorkflow.value.module, lastWorkflow.value.submodule); } }; const dismissContinuePrompt = () => { showContinuePrompt.value = false; }; const goHome = () => { navigate(null, null); }; const goBack = () => { if (workorderDetailOpen.value && workorderRef.value?.closeDetail) { workorderRef.value.closeDetail(); return; } if (currentSubmodule.value) { navigate(currentModule.value, null); } else if (currentModule.value) { navigate(null, null); } }; const handleWorkorderDetailOpen = (workorderId) => { workorderDetailOpen.value = true; }; const handleWorkorderDetailClose = () => { workorderDetailOpen.value = false; }; const handlePopstate = (event) => { if (workorderDetailOpen.value && workorderRef.value?.closeDetail) { workorderRef.value.closeDetail(); return; } if (event.state) { currentModule.value = event.state.module; currentSubmodule.value = event.state.submodule; } else { currentModule.value = null; currentSubmodule.value = null; } }; const handleLogin = async (credentials) => { if (credentials._2faSuccess) { user.value = credentials.user; currentView.value = 'app'; showToast('Erfolgreich angemeldet', 'success'); return { success: true }; } const result = await login(credentials); if (result.success) { user.value = result.user; currentView.value = 'app'; showToast('Erfolgreich angemeldet', 'success'); } return result; }; const handleLogout = async () => { await logout(); user.value = null; currentModule.value = null; currentSubmodule.value = null; currentView.value = 'login'; showToast('Abgemeldet', 'success'); }; const showToast = (message, type = 'success') => { toast.value = { show: true, message, type }; setTimeout(() => { toast.value.show = false; }, 3000); }; const currentComponent = computed(() => { if (currentView.value !== 'app') return null; if (!currentModule.value) return 'MainMenu'; if (currentModule.value.toLowerCase() === 'lieferschein') return 'ShippingNoteModule'; if (currentModule.value.toLowerCase() === 'lager') return 'LagerModule'; if (currentModule.value.toLowerCase() === 'workorder') return 'WorkorderModule'; return 'MainMenu'; }); const breadcrumbs = computed(() => { const crumbs = [{ label: 'Home', module: null, submodule: null }]; if (currentModule.value) { crumbs.push({ label: currentModule.value, module: currentModule.value, submodule: null }); } if (currentSubmodule.value) { crumbs.push({ label: currentSubmodule.value, module: currentModule.value, submodule: currentSubmodule.value }); } return crumbs; }); const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); onMounted(async () => { const savedTheme = localStorage.getItem('theme'); if (savedTheme) theme.value = savedTheme; applyTheme(); mediaQuery.addEventListener('change', applyTheme); window.addEventListener('popstate', handlePopstate); window.addEventListener('beforeinstallprompt', handleInstallPrompt); loadLagerSettings(); if (shouldRequirePWA() && !isPWAInstalled()) { showInstallPrompt.value = true; currentView.value = 'install'; return; } const result = await checkAuth(); if (result.authenticated) { user.value = result.user; currentView.value = 'app'; const initialRoute = parseInitialRoute(); currentModule.value = initialRoute.module; currentSubmodule.value = initialRoute.submodule; history.replaceState( { module: initialRoute.module, submodule: initialRoute.submodule }, '', window.location.pathname ); if (!initialRoute.module && !initialRoute.submodule) { const saved = loadLastWorkflow(); if (saved) { lastWorkflow.value = saved; showContinuePrompt.value = true; } } } else { currentView.value = 'login'; } }); onUnmounted(() => { mediaQuery.removeEventListener('change', applyTheme); window.removeEventListener('popstate', handlePopstate); window.removeEventListener('beforeinstallprompt', handleInstallPrompt); }); return { currentView, user, toast, theme, showSettings, currentModule, currentSubmodule, currentComponent, canGoBack, breadcrumbs, handleLogin, handleLogout, navigate, goHome, goBack, showToast, setTheme, lagerSimpleMode, setLagerSimpleMode, showInstallPrompt, deferredInstallPrompt, isIOS, isAndroid, triggerInstall, lastWorkflow, showContinuePrompt, continueLastWorkflow, dismissContinuePrompt, workorderRef, handleWorkorderDetailOpen, handleWorkorderDetailClose, }; }, template: `
Für die beste Erfahrung installiere die App auf deinem Gerät.
So installierst du die App:
So installierst du die App:
Hinweis: Diese App ist für mobile Geräte optimiert. Bitte öffne diese Seite auf deinem Smartphone und installiere die App.
powered by XINON
Fortsetzen
{{ lastWorkflow?.module }} › {{ lastWorkflow.submodule }}
{{ user?.name }}
{{ user?.username }}
Farbschema
Lager
Simpel Modus
Weniger Optionen