ファイル
btrc-hub/frontend/src/pages/help/HelpDiffPage.tsx
T
2026-10-12 14:46:19 +09:00

82 行
2.6 KiB
TypeScript

import { useQuery } from '@tanstack/react-query'
import { Helmet } from 'react-helmet-async'
import { useParams, useSearchParams } from 'react-router-dom'
import PrefetchLink from '@/components/PrefetchLink'
import PageTitle from '@/components/common/PageTitle'
import MainArea from '@/components/layout/MainArea'
import { SITE_TITLE } from '@/config'
import { getHelpDiff } from '@/lib/help'
import { helpKeys } from '@/lib/queryKeys'
import { cn } from '@/lib/utils'
import NotFound from '@/pages/NotFound'
import type { FC } from 'react'
const markers = { added: '+ ', removed: '- ', unchanged: ' ' }
const HelpDiffPage: FC = () => {
const { identifier = '' } = useParams ()
const [searchParams] = useSearchParams ()
const from = searchParams.get ('from') ?? ''
const to = searchParams.get ('to') ?? ''
const validParams = Boolean (identifier && from && to)
&& searchParams.getAll ('from').length === 1
&& searchParams.getAll ('to').length === 1
const { data: diff, isLoading, isError } = useQuery ({
enabled: validParams,
queryKey: helpKeys.diff (identifier, 'ja', from, to),
queryFn: () => getHelpDiff (identifier, 'ja', from, to),
staleTime: Infinity })
if (!(validParams) || isError || (!(isLoading) && diff == null))
return <NotFound/>
const title = `${ diff?.to.title ?? identifier } (${ from } → ${ to })`
const path = `/help/${ encodeURIComponent (identifier) }`
return (
<MainArea>
<Helmet>
<title>{`ヘルプ 差分: ${ title } | ${ SITE_TITLE }`}</title>
</Helmet>
<PageTitle>{title}</PageTitle>
{diff
? (
<>
<div className="flex flex-wrap items-center gap-3">
<PrefetchLink to={`${ path }?edition=${ encodeURIComponent (from) }`}>
{diff.from.title} ({from})
</PrefetchLink>
<span>→</span>
<PrefetchLink to={`${ path }?edition=${ encodeURIComponent (to) }`}>
{diff.to.title} ({to})
</PrefetchLink>
</div>
<pre className="mt-4 overflow-x-auto whitespace-pre">
<code>
{diff.lines.map ((line, index) => {
const colour = cn (
'block text-gray-900 dark:text-gray-100',
line.type === 'added' && 'bg-green-200 dark:bg-green-800',
line.type === 'added' && 'text-green-950 dark:text-green-50',
line.type === 'removed' && 'bg-red-200 dark:bg-red-800',
line.type === 'removed' && 'text-red-950 dark:text-red-50')
return (
<span key={index} className={colour}>
{markers[line.type]}{line.content.replace (/\r?\n$/, '')}
</span>)
})}
</code>
</pre>
</>)
: <div>Loading...</div>}
</MainArea>)
}
export default HelpDiffPage