This commit is contained in:
Tomas Dvorak
2025-11-02 21:31:00 +01:00
parent b9cea0cd77
commit 087f30e82c
130 changed files with 20104 additions and 34330 deletions
+33
View File
@@ -54,6 +54,8 @@ import NavigationAdminPage from './pages/admin/NavigationAdminPage';
import ShortlinksAdminPage from './pages/admin/ShortlinksAdminPage';
import CommentsAdminPage from './pages/admin/CommentsAdminPage';
import EngagementAdminPage from './pages/admin/EngagementAdminPage';
import SweepstakesAdminPage from './pages/admin/SweepstakesAdminPage';
import SweepstakeVisualPage from './pages/admin/SweepstakeVisualPage';
import SemiAdminPage from './pages/SemiAdminPage';
import PollsAdminPage from './pages/admin/PollsAdminPage';
// Admin pages render their own AdminLayout internally
@@ -69,6 +71,7 @@ import NewsletterPreferencesPage from './pages/NewsletterPreferencesPage';
import { ClubThemeProvider } from './contexts/ClubThemeContext';
import CookiePolicyPage from './pages/legal/CookiePolicyPage';
import OverlayScoreboardPage from './pages/OverlayScoreboardPage';
import OverlaySponsorsPage from './pages/OverlaySponsorsPage';
import CookieBanner from './components/CookieBanner';
import DefaultSEO from './components/seo/DefaultSEO';
import ProtectedRoute from './components/ProtectedRoute';
@@ -82,6 +85,7 @@ import ShortRedirectPage from './pages/ShortRedirectPage';
import ClothingPage from './pages/ClothingPage';
import PollsPage from './pages/PollsPage';
import { useUmami } from './hooks/useUmami';
import { checkin } from './services/engagement';
import { useFontLoader } from './hooks/useFontLoader';
// Create a client with better cache configuration
@@ -262,6 +266,31 @@ const FontLoader: React.FC = () => {
return null;
};
// Component to trigger daily check-in for authenticated users (once per day per device)
const CheckinInitializer: React.FC = () => {
const { isAuthenticated } = useAuth();
useEffect(() => {
if (!isAuthenticated) return;
let cancelled = false;
const todayKey = (() => {
const d = new Date();
const y = d.getFullYear();
const m = String(d.getMonth() + 1).padStart(2, '0');
const day = String(d.getDate()).padStart(2, '0');
return `fc_checkin_${y}-${m}-${day}`;
})();
try {
if (localStorage.getItem(todayKey) === '1') return;
} catch {}
// Fire and forget; backend caps ensure idempotence server-side
(async () => {
try { await checkin(); if (!cancelled) { try { localStorage.setItem(todayKey, '1'); } catch {} } } catch {}
})();
return () => { cancelled = true; };
}, [isAuthenticated]);
return null;
};
// Redirect /news -> /blog while preserving query parameters
const NewsRedirect: React.FC = () => {
const loc = useLocation();
@@ -333,6 +362,7 @@ const App: React.FC = () => {
<ClubThemeProvider>
<AnalyticsInitializer />
<FontLoader />
<CheckinInitializer />
<DefaultSEO />
<Routes>
{/* Public routes */}
@@ -340,6 +370,7 @@ const App: React.FC = () => {
<Route path="/hledat" element={<SearchPage />} />
<Route path="/search" element={<SearchPage />} />
<Route path="/overlay/scoreboard" element={<OverlayScoreboardPage />} />
<Route path="/overlay/sponsors" element={<OverlaySponsorsPage />} />
<Route path="/blog" element={<BlogPage />} />
<Route path="/klub" element={<ClubPage />} />
<Route path="/o-klubu" element={<AboutPage />} />
@@ -458,6 +489,8 @@ const App: React.FC = () => {
<Route path="/admin/navigace" element={<NavigationAdminPage />} />
<Route path="/admin/komentare" element={<CommentsAdminPage />} />
<Route path="/admin/engagement" element={<EngagementAdminPage />} />
<Route path="/admin/sweepstakes" element={<SweepstakesAdminPage />} />
<Route path="/admin/sweepstakes/:id/visual" element={<SweepstakeVisualPage />} />
</Route>
{/* Remaining protected routes that don't use AdminLayout */}