Files
nahodka-front/src/components/Sidebar.jsx
2026-10-02 01:50:42 +03:00

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