fix: Use upsert for profile updates to handle missing rows

Changes:
1. Created migration 003_fix_profile_creation.sql:
   - Added INSERT policy for profiles table
   - Made username nullable with default value
   - Created upsert_profile function for safe upserts

2. Updated ProfileSettings.tsx:
   - Changed from .update() to .upsert()
   - Added id field to upsert data
   - Added loadProfile() call after save to refresh state

This fixes the issue where users couldn't update their profile
because no profile row existed in the database.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-29 04:45:23 +03:00
parent ca510ead86
commit 280c335977
2 changed files with 96 additions and 7 deletions
+14 -7
View File
@@ -80,8 +80,9 @@ export default function ProfileSettings() {
const updateProfile = async () => {
setLoading(true);
try {
const updateData = {
username: profile.username,
const profileData = {
id: user?.id,
username: profile.username || '',
full_name: profile.full_name,
bio: profile.bio,
phone_number: profile.phone_number,
@@ -92,17 +93,20 @@ export default function ProfileSettings() {
updated_at: new Date().toISOString()
};
console.log('💾 SAVING PROFILE DATA:', updateData);
console.log('💾 UPSERTING PROFILE DATA:', profileData);
console.log('👤 User ID:', user?.id);
// Use upsert to create row if it doesn't exist, or update if it does
const { data, error } = await supabase
.from('profiles')
.update(updateData)
.eq('id', user?.id)
.upsert(profileData, {
onConflict: 'id',
ignoreDuplicates: false
})
.select();
console.log('✅ Save response data:', data);
console.log('❌ Save error:', error);
console.log('✅ Upsert response data:', data);
console.log('❌ Upsert error:', error);
if (error) throw error;
@@ -110,6 +114,9 @@ export default function ProfileSettings() {
title: 'Success',
description: 'Profile updated successfully',
});
// Reload profile to ensure state is in sync
await loadProfile();
} catch (error) {
console.error('❌ Profile update failed:', error);
toast({
@@ -0,0 +1,82 @@
-- ========================================
-- Fix Profile Creation Issue
-- ========================================
-- Adds INSERT policy and function to handle profile creation
-- Add INSERT policy for profiles
DROP POLICY IF EXISTS "Users can insert their own profile" ON public.profiles;
CREATE POLICY "Users can insert their own profile"
ON public.profiles FOR INSERT
WITH CHECK (auth.uid() = id);
-- Make username nullable and add default
ALTER TABLE public.profiles
ALTER COLUMN username DROP NOT NULL;
ALTER TABLE public.profiles
ALTER COLUMN username SET DEFAULT '';
-- Create function to handle profile upsert
CREATE OR REPLACE FUNCTION public.upsert_profile(
p_user_id UUID,
p_username TEXT DEFAULT '',
p_full_name TEXT DEFAULT '',
p_bio TEXT DEFAULT '',
p_phone_number TEXT DEFAULT '',
p_location TEXT DEFAULT '',
p_website TEXT DEFAULT '',
p_language TEXT DEFAULT 'en',
p_theme TEXT DEFAULT 'dark'
)
RETURNS SETOF public.profiles AS $$
BEGIN
RETURN QUERY
INSERT INTO public.profiles (
id,
username,
full_name,
bio,
phone_number,
location,
website,
language,
theme,
updated_at
)
VALUES (
p_user_id,
p_username,
p_full_name,
p_bio,
p_phone_number,
p_location,
p_website,
p_language,
p_theme,
NOW()
)
ON CONFLICT (id)
DO UPDATE SET
username = COALESCE(NULLIF(EXCLUDED.username, ''), public.profiles.username),
full_name = EXCLUDED.full_name,
bio = EXCLUDED.bio,
phone_number = EXCLUDED.phone_number,
location = EXCLUDED.location,
website = EXCLUDED.website,
language = EXCLUDED.language,
theme = EXCLUDED.theme,
updated_at = NOW()
RETURNING *;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Grant execute permission to authenticated users
GRANT EXECUTE ON FUNCTION public.upsert_profile TO authenticated;
-- Success message
DO $$
BEGIN
RAISE NOTICE 'Profile creation fix applied successfully!';
RAISE NOTICE 'Users can now create and update their profiles.';
END $$;