product list
deploy to danak / build_and_deploy (push) Has been cancelled

This commit is contained in:
2026-07-21 10:49:40 +03:30
parent e28a0d611e
commit bf16a84ba4
3 changed files with 98 additions and 15 deletions
+53 -5
View File
@@ -1,9 +1,10 @@
import Button from '@/components/Button'
import Filters from '@/components/Filters'
import Filters, { type FilterValues } from '@/components/Filters'
import Table from '@/components/Table'
import Tabs from '@/components/Tabs'
import { AddSquare, Edit, More2 } from 'iconsax-react'
import { type FC, useState } from 'react'
import { useDeleteProduct, useDuplicateProduct, useGetProducts } from './hooks/useProductData'
import { type FC, useMemo, useState } from 'react'
import { useDeleteProduct, useDuplicateProduct, useGetCategory, useGetProducts } from './hooks/useProductData'
import { Link } from 'react-router-dom'
import { Paths } from '@/config/Paths'
import TrashWithConfrim from '@/components/TrashWithConfrim'
@@ -12,8 +13,37 @@ import { toast } from 'react-toastify'
import { extractErrorMessage } from '@/config/func'
const ProductList: FC = () => {
const [page, setPage] = useState<number>(1)
const [search, setSearch] = useState<string>('')
const [categoryId, setCategoryId] = useState<string>('')
const { data: products, refetch } = useGetProducts()
const { data: categoriesData } = useGetCategory({ limit: 1000 })
const { data: products, refetch } = useGetProducts({
page,
search: search || undefined,
categoryId: categoryId || undefined,
})
const categoryTabs = useMemo(
() => [
{ label: 'همه', value: '' },
...(categoriesData?.data?.map((category) => ({
label: category.title,
value: category.id,
})) ?? []),
],
[categoriesData?.data],
)
const handleFiltersChange = (filters: FilterValues) => {
setSearch((filters.search as string) ?? '')
setPage(1)
}
const handleCategoryTabChange = (tab: string) => {
setCategoryId(tab)
setPage(1)
}
const { mutate: deleteProduct, isPending: isDeleting } = useDeleteProduct()
const { mutate: duplicateProduct, isPending: isDuplicating } = useDuplicateProduct()
const [duplicatingId, setDuplicatingId] = useState<string | null>(null)
@@ -68,6 +98,14 @@ const ProductList: FC = () => {
</div>
</div>
<div className='mt-8'>
<Tabs
items={categoryTabs}
activeTab={categoryId}
onTabChange={handleCategoryTabChange}
/>
</div>
<div className='mt-8'>
<Filters
fields={[
@@ -77,7 +115,7 @@ const ProductList: FC = () => {
placeholder: 'جستجوی محصول'
}
]}
onChange={() => { }}
onChange={handleFiltersChange}
/>
</div>
@@ -88,6 +126,11 @@ const ProductList: FC = () => {
key: 'title',
title: 'عنوان محصول',
},
{
key: 'category',
title: 'دسته‌بندی',
render: (item) => item.category?.title ?? '-',
},
{
key: 'attribute',
title: 'ویژگی ها',
@@ -133,6 +176,11 @@ const ProductList: FC = () => {
},
]}
data={products?.data}
pagination={{
currentPage: page,
onPageChange: setPage,
totalPages: products?.meta?.totalPages ?? 1,
}}
/>
</div>
</div>
+15 -6
View File
@@ -12,10 +12,14 @@ import type {
CreateProductType,
} from "../types/Types";
export const useGetCategory = () => {
export const useGetCategory = (params?: api.GetCategoryParams) => {
const page = params?.page ?? 1;
const limit = params?.limit;
const search = params?.search;
return useQuery({
queryKey: ["category"],
queryFn: api.getCategory,
queryKey: ["category", page, limit, search],
queryFn: () => api.getCategory({ page, limit, search }),
});
};
@@ -52,10 +56,15 @@ export const useGetCategoryDetail = (id: string) => {
});
};
export const useGetProducts = () => {
export const useGetProducts = (params?: api.GetProductsParams) => {
const page = params?.page ?? 1;
const search = params?.search;
const limit = params?.limit;
const categoryId = params?.categoryId;
return useQuery({
queryKey: ["products"],
queryFn: api.getProducts,
queryKey: ["products", page, search, limit, categoryId],
queryFn: () => api.getProducts({ page, search, limit, categoryId }),
});
};
+30 -4
View File
@@ -1,8 +1,20 @@
import axios from "@/config/axios";
import { type AttributeDetailResponseType, type AttributeResponseType, type AttributeValueDetailResponseType, type AttributeValuesResponseType, type CategoriesResponse, type CategoryResponse, type CreateAttributeType, type CreateAttributeValueType, type CreateCategoryType, type CreateProductType, type ProductDetailResponeType, type ProductResponeType } from "../types/Types";
export const getCategory = async () => {
const { data } = await axios.get<CategoriesResponse>("/admin/category");
export type GetCategoryParams = {
page?: number;
limit?: number;
search?: string;
};
export const getCategory = async (params?: GetCategoryParams) => {
const { data } = await axios.get<CategoriesResponse>("/admin/category", {
params: {
page: params?.page,
limit: params?.limit,
search: params?.search || undefined,
},
});
return data;
};
@@ -26,8 +38,22 @@ export const getCategoryDetail = async(id:string) => {
return data
}
export const getProducts = async () => {
const { data } = await axios.get<ProductResponeType>("/admin/products");
export type GetProductsParams = {
page?: number;
limit?: number;
search?: string;
categoryId?: string;
};
export const getProducts = async (params?: GetProductsParams) => {
const { data } = await axios.get<ProductResponeType>("/admin/products", {
params: {
page: params?.page,
limit: params?.limit,
search: params?.search || undefined,
categoryId: params?.categoryId || undefined,
},
});
return data;
};