feat: Add submissions and rankings to activity feed

This commit is contained in:
gpt-engineer-app[bot]
2025-09-29 19:24:37 +00:00
parent a46179a1d0
commit aa92b79c8b

View File

@@ -14,7 +14,7 @@ import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from '@/components/ui/alert-dialog';
import { useAuth } from '@/hooks/useAuth';
import { useUsernameValidation } from '@/hooks/useUsernameValidation';
import { User, MapPin, Calendar, Star, Trophy, Settings, Camera, Edit3, Save, X, ArrowLeft, Check, AlertCircle, Loader2, UserX } from 'lucide-react';
import { User, MapPin, Calendar, Star, Trophy, Settings, Camera, Edit3, Save, X, ArrowLeft, Check, AlertCircle, Loader2, UserX, FileText, Image } from 'lucide-react';
import { Profile as ProfileType } from '@/types/database';
import { supabase } from '@/integrations/supabase/client';
import { useToast } from '@/hooks/use-toast';
@@ -119,14 +119,21 @@ export default function Profile() {
const fetchRecentActivity = async (userId: string) => {
setActivityLoading(true);
try {
const isOwnProfile = currentUser && currentUser.id === userId;
// Fetch last 10 reviews
const { data: reviews, error: reviewsError } = await supabase
let reviewsQuery = supabase
.from('reviews')
.select('id, rating, title, created_at, moderation_status, park_id, ride_id, parks(name, slug), rides(name, slug, parks(name, slug))')
.eq('user_id', userId)
.order('created_at', { ascending: false })
.limit(10);
if (!isOwnProfile) {
reviewsQuery = reviewsQuery.eq('moderation_status', 'approved');
}
const { data: reviews, error: reviewsError } = await reviewsQuery;
if (reviewsError) throw reviewsError;
// Fetch last 10 ride credits
@@ -139,10 +146,38 @@ export default function Profile() {
if (creditsError) throw creditsError;
// Fetch last 10 submissions
let submissionsQuery = supabase
.from('content_submissions')
.select('id, submission_type, content, status, created_at')
.eq('user_id', userId)
.order('created_at', { ascending: false })
.limit(10);
if (!isOwnProfile) {
submissionsQuery = submissionsQuery.eq('status', 'approved');
}
const { data: submissions, error: submissionsError } = await submissionsQuery;
if (submissionsError) throw submissionsError;
// Fetch last 10 rankings (public top lists)
const { data: rankings, error: rankingsError } = await supabase
.from('user_top_lists')
.select('id, title, description, list_type, created_at')
.eq('user_id', userId)
.eq('is_public', true)
.order('created_at', { ascending: false })
.limit(10);
if (rankingsError) throw rankingsError;
// Combine and sort by date
const combined = [
...(reviews?.map(r => ({ ...r, type: 'review' })) || []),
...(credits?.map(c => ({ ...c, type: 'credit' })) || [])
...(credits?.map(c => ({ ...c, type: 'credit' })) || []),
...(submissions?.map(s => ({ ...s, type: 'submission' })) || []),
...(rankings?.map(r => ({ ...r, type: 'ranking' })) || [])
].sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())
.slice(0, 15);
@@ -602,6 +637,14 @@ export default function Profile() {
<div className="flex-shrink-0 mt-1">
{activity.type === 'review' ? (
<Star className="w-5 h-5 text-accent" />
) : activity.type === 'credit' ? (
<Trophy className="w-5 h-5 text-accent" />
) : activity.type === 'submission' ? (
activity.submission_type === 'photo' ? (
<Image className="w-5 h-5 text-accent" />
) : (
<FileText className="w-5 h-5 text-accent" />
)
) : (
<Trophy className="w-5 h-5 text-accent" />
)}
@@ -641,6 +684,43 @@ export default function Profile() {
</div>
) : null}
</>
) : activity.type === 'submission' ? (
<>
<div className="flex items-center gap-2 mb-1">
<p className="font-medium">
Submitted {activity.submission_type}
{activity.content?.name && `: ${activity.content.name}`}
</p>
{activity.status === 'pending' && (
<Badge variant="secondary" className="text-xs">Pending</Badge>
)}
{activity.status === 'approved' && (
<Badge variant="default" className="text-xs">Approved</Badge>
)}
{activity.status === 'rejected' && (
<Badge variant="destructive" className="text-xs">Rejected</Badge>
)}
</div>
{activity.content?.description && (
<p className="text-sm text-muted-foreground line-clamp-2">
{activity.content.description}
</p>
)}
</>
) : activity.type === 'ranking' ? (
<>
<div className="flex items-center gap-2 mb-1">
<p className="font-medium">Created ranking: {activity.title}</p>
<Badge variant="outline" className="text-xs capitalize">
{activity.list_type.replace('_', ' ')}
</Badge>
</div>
{activity.description && (
<p className="text-sm text-muted-foreground line-clamp-2">
{activity.description}
</p>
)}
</>
) : (
<>
<p className="font-medium mb-1">Added ride credit</p>