From a088503272f1d73b12187ec25971bfc033f4e430 Mon Sep 17 00:00:00 2001 From: miteruzo Date: Sun, 1 Mar 2026 13:48:47 +0900 Subject: [PATCH] #206 --- frontend/src/consts.ts | 35 +++++++++++++------ frontend/src/lib/posts.ts | 37 ++++++++++----------- frontend/src/lib/queryKeys.ts | 15 ++------- frontend/src/pages/posts/PostSearchPage.tsx | 21 +++++++----- frontend/src/types.ts | 24 ++++++++++++- 5 files changed, 80 insertions(+), 52 deletions(-) diff --git a/frontend/src/consts.ts b/frontend/src/consts.ts index 214a19b..13968d2 100644 --- a/frontend/src/consts.ts +++ b/frontend/src/consts.ts @@ -3,13 +3,23 @@ import type { Category } from 'types' export const LIGHT_COLOUR_SHADE = 800 export const DARK_COLOUR_SHADE = 300 -export const CATEGORIES = ['deerjikist', - 'meme', - 'character', - 'general', - 'material', - 'meta', - 'nico'] as const +export const CATEGORIES = [ + 'deerjikist', + 'meme', + 'character', + 'general', + 'material', + 'meta', + 'nico', + ] as const + +export const FETCH_POSTS_ORDER_FIELDS = [ + 'title', + 'url', + 'original_created_at', + 'created_at', + 'updated_at', + ] as const export const TAG_COLOUR = { deerjikist: 'rose', @@ -18,10 +28,13 @@ export const TAG_COLOUR = { general: 'cyan', material: 'orange', meta: 'yellow', - nico: 'gray' } as const satisfies Record + nico: 'gray', + } as const satisfies Record export const USER_ROLES = ['admin', 'member', 'guest'] as const -export const ViewFlagBehavior = { OnShowedDetail: 1, - OnClickedLink: 2, - NotAuto: 3 } as const +export const ViewFlagBehavior = { + OnShowedDetail: 1, + OnClickedLink: 2, + NotAuto: 3, + } as const diff --git a/frontend/src/lib/posts.ts b/frontend/src/lib/posts.ts index 181945e..04ec1ba 100644 --- a/frontend/src/lib/posts.ts +++ b/frontend/src/lib/posts.ts @@ -1,31 +1,28 @@ import { apiDelete, apiGet, apiPost } from '@/lib/api' -import type { Post, PostTagChange } from '@/types' +import type { FetchPostsParams, Post, PostTagChange } from '@/types' export const fetchPosts = async ( - { url, title, tags, match, created_from, created_to, updated_from, - updated_to, original_created_from, original_created_to, page, limit }: { - url?: string - title?: string - tags?: string - match?: 'all' | 'any' - created_from?: string - created_to?: string - updated_from?: string - updated_to?: string - original_created_from?: string - original_created_to?: string - page?: number - limit?: number }, + { url, title, tags, match, createdFrom, createdTo, updatedFrom, updatedTo, + originalCreatedFrom, originalCreatedTo, page, limit, order }: FetchPostsParams ): Promise<{ - posts: Post[] - count: number }> => + posts: Post[] + count: number }> => await apiGet ('/posts', { params: { - url, title, tags, match, created_from, created_to, updated_from, updated_to, - original_created_from, original_created_to, + ...(url && { url }), + ...(title && { title }), + ...(tags && { tags }), + ...(match && { match }), + ...(createdFrom && { created_from: createdFrom }), + ...(createdTo && { created_to: createdTo }), + ...(updatedFrom && { updated_from: updatedFrom }), + ...(updatedTo && { updated_to: updatedTo }), + ...(originalCreatedFrom && { original_created_from: originalCreatedFrom }), + ...(originalCreatedTo && { original_created_to: originalCreatedTo }), ...(page && { page }), - ...(limit && { limit }) } }) + ...(limit && { limit }), + ...(order && { order }) } }) export const fetchPost = async (id: string): Promise => await apiGet (`/posts/${ id }`) diff --git a/frontend/src/lib/queryKeys.ts b/frontend/src/lib/queryKeys.ts index 081afea..d8cbeef 100644 --- a/frontend/src/lib/queryKeys.ts +++ b/frontend/src/lib/queryKeys.ts @@ -1,17 +1,8 @@ +import type { FetchPostsParams } from '@/types' + export const postsKeys = { root: ['posts'] as const, - index: (p: { url?: string - title?: string - tags?: string - match?: 'all' | 'any' - created_from?: string - created_to?: string - updated_from?: string - updated_to?: string - original_created_from?: string - original_created_to?: string - page?: number - limit?: number }) => ['posts', 'index', p] as const, + index: (p: FetchPostsParams) => ['posts', 'index', p] as const, show: (id: string) => ['posts', id] as const, related: (id: string) => ['related', id] as const, changes: (p: { id?: string; page: number; limit: number }) => diff --git a/frontend/src/pages/posts/PostSearchPage.tsx b/frontend/src/pages/posts/PostSearchPage.tsx index 1ce25a9..461461f 100644 --- a/frontend/src/pages/posts/PostSearchPage.tsx +++ b/frontend/src/pages/posts/PostSearchPage.tsx @@ -18,7 +18,7 @@ import { postsKeys } from '@/lib/queryKeys' import type { FC, ChangeEvent, FormEvent, KeyboardEvent } from 'react' -import type { Tag } from '@/types' +import type { FetchPostsOrder, FetchPostsParams, Tag } from '@/types' const setIf = (qs: URLSearchParams, k: string, v: string | null) => { @@ -49,11 +49,13 @@ export default (() => { const qCreatedTo = query.get ('created_to') const qUpdatedFrom = query.get ('updated_from') const qUpdatedTo = query.get ('updated_to') + const qOrder = (query.get ('order') || 'original_created_at:desc') as FetchPostsOrder const [activeIndex, setActiveIndex] = useState (-1) const [createdFrom, setCreatedFrom] = useState (qCreatedFrom) const [createdTo, setCreatedTo] = useState (qCreatedTo) const [matchType, setMatchType] = useState (qMatch ?? 'all') + const [order, setOrder] = useState ('original_created_at:desc') const [originalCreatedFrom, setOriginalCreatedFrom] = useState (qOriginalCreatedFrom) const [originalCreatedTo, setOriginalCreatedTo] = useState (qOriginalCreatedTo) const [suggestions, setSuggestions] = useState ([]) @@ -64,16 +66,17 @@ export default (() => { const [updatedTo, setUpdatedTo] = useState (qUpdatedTo) const [url, setURL] = useState (qURL ?? '') - const keys = { + const keys: FetchPostsParams = { tags: qTags, match: qMatch, page, limit, ...(qURL && { url: qURL }), ...(qTitle && { title: qTitle }), - ...(qOriginalCreatedFrom && { original_created_from: qOriginalCreatedFrom }), - ...(qOriginalCreatedTo && { original_created_to: qOriginalCreatedTo }), - ...(qCreatedFrom && { created_from: qCreatedFrom }), - ...(qCreatedTo && { created_to: qCreatedTo }), - ...(qUpdatedFrom && { updated_from: qUpdatedFrom }), - ...(qUpdatedTo && { updated_to: qUpdatedTo }) } + ...(qOriginalCreatedFrom && { originalCreatedFrom: qOriginalCreatedFrom }), + ...(qOriginalCreatedTo && { originalCreatedTo: qOriginalCreatedTo }), + ...(qCreatedFrom && { createdFrom: qCreatedFrom }), + ...(qCreatedTo && { createdTo: qCreatedTo }), + ...(qUpdatedFrom && { updatedFrom: qUpdatedFrom }), + ...(qUpdatedTo && { updatedTo: qUpdatedTo }), + ...(qOrder && { order: qOrder }) } const { data, isLoading: loading } = useQuery ({ queryKey: postsKeys.index (keys), queryFn: () => fetchPosts (keys) }) @@ -91,6 +94,7 @@ export default (() => { setCreatedTo (qCreatedTo) setUpdatedFrom (qUpdatedFrom) setUpdatedTo (qUpdatedTo) + setOrder (qOrder) document.querySelector ('table')?.scrollIntoView ({ behavior: 'smooth' }) }, [location.search]) @@ -160,6 +164,7 @@ export default (() => { setIf (qs, 'updated_to', updatedTo) qs.set ('match', matchType) qs.set ('page', String ('1')) + qs.set ('order', order) navigate (`${ location.pathname }?${ qs.toString () }`) } diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 156f785..7cecaa2 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -1,9 +1,31 @@ -import { CATEGORIES, USER_ROLES, ViewFlagBehavior } from '@/consts' +import { CATEGORIES, + FETCH_POSTS_ORDER_FIELDS, + USER_ROLES, + ViewFlagBehavior } from '@/consts' import type { ReactNode } from 'react' export type Category = typeof CATEGORIES[number] +export type FetchPostsOrder = `${ FetchPostsOrderField }:${ 'asc' | 'desc' }` + +export type FetchPostsOrderField = typeof FETCH_POSTS_ORDER_FIELDS[number] + +export type FetchPostsParams = { + url?: string + title?: string + tags?: string + match?: 'all' | 'any' + createdFrom?: string + createdTo?: string + updatedFrom?: string + updatedTo?: string + originalCreatedFrom?: string + originalCreatedTo?: string + page?: number + limit?: number + order?: FetchPostsOrder } + export type Menu = MenuItem[] export type MenuItem = {