diff --git a/frontend/src/lib/prefetchers.ts b/frontend/src/lib/prefetchers.ts index 956f250..a0380e0 100644 --- a/frontend/src/lib/prefetchers.ts +++ b/frontend/src/lib/prefetchers.ts @@ -68,13 +68,32 @@ const prefetchWikiPageShow: Prefetcher = async (qc, url) => { const prefetchPostsIndex: Prefetcher = async (qc, url) => { const tags = url.searchParams.get ('tags') ?? '' - const m = url.searchParams.get ('match') === 'any' ? 'any' : 'all' + const qURL = url.searchParams.get ('url') + const title = url.searchParams.get ('title') + const originalCreatedFrom = url.searchParams.get ('original_created_from') + const originalCreatedTo = url.searchParams.get ('original_created_to') + const createdFrom = url.searchParams.get ('created_from') + const createdTo = url.searchParams.get ('created_to') + const updatedFrom = url.searchParams.get ('updated_from') + const updatedTo = url.searchParams.get ('updated_to') + const m: 'all' | 'any' = url.searchParams.get ('match') === 'any' ? 'any' : 'all' const page = Number (url.searchParams.get ('page') || 1) const limit = Number (url.searchParams.get ('limit') || 20) + const keys = { + tags, match: m, page, limit, + ...(qURL && { url: qURL }), + ...(title && { title }), + ...(originalCreatedFrom && { original_created_from: originalCreatedFrom }), + ...(originalCreatedTo && { original_created_to: originalCreatedTo }), + ...(createdFrom && { created_from: createdFrom }), + ...(createdTo && { created_to: createdTo }), + ...(updatedFrom && { updated_from: updatedFrom }), + ...(updatedTo && { updated_to: updatedTo }) } + await qc.prefetchQuery ({ - queryKey: postsKeys.index ({ tags, match: m, page, limit }), - queryFn: () => fetchPosts ({ tags, match: m, page, limit }) }) + queryKey: postsKeys.index (keys), + queryFn: () => fetchPosts (keys) }) } @@ -103,7 +122,8 @@ const prefetchPostChanges: Prefetcher = async (qc, url) => { export const routePrefetchers: { test: (u: URL) => boolean; run: Prefetcher }[] = [ - { test: u => u.pathname === '/' || u.pathname === '/posts', run: prefetchPostsIndex }, + { test: u => ['/', '/posts', '/posts/search'].includes (u.pathname), + run: prefetchPostsIndex }, { test: u => (!(['/posts/new', '/posts/changes', '/posts/search'].includes (u.pathname)) && Boolean (mPost (u.pathname))), run: prefetchPostShow }, @@ -119,5 +139,6 @@ export const prefetchForURL = async (qc: QueryClient, urlLike: string): Promise< const r = routePrefetchers.find (x => x.test (u)) if (!(r)) return + await r.run (qc, u) } diff --git a/frontend/src/pages/posts/PostSearchPage.tsx b/frontend/src/pages/posts/PostSearchPage.tsx index 41ca095..c8b56fc 100644 --- a/frontend/src/pages/posts/PostSearchPage.tsx +++ b/frontend/src/pages/posts/PostSearchPage.tsx @@ -1,6 +1,7 @@ +import { useQuery } from '@tanstack/react-query' import { useState } from 'react' import { Helmet } from 'react-helmet-async' -import { useLocation } from 'react-router-dom' +import { useLocation, useNavigate } from 'react-router-dom' import PrefetchLink from '@/components/PrefetchLink' import TagLink from '@/components/TagLink' @@ -11,42 +12,56 @@ import Pagination from '@/components/common/Pagination' import MainArea from '@/components/layout/MainArea' import { SITE_TITLE } from '@/config' import { fetchPosts } from '@/lib/posts' +import { postsKeys } from '@/lib/queryKeys' import type { FC, FormEvent } from 'react' -import type { Post } from '@/types' - export default (() => { - const [createdFrom, setCreatedFrom] = useState () - const [createdTo, setCreatedTo] = useState () - const [matchType, setMatchType] = useState<'all' | 'any'> ('all') - const [originalCreatedFrom, setOriginalCreatedFrom] = useState () - const [originalCreatedTo, setOriginalCreatedTo] = useState () - const [tagsStr, setTagsStr] = useState ('') - const [title, setTitle] = useState ('') - const [updatedFrom, setUpdatedFrom] = useState () - const [updatedTo, setUpdatedTo] = useState () - const [url, setURL] = useState ('') - const [results, setResults] = useState ([]) - const [totalPages, setTotalPages] = useState (0) + const navigate = useNavigate () const location = useLocation () const query = new URLSearchParams (location.search) const page = Number (query.get ('page') ?? 1) const limit = Number (query.get ('limit') ?? 20) + const [createdFrom, setCreatedFrom] = + useState (query.get ('created_from')) + const [createdTo, setCreatedTo] = + useState (query.get ('created_to')) + const [matchType, setMatchType] = + useState<'all' | 'any'> ((query.get ('match') as 'all' | 'any' | null) ?? 'all') + const [originalCreatedFrom, setOriginalCreatedFrom] = + useState (query.get ('original_created_from')) + const [originalCreatedTo, setOriginalCreatedTo] = + useState (query.get ('original_created_to')) + const [tagsStr, setTagsStr] = useState (query.get ('tags') ?? '') + const [title, setTitle] = useState (query.get ('title') ?? '') + const [updatedFrom, setUpdatedFrom] = + useState (query.get ('updated_from')) + const [updatedTo, setUpdatedTo] = + useState (query.get ('updated_to')) + const [url, setURL] = useState (query.get ('url') ?? '') + + const keys = { + tags: tagsStr, match: matchType, page, limit, + ...(url && { url }), + ...(title && { title }), + ...(originalCreatedFrom && { original_created_from: originalCreatedFrom }), + ...(originalCreatedTo && { original_created_to: originalCreatedTo }), + ...(createdFrom && { created_from: createdFrom }), + ...(createdTo && { created_to: createdTo }), + ...(updatedFrom && { updated_from: updatedFrom }), + ...(updatedTo && { updated_to: updatedTo }) } + const { data, /* isLoading: loading */ } = useQuery ({ + queryKey: postsKeys.index (keys), queryFn: () => fetchPosts (keys) }) + const results = data?.posts ?? [] + const totalPages = data ? Math.ceil (data.count / limit) : 0 + const search = async () => { - const tags = tagsStr.split (' ').filter (e => e !== '') - const data = await fetchPosts ({ - url, title, tags: tags.join (' '), match: matchType, - created_from: createdFrom, created_to: createdTo, - updated_from: updatedFrom, updated_to: updatedTo, - original_created_from: originalCreatedFrom, - original_created_to: originalCreatedTo, - page, limit }) - setResults (data.posts) - setTotalPages (data ? Math.ceil (data.count / limit) : 0) + const qs = new URLSearchParams (location.search) + qs.set ('page', String ('1')) + navigate (`${ location.pathname }?${ qs.toString () }`) } const handleSearch = (e: FormEvent) => { @@ -118,11 +133,11 @@ export default (() => { setOriginalCreatedFrom (isoUTC ?? undefined)}/> + onChange={setOriginalCreatedFrom}/> setOriginalCreatedTo (isoUTC ?? undefined)}/> + onChange={setOriginalCreatedTo}/> {/* 投稿日時 */} @@ -130,11 +145,11 @@ export default (() => { setCreatedFrom (isoUTC ?? undefined)}/> + onChange={setCreatedFrom}/> setCreatedTo (isoUTC ?? undefined)}/> + onChange={setCreatedTo}/> {/* 更新日時 */} @@ -142,11 +157,11 @@ export default (() => { setUpdatedFrom (isoUTC ?? undefined)}/> + onChange={setUpdatedFrom}/> setUpdatedTo (isoUTC ?? undefined)}/> + onChange={setUpdatedTo}/> {/* 検索 */}