Files
Fridger/public/index.html
T
me0nline 3d89aab10e
Build and Push Fridger Container / Build & Push Fridger Image (push) Successful in 1m23s
feat(ui): add dedicated Filters tab with scrollable categories and pack state cards
2026-10-11 00:00:59 +02:00

669 lines
36 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 - Current Stock & 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 HEADER -->
<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-3">
<!-- Logo & Title -->
<a href="/" onclick="navigateTo('/'); return false;" class="flex items-center gap-2.5 shrink-0 group">
<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 group-hover:scale-105 transition-transform">
🧊
</div>
<div>
<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 id="page-subtitle" class="text-[11px] text-slate-400 font-medium">Current Stock</p>
</div>
</a>
<!-- TOP NAVIGATION SWITCHER -->
<div class="flex items-center bg-slate-950 p-1.5 rounded-2xl border border-slate-800 shadow-inner gap-1">
<!-- 1. Current Stock (/) -->
<button
id="nav-stock-btn"
onclick="navigateTo('/')"
class="flex items-center justify-center gap-2 px-3 sm:px-5 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="layout-grid" class="w-4 h-4 sm:w-5 sm:h-5"></i>
<span>Stock</span>
</button>
<!-- 2. Filters (/filters) -->
<button
id="nav-filters-btn"
onclick="navigateTo('/filters')"
class="relative flex items-center justify-center gap-1.5 sm:gap-2 px-3 sm:px-5 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="filter" class="w-4 h-4 sm:w-5 sm:h-5 text-teal-400"></i>
<span>Filters</span>
<span id="nav-filter-badge" class="hidden px-1.5 py-0.5 text-[10px] font-black rounded-full bg-teal-500 text-white leading-none">0</span>
</button>
<!-- 3. Manager (/manage) -->
<button
id="nav-manage-btn"
onclick="navigateTo('/manage')"
class="flex items-center justify-center gap-2 px-3 sm:px-5 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 text-teal-400"></i>
<span>Manager</span>
</button>
</div>
</div>
</div>
</header>
<!-- ======================================================== -->
<!-- 1. ROOT VIEW: / (CURRENT STOCK ONLY) -->
<!-- ======================================================== -->
<div id="stock-view-page" class="flex-1 flex flex-col">
<!-- Quick Stock Summary 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>Total Stock: <strong id="stat-total" class="text-white font-black text-sm sm:text-base">0</strong> items</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>Full Packs: <strong id="stat-full" 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-indigo-400"></span>
<span>Opened / Partial: <strong id="stat-opened" class="text-indigo-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>Low (&le;25%): <strong id="stat-low" class="text-amber-300 font-bold">0</strong></span>
</div>
</div>
</div>
</section>
<!-- Stock Search & Active Filters Bar -->
<main class="flex-1 max-w-4xl mx-auto px-3 sm:px-6 py-4 w-full space-y-3">
<div class="space-y-2">
<div class="flex gap-2 items-center">
<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 current stock by name, brand, or barcode..."
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>
<button onclick="navigateTo('/filters')" class="px-3.5 py-2.5 rounded-xl bg-slate-900 hover:bg-slate-800 text-slate-300 border border-slate-800 text-xs sm:text-sm font-bold flex items-center gap-1.5 shrink-0 min-h-[42px] touch-manipulation">
<i data-lucide="sliders" class="w-4 h-4 text-teal-400"></i>
<span>Filter</span>
</button>
</div>
<!-- Active Filter Indicator Banner -->
<div id="active-filter-indicator" class="hidden flex items-center justify-between gap-2 p-2 px-3 bg-teal-950/40 border border-teal-500/30 rounded-xl text-xs">
<div class="flex items-center gap-2 min-w-0">
<i data-lucide="filter" class="w-3.5 h-3.5 text-teal-400 shrink-0"></i>
<span id="active-filter-text" class="text-teal-200 truncate font-medium">Filtering by Category: Dairy & Cheese</span>
</div>
<button onclick="resetAllFilters()" class="text-teal-300 hover:text-white underline text-xs shrink-0 font-bold">
Reset
</button>
</div>
</div>
<!-- Current Stock Grid (Display only) -->
<div id="stock-grid" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3.5 sm:gap-4 pt-1">
<!-- Rendered items -->
</div>
<!-- Empty Stock State -->
<div id="empty-stock" 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">No items in stock</h3>
<p class="text-xs sm:text-sm text-slate-400 max-w-xs mx-auto mb-6">No matching items found with the current filters.</p>
<div class="flex items-center justify-center gap-3">
<button onclick="resetAllFilters()" class="px-4 py-2.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-white text-xs sm:text-sm font-bold active:scale-95 touch-manipulation">
Reset Filters
</button>
<button onclick="navigateTo('/manage')" class="px-5 py-2.5 rounded-xl bg-teal-500 hover:bg-teal-400 text-white text-xs sm:text-sm font-bold flex items-center gap-2 shadow-lg shadow-teal-500/20 active:scale-95 touch-manipulation">
<i data-lucide="sliders-horizontal" class="w-4 h-4"></i>
<span>Go to Manager</span>
</button>
</div>
</div>
</main>
</div>
<!-- ======================================================== -->
<!-- 2. FILTERS VIEW: /filters -->
<!-- ======================================================== -->
<div id="filters-view-page" class="hidden flex-1 flex flex-col">
<main class="flex-1 max-w-3xl mx-auto px-3 sm:px-6 py-4 sm:py-6 w-full space-y-6">
<!-- Top Title Bar -->
<div class="flex items-center justify-between">
<div>
<h2 class="text-lg sm:text-xl font-extrabold text-white">Filter Stock</h2>
<p class="text-xs sm:text-sm text-slate-400">Scroll and select pack states and categories</p>
</div>
<button
onclick="resetAllFilters()"
class="px-3.5 py-2 rounded-xl bg-slate-900 hover:bg-slate-800 text-slate-400 hover:text-white border border-slate-800 text-xs sm:text-sm font-bold transition active:scale-95 touch-manipulation"
>
Reset All
</button>
</div>
<!-- Section 1: Pack States (Scrollable cards) -->
<div class="space-y-2.5">
<div class="flex items-center justify-between">
<label class="text-xs font-bold text-teal-400 uppercase tracking-wider">Pack States & Condition</label>
<span class="text-[11px] text-slate-500">Scroll horizontally &rarr;</span>
</div>
<div class="flex items-stretch gap-3 overflow-x-auto pb-2 scrollbar-none pt-1">
<!-- All Pack States -->
<button
onclick="setStatusFilter('all')"
data-filter-status="all"
class="filter-status-card flex-1 min-w-[140px] sm:min-w-[160px] p-4 rounded-2xl border text-left flex flex-col justify-between space-y-3 transition-all active:scale-95 touch-manipulation bg-teal-500/20 border-teal-500 text-white shadow-lg shadow-teal-500/10"
>
<div class="flex items-center justify-between">
<span class="w-8 h-8 rounded-xl bg-teal-500/20 text-teal-300 flex items-center justify-center">
<i data-lucide="layers" class="w-4 h-4"></i>
</span>
<span id="filter-count-all" class="text-xs font-bold px-2 py-0.5 rounded-md bg-slate-800 text-slate-300">0</span>
</div>
<div>
<h4 class="text-sm sm:text-base font-extrabold text-white">All Stock</h4>
<p class="text-[11px] text-slate-400 mt-0.5">Everything in fridge</p>
</div>
</button>
<!-- Full Packs -->
<button
onclick="setStatusFilter('full')"
data-filter-status="full"
class="filter-status-card flex-1 min-w-[140px] sm:min-w-[160px] p-4 rounded-2xl border text-left flex flex-col justify-between space-y-3 transition-all active:scale-95 touch-manipulation bg-slate-900 border-slate-800 text-slate-300 hover:border-slate-700"
>
<div class="flex items-center justify-between">
<span class="w-8 h-8 rounded-xl bg-emerald-500/20 text-emerald-400 flex items-center justify-center">
<i data-lucide="package-check" class="w-4 h-4"></i>
</span>
<span id="filter-count-full" class="text-xs font-bold px-2 py-0.5 rounded-md bg-slate-800 text-emerald-300">0</span>
</div>
<div>
<h4 class="text-sm sm:text-base font-extrabold text-white">Full Packs</h4>
<p class="text-[11px] text-slate-400 mt-0.5">100% unopened items</p>
</div>
</button>
<!-- Opened / In Use -->
<button
onclick="setStatusFilter('opened')"
data-filter-status="opened"
class="filter-status-card flex-1 min-w-[140px] sm:min-w-[160px] p-4 rounded-2xl border text-left flex flex-col justify-between space-y-3 transition-all active:scale-95 touch-manipulation bg-slate-900 border-slate-800 text-slate-300 hover:border-slate-700"
>
<div class="flex items-center justify-between">
<span class="w-8 h-8 rounded-xl bg-indigo-500/20 text-indigo-400 flex items-center justify-center">
<i data-lucide="package-open" class="w-4 h-4"></i>
</span>
<span id="filter-count-opened" class="text-xs font-bold px-2 py-0.5 rounded-md bg-slate-800 text-indigo-300">0</span>
</div>
<div>
<h4 class="text-sm sm:text-base font-extrabold text-white">Opened</h4>
<p class="text-[11px] text-slate-400 mt-0.5">In-use & partial packs</p>
</div>
</button>
<!-- Low Stock -->
<button
onclick="setStatusFilter('low')"
data-filter-status="low"
class="filter-status-card flex-1 min-w-[140px] sm:min-w-[160px] p-4 rounded-2xl border text-left flex flex-col justify-between space-y-3 transition-all active:scale-95 touch-manipulation bg-slate-900 border-slate-800 text-slate-300 hover:border-slate-700"
>
<div class="flex items-center justify-between">
<span class="w-8 h-8 rounded-xl bg-amber-500/20 text-amber-400 flex items-center justify-center">
<i data-lucide="alert-circle" class="w-4 h-4"></i>
</span>
<span id="filter-count-low" class="text-xs font-bold px-2 py-0.5 rounded-md bg-slate-800 text-amber-300">0</span>
</div>
<div>
<h4 class="text-sm sm:text-base font-extrabold text-white">Low Stock</h4>
<p class="text-[11px] text-slate-400 mt-0.5">&le;25% remaining</p>
</div>
</button>
</div>
</div>
<!-- Section 2: Categories (Scrollable touch grid) -->
<div class="space-y-2.5">
<div class="flex items-center justify-between">
<label class="text-xs font-bold text-teal-400 uppercase tracking-wider">Categories</label>
<span class="text-[11px] text-slate-500">Tap to filter</span>
</div>
<div id="filter-categories-container" class="grid grid-cols-2 sm:grid-cols-3 gap-2.5 max-h-[380px] overflow-y-auto p-1 scrollbar-none">
<!-- Populated dynamically with Category Cards -->
</div>
</div>
<!-- Floating Bottom Action Bar -->
<div class="pt-2 sticky bottom-4 z-20">
<button
onclick="navigateTo('/')"
class="w-full py-4 rounded-2xl bg-teal-500 hover:bg-teal-400 text-white font-extrabold text-base sm:text-lg shadow-2xl shadow-teal-500/30 active:scale-95 transition-all touch-manipulation flex items-center justify-center gap-2"
>
<i data-lucide="check" class="w-5 h-5"></i>
<span>View Filtered Stock (<span id="filter-total-count">0</span> items)</span>
</button>
</div>
</main>
</div>
<!-- ======================================================== -->
<!-- 2. MANAGER: /manage -->
<!-- ======================================================== -->
<div id="manage-view-page" class="hidden flex-1 flex flex-col">
<main class="flex-1 max-w-3xl mx-auto px-3 sm:px-6 py-4 sm:py-6 w-full space-y-4">
<!-- STEP 1: SCAN / SEARCH / ADD MANUALLY -->
<div id="tablet-step-select" class="bg-slate-900 border border-slate-800 rounded-3xl p-5 sm:p-7 shadow-xl space-y-5">
<div class="flex items-center justify-between gap-2">
<div>
<h2 class="text-lg sm:text-xl font-extrabold text-white">Manager</h2>
<p class="text-xs sm:text-sm text-slate-400">Scan barcode, search product, or add manually</p>
</div>
<!-- Add Manually Button -->
<button
onclick="openItemModal()"
class="px-4 py-2.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-teal-300 border border-teal-500/30 text-xs sm:text-sm font-bold flex items-center gap-1.5 active:scale-95 touch-manipulation shadow-sm shrink-0"
>
<i data-lucide="plus" class="w-4 h-4"></i>
<span>Add Manually</span>
</button>
</div>
<!-- Integrated Camera Scanner & Live Search Box -->
<div class="grid grid-cols-1 sm:grid-cols-3 gap-3 pt-1">
<!-- Big Camera Scanner Touch Launch -->
<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-[60px]"
>
<i data-lucide="scan-barcode" class="w-6 h-6"></i>
<span class="text-sm sm:text-base">Scan Barcode</span>
</button>
<!-- Search or 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="tablet-search-input"
placeholder="Search product name, brand, or barcode..."
oninput="handleTabletSearch(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-[60px]"
>
</div>
</div>
<!-- Matching Search Results Container (Only shows when searching) -->
<div id="tablet-search-results-container" class="hidden space-y-2 pt-3 border-t border-slate-800">
<label class="text-xs font-bold text-teal-400 uppercase tracking-wider block">Search Results:</label>
<div id="tablet-product-picker" class="grid grid-cols-1 sm:grid-cols-2 gap-2.5 max-h-64 overflow-y-auto p-1 scrollbar-none">
<!-- Populated dynamically when user searches -->
</div>
</div>
</div>
<!-- STEP 2 & 3: PRODUCT ACTION SCREEN (ADD / REMOVE -> PACKET / AMOUNT) -->
<div id="tablet-step-action" class="hidden bg-slate-900 border border-teal-500/40 rounded-3xl p-5 sm:p-6 shadow-2xl space-y-5 animate-scale-up">
<!-- Product Header Banner -->
<div class="bg-slate-950 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="action-product-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="action-product-name" class="font-extrabold text-white text-base sm:text-lg truncate">Selected Product</h3>
<p id="action-product-sub" class="text-xs sm:text-sm text-slate-400 mt-0.5">Current Stock: 250g &bull; 1 Pack = 250g</p>
</div>
</div>
<button onclick="cancelActionAndReturnToManage()" 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>
<!-- Choose Action: Add or Remove -->
<div class="space-y-2.5">
<label class="text-xs font-bold text-slate-400 uppercase tracking-wider block">Choose Action:</label>
<div class="grid grid-cols-2 gap-3 sm:gap-4">
<button
id="action-btn-add"
onclick="setActionType('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-[84px] 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 Stock</span>
</button>
<button
id="action-btn-remove"
onclick="setActionType('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-[84px] 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 Stock</span>
</button>
</div>
</div>
<!-- Choose Mode: Whole Packet vs Specific Grams -->
<div id="action-qty-section" class="hidden space-y-4 pt-2 border-t border-slate-800">
<div class="grid grid-cols-2 gap-2 p-1.5 bg-slate-950 rounded-2xl border border-slate-800">
<button
id="btn-mode-packet"
onclick="setActionQtyMode('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="btn-mode-amount"
onclick="setActionQtyMode('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>
<!-- Packet Controls -->
<div id="controls-packet" 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 Full Packet = <strong id="action-pack-size-label" class="text-teal-300 font-bold">250g</strong>
</div>
<div class="flex items-center justify-center gap-4">
<button onclick="changeActionPackCount(-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="action-pack-count-val">1</span> <span class="text-sm font-normal text-slate-400">pack</span>
</div>
<button onclick="changeActionPackCount(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>
<div class="flex items-center justify-center gap-2">
<button onclick="setActionPackCount(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="setActionPackCount(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="setActionPackCount(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>
<!-- Specific Grams Controls (Slider & Quick Chips) -->
<div id="controls-amount" 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="action-amount-val">150</span>
<span id="action-amount-unit" class="text-base font-normal text-teal-400">g</span>
</div>
<div class="text-xs text-slate-400 mt-1 font-medium">New remaining amount in stock</div>
</div>
<input
type="range"
id="action-amount-slider"
min="0"
max="500"
step="5"
value="150"
oninput="onActionAmountSlider(this.value)"
class="w-full accent-teal-500 cursor-pointer h-3.5 bg-slate-800 rounded-xl"
>
<div class="grid grid-cols-3 sm:grid-cols-6 gap-2">
<button onclick="applyActionDelta(-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="applyActionDelta(-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="applyActionDelta(-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="applyActionDelta(-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="setActionAmountRatio(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="setActionAmountRatio(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>
<!-- Confirm & Finish (Returns back to /manage) -->
<div class="flex items-center gap-3 pt-2">
<button
onclick="cancelActionAndReturnToManage()"
class="px-5 py-4 rounded-2xl bg-slate-800 hover:bg-slate-700 text-slate-300 font-bold text-sm touch-manipulation"
>
Cancel
</button>
<button
id="action-confirm-btn"
onclick="confirmAndFinishAction()"
class="flex-1 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="action-confirm-label">Confirm & Done</span>
</button>
</div>
</div>
</div>
</main>
</div>
<!-- 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 Manually</h3>
<p class="text-xs text-slate-400">Enter product name and package size</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 Lookup row -->
<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. Frozen Berries" 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. Bio" 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="500" 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="500" 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>
<label class="block text-slate-300 font-semibold mb-1">Notes (Optional)</label>
<input type="text" id="modal-notes" placeholder="e.g. In freezer top basket" 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 Viewfinder -->
<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>
<!-- Status & Manual fallback -->
<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">
Hold product barcode in front of camera
</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>