feat(products-list): add pagination to products list and update filter handling
This commit is contained in:
parent
e601a2cc5a
commit
9bf5d63d1b
|
|
@ -8,6 +8,7 @@ import { Button } from "@/components/ui/Button";
|
||||||
import { Trash2, Edit3, Plus, Package, Eye, Image } from "lucide-react";
|
import { Trash2, Edit3, Plus, Package, Eye, Image } from "lucide-react";
|
||||||
import { Modal } from "@/components/ui/Modal";
|
import { Modal } from "@/components/ui/Modal";
|
||||||
import { persianToEnglish } from '../../../utils/numberUtils';
|
import { persianToEnglish } from '../../../utils/numberUtils';
|
||||||
|
import { Pagination } from "@/components/ui/Pagination";
|
||||||
|
|
||||||
const ProductsTableSkeleton = () => (
|
const ProductsTableSkeleton = () => (
|
||||||
<div className="bg-white dark:bg-gray-800 shadow-sm border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden">
|
<div className="bg-white dark:bg-gray-800 shadow-sm border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden">
|
||||||
|
|
@ -71,14 +72,16 @@ const ProductsListPage = () => {
|
||||||
category_id: '',
|
category_id: '',
|
||||||
status: '',
|
status: '',
|
||||||
min_price: '',
|
min_price: '',
|
||||||
max_price: ''
|
max_price: '',
|
||||||
|
page: 1,
|
||||||
|
limit: 100,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { data: productsData, isLoading, error } = useProducts({
|
const { data: productsData, isLoading, error } = useProducts({
|
||||||
...filters,
|
...filters,
|
||||||
category_id: filters.category_id ? Number(filters.category_id) : undefined,
|
category_id: filters.category_id ? Number(filters.category_id) : undefined,
|
||||||
min_price: filters.min_price ? Number(filters.min_price) : undefined,
|
min_price: filters.min_price ? Number(filters.min_price) : undefined,
|
||||||
max_price: filters.max_price ? Number(filters.max_price) : undefined
|
max_price: filters.max_price ? Number(filters.max_price) : undefined,
|
||||||
});
|
});
|
||||||
const { data: categories } = useCategories();
|
const { data: categories } = useCategories();
|
||||||
const { mutate: deleteProduct, isPending: isDeleting } = useDeleteProduct();
|
const { mutate: deleteProduct, isPending: isDeleting } = useDeleteProduct();
|
||||||
|
|
@ -108,15 +111,15 @@ const ProductsListPage = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setFilters(prev => ({ ...prev, search: e.target.value }));
|
setFilters(prev => ({ ...prev, search: e.target.value, page: 1 }));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCategoryChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
const handleCategoryChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||||
setFilters(prev => ({ ...prev, category_id: e.target.value }));
|
setFilters(prev => ({ ...prev, category_id: e.target.value, page: 1 }));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleStatusChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
const handleStatusChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||||
setFilters(prev => ({ ...prev, status: e.target.value }));
|
setFilters(prev => ({ ...prev, status: e.target.value, page: 1 }));
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatPrice = (price: number) => {
|
const formatPrice = (price: number) => {
|
||||||
|
|
@ -142,6 +145,11 @@ const ProductsListPage = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const total = productsData?.total || 0;
|
||||||
|
const currentPage = productsData?.page || filters.page;
|
||||||
|
const perPage = productsData?.per_page || filters.limit;
|
||||||
|
const totalPages = Math.max(1, Math.ceil((total || 0) / (perPage || 20)));
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return (
|
return (
|
||||||
<div className="p-6">
|
<div className="p-6">
|
||||||
|
|
@ -233,7 +241,7 @@ const ProductsListPage = () => {
|
||||||
value={filters.min_price}
|
value={filters.min_price}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const converted = persianToEnglish(e.target.value);
|
const converted = persianToEnglish(e.target.value);
|
||||||
setFilters(prev => ({ ...prev, min_price: converted }));
|
setFilters(prev => ({ ...prev, min_price: converted, page: 1 }));
|
||||||
}}
|
}}
|
||||||
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-1 focus:ring-primary-500 dark:bg-gray-700 dark:text-gray-100"
|
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-1 focus:ring-primary-500 dark:bg-gray-700 dark:text-gray-100"
|
||||||
/>
|
/>
|
||||||
|
|
@ -244,7 +252,7 @@ const ProductsListPage = () => {
|
||||||
value={filters.max_price}
|
value={filters.max_price}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const converted = persianToEnglish(e.target.value);
|
const converted = persianToEnglish(e.target.value);
|
||||||
setFilters(prev => ({ ...prev, max_price: converted }));
|
setFilters(prev => ({ ...prev, max_price: converted, page: 1 }));
|
||||||
}}
|
}}
|
||||||
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-1 focus:ring-primary-500 dark:bg-gray-700 dark:text-gray-100"
|
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-1 focus:ring-primary-500 dark:bg-gray-700 dark:text-gray-100"
|
||||||
/>
|
/>
|
||||||
|
|
@ -435,6 +443,15 @@ const ProductsListPage = () => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Pagination */}
|
||||||
|
<Pagination
|
||||||
|
currentPage={currentPage}
|
||||||
|
totalPages={totalPages}
|
||||||
|
itemsPerPage={perPage}
|
||||||
|
totalItems={total}
|
||||||
|
onPageChange={(page) => setFilters(prev => ({ ...prev, page }))}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Delete Confirmation Modal */}
|
{/* Delete Confirmation Modal */}
|
||||||
<Modal
|
<Modal
|
||||||
isOpen={!!deleteProductId}
|
isOpen={!!deleteProductId}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue