Projektarbeit-MYP/backend/templates/kiosk-base-optimized.html
2025-06-01 23:41:02 +02:00

239 lines
9.7 KiB
HTML

<!DOCTYPE html>
<html lang="de" class="h-full">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Kiosk-spezifische Meta-Tags -->
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="format-detection" content="telephone=no">
<title>{% block title %}MYP Druckerverwaltung{% endblock %}</title>
<!-- Critical CSS inline für sofortiges Rendering -->
<style>
/* CRITICAL INLINE CSS - Füge hier den Inhalt von critical-inline.css ein */
:root{--primary:#0073ce;--bg:#fafbfc;--surface:#fff;--text:#111827;--border:#e5e7eb;--shadow:0 2px 4px rgba(0,0,0,.05)}
*{box-sizing:border-box;margin:0;padding:0;contain:layout style}
body{font-family:system-ui,-apple-system,sans-serif;background:var(--bg);color:var(--text);line-height:1.5;text-rendering:optimizeSpeed;-webkit-font-smoothing:antialiased}
.header{background:var(--surface);border-bottom:1px solid var(--border);padding:1rem;position:sticky;top:0;z-index:1000}
.nav{display:flex;gap:1rem}
.nav-item{padding:.5rem 1rem;border-radius:6px;text-decoration:none;color:#6b7280;transition:background .1s}
.nav-item:hover{background:var(--bg);color:var(--text)}
.nav-item.active{background:var(--primary);color:#fff}
.container{max-width:1200px;margin:0 auto;padding:0 1rem}
.btn{background:var(--primary);color:#fff;border:none;border-radius:6px;padding:.75rem 1.5rem;font-weight:600;cursor:pointer;transition:background .1s}
.btn:hover{background:#005a9f}
.card{background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:1rem;box-shadow:var(--shadow)}
.flex{display:flex}
.grid{display:grid;gap:1rem}
.hidden{display:none}
.w-full{width:100%}
.text-center{text-align:center}
.p-4{padding:1rem}
.mb-4{margin-bottom:1rem}
.status{display:inline-block;padding:.25rem .75rem;border-radius:999px;font-size:.75rem;font-weight:600;text-transform:uppercase}
.status-online{background:#d1fae5;color:#065f46}
.status-offline{background:#fee2e2;color:#991b1b}
.status-printing{background:#dbeafe;color:#1e40af}
.input{background:var(--surface);border:1px solid var(--border);border-radius:6px;padding:.75rem;width:100%}
.input:focus{outline:none;border-color:var(--primary)}
@media (prefers-color-scheme:dark){:root{--bg:#1e293b;--surface:#334155;--text:#f8fafc;--border:#475569;--shadow:0 2px 4px rgba(0,0,0,.3)}}
@media (max-width:768px){.nav{flex-direction:column;gap:.5rem}}
@media (prefers-reduced-motion:reduce){*{transition:none!important}}
</style>
<!-- Kiosk-spezifische Optimierungen -->
<style>
/* Kiosk-spezifische Styles für bessere Performance */
* {
/* Deaktiviere Touch-Events für Kiosk */
touch-action: none;
-webkit-touch-callout: none;
-webkit-user-select: none;
user-select: none;
}
/* Nur Inputs sollen selektierbar sein */
input, textarea, [contenteditable] {
-webkit-user-select: text;
user-select: text;
touch-action: manipulation;
}
/* Verhindere Zoom bei Double-Tap */
* {
-webkit-touch-callout: none;
-webkit-tap-highlight-color: transparent;
}
/* Optimiere für Vollbild-Kiosk */
html, body {
height: 100%;
overflow-x: hidden;
}
/* Vereinfachte Fokus-Styles für Keyboard-Navigation */
:focus-visible {
outline: 2px solid var(--primary);
outline-offset: 2px;
}
/* Loading-State für bessere UX */
.loading-skeleton {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: skeleton 1.5s infinite;
}
@keyframes skeleton {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
</style>
<!-- DNS-Prefetch für lokale Ressourcen (falls nötig) -->
<link rel="dns-prefetch" href="//localhost">
<!-- Resource Hints für bessere Performance -->
<link rel="preload" href="/static/css/build/kiosk-production.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<!-- Fallback CSS falls Preload fehlschlägt -->
<noscript>
<link rel="stylesheet" href="/static/css/build/kiosk-production.css">
</noscript>
<!-- Favicon für Kiosk-Modus -->
<link rel="icon" type="image/svg+xml" href="/static/icons/favicon.svg">
<link rel="icon" type="image/png" href="/static/icons/favicon-32x32.png">
{% block extra_head %}{% endblock %}
</head>
<body class="h-full bg-gray-50">
<!-- Loading-Overlay für bessere UX -->
<div id="loading-overlay" class="fixed inset-0 bg-white z-50 flex items-center justify-center" style="display: none;">
<div class="text-center">
<div class="loading-skeleton w-16 h-16 rounded-full mb-4 mx-auto"></div>
<p class="text-gray-600">Lädt...</p>
</div>
</div>
<!-- Haupt-Layout -->
<div class="h-full flex flex-col">
<!-- Header -->
<header class="header">
<div class="container">
<nav class="nav">
<a href="/" class="nav-item {% if request.endpoint == 'dashboard' %}active{% endif %}">
<span class="icon icon-dashboard mr-2"></span>
Dashboard
</a>
<a href="/printers" class="nav-item {% if request.endpoint == 'printers' %}active{% endif %}">
<span class="icon icon-printer mr-2"></span>
Drucker
</a>
<a href="/jobs" class="nav-item {% if request.endpoint == 'jobs' %}active{% endif %}">
<span class="icon icon-queue mr-2"></span>
Jobs
</a>
<a href="/users" class="nav-item {% if request.endpoint == 'users' %}active{% endif %}">
<span class="icon icon-users mr-2"></span>
Benutzer
</a>
<a href="/settings" class="nav-item {% if request.endpoint == 'settings' %}active{% endif %}">
<span class="icon icon-settings mr-2"></span>
Einstellungen
</a>
</nav>
</div>
</header>
<!-- Main Content -->
<main class="flex-1 container py-6">
{% block content %}{% endblock %}
</main>
<!-- Footer (optional) -->
{% block footer %}
<footer class="border-t border-gray-200 py-4">
<div class="container text-center text-sm text-gray-500">
MYP Druckerverwaltung - Kiosk-Modus
</div>
</footer>
{% endblock %}
</div>
<!-- JavaScript für optimale Performance -->
<script>
// Minimales JavaScript für Kiosk-Performance
// Entferne Loading-Overlay nach DOM-Ready
document.addEventListener('DOMContentLoaded', function() {
const overlay = document.getElementById('loading-overlay');
if (overlay) {
overlay.style.display = 'none';
}
});
// Deaktiviere Right-Click-Menü für Kiosk
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
return false;
});
// Deaktiviere F12, Ctrl+Shift+I etc. für Kiosk
document.addEventListener('keydown', function(e) {
if (
e.key === 'F12' ||
(e.ctrlKey && e.shiftKey && (e.key === 'I' || e.key === 'C' || e.key === 'J')) ||
(e.ctrlKey && e.key === 'U')
) {
e.preventDefault();
return false;
}
});
// Verhindere Zoom via Keyboard
document.addEventListener('keydown', function(e) {
if ((e.ctrlKey || e.metaKey) && (e.key === '+' || e.key === '-' || e.key === '0')) {
e.preventDefault();
return false;
}
});
// Optimiertes Form-Handling für bessere UX
document.addEventListener('submit', function(e) {
const form = e.target;
if (form.tagName === 'FORM') {
// Zeige Loading-State
const submitBtn = form.querySelector('button[type="submit"]');
if (submitBtn) {
submitBtn.disabled = true;
submitBtn.innerHTML = '<span class="icon icon-refresh mr-2"></span>Lädt...';
}
}
});
// Einfache Error-Handling für bessere UX
window.addEventListener('error', function(e) {
console.warn('Fehler abgefangen:', e.error);
// Könnte hier eine einfache Fehler-Benachrichtigung zeigen
});
// Memory-Management für lange Kiosk-Sessions
if ('requestIdleCallback' in window) {
requestIdleCallback(function() {
// Cleanup ungenutzter Ressourcen in Idle-Zeit
if (typeof gc === 'function') {
gc(); // Falls verfügbar
}
});
}
</script>
{% block extra_js %}{% endblock %}
</body>
</html>