import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useEffect, useState } from 'react' import { Helmet } from 'react-helmet-async' import { useParams } from 'react-router-dom' import PostList from '@/components/PostList' import TagDetailSidebar from '@/components/TagDetailSidebar' import PostEditForm from '@/components/PostEditForm' import PostEmbed from '@/components/PostEmbed' import TabGroup, { Tab } from '@/components/common/TabGroup' import MainArea from '@/components/layout/MainArea' import { Button } from '@/components/ui/button' import { toast } from '@/components/ui/use-toast' import { SITE_TITLE } from '@/config' import { fetchPost, toggleViewedFlg } from '@/lib/posts' import { cn } from '@/lib/utils' import NotFound from '@/pages/NotFound' import ServiceUnavailable from '@/pages/ServiceUnavailable' import type { FC } from 'react' import type { User } from '@/types' type Props = { user: User | null } export default (({ user }: Props) => { const { id } = useParams () const { data: post, isError: errorFlg, error } = useQuery ({ enabled: Boolean (id), queryKey: ['posts', String (id)], queryFn: () => fetchPost (String (id)) }) const qc = useQueryClient () const [status, setStatus] = useState (200) const changeViewedFlg = useMutation ({ mutationFn: async () => { const next = !(post!.viewed) await toggleViewedFlg (id!, next) return next }, onMutate: async () => { await qc.cancelQueries ({ queryKey: ['posts', String (id)] }) const prev = qc.getQueryData (['posts', String (id)]) qc.setQueryData (['posts', String (id)], (cur: any) => cur ? { ...cur, viewed: !(cur.viewed) } : cur) return { prev } }, onError: (...[, , ctx]) => { if (ctx?.prev) qc.setQueryData (['posts', String (id)], ctx.prev) toast ({ title: '失敗……', description: '通信に失敗しました……' }) }, onSuccess: () => { qc.invalidateQueries ({ queryKey: ['posts', 'index'] }) qc.invalidateQueries ({ queryKey: ['related', String (id)] }) } }) useEffect (() => { if (!(errorFlg)) return const code = (error as any)?.response.status ?? (error as any)?.status if (code) setStatus (code) }, [errorFlg, error]) switch (status) { case 404: return case 503: return } const viewedClass = (post?.viewed ? 'bg-blue-600 hover:bg-blue-700' : 'bg-gray-500 hover:bg-gray-600') return (
{(post?.thumbnail || post?.thumbnailBase) && ( )} {post && {`${ post.title || post.url } | ${ SITE_TITLE }`}}
{post ? ( <> {post.related.length > 0 ? : 'まだないよ(笑)'} {['admin', 'member'].some (r => user?.role === r) && ( { qc.setQueryData (['posts', String (id)], (prev: any) => newPost ?? prev) qc.invalidateQueries ({ queryKey: ['posts', 'index'] }) qc.invalidateQueries ({ queryKey: ['related', String (id)] }) toast ({ description: '更新しました.' }) }}/> )} ) : 'Loading...'}
) }) satisfies FC