mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 08:51:13 -05:00
Reverted to commit 0091584677
This commit is contained in:
@@ -28,7 +28,6 @@ import { handleError, handleSuccess, AppError } from '@/lib/errorHandler';
|
||||
import { useAvatarUpload } from '@/hooks/useAvatarUpload';
|
||||
import { useUsernameValidation } from '@/hooks/useUsernameValidation';
|
||||
import { useAutoSave } from '@/hooks/useAutoSave';
|
||||
import { useProfileUpdateMutation } from '@/hooks/profile/useProfileUpdateMutation';
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
@@ -43,7 +42,7 @@ type ProfileFormData = z.infer<typeof profileSchema>;
|
||||
export function AccountProfileTab() {
|
||||
const { user, pendingEmail, clearPendingEmail } = useAuth();
|
||||
const { data: profile, refreshProfile } = useProfile(user?.id);
|
||||
const updateProfileMutation = useProfileUpdateMutation();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
|
||||
const [showEmailDialog, setShowEmailDialog] = useState(false);
|
||||
const [showCancelEmailDialog, setShowCancelEmailDialog] = useState(false);
|
||||
@@ -108,28 +107,47 @@ export function AccountProfileTab() {
|
||||
const handleFormSubmit = async (data: ProfileFormData) => {
|
||||
if (!user) return;
|
||||
|
||||
// Update Novu subscriber if username changed (before mutation for optimistic update)
|
||||
const usernameChanged = data.username !== profile?.username;
|
||||
|
||||
updateProfileMutation.mutate({
|
||||
userId: user.id,
|
||||
updates: {
|
||||
username: data.username,
|
||||
display_name: data.display_name || null,
|
||||
bio: data.bio || null
|
||||
}
|
||||
}, {
|
||||
onSuccess: async () => {
|
||||
if (usernameChanged && notificationService.isEnabled()) {
|
||||
await notificationService.updateSubscriber({
|
||||
subscriberId: user.id,
|
||||
email: user.email,
|
||||
firstName: data.username,
|
||||
});
|
||||
setLoading(true);
|
||||
try {
|
||||
// Use the update_profile RPC function with server-side validation
|
||||
const { data: result, error } = await supabase.rpc('update_profile', {
|
||||
p_username: data.username,
|
||||
p_display_name: data.display_name || null,
|
||||
p_bio: data.bio || null
|
||||
});
|
||||
|
||||
if (error) {
|
||||
// Handle rate limiting error
|
||||
if (error.code === 'P0001') {
|
||||
const resetTime = error.message.match(/Try again at (.+)$/)?.[1];
|
||||
throw new AppError(
|
||||
error.message,
|
||||
'RATE_LIMIT',
|
||||
`Too many profile updates. ${resetTime ? 'Try again at ' + new Date(resetTime).toLocaleTimeString() : 'Please wait a few minutes.'}`
|
||||
);
|
||||
}
|
||||
await refreshProfile();
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// Type the RPC result
|
||||
const rpcResult = result as unknown as { success: boolean; changes_count: number };
|
||||
|
||||
// Update Novu subscriber if username changed
|
||||
if (rpcResult?.changes_count > 0 && notificationService.isEnabled()) {
|
||||
await notificationService.updateSubscriber({
|
||||
subscriberId: user.id,
|
||||
email: user.email,
|
||||
firstName: data.username,
|
||||
});
|
||||
}
|
||||
|
||||
await refreshProfile();
|
||||
handleSuccess('Profile updated', 'Your profile has been successfully updated.');
|
||||
} catch (error: unknown) {
|
||||
handleError(error, { action: 'Update profile', userId: user.id });
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const onSubmit = async (data: ProfileFormData) => {
|
||||
@@ -382,17 +400,17 @@ export function AccountProfileTab() {
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={
|
||||
updateProfileMutation.isPending ||
|
||||
loading ||
|
||||
isDeactivated ||
|
||||
isSaving ||
|
||||
usernameValidation.isChecking ||
|
||||
usernameValidation.isAvailable === false
|
||||
}
|
||||
>
|
||||
{updateProfileMutation.isPending || isSaving ? 'Saving...' : 'Save Changes'}
|
||||
{loading || isSaving ? 'Saving...' : 'Save Changes'}
|
||||
</Button>
|
||||
|
||||
{lastSaved && !updateProfileMutation.isPending && !isSaving && (
|
||||
{lastSaved && !loading && !isSaving && (
|
||||
<span className="text-sm text-muted-foreground">
|
||||
Last saved {formatDistanceToNow(lastSaved, { addSuffix: true })}
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user