214 lines
7.7 KiB
JavaScript
214 lines
7.7 KiB
JavaScript
import { useState } from "react";
|
|
import GlobeIcon from "./icons/GlobeIcon";
|
|
import SunIcon from "./icons/SunIcon";
|
|
import MoonIcon from "./icons/MoonIcon";
|
|
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 { useLanguageToggle } from "../hooks/useLanguageToggle";
|
|
import { useTranslation } from 'react-i18next';
|
|
import { useAuthContext } from "../context/AuthContext";
|
|
import { useIsDesktop } from "../hooks/useIsDesktop";
|
|
import SupportModal from "./SupportModal";
|
|
import UploadAdModal from "./UploadAdModal";
|
|
import ProfileAvatar from "./profile/ProfileAvatar";
|
|
import NahodkaLogo from "./MainNahodkaLogo";
|
|
|
|
export default function Sidebar({
|
|
open,
|
|
activeNav,
|
|
onClose,
|
|
onNavClick,
|
|
onLogoClick,
|
|
isAuthenticated,
|
|
onLoginClick,
|
|
onRulesClick,
|
|
onReviewsClick,
|
|
onCreatePost,
|
|
onProfileClick,
|
|
profileData,
|
|
}) {
|
|
const navigate = useNavigate();
|
|
const { isAdmin } = useAuthContext();
|
|
// Админ-пункты (реклама) показываем только в десктоп-раскладке:
|
|
// на мобильном их не должно быть вообще (ни в drawer-меню).
|
|
const isDesktop = useIsDesktop();
|
|
const { theme, toggle: toggleTheme } = useTheme();
|
|
const { totalUnread } = useUnread();
|
|
const { t } = useTranslation();
|
|
const { language, toggleLanguage } = useLanguageToggle();
|
|
const [supportOpen, setSupportOpen] = useState(false);
|
|
const [uploadAdOpen, setUploadAdOpen] = useState(false);
|
|
const HelpIcon = NavIcons.help;
|
|
|
|
const handleNavItem = (itemKey) => {
|
|
if (!isAuthenticated && itemKey === "myads") {
|
|
onLoginClick();
|
|
return;
|
|
}
|
|
if (itemKey === "chat") {
|
|
if (!isAuthenticated) {
|
|
onLoginClick();
|
|
} else {
|
|
navigate("/chats");
|
|
}
|
|
return;
|
|
}
|
|
if (itemKey === "create") {
|
|
onCreatePost?.();
|
|
return;
|
|
}
|
|
onNavClick(itemKey);
|
|
};
|
|
|
|
const handleProfileClick = () => {
|
|
if (!isAuthenticated) {
|
|
onLoginClick();
|
|
} else {
|
|
onProfileClick?.();
|
|
}
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<div className={`f-overlay${open ? " show" : ""}`} onClick={onClose} />
|
|
<div className={`f-sidebar${open ? " open" : ""}`}>
|
|
<div className="f-sb-head">
|
|
<button
|
|
type="button"
|
|
className="f-sb-logo-btn"
|
|
onClick={() => {
|
|
onLogoClick?.();
|
|
onClose();
|
|
}}
|
|
title={t('nav.home')}
|
|
>
|
|
<NahodkaLogo />
|
|
</button>
|
|
</div>
|
|
<nav className="f-sb-nav">
|
|
{NAV_ITEMS.map(({ icon, key: itemKey, labelKey }) => {
|
|
const Ic = NavIcons[icon];
|
|
return (
|
|
<button
|
|
type="button"
|
|
key={itemKey}
|
|
className={`f-sb-item${activeNav === itemKey ? " active" : ""}${itemKey === "create" ? " f-sb-create" : ""}`}
|
|
onClick={() => {
|
|
handleNavItem(itemKey);
|
|
onClose();
|
|
}}
|
|
>
|
|
<Ic /> {t(labelKey)}
|
|
{itemKey === "chat" && totalUnread > 0 && (
|
|
<span className="f-sb-unread-badge">{totalUnread > 99 ? "99+" : totalUnread}</span>
|
|
)}
|
|
</button>
|
|
);
|
|
})}
|
|
{isAdmin && isDesktop && (
|
|
<>
|
|
<div className="f-sb-divider" />
|
|
<button
|
|
type="button"
|
|
className="f-sb-item"
|
|
onClick={() => {
|
|
setUploadAdOpen(true);
|
|
onClose();
|
|
}}
|
|
>
|
|
{NavIcons.megaphone()} {t('admin.uploadAd')}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
className={`f-sb-item${activeNav === "admin-campaigns" ? " active" : ""}`}
|
|
onClick={() => {
|
|
navigate("/admin/ads");
|
|
onClose();
|
|
}}
|
|
>
|
|
{NavIcons.grid()} {t('adminPanel.campaignsNav')}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
className={`f-sb-item${activeNav === "admin-posts" ? " active" : ""}`}
|
|
onClick={() => {
|
|
navigate("/admin/ads?tab=posts");
|
|
onClose();
|
|
}}
|
|
>
|
|
{NavIcons.rules()} {t('adminPanel.postsNav')}
|
|
</button>
|
|
</>
|
|
)}
|
|
</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 (
|
|
<button
|
|
type="button"
|
|
key={itemKey}
|
|
className={`f-sb-item${activeNav === itemKey ? " active" : ""}`}
|
|
onClick={handleBottomClick}
|
|
>
|
|
<Ic /> {t(labelKey)}
|
|
</button>
|
|
);
|
|
})}
|
|
<button type="button" className="f-sb-item" onClick={() => setSupportOpen(true)}>
|
|
<HelpIcon /> {t('nav.support')} </button>
|
|
<div className="f-sb-divider" />
|
|
<button type="button" className="f-sb-item" onClick={toggleTheme}>
|
|
{theme === "dark" ? <SunIcon /> : <MoonIcon />}
|
|
{theme === "dark" ? t('sidebar.lightTheme') : t('sidebar.darkTheme')}
|
|
</button>
|
|
<button type="button" className="f-sb-item" onClick={toggleLanguage}>
|
|
<GlobeIcon />
|
|
{language === 'ru' ? 'English' : 'Русский'}
|
|
</button>
|
|
<div className="f-sb-divider" />
|
|
<button type="button" className="f-sb-profile" onClick={handleProfileClick}>
|
|
{isAuthenticated ? (
|
|
<ProfileAvatar
|
|
avatar={profileData?.avatar}
|
|
name={`${profileData?.firstName || ""} ${profileData?.lastName || ""}`}
|
|
/>
|
|
) : (
|
|
<div className="f-profile-avatar-placeholder">👤</div>
|
|
)}
|
|
<div className="f-sb-profile-info">
|
|
<div className="f-sb-profile-name">
|
|
{isAuthenticated
|
|
? `${profileData?.firstName || ""} ${profileData?.lastName || ""}`.trim() || profileData?.login
|
|
: t('feed.login')}
|
|
</div>
|
|
<div className="f-sb-profile-login">
|
|
{isAuthenticated ? profileData?.login || t('profile.default') : t('auth.noAccount')}
|
|
</div>
|
|
</div>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
{supportOpen && <SupportModal onClose={() => setSupportOpen(false)} />}
|
|
{uploadAdOpen && <UploadAdModal onClose={() => setUploadAdOpen(false)} />}
|
|
</>
|
|
);
|
|
}
|