sushilideaclan01's picture
first push
91d209c
import { useEffect, useState } from 'react';
import { AnimatePresence, motion } from 'framer-motion';
import { GenerationProvider, useGeneration } from '@/context/GenerationContext';
import { AuthProvider, useAuth } from '@/context/AuthContext';
import {
ProviderSelect,
GenerationForm,
GenerationProgress,
GenerationComplete,
ErrorDisplay,
Login,
LogoIcon
} from '@/components';
import { checkHealth } from '@/utils/api';
import type { HealthStatus } from '@/types';
// Main App Content (uses context)
function AppContent() {
const { isAuthenticated, loading: authLoading, logout } = useAuth();
const { state, selectProvider, reset } = useGeneration();
const [healthStatus, setHealthStatus] = useState<HealthStatus | null>(null);
const [healthError, setHealthError] = useState<string | null>(null);
// Check backend health on mount (must be called before any conditional returns)
useEffect(() => {
if (isAuthenticated) {
checkHealth()
.then(setHealthStatus)
.catch((err) => setHealthError(err.message));
}
}, [isAuthenticated]);
// Show login if not authenticated
if (authLoading) {
return (
<div className="min-h-screen flex items-center justify-center bg-mesh-pattern">
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-coral-500 mx-auto mb-4"></div>
<p className="text-void-400">Loading...</p>
</div>
</div>
);
}
if (!isAuthenticated) {
return <Login />;
}
// Render based on current step
const renderContent = () => {
switch (state.step) {
case 'idle':
return (
<ProviderSelect
onSelect={(provider) => selectProvider(provider)}
/>
);
case 'configuring':
return (
<GenerationForm
provider={state.provider!}
onBack={() => reset()}
/>
);
case 'generating_prompts':
case 'generating_video':
case 'processing':
return <GenerationProgress />;
case 'completed':
return <GenerationComplete />;
case 'error':
return <ErrorDisplay />;
default:
return (
<ProviderSelect
onSelect={(provider) => selectProvider(provider)}
/>
);
}
};
return (
<div className="min-h-screen flex flex-col bg-mesh-pattern">
{/* Header */}
<header className="glass-dark sticky top-0 z-50">
<div className="max-w-7xl mx-auto px-6 py-4">
<div className="flex items-center justify-between">
{/* Logo */}
<button
onClick={reset}
className="flex items-center gap-3 hover:opacity-80 transition-opacity"
>
<LogoIcon size={36} />
<div>
<h1 className="text-lg font-display font-bold text-void-100">
Video AdGenesis
</h1>
<p className="text-xs text-void-500 -mt-0.5">Studio</p>
</div>
</button>
{/* Status Indicator */}
<div className="flex items-center gap-4">
{/* Provider Badge */}
{state.provider && state.step !== 'idle' && (
<motion.span
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
className={`
px-3 py-1 rounded-full text-xs font-semibold
${state.provider === 'kling'
? 'bg-coral-500/20 text-coral-300'
: 'bg-electric-500/20 text-electric-300'
}
`}
>
{state.provider === 'kling' ? 'KIE API' : 'Replicate'}
</motion.span>
)}
{/* Backend Status */}
<div className="flex items-center gap-2">
<div
className={`w-2 h-2 rounded-full ${
healthError ? 'bg-red-500' :
healthStatus ? 'bg-green-500' : 'bg-amber-500 animate-pulse'
}`}
/>
<span className="text-xs text-void-400">
{healthError ? 'Backend Offline' :
healthStatus ? (healthStatus.is_dev_mode ? 'Dev Mode' : 'Production') :
'Connecting...'}
</span>
</div>
{/* Logout Button */}
<button
onClick={logout}
className="px-3 py-1.5 text-xs font-medium text-void-400 hover:text-void-200
hover:bg-void-800 rounded-lg transition-colors"
title="Logout"
>
Logout
</button>
</div>
</div>
</div>
</header>
{/* Main Content */}
<main className="flex-grow">
<AnimatePresence mode="wait">
<motion.div
key={state.step}
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ duration: 0.3 }}
>
{renderContent()}
</motion.div>
</AnimatePresence>
</main>
{/* Footer */}
<footer className="py-6 text-center">
<p className="text-xs text-void-600">
Powered by {' '}
<span className="text-coral-400">AdGenesis</span>
</p>
</footer>
</div>
);
}
// App Wrapper with Providers
function App() {
return (
<AuthProvider>
<GenerationProvider>
<AppContent />
</GenerationProvider>
</AuthProvider>
);
}
export default App;