diff --git a/src/pages/AuditLogs.jsx b/src/pages/AuditLogs.jsx index 7b3f741..37078a3 100644 --- a/src/pages/AuditLogs.jsx +++ b/src/pages/AuditLogs.jsx @@ -8,6 +8,10 @@ const AuditLogs = () => { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); + // Pagination states + const [currentPage, setCurrentPage] = useState(1); + const [itemsPerPage, setItemsPerPage] = useState(10); + useEffect(() => { const fetchLogs = async () => { try { @@ -20,6 +24,7 @@ const AuditLogs = () => { if (!res.ok) throw new Error('Failed to fetch system audit logs'); const data = await res.json(); setLogs(data); + setCurrentPage(1); // reset to page 1 on fetch } catch (err) { setError(err.message); } finally { @@ -29,6 +34,13 @@ const AuditLogs = () => { fetchLogs(); }, [token]); + // Compute pagination details + const totalItems = logs.length; + const totalPages = Math.ceil(totalItems / itemsPerPage); + const startIdx = totalItems === 0 ? 0 : (currentPage - 1) * itemsPerPage + 1; + const endIdx = Math.min(currentPage * itemsPerPage, totalItems); + const currentLogs = logs.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage); + return (

Admin System Audit Logs

@@ -39,48 +51,105 @@ const AuditLogs = () => { ) : error ? (
Error: {error}
) : ( -
- - - - - - - - - - - - - {logs.map(log => ( - - - - - - - + <> +
+
Log IDAdmin UserActionTarget ObjectOperation DetailsTimestamp
#{log.id}{log.admin_username || log.admin || 'system'} - - {log.action} - - - {log.target_type} #{log.target_id || ''} - {typeof log.details === 'object' ? JSON.stringify(log.details) : log.details} - {log.performed_at ? new Date(log.performed_at).toLocaleString() : log.time} -
+ + + + + + + + - ))} - -
Log IDAdmin UserActionTarget ObjectOperation DetailsTimestamp
-
+ + + {currentLogs.map(log => ( + + #{log.id} + {log.admin_username || log.admin || 'system'} + + + {log.action} + + + + {log.target_type} #{log.target_id || ''} + + {typeof log.details === 'object' ? JSON.stringify(log.details) : log.details} + + {log.performed_at ? new Date(log.performed_at).toLocaleString() : log.time} + + + ))} + + +
+ + {/* Pagination Controls */} +
+
+ Showing {startIdx} to {endIdx} of {totalItems} items +
+ +
+
+ Items per page: + +
+ +
+ + + Page {currentPage} of {totalPages || 1} + + +
+
+
+ )} diff --git a/src/pages/customers/CustomerList.jsx b/src/pages/customers/CustomerList.jsx index b9d3d4f..a410d54 100644 --- a/src/pages/customers/CustomerList.jsx +++ b/src/pages/customers/CustomerList.jsx @@ -12,6 +12,10 @@ const CustomerList = () => { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); + // Pagination states + const [currentPage, setCurrentPage] = useState(1); + const [itemsPerPage, setItemsPerPage] = useState(10); + useEffect(() => { const fetchCustomers = async () => { try { @@ -32,6 +36,7 @@ const CustomerList = () => { if (!res.ok) throw new Error('Failed to fetch customers'); const data = await res.json(); setCustomers(data); + setCurrentPage(1); // Reset page to 1 on filter/search change } catch (err) { setError(err.message); } finally { @@ -42,6 +47,13 @@ const CustomerList = () => { fetchCustomers(); }, [searchTerm, filter, token]); + // Compute pagination details + const totalItems = customers.length; + const totalPages = Math.ceil(totalItems / itemsPerPage); + const startIdx = totalItems === 0 ? 0 : (currentPage - 1) * itemsPerPage + 1; + const endIdx = Math.min(currentPage * itemsPerPage, totalItems); + const currentCustomers = customers.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage); + return (

Customer Management

@@ -75,36 +87,93 @@ const CustomerList = () => { ) : error ? (
Error: {error}
) : ( -
- - - - - - - - - - - - - {customers.map(cust => ( - - - - - - - + <> +
+
Customer IDNameEmailPhoneStatusActions
#{cust.id}{cust.name}{cust.email}{cust.phone} - - 👁️ View Detail - -
+ + + + + + + + - ))} - -
Customer IDNameEmailPhoneStatusActions
-
+ + + {currentCustomers.map(cust => ( + + #{cust.id} + {cust.name} + {cust.email} + {cust.phone} + + + + 👁️ View Detail + + + + ))} + + +
+ + {/* Pagination Controls */} +
+
+ Showing {startIdx} to {endIdx} of {totalItems} items +
+ +
+
+ Items per page: + +
+ +
+ + + Page {currentPage} of {totalPages || 1} + + +
+
+
+ )} diff --git a/src/pages/products/ProductList.jsx b/src/pages/products/ProductList.jsx index 8113b6f..8a740a7 100644 --- a/src/pages/products/ProductList.jsx +++ b/src/pages/products/ProductList.jsx @@ -13,6 +13,10 @@ const ProductList = () => { const [error, setError] = useState(null); const [selectedProduct, setSelectedProduct] = useState(null); + // Pagination states + const [currentPage, setCurrentPage] = useState(1); + const [itemsPerPage, setItemsPerPage] = useState(10); + const fetchProducts = async () => { try { setLoading(true); @@ -32,6 +36,7 @@ const ProductList = () => { if (!res.ok) throw new Error('Failed to fetch products'); const data = await res.json(); setProducts(data); + setCurrentPage(1); // Reset page to 1 when filters change } catch (err) { setError(err.message); } finally { @@ -83,6 +88,18 @@ const ProductList = () => { (p.supplier_name && p.supplier_name.toLowerCase().includes(searchTerm.toLowerCase())) ); + // Reset page when search term changes + useEffect(() => { + setCurrentPage(1); + }, [searchTerm]); + + // Compute pagination details + const totalItems = filteredProducts.length; + const totalPages = Math.ceil(totalItems / itemsPerPage); + const startIdx = totalItems === 0 ? 0 : (currentPage - 1) * itemsPerPage + 1; + const endIdx = Math.min(currentPage * itemsPerPage, totalItems); + const currentProducts = filteredProducts.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage); + return (

Product Review & Management

@@ -142,73 +159,130 @@ const ProductList = () => { ) : error ? (
Error: {error}
) : ( -
- - - - - - - - - - - - - - {filteredProducts.map(prod => ( - - - - - - - - + <> +
+
IDProduct TitleSellerPriceStockStatusActions
#{prod.id} setSelectedProduct(prod)} - > - {prod.name} - {prod.supplier_name || 'N/A'}₹{parseFloat(prod.price).toLocaleString('en-IN')}{prod.stock} items -
- {(prod.status === 'pending' || prod.status === 'pending_approval') && ( - <> - - - - - )} - {prod.status === 'approved' && ( - <> - - - - )} - {(prod.status === 'hold' || prod.status === 'on_hold' || prod.status === 'rejected') && ( - - )} - -
-
+ + + + + + + + + - ))} - -
IDProduct TitleSellerPriceStockStatusActions
-
+ + + {currentProducts.map(prod => ( + + #{prod.id} + setSelectedProduct(prod)} + > + {prod.name} + + {prod.supplier_name || 'N/A'} + ₹{parseFloat(prod.price).toLocaleString('en-IN')} + {prod.stock} items + + +
+ {(prod.status === 'pending' || prod.status === 'pending_approval') && ( + <> + + + + + )} + {prod.status === 'approved' && ( + <> + + + + )} + {(prod.status === 'hold' || prod.status === 'on_hold' || prod.status === 'rejected') && ( + + )} + +
+ + + ))} + + +
+ + {/* Pagination Controls */} +
+
+ Showing {startIdx} to {endIdx} of {totalItems} items +
+ +
+
+ Items per page: + +
+ +
+ + + Page {currentPage} of {totalPages || 1} + + +
+
+
+ )} diff --git a/src/pages/sellers/SellerList.jsx b/src/pages/sellers/SellerList.jsx index 6588743..d394eae 100644 --- a/src/pages/sellers/SellerList.jsx +++ b/src/pages/sellers/SellerList.jsx @@ -12,6 +12,10 @@ const SellerList = () => { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); + // Pagination states + const [currentPage, setCurrentPage] = useState(1); + const [itemsPerPage, setItemsPerPage] = useState(10); + useEffect(() => { const fetchSellers = async () => { try { @@ -28,6 +32,7 @@ const SellerList = () => { if (!res.ok) throw new Error('Failed to fetch sellers'); const data = await res.json(); setSellers(data); + setCurrentPage(1); // Reset page to 1 when filter changes } catch (err) { setError(err.message); } finally { @@ -44,6 +49,18 @@ const SellerList = () => { return matchesSearch; }); + // Reset page when search term changes + useEffect(() => { + setCurrentPage(1); + }, [searchTerm]); + + // Compute pagination details + const totalItems = filteredSellers.length; + const totalPages = Math.ceil(totalItems / itemsPerPage); + const startIdx = totalItems === 0 ? 0 : (currentPage - 1) * itemsPerPage + 1; + const endIdx = Math.min(currentPage * itemsPerPage, totalItems); + const currentSellers = filteredSellers.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage); + return (
@@ -75,40 +92,97 @@ const SellerList = () => {
{loading ? ( -
Loading seller profiles...
+
Loading seller profiles...
) : error ? (
Error: {error}
) : ( -
- - - - - - - - - - - - {filteredSellers.map((seller) => ( - - - - - - + <> +
+
Seller NameEmailStatusJoined DateActions
{seller.name}{seller.email} - - {seller.joined_at ? new Date(seller.joined_at).toLocaleDateString() : 'N/A'} - - 👁️ View Details - -
+ + + + + + + - ))} - -
Seller NameEmailStatusJoined DateActions
-
+ + + {currentSellers.map((seller) => ( + + {seller.name} + {seller.email} + + + + {seller.joined_at ? new Date(seller.joined_at).toLocaleDateString() : 'N/A'} + + + 👁️ View Details + + + + ))} + + +
+ + {/* Pagination Controls */} +
+
+ Showing {startIdx} to {endIdx} of {totalItems} items +
+ +
+
+ Items per page: + +
+ +
+ + + Page {currentPage} of {totalPages || 1} + + +
+
+
+ )}