Merge remote-tracking branch 'origin/main'

This commit is contained in:
charles-gauthereau
2024-11-11 16:17:58 +01:00
13 changed files with 568 additions and 128 deletions
+22 -111
View File
@@ -1,27 +1,23 @@
'use client'
import React, {useState} from 'react'
import {Card} from "@/components/ui/card"
import {cn} from "@/lib/utils";
import {
Pagination, PaginationContent,
PaginationEllipsis,
PaginationItem,
PaginationLink,
PaginationNext, PaginationPrevious
} from "@/components/ui/pagination";
import {PaginationNavigation} from "@/components/wrappers/pagination/pagination-navigation";
export type cardsWithPaginationProps = {
className?: string
data: Array<{}>;
cardItem: React.ComponentType;
cardsPerPage?: number
numberOfColumns?: number
maxVisiblePages?: number
}
export const CardsWithPagination = (props: cardsWithPaginationProps) => {
const {data, cardItem, cardsPerPage = 5, numberOfColumns = 1} = props
const {className, data, cardItem, cardsPerPage = 5, numberOfColumns = 1, maxVisiblePages = 3} = props
const CardItem = cardItem
@@ -32,119 +28,34 @@ export const CardsWithPagination = (props: cardsWithPaginationProps) => {
const indexOfFirstCard = indexOfLastCard - cardsPerPage
const currentCards = data.slice(indexOfFirstCard, indexOfLastCard)
const handlePageChange = (pageNumber: number) => {
const goToPage = (pageNumber: number) => {
setCurrentPage(pageNumber)
}
const renderPaginationItems = () => {
const items = []
const maxVisiblePages = 3
if (totalPages <= maxVisiblePages) {
for (let i = 1; i <= totalPages; i++) {
items.push(
<PaginationItem key={i}>
<PaginationLink
onClick={() => handlePageChange(i)}
isActive={currentPage === i}
>
{i}
</PaginationLink>
</PaginationItem>
)
}
} else {
if (currentPage <= 2) {
for (let i = 1; i <= maxVisiblePages; i++) {
items.push(
<PaginationItem key={i}>
<PaginationLink
onClick={() => handlePageChange(i)}
isActive={currentPage === i}
>
{i}
</PaginationLink>
</PaginationItem>
)
}
items.push(
<PaginationItem key="ellipsis1">
<PaginationEllipsis/>
</PaginationItem>
)
} else if (currentPage >= totalPages - 1) {
items.push(
<PaginationItem key="ellipsis2">
<PaginationEllipsis/>
</PaginationItem>
)
for (let i = totalPages - 2; i <= totalPages; i++) {
items.push(
<PaginationItem key={i}>
<PaginationLink
onClick={() => handlePageChange(i)}
isActive={currentPage === i}
>
{i}
</PaginationLink>
</PaginationItem>
)
}
} else {
items.push(
<PaginationItem key="ellipsis3">
<PaginationEllipsis/>
</PaginationItem>
)
for (let i = currentPage - 1; i <= currentPage + 1; i++) {
items.push(
<PaginationItem key={i}>
<PaginationLink
onClick={() => handlePageChange(i)}
isActive={currentPage === i}
>
{i}
</PaginationLink>
</PaginationItem>
)
}
items.push(
<PaginationItem key="ellipsis4">
<PaginationEllipsis/>
</PaginationItem>
)
}
}
return items
const goToPrevPage = () => {
goToPage(Math.max(1, currentPage - 1))
}
const goToNextPage = () => {
goToPage(Math.min(totalPages, currentPage + 1))
}
return (
<div className="">
<div className={cn("", className)}>
<div className={cn(`grid auto-rows-min gap-4 md:grid-cols-${numberOfColumns}`)}>
{currentCards.map((card, key) => (
<CardItem key={key} {...card}/>
))}
</div>
<Pagination className="mt-8">
<PaginationContent>
<PaginationItem>
<PaginationPrevious
onClick={() => handlePageChange(Math.max(1, currentPage - 1))}
aria-disabled={currentPage === 1}
tabIndex={currentPage === 1 ? -1 : 0}
/>
</PaginationItem>
{renderPaginationItems()}
<PaginationItem>
<PaginationNext
onClick={() => handlePageChange(Math.min(totalPages, currentPage + 1))}
aria-disabled={currentPage === totalPages}
tabIndex={currentPage === totalPages ? -1 : 0}
/>
</PaginationItem>
</PaginationContent>
</Pagination>
<PaginationNavigation
className="mt-8 justify-end"
totalPages={totalPages}
currentPage={currentPage}
goToPage={goToPage}
goToPrevPage={goToPrevPage}
goToNextPage={goToNextPage}
maxVisiblePages={maxVisiblePages}/>
</div>
)
}
@@ -0,0 +1,95 @@
import {PaginationEllipsis, PaginationItem, PaginationLink} from "@/components/ui/pagination";
export type paginationItemsProps = {
totalPages: number
currentPage: number
handlePageChange: (page: number) => void
maxVisiblePages?: number
}
export const PaginationIndexes = (props: paginationItemsProps) => {
const {totalPages, currentPage, handlePageChange, maxVisiblePages = 3} = props
const items = []
if (totalPages <= maxVisiblePages) {
for (let i = 1; i <= totalPages; i++) {
items.push(
<PaginationItem key={i}>
<PaginationLink
onClick={() => handlePageChange(i)}
isActive={currentPage === i}
>
{i}
</PaginationLink>
</PaginationItem>
)
}
} else {
if (currentPage <= 2) {
for (let i = 1; i <= maxVisiblePages; i++) {
items.push(
<PaginationItem key={i}>
<PaginationLink
onClick={() => handlePageChange(i)}
isActive={currentPage === i}
>
{i}
</PaginationLink>
</PaginationItem>
)
}
items.push(
<PaginationItem key="ellipsis1">
<PaginationEllipsis/>
</PaginationItem>
)
} else if (currentPage >= totalPages - 1) {
items.push(
<PaginationItem key="ellipsis2">
<PaginationEllipsis/>
</PaginationItem>
)
for (let i = totalPages - 2; i <= totalPages; i++) {
items.push(
<PaginationItem key={i}>
<PaginationLink
onClick={() => handlePageChange(i)}
isActive={currentPage === i}
>
{i}
</PaginationLink>
</PaginationItem>
)
}
} else {
items.push(
<PaginationItem key="ellipsis3">
<PaginationEllipsis/>
</PaginationItem>
)
for (let i = currentPage - 1; i <= currentPage + 1; i++) {
items.push(
<PaginationItem key={i}>
<PaginationLink
onClick={() => handlePageChange(i)}
isActive={currentPage === i}
>
{i}
</PaginationLink>
</PaginationItem>
)
}
items.push(
<PaginationItem key="ellipsis4">
<PaginationEllipsis/>
</PaginationItem>
)
}
}
return items
}
@@ -0,0 +1,41 @@
import {
Pagination,
PaginationContent,
PaginationItem,
PaginationNext,
PaginationPrevious
} from "@/components/ui/pagination";
import {PaginationIndexes} from "@/components/wrappers/pagination/pagination-indexes";
import {cn} from "@/lib/utils";
export type paginationNavigationProps = {
className?: string
totalPages: number
currentPage: number
goToPage: (page: number) => void
goToPrevPage: () => void
goToNextPage: () => void
maxVisiblePages?: number
}
export const PaginationNavigation = (props: paginationNavigationProps) => {
const {className, totalPages, currentPage, goToPage, goToPrevPage, goToNextPage, maxVisiblePages = 3} = props
return (
<Pagination className={cn("w-auto m-0", className)}>
<PaginationContent>
<PaginationItem>
<PaginationPrevious onClick={goToPrevPage}/>
</PaginationItem>
<PaginationIndexes totalPages={totalPages} currentPage={currentPage} handlePageChange={goToPage}
maxVisiblePages={maxVisiblePages}/>
<PaginationItem>
<PaginationNext onClick={goToNextPage}/>
</PaginationItem>
</PaginationContent>
</Pagination>
)
}
+20 -9
View File
@@ -1,22 +1,33 @@
import {Badge} from "@/components/ui/badge";
import {cn} from "@/lib/utils";
export type cardsWithPaginationProps = {
status: "waiting" | "ongoing" | "failed" | "success";
export type statusBadgeProps = {
status: "pending" | "processing" | "success" | "failed"
}
export const StatusBadge = ({status}: cardsWithPaginationProps) => {
export const StatusBadge = ({status}: statusBadgeProps) => {
let style = "";
switch (status) {
case 'waiting':
return <Badge variant="outline" className="text-yellow-500 border-2 border-yellow-500">waiting</Badge>
case 'ongoing':
return <Badge variant="outline" className="text-orange-500 border-2 border-orange-500">ongoing</Badge>
case 'pending':
style = "text-yellow-500 border-yellow-500"
break
case 'processing':
style = "text-orange-500 border-orange-500"
break
case 'failed':
return <Badge variant="outline" className="text-red-500 border-2 border-red-500">failed</Badge>
style = "text-red-500 border-red-500"
break
case 'success':
return <Badge variant="outline" className="text-green-500 border-2 border-green-500">success</Badge>
style = "text-green-500 border-green-500"
break
default:
throw Error
}
return (
<Badge variant="outline" className={cn("w-20 border-2 justify-center")}>{status}</Badge>
)
}
@@ -0,0 +1,38 @@
"use client"
import {useState} from "react";
import {
ColumnDef, getCoreRowModel, getPaginationRowModel, getSortedRowModel, SortingState, useReactTable
} from "@tanstack/react-table"
import {DataTable} from "@/components/wrappers/table/data-table";
import {TablePagination} from "@/components/wrappers/table/table-pagination";
interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[]
data: TData[]
}
export function DataTableWithPagination<TData, TValue>({columns, data}: DataTableProps<TData, TValue>) {
const [sorting, setSorting] = useState<SortingState>([])
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
onSortingChange: setSorting,
getSortedRowModel: getSortedRowModel(),
state: {
sorting,
},
})
return (
<div>
<DataTable table={table}/>
<TablePagination table={table}/>
</div>
)
}
@@ -0,0 +1,54 @@
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
import {flexRender} from "@tanstack/react-table";
export type dataTableProps = {
table: any
}
export const DataTable = ({table}: dataTableProps) => {
return (
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
)
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={table.columns.length} className="h-24 text-center">
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
)
}
@@ -0,0 +1,41 @@
import {PaginationNavigation} from "@/components/wrappers/pagination/pagination-navigation";
export type paginationNavigationProps = {
className?: string
table: any
maxVisiblePages?: number
}
export const TablePaginationNavigation = (props: paginationNavigationProps) => {
const {className, table, maxVisiblePages = 3} = props
const totalPages = table.getPageCount()
const currentPage = table.getState().pagination.pageIndex + 1
const goToPage = (page: number) => {
table.setPageIndex(page - 1)
}
const goToPrevPage = () => {
if (table.getCanPreviousPage()) table.previousPage()
}
const goToNextPage = () => {
if (table.getCanNextPage()) table.nextPage()
}
return (
<PaginationNavigation
className={className}
totalPages={totalPages}
currentPage={currentPage}
goToPage={goToPage}
goToPrevPage={goToPrevPage}
goToNextPage={goToNextPage}
maxVisiblePages={maxVisiblePages}/>
)
}
@@ -0,0 +1,38 @@
import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue} from "@/components/ui/select";
import {cn} from "@/lib/utils";
export type tablePaginationSizeProps = {
className?: string
table: any
pageSizeOptions?: number[]
}
export const TablePaginationSize = (props: tablePaginationSizeProps) => {
const {className, table, pageSizeOptions = [10, 20, 30, 40, 50]} = props
return (
<div className={cn("flex items-center space-x-2", className)}>
<p className="whitespace-nowrap text-sm font-medium">Rows per page</p>
<Select
value={`${table.getState().pagination.pageSize}`}
onValueChange={(value) => {
table.setPageSize(Number(value))
}}
>
<SelectTrigger className="h-8 w-[4.5rem]">
<SelectValue placeholder={table.getState().pagination.pageSize}/>
</SelectTrigger>
<SelectContent side="top">
{pageSizeOptions.map((pageSize) => (
<SelectItem key={pageSize} value={`${pageSize}`}>
{pageSize}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
)
}
@@ -0,0 +1,23 @@
"use client"
import {TablePaginationNavigation} from "@/components/wrappers/table/table-pagination-navigation";
import {TablePaginationSize} from "@/components/wrappers/table/table-pagination-size";
import {cn} from "@/lib/utils";
interface tablePaginationProps {
className?: string
table: any
maxVisiblePages?: number
}
export function TablePagination(props: tablePaginationProps) {
const {className, table, maxVisiblePages = 3} = props
return (
<div className={cn("flex justify-between mt-8", className)}>
<TablePaginationSize table={table}/>
<TablePaginationNavigation table={table} maxVisiblePages={maxVisiblePages}/>
</div>
)
}