mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 08:31:12 -05:00
Refactor: Simplify auth and profile handling
This commit is contained in:
@@ -5,16 +5,13 @@ import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
|||||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
|
||||||
import { User, Settings, LogOut } from 'lucide-react';
|
import { User, Settings, LogOut } from 'lucide-react';
|
||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
|
import { useProfile } from '@/hooks/useProfile';
|
||||||
import { useToast } from '@/hooks/use-toast';
|
import { useToast } from '@/hooks/use-toast';
|
||||||
import { AuthModal } from './AuthModal';
|
import { AuthModal } from './AuthModal';
|
||||||
|
|
||||||
export function AuthButtons() {
|
export function AuthButtons() {
|
||||||
const {
|
const { user, loading: authLoading, signOut } = useAuth();
|
||||||
user,
|
const { data: profile, isLoading: profileLoading } = useProfile(user?.id);
|
||||||
profile,
|
|
||||||
loading,
|
|
||||||
signOut
|
|
||||||
} = useAuth();
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const {
|
const {
|
||||||
toast
|
toast
|
||||||
@@ -43,7 +40,7 @@ export function AuthButtons() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Show loading skeleton only during initial auth check
|
// Show loading skeleton only during initial auth check
|
||||||
if (loading) {
|
if (authLoading) {
|
||||||
return (
|
return (
|
||||||
<div className="flex gap-2 items-center">
|
<div className="flex gap-2 items-center">
|
||||||
<div className="h-8 w-16 bg-muted animate-pulse rounded" />
|
<div className="h-8 w-16 bg-muted animate-pulse rounded" />
|
||||||
@@ -83,17 +80,6 @@ export function AuthButtons() {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Debug logging for avatar rendering
|
|
||||||
console.log('[AuthButtons] Component render:', {
|
|
||||||
hasUser: !!user,
|
|
||||||
hasProfile: !!profile,
|
|
||||||
hasAvatarUrl: !!profile?.avatar_url,
|
|
||||||
avatarUrl: profile?.avatar_url,
|
|
||||||
displayName: profile?.display_name,
|
|
||||||
username: profile?.username,
|
|
||||||
loading
|
|
||||||
});
|
|
||||||
|
|
||||||
return <DropdownMenu>
|
return <DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button variant="ghost" className="relative h-8 w-8 rounded-full">
|
<Button variant="ghost" className="relative h-8 w-8 rounded-full">
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { Separator } from '@/components/ui/separator';
|
|||||||
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from '@/components/ui/alert-dialog';
|
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from '@/components/ui/alert-dialog';
|
||||||
import { useToast } from '@/hooks/use-toast';
|
import { useToast } from '@/hooks/use-toast';
|
||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
|
import { useProfile } from '@/hooks/useProfile';
|
||||||
import { supabase } from '@/integrations/supabase/client';
|
import { supabase } from '@/integrations/supabase/client';
|
||||||
import { User, Upload, Trash2, Mail, AlertCircle, X } from 'lucide-react';
|
import { User, Upload, Trash2, Mail, AlertCircle, X } from 'lucide-react';
|
||||||
import { PhotoUpload } from '@/components/upload/PhotoUpload';
|
import { PhotoUpload } from '@/components/upload/PhotoUpload';
|
||||||
@@ -36,7 +37,8 @@ const profileSchema = z.object({
|
|||||||
type ProfileFormData = z.infer<typeof profileSchema>;
|
type ProfileFormData = z.infer<typeof profileSchema>;
|
||||||
|
|
||||||
export function AccountProfileTab() {
|
export function AccountProfileTab() {
|
||||||
const { user, profile, refreshProfile, pendingEmail, clearPendingEmail } = useAuth();
|
const { user, pendingEmail, clearPendingEmail } = useAuth();
|
||||||
|
const { data: profile, refreshProfile } = useProfile(user?.id);
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [avatarLoading, setAvatarLoading] = useState(false);
|
const [avatarLoading, setAvatarLoading] = useState(false);
|
||||||
|
|||||||
@@ -6,13 +6,12 @@ import { Separator } from '@/components/ui/separator';
|
|||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { useToast } from '@/hooks/use-toast';
|
import { useToast } from '@/hooks/use-toast';
|
||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
|
import { useProfile } from '@/hooks/useProfile';
|
||||||
import { supabase } from '@/integrations/supabase/client';
|
import { supabase } from '@/integrations/supabase/client';
|
||||||
import { Download, BarChart3, Upload, FileText, History } from 'lucide-react';
|
import { Download, BarChart3, Upload, FileText, History } from 'lucide-react';
|
||||||
export function DataExportTab() {
|
export function DataExportTab() {
|
||||||
const {
|
const { user } = useAuth();
|
||||||
user,
|
const { data: profile } = useProfile(user?.id);
|
||||||
profile
|
|
||||||
} = useAuth();
|
|
||||||
const {
|
const {
|
||||||
toast
|
toast
|
||||||
} = useToast();
|
} = useToast();
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { Separator } from '@/components/ui/separator';
|
|||||||
import { Switch } from '@/components/ui/switch';
|
import { Switch } from '@/components/ui/switch';
|
||||||
import { useToast } from '@/hooks/use-toast';
|
import { useToast } from '@/hooks/use-toast';
|
||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
|
import { useProfile } from '@/hooks/useProfile';
|
||||||
import { useUnitPreferences } from '@/hooks/useUnitPreferences';
|
import { useUnitPreferences } from '@/hooks/useUnitPreferences';
|
||||||
import { supabase } from '@/integrations/supabase/client';
|
import { supabase } from '@/integrations/supabase/client';
|
||||||
import { MapPin, Calendar, Globe, Accessibility, Ruler } from 'lucide-react';
|
import { MapPin, Calendar, Globe, Accessibility, Ruler } from 'lucide-react';
|
||||||
@@ -28,14 +29,9 @@ interface AccessibilityOptions {
|
|||||||
reduced_motion: boolean;
|
reduced_motion: boolean;
|
||||||
}
|
}
|
||||||
export function LocationTab() {
|
export function LocationTab() {
|
||||||
const {
|
const { user } = useAuth();
|
||||||
user,
|
const { data: profile, refreshProfile } = useProfile(user?.id);
|
||||||
profile,
|
const { toast } = useToast();
|
||||||
refreshProfile
|
|
||||||
} = useAuth();
|
|
||||||
const {
|
|
||||||
toast
|
|
||||||
} = useToast();
|
|
||||||
const { preferences: unitPreferences, updatePreferences: updateUnitPreferences } = useUnitPreferences();
|
const { preferences: unitPreferences, updatePreferences: updateUnitPreferences } = useUnitPreferences();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [parks, setParks] = useState<any[]>([]);
|
const [parks, setParks] = useState<any[]>([]);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/com
|
|||||||
import { Separator } from '@/components/ui/separator';
|
import { Separator } from '@/components/ui/separator';
|
||||||
import { useToast } from '@/hooks/use-toast';
|
import { useToast } from '@/hooks/use-toast';
|
||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
|
import { useProfile } from '@/hooks/useProfile';
|
||||||
import { supabase } from '@/integrations/supabase/client';
|
import { supabase } from '@/integrations/supabase/client';
|
||||||
import { Eye, UserX, Shield, Search } from 'lucide-react';
|
import { Eye, UserX, Shield, Search } from 'lucide-react';
|
||||||
import { BlockedUsers } from '@/components/privacy/BlockedUsers';
|
import { BlockedUsers } from '@/components/privacy/BlockedUsers';
|
||||||
@@ -26,14 +27,9 @@ interface ProfilePrivacy {
|
|||||||
show_pronouns: boolean;
|
show_pronouns: boolean;
|
||||||
}
|
}
|
||||||
export function PrivacyTab() {
|
export function PrivacyTab() {
|
||||||
const {
|
const { user } = useAuth();
|
||||||
user,
|
const { data: profile, refreshProfile } = useProfile(user?.id);
|
||||||
profile,
|
const { toast } = useToast();
|
||||||
refreshProfile
|
|
||||||
} = useAuth();
|
|
||||||
const {
|
|
||||||
toast
|
|
||||||
} = useToast();
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [preferences, setPreferences] = useState<PrivacySettings | null>(null);
|
const [preferences, setPreferences] = useState<PrivacySettings | null>(null);
|
||||||
const form = useForm<ProfilePrivacy & PrivacySettings>({
|
const form = useForm<ProfilePrivacy & PrivacySettings>({
|
||||||
|
|||||||
@@ -8,12 +8,10 @@ import { authLog, authWarn, authError } from '@/lib/authLogger';
|
|||||||
interface AuthContextType {
|
interface AuthContextType {
|
||||||
user: User | null;
|
user: User | null;
|
||||||
session: Session | null;
|
session: Session | null;
|
||||||
profile: Profile | null;
|
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
pendingEmail: string | null;
|
pendingEmail: string | null;
|
||||||
sessionError: string | null;
|
sessionError: string | null;
|
||||||
signOut: () => Promise<void>;
|
signOut: () => Promise<void>;
|
||||||
refreshProfile: () => Promise<void>;
|
|
||||||
verifySession: () => Promise<boolean>;
|
verifySession: () => Promise<boolean>;
|
||||||
clearPendingEmail: () => void;
|
clearPendingEmail: () => void;
|
||||||
}
|
}
|
||||||
@@ -23,61 +21,16 @@ const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
|||||||
function AuthProviderComponent({ children }: { children: React.ReactNode }) {
|
function AuthProviderComponent({ children }: { children: React.ReactNode }) {
|
||||||
const [user, setUser] = useState<User | null>(null);
|
const [user, setUser] = useState<User | null>(null);
|
||||||
const [session, setSession] = useState<Session | null>(null);
|
const [session, setSession] = useState<Session | null>(null);
|
||||||
const [profile, setProfile] = useState<Profile | null>(null);
|
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [pendingEmail, setPendingEmail] = useState<string | null>(null);
|
const [pendingEmail, setPendingEmail] = useState<string | null>(null);
|
||||||
const [sessionError, setSessionError] = useState<string | null>(null);
|
const [sessionError, setSessionError] = useState<string | null>(null);
|
||||||
|
|
||||||
// Refs for lifecycle and cleanup management
|
// Refs for lifecycle and cleanup management
|
||||||
const isMountedRef = useRef(true);
|
|
||||||
const profileFetchTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
||||||
const novuUpdateTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
const novuUpdateTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||||
const fetchedUserIdRef = useRef<string | null>(null);
|
|
||||||
const previousEmailRef = useRef<string | null>(null);
|
const previousEmailRef = useRef<string | null>(null);
|
||||||
|
|
||||||
const fetchProfile = async (userId: string) => {
|
|
||||||
console.log('[Auth] 📡 fetchProfile called for userId:', userId);
|
|
||||||
try {
|
|
||||||
const { data, error } = await supabase
|
|
||||||
.from('profiles')
|
|
||||||
.select(`*, location:locations(*)`)
|
|
||||||
.eq('user_id', userId)
|
|
||||||
.maybeSingle();
|
|
||||||
|
|
||||||
console.log('[Auth] 📦 Profile fetch result:', {
|
|
||||||
hasData: !!data,
|
|
||||||
hasError: !!error,
|
|
||||||
avatar_url: data?.avatar_url
|
|
||||||
});
|
|
||||||
|
|
||||||
if (error && error.code !== 'PGRST116') {
|
|
||||||
authError('[Auth] ❌ Error fetching profile:', error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isMountedRef.current && data) {
|
|
||||||
console.log('[Auth] ✅ Setting profile state with data:', {
|
|
||||||
userId: data.user_id,
|
|
||||||
username: data.username,
|
|
||||||
avatar_url: data.avatar_url,
|
|
||||||
});
|
|
||||||
setProfile(data as Profile);
|
|
||||||
} else {
|
|
||||||
console.log('[Auth] ⚠️ NOT setting profile - mounted:', isMountedRef.current, 'hasData:', !!data);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
authError('[Auth] ❌ Exception in fetchProfile:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const refreshProfile = async () => {
|
|
||||||
if (user) {
|
|
||||||
await fetchProfile(user.id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Verify session is still valid - simplified
|
// Verify session is still valid - simplified
|
||||||
const verifySession = async (updateLoadingState = false) => {
|
const verifySession = async () => {
|
||||||
try {
|
try {
|
||||||
const { data: { session }, error } = await supabase.auth.getSession();
|
const { data: { session }, error } = await supabase.auth.getSession();
|
||||||
|
|
||||||
@@ -95,7 +48,7 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) {
|
|||||||
authLog('[Auth] Session verified:', session.user.email);
|
authLog('[Auth] Session verified:', session.user.email);
|
||||||
|
|
||||||
// Update state if session was found but not set
|
// Update state if session was found but not set
|
||||||
if (!user && isMountedRef.current) {
|
if (!user) {
|
||||||
setSession(session);
|
setSession(session);
|
||||||
setUser(session.user);
|
setUser(session.user);
|
||||||
}
|
}
|
||||||
@@ -142,17 +95,13 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) {
|
|||||||
authLog('[Auth] INITIAL_SESSION - no user');
|
authLog('[Auth] INITIAL_SESSION - no user');
|
||||||
setSession(null);
|
setSession(null);
|
||||||
setUser(null);
|
setUser(null);
|
||||||
setProfile(null);
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (event === 'SIGNED_OUT') {
|
} else if (event === 'SIGNED_OUT') {
|
||||||
authLog('[Auth] SIGNED_OUT - clearing state');
|
authLog('[Auth] SIGNED_OUT - clearing state');
|
||||||
console.log('[Auth] 🔴 SIGNED_OUT - clearing profile and fetch tracking');
|
|
||||||
fetchedUserIdRef.current = null;
|
|
||||||
setSession(null);
|
setSession(null);
|
||||||
setUser(null);
|
setUser(null);
|
||||||
setProfile(null);
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
@@ -222,24 +171,6 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) {
|
|||||||
if (currentEmail) {
|
if (currentEmail) {
|
||||||
previousEmailRef.current = currentEmail;
|
previousEmailRef.current = currentEmail;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle profile fetching for authenticated users (async, doesn't block loading)
|
|
||||||
if (session?.user) {
|
|
||||||
// Only fetch if we haven't fetched for this user yet
|
|
||||||
if (fetchedUserIdRef.current !== session.user.id) {
|
|
||||||
console.log('[Auth] 🔄 Fetching profile for user:', session.user.id);
|
|
||||||
fetchedUserIdRef.current = session.user.id;
|
|
||||||
|
|
||||||
if (profileFetchTimeoutRef.current) {
|
|
||||||
clearTimeout(profileFetchTimeoutRef.current);
|
|
||||||
profileFetchTimeoutRef.current = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchProfile(session.user.id);
|
|
||||||
} else {
|
|
||||||
console.log('[Auth] ✅ Profile already fetched for user:', session.user.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// THEN get initial session (this may trigger INITIAL_SESSION event)
|
// THEN get initial session (this may trigger INITIAL_SESSION event)
|
||||||
@@ -258,15 +189,9 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) {
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
authLog('[Auth] Cleaning up auth provider');
|
authLog('[Auth] Cleaning up auth provider');
|
||||||
isMountedRef.current = false;
|
|
||||||
fetchedUserIdRef.current = null;
|
|
||||||
subscription.unsubscribe();
|
subscription.unsubscribe();
|
||||||
|
|
||||||
// Clear any pending timeouts
|
// Clear any pending timeouts
|
||||||
if (profileFetchTimeoutRef.current) {
|
|
||||||
clearTimeout(profileFetchTimeoutRef.current);
|
|
||||||
profileFetchTimeoutRef.current = null;
|
|
||||||
}
|
|
||||||
if (novuUpdateTimeoutRef.current) {
|
if (novuUpdateTimeoutRef.current) {
|
||||||
clearTimeout(novuUpdateTimeoutRef.current);
|
clearTimeout(novuUpdateTimeoutRef.current);
|
||||||
novuUpdateTimeoutRef.current = null;
|
novuUpdateTimeoutRef.current = null;
|
||||||
@@ -289,12 +214,10 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) {
|
|||||||
const value = {
|
const value = {
|
||||||
user,
|
user,
|
||||||
session,
|
session,
|
||||||
profile,
|
|
||||||
loading,
|
loading,
|
||||||
pendingEmail,
|
pendingEmail,
|
||||||
sessionError,
|
sessionError,
|
||||||
signOut,
|
signOut,
|
||||||
refreshProfile,
|
|
||||||
verifySession,
|
verifySession,
|
||||||
clearPendingEmail,
|
clearPendingEmail,
|
||||||
};
|
};
|
||||||
|
|||||||
50
src/hooks/useProfile.tsx
Normal file
50
src/hooks/useProfile.tsx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
|
import { supabase } from '@/integrations/supabase/client';
|
||||||
|
import { Profile } from '@/types/database';
|
||||||
|
|
||||||
|
export function useProfile(userId: string | undefined) {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
const query = useQuery({
|
||||||
|
queryKey: ['profile', userId],
|
||||||
|
queryFn: async () => {
|
||||||
|
if (!userId) return null;
|
||||||
|
|
||||||
|
console.log('[useProfile] Fetching profile for userId:', userId);
|
||||||
|
|
||||||
|
const { data, error } = await supabase
|
||||||
|
.from('profiles')
|
||||||
|
.select('*, location:locations(*)')
|
||||||
|
.eq('user_id', userId)
|
||||||
|
.maybeSingle();
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error('[useProfile] Error:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('[useProfile] Profile loaded:', {
|
||||||
|
username: data?.username,
|
||||||
|
avatar_url: data?.avatar_url
|
||||||
|
});
|
||||||
|
|
||||||
|
return data as Profile;
|
||||||
|
},
|
||||||
|
enabled: !!userId,
|
||||||
|
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||||
|
refetchOnWindowFocus: false,
|
||||||
|
retry: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
const refreshProfile = () => {
|
||||||
|
if (userId) {
|
||||||
|
console.log('[useProfile] Invalidating profile cache for userId:', userId);
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['profile', userId] });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
...query,
|
||||||
|
refreshProfile,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import { Separator } from '@/components/ui/separator';
|
|||||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||||
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from '@/components/ui/alert-dialog';
|
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from '@/components/ui/alert-dialog';
|
||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
|
import { useProfile } from '@/hooks/useProfile';
|
||||||
import { useUsernameValidation } from '@/hooks/useUsernameValidation';
|
import { useUsernameValidation } from '@/hooks/useUsernameValidation';
|
||||||
import { User, MapPin, Calendar, Star, Trophy, Settings, Camera, Edit3, Save, X, ArrowLeft, Check, AlertCircle, Loader2, UserX, FileText, Image } from 'lucide-react';
|
import { User, MapPin, Calendar, Star, Trophy, Settings, Camera, Edit3, Save, X, ArrowLeft, Check, AlertCircle, Loader2, UserX, FileText, Image } from 'lucide-react';
|
||||||
import { Profile as ProfileType } from '@/types/database';
|
import { Profile as ProfileType } from '@/types/database';
|
||||||
@@ -36,9 +37,8 @@ export default function Profile() {
|
|||||||
const {
|
const {
|
||||||
toast
|
toast
|
||||||
} = useToast();
|
} = useToast();
|
||||||
const {
|
const { user: authUser } = useAuth();
|
||||||
refreshProfile
|
const { refreshProfile } = useProfile(authUser?.id);
|
||||||
} = useAuth();
|
|
||||||
const [profile, setProfile] = useState<ProfileType | null>(null);
|
const [profile, setProfile] = useState<ProfileType | null>(null);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [editing, setEditing] = useState(false);
|
const [editing, setEditing] = useState(false);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
|||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Settings, User, Shield, Eye, Bell, MapPin, Download, MonitorSmartphone } from 'lucide-react';
|
import { Settings, User, Shield, Eye, Bell, MapPin, Download, MonitorSmartphone } from 'lucide-react';
|
||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
|
import { useProfile } from '@/hooks/useProfile';
|
||||||
import { Navigate } from 'react-router-dom';
|
import { Navigate } from 'react-router-dom';
|
||||||
import { Header } from '@/components/layout/Header';
|
import { Header } from '@/components/layout/Header';
|
||||||
import { AccountProfileTab } from '@/components/settings/AccountProfileTab';
|
import { AccountProfileTab } from '@/components/settings/AccountProfileTab';
|
||||||
@@ -14,8 +15,11 @@ import { LocationTab } from '@/components/settings/LocationTab';
|
|||||||
import { DataExportTab } from '@/components/settings/DataExportTab';
|
import { DataExportTab } from '@/components/settings/DataExportTab';
|
||||||
|
|
||||||
export default function UserSettings() {
|
export default function UserSettings() {
|
||||||
const { user, loading } = useAuth();
|
const { user, loading: authLoading } = useAuth();
|
||||||
|
const { data: profile, isLoading: profileLoading } = useProfile(user?.id);
|
||||||
const [activeTab, setActiveTab] = useState('profile');
|
const [activeTab, setActiveTab] = useState('profile');
|
||||||
|
|
||||||
|
const loading = authLoading || profileLoading;
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user