diff --git a/src/contexts/AuthContext.jsx b/src/contexts/AuthContext.jsx index b15b766..9c5353f 100644 --- a/src/contexts/AuthContext.jsx +++ b/src/contexts/AuthContext.jsx @@ -31,36 +31,33 @@ export const AuthProvider = ({ children }) => { // Функция для загрузки профиля пользователя const loadUserProfile = async (userId) => { + if (!userId) { + console.log('AuthProvider: Нет userId для загрузки профиля'); + setLoading(false); + return; + } + try { console.log('AuthProvider: Загрузка профиля пользователя:', userId); - const { data: profile, error: profileError } = await supabase - .from('users') - .select('*') - .eq('id', userId) - .single(); + const profile = await getUserProfile(userId); + + if (!profile) { + console.log('AuthProvider: Профиль не найден, создаем новый'); + const { data: newProfile, error: createError } = await supabase + .from('users') + .insert([ + { + id: userId, + username: `user_${userId.slice(0, 8)}`, + role: 'user' + } + ]) + .select() + .single(); - if (profileError) { - if (profileError.code === 'PGRST116') { - // Если профиль не найден, создаем новый - console.log('AuthProvider: Профиль не найден, создаем новый'); - const { data: newProfile, error: createError } = await supabase - .from('users') - .insert([ - { - id: userId, - username: `user_${userId.slice(0, 8)}`, - role: 'user' - } - ]) - .select() - .single(); - - if (createError) throw createError; - console.log('AuthProvider: Новый профиль создан:', newProfile); - setUserProfile(newProfile); - } else { - throw profileError; - } + if (createError) throw createError; + console.log('AuthProvider: Новый профиль создан:', newProfile); + setUserProfile(newProfile); } else { console.log('AuthProvider: Профиль загружен:', profile); setUserProfile(profile); @@ -68,6 +65,10 @@ export const AuthProvider = ({ children }) => { } catch (error) { console.error('AuthProvider: Ошибка загрузки профиля:', error); setError(error.message); + setCurrentUser(null); + setUserProfile(null); + } finally { + setLoading(false); } }; @@ -78,7 +79,14 @@ export const AuthProvider = ({ children }) => { const { data: { session }, error: sessionError } = await supabase.auth.getSession(); console.log('AuthProvider: Результат проверки сессии:', { session, error: sessionError }); - if (sessionError) throw sessionError; + if (sessionError) { + console.error('AuthProvider: Ошибка получения сессии:', sessionError); + await supabase.auth.signOut(); + setCurrentUser(null); + setUserProfile(null); + setLoading(false); + return; + } if (session?.user) { console.log('AuthProvider: Пользователь найден в сессии'); @@ -88,41 +96,59 @@ export const AuthProvider = ({ children }) => { console.log('AuthProvider: Пользователь не найден в сессии'); setCurrentUser(null); setUserProfile(null); + setLoading(false); } } catch (error) { console.error('AuthProvider: Ошибка проверки сессии:', error); setError(error.message); + await supabase.auth.signOut(); setCurrentUser(null); setUserProfile(null); - } finally { - console.log('AuthProvider: Завершение проверки сессии'); setLoading(false); } }; useEffect(() => { + let mounted = true; console.log('AuthProvider: Инициализация...'); - checkSession(); + + const initialize = async () => { + try { + await checkSession(); + } catch (error) { + console.error('AuthProvider: Ошибка инициализации:', error); + setError(error.message); + setLoading(false); + } + }; + + initialize(); const { data: { subscription } } = supabase.auth.onAuthStateChange(async (event, session) => { + if (!mounted) return; + console.log('AuthProvider: Изменение состояния авторизации:', { event, session }); - setLoading(true); + + if (event === 'INITIAL_SESSION') { + setLoading(false); + return; + } if (event === 'SIGNED_IN') { console.log('AuthProvider: Пользователь вошел в систему'); setCurrentUser(session.user); await loadUserProfile(session.user.id); - } else if (event === 'SIGNED_OUT') { + } else if (event === 'SIGNED_OUT' || event === 'USER_DELETED') { console.log('AuthProvider: Пользователь вышел из системы'); setCurrentUser(null); setUserProfile(null); + setLoading(false); } - - setLoading(false); }); return () => { console.log('AuthProvider: Отписка от изменений состояния авторизации'); + mounted = false; subscription.unsubscribe(); }; }, []); @@ -189,7 +215,7 @@ export const AuthProvider = ({ children }) => { console.log('AuthProvider: Текущее состояние:', value); - if (loading || (currentUser && !userProfile)) { + if (loading && !currentUser) { console.log('AuthProvider: Отображение состояния загрузки'); return (
diff --git a/src/services/supabase.js b/src/services/supabase.js index 2400a40..8a237e4 100644 --- a/src/services/supabase.js +++ b/src/services/supabase.js @@ -80,64 +80,90 @@ export const getCurrentUser = async () => { }; // User functions -export const getUserProfile = async (username) => { - const { data, error } = await supabase - .from('users') - .select('*') - .eq('username', username) - .single(); - - if (error) throw error; - return data; +export const getUserProfile = async (userId) => { + try { + const { data, error } = await supabase + .from('users') + .select('*') + .eq('id', userId) + .single(); + + if (error) { + if (error.code === 'PGRST116') { + // Если профиль не найден, создаем новый + const { data: newProfile, error: createError } = await supabase + .from('users') + .insert([ + { + id: userId, + username: `user_${userId.slice(0, 8)}`, + role: 'user' + } + ]) + .select() + .single(); + + if (createError) throw createError; + return newProfile; + } + throw error; + } + + return data; + } catch (error) { + console.error('Error getting user profile:', error); + throw error; + } +}; + +export const updateUserProfile = async (userId, profileData) => { + try { + const { data, error } = await supabase + .from('users') + .update(profileData) + .eq('id', userId) + .select() + .single(); + + if (error) throw error; + return data; + } catch (error) { + console.error('Error updating user profile:', error); + throw error; + } }; // Media functions export const createMedia = async (mediaData) => { try { - const { data: { user } } = await supabase.auth.getUser(); - if (!user) { - throw new Error('Пользователь не авторизован'); - } - const { data, error } = await supabase .from('media') - .insert({ - ...mediaData, - created_by: user.id, - created_at: new Date().toISOString(), - is_published: false - }) + .insert([mediaData]) .select() .single(); - - if (error) { - console.error('Error creating media:', error); - throw error; - } - + + if (error) throw error; return data; } catch (error) { - console.error('Failed to create media:', error); + console.error('Error creating media:', error); throw error; } }; export const getMediaById = async (id) => { - const { data, error } = await supabase - .from('media') - .select(` - *, - created_by:users(username), - reviews( - *, - user:users(username, profile_picture, is_critic) - ) - `) - .eq('id', id) - .single(); - - if (error) throw error; - return data; + try { + const { data, error } = await supabase + .from('media') + .select('*') + .eq('id', id) + .single(); + + if (error) throw error; + return data; + } catch (error) { + console.error('Error getting media:', error); + throw error; + } }; export const listMedia = async (type = null, page = 1, limit = 20) => { @@ -159,40 +185,81 @@ export const listMedia = async (type = null, page = 1, limit = 20) => { return { data, count, - error: null + totalPages: Math.ceil(count / limit) }; } catch (error) { - console.error('Error in listMedia:', error); - return { - data: [], - count: 0, - error: error.message - }; + console.error('Error listing media:', error); + throw error; + } +}; + +export const updateMedia = async (id, mediaData) => { + try { + const { data, error } = await supabase + .from('media') + .update(mediaData) + .eq('id', id) + .select() + .single(); + + if (error) throw error; + return data; + } catch (error) { + console.error('Error updating media:', error); + throw error; + } +}; + +export const deleteMedia = async (id) => { + try { + const { error } = await supabase + .from('media') + .delete() + .eq('id', id); + + if (error) throw error; + } catch (error) { + console.error('Error deleting media:', error); + throw error; } }; // Review functions export const createReview = async (reviewData) => { - const { data, error } = await supabase - .from('reviews') - .insert(reviewData) - .select() - .single(); - - if (error) throw error; - return data; + try { + const { data, error } = await supabase + .from('reviews') + .insert([reviewData]) + .select() + .single(); + + if (error) throw error; + return data; + } catch (error) { + console.error('Error creating review:', error); + throw error; + } }; -export const getUserReviews = async (userId) => { - const { data, error } = await supabase - .from('reviews') - .select(` - *, - media(title, type, poster_url) - `) - .eq('user_id', userId) - .order('created_at', { ascending: false }); - - if (error) throw error; - return data; +export const getReviewsByMediaId = async (mediaId) => { + try { + const { data, error } = await supabase + .from('reviews') + .select(` + *, + users ( + id, + username, + profile_picture + ) + `) + .eq('media_id', mediaId) + .order('created_at', { ascending: false }); + + if (error) throw error; + return data; + } catch (error) { + console.error('Error getting reviews:', error); + throw error; + } }; \ No newline at end of file