Files
dkala-admin/src/pages/coupon/List.tsx
T
2026-02-07 16:20:18 +03:30

103 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { type FC, useMemo } from 'react'
import Table from '@/components/Table'
import Filters from '@/components/Filters'
import { useGetCoupons, useDeleteCoupon } from './hooks/useCouponData'
import { useCouponFilters } from './hooks/useCouponFilters'
import { getCouponTableColumns } from './components/CouponTableColumns'
import { useCouponFiltersFields } from './components/CouponFiltersFields'
import { Add } from 'iconsax-react'
import { Link } from 'react-router-dom'
import { Pages } from '@/config/Pages'
import Button from '@/components/Button'
import type { ICoupon } from './types/Types'
import type { RowDataType } from '@/components/types/TableTypes'
const CouponsList: FC = () => {
const {
filters,
currentPage,
handleFiltersChange,
handlePageChange,
limit,
} = useCouponFilters()
const { data: couponsData, isLoading } = useGetCoupons()
const { mutate: deleteCoupon, isPending: isDeleting } = useDeleteCoupon()
const coupons = useMemo(() => couponsData?.data || [], [couponsData])
const filteredCoupons = useMemo(() => {
const searchValue = (filters.search as string || '').toLowerCase().trim()
const statusFilter = filters.status || 'all'
const typeFilter = filters.type || 'all'
return coupons.filter((coupon: ICoupon) => {
const matchesSearch =
searchValue === '' ||
(coupon.code || '').toLowerCase().includes(searchValue) ||
(coupon.name || '').toLowerCase().includes(searchValue)
const matchesStatus =
statusFilter === 'all' ||
(statusFilter === 'active' && coupon.isActive) ||
(statusFilter === 'inactive' && !coupon.isActive)
const matchesType =
typeFilter === 'all' ||
coupon.type === typeFilter
return matchesSearch && matchesStatus && matchesType
})
}, [coupons, filters])
const totalPages = Math.max(1, Math.ceil(filteredCoupons.length / limit) || 1)
const paginatedCoupons = useMemo(() => {
const startIndex = (currentPage - 1) * limit
return filteredCoupons.slice(startIndex, startIndex + limit)
}, [filteredCoupons, currentPage, limit])
const columns = getCouponTableColumns({
onDelete: (id: string) => deleteCoupon(id),
isDeleting
})
const filterFields = useCouponFiltersFields()
return (
<div className='mt-5'>
<div className='flex justify-between items-center'>
<h1 className='text-lg font-light'>لیست کوپنها</h1>
<Link to={Pages.coupons.add}>
<Button className='w-fit px-6'>
<div className='flex gap-2 items-center'>
<Add color='#fff' size={20} />
<span>افزودن کوپن</span>
</div>
</Button>
</Link>
</div>
<div className='mt-8'>
<Filters
fields={filterFields}
onChange={handleFiltersChange}
initialValues={filters}
searchField="search"
/>
</div>
<Table<ICoupon & RowDataType>
columns={columns}
data={paginatedCoupons as (ICoupon & RowDataType)[]}
isloading={isLoading}
pagination={{
currentPage,
totalPages,
onPageChange: handlePageChange,
}}
/>
</div>
)
}
export default CouponsList