1- import { BootstrapTable , TableHeaderColumn } from 'react-bootstrap-table' ;
1+ import {
2+ BootstrapTable ,
3+ SortOrder ,
4+ TableHeaderColumn ,
5+ } from 'react-bootstrap-table' ;
26import React , { useState } from 'react' ;
37import { Button } from 'reactstrap' ;
48import dataFormat from 'dateformat' ;
@@ -23,6 +27,7 @@ import {
2327} from '../../interfaces/MergedProblem' ;
2428import { ProblemDetailModal } from '../../components/ProblemDetailModal' ;
2529import { useNavigate } from 'react-router' ;
30+ import { useSearchParams } from 'react-router-dom' ;
2631
2732export type FilterState = 'All' | 'Only Trying' | 'Only AC' ;
2833
@@ -38,6 +43,32 @@ interface Props {
3843 problemLinkColorMode : ProblemLinkColorMode ;
3944}
4045
46+ const SORT_NAMES = [
47+ 'Date' ,
48+ 'Title' ,
49+ 'Level' ,
50+ 'Contest' ,
51+ 'SolveDate' ,
52+ 'FirstSolveDate' ,
53+ 'Tags' ,
54+ 'Difficulty' ,
55+ 'FastestRankingProblem' ,
56+ 'ShortestRankingProblem' ,
57+ 'PureShortestRankingProblem' ,
58+ 'ProblemType' ,
59+ 'No' ,
60+ 'ProblemId' ,
61+ ] as const ;
62+ type SortName = typeof SORT_NAMES [ number ] ;
63+ const sanitizeColumnName = ( sortName : string | null ) : SortName => {
64+ if ( SORT_NAMES . includes ( sortName as SortName ) ) return sortName as SortName ;
65+ else return 'Date' ;
66+ } ;
67+ const sanitizeSortOrder = ( sortOrder : string | null ) : SortOrder => {
68+ if ( sortOrder == 'asc' || sortOrder == 'desc' ) return sortOrder ;
69+ else return 'desc' ;
70+ } ;
71+
4172export const ListTable : React . FC < Props > = ( props ) => {
4273 const {
4374 rankingMergedProblems,
@@ -59,6 +90,8 @@ export const ListTable: React.FC<Props> = (props) => {
5990 rankingMergedProblem : undefined ,
6091 } ) ;
6192
93+ const [ searchParams , setSearchParams ] = useSearchParams ( ) ;
94+
6295 const columns = [
6396 {
6497 header : 'Date' ,
@@ -335,7 +368,8 @@ export const ListTable: React.FC<Props> = (props) => {
335368 } }
336369 options = { {
337370 paginationPosition : 'top' ,
338- sizePerPage : 20 ,
371+ page : Number ( searchParams . get ( 'page' ) ?? 1 ) ,
372+ sizePerPage : Number ( searchParams . get ( 'sizePerPage' ) ?? 20 ) ,
339373 sizePerPageList : [
340374 {
341375 text : '20' ,
@@ -358,11 +392,40 @@ export const ListTable: React.FC<Props> = (props) => {
358392 value : rankingMergedProblems . length ,
359393 } ,
360394 ] ,
395+ onSizePerPageList : function _onSizePerPageList ( sizePerPage : number ) {
396+ searchParams . set ( 'page' , `1` ) ;
397+ searchParams . set ( 'sizePerPage' , `${ sizePerPage } ` ) ;
398+ setSearchParams ( searchParams ) ;
399+ } ,
400+ onPageChange : function _onPageChange (
401+ page : number ,
402+ sizePerPage : number
403+ ) {
404+ searchParams . set ( 'page' , `${ page } ` ) ;
405+ searchParams . set ( 'sizePerPage' , `${ sizePerPage } ` ) ;
406+ setSearchParams ( searchParams ) ;
407+ } ,
361408 paginationPanel : function _paginationPanel (
362409 paginationPanelProps : ListPaginationPanelProps
363410 ) {
364411 return < ListPaginationPanel { ...paginationPanelProps } /> ;
365412 } ,
413+ defaultSortName : sanitizeColumnName ( searchParams . get ( 'sortName' ) ) ,
414+ defaultSortOrder : sanitizeSortOrder ( searchParams . get ( 'sortOrder' ) ) ,
415+ onSortChange : function _onSortChange (
416+ sortName : string | number | symbol ,
417+ sortOrder : SortOrder
418+ ) {
419+ searchParams . set ( 'sortName' , sortName as string ) ;
420+ searchParams . set ( 'sortOrder' , sortOrder ) ;
421+ setSearchParams ( searchParams ) ;
422+ } ,
423+ defaultSearch : searchParams . get ( 'search' ) ?? '' ,
424+ onSearchChange : function _onSearchChange ( searchText : string ) {
425+ searchParams . set ( 'page' , `1` ) ;
426+ searchParams . set ( 'search' , searchText ) ;
427+ setSearchParams ( searchParams , { replace : true } ) ;
428+ } ,
366429 } }
367430 >
368431 { columns . map ( ( c ) => (
0 commit comments