Build [v1.10.4]
This commit is contained in:
@@ -252,10 +252,10 @@ export default function InventoryPage() {
|
||||
<div className="p-3 md:p-4 bg-primary/10 rounded-3xl text-primary border border-primary/20 shadow-xl shadow-primary/5">
|
||||
<Package size={28} className="md:w-8 md:h-8" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-2xl md:text-3xl font-black tracking-tight text-white leading-tight">Inventory Catalog</h1>
|
||||
<p className="text-[10px] md:text-xs text-slate-500 font-bold mt-0.5">Enterprise Stock Overview</p>
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-2xl md:text-3xl font-black tracking-tight text-white leading-tight">Inventory Catalog</h1>
|
||||
<p className="text-xs md:text-sm text-slate-400 font-bold mt-1 uppercase tracking-widest">Enterprise Stock Overview</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setShowBoxManager(true)}
|
||||
className="ml-auto p-3 bg-slate-900 border border-slate-800 text-slate-400 rounded-2xl hover:text-primary transition-all active:scale-95 shadow-xl"
|
||||
@@ -311,12 +311,12 @@ export default function InventoryPage() {
|
||||
<div className="w-10 h-10 rounded-2xl bg-primary/10 flex items-center justify-center text-primary transition-colors">
|
||||
<Layers size={20} />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<h3 className="font-bold text-lg">{cat}</h3>
|
||||
<p className="text-[9px] font-black text-slate-400">
|
||||
{inventory.filter(i => i.category === cat).length} Item types in stock
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<h3 className="font-bold text-lg">{cat}</h3>
|
||||
<p className="text-xs font-bold text-slate-400 mt-1 uppercase tracking-tight">
|
||||
{inventory.filter(i => i.category === cat).length} Item types in stock
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
{expandedCategory === cat ? <ChevronDown size={20} className="text-primary" /> : <ChevronRight size={20} className="text-slate-600" />}
|
||||
@@ -353,20 +353,20 @@ export default function InventoryPage() {
|
||||
<div className="w-8 h-8 rounded-xl bg-green-500/10 flex items-center justify-center text-green-500 shrink-0">
|
||||
<Package size={14} />
|
||||
</div>
|
||||
<div className="truncate">
|
||||
<h4 className="font-bold text-slate-200 truncate">{item.name}</h4>
|
||||
<p className="text-[10px] text-slate-500 truncate mt-0.5">{item.specs}</p>
|
||||
</div>
|
||||
<div className="truncate">
|
||||
<h4 className="font-bold text-slate-200 truncate">{item.name}</h4>
|
||||
<p className="text-xs text-slate-400 truncate mt-1">{item.specs}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-right shrink-0">
|
||||
<span className={cn(
|
||||
"text-lg font-black",
|
||||
item.quantity <= item.min_quantity ? "text-amber-500" : "text-primary"
|
||||
)}>
|
||||
{item.quantity}
|
||||
</span>
|
||||
<p className="text-xs text-slate-600 font-bold">Stock</p>
|
||||
</div>
|
||||
{item.quantity}
|
||||
</span>
|
||||
<p className="text-sm text-slate-500 font-bold uppercase tracking-tight">Stock</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -389,12 +389,12 @@ export default function InventoryPage() {
|
||||
<div className="w-full max-w-lg bg-slate-900 border-x border-t sm:border border-slate-800 rounded-t-[2.5rem] sm:rounded-[2.5rem] shadow-2xl p-5 sm:p-8 overflow-hidden animate-in slide-in-from-bottom-10 duration-300">
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<h3 className="text-xl font-black tracking-tight flex items-center gap-2">
|
||||
{isEditing ? "Edit Item" : selectedItem.name}
|
||||
{!isEditing && (
|
||||
<span className="text-[10px] bg-slate-800 text-slate-400 px-2 py-0.5 rounded-md font-black uppercase">
|
||||
In Stock: {selectedItem.quantity}
|
||||
</span>
|
||||
)}
|
||||
{isEditing ? "Edit Item" : selectedItem.name}
|
||||
{!isEditing && (
|
||||
<span className="text-xs bg-slate-800 text-slate-300 px-3 py-1 rounded-lg font-bold uppercase tracking-tight">
|
||||
In Stock: {selectedItem.quantity}
|
||||
</span>
|
||||
)}
|
||||
</h3>
|
||||
<div className="flex gap-2">
|
||||
{!isEditing && (
|
||||
@@ -431,8 +431,8 @@ export default function InventoryPage() {
|
||||
|
||||
{isEditing ? (
|
||||
<div className="max-h-[60vh] overflow-y-auto pr-2 space-y-4 mb-6 scrollbar-hide">
|
||||
<div>
|
||||
<label className="text-[11px] font-black text-slate-500 ml-1 uppercase tracking-wider">Item Name</label>
|
||||
<div>
|
||||
<label className="text-sm font-bold text-slate-400 ml-1 uppercase tracking-tight">Item Name</label>
|
||||
<input
|
||||
type="text"
|
||||
value={editedItem.name || ''}
|
||||
@@ -440,8 +440,8 @@ export default function InventoryPage() {
|
||||
className="w-full bg-slate-950 border border-slate-800 rounded-xl py-3 px-4 text-sm font-bold outline-none text-slate-100 placeholder:text-slate-700"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[11px] font-black text-slate-500 ml-1 uppercase tracking-wider">Part Number</label>
|
||||
<div>
|
||||
<label className="text-sm font-bold text-slate-400 ml-1 uppercase tracking-tight">Part Number</label>
|
||||
<input
|
||||
type="text"
|
||||
value={editedItem.part_number || ''}
|
||||
@@ -450,8 +450,8 @@ export default function InventoryPage() {
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="text-[11px] font-black text-slate-500 ml-1 uppercase tracking-wider">Category</label>
|
||||
<div>
|
||||
<label className="text-sm font-bold text-slate-400 ml-1 uppercase tracking-tight">Category</label>
|
||||
<input
|
||||
type="text"
|
||||
list="existing-categories"
|
||||
@@ -466,8 +466,8 @@ export default function InventoryPage() {
|
||||
))}
|
||||
</datalist>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[11px] font-black text-slate-500 ml-1 uppercase tracking-wider">Item Type</label>
|
||||
<div>
|
||||
<label className="text-sm font-bold text-slate-400 ml-1 uppercase tracking-tight">Item Type</label>
|
||||
<input
|
||||
type="text"
|
||||
list="existing-types"
|
||||
@@ -476,8 +476,8 @@ export default function InventoryPage() {
|
||||
className="w-full bg-slate-950 border border-slate-800 rounded-xl py-3 px-4 text-sm font-bold outline-none text-slate-100"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[11px] font-black text-slate-500 ml-1 uppercase tracking-wider">Connector</label>
|
||||
<div>
|
||||
<label className="text-sm font-bold text-slate-400 ml-1 uppercase tracking-tight">Connector</label>
|
||||
<input
|
||||
type="text"
|
||||
value={editedItem.connector || ''}
|
||||
@@ -486,8 +486,8 @@ export default function InventoryPage() {
|
||||
placeholder="e.g. LC/UPC"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[11px] font-black text-slate-500 ml-1 uppercase tracking-wider">Size / Length</label>
|
||||
<div>
|
||||
<label className="text-sm font-bold text-slate-400 ml-1 uppercase tracking-tight">Size / Length</label>
|
||||
<input
|
||||
type="text"
|
||||
value={editedItem.size || ''}
|
||||
@@ -496,8 +496,8 @@ export default function InventoryPage() {
|
||||
placeholder="e.g. 1.6TB"
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<label className="text-[11px] font-black text-slate-500 ml-1 uppercase tracking-wider">Item Color</label>
|
||||
<div className="col-span-2">
|
||||
<label className="text-sm font-bold text-slate-400 ml-1 uppercase tracking-tight">Item Color</label>
|
||||
<input
|
||||
type="text"
|
||||
value={editedItem.color || ''}
|
||||
@@ -506,8 +506,8 @@ export default function InventoryPage() {
|
||||
placeholder="e.g. Blue"
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<label className="text-[11px] font-black text-slate-500 ml-1 uppercase tracking-wider">Box / Container Label</label>
|
||||
<div className="col-span-2">
|
||||
<label className="text-sm font-bold text-slate-400 ml-1 uppercase tracking-tight">Box / Container Label</label>
|
||||
<div className="relative flex items-center">
|
||||
<input
|
||||
type="text"
|
||||
@@ -534,16 +534,16 @@ export default function InventoryPage() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[11px] font-black text-slate-500 ml-1 uppercase tracking-wider">Specs / Comments</label>
|
||||
<div>
|
||||
<label className="text-sm font-bold text-slate-400 ml-1 uppercase tracking-tight">Specs / Comments</label>
|
||||
<textarea
|
||||
value={editedItem.specs || ''}
|
||||
onChange={e => setEditedItem({...editedItem, specs: e.target.value})}
|
||||
className="w-full bg-slate-950 border border-slate-800 rounded-xl py-3 px-4 text-sm font-bold outline-none text-slate-100 h-20 resize-none"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-[11px] font-black text-slate-500 ml-1 uppercase tracking-wider">OCR Matching Key</label>
|
||||
<div>
|
||||
<label className="text-sm font-bold text-slate-400 ml-1 uppercase tracking-tight">OCR Matching Key</label>
|
||||
<textarea
|
||||
value={editedItem.ocr_text || ''}
|
||||
onChange={e => setEditedItem({...editedItem, ocr_text: e.target.value})}
|
||||
@@ -567,9 +567,9 @@ export default function InventoryPage() {
|
||||
adjustType === t.id ? "bg-slate-800 shadow-lg" : "text-slate-500"
|
||||
)}
|
||||
>
|
||||
<t.icon size={20} className={adjustType === t.id ? t.color : ""} />
|
||||
<span className="text-xs font-black mt-1">{t.label}</span>
|
||||
</button>
|
||||
<t.icon size={20} className={adjustType === t.id ? t.color : ""} />
|
||||
<span className="text-sm font-bold mt-1.5 uppercase tracking-tight">{t.label}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -641,8 +641,8 @@ export default function InventoryPage() {
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="text-xs font-black text-slate-500 ml-1">Name</label>
|
||||
<div>
|
||||
<label className="text-sm font-bold text-slate-400 ml-1 uppercase tracking-tight">Name</label>
|
||||
<input
|
||||
type="text"
|
||||
value={catEditedName}
|
||||
@@ -650,8 +650,8 @@ export default function InventoryPage() {
|
||||
className="w-full bg-slate-950 border border-slate-800 rounded-xl py-3 px-4 text-sm outline-none text-slate-100"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-xs font-black text-slate-500 ml-1">Description</label>
|
||||
<div>
|
||||
<label className="text-sm font-bold text-slate-400 ml-1 uppercase tracking-tight">Description</label>
|
||||
<textarea
|
||||
value={catEditedDesc}
|
||||
onChange={e => setCatEditedDesc(e.target.value)}
|
||||
@@ -736,18 +736,18 @@ export default function InventoryPage() {
|
||||
<p className="text-xs text-slate-500 font-bold mt-0.5">{itemCount} items linked</p>
|
||||
</div>
|
||||
<div className="flex gap-2 shrink-0">
|
||||
<button
|
||||
onClick={() => setSelectedBoxLabel(box)}
|
||||
className="flex-1 py-3 bg-primary text-white text-[11px] font-black rounded-xl flex items-center justify-center gap-2 hover:bg-blue-500 transition-colors shadow-lg shadow-primary/10 active:scale-95"
|
||||
>
|
||||
<Printer size={14} /> Print Label
|
||||
</button>
|
||||
<button
|
||||
onClick={() => { setSearchQuery(box); setShowBoxManager(false); setBoxSearchQuery(''); }}
|
||||
className="px-4 py-3 bg-slate-900 border border-slate-800 text-slate-400 text-[11px] font-bold rounded-xl hover:bg-slate-800 active:scale-95"
|
||||
>
|
||||
View
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setSelectedBoxLabel(box)}
|
||||
className="flex-1 py-3 bg-primary text-white text-xs font-black rounded-xl flex items-center justify-center gap-2 hover:bg-blue-500 transition-colors shadow-lg shadow-primary/10 active:scale-95"
|
||||
>
|
||||
<Printer size={14} /> Print Label
|
||||
</button>
|
||||
<button
|
||||
onClick={() => { setSearchQuery(box); setShowBoxManager(false); setBoxSearchQuery(''); }}
|
||||
className="px-4 py-3 bg-slate-900 border border-slate-800 text-slate-400 text-xs font-bold rounded-xl hover:bg-slate-800 active:scale-95"
|
||||
>
|
||||
View
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -757,9 +757,9 @@ export default function InventoryPage() {
|
||||
</div>
|
||||
|
||||
<div className="p-6 py-4 bg-slate-950/50 border-t border-slate-800 text-center flex items-center justify-center gap-2">
|
||||
<div className="w-1 h-1 rounded-full bg-primary animate-pulse" />
|
||||
<p className="text-[10px] text-slate-500 font-bold font-mono">TFM aInventory • Box management mode</p>
|
||||
</div>
|
||||
<div className="w-1 h-1 rounded-full bg-primary animate-pulse" />
|
||||
<p className="text-xs text-slate-400 font-bold font-mono">TFM aInventory • Box management mode</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -775,11 +775,10 @@ export default function InventoryPage() {
|
||||
</h2>
|
||||
|
||||
<div className="w-full aspect-[2/1] bg-white flex flex-col items-center justify-center overflow-hidden" dangerouslySetInnerHTML={{ __html: generateBarcode128(selectedBoxLabel) }} />
|
||||
|
||||
<div className="flex flex-col items-center gap-1">
|
||||
<p className="text-[10px] font-black tracking-[0.2em] text-black/50">TFM INVENTORY BOX LABEL</p>
|
||||
<img src={getQRCodeURL(selectedBoxLabel)} className="w-24 h-24" alt="QR Code" />
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-1">
|
||||
<p className="text-xs font-black tracking-[0.2em] text-black/50">TFM INVENTORY BOX LABEL</p>
|
||||
<img src={getQRCodeURL(selectedBoxLabel)} className="w-24 h-24" alt="QR Code" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-3 no-print">
|
||||
|
||||
Reference in New Issue
Block a user