"use client"; import { useEffect, useState } from "react"; import { Edit2, Package, RefreshCw, Trash2, Download } from "lucide-react"; import * as xlsx from "xlsx"; export default function Dashboard() { const [items, setItems] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [editingId, setEditingId] = useState(null); const [editForm, setEditForm] = useState({}); const [searchQuery, setSearchQuery] = useState(""); const [selectedCategory, setSelectedCategory] = useState(""); const [currentPage, setCurrentPage] = useState(1); const itemsPerPage = 10; const fetchItems = async () => { setLoading(true); setError(null); try { const res = await fetch("/api/inventory"); if (!res.ok) throw new Error("Failed to fetch inventory from database"); const data = await res.json(); setItems(data); } catch (err) { setError(err.message); } finally { setLoading(false); } }; useEffect(() => { fetchItems(); }, []); const deleteItem = async (id) => { if (!confirm("Are you sure you want to delete this item?")) return; try { const res = await fetch(`/api/inventory?id=${id}`, { method: "DELETE" }); if (res.ok) { setItems(items.filter(item => item.id !== id)); } else { alert("Error deleting item"); } } catch (error) { alert("Error deleting item: " + error.message); } }; const startEdit = (item) => { setEditingId(item.id); setEditForm({ name: item.name, category: item.category || "", location: item.location || "", quantity: item.quantity, price: item.price }); }; const saveEdit = async (id) => { try { const parsedQty = parseInt(editForm.quantity, 10); const payload = { id, name: editForm.name, category: editForm.category, location: editForm.location, quantity: isNaN(parsedQty) ? 0 : parsedQty, price: parseFloat(editForm.price) || 0.0, }; const res = await fetch("/api/inventory", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload), }); if (res.ok) { const updatedItem = await res.json(); setItems(items.map(item => item.id === id ? updatedItem : item)); setEditingId(null); } else { alert("Failed to save changes"); } } catch (err) { alert("Error saving: " + err.message); } }; // Filter and Paginate Items useEffect(() => { setCurrentPage(1); }, [searchQuery, selectedCategory]); const uniqueCategories = [...new Set(items.map(item => item.category?.trim() || "Uncategorized"))].filter(c => c).sort(); const filteredItems = items.filter(item => { const matchesSearch = item.name.toLowerCase().includes(searchQuery.toLowerCase()) || item.qrCodeId.toLowerCase().includes(searchQuery.toLowerCase()); const matchesCategory = selectedCategory === "" || (item.category?.trim() || "Uncategorized") === selectedCategory; return matchesSearch && matchesCategory; }); const totalPages = Math.max(1, Math.ceil(filteredItems.length / itemsPerPage)); const startIndex = (currentPage - 1) * itemsPerPage; const paginatedItems = filteredItems.slice(startIndex, startIndex + itemsPerPage); const handleExport = () => { if (filteredItems.length === 0) return alert("No items to export"); const ws = xlsx.utils.json_to_sheet(filteredItems.map(i => ({ "QR ID": i.qrCodeId, "Name": i.name, "Quantity": i.quantity, "Price": i.price, "Category": i.category || "", "Location": i.location || "", "Description": i.description || "", "Last Updated": i.updatedAt ? new Date(i.updatedAt).toLocaleString() : "" }))); const wb = xlsx.utils.book_new(); xlsx.utils.book_append_sheet(wb, ws, "Inventory"); xlsx.writeFile(wb, "Inventory_Export.xlsx"); }; return (

Inventory Overview

Manage your inventory quantities and prices.

{error ? (

Error: {error}

Ensure your PostgreSQL database is running and DATABASE_URL is configured in your .env or prisma.config.ts

) : loading ? (

Loading inventory...

) : items.length === 0 ? (

No items found

Start by adding a new item or importing an Excel sheet.

) : (
setSearchQuery(e.target.value)} style={{ flex: 1 }} />
{paginatedItems.length === 0 ? ( ) : paginatedItems.map(item => ( ))}
Name QR ID Category Location Quantity Price Last Updated Actions
No items match your filters.
{editingId === item.id ? ( setEditForm({...editForm, name: e.target.value})} /> ) : item.name} {item.qrCodeId} {editingId === item.id ? ( setEditForm({...editForm, category: e.target.value})} /> ) : (item.category || "-")} {editingId === item.id ? ( setEditForm({...editForm, location: e.target.value})} /> ) : (item.location || "-")} {editingId === item.id ? ( setEditForm({...editForm, quantity: e.target.value})} /> ) : ( {item.quantity} )} {editingId === item.id ? ( setEditForm({...editForm, price: e.target.value})} /> ) : `$${Number(item.price).toFixed(2)}`} {item.updatedAt ? new Date(item.updatedAt).toLocaleDateString() + " " + new Date(item.updatedAt).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'}) : "N/A"}
{editingId === item.id ? ( <> ) : ( <> )}
{filteredItems.length > 0 && (
Showing {startIndex + 1} to {Math.min(startIndex + itemsPerPage, filteredItems.length)} of {filteredItems.length} entries
Page {currentPage} of {totalPages}
)}
)}
); }