132 lines
5.0 KiB
JavaScript
132 lines
5.0 KiB
JavaScript
import { useState, useEffect, useMemo } 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';
|
|
|
|
export default function ReviewsPage() {
|
|
const { t } = useTranslation();
|
|
const navigate = useNavigate();
|
|
const { user, token, isAuthenticated } = useAuthContext();
|
|
|
|
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
const [profileModalOpen, setProfileModalOpen] = useState(false);
|
|
const [authModalOpen, setAuthModalOpen] = useState(false);
|
|
const [rulesModalOpen, setRulesModalOpen] = useState(false);
|
|
|
|
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]);
|
|
|
|
return (
|
|
<div className="f-app">
|
|
<Sidebar
|
|
open={sidebarOpen}
|
|
activeNav="reviews"
|
|
onClose={() => setSidebarOpen(false)}
|
|
onNavClick={(key) => navigate("/feed")}
|
|
isAuthenticated={isAuthenticated}
|
|
onLoginClick={() => setAuthModalOpen(true)}
|
|
onRulesClick={() => setRulesModalOpen(true)}
|
|
onCreatePost={() => navigate("/feed")}
|
|
onProfileClick={() => setProfileModalOpen(true)}
|
|
profileData={profileData}
|
|
/>
|
|
|
|
<div className="f-main">
|
|
<AppTopBar
|
|
onMenuClick={() => setSidebarOpen((v) => !v)}
|
|
isAuthenticated={isAuthenticated}
|
|
profileData={profileData}
|
|
onProfileClick={() => setProfileModalOpen(true)}
|
|
onLoginClick={() => setAuthModalOpen(true)}
|
|
loginLabel={t('reviews.login')}
|
|
centerContent={<h1 className="rv-page-title">{t('reviews.title')}</h1>}
|
|
/>
|
|
|
|
<div className="rv-layout">
|
|
<div className="rv-sidebar">
|
|
<RatingSummary
|
|
avgRating={avgRating}
|
|
totalCount={reviews.length}
|
|
distribution={distribution}
|
|
/>
|
|
|
|
{isAuthenticated ? (
|
|
<>
|
|
<ReviewForm onSubmit={submitReview} submitting={submitting} />
|
|
{submitError && (
|
|
<div className="rv-form-error">{t('reviews.submitError')}</div>
|
|
)}
|
|
</>
|
|
) : (
|
|
<div className="rv-login-prompt">
|
|
<p>{t('reviews.loginPrompt')}</p>
|
|
<button className="rv-login-btn" onClick={() => setAuthModalOpen(true)}>
|
|
{t('reviews.login')}
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="rv-list">
|
|
{loading ? (
|
|
<div className="f-center">
|
|
<div className="f-spinner-wrap">
|
|
<div className="f-spinner" />
|
|
{t('reviews.loading')}
|
|
</div>
|
|
</div>
|
|
) : error && reviews.length === 0 ? (
|
|
<div className="f-center">
|
|
<div className="f-center-icon">💬</div>
|
|
<div className="f-center-title">{t('reviews.emptyTitle')}</div>
|
|
<div className="f-center-sub">{t('reviews.emptySub')}</div>
|
|
</div>
|
|
) : (
|
|
reviews.map((review) => <ReviewCard key={review.id} review={review} />)
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{profileModalOpen && isAuthenticated && (
|
|
<ProfileModal onClose={() => setProfileModalOpen(false)} initialData={profileData} />
|
|
)}
|
|
{authModalOpen && <AuthModal onClose={() => setAuthModalOpen(false)} />}
|
|
{rulesModalOpen && <RulesModal onClose={() => setRulesModalOpen(false)} />}
|
|
</div>
|
|
);
|
|
} |