130 lines
5.1 KiB
JavaScript
130 lines
5.1 KiB
JavaScript
import { useState } from "react";
|
|
import LogoIcon from "./icons/LogoIcon";
|
|
import {NAV_BOTTOM, NAV_ITEMS} from "../config/feedConstants";
|
|
import {NavIcons} from "./icons/NavIcons";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { useTheme } from "../context/ThemeContext";
|
|
import { useUnread } from "../context/UnreadContext";
|
|
import { useTranslation } from 'react-i18next';
|
|
import SupportModal from "./SupportModal";
|
|
|
|
export default function Sidebar({
|
|
open,
|
|
activeNav,
|
|
onClose,
|
|
onNavClick,
|
|
isAuthenticated,
|
|
onLoginClick,
|
|
onRulesClick,
|
|
onReviewsClick,
|
|
}) {
|
|
const navigate = useNavigate();
|
|
const { theme, toggle: toggleTheme } = useTheme();
|
|
const { totalUnread } = useUnread();
|
|
const { t, i18n } = useTranslation();
|
|
const [supportOpen, setSupportOpen] = useState(false);
|
|
|
|
const toggleLang = () => {
|
|
const next = i18n.language === 'ru' ? 'en' : 'ru';
|
|
i18n.changeLanguage(next);
|
|
localStorage.setItem('i18nextLng', next);
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<div className={`f-overlay${open ? " show" : ""}`} onClick={onClose} />
|
|
<div className={`f-sidebar${open ? " open" : ""}`}>
|
|
<div className="f-sb-head">
|
|
<div className="f-sb-logo"><LogoIcon /></div>
|
|
<span className="f-sb-name">{t('app.name')}</span>
|
|
</div>
|
|
<nav className="f-sb-nav">
|
|
{NAV_ITEMS.map(({ icon, key: itemKey, labelKey }) => {
|
|
const Ic = NavIcons[icon];
|
|
const handleClick = () => {
|
|
// «Мои объявления» требует авторизации
|
|
if (!isAuthenticated && itemKey === "myads") {
|
|
onLoginClick();
|
|
} else if (itemKey === "chat") {
|
|
if (!isAuthenticated) {
|
|
onLoginClick();
|
|
} else {
|
|
navigate("/chats");
|
|
}
|
|
} else {
|
|
onNavClick(itemKey);
|
|
}
|
|
onClose();
|
|
};
|
|
return (
|
|
<div
|
|
key={itemKey}
|
|
className={`f-sb-item${activeNav === itemKey ? " active" : ""}`}
|
|
onClick={handleClick}
|
|
>
|
|
<Ic /> {t(labelKey)}
|
|
{itemKey === "chat" && totalUnread > 0 && (
|
|
<span className="f-sb-unread-badge">{totalUnread > 99 ? "99+" : totalUnread}</span>
|
|
)}
|
|
</div>
|
|
);
|
|
})}
|
|
</nav>
|
|
<div className="f-sb-bottom">
|
|
{NAV_BOTTOM.map(({ icon, key: itemKey, labelKey }) => {
|
|
const Ic = NavIcons[icon];
|
|
const handleBottomClick = () => {
|
|
if (itemKey === "rules") {
|
|
onRulesClick?.();
|
|
onClose();
|
|
return;
|
|
}
|
|
if (itemKey === "reviews") {
|
|
onReviewsClick?.();
|
|
onClose();
|
|
return;
|
|
}
|
|
onNavClick(itemKey);
|
|
onClose();
|
|
};
|
|
return (
|
|
<div
|
|
key={itemKey}
|
|
className={`f-sb-item${activeNav === itemKey ? " active" : ""}`}
|
|
onClick={handleBottomClick}
|
|
>
|
|
<Ic /> {t(labelKey)}
|
|
</div>
|
|
);
|
|
})}
|
|
<div className="f-sb-item" onClick={() => setSupportOpen(true)}>
|
|
<NavIcons.help /> {t('nav.support')}
|
|
</div>
|
|
<div className="f-sb-divider" />
|
|
<div className="f-sb-item f-sb-theme-toggle" onClick={toggleTheme}>
|
|
{theme === "dark" ? (
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
<circle cx="12" cy="12" r="5"/>
|
|
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
|
|
</svg>
|
|
) : (
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
|
</svg>
|
|
)}
|
|
{theme === "dark" ? t('sidebar.lightTheme') : t('sidebar.darkTheme')}
|
|
</div>
|
|
<div className="f-sb-item f-sb-lang-toggle" onClick={toggleLang}>
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
<circle cx="12" cy="12" r="10"/>
|
|
<path d="M2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/>
|
|
</svg>
|
|
{i18n.language === 'ru' ? 'English' : 'Русский'}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{supportOpen && <SupportModal onClose={() => setSupportOpen(false)} />}
|
|
</>
|
|
);
|
|
}
|