Fix privacy settings implementation

This commit is contained in:
gpt-engineer-app[bot]
2025-09-28 20:29:15 +00:00
parent 65e5b8e52f
commit 10bdfa67a2
5 changed files with 388 additions and 22 deletions

View File

@@ -0,0 +1,192 @@
import { useState, useEffect } from 'react';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from '@/components/ui/alert-dialog';
import { UserX, Trash2 } from 'lucide-react';
import { supabase } from '@/integrations/supabase/client';
import { useAuth } from '@/hooks/useAuth';
import { useToast } from '@/hooks/use-toast';
interface BlockedUser {
id: string;
blocked_id: string;
reason?: string;
created_at: string;
blocked_profile?: {
username: string;
display_name?: string;
avatar_url?: string;
};
}
export function BlockedUsers() {
const { user } = useAuth();
const { toast } = useToast();
const [blockedUsers, setBlockedUsers] = useState<BlockedUser[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
if (user) {
fetchBlockedUsers();
}
}, [user]);
const fetchBlockedUsers = async () => {
if (!user) return;
try {
// First get the blocked user IDs
const { data: blocks, error: blocksError } = await supabase
.from('user_blocks')
.select('id, blocked_id, reason, created_at')
.eq('blocker_id', user.id)
.order('created_at', { ascending: false });
if (blocksError) throw blocksError;
if (!blocks || blocks.length === 0) {
setBlockedUsers([]);
return;
}
// Then get the profile information for blocked users
const blockedIds = blocks.map(b => b.blocked_id);
const { data: profiles, error: profilesError } = await supabase
.from('profiles')
.select('user_id, username, display_name, avatar_url')
.in('user_id', blockedIds);
if (profilesError) throw profilesError;
// Combine the data
const blockedUsersWithProfiles = blocks.map(block => ({
...block,
blocked_profile: profiles?.find(p => p.user_id === block.blocked_id)
}));
setBlockedUsers(blockedUsersWithProfiles);
} catch (error: any) {
console.error('Error fetching blocked users:', error);
toast({
title: 'Error',
description: 'Failed to load blocked users',
variant: 'destructive'
});
} finally {
setLoading(false);
}
};
const handleUnblock = async (blockId: string, username: string) => {
try {
const { error } = await supabase
.from('user_blocks')
.delete()
.eq('id', blockId);
if (error) throw error;
setBlockedUsers(prev => prev.filter(block => block.id !== blockId));
toast({
title: 'User unblocked',
description: `You have unblocked @${username}`
});
} catch (error: any) {
toast({
title: 'Error',
description: 'Failed to unblock user',
variant: 'destructive'
});
}
};
if (loading) {
return (
<div className="space-y-4">
{Array.from({ length: 2 }, (_, i) => (
<div key={i} className="flex items-center gap-3 p-3 rounded-lg border animate-pulse">
<div className="w-10 h-10 bg-muted rounded-full"></div>
<div className="flex-1">
<div className="h-4 bg-muted rounded w-1/3 mb-1"></div>
<div className="h-3 bg-muted rounded w-1/4"></div>
</div>
<div className="w-20 h-8 bg-muted rounded"></div>
</div>
))}
</div>
);
}
if (blockedUsers.length === 0) {
return (
<div className="text-center p-4 text-muted-foreground">
<UserX className="w-8 h-8 mx-auto mb-2" />
<p className="text-sm">No blocked users</p>
<p className="text-xs mt-1">
Blocked users will appear here and can be unblocked at any time.
</p>
</div>
);
}
return (
<div className="space-y-3">
{blockedUsers.map((block) => (
<div key={block.id} className="flex items-center gap-3 p-3 rounded-lg border">
<Avatar className="w-10 h-10">
<AvatarImage src={block.blocked_profile?.avatar_url || ''} />
<AvatarFallback>
{(block.blocked_profile?.display_name || block.blocked_profile?.username || 'U').charAt(0).toUpperCase()}
</AvatarFallback>
</Avatar>
<div className="flex-1">
<div className="font-medium">
{block.blocked_profile?.display_name || block.blocked_profile?.username || 'Unknown User'}
</div>
{block.blocked_profile?.display_name && (
<div className="text-sm text-muted-foreground">
@{block.blocked_profile.username}
</div>
)}
{block.reason && (
<div className="text-xs text-muted-foreground mt-1">
Reason: {block.reason}
</div>
)}
<div className="text-xs text-muted-foreground">
Blocked {new Date(block.created_at).toLocaleDateString()}
</div>
</div>
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="outline" size="sm">
<Trash2 className="w-4 h-4 mr-1" />
Unblock
</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Unblock User</AlertDialogTitle>
<AlertDialogDescription>
Are you sure you want to unblock @{block.blocked_profile?.username}?
They will be able to interact with your content again.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction
onClick={() => handleUnblock(block.id, block.blocked_profile?.username || 'user')}
>
Unblock
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</div>
))}
</div>
);
}