|
|
@@ -1,8 +1,9 @@ |
|
|
|
import axios from 'axios' |
|
|
|
import toCamel from 'camelcase-keys' |
|
|
|
import { useState, useEffect } from 'react' |
|
|
|
import { Link, useLocation, /* useNavigate */ } from 'react-router-dom' |
|
|
|
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' |
|
|
@@ -14,16 +15,12 @@ type Props = { user: User | null } |
|
|
|
|
|
|
|
export default ({ user }: Props) => { |
|
|
|
const location = useLocation () |
|
|
|
// const navigate = useNavigate () |
|
|
|
const navigate = useNavigate () |
|
|
|
|
|
|
|
// const [activeIndex, setActiveIndex] = useState (-1) |
|
|
|
const [menuOpen, setMenuOpen] = useState (false) |
|
|
|
const [openItemIdx, setOpenItemIdx] = useState (-1) |
|
|
|
const [postCount, setPostCount] = useState<number | null> (null) |
|
|
|
// const [suggestionsVsbl, setSuggestionsVsbl] = useState (false) |
|
|
|
// const [suggestions, setSuggestions] = useState<WikiPage[]> ([]) |
|
|
|
// const [tagSearch, setTagSearch] = useState ('') |
|
|
|
// const [userSearch, setUserSearch] = useState ('') |
|
|
|
const [wikiId, setWikiId] = useState<number | null> (WikiIdBus.get ()) |
|
|
|
// const [wikiSearch, setWikiSearch] = useState ('') |
|
|
|
|
|
|
|
const wikiPageFlg = Boolean (/^\/wiki\/(?!new|changes)[^\/]+/.test (location.pathname) && wikiId) |
|
|
|
const wikiTitle = location.pathname.split ('/')[2] |
|
|
@@ -44,8 +41,7 @@ export default ({ user }: Props) => { |
|
|
|
{ name: '新規', to: '/wiki/new' }, |
|
|
|
{ name: '全体履歴', to: '/wiki/changes' }, |
|
|
|
{ name: 'ヘルプ', to: '/wiki/ヘルプ:Wiki' }, |
|
|
|
{ component: <span className="flex items-center px-2">|</span>, |
|
|
|
visible: wikiPageFlg }, |
|
|
|
{ component: <Separator />, visible: wikiPageFlg }, |
|
|
|
{ name: `広場 (${ postCount || 0 })`, to: `/posts?tags=${ wikiTitle }`, |
|
|
|
visible: wikiPageFlg }, |
|
|
|
{ name: '履歴', to: `/wiki/changes?id=${ wikiId }`, visible: wikiPageFlg }, |
|
|
@@ -55,61 +51,16 @@ export default ({ user }: Props) => { |
|
|
|
{ name: 'お前', to: `/users/${ user?.id }`, visible: false }, |
|
|
|
{ name: '設定', to: '/users/settings', visible: Boolean (user) }] }] |
|
|
|
|
|
|
|
// const whenTagSearchChanged = (ev: React.ChangeEvent<HTMLInputElement>) => { |
|
|
|
// // TODO: 実装 |
|
|
|
// |
|
|
|
// setTagSearch (ev.target.value) |
|
|
|
// |
|
|
|
// const q: string = ev.target.value.split (' ').at (-1) |
|
|
|
// if (!(q)) |
|
|
|
// { |
|
|
|
// // setSuggestions ([]) |
|
|
|
// return |
|
|
|
// } |
|
|
|
// } |
|
|
|
|
|
|
|
// const whenWikiSearchChanged = (ev: React.ChangeEvent<HTMLInputElement>) => { |
|
|
|
// // TODO: 実装 |
|
|
|
// |
|
|
|
// setWikiSearch (ev.target.value) |
|
|
|
// |
|
|
|
// const q: string = ev.target.value.split (' ').at (-1) |
|
|
|
// if (!(q)) |
|
|
|
// { |
|
|
|
// // setSuggestions ([]) |
|
|
|
// return |
|
|
|
// } |
|
|
|
// } |
|
|
|
|
|
|
|
// const whenUserSearchChanged = (ev: React.ChangeEvent<HTMLInputElement>) => { |
|
|
|
// // TODO: 実装 |
|
|
|
// |
|
|
|
// setUserSearch (ev.target.value) |
|
|
|
// |
|
|
|
// const q: string = ev.target.value.split (' ').at (-1) |
|
|
|
// if (!(q)) |
|
|
|
// { |
|
|
|
// // setSuggestions ([]) |
|
|
|
// return |
|
|
|
// } |
|
|
|
// } |
|
|
|
|
|
|
|
// const handleKeyDown = (ev: React.KeyboardEvent<HTMLInputElement>) => { |
|
|
|
// if (ev.key === 'Enter' && wikiSearch.length && (!(suggestionsVsbl) || activeIndex < 0)) |
|
|
|
// { |
|
|
|
// navigate (`/wiki/${ encodeURIComponent (wikiSearch) }`) |
|
|
|
// setSuggestionsVsbl (false) |
|
|
|
// } |
|
|
|
// } |
|
|
|
|
|
|
|
// const handleTagSelect = (tag: Tag) => { |
|
|
|
// } |
|
|
|
|
|
|
|
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 |
|
|
@@ -136,16 +87,18 @@ export default ({ user }: Props) => { |
|
|
|
return ( |
|
|
|
<> |
|
|
|
<nav className="px-3 flex justify-between items-center w-full min-h-[48px] |
|
|
|
bg-yellow-50 dark:bg-red-975"> |
|
|
|
bg-yellow-200 dark:bg-red-975 md:bg-yellow-50"> |
|
|
|
<div className="flex items-center gap-2 h-full"> |
|
|
|
<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 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> |
|
|
|
{menu.map (item => ( |
|
|
|
<Link to={item.to} |
|
|
|
className={cn ('h-full flex items-center', |
|
|
|
|
|
|
|
{menu.map ((item, i) => ( |
|
|
|
<Link key={i} |
|
|
|
to={item.to} |
|
|
|
className={cn ('hidden md:flex h-full items-center', |
|
|
|
(location.pathname.startsWith (item.base || item.to) |
|
|
|
? 'bg-yellow-200 dark:bg-red-950 px-4 font-bold' |
|
|
|
: 'px-2'))}> |
|
|
@@ -153,23 +106,83 @@ export default ({ user }: Props) => { |
|
|
|
</Link> |
|
|
|
))} |
|
|
|
</div> |
|
|
|
|
|
|
|
{user && ( |
|
|
|
<div className="ml-auto pr-4"> |
|
|
|
<div className="hidden md:block 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 || '名もなきニジラー'} |
|
|
|
</Link> |
|
|
|
</div>)} |
|
|
|
|
|
|
|
<a href="#" |
|
|
|
className="md:hidden ml-auto pr-4 |
|
|
|
text-pink-600 hover:text-pink-400 |
|
|
|
dark:text-pink-300 dark:hover:text-pink-100" |
|
|
|
onClick={ev => { |
|
|
|
ev.preventDefault () |
|
|
|
setMenuOpen (!(menuOpen)) |
|
|
|
}}> |
|
|
|
{menuOpen ? '×' : 'Menu'} |
|
|
|
</a> |
|
|
|
</nav> |
|
|
|
<div className={cn ('bg-yellow-200 dark:bg-red-950', |
|
|
|
'text-white px-3 flex items-center w-full min-h-[40px]')}> |
|
|
|
|
|
|
|
<div className="hidden md:flex bg-yellow-200 dark:bg-red-950 |
|
|
|
items-center w-full min-h-[40px]"> |
|
|
|
{menu.find (item => location.pathname.startsWith (item.base || item.to))?.subMenu |
|
|
|
.filter (item => item.visible ?? true) |
|
|
|
.map (item => 'component' in item ? item.component : ( |
|
|
|
<Link to={item.to} className="h-full flex items-center px-3"> |
|
|
|
.map ((item, i) => 'component' in item ? item.component : ( |
|
|
|
<Link key={i} |
|
|
|
to={item.to} |
|
|
|
className="h-full flex items-center px-3"> |
|
|
|
{item.name} |
|
|
|
</Link>))} |
|
|
|
</div> |
|
|
|
|
|
|
|
<div className={cn (menuOpen ? 'flex flex-col md:hidden' : 'hidden', |
|
|
|
'bg-yellow-200 dark:bg-red-975 items-start')}> |
|
|
|
<Separator /> |
|
|
|
{menu.map ((item, i) => ( |
|
|
|
<> |
|
|
|
<a key={i} |
|
|
|
href="#" |
|
|
|
className={cn ('w-full min-h-[40px] flex items-center pl-8', |
|
|
|
i === openItemIdx && 'font-bold bg-yellow-50 dark:bg-red-950')} |
|
|
|
onClick={ev => { |
|
|
|
ev.preventDefault () |
|
|
|
if (i === openItemIdx) |
|
|
|
{ |
|
|
|
setMenuOpen (false) |
|
|
|
navigate (item.to) |
|
|
|
} |
|
|
|
else |
|
|
|
setOpenItemIdx (i) |
|
|
|
}}> |
|
|
|
{item.name} |
|
|
|
</a> |
|
|
|
{i === openItemIdx && ( |
|
|
|
item.subMenu |
|
|
|
.filter (subItem => subItem.visible ?? true) |
|
|
|
.map ((subItem, j) => 'component' in subItem ? subItem.component : ( |
|
|
|
<Link key={j} |
|
|
|
to={subItem.to} |
|
|
|
className="w-full min-h-[36px] flex items-center pl-12 |
|
|
|
bg-yellow-50 dark:bg-red-950"> |
|
|
|
{subItem.name} |
|
|
|
</Link>)))} |
|
|
|
</>))} |
|
|
|
{user && ( |
|
|
|
<> |
|
|
|
<Separator /> |
|
|
|
<Link to="/users/settings" |
|
|
|
className="w-full min-h-[40px] flex items-center pl-8 |
|
|
|
font-bold text-red-600 hover:text-red-400 |
|
|
|
dark:text-yellow-400 dark:hover:text-yellow-200"> |
|
|
|
{user.name || '名もなきニジラー'} |
|
|
|
</Link> |
|
|
|
</>)} |
|
|
|
<Separator /> |
|
|
|
</div> |
|
|
|
</>) |
|
|
|
} |