mirror of
https://github.com/s-frick/effigenix.git
synced 2026-03-28 15:19:35 +01:00
908 lines
54 KiB
HTML
908 lines
54 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||
<title>Effigenix Mobile – Chargen</title>
|
||
<link rel="manifest" crossorigin="use-credentials">
|
||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||
<meta name="theme-color" content="#c06b3a">
|
||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||
<script src="https://cdn.tailwindcss.com"></script>
|
||
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
|
||
<script>
|
||
tailwind.config = {
|
||
theme: {
|
||
extend: {
|
||
fontFamily: { sans: ['Poppins','sans-serif'], mono: ['JetBrains Mono','monospace'] },
|
||
colors: {
|
||
brand: { 50:'#fdf6f0',100:'#fae8d8',200:'#f4cfaf',300:'#ecb07f',400:'#e18b4e',500:'#c06b3a',600:'#a8562e',700:'#8c4426',800:'#733822',900:'#5f2f1e' },
|
||
warm: { 50:'#faf8f4',100:'#f4f1eb',200:'#ede7dd',300:'#ded9d1',400:'#c5bfb5',500:'#979089',600:'#6d6459',700:'#574c3e',800:'#453d32',900:'#2e2820' },
|
||
success: { 50:'#f0f7f1',100:'#d9edd9',200:'#b4dbb6',400:'#5aaa60',500:'#3d8f44',600:'#2e7234',700:'#265b2b' },
|
||
warning: { 50:'#fdf9ec',100:'#faf0c9',200:'#f5dd8f',400:'#e8ae25',500:'#d49518',600:'#ab7013',700:'#825013' },
|
||
danger: { 50:'#fdf3f3',100:'#fce4e4',200:'#facece',400:'#ec7a7a',500:'#df5050',600:'#c43a3a',700:'#a42d2d' },
|
||
info: { 50:'#f0f7fb',100:'#ddedf6',200:'#c3dfef',400:'#69aed4',500:'#4993c3',600:'#3879a8',700:'#2e6189' },
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
<style>
|
||
:root { --primary: #c06b3a; --radius: 0.875rem; }
|
||
body { background: #faf8f4; color: #453d32; -webkit-tap-highlight-color: transparent; overscroll-behavior: none; }
|
||
.page { display:none; } .page.active { display:flex; flex-direction:column; animation: fadeIn 0.2s ease; }
|
||
@keyframes fadeIn { from{opacity:0;transform:translateY(8px)} to{opacity:1;transform:translateY(0)} }
|
||
@keyframes pulse { 0%,100%{opacity:1} 50%{opacity:0.5} }
|
||
@keyframes scanLine { 0%{top:10%} 50%{top:85%} 100%{top:10%} }
|
||
.btn { display:inline-flex;align-items:center;justify-content:center;gap:0.5rem;padding:0.75rem 1.25rem;border-radius:var(--radius);font-size:0.9375rem;font-weight:600;cursor:pointer;transition:all 0.15s;border:none;user-select:none;-webkit-user-select:none; }
|
||
.btn:active { transform:scale(0.96); }
|
||
.btn-primary { background:var(--primary);color:#fff;box-shadow:0 2px 8px rgba(192,107,58,0.3); }
|
||
.btn-outline { background:#fff;border:1.5px solid #ede7dd;color:#574c3e; }
|
||
.btn-ghost { background:transparent;color:#574c3e; }
|
||
.btn-danger { background:#df5050;color:#fff; }
|
||
.btn-success { background:#3d8f44;color:#fff; }
|
||
.btn-lg { padding:1rem 1.5rem;font-size:1rem; }
|
||
.btn-full { width:100%; }
|
||
.card { background:#fff;border:1px solid #ede7dd;border-radius:var(--radius);box-shadow:0 1px 3px rgba(0,0,0,0.04); }
|
||
.input { width:100%;padding:0.75rem 1rem;border:1.5px solid #ede7dd;border-radius:calc(var(--radius) - 2px);font-size:1rem;font-family:inherit;background:#fff;transition:border-color 0.15s;color:inherit; }
|
||
.input:focus { outline:none;border-color:var(--primary);box-shadow:0 0 0 3px rgba(192,107,58,0.12); }
|
||
.badge { display:inline-flex;align-items:center;padding:3px 10px;border-radius:9999px;font-size:0.6875rem;font-weight:600;letter-spacing:0.01em; }
|
||
.badge-ok { background:#d9edd9;color:#265b2b; }
|
||
.badge-warn { background:#faf0c9;color:#825013; }
|
||
.badge-error { background:#fce4e4;color:#a42d2d; }
|
||
.badge-info { background:#ddedf6;color:#2e6189; }
|
||
.badge-neutral { background:#ede7dd;color:#6d6459; }
|
||
.nav-item { flex:1;display:flex;flex-direction:column;align-items:center;gap:2px;padding:6px 0;font-size:0.625rem;font-weight:500;color:#979089;transition:color 0.15s;cursor:pointer;-webkit-tap-highlight-color:transparent; }
|
||
.nav-item.active { color:var(--primary); }
|
||
.scan-btn { width:56px;height:56px;border-radius:50%;background:linear-gradient(135deg,#c06b3a,#a8562e);color:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 16px rgba(192,107,58,0.4);margin-top:-20px;border:3px solid #faf8f4;cursor:pointer;transition:transform 0.15s; }
|
||
.scan-btn:active { transform:scale(0.92); }
|
||
.action-card { transition:all 0.15s; }
|
||
.action-card:active { transform:scale(0.97);background:#faf8f4; }
|
||
.step-indicator { display:flex;align-items:center;gap:0;margin-bottom:1.5rem; }
|
||
.step-dot { width:2rem;height:2rem;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:0.75rem;font-weight:700;transition:all 0.2s; }
|
||
.step-dot.done { background:#d9edd9;color:#265b2b; }
|
||
.step-dot.active { background:var(--primary);color:#fff;box-shadow:0 2px 8px rgba(192,107,58,0.3); }
|
||
.step-dot.pending { background:#ede7dd;color:#979089; }
|
||
.step-line { flex:1;height:2px;background:#ede7dd;transition:background 0.2s; }
|
||
.step-line.done { background:#b4dbb6; }
|
||
.scanned-item { animation: fadeIn 0.3s ease; }
|
||
#sidebar::-webkit-scrollbar { display:none; }
|
||
</style>
|
||
</head>
|
||
<body class="font-sans antialiased">
|
||
|
||
<!-- ═══ Wrapper (phone frame) ═══ -->
|
||
<div class="mx-auto max-w-[430px] min-h-screen flex flex-col relative bg-warm-50">
|
||
|
||
<!-- ═══════════ LOGIN ═══════════ -->
|
||
<div id="page-login" class="page active min-h-screen items-center justify-center px-6" style="background:linear-gradient(180deg,#faf8f4 0%,#f4e8d8 100%)">
|
||
<div class="w-full max-w-sm">
|
||
<div class="text-center mb-8">
|
||
<div class="inline-flex items-center justify-center w-16 h-16 rounded-2xl mb-4 shadow-lg" style="background:linear-gradient(135deg,#c06b3a,#a8562e)">
|
||
<i data-lucide="scan-line" class="w-8 h-8 text-white"></i>
|
||
</div>
|
||
<h1 class="text-2xl font-bold text-warm-800 tracking-tight">Effigenix Mobile</h1>
|
||
<p class="text-warm-500 text-sm mt-1">Chargen & Lager</p>
|
||
</div>
|
||
<div class="space-y-4">
|
||
<div>
|
||
<label class="block text-sm font-medium text-warm-700 mb-1">Betrieb</label>
|
||
<div class="input flex items-center gap-2 text-warm-700" style="cursor:pointer">
|
||
<i data-lucide="building-2" class="w-4 h-4 text-warm-400"></i> Metzgerei Huber – Hauptbetrieb
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label class="block text-sm font-medium text-warm-700 mb-1">Benutzer</label>
|
||
<input class="input" placeholder="Benutzername" value="l.meier">
|
||
</div>
|
||
<div>
|
||
<label class="block text-sm font-medium text-warm-700 mb-1">Passwort</label>
|
||
<input type="password" class="input" placeholder="••••••" value="password">
|
||
</div>
|
||
<button class="btn btn-primary btn-full btn-lg mt-2" onclick="mNav('home')">
|
||
<i data-lucide="log-in" class="w-5 h-5"></i> Anmelden
|
||
</button>
|
||
</div>
|
||
<p class="text-center text-warm-400 text-xs mt-8">Verbunden mit Effigenix ERP · v2.0</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══════════ HOME ═══════════ -->
|
||
<div id="page-home" class="page min-h-screen">
|
||
<!-- Header -->
|
||
<div class="px-5 pt-6 pb-4">
|
||
<div class="flex items-center justify-between">
|
||
<div>
|
||
<h1 class="text-lg font-bold text-warm-800">Hallo, Lisa</h1>
|
||
<p class="text-xs text-warm-500">Mi, 19. März 2026 · Hauptbetrieb</p>
|
||
</div>
|
||
<div class="w-10 h-10 rounded-full bg-brand-100 flex items-center justify-center text-brand-700 font-bold text-sm">LM</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Status Banner -->
|
||
<div class="mx-5 mb-4 card p-3 flex items-center gap-3 border-brand-200 bg-brand-50">
|
||
<div class="w-9 h-9 rounded-lg bg-brand-100 flex items-center justify-center shrink-0"><i data-lucide="radio" class="w-4.5 h-4.5 text-brand-600"></i></div>
|
||
<div class="flex-1 min-w-0">
|
||
<div class="text-sm font-semibold text-brand-800">Scanner verbunden</div>
|
||
<div class="text-xs text-brand-600">Zebra DS3678 · Bluetooth</div>
|
||
</div>
|
||
<div class="w-2.5 h-2.5 rounded-full bg-success-400 shrink-0"></div>
|
||
</div>
|
||
|
||
<!-- Quick Actions -->
|
||
<div class="px-5 mb-5">
|
||
<h2 class="text-xs font-bold text-warm-500 uppercase tracking-wider mb-3">Schnellaktionen</h2>
|
||
<div class="grid grid-cols-2 gap-3">
|
||
<div class="action-card card p-4 flex flex-col items-center gap-2 text-center cursor-pointer" onclick="mNav('scan',{flow:'move'})">
|
||
<div class="w-11 h-11 rounded-xl bg-info-50 flex items-center justify-center"><i data-lucide="arrow-right-left" class="w-5 h-5 text-info-600"></i></div>
|
||
<span class="text-sm font-medium text-warm-700">Umlagerung</span>
|
||
<span class="text-[11px] text-warm-500">Charge → Lagerort</span>
|
||
</div>
|
||
<div class="action-card card p-4 flex flex-col items-center gap-2 text-center cursor-pointer" onclick="mNav('scan',{flow:'consume'})">
|
||
<div class="w-11 h-11 rounded-xl bg-warning-50 flex items-center justify-center"><i data-lucide="package-minus" class="w-5 h-5 text-warning-600"></i></div>
|
||
<span class="text-sm font-medium text-warm-700">Verbrauch</span>
|
||
<span class="text-[11px] text-warm-500">Material → Produktion</span>
|
||
</div>
|
||
<div class="action-card card p-4 flex flex-col items-center gap-2 text-center cursor-pointer" onclick="mNav('scan',{flow:'book'})">
|
||
<div class="w-11 h-11 rounded-xl bg-success-50 flex items-center justify-center"><i data-lucide="package-check" class="w-5 h-5 text-success-600"></i></div>
|
||
<span class="text-sm font-medium text-warm-700">Produktion buchen</span>
|
||
<span class="text-[11px] text-warm-500">Charge abschließen</span>
|
||
</div>
|
||
<div class="action-card card p-4 flex flex-col items-center gap-2 text-center cursor-pointer" onclick="mNav('scan',{flow:'info'})">
|
||
<div class="w-11 h-11 rounded-xl bg-warm-100 flex items-center justify-center"><i data-lucide="search" class="w-5 h-5 text-warm-600"></i></div>
|
||
<span class="text-sm font-medium text-warm-700">Charge prüfen</span>
|
||
<span class="text-[11px] text-warm-500">Info & Historie</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Recent Activity -->
|
||
<div class="px-5 flex-1">
|
||
<h2 class="text-xs font-bold text-warm-500 uppercase tracking-wider mb-3">Letzte Buchungen</h2>
|
||
<div class="space-y-2.5">
|
||
<div class="card p-3 flex items-center gap-3 cursor-pointer" onclick="mNav('batch-detail')">
|
||
<div class="w-9 h-9 rounded-lg bg-success-50 flex items-center justify-center shrink-0"><i data-lucide="check-circle-2" class="w-4 h-4 text-success-600"></i></div>
|
||
<div class="flex-1 min-w-0">
|
||
<div class="text-sm font-medium text-warm-800 truncate">P-2026-03-19-003 → Kühlhaus 1</div>
|
||
<div class="text-xs text-warm-500">Umlagerung · 118 kg · vor 23 min</div>
|
||
</div>
|
||
<i data-lucide="chevron-right" class="w-4 h-4 text-warm-300 shrink-0"></i>
|
||
</div>
|
||
<div class="card p-3 flex items-center gap-3 cursor-pointer" onclick="mNav('batch-detail')">
|
||
<div class="w-9 h-9 rounded-lg bg-warning-50 flex items-center justify-center shrink-0"><i data-lucide="package-minus" class="w-4 h-4 text-warning-600"></i></div>
|
||
<div class="flex-1 min-w-0">
|
||
<div class="text-sm font-medium text-warm-800 truncate">54 kg Schweinefleisch S1 → P-003</div>
|
||
<div class="text-xs text-warm-500">Verbrauch · vor 1 Std</div>
|
||
</div>
|
||
<i data-lucide="chevron-right" class="w-4 h-4 text-warm-300 shrink-0"></i>
|
||
</div>
|
||
<div class="card p-3 flex items-center gap-3 cursor-pointer" onclick="mNav('batch-detail')">
|
||
<div class="w-9 h-9 rounded-lg bg-info-50 flex items-center justify-center shrink-0"><i data-lucide="arrow-right-left" class="w-4 h-4 text-info-600"></i></div>
|
||
<div class="flex-1 min-w-0">
|
||
<div class="text-sm font-medium text-warm-800 truncate">WE-2026-03-18-001 → Kühlhaus 1</div>
|
||
<div class="text-xs text-warm-500">Wareneingang · 500 kg · vor 3 Std</div>
|
||
</div>
|
||
<i data-lucide="chevron-right" class="w-4 h-4 text-warm-300 shrink-0"></i>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Bottom Nav -->
|
||
<div class="sticky bottom-0 bg-white border-t border-warm-200 px-4 pb-[env(safe-area-inset-bottom)] pt-1 flex items-end justify-around">
|
||
<div class="nav-item active" onclick="mNav('home')"><i data-lucide="home" class="w-5 h-5"></i><span>Start</span></div>
|
||
<div class="nav-item" onclick="mNav('tasks')"><i data-lucide="clipboard-list" class="w-5 h-5"></i><span>Aufgaben</span></div>
|
||
<div class="scan-btn" onclick="mNav('scan',{flow:'info'})"><i data-lucide="scan-line" class="w-6 h-6"></i></div>
|
||
<div class="nav-item" onclick="mNav('history')"><i data-lucide="history" class="w-5 h-5"></i><span>Verlauf</span></div>
|
||
<div class="nav-item"><i data-lucide="settings" class="w-5 h-5"></i><span>Mehr</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══════════ SCANNER ═══════════ -->
|
||
<div id="page-scan" class="page min-h-screen bg-warm-900">
|
||
<!-- Camera Viewfinder -->
|
||
<div class="flex-1 relative flex flex-col">
|
||
<!-- Top bar -->
|
||
<div class="absolute top-0 inset-x-0 z-10 flex items-center justify-between px-5 pt-6">
|
||
<button class="w-10 h-10 rounded-full bg-black/30 backdrop-blur flex items-center justify-center" onclick="mNav('home')">
|
||
<i data-lucide="x" class="w-5 h-5 text-white"></i>
|
||
</button>
|
||
<div id="scan-flow-label" class="px-3 py-1.5 rounded-full bg-black/30 backdrop-blur text-white text-xs font-semibold">Charge scannen</div>
|
||
<button class="w-10 h-10 rounded-full bg-black/30 backdrop-blur flex items-center justify-center">
|
||
<i data-lucide="flashlight" class="w-5 h-5 text-white"></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Camera sim -->
|
||
<div class="flex-1 flex items-center justify-center relative" style="background: linear-gradient(180deg, #1a1611 0%, #2e2820 50%, #1a1611 100%)">
|
||
<!-- Scan frame -->
|
||
<div class="w-64 h-64 relative">
|
||
<div class="absolute inset-0 border-2 border-white/20 rounded-2xl"></div>
|
||
<!-- Corner accents -->
|
||
<div class="absolute top-0 left-0 w-8 h-8 border-t-3 border-l-3 border-white rounded-tl-2xl" style="border-width:3px"></div>
|
||
<div class="absolute top-0 right-0 w-8 h-8 border-t-3 border-r-3 border-white rounded-tr-2xl" style="border-width:3px"></div>
|
||
<div class="absolute bottom-0 left-0 w-8 h-8 border-b-3 border-l-3 border-white rounded-bl-2xl" style="border-width:3px"></div>
|
||
<div class="absolute bottom-0 right-0 w-8 h-8 border-b-3 border-r-3 border-white rounded-br-2xl" style="border-width:3px"></div>
|
||
<!-- Scan line -->
|
||
<div class="absolute left-3 right-3 h-0.5 bg-brand-400 rounded-full" style="animation: scanLine 2.5s ease-in-out infinite; box-shadow: 0 0 12px rgba(192,107,58,0.6)"></div>
|
||
</div>
|
||
<p class="absolute bottom-8 text-white/50 text-sm font-medium">QR-Code, DataMatrix oder Barcode in den Rahmen halten</p>
|
||
</div>
|
||
|
||
<!-- Bottom actions -->
|
||
<div class="bg-warm-900 px-5 py-5 space-y-3">
|
||
<button class="btn btn-primary btn-full btn-lg" onclick="simulateScan()">
|
||
<i data-lucide="scan-line" class="w-5 h-5"></i> Scan simulieren
|
||
</button>
|
||
<button class="btn btn-outline btn-full bg-white/10 border-white/20 text-white" onclick="mNav('manual-entry')">
|
||
<i data-lucide="keyboard" class="w-4 h-4"></i> Manuell eingeben
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══════════ MANUAL ENTRY ═══════════ -->
|
||
<div id="page-manual-entry" class="page min-h-screen">
|
||
<div class="px-5 pt-6 pb-4 flex items-center gap-3">
|
||
<button class="w-9 h-9 rounded-full bg-warm-100 flex items-center justify-center shrink-0" onclick="mNav('scan')"><i data-lucide="arrow-left" class="w-4.5 h-4.5 text-warm-600"></i></button>
|
||
<h1 class="text-lg font-bold text-warm-800">Manuelle Eingabe</h1>
|
||
</div>
|
||
<div class="px-5 space-y-4 flex-1">
|
||
<div>
|
||
<label class="block text-sm font-medium text-warm-700 mb-1.5">Chargennummer</label>
|
||
<input class="input font-mono text-lg" placeholder="P-2026-03-19-003" value="P-2026-03-19-003">
|
||
</div>
|
||
<div>
|
||
<label class="block text-sm font-medium text-warm-700 mb-1.5">Code-Typ</label>
|
||
<div class="flex gap-2">
|
||
<button class="btn btn-primary flex-1">QR-Code</button>
|
||
<button class="btn btn-outline flex-1">EAN / GTIN</button>
|
||
<button class="btn btn-outline flex-1">DataMatrix</button>
|
||
</div>
|
||
</div>
|
||
<div class="card p-3 bg-info-50 border-info-200 flex items-start gap-2.5">
|
||
<i data-lucide="info" class="w-4 h-4 text-info-600 shrink-0 mt-0.5"></i>
|
||
<p class="text-xs text-info-700">Sie können auch Lieferschein-Nummern, Artikel-Nummern oder interne Referenzen eingeben.</p>
|
||
</div>
|
||
</div>
|
||
<div class="px-5 py-5">
|
||
<button class="btn btn-primary btn-full btn-lg" onclick="simulateScan()">
|
||
<i data-lucide="search" class="w-5 h-5"></i> Charge suchen
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══════════ BATCH DETAIL ═══════════ -->
|
||
<div id="page-batch-detail" class="page min-h-screen">
|
||
<div class="px-5 pt-6 pb-3 flex items-center gap-3">
|
||
<button class="w-9 h-9 rounded-full bg-warm-100 flex items-center justify-center shrink-0" onclick="goBack()"><i data-lucide="arrow-left" class="w-4.5 h-4.5 text-warm-600"></i></button>
|
||
<div class="flex-1">
|
||
<h1 class="text-lg font-bold text-warm-800">Chargendetail</h1>
|
||
<p class="text-xs text-warm-500 font-mono">P-2026-03-19-003</p>
|
||
</div>
|
||
<span class="badge badge-ok">Abgeschlossen</span>
|
||
</div>
|
||
|
||
<div class="px-5 space-y-4 flex-1 pb-4">
|
||
<!-- Product Info -->
|
||
<div class="card p-4">
|
||
<div class="flex items-center gap-3 mb-3">
|
||
<div class="w-11 h-11 rounded-xl bg-brand-50 flex items-center justify-center"><i data-lucide="beef" class="w-5 h-5 text-brand-500"></i></div>
|
||
<div>
|
||
<div class="font-semibold text-warm-800">Wiener Würstchen</div>
|
||
<div class="text-xs text-warm-500">ART-001 · Wurstwaren</div>
|
||
</div>
|
||
</div>
|
||
<div class="grid grid-cols-3 gap-2">
|
||
<div class="text-center p-2 bg-warm-50 rounded-lg"><div class="text-[10px] text-warm-500 font-semibold uppercase">Menge</div><div class="text-sm font-bold text-warm-800 mt-0.5">118 kg</div></div>
|
||
<div class="text-center p-2 bg-warm-50 rounded-lg"><div class="text-[10px] text-warm-500 font-semibold uppercase">MHD</div><div class="text-sm font-bold text-warm-800 mt-0.5">29.03.</div></div>
|
||
<div class="text-center p-2 bg-warm-50 rounded-lg"><div class="text-[10px] text-warm-500 font-semibold uppercase">Lagerort</div><div class="text-sm font-bold text-warm-800 mt-0.5">KH 1</div></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Status Timeline -->
|
||
<div class="card p-4">
|
||
<h3 class="text-xs font-bold text-warm-500 uppercase tracking-wider mb-3">Status</h3>
|
||
<div class="space-y-3">
|
||
<div class="flex items-center gap-3">
|
||
<div class="w-7 h-7 rounded-full bg-success-100 flex items-center justify-center"><i data-lucide="check" class="w-3.5 h-3.5 text-success-600"></i></div>
|
||
<div class="flex-1"><div class="text-sm font-medium text-warm-800">Produktion abgeschlossen</div><div class="text-xs text-warm-500">19.03. 10:32 · Lisa Meier</div></div>
|
||
</div>
|
||
<div class="flex items-center gap-3">
|
||
<div class="w-7 h-7 rounded-full bg-success-100 flex items-center justify-center"><i data-lucide="check" class="w-3.5 h-3.5 text-success-600"></i></div>
|
||
<div class="flex-1"><div class="text-sm font-medium text-warm-800">Eingelagert: Kühlhaus 1</div><div class="text-xs text-warm-500">19.03. 10:45 · Stefan Koch</div></div>
|
||
</div>
|
||
<div class="flex items-center gap-3">
|
||
<div class="w-7 h-7 rounded-full bg-info-100 flex items-center justify-center"><i data-lucide="flask-conical" class="w-3.5 h-3.5 text-info-600"></i></div>
|
||
<div class="flex-1"><div class="text-sm font-medium text-warm-800">Produktion gestartet</div><div class="text-xs text-warm-500">19.03. 07:30 · Lisa Meier</div></div>
|
||
</div>
|
||
<div class="flex items-center gap-3">
|
||
<div class="w-7 h-7 rounded-full bg-warm-100 flex items-center justify-center"><i data-lucide="calendar" class="w-3.5 h-3.5 text-warm-500"></i></div>
|
||
<div class="flex-1"><div class="text-sm font-medium text-warm-800">Geplant</div><div class="text-xs text-warm-500">18.03. 14:00 · Max Huber</div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Actions -->
|
||
<div class="space-y-2.5">
|
||
<button class="btn btn-outline btn-full" onclick="mNav('move-flow')">
|
||
<i data-lucide="arrow-right-left" class="w-4 h-4 text-info-600"></i> Umlagern
|
||
</button>
|
||
<button class="btn btn-outline btn-full" onclick="mNav('consume-flow')">
|
||
<i data-lucide="package-minus" class="w-4 h-4 text-warning-600"></i> Als Verbrauch buchen
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══════════ MOVE FLOW ═══════════ -->
|
||
<div id="page-move-flow" class="page min-h-screen">
|
||
<div class="px-5 pt-6 pb-3 flex items-center gap-3">
|
||
<button class="w-9 h-9 rounded-full bg-warm-100 flex items-center justify-center shrink-0" onclick="goBack()"><i data-lucide="arrow-left" class="w-4.5 h-4.5 text-warm-600"></i></button>
|
||
<h1 class="text-lg font-bold text-warm-800">Umlagerung</h1>
|
||
</div>
|
||
|
||
<!-- Steps -->
|
||
<div class="px-8 mb-2">
|
||
<div class="step-indicator">
|
||
<div class="step-dot done"><i data-lucide="check" class="w-3.5 h-3.5"></i></div>
|
||
<div class="step-line done"></div>
|
||
<div class="step-dot active">2</div>
|
||
<div class="step-line"></div>
|
||
<div class="step-dot pending">3</div>
|
||
</div>
|
||
<div class="flex justify-between text-[10px] font-semibold text-warm-500 uppercase -mt-1 px-0.5">
|
||
<span class="text-success-600">Charge</span><span class="text-brand-600">Ziel</span><span>Bestätigen</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="px-5 space-y-4 flex-1">
|
||
<!-- Scanned batch -->
|
||
<div class="card p-3 flex items-center gap-3 border-success-200 bg-success-50">
|
||
<div class="w-9 h-9 rounded-lg bg-success-100 flex items-center justify-center"><i data-lucide="check" class="w-4 h-4 text-success-600"></i></div>
|
||
<div class="flex-1 min-w-0">
|
||
<div class="text-sm font-semibold text-warm-800">P-2026-03-19-003</div>
|
||
<div class="text-xs text-warm-500">Wiener Würstchen · 118 kg</div>
|
||
</div>
|
||
<span class="text-xs text-warm-500">KH 1</span>
|
||
</div>
|
||
|
||
<div class="flex items-center gap-2 text-warm-400"><div class="flex-1 h-px bg-warm-200"></div><i data-lucide="arrow-down" class="w-4 h-4"></i><div class="flex-1 h-px bg-warm-200"></div></div>
|
||
|
||
<!-- Target location -->
|
||
<div>
|
||
<label class="block text-sm font-medium text-warm-700 mb-2">Ziel-Lagerort</label>
|
||
<div class="grid grid-cols-2 gap-2.5">
|
||
<div class="card p-3 text-center cursor-pointer border-2 border-transparent hover:border-brand-300 transition" onclick="selectLocation(this)">
|
||
<i data-lucide="thermometer-snowflake" class="w-5 h-5 text-info-500 mx-auto mb-1"></i>
|
||
<div class="text-sm font-semibold text-warm-800">Kühlhaus 1</div><div class="text-[11px] text-warm-500">2–4 °C</div>
|
||
</div>
|
||
<div class="card p-3 text-center cursor-pointer border-2 border-brand-400 bg-brand-50" onclick="selectLocation(this)">
|
||
<i data-lucide="thermometer-snowflake" class="w-5 h-5 text-info-500 mx-auto mb-1"></i>
|
||
<div class="text-sm font-semibold text-warm-800">Kühlhaus 2</div><div class="text-[11px] text-warm-500">0–2 °C</div>
|
||
</div>
|
||
<div class="card p-3 text-center cursor-pointer border-2 border-transparent hover:border-brand-300 transition" onclick="selectLocation(this)">
|
||
<i data-lucide="snowflake" class="w-5 h-5 text-info-700 mx-auto mb-1"></i>
|
||
<div class="text-sm font-semibold text-warm-800">Tiefkühler A</div><div class="text-[11px] text-warm-500">-18 bis -22 °C</div>
|
||
</div>
|
||
<div class="card p-3 text-center cursor-pointer border-2 border-transparent hover:border-brand-300 transition" onclick="selectLocation(this)">
|
||
<i data-lucide="scan-line" class="w-5 h-5 text-warm-400 mx-auto mb-1"></i>
|
||
<div class="text-sm font-semibold text-warm-800">Scannen</div><div class="text-[11px] text-warm-500">Lagerort-QR</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<label class="block text-sm font-medium text-warm-700 mb-1.5">Teilmenge (optional)</label>
|
||
<div class="flex items-center gap-3">
|
||
<input class="input font-mono text-center text-lg" placeholder="118" style="max-width:120px">
|
||
<span class="text-sm text-warm-500 font-medium">von 118 kg</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="px-5 py-5">
|
||
<button class="btn btn-primary btn-full btn-lg" onclick="mNav('move-confirm')">
|
||
<i data-lucide="arrow-right-left" class="w-5 h-5"></i> Umlagerung bestätigen
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══════════ MOVE CONFIRM (Success) ═══════════ -->
|
||
<div id="page-move-confirm" class="page min-h-screen items-center justify-center px-6">
|
||
<div class="text-center">
|
||
<div class="w-20 h-20 rounded-full bg-success-100 flex items-center justify-center mx-auto mb-5">
|
||
<i data-lucide="check-circle-2" class="w-10 h-10 text-success-500"></i>
|
||
</div>
|
||
<h1 class="text-xl font-bold text-warm-800 mb-1">Umlagerung gebucht</h1>
|
||
<p class="text-warm-500 text-sm mb-6">P-2026-03-19-003 → Kühlhaus 2</p>
|
||
<div class="card p-4 text-left mb-6 mx-auto max-w-xs">
|
||
<div class="space-y-2 text-sm">
|
||
<div class="flex justify-between"><span class="text-warm-500">Charge</span><span class="font-mono font-medium">P-2026-03-19-003</span></div>
|
||
<div class="flex justify-between"><span class="text-warm-500">Artikel</span><span class="font-medium">Wiener Würstchen</span></div>
|
||
<div class="flex justify-between"><span class="text-warm-500">Menge</span><span class="font-mono font-medium">118 kg</span></div>
|
||
<div class="flex justify-between"><span class="text-warm-500">Von</span><span>Kühlhaus 1</span></div>
|
||
<div class="flex justify-between"><span class="text-warm-500">Nach</span><span class="font-medium text-success-700">Kühlhaus 2</span></div>
|
||
<div class="flex justify-between"><span class="text-warm-500">Zeitpunkt</span><span>19.03. 11:05</span></div>
|
||
</div>
|
||
</div>
|
||
<div class="space-y-2.5 max-w-xs mx-auto">
|
||
<button class="btn btn-primary btn-full" onclick="mNav('scan',{flow:'move'})"><i data-lucide="scan-line" class="w-4 h-4"></i> Nächste Charge scannen</button>
|
||
<button class="btn btn-outline btn-full" onclick="mNav('home')"><i data-lucide="home" class="w-4 h-4"></i> Zurück zum Start</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══════════ CONSUME FLOW ═══════════ -->
|
||
<div id="page-consume-flow" class="page min-h-screen">
|
||
<div class="px-5 pt-6 pb-3 flex items-center gap-3">
|
||
<button class="w-9 h-9 rounded-full bg-warm-100 flex items-center justify-center shrink-0" onclick="goBack()"><i data-lucide="arrow-left" class="w-4.5 h-4.5 text-warm-600"></i></button>
|
||
<div class="flex-1">
|
||
<h1 class="text-lg font-bold text-warm-800">Verbrauch erfassen</h1>
|
||
<p class="text-xs text-warm-500">Produktionscharge: <span class="font-mono font-medium text-brand-600">P-2026-03-19-004</span></p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Steps -->
|
||
<div class="px-8 mb-2">
|
||
<div class="step-indicator">
|
||
<div class="step-dot done"><i data-lucide="check" class="w-3.5 h-3.5"></i></div>
|
||
<div class="step-line done"></div>
|
||
<div id="consume-step2" class="step-dot active">2</div>
|
||
<div id="consume-line2" class="step-line"></div>
|
||
<div id="consume-step3" class="step-dot pending">3</div>
|
||
</div>
|
||
<div class="flex justify-between text-[10px] font-semibold text-warm-500 uppercase -mt-1 px-0.5">
|
||
<span class="text-success-600">Prod.-Charge</span><span id="consume-step2-label" class="text-brand-600">Materialien</span><span id="consume-step3-label">Bestätigen</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Target batch -->
|
||
<div class="px-5 mb-3">
|
||
<div class="card p-3 flex items-center gap-3 border-brand-200 bg-brand-50">
|
||
<div class="w-9 h-9 rounded-lg bg-brand-100 flex items-center justify-center"><i data-lucide="flask-conical" class="w-4 h-4 text-brand-600"></i></div>
|
||
<div class="flex-1 min-w-0">
|
||
<div class="text-sm font-semibold text-warm-800">P-2026-03-19-004 · Leberkäse</div>
|
||
<div class="text-xs text-warm-500">Soll: 80 kg · In Produktion</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Scanned materials (dynamically filled) -->
|
||
<div class="px-5 flex-1">
|
||
<div class="flex items-center justify-between mb-2.5">
|
||
<h2 id="consume-counter" class="text-xs font-bold text-warm-500 uppercase tracking-wider">Gescannte Materialien (0)</h2>
|
||
</div>
|
||
|
||
<!-- Material list -->
|
||
<div id="consume-list" class="space-y-2.5">
|
||
<!-- items added by JS -->
|
||
</div>
|
||
|
||
<!-- Empty state (shown when no materials scanned) -->
|
||
<div id="consume-empty" class="card p-6 text-center mt-1">
|
||
<div class="inline-flex items-center justify-center w-12 h-12 rounded-xl bg-warm-100 mb-3"><i data-lucide="package-search" class="w-6 h-6 text-warm-400"></i></div>
|
||
<p class="text-sm text-warm-500 mb-1">Noch keine Materialien erfasst</p>
|
||
<p class="text-xs text-warm-400">Scannen Sie die Chargen-Etiketten der<br>verwendeten Eingangsmaterialien.</p>
|
||
</div>
|
||
|
||
<!-- Scan next button -->
|
||
<button id="consume-scan-btn" class="btn btn-outline btn-full mt-3" onclick="startConsumeScan()">
|
||
<i data-lucide="scan-line" class="w-4 h-4"></i> <span id="consume-scan-label">Erste Zutat scannen</span>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Submit button (hidden until at least 1 material) -->
|
||
<div id="consume-submit" class="px-5 py-5 hidden">
|
||
<button id="consume-submit-btn" class="btn btn-primary btn-full btn-lg" onclick="mNav('consume-confirm')">
|
||
<i data-lucide="check" class="w-5 h-5"></i> <span id="consume-submit-label">Verbräuche buchen</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══════════ CONSUME: QUANTITY INPUT (after scan) ═══════════ -->
|
||
<div id="page-consume-qty" class="page min-h-screen">
|
||
<div class="px-5 pt-6 pb-3 flex items-center gap-3">
|
||
<button class="w-9 h-9 rounded-full bg-warm-100 flex items-center justify-center shrink-0" onclick="mNav('consume-flow')"><i data-lucide="x" class="w-4.5 h-4.5 text-warm-600"></i></button>
|
||
<h1 class="text-lg font-bold text-warm-800">Menge erfassen</h1>
|
||
</div>
|
||
|
||
<div class="px-5 flex-1 flex flex-col">
|
||
<!-- Scanned material info -->
|
||
<div class="card p-4 mb-6 border-success-200 bg-success-50">
|
||
<div class="flex items-center gap-2 mb-2">
|
||
<i data-lucide="check-circle-2" class="w-4 h-4 text-success-600"></i>
|
||
<span class="text-xs font-semibold text-success-700 uppercase tracking-wider">Charge erkannt</span>
|
||
</div>
|
||
<div class="flex items-center gap-3">
|
||
<div id="cq-color" class="w-2 h-12 rounded-full bg-brand-400 shrink-0"></div>
|
||
<div class="flex-1">
|
||
<div id="cq-name" class="text-base font-semibold text-warm-800">Schweinefleisch S1</div>
|
||
<div id="cq-batch" class="text-xs text-warm-500 font-mono">WE-2026-03-18-001</div>
|
||
<div id="cq-location" class="text-xs text-warm-500">Kühlhaus 1 · Verfügbar: <span id="cq-avail" class="font-semibold">145 kg</span></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Quantity input (big, centered) -->
|
||
<div class="flex-1 flex flex-col items-center justify-center">
|
||
<label class="text-sm font-medium text-warm-600 mb-2">Verbrauchte Menge</label>
|
||
<div class="flex items-end gap-2 mb-2">
|
||
<input id="cq-input" class="input font-mono text-center text-4xl font-bold py-3 w-40 border-2" type="number" step="0.1" placeholder="0">
|
||
<span id="cq-unit" class="text-lg text-warm-500 font-medium pb-3">kg</span>
|
||
</div>
|
||
<div class="flex items-center gap-3 mb-6">
|
||
<button class="btn btn-outline btn-sm px-4" onclick="qtyPreset(10)">10</button>
|
||
<button class="btn btn-outline btn-sm px-4" onclick="qtyPreset(20)">20</button>
|
||
<button class="btn btn-outline btn-sm px-4" onclick="qtyPreset(25)">25</button>
|
||
<button class="btn btn-outline btn-sm px-4" onclick="qtyPreset(50)">50</button>
|
||
</div>
|
||
<p id="cq-hint" class="text-xs text-warm-400 text-center">Laut Rezept: ca. <span id="cq-recipe-qty" class="font-semibold text-warm-600">32</span> kg für 80 kg Leberkäse</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="px-5 py-5">
|
||
<button class="btn btn-primary btn-full btn-lg" onclick="confirmConsumeQty()">
|
||
<i data-lucide="check" class="w-5 h-5"></i> Menge übernehmen
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══════════ CONSUME CONFIRM ═══════════ -->
|
||
<div id="page-consume-confirm" class="page min-h-screen items-center justify-center px-6">
|
||
<div class="text-center">
|
||
<div class="w-20 h-20 rounded-full bg-success-100 flex items-center justify-center mx-auto mb-5">
|
||
<i data-lucide="check-circle-2" class="w-10 h-10 text-success-500"></i>
|
||
</div>
|
||
<h1 class="text-xl font-bold text-warm-800 mb-1">Verbrauch gebucht</h1>
|
||
<p id="consume-confirm-text" class="text-warm-500 text-sm mb-6">3 Materialien → P-2026-03-19-004</p>
|
||
<div class="space-y-2.5 max-w-xs mx-auto">
|
||
<button class="btn btn-primary btn-full" onclick="resetConsume();startConsumeScan()"><i data-lucide="scan-line" class="w-4 h-4"></i> Weitere Materialien scannen</button>
|
||
<button class="btn btn-success btn-full" onclick="mNav('book-flow')"><i data-lucide="package-check" class="w-4 h-4"></i> Charge abschließen</button>
|
||
<button class="btn btn-outline btn-full" onclick="resetConsume();mNav('home')"><i data-lucide="home" class="w-4 h-4"></i> Zurück zum Start</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══════════ BOOK FLOW (Complete Batch) ═══════════ -->
|
||
<div id="page-book-flow" class="page min-h-screen">
|
||
<div class="px-5 pt-6 pb-3 flex items-center gap-3">
|
||
<button class="w-9 h-9 rounded-full bg-warm-100 flex items-center justify-center shrink-0" onclick="goBack()"><i data-lucide="arrow-left" class="w-4.5 h-4.5 text-warm-600"></i></button>
|
||
<h1 class="text-lg font-bold text-warm-800">Charge abschließen</h1>
|
||
</div>
|
||
|
||
<div class="px-5 space-y-4 flex-1">
|
||
<!-- Batch card -->
|
||
<div class="card p-4">
|
||
<div class="flex items-center gap-3 mb-3">
|
||
<div class="w-11 h-11 rounded-xl bg-brand-50 flex items-center justify-center"><i data-lucide="flask-conical" class="w-5 h-5 text-brand-500"></i></div>
|
||
<div>
|
||
<div class="font-semibold text-warm-800">P-2026-03-19-004</div>
|
||
<div class="text-xs text-warm-500">Leberkäse Bayerisch · Soll: 80 kg</div>
|
||
</div>
|
||
<span class="badge badge-info ml-auto">In Produktion</span>
|
||
</div>
|
||
<div class="text-xs text-warm-500">3 Verbräuche erfasst · Rezept: Leberkäse v2</div>
|
||
</div>
|
||
|
||
<!-- Actual values -->
|
||
<div>
|
||
<label class="block text-sm font-medium text-warm-700 mb-1.5">Ist-Menge (kg) *</label>
|
||
<input class="input font-mono text-lg text-center" type="number" placeholder="0" value="78">
|
||
<div class="flex items-center justify-between mt-1.5 text-xs text-warm-500">
|
||
<span>Soll: 80 kg</span>
|
||
<span>Ausbeute: <span class="font-semibold text-success-600">97.5%</span></span>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label class="block text-sm font-medium text-warm-700 mb-1.5">Ausschuss (kg)</label>
|
||
<input class="input font-mono text-lg text-center" type="number" placeholder="0" value="2.1">
|
||
</div>
|
||
<div>
|
||
<label class="block text-sm font-medium text-warm-700 mb-1.5">Ziel-Lagerort</label>
|
||
<select class="input" style="appearance:none;background-image:url('data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2716%27 height=%2716%27 viewBox=%270 0 24 24%27 fill=%27none%27 stroke=%27%236d6459%27 stroke-width=%272%27%3E%3Cpath d=%27m6 9 6 6 6-6%27/%3E%3C/svg%3E');background-repeat:no-repeat;background-position:right 0.75rem center;padding-right:2.5rem">
|
||
<option>Kühlhaus 1 (2–4 °C)</option>
|
||
<option>Kühlhaus 2 (0–2 °C)</option>
|
||
<option>Regal Ladentheke</option>
|
||
</select>
|
||
</div>
|
||
<div>
|
||
<label class="block text-sm font-medium text-warm-700 mb-1.5">Bemerkung</label>
|
||
<textarea class="input" rows="2" placeholder="Optional…"></textarea>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="px-5 py-5 space-y-2.5">
|
||
<button class="btn btn-success btn-full btn-lg" onclick="mNav('book-confirm')">
|
||
<i data-lucide="package-check" class="w-5 h-5"></i> Charge abschließen & einlagern
|
||
</button>
|
||
<button class="btn btn-ghost btn-full text-warm-500" onclick="goBack()">Abbrechen</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══════════ BOOK CONFIRM ═══════════ -->
|
||
<div id="page-book-confirm" class="page min-h-screen items-center justify-center px-6">
|
||
<div class="text-center">
|
||
<div class="w-20 h-20 rounded-full bg-success-100 flex items-center justify-center mx-auto mb-5">
|
||
<i data-lucide="check-circle-2" class="w-10 h-10 text-success-500"></i>
|
||
</div>
|
||
<h1 class="text-xl font-bold text-warm-800 mb-1">Charge abgeschlossen</h1>
|
||
<p class="text-warm-500 text-sm mb-6">P-2026-03-19-004 → Kühlhaus 1</p>
|
||
<div class="card p-4 text-left mb-6 mx-auto max-w-xs">
|
||
<div class="space-y-2 text-sm">
|
||
<div class="flex justify-between"><span class="text-warm-500">Charge</span><span class="font-mono font-medium">P-2026-03-19-004</span></div>
|
||
<div class="flex justify-between"><span class="text-warm-500">Artikel</span><span class="font-medium">Leberkäse Bayerisch</span></div>
|
||
<div class="flex justify-between"><span class="text-warm-500">Ist-Menge</span><span class="font-mono font-medium">78 kg</span></div>
|
||
<div class="flex justify-between"><span class="text-warm-500">Ausschuss</span><span class="font-mono">2.1 kg</span></div>
|
||
<div class="flex justify-between"><span class="text-warm-500">Ausbeute</span><span class="font-semibold text-success-600">97.5%</span></div>
|
||
<div class="flex justify-between"><span class="text-warm-500">Eingelagert</span><span class="font-medium">Kühlhaus 1</span></div>
|
||
<div class="flex justify-between"><span class="text-warm-500">MHD</span><span class="font-mono">26.03.2026</span></div>
|
||
</div>
|
||
</div>
|
||
<div class="space-y-2.5 max-w-xs mx-auto">
|
||
<button class="btn btn-primary btn-full" onclick="mNav('scan',{flow:'book'})"><i data-lucide="scan-line" class="w-4 h-4"></i> Nächste Charge</button>
|
||
<button class="btn btn-outline btn-full" onclick="mNav('home')"><i data-lucide="home" class="w-4 h-4"></i> Zurück zum Start</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══════════ TASKS ═══════════ -->
|
||
<div id="page-tasks" class="page min-h-screen">
|
||
<div class="px-5 pt-6 pb-4">
|
||
<h1 class="text-lg font-bold text-warm-800">Aufgaben</h1>
|
||
<p class="text-xs text-warm-500">Offene Produktionsaufträge und Aufgaben</p>
|
||
</div>
|
||
<div class="px-5 flex-1 space-y-2.5">
|
||
<div class="card p-4 cursor-pointer" onclick="mNav('consume-flow')">
|
||
<div class="flex items-center justify-between mb-2">
|
||
<span class="badge badge-error">Dringend</span>
|
||
<span class="text-xs text-warm-500">Heute</span>
|
||
</div>
|
||
<div class="font-semibold text-warm-800 text-sm">PA-2026-0049 · Fleischwurst</div>
|
||
<div class="text-xs text-warm-500 mt-0.5">60 kg · Freigegeben · Noch keine Charge</div>
|
||
<div class="flex items-center gap-2 mt-2.5">
|
||
<div class="flex-1 h-1.5 bg-warm-200 rounded-full"><div class="h-full bg-danger-400 rounded-full" style="width:0%"></div></div>
|
||
<span class="text-[10px] text-warm-500 font-semibold">0%</span>
|
||
</div>
|
||
</div>
|
||
<div class="card p-4 cursor-pointer" onclick="mNav('consume-flow')">
|
||
<div class="flex items-center justify-between mb-2">
|
||
<span class="badge badge-warn">Hoch</span>
|
||
<span class="text-xs text-warm-500">Heute</span>
|
||
</div>
|
||
<div class="font-semibold text-warm-800 text-sm">PA-2026-0048 · Leberkäse Bayerisch</div>
|
||
<div class="text-xs text-warm-500 mt-0.5">80 kg · In Bearbeitung · P-2026-03-19-004</div>
|
||
<div class="flex items-center gap-2 mt-2.5">
|
||
<div class="flex-1 h-1.5 bg-warm-200 rounded-full"><div class="h-full bg-warning-400 rounded-full" style="width:60%"></div></div>
|
||
<span class="text-[10px] text-warm-500 font-semibold">60%</span>
|
||
</div>
|
||
</div>
|
||
<div class="card p-4 cursor-pointer">
|
||
<div class="flex items-center justify-between mb-2">
|
||
<span class="badge badge-neutral">Normal</span>
|
||
<span class="text-xs text-warm-500">Morgen</span>
|
||
</div>
|
||
<div class="font-semibold text-warm-800 text-sm">PA-2026-0050 · Weißwurst</div>
|
||
<div class="text-xs text-warm-500 mt-0.5">40 kg · Geplant · 21.03.2026</div>
|
||
<div class="flex items-center gap-2 mt-2.5">
|
||
<div class="flex-1 h-1.5 bg-warm-200 rounded-full"><div class="h-full bg-warm-300 rounded-full" style="width:0%"></div></div>
|
||
<span class="text-[10px] text-warm-500 font-semibold">0%</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- Bottom Nav -->
|
||
<div class="sticky bottom-0 bg-white border-t border-warm-200 px-4 pb-[env(safe-area-inset-bottom)] pt-1 flex items-end justify-around">
|
||
<div class="nav-item" onclick="mNav('home')"><i data-lucide="home" class="w-5 h-5"></i><span>Start</span></div>
|
||
<div class="nav-item active" onclick="mNav('tasks')"><i data-lucide="clipboard-list" class="w-5 h-5"></i><span>Aufgaben</span></div>
|
||
<div class="scan-btn" onclick="mNav('scan',{flow:'info'})"><i data-lucide="scan-line" class="w-6 h-6"></i></div>
|
||
<div class="nav-item" onclick="mNav('history')"><i data-lucide="history" class="w-5 h-5"></i><span>Verlauf</span></div>
|
||
<div class="nav-item"><i data-lucide="settings" class="w-5 h-5"></i><span>Mehr</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══════════ HISTORY ═══════════ -->
|
||
<div id="page-history" class="page min-h-screen">
|
||
<div class="px-5 pt-6 pb-4">
|
||
<h1 class="text-lg font-bold text-warm-800">Verlauf</h1>
|
||
<p class="text-xs text-warm-500">Alle Buchungen heute</p>
|
||
</div>
|
||
<div class="px-5 mb-3">
|
||
<div class="flex gap-2">
|
||
<button class="btn btn-primary btn-sm flex-1">Heute</button>
|
||
<button class="btn btn-outline btn-sm flex-1">Gestern</button>
|
||
<button class="btn btn-outline btn-sm flex-1">Woche</button>
|
||
</div>
|
||
</div>
|
||
<div class="px-5 flex-1 space-y-2">
|
||
<div class="text-[10px] font-bold text-warm-400 uppercase tracking-wider">11:05</div>
|
||
<div class="card p-3 flex items-center gap-3">
|
||
<div class="w-8 h-8 rounded-lg bg-info-50 flex items-center justify-center"><i data-lucide="arrow-right-left" class="w-4 h-4 text-info-600"></i></div>
|
||
<div class="flex-1"><div class="text-sm font-medium text-warm-800">Umlagerung</div><div class="text-xs text-warm-500">P-003 · 118 kg → KH 2</div></div>
|
||
</div>
|
||
<div class="text-[10px] font-bold text-warm-400 uppercase tracking-wider mt-3">10:45</div>
|
||
<div class="card p-3 flex items-center gap-3">
|
||
<div class="w-8 h-8 rounded-lg bg-success-50 flex items-center justify-center"><i data-lucide="package-check" class="w-4 h-4 text-success-600"></i></div>
|
||
<div class="flex-1"><div class="text-sm font-medium text-warm-800">Produktion abgeschlossen</div><div class="text-xs text-warm-500">P-003 · Wiener · 118 kg</div></div>
|
||
</div>
|
||
<div class="text-[10px] font-bold text-warm-400 uppercase tracking-wider mt-3">09:15</div>
|
||
<div class="card p-3 flex items-center gap-3">
|
||
<div class="w-8 h-8 rounded-lg bg-warning-50 flex items-center justify-center"><i data-lucide="package-minus" class="w-4 h-4 text-warning-600"></i></div>
|
||
<div class="flex-1"><div class="text-sm font-medium text-warm-800">Verbrauch</div><div class="text-xs text-warm-500">54 kg Schweinefleisch → P-003</div></div>
|
||
</div>
|
||
<div class="card p-3 flex items-center gap-3">
|
||
<div class="w-8 h-8 rounded-lg bg-warning-50 flex items-center justify-center"><i data-lucide="package-minus" class="w-4 h-4 text-warning-600"></i></div>
|
||
<div class="flex-1"><div class="text-sm font-medium text-warm-800">Verbrauch</div><div class="text-xs text-warm-500">24 kg Speck → P-003</div></div>
|
||
</div>
|
||
<div class="card p-3 flex items-center gap-3">
|
||
<div class="w-8 h-8 rounded-lg bg-warning-50 flex items-center justify-center"><i data-lucide="package-minus" class="w-4 h-4 text-warning-600"></i></div>
|
||
<div class="flex-1"><div class="text-sm font-medium text-warm-800">Verbrauch</div><div class="text-xs text-warm-500">2.2 kg Nitritpökelsalz → P-003</div></div>
|
||
</div>
|
||
<div class="text-[10px] font-bold text-warm-400 uppercase tracking-wider mt-3">07:30</div>
|
||
<div class="card p-3 flex items-center gap-3">
|
||
<div class="w-8 h-8 rounded-lg bg-info-50 flex items-center justify-center"><i data-lucide="play-circle" class="w-4 h-4 text-info-600"></i></div>
|
||
<div class="flex-1"><div class="text-sm font-medium text-warm-800">Produktion gestartet</div><div class="text-xs text-warm-500">P-003 · Wiener Würstchen</div></div>
|
||
</div>
|
||
</div>
|
||
<!-- Bottom Nav -->
|
||
<div class="sticky bottom-0 bg-white border-t border-warm-200 px-4 pb-[env(safe-area-inset-bottom)] pt-1 flex items-end justify-around mt-4">
|
||
<div class="nav-item" onclick="mNav('home')"><i data-lucide="home" class="w-5 h-5"></i><span>Start</span></div>
|
||
<div class="nav-item" onclick="mNav('tasks')"><i data-lucide="clipboard-list" class="w-5 h-5"></i><span>Aufgaben</span></div>
|
||
<div class="scan-btn" onclick="mNav('scan',{flow:'info'})"><i data-lucide="scan-line" class="w-6 h-6"></i></div>
|
||
<div class="nav-item active" onclick="mNav('history')"><i data-lucide="history" class="w-5 h-5"></i><span>Verlauf</span></div>
|
||
<div class="nav-item"><i data-lucide="settings" class="w-5 h-5"></i><span>Mehr</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', () => lucide.createIcons());
|
||
|
||
let navHistory = ['login'];
|
||
let currentFlow = 'info';
|
||
const flowLabels = { move:'Charge zum Umlagern scannen', consume:'Material scannen', book:'Produktionscharge scannen', info:'Charge scannen' };
|
||
|
||
// ─── Consume flow state ───
|
||
let consumeItems = [];
|
||
let consumeScanIndex = 0;
|
||
const consumeMaterials = [
|
||
{ name:'Schweinefleisch S1', batch:'WE-2026-03-18-001', location:'Kühlhaus 1', avail:145, unit:'kg', color:'bg-brand-400', recipeQty:32 },
|
||
{ name:'Schweinefett (Speck)', batch:'WE-2026-03-17-003', location:'Kühlhaus 1', avail:80, unit:'kg', color:'bg-warning-400', recipeQty:20 },
|
||
{ name:'Leberkäse-Gewürz', batch:'WE-2026-03-10-014', location:'Trockenlager', avail:8, unit:'kg', color:'bg-warm-400', recipeQty:1.4 },
|
||
];
|
||
|
||
function mNav(page, opts) {
|
||
if (opts?.flow) currentFlow = opts.flow;
|
||
// Reset consume state when starting fresh
|
||
if (page === 'consume-flow' && opts?.flow === 'consume') { resetConsume(); }
|
||
document.querySelectorAll('.page').forEach(p => p.classList.remove('active'));
|
||
const el = document.getElementById('page-' + page);
|
||
if (el) el.classList.add('active');
|
||
if (page === 'scan') {
|
||
document.getElementById('scan-flow-label').textContent = flowLabels[currentFlow] || 'Charge scannen';
|
||
}
|
||
if (page === 'consume-flow') renderConsumeList();
|
||
if (page !== navHistory[navHistory.length - 1]) navHistory.push(page);
|
||
lucide.createIcons();
|
||
}
|
||
|
||
function goBack() {
|
||
navHistory.pop();
|
||
const prev = navHistory[navHistory.length - 1] || 'home';
|
||
document.querySelectorAll('.page').forEach(p => p.classList.remove('active'));
|
||
document.getElementById('page-' + prev)?.classList.add('active');
|
||
if (prev === 'consume-flow') renderConsumeList();
|
||
lucide.createIcons();
|
||
}
|
||
|
||
function simulateScan() {
|
||
if (currentFlow === 'consume') {
|
||
// Simulate scanning the next material
|
||
if (consumeScanIndex < consumeMaterials.length) {
|
||
showConsumeQtyInput(consumeScanIndex);
|
||
} else {
|
||
mNav('consume-flow');
|
||
}
|
||
return;
|
||
}
|
||
const targets = { move:'batch-detail', book:'book-flow', info:'batch-detail' };
|
||
mNav(targets[currentFlow] || 'batch-detail');
|
||
}
|
||
|
||
// ─── Consume: quantity input after scan ───
|
||
function startConsumeScan() {
|
||
currentFlow = 'consume';
|
||
mNav('scan', { flow:'consume' });
|
||
}
|
||
|
||
function showConsumeQtyInput(idx) {
|
||
const mat = consumeMaterials[idx];
|
||
document.getElementById('cq-name').textContent = mat.name;
|
||
document.getElementById('cq-batch').textContent = mat.batch;
|
||
document.getElementById('cq-location').innerHTML = mat.location + ' · Verfügbar: <span class="font-semibold">' + mat.avail + ' ' + mat.unit + '</span>';
|
||
document.getElementById('cq-color').className = 'w-2 h-12 rounded-full shrink-0 ' + mat.color;
|
||
document.getElementById('cq-unit').textContent = mat.unit;
|
||
document.getElementById('cq-recipe-qty').textContent = mat.recipeQty;
|
||
document.getElementById('cq-input').value = '';
|
||
document.getElementById('cq-input').placeholder = String(mat.recipeQty);
|
||
mNav('consume-qty');
|
||
setTimeout(() => document.getElementById('cq-input').focus(), 300);
|
||
}
|
||
|
||
function qtyPreset(val) {
|
||
document.getElementById('cq-input').value = val;
|
||
}
|
||
|
||
function confirmConsumeQty() {
|
||
const input = document.getElementById('cq-input');
|
||
const mat = consumeMaterials[consumeScanIndex];
|
||
const qty = parseFloat(input.value) || mat.recipeQty;
|
||
consumeItems.push({ ...mat, qty });
|
||
consumeScanIndex++;
|
||
mNav('consume-flow');
|
||
}
|
||
|
||
function renderConsumeList() {
|
||
const list = document.getElementById('consume-list');
|
||
const empty = document.getElementById('consume-empty');
|
||
const counter = document.getElementById('consume-counter');
|
||
const submit = document.getElementById('consume-submit');
|
||
const scanLabel = document.getElementById('consume-scan-label');
|
||
const submitLabel = document.getElementById('consume-submit-label');
|
||
const confirmText = document.getElementById('consume-confirm-text');
|
||
|
||
counter.textContent = 'Gescannte Materialien (' + consumeItems.length + ')';
|
||
confirmText.textContent = consumeItems.length + ' Materialien → P-2026-03-19-004';
|
||
|
||
// Render scanned items
|
||
list.innerHTML = consumeItems.map((item, i) => `
|
||
<div class="scanned-item card p-3 flex items-center gap-3">
|
||
<div class="w-2 h-10 rounded-full ${item.color} shrink-0"></div>
|
||
<div class="flex-1 min-w-0">
|
||
<div class="text-sm font-medium text-warm-800">${item.name}</div>
|
||
<div class="text-xs text-warm-500">${item.batch} · ${item.location}</div>
|
||
</div>
|
||
<div class="text-right shrink-0">
|
||
<div class="font-mono font-semibold text-sm text-warm-800">${item.qty} ${item.unit}</div>
|
||
<div class="text-[10px] text-warm-400">von ${item.avail} ${item.unit}</div>
|
||
</div>
|
||
</div>
|
||
`).join('');
|
||
|
||
// Show/hide empty state
|
||
empty.classList.toggle('hidden', consumeItems.length > 0);
|
||
|
||
// Update scan button label
|
||
if (consumeScanIndex >= consumeMaterials.length) {
|
||
scanLabel.textContent = 'Weitere Zutat scannen';
|
||
} else if (consumeItems.length === 0) {
|
||
scanLabel.textContent = 'Erste Zutat scannen';
|
||
} else {
|
||
scanLabel.textContent = 'Nächste Zutat scannen';
|
||
}
|
||
|
||
// Show submit button when at least 1 item
|
||
submit.classList.toggle('hidden', consumeItems.length === 0);
|
||
submitLabel.textContent = consumeItems.length + ' Verbrauch' + (consumeItems.length !== 1 ? 'e' : '') + ' buchen';
|
||
|
||
lucide.createIcons();
|
||
}
|
||
|
||
function resetConsume() {
|
||
consumeItems = [];
|
||
consumeScanIndex = 0;
|
||
}
|
||
|
||
// ─── Location selection ───
|
||
function selectLocation(el) {
|
||
el.closest('.grid').querySelectorAll('.card').forEach(c => {
|
||
c.classList.remove('border-brand-400','bg-brand-50');
|
||
c.classList.add('border-transparent');
|
||
});
|
||
el.classList.remove('border-transparent');
|
||
el.classList.add('border-brand-400','bg-brand-50');
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|