import { useEffect, useMemo, useState } from 'react' import { useQuery } from '@tanstack/react-query' import { getRouteApi } from '@tanstack/react-router' import { type SortingState, type VisibilityState, flexRender, getCoreRowModel, getFacetedRowModel, getFacetedUniqueValues, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable, } from '@tanstack/react-table' import { useMediaQuery } from '@/hooks' import { useTranslation } from 'react-i18next' import { cn } from '@/lib/utils' import { useTableUrlState } from '@/hooks/use-table-url-state' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table' import { DataTablePagination, DataTableToolbar, TableSkeleton, TableEmpty, MobileCardList, } from '@/components/data-table' import { PageFooterPortal } from '@/components/layout' import { getRedemptions, searchRedemptions } from '../api' import { REDEMPTION_STATUS, getRedemptionStatusOptions } from '../constants' import { isRedemptionExpired } from '../lib' import { DataTableBulkActions } from './data-table-bulk-actions' import { useRedemptionsColumns } from './redemptions-columns' import { useRedemptions } from './redemptions-provider' const route = getRouteApi('/_authenticated/redemption-codes/') export function RedemptionsTable() { const { t } = useTranslation() const columns = useRedemptionsColumns() const { refreshTrigger } = useRedemptions() const isMobile = useMediaQuery('(max-width: 640px)') const [rowSelection, setRowSelection] = useState({}) const [sorting, setSorting] = useState([]) const [columnVisibility, setColumnVisibility] = useState({}) const { globalFilter, onGlobalFilterChange, columnFilters, onColumnFiltersChange, pagination, onPaginationChange, ensurePageInRange, } = useTableUrlState({ search: route.useSearch(), navigate: route.useNavigate(), pagination: { defaultPage: 1, defaultPageSize: 20 }, globalFilter: { enabled: true, key: 'filter' }, columnFilters: [{ columnId: 'status', searchKey: 'status', type: 'array' }], }) // Fetch data with React Query const { data, isLoading, isFetching } = useQuery({ queryKey: [ 'redemptions', pagination.pageIndex + 1, pagination.pageSize, globalFilter, refreshTrigger, ], queryFn: async () => { const hasFilter = globalFilter?.trim() const params = { p: pagination.pageIndex + 1, page_size: pagination.pageSize, } const result = hasFilter ? await searchRedemptions({ ...params, keyword: globalFilter }) : await getRedemptions(params) return { items: result.data?.items || [], total: result.data?.total || 0, } }, placeholderData: (previousData) => previousData, }) const redemptions = data?.items || [] const table = useReactTable({ data: redemptions, columns, state: { sorting, columnVisibility, rowSelection, columnFilters, globalFilter, pagination, }, enableRowSelection: true, onRowSelectionChange: setRowSelection, onSortingChange: setSorting, onColumnVisibilityChange: setColumnVisibility, globalFilterFn: (row, _columnId, filterValue) => { const name = String(row.getValue('name')).toLowerCase() const id = String(row.getValue('id')) const searchValue = String(filterValue).toLowerCase() return name.includes(searchValue) || id.includes(searchValue) }, getCoreRowModel: getCoreRowModel(), getFilteredRowModel: getFilteredRowModel(), getPaginationRowModel: getPaginationRowModel(), getSortedRowModel: getSortedRowModel(), getFacetedRowModel: getFacetedRowModel(), getFacetedUniqueValues: getFacetedUniqueValues(), onPaginationChange, onGlobalFilterChange, onColumnFiltersChange, manualPagination: !globalFilter, pageCount: Math.ceil((data?.total || 0) / pagination.pageSize), }) const pageCount = table.getPageCount() useEffect(() => { ensurePageInRange(pageCount) }, [pageCount, ensurePageInRange]) const redemptionStatusOptions = useMemo( () => getRedemptionStatusOptions(t), [t] ) return ( <>
{isMobile ? ( ) : ( <>
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => { return ( {header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext() )} ) })} ))} {isLoading ? ( ) : table.getRowModel().rows.length === 0 ? ( ) : ( table.getRowModel().rows.map((row) => { const redemption = row.original const isDisabled = redemption.status !== REDEMPTION_STATUS.ENABLED || isRedemptionExpired( redemption.expired_time, redemption.status ) return ( {row.getVisibleCells().map((cell) => ( {flexRender( cell.column.columnDef.cell, cell.getContext() )} ))} ) }) )}
)}
) }