website refactor

This commit is contained in:
2026-01-18 13:26:35 +01:00
parent 350c78504d
commit 0b301feb61
225 changed files with 1678 additions and 26666 deletions

View File

@@ -1,6 +1,7 @@
import { notFound, redirect } from 'next/navigation';
import { DashboardPageQuery } from '@/lib/page-queries/DashboardPageQuery';
import { DashboardTemplate } from '@/templates/DashboardTemplate';
import { logger } from '@/lib/infrastructure/logging/logger';
export default async function DashboardPage() {
const result = await DashboardPageQuery.execute();
@@ -15,7 +16,7 @@ export default async function DashboardPage() {
redirect('/');
} else {
// serverError, networkError, unknown, validationError, unauthorized
console.error('Dashboard error:', error);
logger.error('Dashboard error', undefined, { errorType: error });
notFound();
}
}

View File

@@ -0,0 +1,5 @@
import { NextResponse } from 'next/server';
export async function GET() {
return NextResponse.json({ status: 'ok', timestamp: new Date().toISOString() });
}

View File

@@ -6,6 +6,8 @@ import React from 'react';
import './globals.css';
import { AppWrapper } from '@/components/AppWrapper';
import { RootAppShellTemplate } from '@/templates/layout/RootAppShellTemplate';
import { getWebsiteServerEnv } from '@/lib/config/env';
import { logger } from '@/lib/infrastructure/logging/logger';
export const dynamic = 'force-dynamic';
@@ -46,7 +48,8 @@ export default async function RootLayout({
children: React.ReactNode;
}) {
// Initialize debug tools in development
if (process.env.NODE_ENV === 'development') {
const env = getWebsiteServerEnv();
if (env.NODE_ENV === 'development') {
try {
initializeGlobalErrorHandling({
showDevOverlay: true,
@@ -59,7 +62,7 @@ export default async function RootLayout({
logResponses: true,
});
} catch (error) {
console.warn('Failed to initialize debug tools:', error);
logger.warn('Failed to initialize debug tools', { error });
}
}

View File

@@ -2,6 +2,7 @@ import { notFound, redirect } from 'next/navigation';
import { DriverRankingsPageQuery } from '@/lib/page-queries/DriverRankingsPageQuery';
import { DriverRankingsPageClient } from './DriverRankingsPageClient';
import { routes } from '@/lib/routing/RouteConfig';
import { logger } from '@/lib/infrastructure/logging/logger';
export default async function DriverLeaderboardPage() {
const result = await DriverRankingsPageQuery.execute();
@@ -16,7 +17,7 @@ export default async function DriverLeaderboardPage() {
redirect(routes.public.home);
} else {
// serverError, networkError, unknown, validationError, unauthorized
console.error('Driver rankings error:', error);
logger.error('Driver rankings error:', undefined, { error });
notFound();
}
}

View File

@@ -2,6 +2,7 @@ import { notFound, redirect } from 'next/navigation';
import { LeaderboardsPageQuery } from '@/lib/page-queries/LeaderboardsPageQuery';
import { LeaderboardsPageClient } from './LeaderboardsPageClient';
import { routes } from '@/lib/routing/RouteConfig';
import { logger } from '@/lib/infrastructure/logging/logger';
export default async function LeaderboardsPage() {
const result = await LeaderboardsPageQuery.execute();
@@ -16,7 +17,7 @@ export default async function LeaderboardsPage() {
redirect(routes.public.home);
} else {
// serverError, networkError, unknown, validationError, unauthorized
console.error('Leaderboards error:', error);
logger.error('Leaderboards error:', undefined, { error });
notFound();
}
}

View File

@@ -1,7 +1,8 @@
'use client';
import React, { useState } from 'react';
import { LeagueCard } from '@/components/leagues/LeagueCard';
import { LeagueCard } from '@/components/leagues/LeagueCardWrapper';
import { LeagueSummaryViewModel } from '@/lib/view-models/LeagueSummaryViewModel';
import { routes } from '@/lib/routing/RouteConfig';
import type { LeaguesViewData } from '@/lib/view-data/LeaguesViewData';
import { Box } from '@/ui/Box';
@@ -26,7 +27,6 @@ import {
type LucideIcon,
} from 'lucide-react';
import { useRouter } from 'next/navigation';
import { getMediaUrl } from '@/lib/utilities/media';
// ============================================================================
// TYPES
@@ -252,15 +252,7 @@ export function LeaguesPageClient({ viewData }: LeaguesTemplateProps) {
{filteredLeagues.map((league) => (
<LeagueCard
key={league.id}
id={league.id}
name={league.name}
description={league.description || undefined}
coverUrl={getMediaUrl('league-cover', league.id)}
logoUrl={league.logoUrl || undefined}
gameName={league.scoring?.gameName}
memberCount={league.usedDriverSlots || 0}
maxMembers={league.maxDrivers}
championshipType={(league.scoring?.primaryChampionshipType as 'driver' | 'team' | 'nations' | 'trophy') || 'driver'}
league={league as unknown as LeagueSummaryViewModel}
onClick={() => router.push(routes.league.detail(league.id))}
/>
))}

View File

@@ -2,7 +2,7 @@
import React, { useState } from 'react';
import { LeagueRulebookTemplate } from '@/templates/LeagueRulebookTemplate';
import { type RulebookSection } from '@/ui/RulebookTabs';
import { type RulebookSection } from '@/components/leagues/RulebookTabs';
import type { LeagueRulebookViewData } from '@/lib/view-data/LeagueRulebookViewData';
interface LeagueRulebookPageClientProps {

View File

@@ -1,7 +1,7 @@
'use client';
import { StewardingQueuePanel } from '@/components/leagues/StewardingQueuePanel';
import { PenaltyFAB } from '@/ui/PenaltyFAB';
import { PenaltyFAB } from '@/components/races/PenaltyFAB';
import { QuickPenaltyModal } from '@/components/leagues/QuickPenaltyModal';
import { ReviewProtestModal } from '@/components/leagues/ReviewProtestModal';
import { StewardingStats } from '@/components/leagues/StewardingStats';

View File

@@ -1,6 +1,7 @@
'use client';
import { useState, useMemo } from 'react';
import { useRouter } from 'next/navigation';
import { RacesTemplate, type TimeFilter, type RaceStatusFilter } from '@/templates/RacesTemplate';
import type { RacesViewData } from '@/lib/view-data/RacesViewData';
@@ -9,6 +10,7 @@ interface RacesPageClientProps {
}
export function RacesPageClient({ viewData }: RacesPageClientProps) {
const router = useRouter();
const [statusFilter, setStatusFilter] = useState<RaceStatusFilter>('all');
const [leagueFilter, setLeagueFilter] = useState<string>('all');
const [timeFilter, setTimeFilter] = useState<TimeFilter>('upcoming');
@@ -56,8 +58,8 @@ export function RacesPageClient({ viewData }: RacesPageClientProps) {
setTimeFilter={setTimeFilter}
showFilterModal={showFilterModal}
setShowFilterModal={setShowFilterModal}
onRaceClick={(id) => console.log('Race click', id)}
onLeagueClick={(id) => console.log('League click', id)}
onRaceClick={(id) => router.push(`/races/${id}`)}
onLeagueClick={(id) => router.push(`/leagues/${id}`)}
onWithdraw={(id) => console.log('Withdraw', id)}
onCancel={(id) => console.log('Cancel', id)}
/>

View File

@@ -1,6 +1,7 @@
import { headers } from 'next/headers';
import { redirect } from 'next/navigation';
import { createRouteGuard } from '@/lib/auth/createRouteGuard';
import { Box } from '@/ui/Box';
interface SponsorLayoutProps {
children: React.ReactNode;
@@ -23,8 +24,8 @@ export default async function SponsorLayout({ children }: SponsorLayoutProps) {
}
return (
<div className="min-h-screen bg-deep-graphite">
<Box minHeight="screen" bg="bg-deep-graphite">
{children}
</div>
</Box>
);
}

View File

@@ -3,7 +3,7 @@
import React, { useState, useMemo } from 'react';
import { SponsorLeaguesTemplate, type SortOption, type TierFilter, type AvailabilityFilter } from '@/templates/SponsorLeaguesTemplate';
export default function SponsorLeaguesPageClient({ data }: { data: unknown }) {
export function SponsorLeaguesPageClient({ data }: { data: unknown }) {
const [searchQuery, setSearchQuery] = useState('');
const [tierFilter] = useState<TierFilter>('all');
const [availabilityFilter] = useState<AvailabilityFilter>('all');

View File

@@ -3,7 +3,7 @@
import React, { useState } from 'react';
import { SponsorLeagueDetailTemplate } from '@/templates/SponsorLeagueDetailTemplate';
export default function SponsorLeagueDetailPageClient({ data }: { data: any }) {
export function SponsorLeagueDetailPageClient({ data }: { data: any }) {
const [activeTab, setActiveTab] = useState<'overview' | 'drivers' | 'races' | 'sponsor'>('overview');
const [selectedTier, setSelectedTier] = useState<'main' | 'secondary'>('main');

View File

@@ -1,20 +1,22 @@
import { notFound } from 'next/navigation';
import { PageWrapper } from '@/components/shared/state/PageWrapper';
import SponsorLeagueDetailPageClient from './SponsorLeagueDetailPageClient';
import { SponsorLeagueDetailPageClient } from './SponsorLeagueDetailPageClient';
import { SponsorsApiClient } from '@/lib/api/sponsors/SponsorsApiClient';
import { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';
import { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';
import { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';
import { getWebsiteServerEnv } from '@/lib/config/env';
export default async function Page({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params;
// Manual wiring: create dependencies
const baseUrl = getWebsiteApiBaseUrl();
const env = getWebsiteServerEnv();
const logger = new ConsoleLogger();
const errorReporter = new EnhancedErrorReporter(logger, {
showUserNotifications: true,
logToConsole: true,
reportToExternal: process.env.NODE_ENV === 'production',
reportToExternal: env.NODE_ENV === 'production',
});
// Create API client

View File

@@ -1,18 +1,20 @@
import { PageWrapper } from '@/components/shared/state/PageWrapper';
import SponsorLeaguesPageClient from './SponsorLeaguesPageClient';
import { SponsorLeaguesPageClient } from './SponsorLeaguesPageClient';
import { SponsorsApiClient } from '@/lib/api/sponsors/SponsorsApiClient';
import { EnhancedErrorReporter } from '@/lib/infrastructure/EnhancedErrorReporter';
import { ConsoleLogger } from '@/lib/infrastructure/logging/ConsoleLogger';
import { getWebsiteApiBaseUrl } from '@/lib/config/apiBaseUrl';
import { getWebsiteServerEnv } from '@/lib/config/env';
export default async function Page() {
// Manual wiring: create dependencies
const baseUrl = getWebsiteApiBaseUrl();
const env = getWebsiteServerEnv();
const logger = new ConsoleLogger();
const errorReporter = new EnhancedErrorReporter(logger, {
showUserNotifications: true,
logToConsole: true,
reportToExternal: process.env.NODE_ENV === 'production',
reportToExternal: env.NODE_ENV === 'production',
});
// Create API client

View File

@@ -5,6 +5,8 @@ import { SponsorSettingsTemplate } from '@/templates/SponsorSettingsTemplate';
import { logoutAction } from '@/app/actions/logoutAction';
import { ConfirmDialog } from '@/components/shared/ux/ConfirmDialog';
import { useRouter } from 'next/navigation';
import { routes } from '@/lib/routing/RouteConfig';
import { logger } from '@/lib/infrastructure/logging/logger';
// ============================================================================
// Mock Data
@@ -61,7 +63,7 @@ export default function SponsorSettingsPage() {
const handleSaveProfile = async () => {
setSaving(true);
await new Promise(resolve => setTimeout(resolve, 800));
console.log('Profile saved:', profile);
logger.info('Profile saved', { profile });
setSaving(false);
setSaved(true);
setTimeout(() => setSaved(false), 3000);
@@ -71,11 +73,11 @@ export default function SponsorSettingsPage() {
setIsDeleting(true);
const result = await logoutAction();
if (result.isErr()) {
console.error('Logout failed:', result.getError());
logger.error('Logout failed', new Error(result.getError()));
setIsDeleting(false);
return;
}
router.push('/auth/login');
router.push(routes.auth.login);
};
const viewData = {