diff --git a/src/pages/Profile.tsx b/src/pages/Profile.tsx index 2b142385..fcca3e5b 100644 --- a/src/pages/Profile.tsx +++ b/src/pages/Profile.tsx @@ -13,23 +13,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 } from 'lucide-react'; import { Profile as ProfileType } from '@/types/database'; import { supabase } from '@/integrations/supabase/client'; import { useToast } from '@/hooks/use-toast'; @@ -37,12 +21,19 @@ import { PhotoUpload } from '@/components/upload/PhotoUpload'; import { profileEditSchema } from '@/lib/validation'; import { LocationDisplay } from '@/components/profile/LocationDisplay'; import { UserBlockButton } from '@/components/profile/UserBlockButton'; - export default function Profile() { - const { username } = useParams<{ username?: string }>(); + const { + username + } = useParams<{ + username?: string; + }>(); const navigate = useNavigate(); - const { toast } = useToast(); - const { refreshProfile } = useAuth(); + const { + toast + } = useToast(); + const { + refreshProfile + } = useAuth(); const [profile, setProfile] = useState(null); const [loading, setLoading] = useState(true); const [editing, setEditing] = useState(false); @@ -50,16 +41,15 @@ export default function Profile() { const [editForm, setEditForm] = useState({ username: '', display_name: '', - bio: '', + bio: '' }); const [showUsernameDialog, setShowUsernameDialog] = useState(false); const [formErrors, setFormErrors] = useState>({}); const [avatarUrl, setAvatarUrl] = useState(''); const [avatarImageId, setAvatarImageId] = useState(''); - + // Username validation const usernameValidation = useUsernameValidation(editForm.username, profile?.username); - useEffect(() => { getCurrentUser(); if (username) { @@ -68,28 +58,27 @@ export default function Profile() { fetchCurrentUserProfile(); } }, [username]); - const getCurrentUser = async () => { - const { data: { user } } = await supabase.auth.getUser(); + const { + data: { + user + } + } = await supabase.auth.getUser(); setCurrentUser(user); }; - const fetchProfile = async (profileUsername: string) => { try { - const { data, error } = await supabase - .from('profiles') - .select(`*, location:locations(*)`) - .eq('username', profileUsername) - .maybeSingle(); - + const { + data, + error + } = await supabase.from('profiles').select(`*, location:locations(*)`).eq('username', profileUsername).maybeSingle(); if (error) throw error; - if (data) { setProfile(data as ProfileType); setEditForm({ username: data.username || '', display_name: data.display_name || '', - bio: data.bio || '', + bio: data.bio || '' }); setAvatarUrl(data.avatar_url || ''); setAvatarImageId(data.avatar_image_id || ''); @@ -99,36 +88,34 @@ export default function Profile() { toast({ variant: "destructive", title: "Error loading profile", - description: error.message, + description: error.message }); } finally { setLoading(false); } }; - const fetchCurrentUserProfile = async () => { try { - const { data: { user } } = await supabase.auth.getUser(); - + const { + data: { + user + } + } = await supabase.auth.getUser(); if (!user) { navigate('/auth'); return; } - - const { data, error } = await supabase - .from('profiles') - .select(`*, location:locations(*)`) - .eq('user_id', user.id) - .maybeSingle(); - + const { + data, + error + } = await supabase.from('profiles').select(`*, location:locations(*)`).eq('user_id', user.id).maybeSingle(); if (error) throw error; - if (data) { setProfile(data as ProfileType); setEditForm({ username: data.username || '', display_name: data.display_name || '', - bio: data.bio || '', + bio: data.bio || '' }); setAvatarUrl(data.avatar_url || ''); setAvatarImageId(data.avatar_image_id || ''); @@ -138,18 +125,17 @@ export default function Profile() { toast({ variant: "destructive", title: "Error loading profile", - description: error.message, + description: error.message }); } finally { setLoading(false); } }; - const validateForm = () => { const result = profileEditSchema.safeParse(editForm); if (!result.success) { const errors: Record = {}; - result.error.issues.forEach((issue) => { + result.error.issues.forEach(issue => { if (issue.path[0]) { errors[issue.path[0] as string] = issue.message; } @@ -157,28 +143,23 @@ export default function Profile() { setFormErrors(errors); return false; } - if (!usernameValidation.isValid && editForm.username !== profile?.username) { - setFormErrors({ username: usernameValidation.error || 'Invalid username' }); + setFormErrors({ + username: usernameValidation.error || 'Invalid username' + }); return false; } - setFormErrors({}); return true; }; - const handleSaveProfile = async () => { if (!profile || !currentUser) return; - if (!validateForm()) return; - const usernameChanged = editForm.username !== profile.username; - if (usernameChanged && !showUsernameDialog) { setShowUsernameDialog(true); return; } - try { const updateData: any = { display_name: editForm.display_name, @@ -186,73 +167,60 @@ export default function Profile() { avatar_url: avatarUrl, avatar_image_id: avatarImageId }; - if (usernameChanged) { updateData.username = editForm.username; } - - const { error } = await supabase - .from('profiles') - .update(updateData) - .eq('user_id', currentUser.id); - + const { + error + } = await supabase.from('profiles').update(updateData).eq('user_id', currentUser.id); if (error) throw error; - setProfile(prev => prev ? { ...prev, ...updateData } : null); - setEditing(false); setShowUsernameDialog(false); - if (usernameChanged) { toast({ title: "Profile updated", - description: "Your username and profile URL have been updated successfully.", + description: "Your username and profile URL have been updated successfully." }); // Navigate to new username URL navigate(`/profile/${editForm.username}`); } else { toast({ title: "Profile updated", - description: "Your profile has been updated successfully.", + description: "Your profile has been updated successfully." }); } } catch (error: any) { toast({ variant: "destructive", title: "Error updating profile", - description: error.message, + description: error.message }); } }; - const confirmUsernameChange = () => { setShowUsernameDialog(false); handleSaveProfile(); }; - const handleAvatarUpload = async (urls: string[], imageId?: string) => { if (!currentUser || !urls[0]) return; - const newAvatarUrl = urls[0]; const newImageId = imageId || ''; - + // Update local state immediately setAvatarUrl(newAvatarUrl); setAvatarImageId(newImageId); - try { // Update database immediately - const { error } = await supabase - .from('profiles') - .update({ - avatar_url: newAvatarUrl, - avatar_image_id: newImageId - }) - .eq('user_id', currentUser.id); - + const { + error + } = await supabase.from('profiles').update({ + avatar_url: newAvatarUrl, + avatar_image_id: newImageId + }).eq('user_id', currentUser.id); if (error) throw error; // Update local profile state @@ -266,29 +234,24 @@ export default function Profile() { if (refreshProfile) { await refreshProfile(); } - toast({ title: "Avatar updated", - description: "Your profile picture has been updated successfully.", + description: "Your profile picture has been updated successfully." }); } catch (error: any) { // Revert local state on error setAvatarUrl(profile?.avatar_url || ''); setAvatarImageId(profile?.avatar_image_id || ''); - toast({ variant: "destructive", title: "Error updating avatar", - description: error.message, + description: error.message }); } }; - const isOwnProfile = currentUser && profile && currentUser.id === profile.user_id; - if (loading) { - return ( -
+ return
@@ -297,13 +260,10 @@ export default function Profile() {
-
- ); +
; } - if (!profile) { - return ( -
+ return
@@ -318,12 +278,9 @@ export default function Profile() {
-
- ); +
; } - - return ( -
+ return
@@ -333,77 +290,40 @@ export default function Profile() {
- { - toast({ - title: "Upload Error", - description: error, - variant: "destructive" - }); - }} - className="mb-4" - /> + { + toast({ + title: "Upload Error", + description: error, + variant: "destructive" + }); + }} className="mb-4" />
- {isOwnProfile && !editing && ( - - )} + } - {!isOwnProfile && ( - - )} + {!isOwnProfile && }
- {editing && isOwnProfile ? ( -
+ {editing && isOwnProfile ?
- setEditForm(prev => ({ ...prev, username: e.target.value }))} - placeholder="your_username" - className={`pr-10 ${formErrors.username ? 'border-destructive' : ''}`} - /> + setEditForm(prev => ({ + ...prev, + username: e.target.value + }))} placeholder="your_username" className={`pr-10 ${formErrors.username ? 'border-destructive' : ''}`} />
- {usernameValidation.isChecking ? ( - - ) : editForm.username === profile?.username ? ( - - ) : usernameValidation.isValid ? ( - - ) : usernameValidation.error ? ( - - ) : null} + {usernameValidation.isChecking ? : editForm.username === profile?.username ? : usernameValidation.isValid ? : usernameValidation.error ? : null}
- {formErrors.username && ( -

{formErrors.username}

- )} - {usernameValidation.error && editForm.username !== profile?.username && ( -

{usernameValidation.error}

- )} - {usernameValidation.isValid && editForm.username !== profile?.username && ( -

Username is available!

- )} + {formErrors.username &&

{formErrors.username}

} + {usernameValidation.error && editForm.username !== profile?.username &&

{usernameValidation.error}

} + {usernameValidation.isValid && editForm.username !== profile?.username &&

Username is available!

}

Your profile URL will be /profile/{editForm.username}

@@ -411,105 +331,71 @@ export default function Profile() {
- setEditForm(prev => ({ ...prev, display_name: e.target.value }))} - placeholder="Your display name" - className={formErrors.display_name ? 'border-destructive' : ''} - /> - {formErrors.display_name && ( -

{formErrors.display_name}

- )} + setEditForm(prev => ({ + ...prev, + display_name: e.target.value + }))} placeholder="Your display name" className={formErrors.display_name ? 'border-destructive' : ''} /> + {formErrors.display_name &&

{formErrors.display_name}

}
-