This commit is contained in:
2026-04-22 02:06:15 +09:00
parent 8ff1819d5a
commit 6b0d262040
8 changed files with 232 additions and 16 deletions
+2
View File
@@ -26,6 +26,7 @@ import PostNewPage from '@/pages/posts/PostNewPage'
import PostSearchPage from '@/pages/posts/PostSearchPage'
import ServiceUnavailable from '@/pages/ServiceUnavailable'
import SettingPage from '@/pages/users/SettingPage'
import TagDetailPage from '@/pages/tags/TagDetailPage'
import TagListPage from '@/pages/tags/TagListPage'
import TheatreDetailPage from '@/pages/theatres/TheatreDetailPage'
import WikiDetailPage from '@/pages/wiki/WikiDetailPage'
@@ -55,6 +56,7 @@ const RouteTransitionWrapper = ({ user, setUser }: {
<Route path="/posts/:id" element={<PostDetailRoute user={user}/>}/>
<Route path="/posts/changes" element={<PostHistoryPage/>}/>
<Route path="/tags" element={<TagListPage/>}/>
<Route path="/tags/:name" element={<TagDetailPage/>}/>
<Route path="/tags/nico" element={<NicoTagListPage user={user}/>}/>
<Route path="/theatres/:id" element={<TheatreDetailPage/>}/>
<Route path="/materials" element={<MaterialBasePage/>}>
+133
View File
@@ -0,0 +1,133 @@
import { useQuery, useQueryClient } from '@tanstack/react-query'
import { useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'
import Label from '@/components/common/Label'
import PageTitle from '@/components/common/PageTitle'
import MainArea from '@/components/layout/MainArea'
import { toast } from '@/components/ui/use-toast'
import { CATEGORIES, CATEGORY_NAMES } from '@/consts'
import { apiPut } from '@/lib/api'
import { postsKeys, tagsKeys } from '@/lib/queryKeys'
import { fetchTagByName } from '@/lib/tags'
import type { FC, FormEvent } from 'react'
import type { Category, Tag } from '@/types'
export default (() => {
const { name: nameRaw } = useParams ()
const tagName = String (nameRaw ?? '')
const tagKey = tagsKeys.show (tagName)
const { data: tag, isLoading: loading } = useQuery ({
queryKey: tagKey,
queryFn: () => fetchTagByName (tagName) })
const [name, setName] = useState ('')
const [category, setCategory] = useState<Category> ('general')
const [aliases, setAliases] = useState ('')
const [parentTags, setParentTags] = useState ('')
const qc = useQueryClient ()
const handleSubmit = async (e: FormEvent) => {
e.preventDefault ()
const formData = new FormData
formData.append ('name', name)
formData.append ('category', category)
formData.append ('aliases', aliases)
formData.append ('parent_tags', parentTags)
try
{
const data = await apiPut<Tag> (`/tags/${ tag?.id }`, formData)
setName (data.name)
setCategory (data.category as Category)
setAliases (data.aliases.join (' '))
setParentTags (data.parents.map (t => t.name).join (' '))
qc.invalidateQueries ({ queryKey: postsKeys.root })
qc.invalidateQueries ({ queryKey: tagsKeys.root })
toast ({ description: '更新しました.' })
}
catch
{
toast ({ description: '更新に失敗しました.' })
}
}
useEffect (() => {
if (!(tag))
return
setName (tag.name)
setCategory (tag.category as Category)
setAliases (tag.aliases?.join (' '))
setParentTags (tag.parents?.map (t => t.name).join (' '))
}, [tag])
return (
<MainArea>
{(loading || !(tag)) ? 'Loading...' : (
<div className="max-w-xl">
<PageTitle>{tag.name}</PageTitle>
<form onSubmit={handleSubmit} className="my-4 space-y-2">
{/* 名称 */}
<div>
<Label></Label>
<input
type="text"
value={name}
onChange={e => setName (e.target.value)}
className="w-full border p-2 rounded"/>
</div>
{/* カテゴリ */}
<div>
<Label></Label>
<select
value={category ?? ''}
onChange={e => setCategory(e.target.value as Category)}
className="w-full border p-2 rounded">
{CATEGORIES.filter (cat => cat !== 'nico').map (cat => (
<option key={cat} value={cat}>
{CATEGORY_NAMES[cat]}
</option>))}
</select>
</div>
{/* 別名 */}
<div>
<Label></Label>
<input
type="text"
value={aliases}
onChange={e => setAliases (e.target.value)}
className="w-full border p-2 rounded"/>
</div>
{/* 上位タグ */}
<div>
<Label></Label>
<input
type="text"
value={parentTags}
onChange={e => setParentTags (e.target.value)}
className="w-full border p-2 rounded"/>
</div>
<div className="py-3">
<button
type="submit"
className="bg-blue-500 text-white px-4 py-2 rounded">
</button>
</div>
</form>
</div>)}
</MainArea>)
}) satisfies FC
+4 -1
View File
@@ -260,7 +260,10 @@ export default (() => {
{results.map (row => (
<tr key={row.id} className="even:bg-gray-100 dark:even:bg-gray-700">
<td className="p-2">
<TagLink tag={row} withCount={false}/>
<TagLink
tag={row}
to={`/tags/${ encodeURIComponent (row.name) }`}
withCount={false}/>
</td>
<td className="p-2">{CATEGORY_NAMES[row.category]}</td>
<td className="p-2 text-right">{row.postCount}</td>
+9 -7
View File
@@ -114,13 +114,15 @@ export default () => {
{...(version && { to: `/wiki/${ encodeURIComponent (title) }` })}/>
</h1>
{loading ? <div>Loading...</div> : <WikiBody title={title} body={wikiPage?.body}/>}
</article>
{(!(version) && posts.length > 0) && (
<TabGroup>
<Tab name="広場">
<PostList posts={posts}/>
</Tab>
</TabGroup>)}
{(!(version) && posts.length > 0) && (
<div className="not-prose">
<TabGroup>
<Tab name="広場">
<PostList posts={posts}/>
</Tab>
</TabGroup>
</div>)}
</article>
</MainArea>)
}
+2
View File
@@ -165,6 +165,8 @@ export type Tag = {
id: number
name: string
category: Category
aliases: string[]
parents: Tag[]
postCount: number
createdAt: string
updatedAt: string