| @@ -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<Category, string> | |||
| nico: 'gray', | |||
| } as const satisfies Record<Category, string> | |||
| 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 | |||
| @@ -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<Post> => await apiGet (`/posts/${ id }`) | |||
| @@ -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 }) => | |||
| @@ -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<FetchPostsOrder> ('original_created_at:desc') | |||
| const [originalCreatedFrom, setOriginalCreatedFrom] = useState (qOriginalCreatedFrom) | |||
| const [originalCreatedTo, setOriginalCreatedTo] = useState (qOriginalCreatedTo) | |||
| const [suggestions, setSuggestions] = useState<Tag[]> ([]) | |||
| @@ -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 () }`) | |||
| } | |||
| @@ -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 = { | |||