diff --git a/package.json b/package.json index e8ca49a..cfaf502 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "react-day-picker": "^8.10.1", "react-dom": "^18.3.1", "react-hook-form": "^7.53.0", + "react-hot-toast": "^2.6.0", "react-resizable-panels": "^2.1.3", "react-router-dom": "^6.26.2", "recharts": "^2.12.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6e5b6e4..8b1cc45 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -146,6 +146,9 @@ importers: react-hook-form: specifier: ^7.53.0 version: 7.55.0(react@18.3.1) + react-hot-toast: + specifier: ^2.6.0 + version: 2.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-resizable-panels: specifier: ^2.1.3 version: 2.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -1824,6 +1827,11 @@ packages: resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} engines: {node: '>=18'} + goober@2.1.16: + resolution: {integrity: sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==} + peerDependencies: + csstype: ^3.0.10 + graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} @@ -2158,6 +2166,13 @@ packages: peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 + react-hot-toast@2.6.0: + resolution: {integrity: sha512-bH+2EBMZ4sdyou/DPrfgIouFpcRLCJ+HoCA32UoAYHn6T3Ur5yfcDCeSr5mwldl6pFOsiocmrXMuoCJ1vV8bWg==} + engines: {node: '>=10'} + peerDependencies: + react: '>=16' + react-dom: '>=16' + react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -4056,6 +4071,10 @@ snapshots: globals@15.15.0: {} + goober@2.1.16(csstype@3.1.3): + dependencies: + csstype: 3.1.3 + graphemer@1.4.0: {} has-flag@4.0.0: {} @@ -4332,6 +4351,13 @@ snapshots: dependencies: react: 18.3.1 + react-hot-toast@2.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + csstype: 3.1.3 + goober: 2.1.16(csstype@3.1.3) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-is@16.13.1: {} react-is@18.3.1: {} diff --git a/src/components/AddStockItemDialog.tsx b/src/components/AddStockItemDialog.tsx new file mode 100644 index 0000000..c15cd70 --- /dev/null +++ b/src/components/AddStockItemDialog.tsx @@ -0,0 +1,111 @@ +import React, { useState } from 'react'; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogDescription, + DialogFooter, +} from '@/components/ui/dialog'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { toast } from 'react-hot-toast'; // Assuming react-hot-toast is available or will be added + +interface AddStockItemDialogProps { + open: boolean; + onOpenChange: (open: boolean) => void; + onAddItem: (item: { name: string; sku: string; quantity: number; price: number; location: string }) => void; +} + +export const AddStockItemDialog: React.FC = ({ open, onOpenChange, onAddItem }) => { + const [name, setName] = useState(''); + const [sku, setSku] = useState(''); + const [quantity, setQuantity] = useState(''); + const [price, setPrice] = useState(''); + const [location, setLocation] = useState(''); + + const handleSubmit = () => { + if (!name || !sku || !quantity || !price || !location) { + toast.error('Please fill in all fields.'); + return; + } + + const parsedQuantity = parseInt(quantity); + const parsedPrice = parseFloat(price); + + if (isNaN(parsedQuantity) || parsedQuantity <= 0) { + toast.error('Quantity must be a positive number.'); + return; + } + if (isNaN(parsedPrice) || parsedPrice <= 0) { + toast.error('Price must be a positive number.'); + return; + } + + onAddItem({ + name, + sku, + quantity: parsedQuantity, + price: parsedPrice, + location, + }); + + // Reset form fields + setName(''); + setSku(''); + setQuantity(''); + setPrice(''); + setLocation(''); + onOpenChange(false); // Close dialog + toast.success('Stock item added successfully!'); + }; + + return ( + + + + Add New Stock Item + + Enter the details for the new stock item. Click save when you're done. + + +
+
+ + setName(e.target.value)} className="col-span-3" /> +
+
+ + setSku(e.target.value)} className="col-span-3" /> +
+
+ + setQuantity(e.target.value)} className="col-span-3" /> +
+
+ + setPrice(e.target.value)} className="col-span-3" /> +
+
+ + setLocation(e.target.value)} className="col-span-3" /> +
+
+ + + +
+
+ ); +}; \ No newline at end of file diff --git a/src/pages/StockList.tsx b/src/pages/StockList.tsx index 327d33d..293e1ed 100644 --- a/src/pages/StockList.tsx +++ b/src/pages/StockList.tsx @@ -1,27 +1,43 @@ -import React from 'react'; +import React, { useState } from 'react'; import { Button } from '@/components/ui/button'; -import { Plus, QrCode } from 'lucide-react'; // Import icons +import { Plus, QrCode } from 'lucide-react'; +import { AddStockItemDialog } from '@/components/AddStockItemDialog'; // Import the new dialog component +import { toast } from 'react-hot-toast'; // Import toast for notifications + +interface StockItem { + id: string; + name: string; + sku: string; + quantity: number; + price: number; + location: string; +} const StockList = () => { - // Mock data for demonstration - const stockItems = [ + const [stockItems, setStockItems] = useState([ { id: '1', name: 'Wireless Mouse', sku: 'WM001', quantity: 150, price: 25.00, location: 'A1' }, { id: '2', name: 'Mechanical Keyboard', sku: 'MK002', quantity: 80, price: 75.00, location: 'A2' }, { id: '3', name: 'USB-C Hub', sku: 'UH003', quantity: 200, price: 30.00, location: 'B1' }, { id: '4', name: 'External SSD 1TB', sku: 'ES004', quantity: 50, price: 120.00, location: 'C3' }, { id: '5', name: 'Monitor Stand', sku: 'MS005', quantity: 100, price: 45.00, location: 'A1' }, - ]; + ]); + const [isAddStockDialogOpen, setIsAddStockDialogOpen] = useState(false); const handleAddStockItem = () => { - console.log('Add Stock Item clicked'); - // Implement navigation or modal for adding a new item + setIsAddStockDialogOpen(true); }; const handleScanQrCode = () => { console.log('Scan QR Code clicked'); + toast.info('QR Code scanning functionality not yet implemented.'); // Implement QR code scanning functionality }; + const handleAddNewStockItem = (newItem: Omit) => { + const newId = (stockItems.length + 1).toString(); // Simple ID generation + setStockItems((prevItems) => [...prevItems, { id: newId, ...newItem }]); + }; + return (
@@ -39,7 +55,6 @@ const StockList = () => {
- {/* Placeholder for stock list table or display */}

Current Stock

@@ -83,6 +98,12 @@ const StockList = () => { )}
+ + ); };