mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 12:31:26 -05:00
feat: Update avatar upload logic
This commit is contained in:
@@ -15,7 +15,7 @@ import { useToast } from '@/hooks/use-toast';
|
|||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
import { supabase } from '@/integrations/supabase/client';
|
import { supabase } from '@/integrations/supabase/client';
|
||||||
import { User, Upload, Trash2 } from 'lucide-react';
|
import { User, Upload, Trash2 } from 'lucide-react';
|
||||||
import { SimplePhotoUpload } from './SimplePhotoUpload';
|
import { PhotoUpload } from '@/components/upload/PhotoUpload';
|
||||||
|
|
||||||
const profileSchema = z.object({
|
const profileSchema = z.object({
|
||||||
username: z.string().min(3).max(30).regex(/^[a-zA-Z0-9_-]+$/),
|
username: z.string().min(3).max(30).regex(/^[a-zA-Z0-9_-]+$/),
|
||||||
@@ -34,6 +34,8 @@ export function AccountProfileTab() {
|
|||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [avatarLoading, setAvatarLoading] = useState(false);
|
const [avatarLoading, setAvatarLoading] = useState(false);
|
||||||
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
|
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
|
||||||
|
const [avatarUrl, setAvatarUrl] = useState<string>(profile?.avatar_url || '');
|
||||||
|
const [avatarImageId, setAvatarImageId] = useState<string>(profile?.avatar_image_id || '');
|
||||||
|
|
||||||
const form = useForm<ProfileFormData>({
|
const form = useForm<ProfileFormData>({
|
||||||
resolver: zodResolver(profileSchema),
|
resolver: zodResolver(profileSchema),
|
||||||
@@ -83,16 +85,22 @@ export function AccountProfileTab() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAvatarUpload = async (imageId: string, imageUrl: string) => {
|
const handleAvatarUpload = async (urls: string[], imageId?: string) => {
|
||||||
if (!user) return;
|
if (!user || !urls[0]) return;
|
||||||
|
|
||||||
|
const newAvatarUrl = urls[0];
|
||||||
|
const newImageId = imageId || '';
|
||||||
|
|
||||||
|
// Update local state immediately
|
||||||
|
setAvatarUrl(newAvatarUrl);
|
||||||
|
setAvatarImageId(newImageId);
|
||||||
|
|
||||||
setAvatarLoading(true);
|
|
||||||
try {
|
try {
|
||||||
const { error } = await supabase
|
const { error } = await supabase
|
||||||
.from('profiles')
|
.from('profiles')
|
||||||
.update({
|
.update({
|
||||||
avatar_image_id: imageId,
|
avatar_url: newAvatarUrl,
|
||||||
avatar_url: imageUrl,
|
avatar_image_id: newImageId,
|
||||||
updated_at: new Date().toISOString()
|
updated_at: new Date().toISOString()
|
||||||
})
|
})
|
||||||
.eq('user_id', user.id);
|
.eq('user_id', user.id);
|
||||||
@@ -105,13 +113,14 @@ export function AccountProfileTab() {
|
|||||||
description: 'Your avatar has been successfully updated.'
|
description: 'Your avatar has been successfully updated.'
|
||||||
});
|
});
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
// Revert local state on error
|
||||||
|
setAvatarUrl(profile?.avatar_url || '');
|
||||||
|
setAvatarImageId(profile?.avatar_image_id || '');
|
||||||
toast({
|
toast({
|
||||||
title: 'Error',
|
title: 'Error',
|
||||||
description: error.message || 'Failed to update avatar',
|
description: error.message || 'Failed to update avatar',
|
||||||
variant: 'destructive'
|
variant: 'destructive'
|
||||||
});
|
});
|
||||||
} finally {
|
|
||||||
setAvatarLoading(false);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -142,28 +151,20 @@ export function AccountProfileTab() {
|
|||||||
{/* Profile Picture */}
|
{/* Profile Picture */}
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<h3 className="text-lg font-medium">Profile Picture</h3>
|
<h3 className="text-lg font-medium">Profile Picture</h3>
|
||||||
<div className="flex items-center gap-6">
|
<PhotoUpload
|
||||||
<Avatar className="w-20 h-20">
|
variant="avatar"
|
||||||
<AvatarImage src={profile?.avatar_url || undefined} />
|
maxFiles={1}
|
||||||
<AvatarFallback className="text-lg">
|
existingPhotos={avatarUrl ? [avatarUrl] : []}
|
||||||
{profile?.display_name?.[0] || profile?.username?.[0] || <User className="w-8 h-8" />}
|
onUploadComplete={handleAvatarUpload}
|
||||||
</AvatarFallback>
|
currentImageId={avatarImageId}
|
||||||
</Avatar>
|
onError={(error) => {
|
||||||
<div className="space-y-2">
|
toast({
|
||||||
<SimplePhotoUpload
|
title: "Upload Error",
|
||||||
onUpload={handleAvatarUpload}
|
description: error,
|
||||||
disabled={avatarLoading}
|
variant: "destructive"
|
||||||
>
|
});
|
||||||
<Button variant="outline" disabled={avatarLoading}>
|
}}
|
||||||
<Upload className="w-4 h-4 mr-2" />
|
/>
|
||||||
{avatarLoading ? 'Uploading...' : 'Change Avatar'}
|
|
||||||
</Button>
|
|
||||||
</SimplePhotoUpload>
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
JPG, PNG or GIF. Max size 5MB.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Separator />
|
<Separator />
|
||||||
|
|||||||
Reference in New Issue
Block a user