| @@ -29,14 +29,17 @@ export const fetchPost = async (id: string): Promise<Post> => await apiGet (`/po | |||||
| export const fetchPostChanges = async ( | export const fetchPostChanges = async ( | ||||
| { id, page, limit }: { | |||||
| { id, tag, page, limit }: { | |||||
| id?: string | id?: string | ||||
| tag?: string | |||||
| page: number | page: number | ||||
| limit: number }, | limit: number }, | ||||
| ): Promise<{ | ): Promise<{ | ||||
| changes: PostTagChange[] | changes: PostTagChange[] | ||||
| count: number }> => | count: number }> => | ||||
| await apiGet ('/posts/changes', { params: { ...(id && { id }), page, limit } }) | |||||
| await apiGet ('/posts/changes', { params: { ...(id && { id }), | |||||
| ...(tag && { tag }), | |||||
| page, limit } }) | |||||
| export const toggleViewedFlg = async (id: string, viewed: boolean): Promise<void> => { | export const toggleViewedFlg = async (id: string, viewed: boolean): Promise<void> => { | ||||
| @@ -3,7 +3,7 @@ import { match } from 'path-to-regexp' | |||||
| import { fetchPost, fetchPosts, fetchPostChanges } from '@/lib/posts' | import { fetchPost, fetchPosts, fetchPostChanges } from '@/lib/posts' | ||||
| import { postsKeys, tagsKeys, wikiKeys } from '@/lib/queryKeys' | import { postsKeys, tagsKeys, wikiKeys } from '@/lib/queryKeys' | ||||
| import { fetchTagByName, fetchTags } from '@/lib/tags' | |||||
| import { fetchTagByName, fetchTag, fetchTags } from '@/lib/tags' | |||||
| import { fetchWikiPage, | import { fetchWikiPage, | ||||
| fetchWikiPageByTitle, | fetchWikiPageByTitle, | ||||
| fetchWikiPages } from '@/lib/wiki' | fetchWikiPages } from '@/lib/wiki' | ||||
| @@ -122,12 +122,24 @@ const prefetchPostShow: Prefetcher = async (qc, url) => { | |||||
| const prefetchPostChanges: Prefetcher = async (qc, url) => { | const prefetchPostChanges: Prefetcher = async (qc, url) => { | ||||
| const id = url.searchParams.get ('id') | const id = url.searchParams.get ('id') | ||||
| const tag = url.searchParams.get ('tag') | |||||
| const page = Number (url.searchParams.get ('page') || 1) | const page = Number (url.searchParams.get ('page') || 1) | ||||
| const limit = Number (url.searchParams.get ('limit') || 20) | const limit = Number (url.searchParams.get ('limit') || 20) | ||||
| if (tag) | |||||
| { | |||||
| await qc.prefetchQuery ({ | |||||
| queryKey: tagsKeys.show (tag), | |||||
| queryFn: () => fetchTag (tag) }) | |||||
| } | |||||
| await qc.prefetchQuery ({ | await qc.prefetchQuery ({ | ||||
| queryKey: postsKeys.changes ({ ...(id && { id }), page, limit }), | |||||
| queryFn: () => fetchPostChanges ({ ...(id && { id }), page, limit }) }) | |||||
| queryKey: postsKeys.changes ({ ...(id && { id }), | |||||
| ...(tag && { tag }), | |||||
| page, limit }), | |||||
| queryFn: () => fetchPostChanges ({ ...(id && { id }), | |||||
| ...(tag && { tag }), | |||||
| page, limit }) }) | |||||
| } | } | ||||
| @@ -5,7 +5,7 @@ export const postsKeys = { | |||||
| index: (p: FetchPostsParams) => ['posts', 'index', p] as const, | index: (p: FetchPostsParams) => ['posts', 'index', p] as const, | ||||
| show: (id: string) => ['posts', id] as const, | show: (id: string) => ['posts', id] as const, | ||||
| related: (id: string) => ['related', id] as const, | related: (id: string) => ['related', id] as const, | ||||
| changes: (p: { id?: string; page: number; limit: number }) => | |||||
| changes: (p: { id?: string; tag?: string; page: number; limit: number }) => | |||||
| ['posts', 'changes', p] as const } | ['posts', 'changes', p] as const } | ||||
| export const tagsKeys = { | export const tagsKeys = { | ||||
| @@ -23,6 +23,18 @@ export const fetchTags = async ( | |||||
| ...(order && { order }) } }) | ...(order && { order }) } }) | ||||
| export const fetchTag = async (id: string): Promise<Tag | null> => { | |||||
| try | |||||
| { | |||||
| return await apiGet (`/tags/${ id }`) | |||||
| } | |||||
| catch | |||||
| { | |||||
| return null | |||||
| } | |||||
| } | |||||
| export const fetchTagByName = async (name: string): Promise<Tag | null> => { | export const fetchTagByName = async (name: string): Promise<Tag | null> => { | ||||
| try | try | ||||
| { | { | ||||
| @@ -11,7 +11,8 @@ import Pagination from '@/components/common/Pagination' | |||||
| import MainArea from '@/components/layout/MainArea' | import MainArea from '@/components/layout/MainArea' | ||||
| import { SITE_TITLE } from '@/config' | import { SITE_TITLE } from '@/config' | ||||
| import { fetchPostChanges } from '@/lib/posts' | import { fetchPostChanges } from '@/lib/posts' | ||||
| import { postsKeys } from '@/lib/queryKeys' | |||||
| import { postsKeys, tagsKeys } from '@/lib/queryKeys' | |||||
| import { fetchTag } from '@/lib/tags' | |||||
| import { cn, dateString } from '@/lib/utils' | import { cn, dateString } from '@/lib/utils' | ||||
| import type { FC } from 'react' | import type { FC } from 'react' | ||||
| @@ -21,15 +22,26 @@ export default (() => { | |||||
| const location = useLocation () | const location = useLocation () | ||||
| const query = new URLSearchParams (location.search) | const query = new URLSearchParams (location.search) | ||||
| const id = query.get ('id') | const id = query.get ('id') | ||||
| const tagId = query.get ('tag') | |||||
| const page = Number (query.get ('page') ?? 1) | const page = Number (query.get ('page') ?? 1) | ||||
| const limit = Number (query.get ('limit') ?? 20) | const limit = Number (query.get ('limit') ?? 20) | ||||
| // 投稿列の結合で使用 | // 投稿列の結合で使用 | ||||
| let rowsCnt: number | let rowsCnt: number | ||||
| const { data: tag } = | |||||
| tagId | |||||
| ? useQuery ({ queryKey: tagsKeys.show (tagId), | |||||
| queryFn: () => fetchTag (tagId) }) | |||||
| : { data: null } | |||||
| const { data, isLoading: loading } = useQuery ({ | const { data, isLoading: loading } = useQuery ({ | ||||
| queryKey: postsKeys.changes ({ ...(id && { id }), page, limit }), | |||||
| queryFn: () => fetchPostChanges ({ ...(id && { id }), page, limit }) }) | |||||
| queryKey: postsKeys.changes ({ ...(id && { id }), | |||||
| ...(tagId && { tag: tagId }), | |||||
| page, limit }), | |||||
| queryFn: () => fetchPostChanges ({ ...(id && { id }), | |||||
| ...(tagId && { tag: tagId }), | |||||
| page, limit }) }) | |||||
| const changes = data?.changes ?? [] | const changes = data?.changes ?? [] | ||||
| const totalPages = data ? Math.ceil (data.count / limit) : 0 | const totalPages = data ? Math.ceil (data.count / limit) : 0 | ||||
| @@ -48,6 +60,7 @@ export default (() => { | |||||
| <PageTitle> | <PageTitle> | ||||
| 耕作履歴 | 耕作履歴 | ||||
| {id && <>: 投稿 {<PrefetchLink to={`/posts/${ id }`}>#{id}</PrefetchLink>}</>} | {id && <>: 投稿 {<PrefetchLink to={`/posts/${ id }`}>#{id}</PrefetchLink>}</>} | ||||
| {tag && <>(<TagLink tag={tag} withWiki={false} withCount={false}/>)</>} | |||||
| </PageTitle> | </PageTitle> | ||||
| {loading ? 'Loading...' : ( | {loading ? 'Loading...' : ( | ||||
| @@ -3,6 +3,7 @@ import { useEffect, useMemo, useState } from 'react' | |||||
| import { Helmet } from 'react-helmet-async' | import { Helmet } from 'react-helmet-async' | ||||
| import { useLocation, useNavigate } from 'react-router-dom' | import { useLocation, useNavigate } from 'react-router-dom' | ||||
| import PrefetchLink from '@/components/PrefetchLink' | |||||
| import SortHeader from '@/components/SortHeader' | import SortHeader from '@/components/SortHeader' | ||||
| import TagLink from '@/components/TagLink' | import TagLink from '@/components/TagLink' | ||||
| import DateTimeField from '@/components/common/DateTimeField' | import DateTimeField from '@/components/common/DateTimeField' | ||||
| @@ -211,6 +212,7 @@ export default (() => { | |||||
| <col className="w-16"/> | <col className="w-16"/> | ||||
| <col className="w-44"/> | <col className="w-44"/> | ||||
| <col className="w-44"/> | <col className="w-44"/> | ||||
| <col className="w-16"/> | |||||
| </colgroup> | </colgroup> | ||||
| <thead className="border-b-2 border-black dark:border-white"> | <thead className="border-b-2 border-black dark:border-white"> | ||||
| @@ -250,6 +252,7 @@ export default (() => { | |||||
| currentOrder={order} | currentOrder={order} | ||||
| defaultDirection={defaultDirection}/> | defaultDirection={defaultDirection}/> | ||||
| </th> | </th> | ||||
| <th className="p-2 text-left whitespace-nowrap"/> | |||||
| </tr> | </tr> | ||||
| </thead> | </thead> | ||||
| @@ -263,6 +266,11 @@ export default (() => { | |||||
| <td className="p-2 text-right">{row.postCount}</td> | <td className="p-2 text-right">{row.postCount}</td> | ||||
| <td className="p-2">{dateString (row.createdAt)}</td> | <td className="p-2">{dateString (row.createdAt)}</td> | ||||
| <td className="p-2">{dateString (row.updatedAt)}</td> | <td className="p-2">{dateString (row.updatedAt)}</td> | ||||
| <td className="p-2"> | |||||
| <PrefetchLink to={`/posts/changes?tag=${ row.id }`}> | |||||
| 耕作履歴 | |||||
| </PrefetchLink> | |||||
| </td> | |||||
| </tr>))} | </tr>))} | ||||
| </tbody> | </tbody> | ||||
| </table> | </table> | ||||