guardia-mall/frontend/src/admin/Inventory.tsx

58 lines
3.6 KiB
TypeScript
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.

import { useEffect, useState } from 'react'
import { useQuery, useQueryClient } from '@tanstack/react-query'
import { Boxes } from 'lucide-react'
import { getStores, getStoreInventory, toggleStoreInventory, adjustStoreInventory } from '../api/client'
export default function Inventory() {
const qc = useQueryClient()
const [storeId, setStoreId] = useState<number>(0)
const { data: stores } = useQuery({ queryKey: ['inv-stores'], queryFn: () => getStores(false) })
useEffect(() => { if (!storeId && stores?.length) setStoreId(stores[0].id) }, [stores])
const { data: inv } = useQuery({ queryKey: ['store-inv', storeId], queryFn: () => getStoreInventory(storeId), enabled: !!storeId })
const toggle = async (pid: number, available: boolean) => { await toggleStoreInventory(storeId, pid, !available).catch(() => {}); qc.invalidateQueries({ queryKey: ['store-inv', storeId] }) }
const adjust = async (pid: number, delta: number) => { await adjustStoreInventory(storeId, pid, delta).catch(() => {}); qc.invalidateQueries({ queryKey: ['store-inv', storeId] }) }
return (
<div>
<div className="flex items-center justify-between mb-5">
<div className="flex items-center gap-2"><Boxes className="text-brand" size={22} /><h1 className="text-xl font-bold">Store Inventory (ON/OFF)</h1></div>
<select value={storeId} onChange={e => setStoreId(Number(e.target.value))} className="bg-card border border-edge rounded-lg px-3 py-2 text-sm">
{(stores || []).map((s: any) => <option key={s.id} value={s.id}>{s.name}</option>)}
</select>
</div>
<p className="text-xs text-slate-500 mb-3">Switching to OFF immediately marks the item as out of stock in that store's area.</p>
<div className="bg-card border border-edge rounded-xl overflow-hidden">
<table className="w-full text-sm">
<thead><tr className="text-slate-400 text-xs border-b border-edge bg-panel">
<th className="text-left p-3">Product</th><th className="text-right">Stock</th><th className="text-center">Adjust</th><th className="text-center">Sale</th>
</tr></thead>
<tbody>
{(inv || []).map((r: any) => {
const available = r.available !== false
return (
<tr key={r.productId || r.id} className="border-b border-edge/50 hover:bg-panel/50">
<td className="p-3">{r.productName || `Product #${r.productId}`}</td>
<td className="text-right text-slate-300">{r.stock ?? r.quantity ?? '-'}</td>
<td className="text-center">
<div className="inline-flex items-center gap-1">
<button onClick={() => adjust(r.productId, -1)} className="w-6 h-6 rounded bg-panel border border-edge text-slate-300"></button>
<button onClick={() => adjust(r.productId, +1)} className="w-6 h-6 rounded bg-panel border border-edge text-slate-300">+</button>
</div>
</td>
<td className="text-center">
<button onClick={() => toggle(r.productId, available)} className={`px-3 py-1 rounded-full text-xs ${available ? 'bg-emerald-500/15 text-emerald-400' : 'bg-rose-500/15 text-rose-400'}`}>
{available ? 'ON' : 'OFF'}
</button>
</td>
</tr>
)
})}
{!(inv || []).length && <tr><td colSpan={4} className="text-center text-slate-500 py-8">No inventory items found.</td></tr>}
</tbody>
</table>
</div>
</div>
)
}