+25
-23
@@ -1,7 +1,6 @@
|
|||||||
import Button from '@/components/Button'
|
import Button from '@/components/Button'
|
||||||
import Filters, { type FilterValues } from '@/components/Filters'
|
import Filters, { type FilterValues } from '@/components/Filters'
|
||||||
import Table from '@/components/Table'
|
import Table from '@/components/Table'
|
||||||
import Tabs from '@/components/Tabs'
|
|
||||||
import { AddSquare, Edit, More2 } from 'iconsax-react'
|
import { AddSquare, Edit, More2 } from 'iconsax-react'
|
||||||
import { type FC, useMemo, useState } from 'react'
|
import { type FC, useMemo, useState } from 'react'
|
||||||
import { useDeleteProduct, useDuplicateProduct, useGetCategory, useGetProducts } from './hooks/useProductData'
|
import { useDeleteProduct, useDuplicateProduct, useGetCategory, useGetProducts } from './hooks/useProductData'
|
||||||
@@ -11,39 +10,44 @@ import TrashWithConfrim from '@/components/TrashWithConfrim'
|
|||||||
import CopyWithConfirm from '@/components/CopyWithConfirm'
|
import CopyWithConfirm from '@/components/CopyWithConfirm'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import { extractErrorMessage } from '@/config/func'
|
import { extractErrorMessage } from '@/config/func'
|
||||||
|
import type { CategoryType } from './types/Types'
|
||||||
|
|
||||||
|
const flattenCategoryOptions = (categories: CategoryType[]) => {
|
||||||
|
const options: { label: string; value: string }[] = []
|
||||||
|
|
||||||
|
for (const category of categories) {
|
||||||
|
options.push({ label: category.title, value: category.id })
|
||||||
|
for (const child of category.children ?? []) {
|
||||||
|
options.push({ label: `— ${child.title}`, value: child.id })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
const ProductList: FC = () => {
|
const ProductList: FC = () => {
|
||||||
const [page, setPage] = useState<number>(1)
|
const [page, setPage] = useState<number>(1)
|
||||||
const [search, setSearch] = useState<string>('')
|
const [search, setSearch] = useState<string>('')
|
||||||
const [categoryId, setCategoryId] = useState<string>('')
|
const [categoryId, setCategoryId] = useState<string>('')
|
||||||
|
|
||||||
const { data: categoriesData } = useGetCategory({ limit: 1000 })
|
const { data: categoriesData } = useGetCategory({ limit: 1000, parentId: 'null' })
|
||||||
const { data: products, refetch } = useGetProducts({
|
const { data: products, refetch } = useGetProducts({
|
||||||
page,
|
page,
|
||||||
search: search || undefined,
|
search: search || undefined,
|
||||||
categoryId: categoryId || undefined,
|
categoryId: categoryId || undefined,
|
||||||
})
|
})
|
||||||
|
|
||||||
const categoryTabs = useMemo(
|
const categoryOptions = useMemo(
|
||||||
() => [
|
() => flattenCategoryOptions((categoriesData?.data ?? []) as CategoryType[]),
|
||||||
{ label: 'همه', value: '' },
|
|
||||||
...(categoriesData?.data?.map((category) => ({
|
|
||||||
label: category.title,
|
|
||||||
value: category.id,
|
|
||||||
})) ?? []),
|
|
||||||
],
|
|
||||||
[categoriesData?.data],
|
[categoriesData?.data],
|
||||||
)
|
)
|
||||||
|
|
||||||
const handleFiltersChange = (filters: FilterValues) => {
|
const handleFiltersChange = (filters: FilterValues) => {
|
||||||
setSearch((filters.search as string) ?? '')
|
setSearch(filters.search ?? '')
|
||||||
|
setCategoryId(filters.categoryId ?? '')
|
||||||
setPage(1)
|
setPage(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCategoryTabChange = (tab: string) => {
|
|
||||||
setCategoryId(tab)
|
|
||||||
setPage(1)
|
|
||||||
}
|
|
||||||
const { mutate: deleteProduct, isPending: isDeleting } = useDeleteProduct()
|
const { mutate: deleteProduct, isPending: isDeleting } = useDeleteProduct()
|
||||||
const { mutate: duplicateProduct, isPending: isDuplicating } = useDuplicateProduct()
|
const { mutate: duplicateProduct, isPending: isDuplicating } = useDuplicateProduct()
|
||||||
const [duplicatingId, setDuplicatingId] = useState<string | null>(null)
|
const [duplicatingId, setDuplicatingId] = useState<string | null>(null)
|
||||||
@@ -98,14 +102,6 @@ const ProductList: FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='mt-8'>
|
|
||||||
<Tabs
|
|
||||||
items={categoryTabs}
|
|
||||||
activeTab={categoryId}
|
|
||||||
onTabChange={handleCategoryTabChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='mt-8'>
|
<div className='mt-8'>
|
||||||
<Filters
|
<Filters
|
||||||
fields={[
|
fields={[
|
||||||
@@ -113,6 +109,12 @@ const ProductList: FC = () => {
|
|||||||
name: 'search',
|
name: 'search',
|
||||||
type: 'input',
|
type: 'input',
|
||||||
placeholder: 'جستجوی محصول'
|
placeholder: 'جستجوی محصول'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'categoryId',
|
||||||
|
type: 'select',
|
||||||
|
placeholder: 'دستهبندی',
|
||||||
|
options: categoryOptions,
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
onChange={handleFiltersChange}
|
onChange={handleFiltersChange}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { type FC, type SelectHTMLAttributes } from 'react'
|
import { type FC, type SelectHTMLAttributes, useMemo } from 'react'
|
||||||
import { useGetCategory } from '../hooks/useProductData'
|
import { useGetCategory } from '../hooks/useProductData'
|
||||||
import Select from '@/components/Select'
|
import Select from '@/components/Select'
|
||||||
|
import type { CategoryType } from '../types/Types'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
error_text?: string,
|
error_text?: string,
|
||||||
@@ -9,6 +10,19 @@ type Props = {
|
|||||||
clearable?: boolean,
|
clearable?: boolean,
|
||||||
} & SelectHTMLAttributes<HTMLSelectElement>
|
} & SelectHTMLAttributes<HTMLSelectElement>
|
||||||
|
|
||||||
|
const flattenCategoryOptions = (categories: CategoryType[]) => {
|
||||||
|
const options: { label: string; value: string }[] = []
|
||||||
|
|
||||||
|
for (const category of categories) {
|
||||||
|
options.push({ label: category.title, value: category.id })
|
||||||
|
for (const child of category.children ?? []) {
|
||||||
|
options.push({ label: `— ${child.title}`, value: child.id })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
const CategoriesSelect: FC<Props> = ({
|
const CategoriesSelect: FC<Props> = ({
|
||||||
isDisableShowLable,
|
isDisableShowLable,
|
||||||
placeholder,
|
placeholder,
|
||||||
@@ -16,8 +30,12 @@ const CategoriesSelect: FC<Props> = ({
|
|||||||
clearable = true,
|
clearable = true,
|
||||||
...selectProps
|
...selectProps
|
||||||
}) => {
|
}) => {
|
||||||
|
const { data: categories } = useGetCategory({ limit: 1000, parentId: 'null' })
|
||||||
|
|
||||||
const { data: categories } = useGetCategory()
|
const items = useMemo(
|
||||||
|
() => flattenCategoryOptions((categories?.data ?? []) as CategoryType[]),
|
||||||
|
[categories?.data],
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Select
|
<Select
|
||||||
@@ -25,15 +43,10 @@ const CategoriesSelect: FC<Props> = ({
|
|||||||
placeholder={placeholder || 'انتخاب'}
|
placeholder={placeholder || 'انتخاب'}
|
||||||
error_text={error_text}
|
error_text={error_text}
|
||||||
clearable={clearable}
|
clearable={clearable}
|
||||||
items={categories?.data?.map((item) => {
|
items={items}
|
||||||
return {
|
|
||||||
label: item.title,
|
|
||||||
value: item.id + ''
|
|
||||||
}
|
|
||||||
}) || []}
|
|
||||||
{...selectProps}
|
{...selectProps}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CategoriesSelect
|
export default CategoriesSelect
|
||||||
|
|||||||
Reference in New Issue
Block a user