171 lines
6.4 KiB
TypeScript
171 lines
6.4 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { Package, Plus, Edit, Trash2, AlertTriangle } from 'lucide-react';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
|
|
import { Input } from '@/components/ui/input';
|
|
import { Label } from '@/components/ui/label';
|
|
import { Badge } from '@/components/ui/badge';
|
|
import { useToast } from '@/hooks/use-toast';
|
|
|
|
const Inventory = () => {
|
|
const [inventory, setInventory] = useState<any[]>([]);
|
|
const { toast } = useToast();
|
|
|
|
const [formData, setFormData] = useState({
|
|
name: '',
|
|
category: '',
|
|
quantity: 0,
|
|
unit: 'kg',
|
|
minStock: 0,
|
|
supplier: ''
|
|
});
|
|
|
|
const handleSubmit = async () => {
|
|
try {
|
|
toast({ title: 'Éxito', description: 'Producto agregado al inventario' });
|
|
setFormData({
|
|
name: '',
|
|
category: '',
|
|
quantity: 0,
|
|
unit: 'kg',
|
|
minStock: 0,
|
|
supplier: ''
|
|
});
|
|
} catch (error: any) {
|
|
toast({ title: 'Error', description: error?.message || 'No se pudo agregar el producto', variant: 'destructive' });
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="min-h-screen bg-gray-50 p-6">
|
|
<div className="max-w-7xl mx-auto">
|
|
<div className="flex items-center gap-3 mb-6">
|
|
<Package className="w-8 h-8 text-orange-600" />
|
|
<div>
|
|
<h1 className="text-3xl font-bold text-gray-900">Gestión de Inventario</h1>
|
|
<p className="text-gray-600">Controla el stock de productos</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex justify-end mb-4">
|
|
<Dialog>
|
|
<DialogTrigger asChild>
|
|
<Button>
|
|
<Plus className="w-4 h-4 mr-2" />
|
|
Nuevo Producto
|
|
</Button>
|
|
</DialogTrigger>
|
|
<DialogContent>
|
|
<DialogHeader>
|
|
<DialogTitle>Agregar Producto</DialogTitle>
|
|
</DialogHeader>
|
|
<div className="grid gap-4">
|
|
<div>
|
|
<Label>Nombre del Producto</Label>
|
|
<Input
|
|
value={formData.name}
|
|
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
|
placeholder="Ej: Tomates"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<Label>Categoría</Label>
|
|
<Input
|
|
value={formData.category}
|
|
onChange={(e) => setFormData({ ...formData, category: e.target.value })}
|
|
placeholder="Ej: Vegetales"
|
|
/>
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<Label>Cantidad</Label>
|
|
<Input
|
|
type="number"
|
|
value={formData.quantity}
|
|
onChange={(e) => setFormData({ ...formData, quantity: parseFloat(e.target.value) })}
|
|
/>
|
|
</div>
|
|
<div>
|
|
<Label>Unidad</Label>
|
|
<Input
|
|
value={formData.unit}
|
|
onChange={(e) => setFormData({ ...formData, unit: e.target.value })}
|
|
placeholder="kg, lb, unidades"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<Label>Stock Mínimo</Label>
|
|
<Input
|
|
type="number"
|
|
value={formData.minStock}
|
|
onChange={(e) => setFormData({ ...formData, minStock: parseFloat(e.target.value) })}
|
|
/>
|
|
</div>
|
|
<div>
|
|
<Label>Proveedor</Label>
|
|
<Input
|
|
value={formData.supplier}
|
|
onChange={(e) => setFormData({ ...formData, supplier: e.target.value })}
|
|
placeholder="Nombre del proveedor"
|
|
/>
|
|
</div>
|
|
<Button onClick={handleSubmit}>Agregar Producto</Button>
|
|
</div>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</div>
|
|
|
|
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
|
{inventory.length === 0 ? (
|
|
<div className="col-span-full text-center py-12 text-muted-foreground">
|
|
No hay productos en el inventario. Agrega el primer producto.
|
|
</div>
|
|
) : (
|
|
inventory.map((item) => (
|
|
<Card key={item.id}>
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
<div>
|
|
<CardTitle className="text-base">{item.name}</CardTitle>
|
|
<p className="text-sm text-muted-foreground">{item.category}</p>
|
|
</div>
|
|
<div className="flex gap-1">
|
|
<Button variant="outline" size="sm">
|
|
<Edit className="w-4 h-4" />
|
|
</Button>
|
|
<Button variant="outline" size="sm">
|
|
<Trash2 className="w-4 h-4" />
|
|
</Button>
|
|
</div>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="space-y-2">
|
|
<div className="flex justify-between items-center">
|
|
<span className="text-sm text-muted-foreground">Stock actual:</span>
|
|
<span className="font-bold">{item.quantity} {item.unit}</span>
|
|
</div>
|
|
<div className="flex justify-between items-center">
|
|
<span className="text-sm text-muted-foreground">Stock mínimo:</span>
|
|
<span>{item.minStock} {item.unit}</span>
|
|
</div>
|
|
{item.quantity <= item.minStock && (
|
|
<Badge variant="destructive" className="w-full justify-center">
|
|
<AlertTriangle className="w-3 h-3 mr-1" />
|
|
Stock Bajo
|
|
</Badge>
|
|
)}
|
|
<p className="text-xs text-muted-foreground">Proveedor: {item.supplier}</p>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
))
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Inventory;
|