110 lines
3.0 KiB
TypeScript
110 lines
3.0 KiB
TypeScript
import { useEffect } from 'react';
|
|
import { BrowserRouter, Routes, Route, Navigate, useLocation } from 'react-router-dom';
|
|
import { useTranslation } from 'react-i18next';
|
|
import Login from './pages/Login';
|
|
import FamilyView from './pages/FamilyView';
|
|
import AdminPanel from './pages/AdminPanel';
|
|
import NoFamily from './pages/NoFamily';
|
|
import InvitePage from './pages/InvitePage';
|
|
import Profile from './pages/Profile';
|
|
import { useStore } from './store/useStore';
|
|
import { authApi } from './api/client';
|
|
import { Loader2 } from 'lucide-react';
|
|
|
|
function AppContent() {
|
|
const { t, i18n } = useTranslation();
|
|
const { user, isAuthenticated, isLoading, setUser, setIsLoading } = useStore();
|
|
const location = useLocation();
|
|
|
|
const themeColors: Record<string, string> = {
|
|
light: '#667eea',
|
|
dark: '#000000',
|
|
sunset: '#f97316',
|
|
ocean: '#3b82f6',
|
|
forest: '#22c55e',
|
|
purple: '#8b5cf6',
|
|
};
|
|
|
|
useEffect(() => {
|
|
const storedTheme = localStorage.getItem('theme') || 'light';
|
|
document.documentElement.setAttribute('data-theme', storedTheme);
|
|
const metaTheme = document.querySelector('meta[name="theme-color"]');
|
|
if (metaTheme) metaTheme.setAttribute('content', themeColors[storedTheme] ?? '#667eea');
|
|
|
|
const storedLocale = localStorage.getItem('locale');
|
|
if (storedLocale && storedLocale !== i18n.language) {
|
|
i18n.changeLanguage(storedLocale);
|
|
}
|
|
|
|
checkAuth();
|
|
}, []);
|
|
|
|
const checkAuth = async () => {
|
|
try {
|
|
const response = await authApi.me();
|
|
setUser(response.data);
|
|
} catch {
|
|
setUser(null);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
if (location.pathname.startsWith('/invite/')) {
|
|
return (
|
|
<Routes>
|
|
<Route path="/invite/:token" element={<InvitePage />} />
|
|
</Routes>
|
|
);
|
|
}
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div className="min-h-screen flex items-center justify-center gradient-bg">
|
|
<div className="flex items-center gap-3 text-white">
|
|
<Loader2 className="w-8 h-8 animate-spin" />
|
|
<span className="text-xl font-medium">{t('common.loading')}</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!isAuthenticated) {
|
|
return (
|
|
<Routes>
|
|
<Route path="*" element={<Login />} />
|
|
</Routes>
|
|
);
|
|
}
|
|
|
|
if (!user?.family_id) {
|
|
return (
|
|
<Routes>
|
|
<Route path="/adminpanel" element={<AdminPanel />} />
|
|
<Route path="/profile" element={<Profile />} />
|
|
<Route path="*" element={<NoFamily />} />
|
|
</Routes>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Routes>
|
|
<Route path="/" element={<Navigate to={`/family/${user.family_id}`} replace />} />
|
|
<Route path="/family/:familyId" element={<FamilyView />} />
|
|
<Route path="/profile" element={<Profile />} />
|
|
<Route path="/adminpanel" element={<AdminPanel />} />
|
|
<Route path="*" element={<Navigate to={`/family/${user.family_id}`} replace />} />
|
|
</Routes>
|
|
);
|
|
}
|
|
|
|
function App() {
|
|
return (
|
|
<BrowserRouter>
|
|
<AppContent />
|
|
</BrowserRouter>
|
|
);
|
|
}
|
|
|
|
export default App;
|