Refine profile privacy controls

This commit is contained in:
gpt-engineer-app[bot]
2025-09-29 02:46:03 +00:00
parent 50d75e0924
commit 93075ba6ca
5 changed files with 241 additions and 43 deletions

View File

@@ -22,6 +22,7 @@ import { profileEditSchema } from '@/lib/validation';
import { LocationDisplay } from '@/components/profile/LocationDisplay';
import { UserBlockButton } from '@/components/profile/UserBlockButton';
import { PersonalLocationDisplay } from '@/components/profile/PersonalLocationDisplay';
import { useProfileFieldAccess } from '@/hooks/useProfileFieldAccess';
export default function Profile() {
const {
username
@@ -54,6 +55,9 @@ export default function Profile() {
parkCount: 0
});
// Profile field access checking
const { canViewField, loading: fieldAccessLoading } = useProfileFieldAccess(profile?.user_id);
// Username validation
const usernameValidation = useUsernameValidation(editForm.username, profile?.username);
useEffect(() => {
@@ -349,13 +353,22 @@ export default function Profile() {
<CardContent className="p-8">
<div className="flex flex-col md:flex-row gap-6">
<div className="flex flex-col items-center md:items-start">
<PhotoUpload variant="avatar" maxFiles={1} maxSizeMB={1} existingPhotos={profile.avatar_url ? [profile.avatar_url] : []} onUploadComplete={handleAvatarUpload} currentImageId={avatarImageId} onError={error => {
toast({
title: "Upload Error",
description: error,
variant: "destructive"
});
}} className="mb-4" />
<PhotoUpload
variant="avatar"
maxFiles={1}
maxSizeMB={1}
existingPhotos={canViewField('avatar_url') && profile.avatar_url ? [profile.avatar_url] : []}
onUploadComplete={handleAvatarUpload}
currentImageId={avatarImageId}
onError={error => {
toast({
title: "Upload Error",
description: error,
variant: "destructive"
});
}}
className="mb-4"
/>
<div className="flex flex-col gap-2 mt-2">
{isOwnProfile && !editing && <Button variant="outline" size="sm" onClick={() => setEditing(true)}>
@@ -432,9 +445,11 @@ export default function Profile() {
{profile.display_name && <Badge variant="secondary" className="cursor-pointer hover:bg-secondary/80" onClick={() => navigate(`/profile/${profile.username}`)}>@{profile.username}</Badge>}
</div>
{profile.bio && <p className="text-muted-foreground mb-4 max-w-2xl">
{canViewField('bio') && profile.bio && (
<p className="text-muted-foreground mb-4 max-w-2xl">
{profile.bio}
</p>}
</p>
)}
<div className="flex flex-wrap gap-4 text-sm text-muted-foreground">
<div className="flex items-center gap-1">
@@ -445,17 +460,31 @@ export default function Profile() {
})}
</div>
{/* Show pronouns if enabled */}
{profile.show_pronouns && profile.preferred_pronouns && <div className="flex items-center gap-1">
{/* Show pronouns if enabled and privacy allows */}
{profile.show_pronouns && canViewField('preferred_pronouns') && profile.preferred_pronouns && (
<div className="flex items-center gap-1">
<User className="w-4 h-4" />
{profile.preferred_pronouns}
</div>}
</div>
)}
{/* Show personal location if available and privacy allows */}
{profile.personal_location && <PersonalLocationDisplay personalLocation={profile.personal_location} userId={profile.user_id} isOwnProfile={isOwnProfile} />}
{canViewField('personal_location') && profile.personal_location && (
<PersonalLocationDisplay
personalLocation={profile.personal_location}
userId={profile.user_id}
isOwnProfile={isOwnProfile}
/>
)}
{/* Show location only if privacy allows */}
{profile.location && <LocationDisplay location={profile.location} userId={profile.user_id} isOwnProfile={isOwnProfile} />}
{canViewField('location_id') && profile.location && (
<LocationDisplay
location={profile.location}
userId={profile.user_id}
isOwnProfile={isOwnProfile}
/>
)}
</div>
</div>}
</div>