Files
open.neuroinf.jp/src/custom/Header.tsx
T
orrisroot e93014bcea feat: migrate from Create React App to Vite
Rebuild the site on the stack the other converted sites share: Vite 8,
React 19, TypeScript 7, react-router 8, Biome and sanitize.css, with the
site data moved out of the bundle into static-contents/.

- base the database and pico code on the other converted sites,
  keeping this site's layout, pages and item fields
- read file timestamps as Unix seconds in the file and license views
- serve all module data from modules/, redirecting the old download and
  /database/file URLs
- keep form controls on white
- track page views with GA4
2026-09-14 17:38:48 +09:00

98 lines
3.9 KiB
TypeScript

import { type FormEvent, useState } from 'react';
import { Link, useNavigate } from 'react-router';
import SelectLang from '../common/blocks/SelectLang';
import Config, { type MultiLang } from '../config';
import ItemUtil from '../database/lib/ItemUtil';
import Functions from '../functions';
interface Props {
lang: MultiLang;
}
const Header = (props: Props) => {
const { lang } = props;
const navigate = useNavigate();
const [keyword, setKeyword] = useState('');
const [showCreditsMenu, setShowCreditsMenu] = useState(false);
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
const trimmed = keyword.trim();
if (trimmed !== '') {
void navigate(ItemUtil.getSearchByKeywordUrl('all', trimmed));
}
};
return (
<header className="header">
<div className="clearfix">
<Link className="logo" to="/">
<span className="hidden">{Config.SITE_TITLE}</span>
</Link>
<div className="utility">
<SelectLang lang={lang} />
<div className="clearfix">
<a
className="incf-japan-node"
href="https://www.neuroinf.jp/"
target="_blank"
rel="noopener noreferrer"
>
<span className="hidden">INCF Japan Node</span>
</a>
<div className="search-box">
<form onSubmit={handleSubmit}>
<input
type="text"
value={keyword}
onChange={(e) => setKeyword(e.target.value)}
placeholder="enter keywords here..."
/>
</form>
</div>
</div>
</div>
</div>
<ul className="mainmenu">
<li>
<Link to="/database/search/itemtype/binder">
{Functions.mlang('[en]Contents[/en][ja]コンテンツ[/ja]', lang)}
</Link>
</li>
<li>
<Link to="/categories">
{Functions.mlang('[en]Categories[/en][ja]カテゴリから検索[/ja]', lang)}
</Link>
</li>
<li>
<Link to="/overview">{Functions.mlang('[en]Overview[/en][ja]概要[/ja]', lang)}</Link>
</li>
<li>
<Link to="/news">{Functions.mlang('[en]News[/en][ja]ニュース[/ja]', lang)}</Link>
</li>
<li onMouseEnter={() => setShowCreditsMenu(true)} onMouseLeave={() => setShowCreditsMenu(false)}>
{Functions.mlang('[en]Credits[/en][ja]サイト情報[/ja]', lang)}
{showCreditsMenu && (
<div className="submenu">
<Link className="item" to="/credits/1">
Instruction for Use
</Link>
<Link className="item" to="/credits/2">
Copyrights
</Link>
<Link className="item" to="/credits/3">
Privacy Policy
</Link>
<Link className="item" to="/credits/4">
About Us
</Link>
</div>
)}
</li>
</ul>
</header>
);
};
export default Header;