'use client' import React from 'react' import ReactDOM from 'react-dom/client' import Link from 'next/link' import { keepPreviousData, QueryClient, useQuery, } from '@tanstack/react-query' import { format } from 'date-fns' import Image from "next/legacy/image" import { PaginationState, useReactTable, getCoreRowModel, ColumnDef, flexRender, } from '@tanstack/react-table' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faSpinner } from '@fortawesome/free-solid-svg-icons' import { fetchStreamData } from '@/app/lib/streams' import { IStream } from '@futureporn/types' const queryClient = new QueryClient() function getStatusClass(value: string) { switch (value) { case 'issue': return 'is-warning'; case 'missing': return 'is-danger'; case 'good': return 'is-success'; default: return ''; } } export default function StreamsTable() { const rerender = React.useReducer(() => ({}), {})[1] // image & name // title // platform // date & time // archiveStatus const columns = React.useMemo[]>( () => [ { header: 'VTuber', accessorFn: d => ({ displayName: d.attributes.vtuber.data?.attributes?.displayName, image: d.attributes.vtuber.data?.attributes.image, imageBlur: d.attributes.vtuber.data?.attributes.imageBlur }), cell: info => { const { displayName, image, imageBlur } = info.getValue<{ displayName: string, image: string, imageBlur: string }>(); return ( <>
{displayName}
{displayName}
) } }, { header: 'Date', accessorFn: d => format(new Date(d.attributes.date2), 'yyyy-MM-dd HH:mm'), // accessorFn: d => new Date(d.attributes.date2), sortingFn: 'datetime', sortDescFirst: true, cell: info => ({info.getValue() as string}) }, { header: 'Platform', accessorFn: d => [ (d.attributes.isChaturbateStream && 'CB'), (d.attributes.isFanslyStream && 'Fansly') ].filter(Boolean).join(', ') || '???' }, { header: 'Status', accessorFn: d => { if (!d.attributes.archiveStatus) return 'missing'; return d.attributes.archiveStatus } }, // { // header: 'Name', // footer: props => props.column.id, // columns: [ // { // accessorKey: 'firstName', // cell: info => info.getValue(), // footer: props => props.column.id, // }, // { // accessorFn: row => row.lastName, // id: 'lastName', // cell: info => info.getValue(), // header: () => Last Name, // footer: props => props.column.id, // }, // ], // }, ], [] ) const [pagination, setPagination] = React.useState({ pageIndex: 0, pageSize: 50, }) const { data, error, isPending } = useQuery({ queryKey: ['streams', pagination.pageIndex, pagination.pageSize], queryFn: () => fetchStreamData(pagination), placeholderData: keepPreviousData, // don't have 0 rows flash while changing pages/loading next page, staleTime: 1000, }, queryClient) const defaultData = React.useMemo(() => [], []) const table = useReactTable({ data: data?.rows ?? defaultData, columns, // pageCount: dataQuery.data?.pageCount ?? -1, //you can now pass in `rowCount` instead of pageCount and `pageCount` will be calculated internally (new in v8.13.0) rowCount: data?.rowCount, // new in v8.13.0 - alternatively, just pass in `pageCount` directly state: { pagination, }, onPaginationChange: setPagination, getCoreRowModel: getCoreRowModel(), manualPagination: true, //we're doing manual "server-side" pagination // getPaginationRowModel: getPaginationRowModel(), // If only doing manual pagination, you don't need this debugTable: true, }) return (
{isPending && } {!isPending && <> {table.getHeaderGroups().map(headerGroup => ( {headerGroup.headers.map(header => { return ( ) })} ))} {table.getRowModel().rows.map(row => { return ( {row.getVisibleCells().map(cell => { return ( ) })} ) })}
{header.isPlaceholder ? null : (
{flexRender( header.column.columnDef.header, header.getContext() )}
)}
{flexRender( cell.column.columnDef.cell, cell.getContext() )}
Page {table.getState().pagination.pageIndex + 1} of{' '} {table.getPageCount().toLocaleString()}
{/* second row with page number input and pages-per-screen select */}
Go to page:
{ const page = e.target.value ? Number(e.target.value) - 1 : 0 table.setPageIndex(page) }} className="input" />
}
) }