Fix review system: display real names and check approval status

Changes:
- ProductReviews.tsx: Use LEFT JOIN and fetch reviewer_name field
- ReviewModal.tsx: Store reviewer_name at submission time
- ProductDetail.tsx: Check is_approved=true in checkUserReview()
- Add migration for reviewer_name column and approval index

This fixes two issues:
1. Reviews now show real account names instead of "Anonymous"
2. Members no longer see "menunggu moderasi" after approval

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
dwindown
2025-12-25 22:29:48 +07:00
parent 466cca5cb4
commit e347a780f8
4 changed files with 31 additions and 5 deletions

View File

@@ -9,6 +9,7 @@ interface Review {
title: string; title: string;
body: string; body: string;
created_at: string; created_at: string;
reviewer_name: string | null;
profiles: { name: string | null } | null; profiles: { name: string | null } | null;
} }
@@ -29,7 +30,7 @@ export function ProductReviews({ productId, type }: ProductReviewsProps) {
const fetchReviews = async () => { const fetchReviews = async () => {
let query = supabase let query = supabase
.from('reviews') .from('reviews')
.select('id, rating, title, body, created_at, profiles:user_id (name)') .select('id, rating, title, body, created_at, reviewer_name, profiles!user_id (name)')
.eq('is_approved', true); .eq('is_approved', true);
if (productId) { if (productId) {
@@ -74,7 +75,7 @@ export function ProductReviews({ productId, type }: ProductReviewsProps) {
rating={review.rating} rating={review.rating}
title={review.title} title={review.title}
body={review.body} body={review.body}
authorName={review.profiles?.name || 'Anonymous'} authorName={review.reviewer_name || review.profiles?.name || 'Anonymous'}
date={review.created_at} date={review.created_at}
/> />
))} ))}

View File

@@ -1,4 +1,4 @@
import { useState } from 'react'; import { useState, useEffect } from 'react';
import { supabase } from '@/integrations/supabase/client'; import { supabase } from '@/integrations/supabase/client';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
@@ -33,6 +33,22 @@ export function ReviewModal({
const [title, setTitle] = useState(''); const [title, setTitle] = useState('');
const [body, setBody] = useState(''); const [body, setBody] = useState('');
const [submitting, setSubmitting] = useState(false); const [submitting, setSubmitting] = useState(false);
const [userName, setUserName] = useState<string | null>(null);
useEffect(() => {
const fetchUserName = async () => {
if (!userId) return;
const { data } = await supabase
.from('profiles')
.select('name')
.eq('id', userId)
.single();
if (data?.name) {
setUserName(data.name);
}
};
fetchUserName();
}, [userId]);
const handleSubmit = async () => { const handleSubmit = async () => {
if (rating === 0) { if (rating === 0) {
@@ -54,6 +70,7 @@ export function ReviewModal({
title: title.trim(), title: title.trim(),
body: body.trim() || null, body: body.trim() || null,
is_approved: false, is_approved: false,
reviewer_name: userName || null,
}); });
if (error) { if (error) {

View File

@@ -162,14 +162,15 @@ export default function ProductDetail() {
const checkUserReview = async () => { const checkUserReview = async () => {
if (!product || !user) return; if (!product || !user) return;
const { data } = await supabase const { data } = await supabase
.from('reviews') .from('reviews')
.select('id') .select('id')
.eq('user_id', user.id) .eq('user_id', user.id)
.eq('product_id', product.id) .eq('product_id', product.id)
.eq('is_approved', true)
.limit(1); .limit(1);
setHasReviewed(!!(data && data.length > 0)); setHasReviewed(!!(data && data.length > 0));
}; };

View File

@@ -0,0 +1,7 @@
-- Add reviewer_name column to store display name at submission time
-- This ensures reviews always show the author's name even if profile is deleted later
ALTER TABLE reviews
ADD COLUMN reviewer_name TEXT;
-- Create index for efficient approval status queries
CREATE INDEX idx_reviews_is_approved ON reviews(is_approved);