mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-23 22:31:12 -05:00
Refactor code structure and remove redundant changes
This commit is contained in:
204
src-old/components/reviews/ReviewsList.tsx
Normal file
204
src-old/components/reviews/ReviewsList.tsx
Normal file
@@ -0,0 +1,204 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { UserAvatar } from '@/components/ui/user-avatar';
|
||||
import { Star, ThumbsUp, Calendar, MapPin } from 'lucide-react';
|
||||
import { supabase } from '@/lib/supabaseClient';
|
||||
import { ReportButton } from '@/components/moderation/ReportButton';
|
||||
import { StarRating } from './StarRating';
|
||||
import { getErrorMessage, handleNonCriticalError } from '@/lib/errorHandler';
|
||||
|
||||
interface ReviewWithProfile {
|
||||
id: string;
|
||||
user_id: string;
|
||||
park_id: string | null;
|
||||
ride_id: string | null;
|
||||
rating: number;
|
||||
title: string | null;
|
||||
content: string | null;
|
||||
visit_date: string | null;
|
||||
wait_time_minutes: number | null;
|
||||
helpful_votes: number;
|
||||
total_votes: number;
|
||||
moderation_status: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
profiles?: {
|
||||
username: string;
|
||||
avatar_url: string | null;
|
||||
display_name: string | null;
|
||||
} | null;
|
||||
}
|
||||
|
||||
interface ReviewsListProps {
|
||||
entityType: 'park' | 'ride';
|
||||
entityId: string;
|
||||
entityName: string;
|
||||
}
|
||||
|
||||
export function ReviewsList({ entityType, entityId, entityName }: ReviewsListProps) {
|
||||
const [reviews, setReviews] = useState<ReviewWithProfile[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
fetchReviews();
|
||||
}, [entityType, entityId]);
|
||||
|
||||
const fetchReviews = async () => {
|
||||
try {
|
||||
const query = supabase
|
||||
.from('reviews')
|
||||
.select(`
|
||||
*,
|
||||
profiles!reviews_user_id_fkey(username, avatar_url, display_name)
|
||||
`)
|
||||
.eq('moderation_status', 'approved')
|
||||
.order('created_at', { ascending: false });
|
||||
|
||||
if (entityType === 'park') {
|
||||
query.eq('park_id', entityId);
|
||||
} else {
|
||||
query.eq('ride_id', entityId);
|
||||
}
|
||||
|
||||
const { data } = await query;
|
||||
setReviews((data || []) as ReviewWithProfile[]);
|
||||
} catch (error: unknown) {
|
||||
handleNonCriticalError(error, {
|
||||
action: 'Fetch reviews',
|
||||
metadata: { entityType, entityId }
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const renderStars = (rating: number) => {
|
||||
return <StarRating rating={rating} size="sm" />;
|
||||
};
|
||||
|
||||
const formatDate = (dateString: string) => {
|
||||
return new Date(dateString).toLocaleDateString('en-US', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric'
|
||||
});
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
{Array.from({ length: 3 }, (_, i) => (
|
||||
<Card key={i} className="animate-pulse">
|
||||
<CardContent className="p-6">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="w-12 h-12 bg-muted rounded-full"></div>
|
||||
<div className="flex-1 space-y-2">
|
||||
<div className="h-4 bg-muted rounded w-1/4"></div>
|
||||
<div className="h-4 bg-muted rounded w-1/6"></div>
|
||||
<div className="h-20 bg-muted rounded"></div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (reviews.length === 0) {
|
||||
return (
|
||||
<div className="text-center py-12">
|
||||
<Star className="w-16 h-16 text-muted-foreground mx-auto mb-4" />
|
||||
<h3 className="text-xl font-semibold mb-2">No Reviews Yet</h3>
|
||||
<p className="text-muted-foreground">
|
||||
Be the first to share your experience with {entityName}!
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="text-lg font-semibold">
|
||||
{reviews.length} Review{reviews.length !== 1 ? 's' : ''}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
{reviews.map((review) => (
|
||||
<Card key={review.id}>
|
||||
<CardContent className="p-6">
|
||||
<div className="flex items-start gap-4">
|
||||
<UserAvatar
|
||||
key={review.profiles?.avatar_url || `review-${review.id}`}
|
||||
avatarUrl={review.profiles?.avatar_url}
|
||||
fallbackText={review.profiles?.display_name || review.profiles?.username || 'U'}
|
||||
size="lg"
|
||||
className="w-12 h-12"
|
||||
/>
|
||||
|
||||
<div className="flex-1 space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<div className="font-medium">
|
||||
{review.profiles?.display_name || review.profiles?.username || 'Anonymous User'}
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<Calendar className="w-3 h-3" />
|
||||
{formatDate(review.created_at)}
|
||||
{review.visit_date && (
|
||||
<>
|
||||
<span>•</span>
|
||||
<span>Visited {formatDate(review.visit_date)}</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
{renderStars(review.rating)}
|
||||
<span className="ml-1 text-sm font-medium">
|
||||
{review.rating}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{review.title && (
|
||||
<h4 className="font-medium text-lg">{review.title}</h4>
|
||||
)}
|
||||
|
||||
{review.content && (
|
||||
<p className="text-muted-foreground leading-relaxed">
|
||||
{review.content}
|
||||
</p>
|
||||
)}
|
||||
|
||||
<div className="flex items-center gap-4 text-sm">
|
||||
{review.wait_time_minutes && (
|
||||
<div className="flex items-center gap-1 text-muted-foreground">
|
||||
<MapPin className="w-3 h-3" />
|
||||
<span>Wait time: {review.wait_time_minutes} min</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex items-center gap-1 text-muted-foreground">
|
||||
<ThumbsUp className="w-3 h-3" />
|
||||
<span>{review.helpful_votes} helpful</span>
|
||||
</div>
|
||||
|
||||
<ReportButton
|
||||
entityType="review"
|
||||
entityId={review.id}
|
||||
className="text-xs"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user