Spaces:
Running
Running
File size: 6,347 Bytes
8457d97 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | "use client";
import React, { useState, useEffect } from "react";
import { db } from "@/lib/firebase";
import { collection, onSnapshot, addDoc, deleteDoc, doc, updateDoc } from "firebase/firestore";
import Link from "next/link";
interface Product {
id: string;
name: string;
category: string;
price: number;
stock: number;
}
export default function InventoryPage() {
const [products, setProducts] = useState<Product[]>([]);
const [isModalOpen, setIsModalOpen] = useState(false);
const [newProduct, setNewProduct] = useState({ name: "", category: "", price: 0, stock: 0 });
useEffect(() => {
const unsub = onSnapshot(collection(db, "products"), (snap) => {
const data = snap.docs.map(doc => ({ id: doc.id, ...doc.data() } as Product));
setProducts(data);
});
return () => unsub();
}, []);
const handleAdd = async (e: React.FormEvent) => {
e.preventDefault();
await addDoc(collection(db, "products"), newProduct);
setIsModalOpen(false);
setNewProduct({ name: "", category: "", price: 0, stock: 0 });
};
const handleDelete = async (id: string) => {
if(confirm("¿Seguro que quieres eliminar este producto?")) {
await deleteDoc(doc(db, "products", id));
}
};
return (
<div className="min-h-screen bg-[#0f172a] text-white p-6">
<header className="flex justify-between items-center mb-8">
<div>
<Link href="/" className="text-blue-400 hover:text-blue-300 transition-colors flex items-center gap-2 mb-2">
← Volver al Dashboard
</Link>
<h1 className="text-3xl font-bold">Gestión de Inventario</h1>
</div>
<button
onClick={() => setIsModalOpen(true)}
className="px-6 py-3 bg-blue-600 hover:bg-blue-500 rounded-2xl font-bold transition-all shadow-lg shadow-blue-900/20"
>
➕ Añadir Producto
</button>
</header>
{/* Inventory Table */}
<div className="bg-white/5 border border-white/10 rounded-3xl overflow-hidden backdrop-blur-xl">
<table className="w-full text-left">
<thead className="bg-white/5 border-b border-white/10">
<tr>
<th className="px-6 py-4 font-semibold text-gray-400 uppercase text-xs tracking-wider">Nombre</th>
<th className="px-6 py-4 font-semibold text-gray-400 uppercase text-xs tracking-wider">Categoría</th>
<th className="px-6 py-4 font-semibold text-gray-400 uppercase text-xs tracking-wider">Precio</th>
<th className="px-6 py-4 font-semibold text-gray-400 uppercase text-xs tracking-wider">Stock</th>
<th className="px-6 py-4 font-semibold text-gray-400 uppercase text-xs tracking-wider">Acciones</th>
</tr>
</thead>
<tbody className="divide-y divide-white/5">
{products.map((p) => (
<tr key={p.id} className="hover:bg-white/5 transition-colors group">
<td className="px-6 py-4 font-medium text-gray-200">{p.name}</td>
<td className="px-6 py-4 text-gray-400">
<span className="px-3 py-1 bg-white/5 rounded-full text-xs border border-white/10">{p.category}</span>
</td>
<td className="px-6 py-4 font-bold text-blue-400">${Number(p.price).toLocaleString()}</td>
<td className="px-6 py-4">
<div className="flex items-center gap-2">
<span className={`w-2 h-2 rounded-full ${p.stock > 10 ? 'bg-green-400' : 'bg-red-400'}`}></span>
{p.stock} uds.
</div>
</td>
<td className="px-6 py-4">
<button onClick={() => handleDelete(p.id)} className="text-gray-600 hover:text-red-400 transition-colors">🗑️</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
{/* Modal Mockup */}
{isModalOpen && (
<div className="fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center p-6 z-50">
<div className="bg-[#1e293b] border border-white/10 p-8 rounded-[40px] w-full max-w-lg shadow-2xl animate-in fade-in zoom-in-95">
<h2 className="text-2xl font-bold mb-6">Nuevo Producto</h2>
<form onSubmit={handleAdd} className="space-y-4">
<input
type="text" placeholder="Nombre" required
value={newProduct.name} onChange={e => setNewProduct({...newProduct, name: e.target.value})}
className="w-full bg-white/5 border border-white/10 rounded-2xl px-6 py-4 outline-none focus:border-blue-500/50"
/>
<input
type="text" placeholder="Categoría" required
value={newProduct.category} onChange={e => setNewProduct({...newProduct, category: e.target.value})}
className="w-full bg-white/5 border border-white/10 rounded-2xl px-6 py-4 outline-none focus:border-blue-500/50"
/>
<div className="grid grid-cols-2 gap-4">
<input
type="number" placeholder="Precio" required
value={newProduct.price} onChange={e => setNewProduct({...newProduct, price: Number(e.target.value)})}
className="w-full bg-white/5 border border-white/10 rounded-2xl px-6 py-4 outline-none focus:border-blue-500/50"
/>
<input
type="number" placeholder="Stock" required
value={newProduct.stock} onChange={e => setNewProduct({...newProduct, stock: Number(e.target.value)})}
className="w-full bg-white/5 border border-white/10 rounded-2xl px-6 py-4 outline-none focus:border-blue-500/50"
/>
</div>
<div className="flex gap-4 mt-8">
<button type="button" onClick={() => setIsModalOpen(false)} className="flex-1 py-4 text-gray-400 hover:text-white transition-colors">Cancelar</button>
<button type="submit" className="flex-1 bg-blue-600 hover:bg-blue-500 py-4 rounded-2xl font-bold transition-all shadow-lg shadow-blue-900/20">Guardar</button>
</div>
</form>
</div>
</div>
)}
</div>
);
}
|