| 
				
				
				
				 | 
			
			 | 
			@@ -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> | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			      </>) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			} |