feat: 耕作履歴ページ作成(#112) (#177)
#112 現在ページの表示を太く #112 完了 Co-authored-by: miteruzo <miteruzo@naver.com> Reviewed-on: #177
This commit was merged in pull request #177.
This commit is contained in:
@@ -30,6 +30,7 @@ export default (({ user }: Props) => {
|
||||
{ name: '広場', to: '/posts', subMenu: [
|
||||
{ name: '一覧', to: '/posts' },
|
||||
{ name: '投稿追加', to: '/posts/new' },
|
||||
{ name: '耕作履歴', to: '/posts/changes' },
|
||||
{ name: 'ヘルプ', to: '/wiki/ヘルプ:広場' }] },
|
||||
{ name: 'タグ', to: '/tags', subMenu: [
|
||||
{ name: 'タグ一覧', to: '/tags', visible: false },
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import { Link, useLocation } from 'react-router-dom'
|
||||
|
||||
import type { FC } from 'react'
|
||||
|
||||
type Props = { page: number
|
||||
totalPages: number
|
||||
siblingCount?: number }
|
||||
|
||||
|
||||
const range = (start: number, end: number): number[] =>
|
||||
[...Array (end - start + 1).keys ()].map (i => start + i)
|
||||
|
||||
|
||||
const getPages = (
|
||||
page: number,
|
||||
total: number,
|
||||
siblingCount: number,
|
||||
): (number | '…')[] => {
|
||||
if (total <= 1)
|
||||
return [1]
|
||||
|
||||
const first = 1
|
||||
const last = total
|
||||
|
||||
const left = Math.max (page - siblingCount, first)
|
||||
const right = Math.min (page + siblingCount, last)
|
||||
|
||||
const pages: (number | '…')[] = []
|
||||
|
||||
pages.push (first)
|
||||
|
||||
if (left > first + 1)
|
||||
pages.push ('…')
|
||||
|
||||
const midStart = Math.max (left, first + 1)
|
||||
const midEnd = Math.min (right, last - 1)
|
||||
pages.push (...range (midStart, midEnd))
|
||||
|
||||
if (right < last - 1)
|
||||
pages.push ('…')
|
||||
|
||||
if (last !== first)
|
||||
pages.push (last)
|
||||
|
||||
return pages.filter ((v, i, arr) => i === 0 || v !== arr[i - 1])
|
||||
}
|
||||
|
||||
|
||||
export default (({ page, totalPages, siblingCount = 4 }) => {
|
||||
const location = useLocation ()
|
||||
|
||||
const buildTo = (p: number) => {
|
||||
const qs = new URLSearchParams (location.search)
|
||||
qs.set ('page', String (p))
|
||||
return `${ location.pathname }?${ qs.toString () }`
|
||||
}
|
||||
|
||||
const pages = getPages (page, totalPages, siblingCount)
|
||||
|
||||
return (
|
||||
<nav className="mt-4 flex justify-center" aria-label="Pagination">
|
||||
<div className="flex items-center gap-2">
|
||||
{(page > 1)
|
||||
? <Link to={buildTo (page - 1)} aria-label="前のページ"><</Link>
|
||||
: <span aria-hidden><</span>}
|
||||
|
||||
{pages.map ((p, idx) => (
|
||||
(p === '…')
|
||||
? <span key={`dots-${ idx }`}>…</span>
|
||||
: ((p === page)
|
||||
? <span key={p} className="font-bold" aria-current="page">{p}</span>
|
||||
: <Link key={p} to={buildTo (p)}>{p}</Link>)))}
|
||||
|
||||
{(page < totalPages)
|
||||
? <Link to={buildTo (page + 1)} aria-label="次のページ">></Link>
|
||||
: <span aria-hidden>></span>}
|
||||
</div>
|
||||
</nav>)
|
||||
}) satisfies FC<Props>
|
||||
Reference in New Issue
Block a user