mirror of https://gitee.com/answerdev/answer.git
189 lines
5.6 KiB
TypeScript
189 lines
5.6 KiB
TypeScript
import { FC, memo, useState, useEffect } from 'react';
|
|
import {
|
|
Navbar,
|
|
Container,
|
|
Nav,
|
|
Form,
|
|
FormControl,
|
|
Button,
|
|
Col,
|
|
} from 'react-bootstrap';
|
|
import { useTranslation } from 'react-i18next';
|
|
import {
|
|
useSearchParams,
|
|
NavLink,
|
|
Link,
|
|
useNavigate,
|
|
useLocation,
|
|
} from 'react-router-dom';
|
|
|
|
import { loggedUserInfoStore, siteInfoStore, brandingStore } from '@/stores';
|
|
import { logout, useQueryNotificationStatus } from '@/services';
|
|
import { RouteAlias } from '@/router/alias';
|
|
|
|
import NavItems from './components/NavItems';
|
|
|
|
import './index.scss';
|
|
|
|
const Header: FC = () => {
|
|
const navigate = useNavigate();
|
|
const { user, clear } = loggedUserInfoStore();
|
|
const { t } = useTranslation();
|
|
const [urlSearch] = useSearchParams();
|
|
const q = urlSearch.get('q');
|
|
const [searchStr, setSearch] = useState('');
|
|
const siteInfo = siteInfoStore((state) => state.siteInfo);
|
|
const brandingInfo = brandingStore((state) => state.branding);
|
|
const { data: redDot } = useQueryNotificationStatus();
|
|
const location = useLocation();
|
|
const handleInput = (val) => {
|
|
setSearch(val);
|
|
};
|
|
|
|
const handleLogout = async () => {
|
|
await logout();
|
|
clear();
|
|
navigate(RouteAlias.home);
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (q) {
|
|
handleInput(q);
|
|
}
|
|
}, [q]);
|
|
|
|
useEffect(() => {
|
|
const collapse = document.querySelector('#navBarContent');
|
|
if (collapse && collapse.classList.contains('show')) {
|
|
const toggle = document.querySelector('#navBarToggle') as HTMLElement;
|
|
if (toggle) {
|
|
toggle?.click();
|
|
}
|
|
}
|
|
}, [location.pathname]);
|
|
|
|
return (
|
|
<Navbar variant="dark" expand="lg" className="sticky-top" id="header">
|
|
<Container className="d-flex align-items-center">
|
|
<Navbar.Toggle
|
|
aria-controls="navBarContent"
|
|
className="answer-navBar me-2"
|
|
id="navBarToggle"
|
|
/>
|
|
|
|
<div className="d-flex justify-content-between align-items-center nav-grow flex-nowrap">
|
|
<Navbar.Brand to="/" as={Link} className="lh-1 me-0 me-sm-3">
|
|
{brandingInfo.logo ? (
|
|
<>
|
|
<img
|
|
className="d-none d-lg-block logo rounded-1 me-0"
|
|
src={brandingInfo.logo}
|
|
alt=""
|
|
/>
|
|
|
|
<img
|
|
className="lg-none logo rounded-1 me-0"
|
|
src={brandingInfo.mobile_logo || brandingInfo.logo}
|
|
alt=""
|
|
/>
|
|
</>
|
|
) : (
|
|
<span>{siteInfo.name || 'Answer'}</span>
|
|
)}
|
|
</Navbar.Brand>
|
|
|
|
{/* mobile nav */}
|
|
<div className="d-flex lg-none align-items-center flex-lg-nowrap">
|
|
{user?.username ? (
|
|
<NavItems redDot={redDot} userInfo={user} logOut={handleLogout} />
|
|
) : (
|
|
<>
|
|
<Button
|
|
variant="link"
|
|
className="me-2 text-white"
|
|
href="/users/login">
|
|
{t('btns.login')}
|
|
</Button>
|
|
<Button variant="light" href="/users/register">
|
|
{t('btns.signup')}
|
|
</Button>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
<Navbar.Collapse id="navBarContent" className="me-auto">
|
|
<hr className="hr lg-none mb-2" style={{ marginTop: '12px' }} />
|
|
<Col md={4}>
|
|
<Nav>
|
|
<NavLink className="nav-link" to="/questions">
|
|
{t('header.nav.question')}
|
|
</NavLink>
|
|
<NavLink className="nav-link" to="/tags">
|
|
{t('header.nav.tag')}
|
|
</NavLink>
|
|
</Nav>
|
|
</Col>
|
|
<hr className="hr lg-none mt-2" />
|
|
|
|
<Col lg={4} className="d-flex justify-content-center">
|
|
<Form action="/search" className="w-75 px-0 px-lg-2">
|
|
<FormControl
|
|
placeholder={t('header.search.placeholder')}
|
|
className="text-white placeholder-search"
|
|
value={searchStr}
|
|
name="q"
|
|
onChange={(e) => handleInput(e.target.value)}
|
|
/>
|
|
</Form>
|
|
</Col>
|
|
|
|
<Nav.Item className="lg-none mt-3 pb-1">
|
|
<Link
|
|
to="/questions/ask"
|
|
className="text-capitalize text-nowrap btn btn-light">
|
|
{t('btns.add_question')}
|
|
</Link>
|
|
</Nav.Item>
|
|
{/* pc nav */}
|
|
<Col
|
|
lg={4}
|
|
className="d-none d-lg-flex justify-content-start justify-content-sm-end">
|
|
{user?.username ? (
|
|
<Nav className="d-flex align-items-center flex-lg-nowrap">
|
|
<Nav.Item className="me-3">
|
|
<Link
|
|
to="/questions/ask"
|
|
className="text-capitalize text-nowrap btn btn-light">
|
|
{t('btns.add_question')}
|
|
</Link>
|
|
</Nav.Item>
|
|
|
|
<NavItems
|
|
redDot={redDot}
|
|
userInfo={user}
|
|
logOut={handleLogout}
|
|
/>
|
|
</Nav>
|
|
) : (
|
|
<>
|
|
<Button
|
|
variant="link"
|
|
className="me-2 text-white"
|
|
href="/users/login">
|
|
{t('btns.login')}
|
|
</Button>
|
|
<Button variant="light" href="/users/register">
|
|
{t('btns.signup')}
|
|
</Button>
|
|
</>
|
|
)}
|
|
</Col>
|
|
</Navbar.Collapse>
|
|
</Container>
|
|
</Navbar>
|
|
);
|
|
};
|
|
|
|
export default memo(Header);
|