Files
Fridger/public/index.html
T
me0nline b73d3b6250
Build and Push Fridger Container / Build & Push Fridger Image (push) Successful in 1m27s
feat(manage): implement interactive Scan/Search -> Add/Remove -> Packet/Amount workflow
2026-10-10 23:48:28 +02:00

542 lines
30 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en" class="h-full bg-slate-950 text-slate-100">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Fridger - Tablet Fridge Manager</title>
<!-- Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
darkMode: 'class',
theme: {
extend: {
colors: {
brand: {
400: '#2dd4bf',
500: '#14b8a6',
600: '#0d9488',
}
}
}
}
}
</script>
<!-- Lucide Icons -->
<script src="https://unpkg.com/lucide@latest"></script>
<!-- HTML5 QR Code Scanner -->
<script src="https://unpkg.com/html5-qrcode" type="text/javascript"></script>
<link rel="stylesheet" href="/styles.css">
</head>
<body class="h-full flex flex-col bg-slate-950 text-slate-100 antialiased selection:bg-teal-500 selection:text-white select-none">
<!-- TOP TABLET HEADER (MAIN -> SCAN -> MANAGE) -->
<header class="sticky top-0 z-30 bg-slate-900/95 backdrop-blur-md border-b border-slate-800 shadow-md">
<div class="max-w-4xl mx-auto px-3 sm:px-6">
<div class="flex items-center justify-between h-16 sm:h-20 gap-2">
<!-- Logo -->
<div class="flex items-center gap-2.5 shrink-0">
<div class="w-10 h-10 sm:w-11 sm:h-11 rounded-2xl bg-gradient-to-tr from-teal-500 to-cyan-400 flex items-center justify-center shadow-lg shadow-teal-500/20 text-white font-black text-xl">
🧊
</div>
<div class="hidden xs:block">
<h1 class="font-extrabold text-lg sm:text-xl leading-none bg-gradient-to-r from-teal-300 to-cyan-300 bg-clip-text text-transparent">Fridger</h1>
<p class="text-[11px] text-slate-400 font-medium">Tablet Manager</p>
</div>
</div>
<!-- 3 MAIN TABS: MAIN -> SCAN -> MANAGE -->
<nav class="flex items-center bg-slate-950 p-1.5 rounded-2xl border border-slate-800 shadow-inner gap-1">
<!-- 1. MAIN (What's in the Fridge) -->
<button
id="nav-main-btn"
onclick="switchTab('main')"
class="flex items-center justify-center gap-2 px-4 sm:px-7 py-2.5 sm:py-3 rounded-xl text-xs sm:text-sm font-bold transition-all bg-teal-500 text-white shadow-md active:scale-95 touch-manipulation min-h-[44px]"
>
<i data-lucide="home" class="w-4 h-4 sm:w-5 sm:h-5"></i>
<span>Main</span>
</button>
<!-- 2. SCAN (Live Camera Barcode) -->
<button
id="nav-scan-btn"
onclick="openScannerModal()"
class="flex items-center justify-center gap-2 px-4 sm:px-7 py-2.5 sm:py-3 rounded-xl text-xs sm:text-sm font-bold transition-all text-slate-300 hover:text-white hover:bg-slate-800/80 active:scale-95 touch-manipulation min-h-[44px]"
>
<i data-lucide="scan-barcode" class="w-4 h-4 sm:w-5 sm:h-5 text-teal-400"></i>
<span>Scan</span>
</button>
<!-- 3. MANAGE (Scan/Search -> Add/Remove -> Packet/Amount) -->
<button
id="nav-manage-btn"
onclick="switchTab('manage')"
class="flex items-center justify-center gap-2 px-4 sm:px-7 py-2.5 sm:py-3 rounded-xl text-xs sm:text-sm font-bold transition-all text-slate-300 hover:text-white hover:bg-slate-800/80 active:scale-95 touch-manipulation min-h-[44px]"
>
<i data-lucide="sliders-horizontal" class="w-4 h-4 sm:w-5 sm:h-5"></i>
<span>Manage</span>
</button>
</nav>
<!-- Quick Add New Product -->
<button
onclick="openItemModal()"
class="flex items-center justify-center gap-1.5 px-3 sm:px-4 py-2.5 sm:py-3 rounded-xl bg-slate-800 hover:bg-slate-700 border border-slate-700 text-slate-200 text-xs sm:text-sm font-semibold transition active:scale-95 min-h-[44px] touch-manipulation shrink-0"
title="New Product"
>
<i data-lucide="plus" class="w-4 h-4"></i>
<span class="hidden sm:inline">New</span>
</button>
</div>
</div>
</header>
<!-- QUICK STATS BAR -->
<section class="bg-slate-900/50 border-b border-slate-800/60 py-2 sm:py-2.5">
<div class="max-w-4xl mx-auto px-3 sm:px-6">
<div class="flex items-center justify-between text-xs sm:text-sm text-slate-400 overflow-x-auto gap-4 scrollbar-none">
<div class="flex items-center gap-2 shrink-0">
<span class="w-2.5 h-2.5 rounded-full bg-teal-400"></span>
<span>In Fridge: <strong id="stat-total" class="text-white font-black text-sm sm:text-base">0</strong></span>
</div>
<div class="flex items-center gap-2 shrink-0">
<span class="w-2.5 h-2.5 rounded-full bg-emerald-400"></span>
<span>Fresh: <strong id="stat-fresh" class="text-emerald-300 font-bold">0</strong></span>
</div>
<div class="flex items-center gap-2 shrink-0">
<span class="w-2.5 h-2.5 rounded-full bg-amber-400"></span>
<span>Expiring Soon: <strong id="stat-expiring" class="text-amber-300 font-bold">0</strong></span>
</div>
<div class="flex items-center gap-2 shrink-0">
<span class="w-2.5 h-2.5 rounded-full bg-indigo-400"></span>
<span>Opened: <strong id="stat-opened" class="text-indigo-300 font-bold">0</strong></span>
</div>
</div>
</div>
</section>
<!-- MAIN TAB CONTENT (FRIDGE VIEW) -->
<main id="main-tab-view" class="flex-1 max-w-4xl mx-auto px-3 sm:px-6 py-4 w-full space-y-3">
<!-- Search & Filter Ribbon in Main tab -->
<div class="space-y-2.5">
<div class="flex flex-col sm:flex-row gap-2.5 items-stretch sm:items-center justify-between">
<div class="relative flex-1">
<i data-lucide="search" class="w-4 h-4 text-slate-400 absolute left-3.5 top-1/2 -translate-y-1/2"></i>
<input
type="text"
id="search-input"
placeholder="Search items in fridge..."
oninput="handleSearch(this.value)"
class="w-full bg-slate-900 border border-slate-800 focus:border-teal-500 rounded-xl pl-9 pr-9 py-2.5 text-sm sm:text-base text-slate-100 placeholder-slate-500 outline-none transition"
>
<button id="clear-search" onclick="clearSearch()" class="hidden absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 hover:text-white p-1">
<i data-lucide="x" class="w-4 h-4"></i>
</button>
</div>
<div class="flex items-center gap-1.5 overflow-x-auto pb-0.5 text-xs sm:text-sm font-medium scrollbar-none">
<button onclick="setStatusFilter('all')" data-status-btn="all" class="status-chip active px-3.5 py-2 rounded-xl bg-slate-800 border border-slate-700 text-white font-bold min-h-[38px] touch-manipulation">All</button>
<button onclick="setStatusFilter('fresh')" data-status-btn="fresh" class="status-chip px-3.5 py-2 rounded-xl bg-slate-900 border border-slate-800 text-slate-400 hover:text-slate-200 min-h-[38px] touch-manipulation">Fresh</button>
<button onclick="setStatusFilter('expiring_soon')" data-status-btn="expiring_soon" class="status-chip px-3.5 py-2 rounded-xl bg-slate-900 border border-slate-800 text-amber-400 hover:text-amber-300 min-h-[38px] touch-manipulation">Expiring</button>
<button onclick="setStatusFilter('low')" data-status-btn="low" class="status-chip px-3.5 py-2 rounded-xl bg-slate-900 border border-slate-800 text-indigo-400 hover:text-indigo-300 min-h-[38px] touch-manipulation">&le;25%</button>
<button onclick="setStatusFilter('expired')" data-status-btn="expired" class="status-chip px-3.5 py-2 rounded-xl bg-slate-900 border border-slate-800 text-rose-400 hover:text-rose-300 min-h-[38px] touch-manipulation">Expired</button>
</div>
</div>
<div id="category-filter-bar" class="flex items-center gap-1.5 overflow-x-auto pb-1 scrollbar-none text-xs sm:text-sm font-medium">
<!-- Injected by JS -->
</div>
</div>
<!-- Fridge Cards Grid -->
<div id="fridge-view-content" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3.5 sm:gap-4 pt-2">
<!-- Rendered items -->
</div>
<!-- Empty State -->
<div id="empty-state" class="hidden text-center py-16 px-4">
<div class="w-16 h-16 sm:w-20 sm:h-20 rounded-2xl bg-slate-900 text-slate-500 flex items-center justify-center mx-auto mb-3 border border-slate-800 text-3xl">
🧊
</div>
<h3 class="text-lg font-bold text-white mb-1">Your fridge is empty</h3>
<p class="text-xs sm:text-sm text-slate-400 max-w-xs mx-auto mb-6">Scan a barcode or add an item to track quantities.</p>
<button onclick="switchTab('manage')" class="px-6 py-3 rounded-xl bg-teal-500 hover:bg-teal-400 text-white text-sm font-bold flex items-center gap-2 shadow-lg shadow-teal-500/20 active:scale-95 touch-manipulation mx-auto">
<i data-lucide="sliders-horizontal" class="w-5 h-5"></i>
<span>Go to Manage</span>
</button>
</div>
</main>
<!-- MANAGE TAB CONTENT (INTERACTIVE STEP FLOW: SCAN/SEARCH -> ADD/REMOVE -> PACKET/AMOUNT) -->
<main id="manage-tab-view" class="hidden flex-1 max-w-4xl mx-auto px-3 sm:px-6 py-4 w-full space-y-5">
<!-- STEP 1: SCAN OR SEARCH / SELECT PRODUCT -->
<div class="bg-slate-900 border border-slate-800 rounded-3xl p-4 sm:p-6 shadow-xl space-y-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-2.5">
<div class="w-7 h-7 rounded-xl bg-teal-500/20 text-teal-300 flex items-center justify-center text-xs font-black">1</div>
<h2 class="text-base sm:text-lg font-extrabold text-white">Scan Barcode or Search Product</h2>
</div>
<button onclick="openItemModal()" class="text-xs text-teal-400 hover:text-teal-300 font-semibold flex items-center gap-1 touch-manipulation">
<i data-lucide="plus-circle" class="w-4 h-4"></i>
<span>Add New</span>
</button>
</div>
<!-- Live Scan & Search Big Controls -->
<div class="grid grid-cols-1 sm:grid-cols-3 gap-3">
<!-- Big Camera Scan Button -->
<button
onclick="openScannerModal()"
class="sm:col-span-1 p-4 rounded-2xl bg-gradient-to-r from-teal-500 to-emerald-600 hover:from-teal-400 hover:to-emerald-500 text-white font-extrabold flex items-center justify-center gap-3 shadow-lg shadow-teal-500/25 active:scale-95 touch-manipulation min-h-[56px]"
>
<i data-lucide="camera" class="w-6 h-6"></i>
<span class="text-sm sm:text-base">Scan Barcode</span>
</button>
<!-- Search / Barcode Input -->
<div class="sm:col-span-2 relative flex items-center">
<i data-lucide="search" class="w-5 h-5 text-slate-400 absolute left-4"></i>
<input
type="text"
id="manage-search-input"
placeholder="Type name, brand, or barcode number..."
oninput="handleManageSearch(this.value)"
class="w-full bg-slate-950 border border-slate-800 focus:border-teal-500 rounded-2xl pl-12 pr-4 py-3.5 text-sm sm:text-base text-white placeholder-slate-500 outline-none transition min-h-[56px]"
>
</div>
</div>
<!-- Quick Product Pick List -->
<div class="space-y-1.5 pt-2">
<label class="text-xs font-bold text-slate-400 uppercase tracking-wider block">Or tap an item from your fridge:</label>
<div id="manage-quick-picker" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2.5 max-h-48 overflow-y-auto p-1 scrollbar-none">
<!-- Rendered dynamically -->
</div>
</div>
</div>
<!-- STEP 2 & 3: ACTION SELECTION (ADD / REMOVE) & QUANTITY TYPE (PACKET / AMOUNT) -->
<div id="manage-action-card" class="hidden bg-slate-900 border border-slate-700/80 rounded-3xl p-5 sm:p-6 shadow-2xl space-y-6 animate-scale-up">
<!-- Selected Product Banner -->
<div class="bg-slate-950/80 p-4 rounded-2xl border border-slate-800 flex items-center justify-between gap-3">
<div class="flex items-center gap-3.5 min-w-0">
<div id="manage-selected-img" class="w-14 h-14 rounded-xl bg-slate-800 flex items-center justify-center text-teal-400 shrink-0 overflow-hidden">
<i data-lucide="package" class="w-7 h-7"></i>
</div>
<div class="min-w-0">
<h3 id="manage-selected-name" class="font-extrabold text-white text-base sm:text-lg truncate">Selected Product</h3>
<p id="manage-selected-details" class="text-xs sm:text-sm text-slate-400 mt-0.5">Currently: 250g in fridge &bull; 1 Pack = 250g</p>
</div>
</div>
<button onclick="clearSelectedManageItem()" class="text-slate-400 hover:text-white p-2 rounded-xl bg-slate-800/80 touch-manipulation">
<i data-lucide="x" class="w-5 h-5"></i>
</button>
</div>
<!-- STEP 2: CHOOSE ADD OR REMOVE -->
<div class="space-y-3">
<div class="flex items-center gap-2">
<div class="w-7 h-7 rounded-xl bg-teal-500/20 text-teal-300 flex items-center justify-center text-xs font-black">2</div>
<h4 class="text-sm sm:text-base font-bold text-white">Choose Action</h4>
</div>
<div class="grid grid-cols-2 gap-3 sm:gap-4">
<button
id="manage-btn-add"
onclick="setManageAction('add')"
class="p-4 sm:p-5 rounded-2xl border-2 text-center font-extrabold transition-all active:scale-95 touch-manipulation flex flex-col items-center justify-center gap-2 min-h-[80px] bg-slate-950 border-slate-800 text-slate-300 hover:border-emerald-500/60 hover:text-white"
>
<i data-lucide="plus-circle" class="w-7 h-7 text-emerald-400"></i>
<span class="text-sm sm:text-base">➕ Add to Fridge</span>
</button>
<button
id="manage-btn-remove"
onclick="setManageAction('remove')"
class="p-4 sm:p-5 rounded-2xl border-2 text-center font-extrabold transition-all active:scale-95 touch-manipulation flex flex-col items-center justify-center gap-2 min-h-[80px] bg-slate-950 border-slate-800 text-slate-300 hover:border-rose-500/60 hover:text-white"
>
<i data-lucide="minus-circle" class="w-7 h-7 text-rose-400"></i>
<span class="text-sm sm:text-base">➖ Remove from Fridge</span>
</button>
</div>
</div>
<!-- STEP 3: CHOOSE QUANTITY TYPE (WHOLE PACKET OR SPECIFIC GRAMS/AMOUNT) -->
<div id="manage-qty-type-section" class="hidden space-y-4 pt-2 border-t border-slate-800">
<div class="flex items-center gap-2">
<div class="w-7 h-7 rounded-xl bg-teal-500/20 text-teal-300 flex items-center justify-center text-xs font-black">3</div>
<h4 id="manage-step3-title" class="text-sm sm:text-base font-bold text-white">How much to Add / Remove?</h4>
</div>
<!-- Mode Toggle: Whole Packet vs Specific Grams -->
<div class="grid grid-cols-2 gap-2 p-1.5 bg-slate-950 rounded-2xl border border-slate-800">
<button
id="qty-mode-packet-btn"
onclick="setQtyMode('packet')"
class="py-3 px-3 rounded-xl font-bold text-xs sm:text-sm transition bg-teal-500 text-white shadow-md touch-manipulation flex items-center justify-center gap-2"
>
<i data-lucide="package" class="w-4 h-4"></i>
<span>Whole Packet(s)</span>
</button>
<button
id="qty-mode-amount-btn"
onclick="setQtyMode('amount')"
class="py-3 px-3 rounded-xl font-bold text-xs sm:text-sm transition text-slate-300 hover:text-white touch-manipulation flex items-center justify-center gap-2"
>
<i data-lucide="scale" class="w-4 h-4"></i>
<span>Specific Grams / Amount</span>
</button>
</div>
<!-- Option A: Whole Packet Controls -->
<div id="qty-packet-controls" class="bg-slate-950 p-4 sm:p-5 rounded-2xl border border-slate-800 space-y-4 text-center">
<div class="text-xs sm:text-sm text-slate-400 font-medium">
1 Packet = <strong id="manage-pack-size-label" class="text-teal-300 font-bold">250g</strong>
</div>
<div class="flex items-center justify-center gap-4">
<button onclick="changePacketCount(-1)" class="w-12 h-12 rounded-2xl bg-slate-800 hover:bg-slate-700 text-white font-extrabold text-2xl flex items-center justify-center active:scale-95 touch-manipulation border border-slate-700">-</button>
<div class="text-3xl sm:text-4xl font-black text-white min-w-[90px]">
<span id="manage-pack-count">1</span> <span class="text-sm font-normal text-slate-400">pack</span>
</div>
<button onclick="changePacketCount(1)" class="w-12 h-12 rounded-2xl bg-slate-800 hover:bg-slate-700 text-white font-extrabold text-2xl flex items-center justify-center active:scale-95 touch-manipulation border border-slate-700">+</button>
</div>
<!-- Quick Chips -->
<div class="flex items-center justify-center gap-2">
<button onclick="setPacketCount(1)" class="px-3.5 py-1.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-xs text-slate-200 border border-slate-700 font-bold">1 Pack</button>
<button onclick="setPacketCount(2)" class="px-3.5 py-1.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-xs text-slate-200 border border-slate-700 font-bold">2 Packs</button>
<button onclick="setPacketCount(3)" class="px-3.5 py-1.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-xs text-slate-200 border border-slate-700 font-bold">3 Packs</button>
</div>
</div>
<!-- Option B: Specific Grams Controls (Slider & Quick Chips) -->
<div id="qty-amount-controls" class="hidden bg-slate-950 p-4 sm:p-5 rounded-2xl border border-slate-800 space-y-4 text-center">
<div>
<div class="text-3xl sm:text-4xl font-black text-white flex items-center justify-center gap-1.5">
<span id="manage-amount-val">150</span>
<span id="manage-amount-unit" class="text-base font-normal text-teal-400">g</span>
</div>
<div id="manage-amount-subtext" class="text-xs text-slate-400 mt-1 font-medium">New remaining amount in fridge</div>
</div>
<input
type="range"
id="manage-amount-slider"
min="0"
max="500"
step="5"
value="150"
oninput="onManageAmountSlider(this.value)"
class="w-full accent-teal-500 cursor-pointer h-3 bg-slate-800 rounded-xl"
>
<!-- Tablet Quick Delta Chips -->
<div class="grid grid-cols-3 sm:grid-cols-6 gap-2">
<button onclick="applyManageDelta(-10)" class="py-2.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-xs sm:text-sm text-slate-200 border border-slate-700 font-bold touch-manipulation">-10</button>
<button onclick="applyManageDelta(-25)" class="py-2.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-xs sm:text-sm text-slate-200 border border-slate-700 font-bold touch-manipulation">-25</button>
<button onclick="applyManageDelta(-50)" class="py-2.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-xs sm:text-sm text-slate-200 border border-slate-700 font-bold touch-manipulation">-50</button>
<button onclick="applyManageDelta(-100)" class="py-2.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-xs sm:text-sm text-slate-200 border border-slate-700 font-bold touch-manipulation">-100</button>
<button onclick="setManageAmountRatio(0.5)" class="py-2.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-xs sm:text-sm text-slate-200 border border-slate-700 font-bold touch-manipulation">Half</button>
<button onclick="setManageAmountRatio(0)" class="py-2.5 rounded-xl bg-rose-950/40 hover:bg-rose-900 text-xs sm:text-sm text-rose-300 border border-rose-800 font-bold touch-manipulation">0 (Empty)</button>
</div>
</div>
<!-- Big Confirm Button -->
<button
id="manage-confirm-btn"
onclick="confirmManageExecution()"
class="w-full py-4 rounded-2xl bg-teal-500 hover:bg-teal-400 text-white font-black text-base sm:text-lg shadow-xl shadow-teal-500/25 active:scale-95 transition-all touch-manipulation flex items-center justify-center gap-2"
>
<i data-lucide="check" class="w-6 h-6"></i>
<span id="manage-confirm-label">Confirm Update</span>
</button>
</div>
</div>
</main>
<!-- ADD / EDIT ITEM MODAL -->
<div id="item-modal" class="fixed inset-0 z-50 bg-black/80 backdrop-blur-sm hidden flex items-center justify-center p-3 sm:p-4 overflow-y-auto">
<div class="bg-slate-900 border border-slate-800 rounded-3xl max-w-lg w-full p-5 sm:p-6 shadow-2xl space-y-4 my-8 animate-scale-up">
<div class="flex items-start justify-between">
<div>
<h3 id="item-modal-title" class="text-base sm:text-lg font-bold text-white">Add Product</h3>
<p class="text-xs text-slate-400">Scan or enter product details</p>
</div>
<button onclick="closeItemModal()" class="text-slate-400 hover:text-white p-2 rounded-xl bg-slate-800/60 touch-manipulation">
<i data-lucide="x" class="w-5 h-5"></i>
</button>
</div>
<!-- Barcode Search strip -->
<div class="bg-slate-950 p-2.5 sm:p-3 rounded-2xl border border-slate-800 flex items-center gap-2">
<div class="relative flex-1">
<i data-lucide="barcode" class="w-4 h-4 text-slate-400 absolute left-3 top-1/2 -translate-y-1/2"></i>
<input
type="text"
id="modal-barcode"
placeholder="Barcode (e.g. 4008452023451)"
class="w-full bg-slate-900 border border-slate-800 focus:border-teal-500 rounded-xl pl-9 pr-3 py-2 text-xs sm:text-sm text-white outline-none"
>
</div>
<button type="button" onclick="lookupCurrentBarcode()" id="modal-barcode-lookup-btn" class="px-3.5 py-2 rounded-xl bg-teal-600 hover:bg-teal-500 text-white text-xs sm:text-sm font-bold shrink-0 min-h-[38px] touch-manipulation">
Lookup
</button>
<button type="button" onclick="openScannerModal(true)" class="p-2 rounded-xl bg-slate-800 hover:bg-slate-700 text-slate-300 border border-slate-700 shrink-0 min-h-[38px] min-w-[38px] flex items-center justify-center touch-manipulation" title="Scan with Camera">
<i data-lucide="camera" class="w-4 h-4"></i>
</button>
</div>
<form id="item-form" onsubmit="handleItemFormSubmit(event)" class="space-y-3.5 text-xs sm:text-sm">
<input type="hidden" id="modal-item-id">
<input type="hidden" id="modal-image-url">
<div id="modal-image-container" class="hidden items-center gap-3 p-2.5 bg-slate-950 rounded-2xl border border-slate-800">
<img id="modal-image-preview" src="" alt="Product" class="w-12 h-12 object-contain rounded-xl bg-white/5">
<div class="flex-1 min-w-0">
<span class="text-xs text-teal-400 font-bold">Product Match</span>
<p id="modal-image-label" class="text-xs text-slate-400 truncate"></p>
</div>
</div>
<div class="grid grid-cols-1 sm:grid-cols-3 gap-2.5">
<div class="sm:col-span-2">
<label class="block text-slate-300 font-semibold mb-1">Product Name *</label>
<input type="text" id="modal-name" required placeholder="e.g. Gouda Cheese" class="w-full bg-slate-950 border border-slate-800 focus:border-teal-500 rounded-xl px-3.5 py-2.5 text-white outline-none">
</div>
<div>
<label class="block text-slate-300 font-semibold mb-1">Brand</label>
<input type="text" id="modal-brand" placeholder="e.g. Milbona" class="w-full bg-slate-950 border border-slate-800 focus:border-teal-500 rounded-xl px-3.5 py-2.5 text-white outline-none">
</div>
</div>
<div class="grid grid-cols-3 gap-2.5">
<div>
<label class="block text-slate-300 font-semibold mb-1">Current Amount *</label>
<input type="number" id="modal-quantity" step="any" min="0" required placeholder="250" class="w-full bg-slate-950 border border-slate-800 focus:border-teal-500 rounded-xl px-3.5 py-2.5 text-white outline-none">
</div>
<div>
<label class="block text-slate-300 font-semibold mb-1">1 Full Pack Size *</label>
<input type="number" id="modal-initial-quantity" step="any" min="0" required placeholder="250" class="w-full bg-slate-950 border border-slate-800 focus:border-teal-500 rounded-xl px-3.5 py-2.5 text-white outline-none">
</div>
<div>
<label class="block text-slate-300 font-semibold mb-1">Unit</label>
<select id="modal-unit" class="w-full bg-slate-950 border border-slate-800 focus:border-teal-500 rounded-xl px-3.5 py-2.5 text-white outline-none">
<option value="g">Grams (g)</option>
<option value="ml">Milliliters (ml)</option>
<option value="pcs">Pieces (Stk)</option>
<option value="kg">Kilograms (kg)</option>
<option value="l">Liters (L)</option>
<option value="pack">Pack</option>
<option value="slices">Slices</option>
</select>
</div>
</div>
<div>
<label class="block text-slate-300 font-semibold mb-1">Category</label>
<select id="modal-category" class="w-full bg-slate-950 border border-slate-800 focus:border-teal-500 rounded-xl px-3.5 py-2.5 text-white outline-none">
<!-- Populated dynamically -->
</select>
</div>
<div>
<div class="flex items-center justify-between mb-1">
<label class="block text-slate-300 font-semibold">Expiration Date</label>
<div class="flex items-center gap-2 text-xs">
<button type="button" onclick="setModalExpiryDays(3)" class="text-slate-400 hover:text-teal-400 font-medium">+3d</button>
<span>&bull;</span>
<button type="button" onclick="setModalExpiryDays(7)" class="text-slate-400 hover:text-teal-400 font-medium">+1w</button>
<span>&bull;</span>
<button type="button" onclick="setModalExpiryDays(14)" class="text-slate-400 hover:text-teal-400 font-medium">+2w</button>
<span>&bull;</span>
<button type="button" onclick="setModalExpiryDays(30)" class="text-slate-400 hover:text-teal-400 font-medium">+1m</button>
</div>
</div>
<input type="date" id="modal-expiry" class="w-full bg-slate-950 border border-slate-800 focus:border-teal-500 rounded-xl px-3.5 py-2.5 text-white outline-none">
</div>
<div>
<label class="block text-slate-300 font-semibold mb-1">Notes (Optional)</label>
<input type="text" id="modal-notes" placeholder="e.g. For dinner" class="w-full bg-slate-950 border border-slate-800 focus:border-teal-500 rounded-xl px-3.5 py-2.5 text-white outline-none">
</div>
<div class="flex items-center justify-end gap-3 pt-3 border-t border-slate-800">
<button type="button" onclick="closeItemModal()" class="px-5 py-3 rounded-xl bg-slate-800 hover:bg-slate-700 text-slate-300 text-sm font-medium touch-manipulation">Cancel</button>
<button type="submit" class="px-6 py-3 rounded-xl bg-teal-500 hover:bg-teal-400 text-white text-sm font-bold shadow-lg shadow-teal-500/20 active:scale-95 touch-manipulation">Save Product</button>
</div>
</form>
</div>
</div>
<!-- TABLET LIVE CAMERA BARCODE SCANNER MODAL -->
<div id="scanner-modal" class="fixed inset-0 z-50 bg-black/90 backdrop-blur-md hidden flex items-center justify-center p-3 sm:p-4">
<div class="bg-slate-900 border border-slate-800 rounded-3xl max-w-lg w-full overflow-hidden shadow-2xl flex flex-col animate-scale-up">
<div class="p-4 bg-slate-850 border-b border-slate-800 flex items-center justify-between">
<div class="flex items-center gap-2.5">
<div class="w-8 h-8 rounded-xl bg-teal-500/10 text-teal-400 flex items-center justify-center">
<i data-lucide="scan-barcode" class="w-5 h-5"></i>
</div>
<span class="font-extrabold text-white text-base">Barcode Scanner</span>
</div>
<button onclick="closeScannerModal()" class="text-slate-400 hover:text-white p-2 rounded-xl bg-slate-800/60 touch-manipulation">
<i data-lucide="x" class="w-5 h-5"></i>
</button>
</div>
<!-- Camera Preview -->
<div class="relative bg-black flex items-center justify-center min-h-[300px] sm:min-h-[360px] w-full overflow-hidden">
<div id="barcode-reader" class="w-full"></div>
<div id="scanner-overlay" class="absolute inset-0 pointer-events-none border-2 border-teal-400/50 rounded-3xl m-8 sm:m-12 flex items-center justify-center">
<div class="w-full h-1 bg-red-500/90 animate-pulse shadow-lg shadow-red-500"></div>
</div>
</div>
<!-- Scanner Status & Manual Input -->
<div class="p-4 bg-slate-900 space-y-3">
<div id="scanner-status" class="text-xs sm:text-sm text-center text-slate-400 font-medium">
Point camera at barcode
</div>
<div class="flex items-center gap-2">
<input
type="text"
id="scanner-manual-input"
placeholder="Or type barcode number manually..."
class="flex-1 bg-slate-950 border border-slate-800 focus:border-teal-500 rounded-xl px-3.5 py-2.5 text-xs sm:text-sm text-white outline-none"
onkeydown="if(event.key === 'Enter') handleManualBarcodeSubmit()"
>
<button onclick="handleManualBarcodeSubmit()" class="px-4 py-2.5 rounded-xl bg-teal-600 hover:bg-teal-500 text-white text-xs sm:text-sm font-bold min-h-[42px] touch-manipulation">
Lookup
</button>
</div>
</div>
</div>
</div>
<!-- TOAST NOTIFICATION CONTAINER -->
<div id="toast-container" class="fixed bottom-5 right-5 z-50 flex flex-col gap-2 max-w-sm pointer-events-none"></div>
<!-- MAIN SCRIPT -->
<script src="/app.js"></script>
</body>
</html>