Spotix-API / frontend /contexts /AuthContext.tsx
Anish-530
Fixed Mobile support. Added a new AI media detection mechanism by Farid, that creates geometric lines. Fixed logs
817ad83
"use client";
import React, { createContext, useContext, useState, useEffect, useRef } from 'react';
import { usePathname } from 'next/navigation';
import { useRouter } from 'next/navigation';
import { apiLayer } from '@/lib/api';
type UserData = {
id: number;
email: string;
name: string;
is_admin: boolean;
avatar_url?: string | null;
google_avatar_url?: string | null;
created_at?: string | null;
};
type AuthContextType = {
isAuthenticated: boolean;
user: UserData | null;
loading: boolean;
logout: () => void;
updateUser: (data: Partial<UserData>) => void;
};
const AuthContext = createContext<AuthContextType>({ isAuthenticated: false, user: null, loading: true, logout: () => {}, updateUser: () => {} });
export function AuthProvider({ children }: { children: React.ReactNode }) {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [user, setUser] = useState<UserData | null>(null);
const [loading, setLoading] = useState(true);
// Guard against double-execution in React StrictMode / Next.js App Router
// (router from useRouter() gets a new identity on every render, so we NEVER
// put it in the dep array — we check auth exactly once on mount)
const hasFetched = useRef(false);
const router = useRouter();
const pathname = usePathname();
useEffect(() => {
if (hasFetched.current) return;
hasFetched.current = true;
setLoading(true);
apiLayer.getCurrentUser()
.then((res) => {
setUser(res.data);
setIsAuthenticated(true);
})
.catch(() => {
setIsAuthenticated(false);
setUser(null);
// Only redirect to login from protected routes
if (pathname?.includes('/dashboard') || pathname?.includes('/profile')) {
router.push('/login');
}
})
.finally(() => {
setLoading(false);
});
// Empty deps: intentional. Auth is checked once on mount, never on re-render.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const logout = () => {
localStorage.removeItem("access_token");
setIsAuthenticated(false);
setUser(null);
hasFetched.current = false; // Allow re-check after logout
router.push("/login");
};
const updateUser = (data: Partial<UserData>) => {
setUser(prev => prev ? { ...prev, ...data } : null);
};
return (
<AuthContext.Provider value={{ isAuthenticated, user, loading, logout, updateUser }}>
{children}
</AuthContext.Provider>
);
}
export const useAuth = () => useContext(AuthContext);