website refactor

This commit is contained in:
2026-01-18 18:27:39 +01:00
parent 067502a4c6
commit c35682cae5
36 changed files with 47 additions and 108 deletions

View File

@@ -6,9 +6,9 @@
* 2. Client component renders with ViewData * 2. Client component renders with ViewData
*/ */
import { AuthError } from '@/components/auth/AuthError';
import { ForgotPasswordPageQuery } from '@/lib/page-queries/auth/ForgotPasswordPageQuery'; import { ForgotPasswordPageQuery } from '@/lib/page-queries/auth/ForgotPasswordPageQuery';
import { ForgotPasswordClient } from './ForgotPasswordClient'; import { ForgotPasswordClient } from './ForgotPasswordClient';
import { AuthError } from '@/ui/AuthError';
export default async function ForgotPasswordPage({ export default async function ForgotPasswordPage({
searchParams, searchParams,

View File

@@ -7,17 +7,17 @@
'use client'; 'use client';
import { useState, useEffect, useMemo } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import { useAuth } from '@/components/auth/AuthContext'; import { useAuth } from '@/components/auth/AuthContext';
import { AuthLoading } from '@/components/auth/AuthLoading';
import { LoginFlowController, LoginState } from '@/lib/auth/LoginFlowController'; import { LoginFlowController, LoginState } from '@/lib/auth/LoginFlowController';
import { LoginViewData } from '@/lib/builders/view-data/types/LoginViewData'; import { LoginViewData } from '@/lib/builders/view-data/types/LoginViewData';
import { LoginTemplate } from '@/templates/auth/LoginTemplate'; import { LoginViewModelBuilder } from '@/lib/builders/view-models/LoginViewModelBuilder';
import { LoginMutation } from '@/lib/mutations/auth/LoginMutation'; import { LoginMutation } from '@/lib/mutations/auth/LoginMutation';
import { validateLoginForm, type LoginFormValues } from '@/lib/utils/validation'; import { validateLoginForm, type LoginFormValues } from '@/lib/utils/validation';
import { LoginViewModelBuilder } from '@/lib/builders/view-models/LoginViewModelBuilder';
import { LoginViewModel } from '@/lib/view-models/auth/LoginViewModel'; import { LoginViewModel } from '@/lib/view-models/auth/LoginViewModel';
import { AuthLoading } from '@/ui/AuthLoading'; import { LoginTemplate } from '@/templates/auth/LoginTemplate';
import { useRouter, useSearchParams } from 'next/navigation';
import { useEffect, useMemo, useState } from 'react';
interface LoginClientProps { interface LoginClientProps {
viewData: LoginViewData; viewData: LoginViewData;

View File

@@ -6,9 +6,9 @@
* 2. Client component renders with ViewData * 2. Client component renders with ViewData
*/ */
import { AuthError } from '@/components/auth/AuthError';
import { LoginPageQuery } from '@/lib/page-queries/auth/LoginPageQuery'; import { LoginPageQuery } from '@/lib/page-queries/auth/LoginPageQuery';
import { LoginClient } from './LoginClient'; import { LoginClient } from './LoginClient';
import { AuthError } from '@/ui/AuthError';
export default async function LoginPage({ export default async function LoginPage({
searchParams, searchParams,

View File

@@ -6,9 +6,9 @@
* 2. Client component renders with ViewData * 2. Client component renders with ViewData
*/ */
import { AuthError } from '@/components/auth/AuthError';
import { ResetPasswordPageQuery } from '@/lib/page-queries/auth/ResetPasswordPageQuery'; import { ResetPasswordPageQuery } from '@/lib/page-queries/auth/ResetPasswordPageQuery';
import { ResetPasswordClient } from './ResetPasswordClient'; import { ResetPasswordClient } from './ResetPasswordClient';
import { AuthError } from '@/ui/AuthError';
export default async function ResetPasswordPage({ export default async function ResetPasswordPage({
searchParams, searchParams,

View File

@@ -6,9 +6,9 @@
* 2. Client component renders with ViewData * 2. Client component renders with ViewData
*/ */
import { AuthError } from '@/components/auth/AuthError';
import { SignupPageQuery } from '@/lib/page-queries/auth/SignupPageQuery'; import { SignupPageQuery } from '@/lib/page-queries/auth/SignupPageQuery';
import { SignupClient } from './SignupClient'; import { SignupClient } from './SignupClient';
import { AuthError } from '@/ui/AuthError';
export default async function SignupPage({ export default async function SignupPage({
searchParams, searchParams,

View File

@@ -1,10 +1,10 @@
'use client'; 'use client';
import type { ProfileTab } from '@/components/profile/ProfileTabs';
import type { DriverProfileViewData } from '@/lib/types/view-data/DriverProfileViewData'; import type { DriverProfileViewData } from '@/lib/types/view-data/DriverProfileViewData';
import { DriverProfileTemplate } from '@/templates/DriverProfileTemplate'; import { DriverProfileTemplate } from '@/templates/DriverProfileTemplate';
import { Container } from '@/ui/Container'; import { Container } from '@/ui/Container';
import { Stack } from '@/ui/primitives/Stack'; import { Stack } from '@/ui/primitives/Stack';
import type { ProfileTab } from '@/ui/ProfileTabs';
import { Text } from '@/ui/Text'; import { Text } from '@/ui/Text';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { useState } from 'react'; import { useState } from 'react';

View File

@@ -1,6 +1,6 @@
import { ErrorBanner } from './ErrorBanner'; import { ErrorBanner } from '../../ui/ErrorBanner';
interface AuthErrorProps { interface AuthErrorProps {
action: string; action: string;

View File

@@ -1,8 +1,7 @@
import React from 'react'; import { LoadingSpinner } from '../../ui/LoadingSpinner';
import { Box } from './primitives/Box'; import { Box } from '../../ui/primitives/Box';
import { Stack } from './primitives/Stack'; import { Stack } from '../../ui/primitives/Stack';
import { LoadingSpinner } from './LoadingSpinner'; import { Text } from '../../ui/Text';
import { Text } from './Text';
interface AuthLoadingProps { interface AuthLoadingProps {
message?: string; message?: string;

View File

@@ -1,12 +1,11 @@
import React from 'react'; import { Flag, Star, Trophy, Users } from 'lucide-react';
import { Box } from './primitives/Box'; import { Avatar } from '../../ui/Avatar';
import { Stack } from './primitives/Stack'; import { Badge } from '../../ui/Badge';
import { Text } from './Text'; import { Heading } from '../../ui/Heading';
import { Heading } from './Heading'; import { Icon } from '../../ui/Icon';
import { Avatar } from './Avatar'; import { Box } from '../../ui/primitives/Box';
import { Badge } from './Badge'; import { Stack } from '../../ui/primitives/Stack';
import { Trophy, Flag, Users, Star } from 'lucide-react'; import { Text } from '../../ui/Text';
import { Icon } from './Icon';
interface DashboardHeroProps { interface DashboardHeroProps {
driverName: string; driverName: string;

View File

@@ -1,6 +1,6 @@
import { DashboardHero as UiDashboardHero } from '@/components/dashboard/DashboardHero';
import { routes } from '@/lib/routing/RouteConfig'; import { routes } from '@/lib/routing/RouteConfig';
import { Button } from '@/ui/Button'; import { Button } from '@/ui/Button';
import { DashboardHero as UiDashboardHero } from '@/ui/DashboardHero';
import { Icon } from '@/ui/Icon'; import { Icon } from '@/ui/Icon';
import { Link } from '@/ui/Link'; import { Link } from '@/ui/Link';
import { StatBox } from '@/ui/StatBox'; import { StatBox } from '@/ui/StatBox';

View File

@@ -1,6 +1,5 @@
import React from 'react'; import { Box } from '../../ui/primitives/Box';
import { Box } from './primitives/Box'; import { Text } from '../../ui/Text';
import { Text } from './Text';
interface OnboardingErrorProps { interface OnboardingErrorProps {
message: string; message: string;

View File

@@ -1,5 +1,5 @@
import React, { ReactNode, FormEvent } from 'react'; import { FormEvent, ReactNode } from 'react';
import { Box } from './primitives/Box'; import { Box } from '../../ui/primitives/Box';
interface OnboardingFormProps { interface OnboardingFormProps {
children: ReactNode; children: ReactNode;

View File

@@ -1,7 +1,6 @@
import React from 'react'; import { Box } from '../../ui/primitives/Box';
import { Box } from './primitives/Box'; import { Grid } from '../../ui/primitives/Grid';
import { Text } from './Text'; import { Text } from '../../ui/Text';
import { Grid } from './primitives/Grid';
interface Stat { interface Stat {
label: string; label: string;

View File

@@ -5,6 +5,7 @@ import { CreateDriverForm } from '@/components/drivers/CreateDriverForm';
import { ProfileDetailsPanel } from '@/components/profile/ProfileDetailsPanel'; import { ProfileDetailsPanel } from '@/components/profile/ProfileDetailsPanel';
import { ProfileHeader } from '@/components/profile/ProfileHeader'; import { ProfileHeader } from '@/components/profile/ProfileHeader';
import { ProfileNavTabs, type ProfileTab } from '@/components/profile/ProfileNavTabs'; import { ProfileNavTabs, type ProfileTab } from '@/components/profile/ProfileNavTabs';
import { ProfileStatGrid } from '@/components/profile/ProfileStatGrid';
import { SessionHistoryTable } from '@/components/profile/SessionHistoryTable'; import { SessionHistoryTable } from '@/components/profile/SessionHistoryTable';
import { TeamMembershipGrid } from '@/components/teams/TeamMembershipGrid'; import { TeamMembershipGrid } from '@/components/teams/TeamMembershipGrid';
import type { ProfileViewData } from '@/lib/view-data/ProfileViewData'; import type { ProfileViewData } from '@/lib/view-data/ProfileViewData';
@@ -14,7 +15,6 @@ import { Icon } from '@/ui/Icon';
import { Box } from '@/ui/primitives/Box'; import { Box } from '@/ui/primitives/Box';
import { Stack } from '@/ui/primitives/Stack'; import { Stack } from '@/ui/primitives/Stack';
import { Surface } from '@/ui/primitives/Surface'; import { Surface } from '@/ui/primitives/Surface';
import { ProfileStatGrid } from '@/ui/ProfileStatGrid';
import { Text } from '@/ui/Text'; import { Text } from '@/ui/Text';
import { User } from 'lucide-react'; import { User } from 'lucide-react';

View File

@@ -1,4 +1,4 @@
import { AppFooter } from '@/ui/AppFooter'; import { AppFooter } from '@/components/app/AppFooter';
import { Box } from '@/ui/primitives/Box'; import { Box } from '@/ui/primitives/Box';
import { Stack } from '@/ui/primitives/Stack'; import { Stack } from '@/ui/primitives/Stack';
import { Text } from '@/ui/Text'; import { Text } from '@/ui/Text';

View File

@@ -1,8 +1,8 @@
'use client'; 'use client';
import { AppShell } from '@/components/app/AppShell';
import { useCurrentSession } from '@/hooks/auth/useCurrentSession'; import { useCurrentSession } from '@/hooks/auth/useCurrentSession';
import { routes } from '@/lib/routing/RouteConfig'; import { routes } from '@/lib/routing/RouteConfig';
import { AppShell } from '@/ui/AppShell';
import { ContentViewport } from '@/ui/ContentViewport'; import { ContentViewport } from '@/ui/ContentViewport';
import { ControlBar } from '@/ui/ControlBar'; import { ControlBar } from '@/ui/ControlBar';
import { Box } from '@/ui/primitives/Box'; import { Box } from '@/ui/primitives/Box';

View File

@@ -1,13 +1,13 @@
'use client'; 'use client';
import { AvatarInfo, AvatarStep } from '@/components/onboarding/AvatarStep'; import { AvatarInfo, AvatarStep } from '@/components/onboarding/AvatarStep';
import { OnboardingError } from '@/components/onboarding/OnboardingError';
import { OnboardingHelpPanel } from '@/components/onboarding/OnboardingHelpPanel'; import { OnboardingHelpPanel } from '@/components/onboarding/OnboardingHelpPanel';
import { OnboardingPrimaryActions } from '@/components/onboarding/OnboardingPrimaryActions'; import { OnboardingPrimaryActions } from '@/components/onboarding/OnboardingPrimaryActions';
import { OnboardingShell } from '@/components/onboarding/OnboardingShell'; import { OnboardingShell } from '@/components/onboarding/OnboardingShell';
import { OnboardingStepPanel } from '@/components/onboarding/OnboardingStepPanel'; import { OnboardingStepPanel } from '@/components/onboarding/OnboardingStepPanel';
import { OnboardingStepper } from '@/components/onboarding/OnboardingStepper'; import { OnboardingStepper } from '@/components/onboarding/OnboardingStepper';
import { PersonalInfo, PersonalInfoStep } from '@/components/onboarding/PersonalInfoStep'; import { PersonalInfo, PersonalInfoStep } from '@/components/onboarding/PersonalInfoStep';
import { OnboardingError } from '@/ui/OnboardingError';
import { Box } from '@/ui/primitives/Box'; import { Box } from '@/ui/primitives/Box';
import { Stack } from '@/ui/primitives/Stack'; import { Stack } from '@/ui/primitives/Stack';
import { Text } from '@/ui/Text'; import { Text } from '@/ui/Text';

View File

@@ -17,7 +17,7 @@ interface AccordionProps {
export function Accordion({ title, icon, children, isOpen, onToggle }: AccordionProps) { export function Accordion({ title, icon, children, isOpen, onToggle }: AccordionProps) {
return ( return (
<Box border={true} borderColor="border-charcoal-outline" rounded="lg" overflow="hidden" bg="bg-iron-gray/30"> <Box border borderColor="border-charcoal-outline" rounded="lg" overflow="hidden" bg="bg-iron-gray/30">
<Box <Box
as="button" as="button"
onClick={onToggle} onClick={onToggle}
@@ -27,7 +27,8 @@ export function Accordion({ title, icon, children, isOpen, onToggle }: Accordion
px={3} px={3}
py={2} py={2}
fullWidth fullWidth
className="hover:bg-iron-gray/50 transition-colors" hoverBg="iron-gray/50"
clickable
> >
<Stack direction="row" align="center" gap={2}> <Stack direction="row" align="center" gap={2}>
{icon} {icon}
@@ -39,7 +40,7 @@ export function Accordion({ title, icon, children, isOpen, onToggle }: Accordion
</Box> </Box>
{isOpen && ( {isOpen && (
<Box p={3} borderTop={true} borderColor="border-charcoal-outline"> <Box p={3} borderTop borderColor="border-charcoal-outline">
{children} {children}
</Box> </Box>
)} )}

View File

@@ -3,14 +3,14 @@ import { Box, BoxProps } from './primitives/Box';
import { Icon } from './Icon'; import { Icon } from './Icon';
import { LucideIcon } from 'lucide-react'; import { LucideIcon } from 'lucide-react';
interface BadgeProps extends Omit<BoxProps<'div'>, 'children'> { interface BadgeProps {
children: ReactNode; children: ReactNode;
variant?: 'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info'; variant?: 'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info';
size?: 'xs' | 'sm' | 'md'; size?: 'xs' | 'sm' | 'md';
icon?: LucideIcon; icon?: LucideIcon;
} }
export function Badge({ children, className = '', variant = 'default', size = 'sm', icon, rounded = 'none', ...props }: BadgeProps) { export function Badge({ children, variant = 'default', size = 'sm', icon }: BadgeProps) {
const baseClasses = 'flex items-center gap-1.5 border font-bold uppercase tracking-widest'; const baseClasses = 'flex items-center gap-1.5 border font-bold uppercase tracking-widest';
const sizeClasses = { const sizeClasses = {
@@ -19,16 +19,6 @@ export function Badge({ children, className = '', variant = 'default', size = 's
md: 'px-3 py-1 text-xs' md: 'px-3 py-1 text-xs'
}; };
const roundedClasses = {
none: 'rounded-none',
sm: 'rounded-sm',
md: 'rounded-md',
lg: 'rounded-lg',
xl: 'rounded-xl',
'2xl': 'rounded-2xl',
full: 'rounded-full'
};
const variantClasses = { const variantClasses = {
default: 'bg-gray-500/10 border-gray-500/30 text-gray-400', default: 'bg-gray-500/10 border-gray-500/30 text-gray-400',
primary: 'bg-primary-accent/10 border-primary-accent/30 text-primary-accent', primary: 'bg-primary-accent/10 border-primary-accent/30 text-primary-accent',
@@ -41,13 +31,11 @@ export function Badge({ children, className = '', variant = 'default', size = 's
const classes = [ const classes = [
baseClasses, baseClasses,
sizeClasses[size], sizeClasses[size],
typeof rounded === 'string' && roundedClasses[rounded as keyof typeof roundedClasses] ? roundedClasses[rounded as keyof typeof roundedClasses] : '', variantClasses[variant],
!props.bg && !props.color && !props.borderColor ? variantClasses[variant] : '',
className
].filter(Boolean).join(' '); ].filter(Boolean).join(' ');
return ( return (
<Box className={classes} {...props}> <Box className={classes}>
{icon && <Icon icon={icon} size={3} />} {icon && <Icon icon={icon} size={3} />}
{children} {children}
</Box> </Box>

View File

@@ -10,7 +10,6 @@ export type BreadcrumbItem = {
interface BreadcrumbsProps { interface BreadcrumbsProps {
items: BreadcrumbItem[]; items: BreadcrumbItem[];
className?: string;
} }
export function Breadcrumbs({ items }: BreadcrumbsProps) { export function Breadcrumbs({ items }: BreadcrumbsProps) {

View File

@@ -1,21 +0,0 @@
import React from 'react';
interface DashboardRailProps {
children?: React.ReactNode;
className?: string;
}
/**
* DashboardRail is the primary sidebar navigation for the "Telemetry Workspace".
* It provides a high-density, instrument-grade navigation experience.
* Aligned with "Precision Racing Minimal" theme.
*/
export function DashboardRail({ children, className = '' }: DashboardRailProps) {
return (
<aside
className={`hidden lg:flex flex-col w-64 bg-[#141619] border-r border-[#23272B] overflow-y-auto ${className}`}
>
{children}
</aside>
);
}

View File

@@ -1,4 +1,4 @@
import React, { ReactNode } from 'react'; import { ReactNode } from 'react';
import { Box } from './primitives/Box'; import { Box } from './primitives/Box';
import { Grid } from './primitives/Grid'; import { Grid } from './primitives/Grid';
import { Stack } from './primitives/Stack'; import { Stack } from './primitives/Stack';
@@ -14,7 +14,6 @@ import { Stack } from './primitives/Stack';
interface LayoutProps { interface LayoutProps {
children: ReactNode; children: ReactNode;
className?: string;
padding?: string; padding?: string;
gap?: string; gap?: string;
grid?: boolean; grid?: boolean;
@@ -27,7 +26,6 @@ interface LayoutProps {
export function Layout({ export function Layout({
children, children,
className = '',
padding = 'p-6', padding = 'p-6',
gap = 'gap-4', gap = 'gap-4',
grid = false, grid = false,
@@ -41,7 +39,7 @@ export function Layout({
return ( return (
<Grid <Grid
cols={gridCols as any} cols={gridCols as any}
className={`${padding} ${gap} ${className}`} className={`${padding} ${gap}`}
> >
{children} {children}
</Grid> </Grid>
@@ -54,7 +52,7 @@ export function Layout({
direction={flexCol ? 'col' : 'row'} direction={flexCol ? 'col' : 'row'}
align={items} align={items}
justify={justify} justify={justify}
className={`${padding} ${gap} ${className}`} className={`${padding} ${gap}`}
> >
{children} {children}
</Stack> </Stack>
@@ -62,7 +60,7 @@ export function Layout({
} }
return ( return (
<Box className={`${padding} ${gap} ${className}`}> <Box className={`${padding} ${gap}`}>
{children} {children}
</Box> </Box>
); );

View File

@@ -1,22 +0,0 @@
import React, { ReactNode } from 'react';
import { Surface } from './primitives/Surface';
interface OnboardingStepPanelProps {
children: ReactNode;
className?: string;
}
export function OnboardingStepPanel({ children, className = '' }: OnboardingStepPanelProps) {
return (
<Surface
variant="muted"
rounded="2xl"
border
p={6}
borderColor="border-charcoal-outline"
className={className}
>
{children}
</Surface>
);
}