summaryrefslogtreecommitdiff
path: root/components/data-table/data-table-pagination.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'components/data-table/data-table-pagination.tsx')
-rw-r--r--components/data-table/data-table-pagination.tsx132
1 files changed, 132 insertions, 0 deletions
diff --git a/components/data-table/data-table-pagination.tsx b/components/data-table/data-table-pagination.tsx
new file mode 100644
index 00000000..7a2a03f8
--- /dev/null
+++ b/components/data-table/data-table-pagination.tsx
@@ -0,0 +1,132 @@
+"use client"
+
+import * as React from "react"
+import { type Table } from "@tanstack/react-table"
+import {
+ ChevronLeft,
+ ChevronRight,
+ ChevronsLeft,
+ ChevronsRight,
+} from "lucide-react"
+
+import { Button } from "@/components/ui/button"
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/components/ui/select"
+
+interface DataTablePaginationProps<TData> {
+ table: Table<TData>
+ pageSizeOptions?: Array<number | "All">
+}
+
+export function DataTablePagination<TData>({
+ table,
+ pageSizeOptions = [10, 20, 30, 40, 50, "All"],
+}: DataTablePaginationProps<TData>) {
+ // 현재 테이블 pageSize
+ const currentPageSize = table.getState().pagination.pageSize
+
+ // "All"을 1,000,000으로 처리할 것이므로,
+ // 만약 현재 pageSize가 1,000,000이면 화면상 "All"로 표시
+ const selectValue =
+ currentPageSize === 1_000_000
+ ? "All"
+ : String(currentPageSize)
+
+ return (
+ <div className="flex w-full flex-col-reverse items-center justify-between gap-4 overflow-auto p-1 sm:flex-row sm:gap-8">
+ <div className="flex-1 whitespace-nowrap text-sm text-muted-foreground">
+ {table.getFilteredSelectedRowModel().rows.length} of{" "}
+ {table.getFilteredRowModel().rows.length} row(s) selected.
+ </div>
+ <div className="flex flex-col-reverse items-center gap-4 sm:flex-row sm:gap-6 lg:gap-8">
+ {/* Rows per page Select */}
+ <div className="flex items-center space-x-2">
+ <p className="whitespace-nowrap text-sm font-medium">Rows per page</p>
+ <Select
+ value={selectValue}
+ onValueChange={(value) => {
+ if (value === "All") {
+ // "All"을 1,000,000으로 치환
+ table.setPageSize(1_000_000)
+ } else {
+ table.setPageSize(Number(value))
+ }
+ }}
+ >
+ <SelectTrigger className="h-8 w-[4.5rem]">
+ <SelectValue placeholder={selectValue} />
+ </SelectTrigger>
+ <SelectContent side="top">
+ {pageSizeOptions.map((option) => {
+ // 화면에 표시할 라벨
+ const label = option === "All" ? "All" : String(option)
+ // value도 문자열화
+ const val = option === "All" ? "All" : String(option)
+
+ return (
+ <SelectItem key={val} value={val}>
+ {label}
+ </SelectItem>
+ )
+ })}
+ </SelectContent>
+ </Select>
+ </div>
+
+ {/* 현재 페이지 / 전체 페이지 */}
+ <div className="flex items-center justify-center text-sm font-medium">
+ Page {table.getState().pagination.pageIndex + 1} of{" "}
+ {table.getPageCount()}
+ </div>
+
+ {/* 페이지 이동 버튼 */}
+ <div className="flex items-center space-x-2">
+ <Button
+ aria-label="Go to first page"
+ variant="outline"
+ className="hidden size-8 p-0 lg:flex"
+ onClick={() => table.setPageIndex(0)}
+ disabled={!table.getCanPreviousPage()}
+ >
+ <ChevronsLeft className="size-4" aria-hidden="true" />
+ </Button>
+ <Button
+ aria-label="Go to previous page"
+ variant="outline"
+ size="icon"
+ className="size-8"
+ onClick={() => table.previousPage()}
+ disabled={!table.getCanPreviousPage()}
+ >
+ <ChevronLeft className="size-4" aria-hidden="true" />
+ </Button>
+ <Button
+ aria-label="Go to next page"
+ variant="outline"
+ size="icon"
+ className="size-8"
+ onClick={() => table.nextPage()}
+ disabled={!table.getCanNextPage()}
+ >
+ <ChevronRight className="size-4" aria-hidden="true" />
+ </Button>
+ <Button
+ aria-label="Go to last page"
+ variant="outline"
+ size="icon"
+ className="hidden size-8 lg:flex"
+ onClick={() => table.setPageIndex(table.getPageCount() - 1)}
+ disabled={!table.getCanNextPage()}
+ >
+ <ChevronsRight className="size-4" aria-hidden="true" />
+ </Button>
+ </div>
+ </div>
+ </div>
+ )
+} \ No newline at end of file