Files
meet-hub/src/components/reviews/TestimonialsSection.tsx
dwindown a824e101ed Use live profile data for reviews instead of frozen reviewer_name
Changes:
- Revert to using profiles!user_id (name, avatar_url) JOIN for reviews
- Remove reviewer_name storage from ReviewModal (no longer needed)
- Add avatar display to ReviewCard component
- Reviews now sync automatically with profile changes
- Public queries safely expose only name + avatar via RLS

This ensures:
- Name/avatar changes update across all reviews automatically
- No frozen/outdated reviewer data
- Only public profile fields exposed (secure)
- Reviews serve as live, credible social proof

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 15:39:58 +07:00

57 lines
1.5 KiB
TypeScript

import { useEffect, useState } from 'react';
import { supabase } from '@/integrations/supabase/client';
import { ReviewCard } from './ReviewCard';
interface Review {
id: string;
rating: number;
title: string;
body: string;
created_at: string;
profiles: { name: string | null; avatar_url: string | null } | null;
}
export function TestimonialsSection() {
const [reviews, setReviews] = useState<Review[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchReviews();
}, []);
const fetchReviews = async () => {
const { data } = await supabase
.from('reviews')
.select('id, rating, title, body, created_at, profiles!user_id (name, avatar_url)')
.eq('is_approved', true)
.order('created_at', { ascending: false })
.limit(6);
if (data) {
setReviews(data as unknown as Review[]);
}
setLoading(false);
};
if (loading || reviews.length === 0) return null;
return (
<section className="container mx-auto px-4 py-16">
<h2 className="text-3xl font-bold text-center mb-8">Apa Kata Mereka</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{reviews.map((review) => (
<ReviewCard
key={review.id}
rating={review.rating}
title={review.title}
body={review.body}
authorName={review.profiles?.name || 'Anonymous'}
authorAvatar={review.profiles?.avatar_url}
date={review.created_at}
/>
))}
</div>
</section>
);
}