diff --git a/app/dashboard/products/page.tsx b/app/dashboard/products/page.tsx index e2de997..f6aa4a7 100644 --- a/app/dashboard/products/page.tsx +++ b/app/dashboard/products/page.tsx @@ -45,7 +45,7 @@ const ProfitAnalysisModal = dynamic(() => import("@/components/modals/profit-ana function ProductTableSkeleton() { return ( - +
@@ -60,8 +60,8 @@ function ProductTableSkeleton() {
{['Product', 'Category', 'Price', 'Stock', 'Status', 'Actions'].map((header, i) => ( -
- + {[...Array(8)].map((_, i) => ( -
(null); + const [selectedProductForAnalysis, setSelectedProductForAnalysis] = useState<{ id: string, name: string } | null>(null); // Fetch products and categories useEffect(() => { @@ -169,7 +169,7 @@ export default function ProductsPage() { const fetchDataAsync = async () => { try { setLoading(true); - + const [fetchedProducts, fetchedCategories] = await Promise.all([ clientFetch('/products'), clientFetch('/categories'), @@ -210,7 +210,7 @@ export default function ProductsPage() { })); }; - // Handle input changes + // Handle input changes const handleChange = ( e: ChangeEvent ) => setProductData({ ...productData, [e.target.name]: e.target.value }); @@ -226,7 +226,7 @@ export default function ProductsPage() { setProductData({ ...productData, pricing: updatedPricing }); }; - + const handleSaveProduct = async (data: Product, file?: File | null) => { try { setLoading(true); @@ -247,7 +247,7 @@ export default function ProductsPage() { // Save the product data const endpoint = editing ? `/products/${data._id}` : "/products"; const method = editing ? "PUT" : "POST"; - + const productResponse = await clientFetch(endpoint, { method, headers: { @@ -259,10 +259,10 @@ export default function ProductsPage() { // If there's a new image to upload if (file) { const imageEndpoint = `/products/${productResponse._id || data._id}/image`; - + const formData = new FormData(); formData.append("file", file); - + await fetch(`${process.env.NEXT_PUBLIC_API_URL}${imageEndpoint}`, { method: "PUT", headers: { @@ -279,10 +279,10 @@ export default function ProductsPage() { // Refresh products list const fetchedProducts = await clientFetch('/products'); setProducts(fetchedProducts); - + setModalOpen(false); setLoading(false); - + toast.success( editing ? "Product updated successfully" : "Product added successfully" ); @@ -296,18 +296,18 @@ export default function ProductsPage() { // Handle delete product const handleDeleteProduct = async (productId: string) => { if (!confirm("Are you sure you want to delete this product?")) return; - + try { setLoading(true); - + await clientFetch(`/products/${productId}`, { method: "DELETE", }); - + // Refresh products list const fetchedProducts = await clientFetch('/products'); setProducts(fetchedProducts); - + toast.success("Product deleted successfully"); setLoading(false); } catch (error) { @@ -323,9 +323,9 @@ export default function ProductsPage() { ...product, pricing: product.pricing ? product.pricing.map((tier) => ({ - minQuantity: tier.minQuantity, - pricePerUnit: tier.pricePerUnit, - })) + minQuantity: tier.minQuantity, + pricePerUnit: tier.pricePerUnit, + })) : [{ minQuantity: 1, pricePerUnit: 0 }], costPerUnit: product.costPerUnit || 0, }); @@ -343,16 +343,16 @@ export default function ProductsPage() { image: null, // Clear image so user can upload a new one pricing: product.pricing ? product.pricing.map((tier) => ({ - minQuantity: tier.minQuantity, - pricePerUnit: tier.pricePerUnit, - })) + minQuantity: tier.minQuantity, + pricePerUnit: tier.pricePerUnit, + })) : [{ minQuantity: 1, pricePerUnit: 0 }], costPerUnit: product.costPerUnit || 0, // Reset stock to defaults for cloned product currentStock: 0, stockStatus: 'out_of_stock' as const, }; - + setProductData(clonedProduct); setEditing(false); // Set to false so it creates a new product setAddProductOpen(true); @@ -390,19 +390,19 @@ export default function ProductsPage() { // Filter products based on search term const filteredProducts = products.filter(product => { if (!searchTerm) return true; - + const searchLower = searchTerm.toLowerCase(); - + // Search in product name if (product.name.toLowerCase().includes(searchLower)) return true; - + // Search in product description if it exists if (product.description && product.description.toLowerCase().includes(searchLower)) return true; - + // Search in category name const categoryName = getCategoryNameById(product.category).toLowerCase(); if (categoryName.includes(searchLower)) return true; - + return false; }); @@ -437,19 +437,19 @@ export default function ProductsPage() { const handleToggleEnabled = async (productId: string, enabled: boolean) => { try { setLoading(true); - + await clientFetch(`/products/${productId}`, { method: "PATCH", body: JSON.stringify({ enabled }), }); - + // Update the local state - setProducts(products.map(product => - product._id === productId - ? { ...product, enabled } + setProducts(products.map(product => + product._id === productId + ? { ...product, enabled } : product )); - + toast.success(`Product ${enabled ? 'enabled' : 'disabled'} successfully`); setLoading(false); } catch (error) { @@ -489,9 +489,9 @@ export default function ProductsPage() { )}
-