Initial commit

This commit is contained in:
2025-07-11 13:21:49 +00:00
commit 8a7ab3ac24
262 changed files with 28219 additions and 0 deletions
+191
View File
@@ -0,0 +1,191 @@
import React, { createContext, useContext, useState, useEffect } from 'react';
import { supabase } from '../supabaseClient';
import { logger } from '../debugConfig';
import { CCUser, CCUserMetadata } from '../services/auth/authService';
import { UserPreferences } from '../services/auth/profileService';
import { DatabaseNameService } from '../services/graph/databaseNameService';
export interface UserContextType {
user: CCUser | null;
loading: boolean;
error: Error | null;
profile: CCUser | null;
preferences: UserPreferences;
isMobile: boolean;
isInitialized: boolean;
updateProfile: (updates: Partial<CCUser>) => Promise<void>;
updatePreferences: (updates: Partial<UserPreferences>) => Promise<void>;
clearError: () => void;
}
export const UserContext = createContext<UserContextType>({
user: null,
loading: true,
error: null,
profile: null,
preferences: {},
isMobile: false,
isInitialized: false,
updateProfile: async () => {},
updatePreferences: async () => {},
clearError: () => {}
});
export function UserProvider({ children }: { children: React.ReactNode }) {
const [user] = useState<CCUser | null>(null);
const [profile, setProfile] = useState<CCUser | null>(null);
const [preferences, setPreferences] = useState<UserPreferences>({});
const [loading, setLoading] = useState(true);
const [isInitialized, setIsInitialized] = useState(false);
const [error, setError] = useState<Error | null>(null);
const [isMobile] = useState(window.innerWidth <= 768);
useEffect(() => {
const loadUserProfile = async () => {
try {
const { data: { user } } = await supabase.auth.getUser();
if (!user) {
setProfile(null);
setLoading(false);
setIsInitialized(true);
return;
}
const { data, error } = await supabase
.from('profiles')
.select('*')
.eq('id', user.id)
.single();
if (error) {
throw error;
}
const metadata = user.user_metadata as CCUserMetadata;
const userDbName = DatabaseNameService.getUserPrivateDB(metadata.user_type || '', metadata.username || '');
const schoolDbName = DatabaseNameService.getDevelopmentSchoolDB();
const userProfile: CCUser = {
id: user.id,
email: user.email,
user_type: metadata.user_type || '',
username: metadata.username || '',
display_name: metadata.display_name || '',
user_db_name: userDbName,
school_db_name: schoolDbName,
created_at: user.created_at,
updated_at: user.updated_at
};
setProfile(userProfile);
logger.debug('user-context', '✅ User profile loaded', {
userId: userProfile.id,
userType: userProfile.user_type,
username: userProfile.username,
userDbName: userProfile.user_db_name,
schoolDbName: userProfile.school_db_name
});
// Load preferences from profile data
setPreferences({
theme: data.theme || 'system',
notifications: data.notifications_enabled || false
});
} catch (error) {
logger.error('user-context', '❌ Failed to load user profile', { error });
setError(error instanceof Error ? error : new Error('Failed to load user profile'));
} finally {
setLoading(false);
setIsInitialized(true);
}
};
loadUserProfile();
}, []);
const updateProfile = async (updates: Partial<CCUser>) => {
if (!user?.id || !profile) {
return;
}
setLoading(true);
try {
const { error } = await supabase
.from('profiles')
.update({
...updates,
updated_at: new Date().toISOString()
})
.eq('id', user.id);
if (error) {
throw error;
}
setProfile(prev => prev ? { ...prev, ...updates } : null);
logger.info('user-context', '✅ Profile updated successfully');
} catch (error) {
logger.error('user-context', '❌ Failed to update profile', { error });
setError(error instanceof Error ? error : new Error('Failed to update profile'));
throw error;
} finally {
setLoading(false);
}
};
const updatePreferences = async (updates: Partial<UserPreferences>) => {
if (!user?.id) {
return;
}
setLoading(true);
try {
const newPreferences = { ...preferences, ...updates };
setPreferences(newPreferences);
const { error } = await supabase
.from('profiles')
.update({
preferences: newPreferences,
updated_at: new Date().toISOString()
})
.eq('id', user.id);
if (error) {
throw error;
}
logger.info('user-context', '✅ Preferences updated successfully');
} catch (error) {
logger.error('user-context', '❌ Failed to update preferences', { error });
setError(error instanceof Error ? error : new Error('Failed to update preferences'));
throw error;
} finally {
setLoading(false);
}
};
return (
<UserContext.Provider
value={{
user: profile,
loading,
error,
profile,
preferences,
isMobile,
isInitialized,
updateProfile,
updatePreferences,
clearError: () => setError(null)
}}
>
{children}
</UserContext.Provider>
);
}
export const useUser = () => useContext(UserContext);