From 5a4919116d52ac080e13bc88567a94060eac80e3 Mon Sep 17 00:00:00 2001 From: miteruzo Date: Mon, 21 Jul 2025 16:54:30 +0900 Subject: [PATCH] #23 --- frontend/src/components/TopNav.tsx | 171 +++++++------------- frontend/src/pages/tags/NicoTagListPage.tsx | 6 +- frontend/src/pages/wiki/WikiDiffPage.tsx | 26 +-- frontend/src/types.ts | 18 +++ 4 files changed, 92 insertions(+), 129 deletions(-) diff --git a/frontend/src/components/TopNav.tsx b/frontend/src/components/TopNav.tsx index fac23c1..db23f4a 100644 --- a/frontend/src/components/TopNav.tsx +++ b/frontend/src/components/TopNav.tsx @@ -7,41 +7,53 @@ import { API_BASE_URL } from '@/config' import { WikiIdBus } from '@/lib/eventBus/WikiIdBus' import { cn } from '@/lib/utils' -import type { Tag, User, WikiPage } from '@/types' +import type { Menu, Tag, User, WikiPage } from '@/types' type Props = { user: User | null } -const Menu = { None: 'None', - Post: 'Post', - User: 'User', - Tag: 'Tag', - Wiki: 'Wiki' } as const -type Menu = typeof Menu[keyof typeof Menu] - export default ({ user }: Props) => { const location = useLocation () // const navigate = useNavigate () - const [selectedMenu, setSelectedMenu] = useState (Menu.None) - const [wikiId, setWikiId] = useState (WikiIdBus.get ()) - // const [wikiSearch, setWikiSearch] = useState ('') // const [activeIndex, setActiveIndex] = useState (-1) - // const [suggestions, setSuggestions] = useState ([]) + const [postCount, setPostCount] = useState (null) // const [suggestionsVsbl, setSuggestionsVsbl] = useState (false) + // const [suggestions, setSuggestions] = useState ([]) // const [tagSearch, setTagSearch] = useState ('') // const [userSearch, setUserSearch] = useState ('') - const [postCount, setPostCount] = useState (null) + const [wikiId, setWikiId] = useState (WikiIdBus.get ()) + // const [wikiSearch, setWikiSearch] = useState ('') - const MyLink = ({ to, title, base }: { to: string - title: string - base?: string }) => ( - - {title} - ) + 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/posts' }, + { 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) }] }] // const whenTagSearchChanged = (ev: React.ChangeEvent) => { // // TODO: 実装 @@ -98,19 +110,6 @@ export default ({ user }: Props) => { return () => unsubscribe () }, []) - useEffect (() => { - if (location.pathname.startsWith ('/posts')) - setSelectedMenu (Menu.Post) - else if (location.pathname.startsWith ('/users')) - setSelectedMenu (Menu.User) - else if (location.pathname.startsWith ('/tags')) - setSelectedMenu (Menu.Tag) - else if (location.pathname.startsWith ('/wiki')) - setSelectedMenu (Menu.Wiki) - else - setSelectedMenu (Menu.None) - }, [location]) - useEffect (() => { if (!(wikiId)) return @@ -144,95 +143,33 @@ export default ({ user }: Props) => { dark:text-pink-300 dark:hover:text-pink-100"> ぼざクリ タグ広場 - - - - + {menu.map (item => ( + + {item.name} + + ))} - {user && + {user && (
{user.name || '名もなきニジラー'} -
} + )} - {(() => { - 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 = () => | - switch (selectedMenu) - { - case Menu.Post: - return ( -
- 一覧 - 投稿追加 - ヘルプ -
) - case Menu.Tag: - return ( -
- {/* TODO: リリース後にやる */} - {/* setSuggestionsVsbl (true)} - onBlur={() => setSuggestionsVsbl (false)} - onKeyDown={handleKeyDown} /> */} - {/* タグ */} - {/* 別名タグ - 上位タグ */} - ニコニコ連携 - タグのつけ方 - ヘルプ -
) - case Menu.Wiki: - return ( -
- {/* TODO: リリース後にやる */} - {/* setSuggestionsVsbl (true)} - onBlur={() => setSuggestionsVsbl (false)} - onKeyDown={handleKeyDown} /> */} - 検索 - 新規 - 全体履歴 - ヘルプ - {(/^\/wiki\/(?!new|changes)[^\/]+/.test (location.pathname) && wikiId) && - <> - - 広場 ({postCount || 0}) - 履歴 - 編輯 - } -
) - case Menu.User: - return ( -
- {/* TODO: リリース後にやる */} - {/* setSuggestionsVsbl (true)} - onBlur={() => setSuggestionsVsbl (false)} - onKeyDown={handleKeyDown} /> */} - {/* 一覧 - {user && お前} */} - {user && 設定} -
) - } - }) ()} +
+ {menu.find (item => location.pathname.startsWith (item.base || item.to))?.subMenu + .filter (item => item.visible ?? true) + .map (item => 'component' in item ? item.component : ( + + {item.name} + ))} +
) } diff --git a/frontend/src/pages/tags/NicoTagListPage.tsx b/frontend/src/pages/tags/NicoTagListPage.tsx index 1c374d1..44f5054 100644 --- a/frontend/src/pages/tags/NicoTagListPage.tsx +++ b/frontend/src/pages/tags/NicoTagListPage.tsx @@ -136,7 +136,11 @@ export default ({ user }: Props) => { handleEdit (tag.id) }}> {editing[tag.id] - ? 更新 + ? ( + + 更新 + ) : 編輯} )} diff --git a/frontend/src/pages/wiki/WikiDiffPage.tsx b/frontend/src/pages/wiki/WikiDiffPage.tsx index 24bf9aa..ef8bdcb 100644 --- a/frontend/src/pages/wiki/WikiDiffPage.tsx +++ b/frontend/src/pages/wiki/WikiDiffPage.tsx @@ -7,6 +7,7 @@ import { useLocation, useParams } from 'react-router-dom' import PageTitle from '@/components/common/PageTitle' import MainArea from '@/components/layout/MainArea' import { API_BASE_URL, SITE_TITLE } from '@/config' +import { cn } from '@/lib/utils' import type { WikiPageDiff } from '@/types' @@ -31,16 +32,19 @@ export default () => { return ( - - {`Wiki 差分: ${ diff?.title } | ${ SITE_TITLE }`} - - {diff?.title} -
- {diff ? ( - diff.diff.map (d => ( - - {d.content == '\n' ?
: d.content} -
))) : 'Loading...'} -
+ + {`Wiki 差分: ${ diff?.title } | ${ SITE_TITLE }`} + + {diff?.title} +
+ {diff + ? ( + diff.diff.map (d => ( + + {d.content == '\n' ?
: d.content} +
))) + : 'Loading...'} +
) } diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 82d6fa9..63dbcce 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -1,7 +1,17 @@ +import React from 'react' + import { CATEGORIES, USER_ROLES, ViewFlagBehavior } from '@/consts' export type Category = typeof CATEGORIES[number] +export type Menu = MenuItem[] + +export type MenuItem = { + name: string + to: string + base?: string + subMenu: SubMenuItem[] } + export type NicoTag = Tag & { category: 'nico' linkedTags: Tag[] } @@ -15,6 +25,14 @@ export type Post = { tags: Tag[] viewed: boolean } +export type SubMenuItem = { + component: React.ReactNode + visible: boolean + } | { + name: string + to: string + visible?: boolean } + export type Tag = { id: number name: string