- Category
+ Category
setEditedItem({ ...editedItem, category: 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 placeholder:text-slate-700"
+ className="w-full bg-background border border-slate-800 rounded-xl py-3 px-4 text-sm font-bold outline-none text-slate-100 placeholder:text-slate-700"
placeholder="e.g. storage"
/>
@@ -467,54 +467,54 @@ export default function InventoryPage() {
- Item Type
+ Item Type
setEditedItem({...editedItem, type: 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"
+ className="w-full bg-background border border-slate-800 rounded-xl py-3 px-4 text-sm font-bold outline-none text-slate-100"
/>
- Connector
+ Connector
setEditedItem({...editedItem, connector: 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"
+ className="w-full bg-background border border-slate-800 rounded-xl py-3 px-4 text-sm font-bold outline-none text-slate-100"
placeholder="e.g. LC/UPC"
/>
- Size / Length
+ Size / Length
setEditedItem({...editedItem, size: 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"
+ className="w-full bg-background border border-slate-800 rounded-xl py-3 px-4 text-sm font-bold outline-none text-slate-100"
placeholder="e.g. 1.6TB"
/>
- Item Color
+ Item Color
setEditedItem({...editedItem, color: 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"
+ className="w-full bg-background border border-slate-800 rounded-xl py-3 px-4 text-sm font-bold outline-none text-slate-100"
placeholder="e.g. Blue"
/>
-
Box / Container Label
+
Box / Container Label
setEditedItem({...editedItem, box_label: e.target.value})}
- className="w-full bg-slate-950 border border-slate-800 rounded-xl py-3 pl-4 pr-12 text-sm font-bold outline-none text-slate-100 placeholder:text-slate-700 focus:border-primary transition-colors"
+ className="w-full bg-background border border-slate-800 rounded-xl py-3 pl-4 pr-12 text-sm font-bold outline-none text-slate-100 placeholder:text-slate-700 focus:border-primary transition-colors"
placeholder="e.g. Box 5"
/>
@@ -535,25 +535,25 @@ export default function InventoryPage() {
- Specs / Comments
+ Specs / Comments
- OCR Matching Key
+ OCR Matching Key
+
{[
{ id: 'ADD', label: 'Buy More', icon: Plus, color: 'text-primary' },
{ id: 'REMOVE', label: 'Subtract', icon: Minus, color: 'text-amber-500' },
@@ -564,7 +564,7 @@ export default function InventoryPage() {
onClick={() => setAdjustType(t.id as any)}
className={cn(
"flex-1 flex flex-col items-center py-3 rounded-xl transition-all",
- adjustType === t.id ? "bg-slate-800 shadow-lg" : "text-slate-500"
+ adjustType === t.id ? "bg-slate-800 shadow-lg" : "text-muted"
)}
>
@@ -595,7 +595,7 @@ export default function InventoryPage() {
setTrashReason(e.target.value)}
- className="w-full bg-slate-950 border border-slate-800 rounded-xl py-3 px-4 text-sm outline-none text-slate-300"
+ className="w-full bg-background border border-slate-800 rounded-xl py-3 px-4 text-sm outline-none text-slate-300"
>
Damaged
Expired
@@ -631,31 +631,31 @@ export default function InventoryPage() {
{/* Category Edit Overlay */}
{editingCategory && (
-
-
+
+
Edit Category
- setEditingCategory(null)} className="p-2 hover:bg-slate-800 rounded-full transition-colors text-slate-400">
+ setEditingCategory(null)} className="p-2 hover:bg-slate-800 rounded-full transition-colors text-secondary">
@@ -680,18 +680,18 @@ export default function InventoryPage() {
{/* Box Manager Modal */}
{showBoxManager && (
-
-
-
+
+
+
Box Inventory
-
Manage physical box labels & printing
+
Manage physical box labels & printing
-
{ setShowBoxManager(false); setBoxSearchQuery(''); }} className="p-3 hover:bg-slate-800 rounded-full transition-colors text-slate-400">
+ { setShowBoxManager(false); setBoxSearchQuery(''); }} className="p-3 hover:bg-slate-800 rounded-full transition-colors text-secondary">
@@ -702,13 +702,13 @@ export default function InventoryPage() {
placeholder="Search boxes..."
value={boxSearchQuery}
onChange={(e) => setBoxSearchQuery(e.target.value)}
- className="w-full bg-slate-950 border border-slate-800 rounded-2xl py-3.5 pl-11 pr-4 text-sm focus:border-primary outline-none transition-all placeholder:text-slate-600"
+ className="w-full bg-background border border-slate-800 rounded-2xl py-3.5 pl-11 pr-4 text-sm focus:border-primary outline-none transition-all placeholder:text-secondary"
/>
-
+
{boxSearchQuery && (
setBoxSearchQuery('')}
- className="absolute right-3 top-1/2 -translate-y-1/2 p-1.5 hover:bg-slate-800 rounded-lg text-slate-500"
+ className="absolute right-3 top-1/2 -translate-y-1/2 p-1.5 hover:bg-slate-800 rounded-lg text-muted"
>
@@ -730,10 +730,10 @@ export default function InventoryPage() {
.map(box => {
const itemCount = inventory.filter(i => i.box_label === box).length;
return (
-
+
{box}
-
{itemCount} items linked
+
{itemCount} items linked
{ 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"
+ className="px-4 py-3 bg-surface border border-slate-800 text-secondary text-xs font-bold rounded-xl hover:bg-slate-800 active:scale-95"
>
View
@@ -756,9 +756,9 @@ export default function InventoryPage() {
)}
-
+
-
TFM aInventory • Box management mode
+
TFM aInventory • Box management mode
@@ -813,14 +813,14 @@ export default function InventoryPage() {
img.src = "data:image/svg+xml;base64," + btoa(svgData);
}
}}
- className="w-full py-4 bg-slate-900 border border-slate-800 text-white rounded-[2rem] font-black text-sm flex items-center justify-center gap-2 active:scale-95 transition-all"
+ className="w-full py-4 bg-surface border border-slate-800 text-white rounded-[2rem] font-black text-sm flex items-center justify-center gap-2 active:scale-95 transition-all"
>
Save for Mobile App
setSelectedBoxLabel(null)}
- className="w-full py-4 text-slate-500 font-bold text-xs"
+ className="w-full py-4 text-muted font-bold text-xs"
>
Cancel
diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx
index 22847817..c901c304 100644
--- a/frontend/app/layout.tsx
+++ b/frontend/app/layout.tsx
@@ -30,7 +30,7 @@ export default function RootLayout({
-
+
{children}
diff --git a/frontend/app/login/page.tsx b/frontend/app/login/page.tsx
index 1af3031d..a50bbb64 100644
--- a/frontend/app/login/page.tsx
+++ b/frontend/app/login/page.tsx
@@ -79,16 +79,16 @@ export default function LoginPage() {
if (!mounted) return null;
return (
-
+
-
+
Identity Check
-
Select operator profile or use direct login
+
Select operator profile or use direct login
@@ -103,20 +103,20 @@ export default function LoginPage() {
className="bg-slate-800/50 hover:bg-slate-800 border border-slate-800 hover:border-primary/40 p-4 rounded-2xl text-left transition-all group flex items-center justify-between"
>
-
+
{user.role === 'admin' ? : }
{user.username}
-
{user.role}
+
{user.role}
-
+
))}
>
) : (
-
+
Connectivity issues? Use manual login below.
)}
@@ -124,7 +124,7 @@ export default function LoginPage() {
setIsEnterprise(true)}
- className="flex items-center justify-center gap-2 py-4 rounded-2xl border border-dashed border-slate-700 text-slate-500 hover:text-white hover:border-slate-500 transition-all font-bold text-xs"
+ className="flex items-center justify-center gap-2 py-4 rounded-2xl border border-dashed border-slate-700 text-muted hover:text-white hover:border-slate-500 transition-all font-bold text-xs"
>
Enterprise
@@ -144,7 +144,7 @@ export default function LoginPage() {
) : isEnterprise ? (
-
Enterprise Account
+
Enterprise Account
setIsEnterprise(false)}
className="text-xs font-black text-primary hover:underline"
@@ -154,9 +154,9 @@ export default function LoginPage() {
-
Username
+
Username
-
+
-
Password
+
Password
-
+
setSelectedUserForLogin(null)}
className="p-1 hover:bg-slate-700 rounded-lg transition-colors"
>
-
+
-
Logging in as
+
Logging in as
{selectedUserForLogin.username || "Manual Input"}
{!selectedUserForLogin.username && (
-
Username
+
Username
-
+
-
Password
+
Password
-
+
Operations Audit
-
Real-time Intervention Tracking
+
Real-time Intervention Tracking
@@ -103,7 +103,7 @@ export default function LogsPage() {
Sync Logs
@@ -142,9 +142,9 @@ export default function LogsPage() {
placeholder="Filter by user, action or asset..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
- className="w-full bg-slate-900/40 border border-slate-800 rounded-2xl py-3.5 pr-4 pl-12 text-sm focus:border-primary outline-none transition-all placeholder:text-slate-600 shadow-2xl"
+ className="w-full bg-surface/50 border border-slate-800 rounded-2xl py-3.5 pr-4 pl-12 text-sm focus:border-primary outline-none transition-all placeholder:text-secondary shadow-2xl"
/>
-
@@ -156,7 +156,7 @@ export default function LogsPage() {
"px-5 py-2 rounded-full text-xs font-bold transition-all whitespace-nowrap border uppercase tracking-widest",
filterAction === 'ALL'
? "bg-white text-slate-950 border-white shadow-xl shadow-white/10"
- : "bg-slate-900/50 text-slate-400 border-slate-800 hover:border-slate-700"
+ : "bg-surface/70 text-secondary border-slate-800 hover:border-slate-700"
)}
>
All Streams
@@ -169,7 +169,7 @@ export default function LogsPage() {
"px-5 py-2 rounded-full text-xs font-bold transition-all whitespace-nowrap border uppercase tracking-widest",
filterAction === f
? "bg-primary text-white border-primary shadow-xl shadow-primary/10"
- : "bg-slate-900/50 text-slate-400 border-slate-800 hover:border-slate-700"
+ : "bg-surface/70 text-secondary border-slate-800 hover:border-slate-700"
)}
>
{f}
@@ -180,18 +180,18 @@ export default function LogsPage() {
{loading ? (
-
+
) : filteredLogs.length === 0 ? (
-
-
+
+
No events found
-
Refine your strategic filters
+
Refine your strategic filters
) : (
@@ -200,7 +200,7 @@ export default function LogsPage() {
setSelectedLog(log)}
- className="w-full text-left bg-slate-900/40 border border-slate-800/30 p-3 px-4 rounded-2xl flex items-center justify-between gap-4 hover:bg-slate-800/40 hover:border-primary/30 transition-all group active:scale-[0.99] relative overflow-hidden shadow-sm"
+ className="w-full text-left bg-surface/50 border border-slate-800/30 p-3 px-4 rounded-2xl flex items-center justify-between gap-4 hover:bg-slate-800/40 hover:border-primary/30 transition-all group active:scale-[0.99] relative overflow-hidden shadow-sm"
>
{/* Compact Action Badge */}
@@ -245,8 +245,8 @@ export default function LogsPage() {
{/* Selected Log Modal */}
{selectedLog && (
-
-
+
+
-
setSelectedLog(null)} className="p-3 bg-slate-800/50 hover:bg-slate-800 rounded-2xl text-slate-500 transition-colors border border-slate-800 shrink-0 shadow-lg">
+ setSelectedLog(null)} className="p-3 bg-slate-800/50 hover:bg-slate-800 rounded-2xl text-muted transition-colors border border-slate-800 shrink-0 shadow-lg">
-
-
Protocol Operator
+
+
Protocol Operator
{selectedLog.username || 'Automated Process'}
-
-
Quantity Delta
+
+
Quantity Delta
0 ? "text-green-500" : "text-rose-500"
@@ -285,8 +285,8 @@ export default function LogsPage() {
-
Universal Timestamp
-
+
Universal Timestamp
+
{new Date(selectedLog.timestamp).toLocaleString(undefined, { dateStyle: 'full', timeStyle: 'medium' })}
@@ -304,8 +304,8 @@ export default function LogsPage() {
{Object.entries(snap).map(([key, val]) => (
(val && key !== 'image_url' && key !== 'id') ? (
-
-
{key.replace('_', ' ')}
+
+
{key.replace('_', ' ')}
{String(val)}
) : null
@@ -318,7 +318,7 @@ export default function LogsPage() {
{selectedLog.details && (
-
Intervention Details
+
Intervention Details
"{selectedLog.details}"
diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx
index 91e12aa2..5afe138b 100644
--- a/frontend/app/page.tsx
+++ b/frontend/app/page.tsx
@@ -548,11 +548,11 @@ export default function Home() {
Inventory Control
-
Check-in, Check-out & Trash Operations
+
Check-in, Check-out & Trash Operations
-
+
{isScannerReady && (
@@ -573,7 +573,7 @@ export default function Home() {
@@ -583,7 +583,7 @@ export default function Home() {
{/* Mode Switcher */}
-
+
{[
{ id: 'CHECK_IN', label: 'Check In', icon: ArrowDownCircle },
{ id: 'CHECK_OUT', label: 'Check Out', icon: ArrowUpCircle },
@@ -594,7 +594,7 @@ export default function Home() {
onClick={() => setMode(m.id as any)}
className={cn(
"flex-1 py-3.5 rounded-xl text-xs sm:text-sm font-black transition-all flex items-center justify-center gap-3",
- mode === m.id ? "bg-slate-800 text-primary shadow-lg ring-1 ring-primary/20" : "text-slate-500 hover:text-slate-300"
+ mode === m.id ? "bg-slate-800 text-primary shadow-lg ring-1 ring-primary/20" : "text-muted hover:text-slate-300"
)}
>
@@ -611,7 +611,7 @@ export default function Home() {
scanning...
setShowScanner(false)}
- className="p-2.5 bg-slate-900 border border-slate-800 text-slate-400 rounded-xl hover:text-rose-500 transition-all active:scale-95"
+ className="p-2.5 bg-surface border border-slate-800 text-secondary rounded-xl hover:text-rose-500 transition-all active:scale-95"
>
@@ -668,13 +668,13 @@ export default function Home() {
{/* Stock Adjustment Overlay */}
{selectedItem && (
-
-
+
+
{isEditing ? "Edit Metadata" : selectedItem.name}
{!isEditing && (
-
+
In Stock: {selectedItem.quantity}
)}
@@ -686,7 +686,7 @@ export default function Home() {
setEditedItem(selectedItem);
setIsEditing(true);
}}
- className="p-2 hover:bg-slate-800 rounded-full text-slate-400"
+ className="p-2 hover:bg-slate-800 rounded-full text-secondary"
>
@@ -714,8 +714,8 @@ export default function Home() {
{isEditing ? (
-
-
Item Name
+
+ Item Name
- Part Number
+ Part Number
setEditedItem({ ...editedItem, part_number: e.target.value })}
- className="w-full bg-slate-950 border border-slate-800 rounded-xl py-3 px-4 text-sm font-mono outline-none text-slate-100"
+ className="w-full bg-background border border-slate-800 rounded-xl py-3 px-4 text-sm font-mono outline-none text-slate-100"
placeholder="e.g. PN-12345"
/>
- Category Group
+ Category Group
setEditedItem({ ...editedItem, category: e.target.value })}
- className="w-full bg-slate-950 border border-slate-800 rounded-xl py-3 px-4 text-sm outline-none text-slate-100 placeholder:text-slate-700"
+ className="w-full bg-background border border-slate-800 rounded-xl py-3 px-4 text-sm outline-none text-slate-100 placeholder:text-slate-700"
placeholder="e.g. storage"
/>
@@ -752,25 +752,25 @@ export default function Home() {
- Item Type
+ Item Type
setEditedItem({...editedItem, type: e.target.value})}
- className="w-full bg-slate-950 border border-slate-800 rounded-xl py-3 px-4 text-sm outline-none text-slate-100"
+ className="w-full bg-background border border-slate-800 rounded-xl py-3 px-4 text-sm outline-none text-slate-100"
placeholder="e.g. spare parts"
/>
-
Box / Container Label
+
Box / Container Label
setEditedItem({...editedItem, box_label: e.target.value})}
- className="w-full bg-slate-950 border border-slate-800 rounded-xl py-3 pl-4 pr-12 text-sm outline-none text-slate-100 placeholder:text-slate-700 focus:border-primary transition-colors"
+ className="w-full bg-background border border-slate-800 rounded-xl py-3 pl-4 pr-12 text-sm outline-none text-slate-100 placeholder:text-slate-700 focus:border-primary transition-colors"
placeholder="e.g. SFPs 40G Cisco"
/>
@@ -790,50 +790,50 @@ export default function Home() {
- Connector
+ Connector
setEditedItem({...editedItem, connector: e.target.value})}
- className="w-full bg-slate-950 border border-slate-800 rounded-xl py-3 px-4 text-sm outline-none text-slate-100"
+ className="w-full bg-background border border-slate-800 rounded-xl py-3 px-4 text-sm outline-none text-slate-100"
placeholder="e.g. LC/UPC"
/>
- Size / Length
+ Size / Length
setEditedItem({...editedItem, size: e.target.value})}
- className="w-full bg-slate-950 border border-slate-800 rounded-xl py-3 px-4 text-sm outline-none text-slate-100"
+ className="w-full bg-background border border-slate-800 rounded-xl py-3 px-4 text-sm outline-none text-slate-100"
placeholder="e.g. 5m / 1600GB"
/>
- Item Color
+ Item Color
setEditedItem({...editedItem, color: e.target.value})}
- className="w-full bg-slate-950 border border-slate-800 rounded-xl py-3 px-4 text-sm outline-none text-slate-100"
+ className="w-full bg-background border border-slate-800 rounded-xl py-3 px-4 text-sm outline-none text-slate-100"
placeholder="e.g. Black"
/>
- Description
+ Description
-
-
Item ID or Code
+
+ Item ID or Code
@@ -842,7 +842,7 @@ export default function Home() {
) : (
<>
-
+
{[
{ id: 'ADD', label: 'Buy More', icon: Plus, color: 'text-primary' },
{ id: 'REMOVE', label: 'Subtract', icon: Minus, color: 'text-amber-500' },
@@ -853,7 +853,7 @@ export default function Home() {
onClick={() => setAdjustType(t.id as any)}
className={cn(
"flex-1 flex flex-col items-center py-3 rounded-xl transition-all",
- adjustType === t.id ? "bg-slate-800 shadow-lg" : "text-slate-500"
+ adjustType === t.id ? "bg-slate-800 shadow-lg" : "text-muted"
)}
>
@@ -866,7 +866,7 @@ export default function Home() {
setAdjustQty(Math.max(1, adjustQty - 1))}
- className="w-12 h-12 rounded-full border border-slate-800 flex items-center justify-center text-slate-400 active:bg-slate-800"
+ className="w-12 h-12 rounded-full border border-slate-800 flex items-center justify-center text-secondary active:bg-slate-800"
>
@@ -876,7 +876,7 @@ export default function Home() {
setAdjustQty(adjustQty + 1)}
- className="w-12 h-12 rounded-full border border-slate-800 flex items-center justify-center text-slate-400 active:bg-slate-800"
+ className="w-12 h-12 rounded-full border border-slate-800 flex items-center justify-center text-secondary active:bg-slate-800"
>
@@ -891,7 +891,7 @@ export default function Home() {
setTrashReason(e.target.value)}
- className="w-full bg-slate-950 border border-slate-800 rounded-xl py-3 px-4 text-sm outline-none text-slate-300"
+ className="w-full bg-background border border-slate-800 rounded-xl py-3 px-4 text-sm outline-none text-slate-300"
>
Damaged
Expired
@@ -929,15 +929,15 @@ export default function Home() {
{/* Box Contents Selection Modal */}
{boxMatches.length > 0 && !selectedItem && (
-
-
+
+
Box Contents
-
Select the item you want to {mode.replace('_', ' ').toLowerCase()}
+
Select the item you want to {mode.replace('_', ' ').toLowerCase()}
setBoxMatches([])} className="p-2 hover:bg-slate-800 rounded-full">
@@ -952,13 +952,13 @@ export default function Home() {
setBoxMatches([]);
setAdjustType(mode === 'CHECK_IN' ? 'ADD' : 'REMOVE');
}}
- className="w-full text-left bg-slate-950/50 hover:bg-slate-800 border border-slate-800/80 p-4 rounded-2xl flex items-center gap-4 transition-all active:scale-[0.98] group"
+ className="w-full text-left bg-background/50 hover:bg-slate-800 border border-slate-800/80 p-4 rounded-2xl flex items-center gap-4 transition-all active:scale-[0.98] group"
>
{item.name}
-
Part #: {item.part_number || 'N/A'}
+
Part #: {item.part_number || 'N/A'}
-
+
))}
@@ -971,7 +971,7 @@ export default function Home() {
Powered by TFM Group Software
- v{versionData.version} • {versionData.last_build} • BUILD: dev-{(versionData as any).commit || 'N/A'}
+ v{versionData.version} • {versionData.last_build} • BUILD: dev-{(versionData as any).commit || 'N/A'}
diff --git a/frontend/components/AIOnboarding.tsx b/frontend/components/AIOnboarding.tsx
index d547aa54..099e2348 100644
--- a/frontend/components/AIOnboarding.tsx
+++ b/frontend/components/AIOnboarding.tsx
@@ -229,7 +229,7 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
}, []);
return (
-
+
@@ -237,13 +237,13 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
AI Discovery
-
Powered by Gemini 2.0 Flash
+
Powered by Gemini 2.0 Flash
{ stopLiveCamera(); onCancel(); }}
aria-label="Close AI Discovery"
- className="p-2 hover:bg-slate-900 rounded-full cursor-pointer transition-colors focus:ring-2 focus:ring-blue-500 focus:outline-none"
+ className="p-2 hover:bg-surface rounded-full cursor-pointer transition-colors focus:ring-2 focus:ring-blue-500 focus:outline-none"
>
@@ -251,11 +251,11 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
{!image && !isLive ? (
-
+
setMode('item')}
aria-label="Select Discovery Mode"
- className={`flex-1 flex items-center justify-center gap-2 py-3 rounded-xl font-bold cursor-pointer transition-all focus:ring-2 focus:ring-primary focus:outline-none ${mode === 'item' ? 'bg-primary text-white shadow-lg' : 'text-slate-500 hover:text-slate-300'}`}
+ className={`flex-1 flex items-center justify-center gap-2 py-3 rounded-xl font-bold cursor-pointer transition-all focus:ring-2 focus:ring-primary focus:outline-none ${mode === 'item' ? 'bg-primary text-white shadow-lg' : 'text-muted hover:text-slate-300'}`}
>
Discovery Mode
@@ -263,21 +263,21 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
setMode('box')}
aria-label="Select Box Lookup mode"
- className={`flex-1 flex items-center justify-center gap-2 py-3 rounded-xl font-bold cursor-pointer transition-all focus:ring-2 focus:ring-primary focus:outline-none ${mode === 'box' ? 'bg-primary text-white shadow-lg' : 'text-slate-500 hover:text-slate-300'}`}
+ className={`flex-1 flex items-center justify-center gap-2 py-3 rounded-xl font-bold cursor-pointer transition-all focus:ring-2 focus:ring-primary focus:outline-none ${mode === 'box' ? 'bg-primary text-white shadow-lg' : 'text-muted hover:text-slate-300'}`}
>
Box Lookup
-
-
+
+
{mode === 'box' ? 'Deep Box Analysis' : 'Multi-Item Extraction'}
-
+
{mode === 'box'
? 'Scan container labels to identify storage locations'
: 'Identify multiple technical items from a single photo or label'}
@@ -296,7 +296,7 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
fileInputRef.current?.click()}
aria-label="Upload photo from device"
- className="flex flex-col items-center justify-center gap-2 bg-slate-900 text-slate-200 border border-slate-800 rounded-3xl font-bold cursor-pointer active:scale-95 transition-all focus:ring-2 focus:ring-blue-500 focus:outline-none"
+ className="flex flex-col items-center justify-center gap-2 bg-surface text-slate-200 border border-slate-800 rounded-3xl font-bold cursor-pointer active:scale-95 transition-all focus:ring-2 focus:ring-blue-500 focus:outline-none"
>
Upload Photo
@@ -340,7 +340,7 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
Cancel
@@ -350,7 +350,7 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
className="flex-1 py-4 bg-white text-slate-950 rounded-2xl font-black text-lg shadow-xl shadow-white/10 cursor-pointer flex items-center justify-center gap-3 active:scale-95 hover:bg-slate-200 transition-all focus:ring-2 focus:ring-offset-2 focus:ring-offset-slate-950 focus:ring-white focus:outline-none"
>
Capture Image
@@ -358,12 +358,12 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
) : extractedItems.length === 0 ? (
-
+
{uploading && (
-
+
@@ -378,7 +378,7 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
onClick={() => setImage(null)}
disabled={uploading}
aria-label="Retake photo"
- className="px-6 py-4 bg-slate-900 border border-slate-800 text-slate-400 rounded-2xl font-bold cursor-pointer transition-all active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed focus:ring-2 focus:ring-blue-500 focus:outline-none"
+ className="px-6 py-4 bg-surface border border-slate-800 text-secondary rounded-2xl font-bold cursor-pointer transition-all active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed focus:ring-2 focus:ring-blue-500 focus:outline-none"
>
Retake
@@ -396,7 +396,7 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
) : editingIndex !== null ? (
- Item Details ({editingIndex + 1}/{extractedItems.length})
+ Item Details ({editingIndex + 1}/{extractedItems.length})
setEditingIndex(null)}
aria-label="Back to item list"
@@ -407,8 +407,8 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
-
-
Item Name
+
+ Item Name
-
-
Category
+
+ Category
-
-
Item Type
+
+
Item Type
-
-
Item Color
+
+ Item Color
updateEditingItem({ Color: e.target.value })}
@@ -459,8 +459,8 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
placeholder="e.g. Aqua"
/>
-
-
Box / Container
+
+ Box / Container
-
-
Description
+
+ Description
-
-
Connector
+
+ Connector
updateEditingItem({ Connector: e.target.value })}
@@ -494,8 +494,8 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
placeholder="e.g. LC/UPC"
/>
-
-
Size / Length
+
+ Size / Length
updateEditingItem({ Size: e.target.value })}
@@ -505,8 +505,8 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
-
-
OCR Matching Key
+
+ OCR Matching Key
-
-
Part Number
+
+ Part Number
updateEditingItem({ PartNr: e.target.value })}
@@ -525,8 +525,8 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
placeholder="ID code..."
/>
-
-
Initial Qty
+
+
Initial Qty
-
Discovery Dashboard
+
Discovery Dashboard
{extractedItems.length} items found
@@ -560,7 +560,7 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
{extractedItems.map((item, idx) => (
{item.Item || item.name || "Unknown Item"}
-
+
{item.Type || item.type || "Generic"}
-
+
{item.PartNr || item.part_number || "No P/N"}
@@ -599,7 +599,7 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
setExtractedItems(newItems);
}}
aria-label={`Delete item: ${item.Item || item.name}`}
- className="p-3 text-slate-600 hover:text-red-500 cursor-pointer transition-colors focus:ring-2 focus:ring-red-500 focus:outline-none rounded-lg"
+ className="p-3 text-secondary hover:text-red-500 cursor-pointer transition-colors focus:ring-2 focus:ring-red-500 focus:outline-none rounded-lg"
>
@@ -629,7 +629,7 @@ export default function AIOnboarding({ onCancel, onComplete, categories, invento
setImage(null);
}}
aria-label="Discard discovery session"
- className="py-3 text-xs text-slate-600 font-bold cursor-pointer hover:text-slate-400 transition-colors focus:ring-2 focus:ring-slate-500 focus:outline-none rounded px-2"
+ className="py-3 text-xs text-secondary font-bold cursor-pointer hover:text-secondary transition-colors focus:ring-2 focus:ring-slate-500 focus:outline-none rounded px-2"
>
Discard Discovery
diff --git a/frontend/components/AdminOverlay.tsx b/frontend/components/AdminOverlay.tsx
index d48ea353..597cd8e9 100644
--- a/frontend/components/AdminOverlay.tsx
+++ b/frontend/components/AdminOverlay.tsx
@@ -113,8 +113,8 @@ export default function AdminOverlay({
loading={confirmState.loading}
dangerLevel={confirmState.affectedCount && confirmState.affectedCount > 10 ? 'high' : 'medium'}
/>
-
-
+
+
@@ -124,7 +124,7 @@ export default function AdminOverlay({
@@ -135,8 +135,8 @@ export default function AdminOverlay({
-
User Management
-
Create accounts and control access
+
User Management
+
Create accounts and control access
setShowCreateUserModal(true)}
@@ -150,12 +150,12 @@ export default function AdminOverlay({
{users.map(u => (
-
+
{u.username}
-
{u.role}
+
{u.role}
@@ -184,8 +184,8 @@ export default function AdminOverlay({
-
Category Groups
-
Organize items by type or location
+
Category Groups
+
Organize items by type or location
setShowCreateCategoryModal(true)}
@@ -204,7 +204,7 @@ export default function AdminOverlay({
{cat.name}
-
{cat.description || 'No description'}
+
{cat.description || 'No description'}
@@ -234,7 +234,7 @@ export default function AdminOverlay({
Sign Out
- End your session and return to the login screen.
+ End your session and return to the login screen.
{
import('@/lib/auth').then(m => m.clearAuth());
diff --git a/frontend/components/BottomNav.tsx b/frontend/components/BottomNav.tsx
index 7cafc4da..5d0973ae 100644
--- a/frontend/components/BottomNav.tsx
+++ b/frontend/components/BottomNav.tsx
@@ -25,8 +25,8 @@ export default function BottomNav({
const isAdmin = pathname === '/admin';
return (
-
-
+
+
router.push('/')}
diff --git a/frontend/components/CategoryCreationModal.tsx b/frontend/components/CategoryCreationModal.tsx
index 135f4460..a1c6f47b 100644
--- a/frontend/components/CategoryCreationModal.tsx
+++ b/frontend/components/CategoryCreationModal.tsx
@@ -51,7 +51,7 @@ export default function CategoryCreationModal({
return (
-
+
@@ -62,7 +62,7 @@ export default function CategoryCreationModal({
diff --git a/frontend/components/ConfirmationModal.tsx b/frontend/components/ConfirmationModal.tsx
index bf01a65d..3da53e75 100644
--- a/frontend/components/ConfirmationModal.tsx
+++ b/frontend/components/ConfirmationModal.tsx
@@ -55,7 +55,7 @@ export default function ConfirmationModal({
return (
-
+
{/* Header */}
@@ -67,7 +67,7 @@ export default function ConfirmationModal({
@@ -82,7 +82,7 @@ export default function ConfirmationModal({
{/* Item Name (if provided) */}
{itemName && (
)}
@@ -97,7 +97,7 @@ export default function ConfirmationModal({
{/* Affected Items Count (for medium-risk+) */}
{affectedCount && affectedCount > 0 && (
-
+
{affectedCount === 1
? 'This will affect 1 item.'
: `This will affect ${affectedCount} items.`}
diff --git a/frontend/components/CreateUserModal.tsx b/frontend/components/CreateUserModal.tsx
index a8200141..d1565879 100644
--- a/frontend/components/CreateUserModal.tsx
+++ b/frontend/components/CreateUserModal.tsx
@@ -71,13 +71,13 @@ export default function CreateUserModal({ show, onClose, onUserCreated }: Create
return (
-
+
{/* Header */}
Create User
diff --git a/frontend/components/IdentityCheckOverlay.tsx b/frontend/components/IdentityCheckOverlay.tsx
index 8c251fb7..124f3b65 100644
--- a/frontend/components/IdentityCheckOverlay.tsx
+++ b/frontend/components/IdentityCheckOverlay.tsx
@@ -60,8 +60,8 @@ const IdentityCheckOverlay = memo(({ show, users, onAuthenticated }: IdentityChe
};
return (
-
-
+
+
{/* Subtle accent light */}
@@ -70,7 +70,7 @@ const IdentityCheckOverlay = memo(({ show, users, onAuthenticated }: IdentityChe
Protocol Access
-
Select operator profile to initialize
+
Select operator profile to initialize
@@ -83,15 +83,15 @@ const IdentityCheckOverlay = memo(({ show, users, onAuthenticated }: IdentityChe
className="bg-slate-800/40 hover:bg-slate-800 border border-slate-800/50 hover:border-primary/40 p-5 rounded-[1.5rem] text-left transition-all group flex items-center justify-between shadow-sm active:scale-[0.98]"
>
-
+
{user.role === 'admin' ? : }
{user.username}
-
{user.role}
+
{user.role}
-
+
@@ -99,7 +99,7 @@ const IdentityCheckOverlay = memo(({ show, users, onAuthenticated }: IdentityChe
setIsEnterprise(true)}
- className="w-full flex items-center justify-center gap-3 py-5 rounded-[1.5rem] border border-dashed border-slate-800 text-slate-600 hover:text-primary hover:border-primary/40 hover:bg-primary/5 transition-all font-black text-xs"
+ className="w-full flex items-center justify-center gap-3 py-5 rounded-[1.5rem] border border-dashed border-slate-800 text-secondary hover:text-primary hover:border-primary/40 hover:bg-primary/5 transition-all font-black text-xs"
>
Enterprise Directory
@@ -109,7 +109,7 @@ const IdentityCheckOverlay = memo(({ show, users, onAuthenticated }: IdentityChe
) : isEnterprise ? (
-
LDAP Authentication
+
LDAP Authentication
setIsEnterprise(false)}
className="text-xs font-black text-primary hover:underline tracking-tighter"
@@ -120,12 +120,12 @@ const IdentityCheckOverlay = memo(({ show, users, onAuthenticated }: IdentityChe
-
+
@@ -133,12 +133,12 @@ const IdentityCheckOverlay = memo(({ show, users, onAuthenticated }: IdentityChe
) : (
-
+
-
Active Profile
+
Active Profile
{selectedUserForLogin.username}
setSelectedUserForLogin(null)}
- className="p-2 hover:bg-slate-800 rounded-xl transition-all text-slate-600 hover:text-rose-500"
+ className="p-2 hover:bg-slate-800 rounded-xl transition-all text-secondary hover:text-rose-500"
title="Change User"
>
@@ -174,13 +174,13 @@ const IdentityCheckOverlay = memo(({ show, users, onAuthenticated }: IdentityChe
-
+
e.key === 'Enter' && handleLogin()}
- className="w-full bg-slate-950/50 border border-slate-800/80 focus:border-primary/50 focus:bg-slate-950 rounded-[1.25rem] py-4.5 pl-14 pr-5 text-sm text-slate-100 focus:outline-none transition-all placeholder:text-slate-700 font-mono"
+ className="w-full bg-background/50 border border-slate-800/80 focus:border-primary/50 focus:bg-background rounded-[1.25rem] py-4.5 pl-14 pr-5 text-sm text-slate-100 focus:outline-none transition-all placeholder:text-slate-700 font-mono"
placeholder="KEY-PHRASE"
/>
diff --git a/frontend/components/ItemComparisonModal.tsx b/frontend/components/ItemComparisonModal.tsx
index e1e5101f..57fb622e 100644
--- a/frontend/components/ItemComparisonModal.tsx
+++ b/frontend/components/ItemComparisonModal.tsx
@@ -42,21 +42,21 @@ export default function ItemComparisonModal({
const hasChanges = fields.some(f => isDifferent(f.key));
return (
-
-
+
+
Part Number Already Exists
-
Compare the versions below
+
Compare the versions below
{/* Comparison Table */}
-
Field
-
Current (ID: {existingItem?.id})
+
Field
+
Current (ID: {existingItem?.id})
New (Import)
@@ -73,10 +73,10 @@ export default function ItemComparisonModal({
}`}
>
{field.label}
-
+
{existing}
-
diff --git a/frontend/components/LogsOverlay.tsx b/frontend/components/LogsOverlay.tsx
index 1aeb4a5d..5698a082 100644
--- a/frontend/components/LogsOverlay.tsx
+++ b/frontend/components/LogsOverlay.tsx
@@ -14,15 +14,15 @@ export default function LogsOverlay({ show, onClose, logs, inventory }: LogsOver
if (!show) return null;
return (
-
+
Audit History
-
Live transaction log from cloud
+
Live transaction log from cloud
@@ -30,13 +30,13 @@ export default function LogsOverlay({ show, onClose, logs, inventory }: LogsOver
{logs.length === 0 ? (
-
+
) : (
logs.map((log) => (
-
+
{log.action}
-
by
-
{log.username || 'System'}
+
by
+
{log.username || 'System'}
@@ -54,11 +54,11 @@ export default function LogsOverlay({ show, onClose, logs, inventory }: LogsOver
{(log.details || log.timestamp) && (
-
+
{new Date(log.timestamp).toLocaleString()}
{log.details && (
-
+
{log.details}
)}
diff --git a/frontend/components/PageShell.tsx b/frontend/components/PageShell.tsx
index 45994f84..5d8e8b78 100644
--- a/frontend/components/PageShell.tsx
+++ b/frontend/components/PageShell.tsx
@@ -48,16 +48,16 @@ export default function PageShell({ children, requireAdmin = false }: PageShellP
if (!mounted) {
- return
;
+ return
;
}
// Prevent flicker by showing dark background if we're redirecting to login
if (!currentUser && pathname !== '/login') {
- return
;
+ return
;
}
return (
-
+
{/* Content Area */}
diff --git a/frontend/components/Scanner.tsx b/frontend/components/Scanner.tsx
index fb07e822..103cb1e4 100644
--- a/frontend/components/Scanner.tsx
+++ b/frontend/components/Scanner.tsx
@@ -216,7 +216,7 @@ export default function Scanner({ onScanSuccess, onOCRMatch, paused }: ScannerPr
return (
{/* Video Viewport Area */}
-
+
@@ -230,11 +230,11 @@ export default function Scanner({ onScanSuccess, onOCRMatch, paused }: ScannerPr
-
+
{/* Selection UI */}
{isSelecting && capturedImage && (
-
+
-
+
Text Found
-
Tap any text to use it
+
Tap any text to use it
{ setIsSelecting(false); setCapturedImage(null); setCountdown(4); }}
@@ -278,18 +278,18 @@ export default function Scanner({ onScanSuccess, onOCRMatch, paused }: ScannerPr
)}
{!isStarted && !error && (
-
+
)}
{error && (
-
+
Camera Error
-
{error}
+
{error}
window.location.reload()}
@@ -303,7 +303,7 @@ export default function Scanner({ onScanSuccess, onOCRMatch, paused }: ScannerPr
{/* External Controls Area */}
-
+
{hasZoom && (
)}
-
+
{ocrProcessing ? (
<>
@@ -337,9 +337,9 @@ export default function Scanner({ onScanSuccess, onOCRMatch, paused }: ScannerPr
>
) : (
<>
-
+
-
Smart Scan
+
Smart Scan
{countdown === 0 ? "Scanning" : `${countdown}s`}
@@ -357,7 +357,7 @@ export default function Scanner({ onScanSuccess, onOCRMatch, paused }: ScannerPr
-
+
Scanner active · Use zoom or tap scan
diff --git a/frontend/components/StatCard.tsx b/frontend/components/StatCard.tsx
index aa53419c..44b33bbd 100644
--- a/frontend/components/StatCard.tsx
+++ b/frontend/components/StatCard.tsx
@@ -9,7 +9,7 @@ interface StatCardProps {
export default function StatCard({ label, value, icon: Icon }: StatCardProps) {
return (
-
+
{Icon &&
}
diff --git a/frontend/components/admin/AiManager.tsx b/frontend/components/admin/AiManager.tsx
index 0683ca9f..5123911a 100644
--- a/frontend/components/admin/AiManager.tsx
+++ b/frontend/components/admin/AiManager.tsx
@@ -32,7 +32,7 @@ export default function AiManager({
onUpdatePrompt
}: AiManagerProps) {
return (
-
+
@@ -51,7 +51,7 @@ export default function AiManager({
"p-4 rounded-2xl border transition-all text-left flex items-center justify-between group",
p.active
? "bg-primary border-primary shadow-xl shadow-primary/10"
- : "bg-slate-950/60 border-slate-800 hover:border-primary/40"
+ : "bg-background/60 border-slate-800 hover:border-primary/40"
)}
>
@@ -94,20 +94,20 @@ export default function AiManager({
className="px-6 py-2.5 bg-primary hover:bg-primary text-white rounded-xl text-sm font-black transition-all active:scale-95 shadow-xl shadow-primary/10 tracking-tight border border-primary/30 flex items-center gap-2"
>
{isSavingKeys ? : }
- {isSavingKeys ? "Storing..." : "Store Keys"}
+ {isSavingKeys ? "Storing..." : "Store API Keys"}
-
Gemini Api Key
+
Gemini Api Key
setAiKeys({...aiKeys, gemini: e.target.value})}
placeholder={aiConfig?.providers?.find((p: any) => p.id === 'gemini')?.masked_key || "Enter Gemini Key..."}
- className="flex-1 bg-slate-950/80 border border-slate-800 rounded-xl py-3 px-4 text-xs text-white outline-none focus:border-primary/50 transition-all placeholder:text-slate-600"
+ className="flex-1 bg-background/80 border border-slate-800 rounded-xl py-3 px-4 text-xs text-white outline-none focus:border-primary/50 transition-all placeholder:text-secondary"
/>
onTestAiKey('gemini')}
@@ -115,7 +115,7 @@ export default function AiManager({
className={cn(
"px-4 py-2 rounded-xl text-xs font-bold tracking-tight transition-all border shadow-lg flex items-center gap-1.5",
isTestingKeys.gemini
- ? "bg-slate-800 border-slate-700 text-slate-500 cursor-wait"
+ ? "bg-slate-800 border-slate-700 text-muted cursor-wait"
: "bg-primary border-primary text-white hover:bg-primary"
)}
>
@@ -125,14 +125,14 @@ export default function AiManager({
-
Claude Api Key
+
Claude Api Key
setAiKeys({...aiKeys, claude: e.target.value})}
placeholder={aiConfig?.providers?.find((p: any) => p.id === 'claude')?.masked_key || "Enter Claude Key..."}
- className="flex-1 bg-slate-950/80 border border-slate-800 rounded-xl py-3 px-4 text-xs text-white outline-none focus:border-primary/50 transition-all placeholder:text-slate-600"
+ className="flex-1 bg-background/80 border border-slate-800 rounded-xl py-3 px-4 text-xs text-white outline-none focus:border-primary/50 transition-all placeholder:text-secondary"
/>
onTestAiKey('claude')}
@@ -140,7 +140,7 @@ export default function AiManager({
className={cn(
"px-4 py-2 rounded-xl text-xs font-bold tracking-tight transition-all border shadow-lg flex items-center gap-1.5",
isTestingKeys.claude
- ? "bg-slate-800 border-slate-700 text-slate-500 cursor-wait"
+ ? "bg-slate-800 border-slate-700 text-muted cursor-wait"
: "bg-primary border-primary text-white hover:bg-primary"
)}
>
@@ -155,7 +155,7 @@ export default function AiManager({
- System Prompt (Vision Extraction)
+ System Prompt (Vision Extraction)
setAiPrompt(e.target.value)}
- className="w-full bg-slate-950/80 border border-slate-800 rounded-2xl p-6 text-xs font-mono font-bold text-slate-300 leading-relaxed outline-none focus:border-purple-500/50 transition-all min-h-[200px] custom-scrollbar shadow-inner"
+ className="w-full bg-background/80 border border-slate-800 rounded-2xl p-6 text-xs font-mono font-bold text-slate-300 leading-relaxed outline-none focus:border-purple-500/50 transition-all min-h-[200px] custom-scrollbar shadow-inner"
/>
-
+
This prompt instructs the Vision AI core on label interpretation. Ensure it defines explicit mapping for technical attributes like Item , Type , and Part Number to avoid extraction null-pointers and ensure inventory data integrity.
diff --git a/frontend/components/admin/CategoryManager.tsx b/frontend/components/admin/CategoryManager.tsx
index fd4203c1..817313d0 100644
--- a/frontend/components/admin/CategoryManager.tsx
+++ b/frontend/components/admin/CategoryManager.tsx
@@ -23,7 +23,7 @@ export default function CategoryManager({
onUpdateCategorySubmit
}: CategoryManagerProps) {
return (
-
+
@@ -41,7 +41,7 @@ export default function CategoryManager({
{categories.map(cat => (
-
+
{cat.name}
{cat.description || 'General storage'}
@@ -52,13 +52,13 @@ export default function CategoryManager({
setEditingCategory(cat);
setEditCatForm({ name: cat.name, description: cat.description || '' });
}}
- className="p-2 text-slate-600 hover:text-white hover:bg-slate-800 rounded-lg transition-all"
+ className="p-2 text-secondary hover:text-white hover:bg-slate-800 rounded-lg transition-all"
>
onDeleteCategory(cat.id, cat.name)}
- className="p-2 text-slate-600 hover:text-rose-500 hover:bg-rose-500/5 rounded-lg transition-all"
+ className="p-2 text-secondary hover:text-rose-500 hover:bg-rose-500/5 rounded-lg transition-all"
>
@@ -69,8 +69,8 @@ export default function CategoryManager({
{/* Edit Category Modal */}
{editingCategory && (
-
-
+
+
@@ -78,26 +78,26 @@ export default function CategoryManager({
Modify Group
-
setEditingCategory(null)} className="p-3 hover:bg-slate-800 rounded-2xl text-slate-500 transition-colors border border-slate-800">
+ setEditingCategory(null)} className="p-3 hover:bg-slate-800 rounded-2xl text-muted transition-colors border border-slate-800">
- Group Identifier
+ Group Identifier
setEditCatForm({...editCatForm, name: e.target.value})}
- className="w-full bg-slate-950 border border-slate-800 rounded-2xl py-3.5 px-5 text-sm text-white focus:border-primary outline-none transition-all"
+ className="w-full bg-background border border-slate-800 rounded-2xl py-3.5 px-5 text-sm text-white focus:border-primary outline-none transition-all"
/>
- Strategic Description
+ Strategic Description
diff --git a/frontend/components/admin/DatabaseManager.tsx b/frontend/components/admin/DatabaseManager.tsx
index a5924337..e9069548 100644
--- a/frontend/components/admin/DatabaseManager.tsx
+++ b/frontend/components/admin/DatabaseManager.tsx
@@ -35,7 +35,7 @@ export default function DatabaseManager({
return (
-
+
@@ -45,14 +45,14 @@ export default function DatabaseManager({
-
Database Health
+
Database Health
-
Last Backup
+
Last Backup
{dbStats.backup_count > 0 ? 'Verified' : 'Pending...'}
@@ -69,7 +69,7 @@ export default function DatabaseManager({
-
+
@@ -77,24 +77,24 @@ export default function DatabaseManager({
Storage Policy
-
Retention & Maintenance
+
Retention & Maintenance
@@ -122,7 +122,7 @@ export default function DatabaseManager({
-
Recovery Points
+
Recovery Points
{formatSize(dbStats.total_size_bytes)} Used
@@ -130,21 +130,21 @@ export default function DatabaseManager({
{backups.map((bak: any) => (
-
+
-
+
{bak.filename}
-
+
{new Date(bak.created_at).toLocaleString()} • {formatSize(bak.size_bytes)}
onRestore(bak.filename)}
- className="p-2 text-slate-600 hover:text-primary hover:bg-primary/5 rounded-xl transition-all opacity-0 group-hover/item:opacity-100 focus-visible:ring-2 focus-visible:ring-primary focus-visible:outline-none"
+ className="p-2 text-secondary hover:text-primary hover:bg-primary/5 rounded-xl transition-all opacity-0 group-hover/item:opacity-100 focus-visible:ring-2 focus-visible:ring-primary focus-visible:outline-none"
aria-label={`Restore backup ${bak.filename}`}
>
@@ -157,7 +157,7 @@ export default function DatabaseManager({
Export Database
@@ -170,7 +170,7 @@ export default function DatabaseManager({
className="absolute inset-0 opacity-0 cursor-pointer z-10"
/>
Import Database
diff --git a/frontend/components/admin/IdentityManager.tsx b/frontend/components/admin/IdentityManager.tsx
index 3b536ab7..7f913517 100644
--- a/frontend/components/admin/IdentityManager.tsx
+++ b/frontend/components/admin/IdentityManager.tsx
@@ -24,7 +24,7 @@ export default function IdentityManager({
onUpdateUserSubmit
}: IdentityManagerProps) {
return (
-