-

+
+

+
-
- {match.partner.firstName && match.partner.lastName
- ? `${match.partner.firstName} ${match.partner.lastName}`
- : match.partner.username}
-
+
+
+ {match.partner.firstName && match.partner.lastName
+ ? `${match.partner.firstName} ${match.partner.lastName}`
+ : match.partner.username}
+
+
@{match.partner.username}
diff --git a/frontend/src/pages/PublicProfilePage.jsx b/frontend/src/pages/PublicProfilePage.jsx
index 402fb8d..3b6b5ed 100644
--- a/frontend/src/pages/PublicProfilePage.jsx
+++ b/frontend/src/pages/PublicProfilePage.jsx
@@ -1,14 +1,16 @@
import { useState, useEffect } from 'react';
import { useParams, Link } from 'react-router-dom';
-import { authAPI } from '../services/api';
+import { authAPI, ratingsAPI } from '../services/api';
import Layout from '../components/layout/Layout';
-import { User, MapPin, Globe, Hash, Youtube, Instagram, Facebook, Award, Users, Star, Calendar, Loader2, AlertCircle } from 'lucide-react';
+import { User, MapPin, Globe, Hash, Youtube, Instagram, Facebook, Award, Users, Star, Calendar, Loader2, AlertCircle, ThumbsUp } from 'lucide-react';
const PublicProfilePage = () => {
const { username } = useParams();
const [profile, setProfile] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
+ const [ratings, setRatings] = useState(null);
+ const [ratingsLoading, setRatingsLoading] = useState(true);
useEffect(() => {
const fetchProfile = async () => {
@@ -26,6 +28,22 @@ const PublicProfilePage = () => {
fetchProfile();
}, [username]);
+ useEffect(() => {
+ const fetchRatings = async () => {
+ try {
+ setRatingsLoading(true);
+ const data = await ratingsAPI.getUserRatings(username);
+ setRatings(data.data);
+ } catch (err) {
+ console.error('Failed to load ratings:', err);
+ } finally {
+ setRatingsLoading(false);
+ }
+ };
+
+ fetchRatings();
+ }, [username]);
+
if (loading) {
return (
@@ -150,7 +168,7 @@ const PublicProfilePage = () => {
{/* Social Media Links */}
{(profile.youtubeUrl || profile.instagramUrl || profile.facebookUrl || profile.tiktokUrl) && (
-
+
Social Media
{profile.youtubeUrl && (
@@ -202,6 +220,118 @@ const PublicProfilePage = () => {
)}
+
+ {/* Ratings Section */}
+
+
+
+ Reviews
+
+
+ {ratingsLoading ? (
+
+
+
+ ) : ratings && ratings.ratings.length > 0 ? (
+
+ {/* Summary */}
+
+
+
{ratings.averageRating}
+
+ {[1, 2, 3, 4, 5].map((star) => (
+
+ ))}
+
+
+
+ Based on {ratings.ratingsCount} {ratings.ratingsCount === 1 ? 'review' : 'reviews'}
+
+
+
+ {/* Individual Ratings */}
+
+ {ratings.ratings.map((rating) => (
+
+
+ {/* Rater Info */}
+
+

+
+
+
+ {/* Rater Name and Stars */}
+
+
+
+ {rating.rater.firstName && rating.rater.lastName
+ ? `${rating.rater.firstName} ${rating.rater.lastName}`
+ : rating.rater.username}
+
+
@{rating.rater.username}
+
+
+ {[1, 2, 3, 4, 5].map((star) => (
+
+ ))}
+
+
+
+ {/* Comment */}
+ {rating.comment && (
+
{rating.comment}
+ )}
+
+ {/* Would Collaborate Again */}
+ {rating.wouldCollaborateAgain && (
+
+
+ Would collaborate again
+
+ )}
+
+ {/* Event and Date */}
+
+
+ {rating.event.name}
+
+ •
+ {new Date(rating.createdAt).toLocaleDateString()}
+
+
+
+
+ ))}
+
+
+ ) : (
+
No reviews yet
+ )}
+