import axios from 'axios' import toCamel from 'camelcase-keys' import { useState, useEffect } from 'react' import { Link, useLocation, useNavigate } from 'react-router-dom' import Separator from '@/components/MenuSeparator' import { API_BASE_URL } from '@/config' import { WikiIdBus } from '@/lib/eventBus/WikiIdBus' import { cn } from '@/lib/utils' import type { Menu, Tag, User, WikiPage } from '@/types' type Props = { user: User | null } export default ({ user }: Props) => { const location = useLocation () const navigate = useNavigate () const [menuOpen, setMenuOpen] = useState (false) const [openItemIdx, setOpenItemIdx] = useState (-1) const [postCount, setPostCount] = useState (null) const [wikiId, setWikiId] = useState (WikiIdBus.get ()) const wikiPageFlg = Boolean (/^\/wiki\/(?!new|changes)[^\/]+/.test (location.pathname) && wikiId) const wikiTitle = location.pathname.split ('/')[2] const menu: Menu = [ { name: '広場', to: '/posts', subMenu: [ { name: '一覧', to: '/posts' }, { name: '投稿追加', to: '/posts/new' }, { name: 'ヘルプ', to: '/wiki/ヘルプ:広場' }] }, { name: 'タグ', to: '/tags', subMenu: [ { name: 'タグ一覧', to: '/tags', visible: false }, { name: '別名タグ', to: '/tags/aliases', visible: false }, { name: '上位タグ', to: '/tags/implications', visible: false }, { name: 'ニコニコ連携', to: '/tags/nico' }, { name: 'タグのつけ方', to: '/wiki/ヘルプ:タグのつけ方' }, { name: 'ヘルプ', to: '/wiki/ヘルプ:タグ' }] }, { name: 'Wiki', to: '/wiki/ヘルプ:ホーム', base: '/wiki', subMenu: [ { name: '検索', to: '/wiki' }, { name: '新規', to: '/wiki/new' }, { name: '全体履歴', to: '/wiki/changes' }, { name: 'ヘルプ', to: '/wiki/ヘルプ:Wiki' }, { component: , visible: wikiPageFlg }, { name: `広場 (${ postCount || 0 })`, to: `/posts?tags=${ wikiTitle }`, visible: wikiPageFlg }, { name: '履歴', to: `/wiki/changes?id=${ wikiId }`, visible: wikiPageFlg }, { name: '編輯', to: `/wiki/${ wikiId || wikiTitle }/edit`, visible: wikiPageFlg }] }, { name: 'ユーザ', to: '/users', subMenu: [ { name: '一覧', to: '/users', visible: false }, { name: 'お前', to: `/users/${ user?.id }`, visible: false }, { name: '設定', to: '/users/settings', visible: Boolean (user) }] }] useEffect (() => { const unsubscribe = WikiIdBus.subscribe (setWikiId) return () => unsubscribe () }, []) useEffect (() => { setOpenItemIdx (menu.findIndex (item => ( location.pathname.startsWith (item.base || item.to)))) }, [location]) useEffect (() => { if (!(wikiId)) return const fetchPostCount = async () => { try { const pageRes = await axios.get (`${ API_BASE_URL }/wiki/${ wikiId }`) const wikiPage = toCamel (pageRes.data as any, { deep: true }) as WikiPage const tagRes = await axios.get (`${ API_BASE_URL }/tags/name/${ wikiPage.title }`) const tag = toCamel (tagRes.data as any, { deep: true }) as Tag setPostCount (tag.postCount) } catch { setPostCount (0) } } fetchPostCount () }, [wikiId]) return ( <>
{menu.find (item => location.pathname.startsWith (item.base || item.to))?.subMenu .filter (item => item.visible ?? true) .map ((item, i) => 'component' in item ? item.component : ( {item.name} ))}
{menu.map ((item, i) => ( <> { ev.preventDefault () if (i === openItemIdx) { setMenuOpen (false) navigate (item.to) } else setOpenItemIdx (i) }}> {item.name} {i === openItemIdx && ( item.subMenu .filter (subItem => subItem.visible ?? true) .map ((subItem, j) => 'component' in subItem ? subItem.component : ( {subItem.name} )))} ))} {user && ( <> {user.name || '名もなきニジラー'} )}
) }