Skip to content

Commit

Permalink
feat(fe): data table admin make filter search pagination delete funct…
Browse files Browse the repository at this point in the history
…ions optional (#1572)

* feat(fe): make component for search lang tags filter

* feat(fe): add enable props for search filter delete functions

* feat(fe): make pagination optional

* feat(fe): change href when click row
  • Loading branch information
jihorobert authored Mar 19, 2024
1 parent 6b4c26e commit 4984ff3
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 68 deletions.
9 changes: 8 additions & 1 deletion apps/frontend/app/admin/problem/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,14 @@ export default function Page() {
))}
</>
) : (
<DataTableAdmin columns={columns} data={problems} />
<DataTableAdmin
columns={columns}
data={problems}
enableSearch={true}
enableFilter={true}
enableDelete={true}
enablePagination={true}
/>
)}
</div>
<ScrollBar orientation="horizontal" />
Expand Down
151 changes: 84 additions & 67 deletions apps/frontend/components/DataTableAdmin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
TableHeader,
TableRow
} from '@/components/ui/table'
import { useQuery, useMutation } from '@apollo/client'
import { useMutation, useQuery } from '@apollo/client'
import type { ColumnDef, SortingState } from '@tanstack/react-table'
import {
flexRender,
Expand All @@ -48,26 +48,28 @@ import { Input } from './ui/input'
interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[]
data: TData[]
enableSearch?: boolean // Enable search title
enableFilter?: boolean // Enable filter for languages and tags
enableDelete?: boolean // Enable delete selected rows
enablePagination?: boolean // Enable pagination
}

// dummy data
const languageOptions = ['C', 'Cpp', 'Golang', 'Java', 'Python2', 'Python3']

export function DataTableAdmin<TData, TValue>({
columns,
data
data,
enableSearch = false,
enableFilter = false,
enableDelete = false,
enablePagination = false
}: DataTableProps<TData, TValue>) {
const [rowSelection, setRowSelection] = useState({})
const [sorting, setSorting] = useState<SortingState>([])
const pathname = usePathname()
const page = pathname.split('/').pop()

const router = useRouter()

const { data: tagsData } = useQuery(GET_TAGS)
const tags =
tagsData?.getTags.map(({ id, name }) => ({ id: +id, name })) ?? []

const selectedRowCount = Object.values(rowSelection).filter(Boolean).length
const table = useReactTable({
data,
columns,
Expand All @@ -87,8 +89,6 @@ export function DataTableAdmin<TData, TValue>({
getFacetedUniqueValues: getFacetedUniqueValues()
})

const selectedRowCount = Object.values(rowSelection).filter(Boolean).length

const DELETE_PROBLEM = gql(`
mutation DeleteProblem($groupId: Int!, $id: Int!) {
deleteProblem(groupId: $groupId, id: $id) {
Expand All @@ -98,13 +98,11 @@ export function DataTableAdmin<TData, TValue>({
`)

const [deleteProblem] = useMutation(DELETE_PROBLEM)

// TODO: contest랑 notice도 같은 방식으로 추가
const handleDeleteRows = async () => {
const selectedRows = table.getSelectedRowModel().rows as {
original: { id: number }
}[]

const deletePromise = selectedRows.map((row) => {
if (page === 'problem') {
return deleteProblem({
Expand All @@ -127,64 +125,81 @@ export function DataTableAdmin<TData, TValue>({
})
}

const { data: tagsData } = useQuery(GET_TAGS)
const tags =
tagsData?.getTags.map(({ id, name }) => ({ id: +id, name })) ?? []

return (
<div className="space-y-4">
<div className="flex justify-between">
<div className="flex gap-2">
<Input
placeholder="Search"
value={(table.getColumn('title')?.getFilterValue() as string) ?? ''}
onChange={(event) =>
table.getColumn('title')?.setFilterValue(event.target.value)
}
className="h-10 w-[150px] lg:w-[250px]"
/>

{table.getColumn('languages') && (
<DataTableLangFilter
column={table.getColumn('languages')}
title="Languages"
options={languageOptions}
/>
)}
{(enableSearch || enableFilter || enableDelete) && (
<div className="flex justify-between">
<div className="flex gap-2">
{enableSearch && (
<Input
placeholder="Search"
value={
(table.getColumn('title')?.getFilterValue() as string) ?? ''
}
onChange={(event) =>
table.getColumn('title')?.setFilterValue(event.target.value)
}
className="h-10 w-[150px] lg:w-[250px]"
/>
)}
{enableFilter && (
<div className="flex gap-2">
{table.getColumn('languages') && (
<DataTableLangFilter
column={table.getColumn('languages')}
title="Languages"
options={languageOptions}
/>
)}
{table.getColumn('tag') && (
<DataTableTagsFilter
column={table.getColumn('tag')}
title="Tags"
options={tags}
/>
)}
</div>
)}
</div>

{table.getColumn('tag') && (
<DataTableTagsFilter
column={table.getColumn('tag')}
title="Tags"
options={tags}
/>
)}
</div>
{selectedRowCount !== 0 ? (
<AlertDialog>
<AlertDialogTrigger asChild>
{enableDelete ? (
selectedRowCount !== 0 ? (
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="outline">
<PiTrashLight fontSize={18} />
</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Delete</AlertDialogTitle>
<AlertDialogDescription>
Are you sure you want to permanently delete{' '}
{selectedRowCount} {page}(s)?
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction asChild>
<Button onClick={() => handleDeleteRows()}>
Continue
</Button>
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
) : (
<Button variant="outline">
<PiTrashLight fontSize={18} />
</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Delete</AlertDialogTitle>
<AlertDialogDescription>
Are you sure you want to permanently delete {selectedRowCount}{' '}
{page}(s)?
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction asChild>
<Button onClick={() => handleDeleteRows()}>Continue</Button>
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
) : (
<Button variant="outline">
<PiTrashLight fontSize={18} />
</Button>
)}
</div>
)
) : null}
</div>
)}

<div className="rounded-md border">
<Table>
Expand All @@ -211,7 +226,9 @@ export function DataTableAdmin<TData, TValue>({
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => {
const href =
`/admin/${page}/${(row.original as { id: number }).id}` as Route
page === 'contest'
? (`/admin/contest/${(row.original as { id: number }).id}` as Route)
: (`/admin/problem/${(row.original as { id: number }).id}` as Route)
return (
<TableRow
key={row.id}
Expand Down Expand Up @@ -250,7 +267,7 @@ export function DataTableAdmin<TData, TValue>({
</TableBody>
</Table>
</div>
<DataTablePagination table={table} />
{enablePagination && <DataTablePagination table={table} />}
</div>
)
}

0 comments on commit 4984ff3

Please sign in to comment.