This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
import TagLink from '@/components/TagLink'
|
||||
import TagSearch from '@/components/TagSearch'
|
||||
import SubsectionTitle from '@/components/common/SubsectionTitle'
|
||||
import SidebarComponent from '@/components/layout/SidebarComponent'
|
||||
@@ -14,47 +14,48 @@ type Props = { post: Post | null }
|
||||
|
||||
|
||||
export default ({ post }: Props) => {
|
||||
const [tags, setTags] = useState({ } as TagByCategory)
|
||||
const [tags, setTags] = useState ({ } as TagByCategory)
|
||||
|
||||
const categoryNames: Partial<{ [key in Category]: string }> = {
|
||||
general: '一般',
|
||||
const categoryNames: Record<Category, string> = {
|
||||
deerjikist: 'ニジラー',
|
||||
meme: '原作・ネタ元・ミーム等',
|
||||
character: 'キャラクター',
|
||||
general: '一般',
|
||||
material: '素材',
|
||||
meta: 'メタタグ',
|
||||
nico: 'ニコニコタグ' }
|
||||
|
||||
useEffect (() => {
|
||||
if (!(post))
|
||||
return
|
||||
|
||||
const fetchTags = () => {
|
||||
const tagsTmp = { } as TagByCategory
|
||||
for (const tag of post.tags)
|
||||
{
|
||||
if (!(tag.category in tagsTmp))
|
||||
tagsTmp[tag.category] = []
|
||||
tagsTmp[tag.category].push (tag)
|
||||
}
|
||||
for (const cat of Object.keys (tagsTmp) as (keyof typeof tagsTmp)[])
|
||||
tagsTmp[cat].sort ((tagA: Tag, tagB: Tag) => tagA.name < tagB.name ? -1 : 1)
|
||||
setTags (tagsTmp)
|
||||
}
|
||||
const tagsTmp = { } as TagByCategory
|
||||
|
||||
fetchTags ()
|
||||
for (const tag of post.tags)
|
||||
{
|
||||
if (!(tag.category in tagsTmp))
|
||||
tagsTmp[tag.category] = []
|
||||
tagsTmp[tag.category].push (tag)
|
||||
}
|
||||
|
||||
for (const cat of Object.keys (tagsTmp) as (keyof typeof tagsTmp)[])
|
||||
tagsTmp[cat].sort ((tagA: Tag, tagB: Tag) => tagA.name < tagB.name ? -1 : 1)
|
||||
|
||||
setTags (tagsTmp)
|
||||
}, [post])
|
||||
|
||||
return (
|
||||
<SidebarComponent>
|
||||
<TagSearch />
|
||||
{CATEGORIES.map ((cat: Category) => cat in tags && (
|
||||
<div className="my-3" key={cat}>
|
||||
<SubsectionTitle>{categoryNames[cat]}</SubsectionTitle>
|
||||
<ul>
|
||||
{tags[cat].map (tag => (
|
||||
<li key={tag.id} className="mb-1">
|
||||
<Link to={`/posts?${ (new URLSearchParams ({ tags: tag.name })).toString () }`}>
|
||||
{tag.name}
|
||||
</Link>
|
||||
</li>))}
|
||||
</ul>
|
||||
</div>))}
|
||||
<TagSearch />
|
||||
{CATEGORIES.map ((cat: Category) => cat in tags && (
|
||||
<div className="my-3" key={cat}>
|
||||
<SubsectionTitle>{categoryNames[cat]}</SubsectionTitle>
|
||||
<ul>
|
||||
{tags[cat].map ((tag, i) => (
|
||||
<li key={i} className="mb-1">
|
||||
<TagLink tag={tag} />
|
||||
</li>))}
|
||||
</ul>
|
||||
</div>))}
|
||||
</SidebarComponent>)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
import { LIGHT_COLOUR_SHADE, DARK_COLOUR_SHADE, TAG_COLOUR } from '@/consts'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
import type { Tag } from '@/types'
|
||||
|
||||
type Props = { tag: Tag
|
||||
linkFlg?: boolean
|
||||
withWiki?: boolean
|
||||
withCount?: boolean }
|
||||
|
||||
|
||||
export default ({ tag,
|
||||
linkFlg = true,
|
||||
withWiki = true,
|
||||
withCount = true }: Props) => {
|
||||
const spanClass = cn (
|
||||
`text-${ TAG_COLOUR[tag.category] }-${ LIGHT_COLOUR_SHADE }`,
|
||||
`dark:text-${ TAG_COLOUR[tag.category] }-${ DARK_COLOUR_SHADE }`)
|
||||
const linkClass = cn (
|
||||
spanClass,
|
||||
`hover:text-${ TAG_COLOUR[tag.category] }-${ LIGHT_COLOUR_SHADE - 200 }`,
|
||||
`dark:hover:text-${ TAG_COLOUR[tag.category] }-${ DARK_COLOUR_SHADE - 200 }`)
|
||||
|
||||
return (
|
||||
<>
|
||||
{(linkFlg && withWiki) && (
|
||||
<span className="mr-1">
|
||||
<Link to={`/wiki/${ encodeURIComponent (tag.name) }`}
|
||||
className={linkClass}>
|
||||
?
|
||||
</Link>
|
||||
</span>)}
|
||||
{linkFlg
|
||||
? (
|
||||
<Link to={`/posts?${ (new URLSearchParams ({ tags: tag.name })).toString () }`}
|
||||
className={linkClass}>
|
||||
{tag.name}
|
||||
</Link>)
|
||||
: (
|
||||
<span className={spanClass}>
|
||||
{tag.name}
|
||||
</span>)}
|
||||
{withCount && (
|
||||
<span className="ml-1">{tag.postCount}</span>)}
|
||||
</>)
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
import axios from 'axios'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Link, useLocation, useNavigate } from 'react-router-dom'
|
||||
import { useLocation, useNavigate } from 'react-router-dom'
|
||||
|
||||
import TagLink from '@/components/TagLink'
|
||||
import TagSearch from '@/components/TagSearch'
|
||||
import SectionTitle from '@/components/common/SectionTitle'
|
||||
import SidebarComponent from '@/components/layout/SidebarComponent'
|
||||
@@ -28,6 +29,7 @@ export default ({ posts }: Props) => {
|
||||
useEffect (() => {
|
||||
const tagsTmp: TagByCategory = { }
|
||||
let cnt = 0
|
||||
|
||||
loop:
|
||||
for (const post of posts)
|
||||
{
|
||||
@@ -35,6 +37,7 @@ export default ({ posts }: Props) => {
|
||||
{
|
||||
if (!(tag.category in tagsTmp))
|
||||
tagsTmp[tag.category] = []
|
||||
|
||||
if (!(tagsTmp[tag.category].map (t => t.id).includes (tag.id)))
|
||||
{
|
||||
tagsTmp[tag.category].push (tag)
|
||||
@@ -44,8 +47,10 @@ export default ({ posts }: Props) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const cat of Object.keys (tagsTmp))
|
||||
tagsTmp[cat].sort ((tagA, tagB) => tagA.name < tagB.name ? -1 : 1)
|
||||
|
||||
setTags (tagsTmp)
|
||||
}, [posts])
|
||||
|
||||
@@ -57,10 +62,7 @@ export default ({ posts }: Props) => {
|
||||
{CATEGORIES.flatMap (cat => cat in tags ? (
|
||||
tags[cat].map (tag => (
|
||||
<li key={tag.id} className="mb-1">
|
||||
<Link to={`/posts?${ (new URLSearchParams ({ tags: tag.name })).toString () }`}>
|
||||
{tag.name}
|
||||
</Link>
|
||||
<span className="ml-1">{tag.postCount}</span>
|
||||
<TagLink tag={tag} />
|
||||
</li>))) : [])}
|
||||
</ul>
|
||||
<SectionTitle>関聯</SectionTitle>
|
||||
|
||||
@@ -17,7 +17,6 @@ const Menu = { None: 'None',
|
||||
User: 'User',
|
||||
Tag: 'Tag',
|
||||
Wiki: 'Wiki' } as const
|
||||
|
||||
type Menu = typeof Menu[keyof typeof Menu]
|
||||
|
||||
|
||||
@@ -38,9 +37,9 @@ export default ({ user }: Props) => {
|
||||
const MyLink = ({ to, title, base }: { to: string
|
||||
title: string
|
||||
base?: string }) => (
|
||||
<Link to={to} className={cn ('hover:text-orange-500 h-full flex items-center',
|
||||
<Link to={to} className={cn ('h-full flex items-center',
|
||||
(location.pathname.startsWith (base ?? to)
|
||||
? 'bg-gray-700 px-4 font-bold'
|
||||
? 'bg-yellow-200 dark:bg-red-950 px-4 font-bold'
|
||||
: 'px-2'))}>
|
||||
{title}
|
||||
</Link>)
|
||||
@@ -121,11 +120,9 @@ export default ({ user }: Props) => {
|
||||
try
|
||||
{
|
||||
const pageRes = await axios.get (`${ API_BASE_URL }/wiki/${ wikiId }`)
|
||||
const pageData: any = pageRes.data
|
||||
const wikiPage = toCamel (pageData, { deep: true }) as WikiPage
|
||||
const wikiPage = toCamel (pageRes.data as any, { deep: true }) as WikiPage
|
||||
|
||||
const tagRes = await axios.get (`${ API_BASE_URL }/tags/name/${ wikiPage.title }`)
|
||||
const tagData: any = tagRes.data
|
||||
const tag = toCamel (tagData, { deep: true }) as Tag
|
||||
|
||||
setPostCount (tag.postCount)
|
||||
@@ -139,25 +136,32 @@ export default ({ user }: Props) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<nav className="bg-gray-800 text-white px-3 flex justify-between items-center w-full min-h-[48px]">
|
||||
<nav className="px-3 flex justify-between items-center w-full min-h-[48px]
|
||||
bg-yellow-50 dark:bg-red-975">
|
||||
<div className="flex items-center gap-2 h-full">
|
||||
<Link to="/" className="mx-4 text-xl font-bold text-orange-500">ぼざクリ タグ広場</Link>
|
||||
<Link to="/" className="mx-4 text-xl font-bold
|
||||
text-pink-600 hover:text-pink-400
|
||||
dark:text-pink-300 dark:hover:text-pink-100">
|
||||
ぼざクリ タグ広場
|
||||
</Link>
|
||||
<MyLink to="/posts" title="広場" />
|
||||
<MyLink to="/tags" title="タグ" />
|
||||
<MyLink to="/wiki/ヘルプ:ホーム" base="/wiki" title="Wiki" />
|
||||
<MyLink to="/users/settings" base="/users" title="ニジラー" />
|
||||
</div>
|
||||
<div className="ml-auto pr-4">
|
||||
{user && (
|
||||
<Button onClick={() => navigate ('/users/settings')}
|
||||
className="bg-gray-600">
|
||||
{user &&
|
||||
<div className="ml-auto pr-4">
|
||||
<Link to="/users/settings"
|
||||
className="font-bold text-red-600 hover:text-red-400
|
||||
dark:text-yellow-400 dark:hover:text-yellow-200">
|
||||
{user.name || '名もなきニジラー'}
|
||||
</Button>)}
|
||||
</div>
|
||||
</Link>
|
||||
</div>}
|
||||
</nav>
|
||||
{(() => {
|
||||
const className = 'bg-gray-700 text-white px-3 flex items-center w-full min-h-[40px]'
|
||||
const subClass = 'hover:text-orange-500 h-full flex items-center px-3'
|
||||
const className = cn ('bg-yellow-200 dark:bg-red-950',
|
||||
'text-white px-3 flex items-center w-full min-h-[40px]')
|
||||
const subClass = 'h-full flex items-center px-3'
|
||||
// const inputBox = 'flex items-center px-3 mx-2'
|
||||
const Separator = () => <span className="flex items-center px-2">|</span>
|
||||
switch (selectedMenu)
|
||||
|
||||
Reference in New Issue
Block a user