import { useState, useEffect, useMemo, useRef } from "react"; import { useNavigate } from "react-router-dom"; import { getImageUrl } from "../config/authConstants"; import { useAuthContext } from "../context/AuthContext"; import Sidebar from "../components/Sidebar"; import AppTopBar from "../components/layout/AppTopBar"; import { ProfileModal } from "../components/profile"; import AuthModal from "../components/AuthModal"; import RulesModal from "./RulesModal"; import ReviewCard from "../components/reviews/ReviewCard"; import ReviewForm from "../components/reviews/ReviewForm"; import RatingSummary from "../components/reviews/RatingSummary"; import { useReviews } from "../hooks/useReviews"; import "../styles/reviews.css"; import { useTranslation } from 'react-i18next'; import { useProfile } from "../hooks/useProfile"; export default function ReviewsPage() { const { t } = useTranslation(); const navigate = useNavigate(); const { user, token, isAuthenticated, updateUser } = useAuthContext(); const { fetchProfile } = useProfile(); const [sidebarOpen, setSidebarOpen] = useState(false); const [profileModalOpen, setProfileModalOpen] = useState(false); const [authModalOpen, setAuthModalOpen] = useState(false); const [rulesModalOpen, setRulesModalOpen] = useState(false); const profileFetchedFor = useRef(null); const profileData = useMemo(() => { if (!user) return {}; const nameParts = (user.name || "").trim().split(/\s+/); return { login: user.login || "", firstName: user.firstName || nameParts[0] || "", lastName: user.lastName || nameParts.slice(1).join(" ") || "", email: user.email || "", phone: user.phone || "", avatar: getImageUrl(user.avatar), id: user.id, }; }, [user]); const { reviews, loading, error, submitting, submitError, loadReviews, submitReview, avgRating, distribution, } = useReviews({ token, isAuthenticated, onAuthRequired: () => setAuthModalOpen(true), authorFallbackName: profileData.firstName || t('reviews.you'), }); useEffect(() => { loadReviews(); }, [loadReviews]); // При загрузке страницы подтягиваем свежие данные профиля (аватар и т.д.) // с бэка, чтобы навигация отражала изменения с других устройств, а не кэш. // Дергаем один раз на пользователя. useEffect(() => { if (isAuthenticated && user?.id && profileFetchedFor.current !== user.id) { profileFetchedFor.current = user.id; fetchProfile(user.id).then(result => { if (result.success) updateUser(result.data); }); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [isAuthenticated, user?.id]); // При открытии профиля подтягиваем свежие данные (аватар/профиль) с бэка, // чтобы изменения с других устройств отражались, а не брались из кэша контекста useEffect(() => { if (profileModalOpen && isAuthenticated && user?.id) { fetchProfile(user.id).then(result => { if (result.success) updateUser(result.data); }); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [profileModalOpen, isAuthenticated, user?.id]); return (
setSidebarOpen(false)} onNavClick={(key) => navigate("/feed")} isAuthenticated={isAuthenticated} onLoginClick={() => setAuthModalOpen(true)} onRulesClick={() => setRulesModalOpen(true)} onCreatePost={() => navigate("/feed")} onProfileClick={() => setProfileModalOpen(true)} profileData={profileData} />
setSidebarOpen((v) => !v)} isAuthenticated={isAuthenticated} profileData={profileData} onProfileClick={() => setProfileModalOpen(true)} onLoginClick={() => setAuthModalOpen(true)} loginLabel={t('reviews.login')} centerContent={

{t('reviews.title')}

} hideWordmark />
{isAuthenticated ? ( <> {submitError && (
{t('reviews.submitError')}
)} ) : (

{t('reviews.loginPrompt')}

)}
{loading ? (
{t('reviews.loading')}
) : error && reviews.length === 0 ? (
💬
{t('reviews.emptyTitle')}
{t('reviews.emptySub')}
) : ( reviews.map((review) => ) )}
{profileModalOpen && isAuthenticated && ( setProfileModalOpen(false)} initialData={profileData} /> )} {authModalOpen && setAuthModalOpen(false)} />} {rulesModalOpen && setRulesModalOpen(false)} />}
); }