This commit is contained in:
2025-06-30 23:31:39 +09:00
parent 068d0aed14
commit e20f7fcc17
13 changed files with 140 additions and 75 deletions
+2 -7
View File
@@ -1,4 +1,5 @@
import axios from 'axios'
import toCamel from 'camelcase-keys'
import React, { useEffect, useState } from 'react'
import { Link, useNavigate, useParams } from 'react-router-dom'
@@ -18,11 +19,9 @@ export default ({ posts }: Props) => {
const navigate = useNavigate ()
const [tags, setTags] = useState<TagByCategory> ({ })
const [tagsCounts, setTagsCounts] = useState<{ [key: number]: number }> ({ })
useEffect (() => {
const tagsTmp: TagByCategory = { }
const tagsCountsTmp: { [key: number]: number } = { }
for (const post of posts)
{
for (const tag of post.tags)
@@ -31,15 +30,11 @@ export default ({ posts }: Props) => {
tagsTmp[tag.category] = []
if (!(tagsTmp[tag.category].map (t => t.id).includes (tag.id)))
tagsTmp[tag.category].push (tag)
if (!(tag.id in tagsCountsTmp))
tagsCountsTmp[tag.id] = 0
++tagsCountsTmp[tag.id]
}
}
for (const cat of Object.keys (tagsTmp))
tagsTmp[cat].sort ((tagA, tagB) => tagA.name < tagB.name ? -1 : 1)
setTags (tagsTmp)
setTagsCounts (tagsCountsTmp)
}, [posts])
return (
@@ -54,7 +49,7 @@ export default ({ posts }: Props) => {
<Link to={`/posts?${ (new URLSearchParams ({ tags: tag.name })).toString () }`}>
{tag.name}
</Link>
<span className="ml-1">{tagsCounts[tag.id]}</span>
<span className="ml-1">{tag.postCount}</span>
</li>))}
</>))}
</ul>
+37 -9
View File
@@ -1,11 +1,15 @@
import axios from 'axios'
import toCamel from 'camelcase-keys'
import React, { useState, useEffect } from 'react'
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom'
import SettingsDialogue from './SettingsDialogue'
import { Button } from './ui/button'
import { cn } from '@/lib/utils'
import { WikiIdBus } from '@/lib/eventBus/WikiIdBus'
import type { User } from '@/types'
import SettingsDialogue from '@/components/SettingsDialogue'
import { Button } from '@/components/ui/button'
import { API_BASE_URL } from '@/config'
import { WikiIdBus } from '@/lib/eventBus/WikiIdBus'
import { cn } from '@/lib/utils'
import type { Tag, User, WikiPage } from '@/types'
type Props = { user: User
setUser: (user: User) => void }
@@ -23,13 +27,14 @@ const TopNav: React.FC = ({ user, setUser }: Props) => {
const [settingsVsbl, setSettingsVsbl] = useState (false)
const [selectedMenu, setSelectedMenu] = useState<Menu> (Menu.None)
const [wikiId, setWikiId] = useState (WikiIdBus.get ())
const [wikiId, setWikiId] = useState<number | null> (WikiIdBus.get ())
const [wikiSearch, setWikiSearch] = useState ('')
const [activeIndex, setActiveIndex] = useState (-1)
const [suggestions, setSuggestions] = useState<WikiPage[]> ([])
const [suggestionsVsbl, setSuggestionsVsbl] = useState (false)
const [tagSearch, setTagSearch] = useState ('')
const [userSearch, setUserSearch] = useState ('')
const [postCount, setPostCount] = useState<number | null> (null)
const MyLink = ({ to, title, menu, base }: { to: string
title: string
@@ -93,7 +98,8 @@ const TopNav: React.FC = ({ user, setUser }: Props) => {
}
useEffect (() => {
WikiIdBus.subscribe (setWikiId)
const unsubscribe = WikiIdBus.subscribe (setWikiId)
return () => unsubscribe ()
}, [])
useEffect (() => {
@@ -109,6 +115,28 @@ const TopNav: React.FC = ({ user, setUser }: Props) => {
setSelectedMenu (Menu.None)
}, [location])
useEffect (() => {
if (!(wikiId))
return
void ((async () => {
try
{
const { data: pageData } = await axios.get (`${ API_BASE_URL }/wiki/${ wikiId }`)
const wikiPage: WikiPage = toCamel (pageData, { deep: true })
const { data: tagData } = await axios.get (`${ API_BASE_URL }/tags/name/${ wikiPage.title }`)
const tag: Tag = toCamel (tagData, { deep: true })
setPostCount (tag.postCount)
}
catch
{
setPostCount (0)
}
}) ())
}, [wikiId])
return (
<>
<nav className="bg-gray-800 text-white px-3 flex justify-between items-center w-full min-h-[48px]">
@@ -173,10 +201,10 @@ const TopNav: React.FC = ({ user, setUser }: Props) => {
<Link to="/wiki/new" className={subClass}></Link>
<Link to="/wiki/changes" className={subClass}></Link>
<Link to="/wiki/ヘルプ:Wiki" className={subClass}></Link>
{/^\/wiki\/(?!new|changes)[^\/]+/.test (location.pathname) &&
{(/^\/wiki\/(?!new|changes)[^\/]+/.test (location.pathname) && wikiId) &&
<>
<Separator />
<Link to={`/posts?tags=${ location.pathname.split ('/')[2] }`} className={subClass}></Link>
<Link to={`/posts?tags=${ location.pathname.split ('/')[2] }`} className={subClass}> ({postCount || 0})</Link>
<Link to={`/wiki/changes?id=${ wikiId }`} className={subClass}></Link>
<Link to={`/wiki/${ wikiId || location.pathname.split ('/')[2] }/edit`} className={subClass}></Link>
</>}
+2 -2
View File
@@ -30,7 +30,7 @@ export default () => {
.then (res => setPosts (toCamel (res.data, { deep: true })))
.catch (err => {
console.error ('Failed to fetch posts:', err)
setPosts (null)
setPosts ([])
}))
setWikiPage (null)
@@ -72,7 +72,7 @@ export default () => {
: '広場には何もありませんよ.')}
</Tab>
{(wikiPage && wikiPage.body) && (
<Tab name="Wiki" init={!(posts?.length)}>
<Tab name="Wiki" init={posts && !(posts.length)}>
<WikiBody body={wikiPage.body} />
<div className="my-2">
<Link to={`/wiki/${ wikiPage.title }`}>Wiki </Link>
@@ -38,6 +38,8 @@ export default () => {
WikiIdBus.set (res.data.id)
})
.catch (() => setWikiPage (null)))
return () => WikiIdBus.set (null)
}, [title, location.search])
return (
+4 -4
View File
@@ -12,10 +12,10 @@ export type Post = {
viewed: boolean }
export type Tag = {
id: number
name: string
category: Category
count?: number}
id: number
name: string
category: Category
postCount: number }
export type User = {
id: number