forge/frontend/components/AuthProvider.tsx
DJP 7a804e896d Initial commit - FORGE AI unified platform
Features:
- Image generation (OpenAI, Gemini, Leonardo, Bria, Stability, Flux)
- Nano Banana iterative editing
- Video generation and upscaling
- Audio TTS, STT, sound effects (ElevenLabs)
- Text prompt studio and alt text
- User authentication with JWT/cookies
- Admin panel with voice management
- Job queue with Celery
- PostgreSQL + Redis backend
- Next.js 15 + FastAPI architecture

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

Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
2025-12-09 20:39:00 -05:00

77 lines
2.3 KiB
TypeScript

'use client';
import { useEffect, useState } from 'react';
import { useRouter, usePathname } from 'next/navigation';
import { useStore } from '@/lib/store';
import { authApi } from '@/lib/api';
import { Loader2 } from 'lucide-react';
// Pages that don't require authentication
const PUBLIC_PAGES = ['/login', '/signup'];
export default function AuthProvider({ children }: { children: React.ReactNode }) {
const router = useRouter();
const pathname = usePathname();
const { user, token, setUser, setToken, logout } = useStore();
const [loading, setLoading] = useState(true);
useEffect(() => {
const initAuth = async () => {
// If on a public page, no need to check auth
if (PUBLIC_PAGES.includes(pathname)) {
setLoading(false);
return;
}
// Try to verify auth with the backend (uses cookie automatically)
try {
const response = await authApi.me();
if (response.data) {
const userData = {
id: response.data.id,
email: response.data.email,
name: response.data.display_name || response.data.email,
role: response.data.role,
avatar_url: response.data.avatar_url,
};
setUser(userData);
// Also set a dummy token for compatibility (actual auth is via cookie)
setToken('cookie-auth');
}
} catch (error) {
// Not authenticated, clear state and redirect
console.log('Not authenticated, redirecting to login');
logout();
router.push('/login');
}
setLoading(false);
};
initAuth();
}, [pathname]);
// Show loading spinner while checking auth
if (loading && !PUBLIC_PAGES.includes(pathname)) {
return (
<div className="min-h-screen bg-forge-gray flex items-center justify-center">
<div className="text-center">
<Loader2 className="w-8 h-8 text-forge-yellow animate-spin mx-auto mb-4" />
<p className="text-gray-500">Loading...</p>
</div>
</div>
);
}
// On public pages, just render children
if (PUBLIC_PAGES.includes(pathname)) {
return <>{children}</>;
}
// On protected pages, only render if we have a user
if (!user && !loading) {
return null;
}
return <>{children}</>;
}