view data fixes
Some checks failed
Contract Testing / contract-tests (pull_request) Failing after 5m42s
Contract Testing / contract-snapshot (pull_request) Has been skipped

This commit is contained in:
2026-01-22 23:40:38 +01:00
parent 1288a9dc30
commit 18133aef4c
111 changed files with 841 additions and 324 deletions

View File

@@ -24,7 +24,7 @@ module.exports = {
create(context) { create(context) {
const filename = context.getFilename(); const filename = context.getFilename();
const isInViewData = filename.includes('/lib/view-data/'); const isInViewData = filename.includes('/lib/view-data/') && !filename.includes('/contracts/');
if (!isInViewData) return {}; if (!isInViewData) return {};
@@ -42,9 +42,15 @@ module.exports = {
// Check if it extends ViewData // Check if it extends ViewData
if (node.extends && node.extends.length > 0) { if (node.extends && node.extends.length > 0) {
for (const ext of node.extends) { for (const ext of node.extends) {
if (ext.type === 'TSExpressionWithTypeArguments' && // Use context.getSourceCode().getText(ext) to be absolutely sure
ext.expression.type === 'Identifier' && const extendsText = context.getSourceCode().getText(ext).trim();
ext.expression.name === 'ViewData') { // We check for 'ViewData' but must be careful not to match 'SomethingViewData'
// unless it's exactly 'ViewData' or part of a qualified name
if (extendsText === 'ViewData' ||
extendsText.endsWith('.ViewData') ||
extendsText.startsWith('ViewData<') ||
extendsText.startsWith('ViewData ') ||
/\bViewData\b/.test(extendsText)) { // Use regex for word boundary
hasViewDataExtends = true; hasViewDataExtends = true;
} }
} }
@@ -74,16 +80,31 @@ module.exports = {
}, },
'Program:exit'() { 'Program:exit'() {
if (!hasCorrectName) { // Only report if we are in a file that should be a ViewData
// and we didn't find a valid declaration
const baseName = filename.split('/').pop();
// All files in lib/view-data/ must end with ViewData.ts
if (baseName && !baseName.endsWith('ViewData.ts') && !baseName.endsWith('ViewData.tsx')) {
context.report({ context.report({
node: context.getSourceCode().ast, node: context.getSourceCode().ast,
messageId: 'notAnInterface', messageId: 'notAnInterface',
}); });
} else if (!hasViewDataExtends) { return;
context.report({ }
node: context.getSourceCode().ast,
messageId: 'missingExtends', if (baseName && (baseName.endsWith('ViewData.ts') || baseName.endsWith('ViewData.tsx'))) {
}); if (!hasCorrectName) {
context.report({
node: context.getSourceCode().ast,
messageId: 'notAnInterface',
});
} else if (!hasViewDataExtends) {
context.report({
node: context.getSourceCode().ast,
messageId: 'missingExtends',
});
}
} }
}, },
}; };

View File

@@ -1,25 +1,28 @@
/** /**
* ViewData Builder Contract * ViewData Builder Contract
* *
* Purpose: Transform ViewModels into ViewData for templates * Purpose: Transform API Transport DTOs into ViewData for templates
* *
* Rules: * Rules:
* - Deterministic and side-effect free * - Deterministic and side-effect free
* - No HTTP/API calls * - No HTTP/API calls
* - Input: ViewModel * - Input: API Transport DTO (must be JSON-serializable)
* - Output: ViewData (JSON-serializable) * - Output: ViewData (JSON-serializable template-ready data)
* - Must be in lib/builders/view-data/ * - Must be in lib/builders/view-data/
* - Must be named *ViewDataBuilder * - Must be named *ViewDataBuilder
* - Must have 'use client' directive * - Must have 'use client' directive
* - Must implement static build() method * - Must implement static build() method
*/ */
export interface ViewDataBuilder<TInput, TOutput> { import { JsonValue } from '../types/primitives';
import { ViewData } from '../view-data/ViewData';
export interface ViewDataBuilder<TDTO extends JsonValue, TViewData extends ViewData> {
/** /**
* Transform ViewModel into ViewData * Transform DTO into ViewData
* *
* @param viewModel - Client-side ViewModel * @param dto - API Transport DTO (JSON-serializable)
* @returns ViewData for template * @returns ViewData for template
*/ */
build(viewModel: TInput): TOutput; build(dto: TDTO): TViewData;
} }

View File

@@ -1,25 +1,28 @@
/** /**
* ViewModel Builder Contract * ViewModel Builder Contract
* *
* Purpose: Transform API Transport DTOs into ViewModels * Purpose: Transform ViewData into ViewModels for client-side state management
* *
* Rules: * Rules:
* - Deterministic and side-effect free * - Deterministic and side-effect free
* - No HTTP/API calls * - No HTTP/API calls
* - Input: API Transport DTO * - Input: ViewData (JSON-serializable template-ready data)
* - Output: ViewModel * - Output: ViewModel (client-only class)
* - Must be in lib/builders/view-models/ * - Must be in lib/builders/view-models/
* - Must be named *ViewModelBuilder * - Must be named *ViewModelBuilder
* - Must have 'use client' directive * - Must have 'use client' directive
* - Must implement static build() method * - Must implement static build() method
*/ */
export interface ViewModelBuilder<TInput, TOutput> { import { ViewData } from '../view-data/ViewData';
import { ViewModel } from '../view-models/ViewModel';
export interface ViewModelBuilder<TViewData extends ViewData, TViewModel extends ViewModel> {
/** /**
* Transform DTO into ViewModel * Transform ViewData into ViewModel
* *
* @param dto - API Transport DTO * @param viewData - ViewData (JSON-serializable template-ready data)
* @returns ViewModel * @returns ViewModel
*/ */
build(dto: TInput): TOutput; build(viewData: TViewData): TViewModel;
} }

View File

@@ -1,6 +1,6 @@
/** /**
* Base interface for ViewData objects * Base interface for ViewData objects
* *
* All ViewData must be JSON-serializable. * All ViewData must be JSON-serializable.
* This type ensures no class instances or functions are included. * This type ensures no class instances or functions are included.
*/ */
@@ -10,7 +10,7 @@ export interface ViewData {
/** /**
* Helper type to ensure a type is ViewData-compatible * Helper type to ensure a type is ViewData-compatible
* *
* Usage: * Usage:
* ```typescript * ```typescript
* type MyViewData = ViewData & { * type MyViewData = ViewData & {

View File

@@ -0,0 +1,33 @@
/**
* ActivityLevelDisplay
*
* Deterministic mapping of engagement rates to activity level labels.
*/
export class ActivityLevelDisplay {
/**
* Maps engagement rate to activity level label.
*/
static levelLabel(engagementRate: number): string {
if (engagementRate < 20) {
return 'Low';
} else if (engagementRate < 50) {
return 'Medium';
} else {
return 'High';
}
}
/**
* Maps engagement rate to activity level value.
*/
static levelValue(engagementRate: number): 'low' | 'medium' | 'high' {
if (engagementRate < 20) {
return 'low';
} else if (engagementRate < 50) {
return 'medium';
} else {
return 'high';
}
}
}

View File

@@ -0,0 +1,37 @@
/**
* AvatarDisplay
*
* Deterministic mapping of avatar-related data to display formats.
*/
export class AvatarDisplay {
/**
* Converts binary buffer to base64 string for display.
*/
static bufferToBase64(buffer: ArrayBuffer): string {
const bytes = new Uint8Array(buffer);
let binary = '';
for (let i = 0; i < bytes.byteLength; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}
/**
* Determines if avatar data is valid for display.
*/
static hasValidData(buffer: ArrayBuffer, contentType: string): boolean {
return buffer.byteLength > 0 && contentType.length > 0;
}
/**
* Formats content type for display (e.g., "image/png" → "PNG").
*/
static formatContentType(contentType: string): string {
const parts = contentType.split('/');
if (parts.length === 2) {
return parts[1].toUpperCase();
}
return contentType;
}
}

View File

@@ -1,36 +1,47 @@
/** /**
* CurrencyDisplay * CurrencyDisplay
* *
* Deterministic currency formatting for display. * Deterministic currency formatting for display.
* Avoids Intl and toLocaleString to prevent SSR/hydration mismatches. * Avoids Intl and toLocaleString to prevent SSR/hydration mismatches.
*/ */
export class CurrencyDisplay { export class CurrencyDisplay {
/** /**
* Formats an amount as currency (e.g., "$10.00"). * Formats an amount as currency (e.g., "$10.00" or "€1.000,00").
* Default currency is USD. * Default currency is USD.
*/ */
static format(amount: number, currency: string = 'USD'): string { static format(amount: number, currency: string = 'USD'): string {
const symbol = currency === 'USD' ? '$' : currency + ' '; const symbol = currency === 'USD' ? '$' : currency === 'EUR' ? '€' : currency + ' ';
const formattedAmount = amount.toFixed(2); const formattedAmount = amount.toFixed(2);
// Add thousands separators // Add thousands separators
const parts = formattedAmount.split('.'); const parts = formattedAmount.split('.');
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
return `${symbol}${parts.join('.')}`; // Use dot as thousands separator for EUR, comma for USD
if (currency === 'EUR') {
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, '.');
return `${symbol}${parts[0]},${parts[1]}`;
} else {
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
return `${symbol}${parts.join('.')}`;
}
} }
/** /**
* Formats an amount as a compact currency (e.g., "$10"). * Formats an amount as a compact currency (e.g., "$10" or "€1.000").
*/ */
static formatCompact(amount: number, currency: string = 'USD'): string { static formatCompact(amount: number, currency: string = 'USD'): string {
const symbol = currency === 'USD' ? '$' : currency + ' '; const symbol = currency === 'USD' ? '$' : currency === 'EUR' ? '€' : currency + ' ';
const roundedAmount = Math.round(amount); const roundedAmount = Math.round(amount);
// Add thousands separators // Add thousands separators
const formattedAmount = roundedAmount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); const formattedAmount = roundedAmount.toString();
return `${symbol}${formattedAmount}`; // Use dot as thousands separator for EUR, comma for USD
if (currency === 'EUR') {
return `${symbol}${formattedAmount.replace(/\B(?=(\d{3})+(?!\d))/g, '.')}`;
} else {
return `${symbol}${formattedAmount.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}`;
}
} }
} }

View File

@@ -0,0 +1,39 @@
/**
* LeagueTierDisplay
*
* Deterministic display logic for league tiers.
*/
export interface LeagueTierDisplayData {
color: string;
bgColor: string;
border: string;
icon: string;
}
export class LeagueTierDisplay {
private static readonly CONFIG: Record<string, LeagueTierDisplayData> = {
premium: {
color: 'text-yellow-400',
bgColor: 'bg-yellow-500/10',
border: 'border-yellow-500/30',
icon: '⭐'
},
standard: {
color: 'text-primary-blue',
bgColor: 'bg-primary-blue/10',
border: 'border-primary-blue/30',
icon: '🏆'
},
starter: {
color: 'text-gray-400',
bgColor: 'bg-gray-500/10',
border: 'border-gray-500/30',
icon: '🚀'
},
};
static getDisplay(tier: 'premium' | 'standard' | 'starter'): LeagueTierDisplayData {
return this.CONFIG[tier];
}
}

View File

@@ -0,0 +1,38 @@
/**
* OnboardingStatusDisplay
*
* Deterministic mapping of onboarding status to display labels and variants.
*/
export class OnboardingStatusDisplay {
/**
* Maps onboarding success status to display label.
*/
static statusLabel(success: boolean): string {
return success ? 'Onboarding Complete' : 'Onboarding Failed';
}
/**
* Maps onboarding success status to badge variant.
*/
static statusVariant(success: boolean): string {
return success ? 'performance-green' : 'racing-red';
}
/**
* Maps onboarding success status to icon.
*/
static statusIcon(success: boolean): string {
return success ? '✅' : '❌';
}
/**
* Maps onboarding success status to message.
*/
static statusMessage(success: boolean, errorMessage?: string): string {
if (success) {
return 'Your onboarding has been completed successfully.';
}
return errorMessage || 'Failed to complete onboarding. Please try again.';
}
}

View File

@@ -0,0 +1,35 @@
/**
* SeasonStatusDisplay
*
* Deterministic display logic for season status.
*/
export interface SeasonStatusDisplayData {
color: string;
bg: string;
label: string;
}
export class SeasonStatusDisplay {
private static readonly CONFIG: Record<string, SeasonStatusDisplayData> = {
active: {
color: 'text-performance-green',
bg: 'bg-performance-green/10',
label: 'Active Season'
},
upcoming: {
color: 'text-warning-amber',
bg: 'bg-warning-amber/10',
label: 'Starting Soon'
},
completed: {
color: 'text-gray-400',
bg: 'bg-gray-400/10',
label: 'Season Ended'
},
};
static getDisplay(status: 'active' | 'upcoming' | 'completed'): SeasonStatusDisplayData {
return this.CONFIG[status];
}
}

View File

@@ -0,0 +1,19 @@
/**
* UserRoleDisplay
*
* Deterministic mapping of user role codes to display labels.
*/
export class UserRoleDisplay {
/**
* Maps user role to display label.
*/
static roleLabel(role: string): string {
const map: Record<string, string> = {
owner: 'Owner',
admin: 'Admin',
user: 'User',
};
return map[role] || role;
}
}

View File

@@ -0,0 +1,52 @@
/**
* UserStatusDisplay
*
* Deterministic mapping of user status codes to display labels and variants.
*/
export class UserStatusDisplay {
/**
* Maps user status to display label.
*/
static statusLabel(status: string): string {
const map: Record<string, string> = {
active: 'Active',
suspended: 'Suspended',
deleted: 'Deleted',
};
return map[status] || status;
}
/**
* Maps user status to badge variant.
*/
static statusVariant(status: string): string {
const map: Record<string, string> = {
active: 'performance-green',
suspended: 'yellow-500',
deleted: 'racing-red',
};
return map[status] || 'gray-500';
}
/**
* Determines if a user can be suspended.
*/
static canSuspend(status: string): boolean {
return status === 'active';
}
/**
* Determines if a user can be activated.
*/
static canActivate(status: string): boolean {
return status === 'suspended';
}
/**
* Determines if a user can be deleted.
*/
static canDelete(status: string): boolean {
return status !== 'deleted';
}
}

View File

@@ -1,9 +1,9 @@
import { ProtestDetailViewDataBuilder } from '@/lib/builders/view-data/ProtestDetailViewDataBuilder';
import { PageQuery } from '@/lib/contracts/page-queries/PageQuery'; import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';
import { type PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';
import { Result } from '@/lib/contracts/Result'; import { Result } from '@/lib/contracts/Result';
import { ProtestDetailService } from '@/lib/services/leagues/ProtestDetailService'; import { ProtestDetailService } from '@/lib/services/leagues/ProtestDetailService';
import { ProtestDetailViewDataBuilder } from '@/lib/builders/view-data/ProtestDetailViewDataBuilder'; import { ProtestDetailViewData } from '@/lib/view-data/ProtestDetailViewData';
import { ProtestDetailViewData } from '@/lib/view-data/leagues/ProtestDetailViewData';
import { type PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';
export class LeagueProtestDetailPageQuery implements PageQuery<ProtestDetailViewData, { leagueId: string; protestId: string }, PresentationError> { export class LeagueProtestDetailPageQuery implements PageQuery<ProtestDetailViewData, { leagueId: string; protestId: string }, PresentationError> {
async execute(params: { leagueId: string; protestId: string }): Promise<Result<ProtestDetailViewData, PresentationError>> { async execute(params: { leagueId: string; protestId: string }): Promise<Result<ProtestDetailViewData, PresentationError>> {

View File

@@ -1,9 +1,9 @@
import { RulebookViewDataBuilder } from '@/lib/builders/view-data/RulebookViewDataBuilder';
import { PageQuery } from '@/lib/contracts/page-queries/PageQuery'; import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';
import { type PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';
import { Result } from '@/lib/contracts/Result'; import { Result } from '@/lib/contracts/Result';
import { LeagueRulebookService } from '@/lib/services/leagues/LeagueRulebookService'; import { LeagueRulebookService } from '@/lib/services/leagues/LeagueRulebookService';
import { RulebookViewDataBuilder } from '@/lib/builders/view-data/RulebookViewDataBuilder'; import { RulebookViewData } from '@/lib/view-data/RulebookViewData';
import { RulebookViewData } from '@/lib/view-data/leagues/RulebookViewData';
import { type PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';
export class LeagueRulebookPageQuery implements PageQuery<RulebookViewData, string, PresentationError> { export class LeagueRulebookPageQuery implements PageQuery<RulebookViewData, string, PresentationError> {
async execute(leagueId: string): Promise<Result<RulebookViewData, PresentationError>> { async execute(leagueId: string): Promise<Result<RulebookViewData, PresentationError>> {

View File

@@ -1,9 +1,9 @@
import { LeagueSettingsViewDataBuilder } from '@/lib/builders/view-data/LeagueSettingsViewDataBuilder';
import { PageQuery } from '@/lib/contracts/page-queries/PageQuery'; import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';
import { type PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';
import { Result } from '@/lib/contracts/Result'; import { Result } from '@/lib/contracts/Result';
import { LeagueSettingsService } from '@/lib/services/leagues/LeagueSettingsService'; import { LeagueSettingsService } from '@/lib/services/leagues/LeagueSettingsService';
import { LeagueSettingsViewDataBuilder } from '@/lib/builders/view-data/LeagueSettingsViewDataBuilder'; import { LeagueSettingsViewData } from '@/lib/view-data/LeagueSettingsViewData';
import { LeagueSettingsViewData } from '@/lib/view-data/leagues/LeagueSettingsViewData';
import { type PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';
export class LeagueSettingsPageQuery implements PageQuery<LeagueSettingsViewData, string, PresentationError> { export class LeagueSettingsPageQuery implements PageQuery<LeagueSettingsViewData, string, PresentationError> {
async execute(leagueId: string): Promise<Result<LeagueSettingsViewData, PresentationError>> { async execute(leagueId: string): Promise<Result<LeagueSettingsViewData, PresentationError>> {

View File

@@ -1,9 +1,9 @@
import { LeagueSponsorshipsViewDataBuilder } from '@/lib/builders/view-data/LeagueSponsorshipsViewDataBuilder';
import { PageQuery } from '@/lib/contracts/page-queries/PageQuery'; import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';
import { type PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';
import { Result } from '@/lib/contracts/Result'; import { Result } from '@/lib/contracts/Result';
import { LeagueSponsorshipsService } from '@/lib/services/leagues/LeagueSponsorshipsService'; import { LeagueSponsorshipsService } from '@/lib/services/leagues/LeagueSponsorshipsService';
import { LeagueSponsorshipsViewDataBuilder } from '@/lib/builders/view-data/LeagueSponsorshipsViewDataBuilder'; import { LeagueSponsorshipsViewData } from '@/lib/view-data/LeagueSponsorshipsViewData';
import { LeagueSponsorshipsViewData } from '@/lib/view-data/leagues/LeagueSponsorshipsViewData';
import { type PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';
export class LeagueSponsorshipsPageQuery implements PageQuery<LeagueSponsorshipsViewData, string, PresentationError> { export class LeagueSponsorshipsPageQuery implements PageQuery<LeagueSponsorshipsViewData, string, PresentationError> {
async execute(leagueId: string): Promise<Result<LeagueSponsorshipsViewData, PresentationError>> { async execute(leagueId: string): Promise<Result<LeagueSponsorshipsViewData, PresentationError>> {

View File

@@ -1,9 +1,9 @@
import { StewardingViewDataBuilder } from '@/lib/builders/view-data/StewardingViewDataBuilder';
import { Result } from '@/lib/contracts/Result'; import { Result } from '@/lib/contracts/Result';
import { PageQuery } from '@/lib/contracts/page-queries/PageQuery'; import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';
import { LeagueStewardingService } from '@/lib/services/leagues/LeagueStewardingService';
import { StewardingViewDataBuilder } from '@/lib/builders/view-data/StewardingViewDataBuilder';
import { StewardingViewData } from '@/lib/view-data/leagues/StewardingViewData';
import { type PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError'; import { type PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';
import { LeagueStewardingService } from '@/lib/services/leagues/LeagueStewardingService';
import { StewardingViewData } from '@/lib/view-data/StewardingViewData';
export class LeagueStewardingPageQuery implements PageQuery<StewardingViewData, string, PresentationError> { export class LeagueStewardingPageQuery implements PageQuery<StewardingViewData, string, PresentationError> {
async execute(leagueId: string): Promise<Result<StewardingViewData, PresentationError>> { async execute(leagueId: string): Promise<Result<StewardingViewData, PresentationError>> {

View File

@@ -1,9 +1,9 @@
import { LeagueWalletViewDataBuilder } from '@/lib/builders/view-data/LeagueWalletViewDataBuilder';
import { PageQuery } from '@/lib/contracts/page-queries/PageQuery'; import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';
import { type PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';
import { Result } from '@/lib/contracts/Result'; import { Result } from '@/lib/contracts/Result';
import { LeagueWalletService } from '@/lib/services/leagues/LeagueWalletService'; import { LeagueWalletService } from '@/lib/services/leagues/LeagueWalletService';
import { LeagueWalletViewDataBuilder } from '@/lib/builders/view-data/LeagueWalletViewDataBuilder'; import { LeagueWalletViewData } from '@/lib/view-data/LeagueWalletViewData';
import { LeagueWalletViewData } from '@/lib/view-data/leagues/LeagueWalletViewData';
import { type PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';
export class LeagueWalletPageQuery implements PageQuery<LeagueWalletViewData, string, PresentationError> { export class LeagueWalletPageQuery implements PageQuery<LeagueWalletViewData, string, PresentationError> {
async execute(leagueId: string): Promise<Result<LeagueWalletViewData, PresentationError>> { async execute(leagueId: string): Promise<Result<LeagueWalletViewData, PresentationError>> {

View File

@@ -1,9 +1,9 @@
import { ForgotPasswordViewDataBuilder } from '@/lib/builders/view-data/ForgotPasswordViewDataBuilder';
import { Result } from '@/lib/contracts/Result'; import { Result } from '@/lib/contracts/Result';
import { PageQuery } from '@/lib/contracts/page-queries/PageQuery'; import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';
import { ForgotPasswordViewDataBuilder } from '@/lib/builders/view-data/ForgotPasswordViewDataBuilder';
import { ForgotPasswordViewData } from '@/lib/builders/view-data/types/ForgotPasswordViewData';
import { AuthPageService } from '@/lib/services/auth/AuthPageService';
import { SearchParamParser } from '@/lib/routing/search-params/SearchParamParser'; import { SearchParamParser } from '@/lib/routing/search-params/SearchParamParser';
import { AuthPageService } from '@/lib/services/auth/AuthPageService';
import { ForgotPasswordViewData } from '@/lib/view-data/ForgotPasswordViewData';
export class ForgotPasswordPageQuery implements PageQuery<ForgotPasswordViewData, URLSearchParams | Record<string, string | string[] | undefined>> { export class ForgotPasswordPageQuery implements PageQuery<ForgotPasswordViewData, URLSearchParams | Record<string, string | string[] | undefined>> {
async execute(searchParams: URLSearchParams | Record<string, string | string[] | undefined>): Promise<Result<ForgotPasswordViewData, string>> { async execute(searchParams: URLSearchParams | Record<string, string | string[] | undefined>): Promise<Result<ForgotPasswordViewData, string>> {

View File

@@ -1,9 +1,9 @@
import { LoginViewDataBuilder } from '@/lib/builders/view-data/LoginViewDataBuilder';
import { Result } from '@/lib/contracts/Result'; import { Result } from '@/lib/contracts/Result';
import { PageQuery } from '@/lib/contracts/page-queries/PageQuery'; import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';
import { LoginViewDataBuilder } from '@/lib/builders/view-data/LoginViewDataBuilder';
import { LoginViewData } from '@/lib/builders/view-data/types/LoginViewData';
import { AuthPageService } from '@/lib/services/auth/AuthPageService';
import { SearchParamParser } from '@/lib/routing/search-params/SearchParamParser'; import { SearchParamParser } from '@/lib/routing/search-params/SearchParamParser';
import { AuthPageService } from '@/lib/services/auth/AuthPageService';
import { LoginViewData } from '@/lib/view-data/LoginViewData';
export class LoginPageQuery implements PageQuery<LoginViewData, URLSearchParams | Record<string, string | string[] | undefined>> { export class LoginPageQuery implements PageQuery<LoginViewData, URLSearchParams | Record<string, string | string[] | undefined>> {
async execute(searchParams: URLSearchParams | Record<string, string | string[] | undefined>): Promise<Result<LoginViewData, string>> { async execute(searchParams: URLSearchParams | Record<string, string | string[] | undefined>): Promise<Result<LoginViewData, string>> {

View File

@@ -1,9 +1,9 @@
import { ResetPasswordViewDataBuilder } from '@/lib/builders/view-data/ResetPasswordViewDataBuilder';
import { Result } from '@/lib/contracts/Result'; import { Result } from '@/lib/contracts/Result';
import { PageQuery } from '@/lib/contracts/page-queries/PageQuery'; import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';
import { ResetPasswordViewDataBuilder } from '@/lib/builders/view-data/ResetPasswordViewDataBuilder';
import { ResetPasswordViewData } from '@/lib/builders/view-data/types/ResetPasswordViewData';
import { AuthPageService } from '@/lib/services/auth/AuthPageService';
import { SearchParamParser } from '@/lib/routing/search-params/SearchParamParser'; import { SearchParamParser } from '@/lib/routing/search-params/SearchParamParser';
import { AuthPageService } from '@/lib/services/auth/AuthPageService';
import { ResetPasswordViewData } from '@/lib/view-data/ResetPasswordViewData';
export class ResetPasswordPageQuery implements PageQuery<ResetPasswordViewData, URLSearchParams | Record<string, string | string[] | undefined>> { export class ResetPasswordPageQuery implements PageQuery<ResetPasswordViewData, URLSearchParams | Record<string, string | string[] | undefined>> {
async execute(searchParams: URLSearchParams | Record<string, string | string[] | undefined>): Promise<Result<ResetPasswordViewData, string>> { async execute(searchParams: URLSearchParams | Record<string, string | string[] | undefined>): Promise<Result<ResetPasswordViewData, string>> {

View File

@@ -1,9 +1,9 @@
import { SignupViewDataBuilder } from '@/lib/builders/view-data/SignupViewDataBuilder'; import { SignupViewDataBuilder } from '@/lib/builders/view-data/SignupViewDataBuilder';
import { SignupViewData } from '@/lib/builders/view-data/types/SignupViewData';
import { Result } from '@/lib/contracts/Result'; import { Result } from '@/lib/contracts/Result';
import { PageQuery } from '@/lib/contracts/page-queries/PageQuery'; import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';
import { AuthPageService } from '@/lib/services/auth/AuthPageService';
import { SearchParamParser } from '@/lib/routing/search-params/SearchParamParser'; import { SearchParamParser } from '@/lib/routing/search-params/SearchParamParser';
import { AuthPageService } from '@/lib/services/auth/AuthPageService';
import { SignupViewData } from '@/lib/view-data/SignupViewData';
export class SignupPageQuery implements PageQuery<SignupViewData, URLSearchParams | Record<string, string | string[] | undefined>> { export class SignupPageQuery implements PageQuery<SignupViewData, URLSearchParams | Record<string, string | string[] | undefined>> {
async execute(searchParams: URLSearchParams | Record<string, string | string[] | undefined>): Promise<Result<SignupViewData, string>> { async execute(searchParams: URLSearchParams | Record<string, string | string[] | undefined>): Promise<Result<SignupViewData, string>> {

View File

@@ -1,9 +1,9 @@
import { RaceDetailViewDataBuilder } from '@/lib/builders/view-data/RaceDetailViewDataBuilder';
import { Result } from '@/lib/contracts/Result'; import { Result } from '@/lib/contracts/Result';
import { PageQuery } from '@/lib/contracts/page-queries/PageQuery'; import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';
import { PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError'; import { PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';
import { RaceDetailViewData } from '@/lib/view-data/races/RaceDetailViewData';
import { RacesService } from '@/lib/services/races/RacesService'; import { RacesService } from '@/lib/services/races/RacesService';
import { RaceDetailViewDataBuilder } from '@/lib/builders/view-data/RaceDetailViewDataBuilder'; import { RaceDetailViewData } from '@/lib/view-data/RaceDetailViewData';
interface RaceDetailPageQueryParams { interface RaceDetailPageQueryParams {
raceId: string; raceId: string;

View File

@@ -1,9 +1,9 @@
import { RaceResultsViewDataBuilder } from '@/lib/builders/view-data/RaceResultsViewDataBuilder';
import { Result } from '@/lib/contracts/Result'; import { Result } from '@/lib/contracts/Result';
import { PageQuery } from '@/lib/contracts/page-queries/PageQuery'; import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';
import { PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError'; import { PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';
import { RaceResultsViewData } from '@/lib/view-data/races/RaceResultsViewData';
import { RaceResultsService } from '@/lib/services/races/RaceResultsService'; import { RaceResultsService } from '@/lib/services/races/RaceResultsService';
import { RaceResultsViewDataBuilder } from '@/lib/builders/view-data/RaceResultsViewDataBuilder'; import { RaceResultsViewData } from '@/lib/view-data/RaceResultsViewData';
interface RaceResultsPageQueryParams { interface RaceResultsPageQueryParams {
raceId: string; raceId: string;

View File

@@ -1,9 +1,9 @@
import { RaceStewardingViewDataBuilder } from '@/lib/builders/view-data/RaceStewardingViewDataBuilder';
import { Result } from '@/lib/contracts/Result'; import { Result } from '@/lib/contracts/Result';
import { PageQuery } from '@/lib/contracts/page-queries/PageQuery'; import { PageQuery } from '@/lib/contracts/page-queries/PageQuery';
import { PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError'; import { PresentationError, mapToPresentationError } from '@/lib/contracts/page-queries/PresentationError';
import { RaceStewardingViewData } from '@/lib/view-data/races/RaceStewardingViewData';
import { RaceStewardingService } from '@/lib/services/races/RaceStewardingService'; import { RaceStewardingService } from '@/lib/services/races/RaceStewardingService';
import { RaceStewardingViewDataBuilder } from '@/lib/builders/view-data/RaceStewardingViewDataBuilder'; import { RaceStewardingViewData } from '@/lib/view-data/RaceStewardingViewData';
interface RaceStewardingPageQueryParams { interface RaceStewardingPageQueryParams {
raceId: string; raceId: string;

View File

@@ -1,5 +1,7 @@
import { ViewData } from '@/lib/contracts/view-data/ViewData';
import { ActionItem } from '@/lib/queries/ActionsPageQuery'; import { ActionItem } from '@/lib/queries/ActionsPageQuery';
export interface ActionsViewData {
export interface ActionsViewData extends ViewData {
actions: ActionItem[]; actions: ActionItem[];
} }

View File

@@ -0,0 +1,14 @@
import { ViewData } from '../contracts/view-data/ViewData';
/**
* ActivityItemViewData
*
* ViewData for activity item rendering.
*/
export interface ActivityItemViewData extends ViewData {
id: string;
type: string;
message: string;
time: string;
impressions?: number;
}

View File

@@ -1,10 +1,13 @@
import { ViewData } from '@/lib/contracts/view-data/ViewData';
/** /**
* AdminDashboardViewData * AdminDashboardViewData
* *
* ViewData for AdminDashboardTemplate. * ViewData for AdminDashboardTemplate.
* Template-ready data structure with only primitives. * Template-ready data structure with only primitives.
*/ */
export interface AdminDashboardViewData {
export interface AdminDashboardViewData extends ViewData {
stats: { stats: {
totalUsers: number; totalUsers: number;
activeUsers: number; activeUsers: number;

View File

@@ -1,10 +1,13 @@
import { ViewData } from '@/lib/contracts/view-data/ViewData';
/** /**
* AdminUsersViewData * AdminUsersViewData
* *
* ViewData for AdminUsersTemplate. * ViewData for AdminUsersTemplate.
* Template-ready data structure with only primitives. * Template-ready data structure with only primitives.
*/ */
export interface AdminUsersViewData {
export interface AdminUsersViewData extends ViewData {
users: Array<{ users: Array<{
id: string; id: string;
email: string; email: string;

View File

@@ -0,0 +1,13 @@
import { ViewData } from "../contracts/view-data/ViewData";
export interface AnalyticsDashboardViewData extends ViewData {
metrics: {
totalUsers: number;
activeUsers: number;
totalRaces: number;
totalLeagues: number;
userEngagementRate: number;
formattedEngagementRate: string;
activityLevel: string;
};
}

View File

@@ -0,0 +1,42 @@
import { ViewData } from "../contracts/view-data/ViewData";
export interface AvailableLeaguesViewData extends ViewData {
leagues: AvailableLeagueViewData[];
}
export interface AvailableLeagueViewData {
id: string;
name: string;
game: string;
drivers: number;
avgViewsPerRace: number;
formattedAvgViews: string;
mainSponsorSlot: {
available: boolean;
price: number;
};
secondarySlots: {
available: number;
total: number;
price: number;
};
cpm: number;
formattedCpm: string;
hasAvailableSlots: boolean;
rating: number;
tier: 'premium' | 'standard' | 'starter';
tierConfig: {
color: string;
bgColor: string;
border: string;
icon: string;
};
nextRace?: string;
seasonStatus: 'active' | 'upcoming' | 'completed';
statusConfig: {
color: string;
bg: string;
label: string;
};
description: string;
}

View File

@@ -0,0 +1,12 @@
import { ViewData } from "../contracts/view-data/ViewData";
/**
* AvatarGenerationViewData
*
* ViewData for avatar generation process.
*/
export interface AvatarGenerationViewData extends ViewData {
success: boolean;
avatarUrls: string[];
errorMessage?: string;
}

View File

@@ -1,9 +1,12 @@
import { ViewData } from '@/lib/contracts/view-data/ViewData';
/** /**
* AvatarViewData * AvatarViewData
* *
* ViewData for avatar media rendering. * ViewData for avatar media rendering.
*/ */
export interface AvatarViewData {
export interface AvatarViewData extends ViewData {
buffer: string; // base64 encoded buffer: string; // base64 encoded
contentType: string; contentType: string;
} }

View File

@@ -1,9 +1,13 @@
import { ViewData } from '@/lib/contracts/view-data/ViewData';
/** /**
* CategoryIconViewData * CategoryIconViewData
* *
* ViewData for category icon media rendering. * ViewData for category icon media rendering.
*/ */
export interface CategoryIconViewData { import { ViewData } from "../contracts/view-data/ViewData";
export interface CategoryIconViewData extends ViewData {
buffer: string; // base64 encoded buffer: string; // base64 encoded
contentType: string; contentType: string;
} }

View File

@@ -0,0 +1,14 @@
import { ViewData } from '../contracts/view-data/ViewData';
/**
* CreateLeagueViewData
*
* ViewData for the create league result page.
* Contains only raw serializable data, no methods or computed properties
*/
export interface CreateLeagueViewData extends ViewData {
leagueId: string;
success: boolean;
successMessage: string;
}

View File

@@ -1,3 +1,5 @@
import { ViewData } from '@/lib/contracts/view-data/ViewData';
/** /**
* Dashboard ViewData * Dashboard ViewData
* *
@@ -6,7 +8,8 @@
* for display and ISO string timestamps for JSON serialization. * for display and ISO string timestamps for JSON serialization.
*/ */
export interface DashboardViewData {
export interface DashboardViewData extends ViewData {
currentDriver: { currentDriver: {
name: string; name: string;
avatarUrl: string; avatarUrl: string;

View File

@@ -1,4 +1,7 @@
export interface DriverRankingItem { import { ViewData } from '@/lib/contracts/view-data/ViewData';
export interface DriverRankingItem extends ViewData {
id: string; id: string;
name: string; name: string;
rating: number; rating: number;

View File

@@ -1,7 +1,9 @@
import { ViewData } from '@/lib/contracts/view-data/ViewData';
import type { DriverRankingItem } from './DriverRankingItem'; import type { DriverRankingItem } from './DriverRankingItem';
import type { PodiumDriver } from './PodiumDriver'; import type { PodiumDriver } from './PodiumDriver';
export interface DriverRankingsViewData {
export interface DriverRankingsViewData extends ViewData {
drivers: DriverRankingItem[]; drivers: DriverRankingItem[];
podium: PodiumDriver[]; podium: PodiumDriver[];
searchQuery: string; searchQuery: string;

View File

@@ -0,0 +1,18 @@
import { ViewData } from '@/lib/contracts/view-data/ViewData';
/**
* Forgot Password View Data
*
* ViewData for the forgot password template.
*/
export interface ForgotPasswordViewData extends ViewData {
returnTo: string;
showSuccess: boolean;
successMessage?: string;
magicLink?: string;
formState: any; // Will be managed by client component
isSubmitting: boolean;
submitError?: string;
}

View File

@@ -1,3 +1,4 @@
/** /**
* Health View Data Types * Health View Data Types
* *
@@ -52,7 +53,9 @@ export interface HealthAlert {
severityColor: string; severityColor: string;
} }
export interface HealthViewData { import { ViewData } from "../contracts/view-data/ViewData";
export interface HealthViewData extends ViewData {
overallStatus: HealthStatus; overallStatus: HealthStatus;
metrics: HealthMetrics; metrics: HealthMetrics;
components: HealthComponent[]; components: HealthComponent[];

View File

@@ -1,4 +1,7 @@
export interface LeaderboardDriverItem { import { ViewData } from '@/lib/contracts/view-data/ViewData';
export interface LeaderboardDriverItem extends ViewData {
id: string; id: string;
name: string; name: string;
rating: number; rating: number;

View File

@@ -1,4 +1,7 @@
export interface LeaderboardTeamItem { import { ViewData } from '@/lib/contracts/view-data/ViewData';
export interface LeaderboardTeamItem extends ViewData {
id: string; id: string;
name: string; name: string;
tag: string; tag: string;

View File

@@ -1,7 +1,9 @@
import { ViewData } from '@/lib/contracts/view-data/ViewData';
import type { LeaderboardDriverItem } from './LeaderboardDriverItem'; import type { LeaderboardDriverItem } from './LeaderboardDriverItem';
import type { LeaderboardTeamItem } from './LeaderboardTeamItem'; import type { LeaderboardTeamItem } from './LeaderboardTeamItem';
export interface LeaderboardsViewData {
export interface LeaderboardsViewData extends ViewData {
drivers: LeaderboardDriverItem[]; drivers: LeaderboardDriverItem[];
teams: LeaderboardTeamItem[]; teams: LeaderboardTeamItem[];
} }

View File

@@ -1,17 +1,10 @@
export interface AdminScheduleRaceData { import { ViewData } from '@/lib/contracts/view-data/ViewData';
export interface AdminScheduleRaceData extends ViewData {
id: string; id: string;
name: string; name: string;
track: string; track: string;
car: string; car: string;
scheduledAt: string; // ISO string scheduledAt: string; // ISO string
} }
export interface LeagueAdminScheduleViewData {
published: boolean;
races: AdminScheduleRaceData[];
seasons: Array<{
seasonId: string;
name: string;
}>;
seasonId: string;
}

View File

@@ -1,9 +1,12 @@
import { ViewData } from '@/lib/contracts/view-data/ViewData';
/** /**
* LeagueCoverViewData * LeagueCoverViewData
* *
* ViewData for league cover media rendering. * ViewData for league cover media rendering.
*/ */
export interface LeagueCoverViewData {
export interface LeagueCoverViewData extends ViewData {
buffer: string; // base64 encoded buffer: string; // base64 encoded
contentType: string; contentType: string;
} }

View File

@@ -87,6 +87,7 @@ export interface RecentResult {
finishedAt: string; finishedAt: string;
} }
export interface LeagueDetailViewData extends ViewData { export interface LeagueDetailViewData extends ViewData {
// Basic info // Basic info
leagueId: string; leagueId: string;

View File

@@ -1,9 +1,12 @@
import { ViewData } from '@/lib/contracts/view-data/ViewData';
/** /**
* LeagueLogoViewData * LeagueLogoViewData
* *
* ViewData for league logo media rendering. * ViewData for league logoViewData extends ViewData {dering.
*/ */
export interface LeagueLogoViewData {
export interface LeagueLogoViewData extends ViewData {
buffer: string; // base64 encoded buffer: string; // base64 encoded
contentType: string; contentType: string;
} }

View File

@@ -1,3 +1,5 @@
import { ViewData } from '@/lib/contracts/view-data/ViewData';
/** /**
* LeagueRosterAdminViewData - Pure ViewData for RosterAdminPage * LeagueRosterAdminViewData - Pure ViewData for RosterAdminPage
* Contains only raw serializable data, no methods or computed properties * Contains only raw serializable data, no methods or computed properties
@@ -25,7 +27,8 @@ export interface JoinRequestData {
message?: string; message?: string;
} }
export interface LeagueRosterAdminViewData {
export interface LeagueRosterAdminViewData extends ViewData {
leagueId: string; leagueId: string;
members: RosterMemberData[]; members: RosterMemberData[];
joinRequests: JoinRequestData[]; joinRequests: JoinRequestData[];

View File

@@ -1,4 +1,7 @@
export interface RulebookScoringConfig { import { ViewData } from '@/lib/contracts/view-data/ViewData';
export interface RulebookScoringConfig extends ViewData {
scoringPresetName: string | null; scoringPresetName: string | null;
gameName: string; gameName: string;
championships: Array<{ championships: Array<{
@@ -12,9 +15,4 @@ export interface RulebookScoringConfig {
bonusSummary: string[]; bonusSummary: string[];
}>; }>;
dropPolicySummary: string; dropPolicySummary: string;
} }
export interface LeagueRulebookViewData {
scoringConfig: RulebookScoringConfig | null;
positionPoints: Array<{ position: number; points: number }>;
}

View File

@@ -1,3 +1,5 @@
import { ViewData } from '@/lib/contracts/view-data/ViewData';
/** /**
* LeagueScheduleViewData - Pure ViewData for LeagueScheduleTemplate * LeagueScheduleViewData - Pure ViewData for LeagueScheduleTemplate
* Contains only raw serializable data, no methods or computed properties * Contains only raw serializable data, no methods or computed properties
@@ -12,7 +14,8 @@ export interface ScheduleRaceData {
status: string; status: string;
} }
export interface LeagueScheduleViewData {
export interface LeagueScheduleViewData extends ViewData {
leagueId: string; leagueId: string;
races: ScheduleRaceData[]; races: ScheduleRaceData[];
seasons: Array<{ seasons: Array<{

View File

@@ -1,4 +1,7 @@
export interface LeagueSettingsViewData { import { ViewData } from "../contracts/view-data/ViewData";
export interface LeagueSettingsViewData extends ViewData {
leagueId: string; leagueId: string;
league: { league: {
id: string; id: string;

View File

@@ -1,4 +1,7 @@
export interface LeagueSponsorshipsViewData { import { ViewData } from '@/lib/contracts/view-data/ViewData';
export interface LeagueSponsorshipsViewData extends ViewData {
leagueId: string; leagueId: string;
activeTab: 'overview' | 'editor'; activeTab: 'overview' | 'editor';
onTabChange: (tab: 'overview' | 'editor') => void; onTabChange: (tab: 'overview' | 'editor') => void;

View File

@@ -1,25 +1,4 @@
/**
* LeagueStandingsViewData - Pure ViewData for LeagueStandingsTemplate
* Contains only raw serializable data, no methods or computed properties
*/
export interface StandingEntryData {
driverId: string;
position: number;
totalPoints: number;
racesFinished: number;
racesStarted: number;
avgFinish: number | null;
penaltyPoints: number;
bonusPoints: number;
teamName?: string;
// New fields from Phase 3
positionChange: number;
lastRacePoints: number;
droppedRaceIds: string[];
wins: number;
podiums: number;
}
export interface DriverData { export interface DriverData {
id: string; id: string;
@@ -36,15 +15,4 @@ export interface LeagueMembershipData {
role: 'owner' | 'admin' | 'steward' | 'member'; role: 'owner' | 'admin' | 'steward' | 'member';
joinedAt: string; joinedAt: string;
status: 'active' | 'pending' | 'banned'; status: 'active' | 'pending' | 'banned';
}
export interface LeagueStandingsViewData {
standings: StandingEntryData[];
drivers: DriverData[];
memberships: LeagueMembershipData[];
leagueId: string;
currentDriverId: string | null;
isAdmin: boolean;
// New fields for team standings toggle
isTeamChampionship?: boolean;
} }

View File

@@ -0,0 +1,16 @@
import { ViewData } from "../contracts/view-data/ViewData";
export interface LeagueWalletTransactionViewData extends ViewData {
id: string;
type: 'deposit' | 'withdrawal' | 'sponsorship' | 'prize';
amount: number;
formattedAmount: string;
amountColor: string;
description: string;
createdAt: string;
formattedDate: string;
status: 'completed' | 'pending' | 'failed';
statusColor: string;
typeColor: string;
}

View File

@@ -1,3 +1,5 @@
import { ViewData } from '@/lib/contracts/view-data/ViewData';
/** /**
* Leagues ViewData * Leagues ViewData
* *
@@ -6,7 +8,8 @@
* for display and ISO string timestamps for JSON serialization. * for display and ISO string timestamps for JSON serialization.
*/ */
export interface LeaguesViewData {
export interface LeaguesViewData extends ViewData {
leagues: Array<{ leagues: Array<{
id: string; id: string;
name: string; name: string;

View File

@@ -0,0 +1,20 @@
/**
* Login View Data
*
* ViewData for the login template.
*/
import { FormState } from '../builders/view-data/types/FormState';
import { ViewData } from '@/lib/contracts/view-data/ViewData';
export interface LoginViewData extends ViewData {
returnTo: string;
hasInsufficientPermissions: boolean;
showPassword: boolean;
showErrorDetails: boolean;
formState: FormState;
isSubmitting: boolean;
submitError?: string;
}

View File

@@ -1,6 +1,8 @@
import { MediaAsset } from '@/components/media/MediaGallery'; import { MediaAsset } from '@/components/media/MediaGallery';
import { ViewData } from '../contracts/view-data/ViewData';
export interface MediaViewData {
export interface MediaViewData extends ViewData {
assets: MediaAsset[]; assets: MediaAsset[];
categories: { label: string; value: string }[]; categories: { label: string; value: string }[];
title: string; title: string;

View File

@@ -1,3 +1,6 @@
export interface OnboardingPageViewData { import { ViewData } from "../contracts/view-data/ViewData";
export interface OnboardingPageViewData extends ViewData {
isAlreadyOnboarded: boolean; isAlreadyOnboarded: boolean;
} }

View File

@@ -1,4 +1,7 @@
export interface PodiumDriver { import { ViewData } from '@/lib/contracts/view-data/ViewData';
export interface PodiumDriverViewData extends ViewData {
id: string; id: string;
name: string; name: string;
rating: number; rating: number;

View File

@@ -1,3 +1,6 @@
export interface ProfileLayoutViewData { import { ViewData } from "../contracts/view-data/ViewData";
export interface ProfileLayoutViewData extends ViewData {
// Empty for now // Empty for now
} }

View File

@@ -3,14 +3,18 @@
* Pure, JSON-serializable data structure for Template rendering * Pure, JSON-serializable data structure for Template rendering
*/ */
export interface ProfileLeaguesLeagueViewData { import { ViewData } from "../contracts/view-data/ViewData";
export interface ProfileLeaguesLeagueViewData extends ViewData {
leagueId: string; leagueId: string;
name: string; name: string;
description: string; description: string;
membershipRole: 'owner' | 'admin' | 'steward' | 'member'; membershipRole: 'owner' | 'admin' | 'steward' | 'member';
} }
export interface ProfileLeaguesViewData {
export interface ProfileLeaguesViewData extends ViewData {
ownedLeagues: ProfileLeaguesLeagueViewData[]; ownedLeagues: ProfileLeaguesLeagueViewData[];
memberLeagues: ProfileLeaguesLeagueViewData[]; memberLeagues: ProfileLeaguesLeagueViewData[];
} }

View File

@@ -1,4 +1,7 @@
export interface ProfileLiveryViewData { import { ViewData } from "../contracts/view-data/ViewData";
export interface ProfileLiveryViewData extends ViewData {
id: string; id: string;
carId: string; carId: string;
carName: string; carName: string;
@@ -7,6 +10,7 @@ export interface ProfileLiveryViewData {
isValidated: boolean; isValidated: boolean;
} }
export interface ProfileLiveriesViewData {
export interface ProfileLiveriesViewData extends ViewData {
liveries: ProfileLiveryViewData[]; liveries: ProfileLiveryViewData[];
} }

View File

@@ -1,4 +1,7 @@
export interface ProfileViewData { import { ViewData } from "../contracts/view-data/ViewData";
export interface ProfileViewData extends ViewData {
driver: { driver: {
id: string; id: string;
name: string; name: string;

View File

@@ -1,4 +1,7 @@
export interface ProtestDetailViewData { import { ViewData } from "../contracts/view-data/ViewData";
export interface ProtestDetailViewData extends ViewData {
protestId: string; protestId: string;
leagueId: string; leagueId: string;
status: string; status: string;

View File

@@ -5,6 +5,8 @@
* JSON-serializable, template-ready data structure. * JSON-serializable, template-ready data structure.
*/ */
import { ViewData } from "../contracts/view-data/ViewData";
export interface RaceDetailEntry { export interface RaceDetailEntry {
id: string; id: string;
name: string; name: string;
@@ -48,7 +50,8 @@ export interface RaceDetailRegistration {
canRegister: boolean; canRegister: boolean;
} }
export interface RaceDetailViewData {
export interface RaceDetailViewData extends ViewData {
race: RaceDetailRace; race: RaceDetailRace;
league?: RaceDetailLeague; league?: RaceDetailLeague;
entryList: RaceDetailEntry[]; entryList: RaceDetailEntry[];

View File

@@ -5,6 +5,8 @@
* JSON-serializable, template-ready data structure. * JSON-serializable, template-ready data structure.
*/ */
import { ViewData } from "../contracts/view-data/ViewData";
export interface RaceResultsResult { export interface RaceResultsResult {
position: number; position: number;
driverId: string; driverId: string;
@@ -29,7 +31,8 @@ export interface RaceResultsPenalty {
notes?: string; notes?: string;
} }
export interface RaceResultsViewData {
export interface RaceResultsViewData extends ViewData {
raceTrack?: string; raceTrack?: string;
raceScheduledAt?: string; raceScheduledAt?: string;
totalDrivers?: number; totalDrivers?: number;

View File

@@ -5,6 +5,8 @@
* JSON-serializable, template-ready data structure. * JSON-serializable, template-ready data structure.
*/ */
import { ViewData } from "../contracts/view-data/ViewData";
export interface Protest { export interface Protest {
id: string; id: string;
protestingDriverId: string; protestingDriverId: string;
@@ -33,7 +35,8 @@ export interface Driver {
name: string; name: string;
} }
export interface RaceStewardingViewData {
export interface RaceStewardingViewData extends ViewData {
race?: { race?: {
id: string; id: string;
track: string; track: string;

View File

@@ -1,4 +1,7 @@
export interface RaceViewData { import { ViewData } from "../contracts/view-data/ViewData";
export interface RaceViewData extends ViewData {
id: string; id: string;
track: string; track: string;
car: string; car: string;
@@ -19,7 +22,8 @@ export interface RaceViewData {
isPast: boolean; isPast: boolean;
} }
export interface RacesViewData {
export interface RacesViewData extends ViewData {
races: RaceViewData[]; races: RaceViewData[];
totalCount: number; totalCount: number;
scheduledCount: number; scheduledCount: number;

View File

@@ -0,0 +1,18 @@
/**
* Reset Password View Data
*
* ViewData for the reset password template.
*/
import { ViewData } from "../contracts/view-data/ViewData";
export interface ResetPasswordViewData extends ViewData {
token: string;
returnTo: string;
showSuccess: boolean;
successMessage?: string;
formState: any; // Will be managed by client component
isSubmitting: boolean;
submitError?: string;
}

View File

@@ -1,4 +1,7 @@
export interface RulebookViewData { import { ViewData } from "../contracts/view-data/ViewData";
export interface RulebookViewData extends ViewData {
leagueId: string; leagueId: string;
gameName: string; gameName: string;
scoringPresetName: string; scoringPresetName: string;

View File

@@ -0,0 +1,15 @@
/**
* Signup View Data
*
* ViewData for the signup template.
*/
import { ViewData } from "../contracts/view-data/ViewData";
export interface SignupViewData extends ViewData {
returnTo: string;
formState: any; // Will be managed by client component
isSubmitting: boolean;
submitError?: string;
}

View File

@@ -1,4 +1,7 @@
export interface SponsorDashboardViewData { import { ViewData } from "../contracts/view-data/ViewData";
export interface SponsorDashboardViewData extends ViewData {
sponsorName: string; sponsorName: string;
totalImpressions: string; totalImpressions: string;
totalInvestment: string; totalInvestment: string;

View File

@@ -1,9 +1,12 @@
import { ViewData } from "../contracts/view-data/ViewData";
/** /**
* SponsorLogoViewData * SponsorLogoViewData
* *
* ViewData for sponsor logo media rendering. * ViewData for sponsor logo media rendering.
*/ */
export interface SponsorLogoViewData {
export interface SponsorLogoViewData extends ViewData {
buffer: string; // base64 encoded buffer: string; // base64 encoded
contentType: string; contentType: string;
} }

View File

@@ -1,4 +1,7 @@
export interface StewardingViewData { import { ViewData } from "../contracts/view-data/ViewData";
export interface StewardingViewData extends ViewData {
leagueId: string; leagueId: string;
totalPending: number; totalPending: number;
totalResolved: number; totalResolved: number;

View File

@@ -3,6 +3,8 @@
* Contains only raw serializable data, no methods or computed properties * Contains only raw serializable data, no methods or computed properties
*/ */
import { ViewData } from "../contracts/view-data/ViewData";
export interface SponsorMetric { export interface SponsorMetric {
icon: string; // Icon name (e.g. 'users', 'zap', 'calendar') icon: string; // Icon name (e.g. 'users', 'zap', 'calendar')
label: string; label: string;
@@ -51,7 +53,8 @@ export interface TeamTab {
visible: boolean; visible: boolean;
} }
export interface TeamDetailViewData {
export interface TeamDetailViewData extends ViewData {
team: TeamDetailData; team: TeamDetailData;
memberships: TeamMemberData[]; memberships: TeamMemberData[];
currentDriverId: string; currentDriverId: string;

View File

@@ -1,9 +1,11 @@
import { ViewData } from '../contracts/view-data/ViewData';
import type { TeamSummaryViewModel } from '../view-models/TeamSummaryViewModel'; import type { TeamSummaryViewModel } from '../view-models/TeamSummaryViewModel';
export type SkillLevel = 'pro' | 'advanced' | 'intermediate' | 'beginner'; export type SkillLevel = 'pro' | 'advanced' | 'intermediate' | 'beginner';
export type SortBy = 'rating' | 'wins' | 'winRate' | 'races'; export type SortBy = 'rating' | 'wins' | 'winRate' | 'races';
export interface TeamLeaderboardViewData {
export interface TeamLeaderboardViewData extends ViewData {
teams: TeamSummaryViewModel[]; teams: TeamSummaryViewModel[];
searchQuery: string; searchQuery: string;
filterLevel: SkillLevel | 'all'; filterLevel: SkillLevel | 'all';

View File

@@ -1,9 +1,12 @@
import { ViewData } from "../contracts/view-data/ViewData";
/** /**
* TeamLogoViewData * TeamLogoViewData
* *
* ViewData for team logo media rendering. * ViewData for team logo media rendering.
*/ */
export interface TeamLogoViewData {
export interface TeamLogoViewData extends ViewData {
buffer: string; // base64 encoded buffer: string; // base64 encoded
contentType: string; contentType: string;
} }

View File

@@ -1,6 +1,8 @@
import { ViewData } from '../contracts/view-data/ViewData';
import type { LeaderboardTeamItem } from './LeaderboardTeamItem'; import type { LeaderboardTeamItem } from './LeaderboardTeamItem';
export interface TeamRankingsViewData {
export interface TeamRankingsViewData extends ViewData {
teams: LeaderboardTeamItem[]; teams: LeaderboardTeamItem[];
podium: LeaderboardTeamItem[]; podium: LeaderboardTeamItem[];
recruitingCount: number; recruitingCount: number;

View File

@@ -22,6 +22,7 @@ export interface TeamSummaryData {
countryCode?: string; countryCode?: string;
} }
export interface TeamsViewData extends ViewData { export interface TeamsViewData extends ViewData {
teams: TeamSummaryData[]; teams: TeamSummaryData[];
} }

View File

@@ -1,9 +1,12 @@
import { ViewData } from "../contracts/view-data/ViewData";
/** /**
* TrackImageViewData * TrackImageViewData
* *
* ViewData for track image media rendering. * ViewData for track image media rendering.
*/ */
export interface TrackImageViewData {
export interface TrackImageViewData extends ViewData {
buffer: string; // base64 encoded buffer: string; // base64 encoded
contentType: string; contentType: string;
} }

View File

@@ -1,24 +0,0 @@
export interface LeagueScheduleViewData {
leagueId: string;
races: Array<{
id: string;
name: string;
scheduledAt: string; // ISO string
track?: string;
car?: string;
sessionType?: string;
isPast: boolean;
isUpcoming: boolean;
status: 'scheduled' | 'completed';
strengthOfField?: number;
// Registration info
isUserRegistered?: boolean;
canRegister?: boolean;
// Admin info
canEdit?: boolean;
canReschedule?: boolean;
}>;
// User permissions
currentDriverId?: string;
isAdmin: boolean;
}

View File

@@ -1,27 +0,0 @@
export interface LeagueWalletTransactionViewData {
id: string;
type: 'deposit' | 'withdrawal' | 'sponsorship' | 'prize';
amount: number;
formattedAmount: string;
amountColor: string;
description: string;
createdAt: string;
formattedDate: string;
status: 'completed' | 'pending' | 'failed';
statusColor: string;
typeColor: string;
}
export interface LeagueWalletViewData {
leagueId: string;
balance: number;
formattedBalance: string;
totalRevenue: number;
formattedTotalRevenue: string;
totalFees: number;
formattedTotalFees: string;
pendingPayouts: number;
formattedPendingPayouts: string;
currency: string;
transactions: LeagueWalletTransactionViewData[];
}

View File

@@ -1,7 +1,6 @@
import React from 'react';
import { ErrorScreen } from '@/components/errors/ErrorScreen'; import { ErrorScreen } from '@/components/errors/ErrorScreen';
export interface FatalErrorViewData { export interface FatalErrorViewData extends ViewData {
error: Error & { digest?: string }; error: Error & { digest?: string };
} }

View File

@@ -1,15 +1,16 @@
'use client'; 'use client';
import { CtaSection } from '@/components/home/CtaSection';
import { Hero } from '@/components/home/Hero'; import { Hero } from '@/components/home/Hero';
import { TelemetryStrip } from '@/components/home/TelemetryStrip';
import { ValuePillars } from '@/components/home/ValuePillars';
import { StewardingPreview } from '@/components/home/StewardingPreview';
import { LeagueIdentityPreview } from '@/components/home/LeagueIdentityPreview'; import { LeagueIdentityPreview } from '@/components/home/LeagueIdentityPreview';
import { MigrationSection } from '@/components/home/MigrationSection'; import { MigrationSection } from '@/components/home/MigrationSection';
import { CtaSection } from '@/components/home/CtaSection'; import { StewardingPreview } from '@/components/home/StewardingPreview';
import { TelemetryStrip } from '@/components/home/TelemetryStrip';
import { ValuePillars } from '@/components/home/ValuePillars';
import { ViewData } from '@/lib/contracts/view-data/ViewData';
import { Stack } from '@/ui/Stack'; import { Stack } from '@/ui/Stack';
export interface HomeViewData { export interface HomeViewData extends ViewData {
isAlpha: boolean; isAlpha: boolean;
upcomingRaces: Array<{ upcomingRaces: Array<{
id: string; id: string;

View File

@@ -1,11 +1,11 @@
'use client'; 'use client';
import type { LeagueSettingsViewData } from '@/lib/view-data/leagues/LeagueSettingsViewData'; import type { LeagueSettingsViewData } from '@/lib/view-data/LeagueSettingsViewData';
import { Box } from '@/ui/Box'; import { Box } from '@/ui/Box';
import { Heading } from '@/ui/Heading';
import { Icon } from '@/ui/Icon';
import { Grid } from '@/ui/Grid'; import { Grid } from '@/ui/Grid';
import { GridItem } from '@/ui/GridItem'; import { GridItem } from '@/ui/GridItem';
import { Heading } from '@/ui/Heading';
import { Icon } from '@/ui/Icon';
import { Stack } from '@/ui/Stack'; import { Stack } from '@/ui/Stack';
import { Surface } from '@/ui/Surface'; import { Surface } from '@/ui/Surface';
import { Text } from '@/ui/Text'; import { Text } from '@/ui/Text';

View File

@@ -3,12 +3,12 @@
import { LeagueDecalPlacementEditor } from '@/components/leagues/LeagueDecalPlacementEditor'; import { LeagueDecalPlacementEditor } from '@/components/leagues/LeagueDecalPlacementEditor';
import { SponsorshipRequestCard } from '@/components/leagues/SponsorshipRequestCard'; import { SponsorshipRequestCard } from '@/components/leagues/SponsorshipRequestCard';
import { SponsorshipSlotCard } from '@/components/leagues/SponsorshipSlotCard'; import { SponsorshipSlotCard } from '@/components/leagues/SponsorshipSlotCard';
import type { LeagueSponsorshipsViewData } from '@/lib/view-data/leagues/LeagueSponsorshipsViewData'; import type { LeagueSponsorshipsViewData } from '@/lib/view-data/LeagueSponsorshipsViewData';
import { Box } from '@/ui/Box'; import { Box } from '@/ui/Box';
import { Card } from '@/ui/Card'; import { Card } from '@/ui/Card';
import { Grid } from '@/ui/Grid';
import { Heading } from '@/ui/Heading'; import { Heading } from '@/ui/Heading';
import { Icon } from '@/ui/Icon'; import { Icon } from '@/ui/Icon';
import { Grid } from '@/ui/Grid';
import { Stack } from '@/ui/Stack'; import { Stack } from '@/ui/Stack';
import { Surface } from '@/ui/Surface'; import { Surface } from '@/ui/Surface';
import { Text } from '@/ui/Text'; import { Text } from '@/ui/Text';

View File

@@ -1,7 +1,8 @@
'use client'; 'use client';
import { WalletSummaryPanel } from '@/components/leagues/WalletSummaryPanel'; import { WalletSummaryPanel } from '@/components/leagues/WalletSummaryPanel';
import type { LeagueWalletViewData } from '@/lib/view-data/leagues/LeagueWalletViewData'; import { TemplateProps } from '@/lib/contracts/components/ComponentContracts';
import type { LeagueWalletViewData } from '@/lib/view-data/LeagueWalletViewData';
import { Box } from '@/ui/Box'; import { Box } from '@/ui/Box';
import { Button } from '@/ui/Button'; import { Button } from '@/ui/Button';
import { Container } from '@/ui/Container'; import { Container } from '@/ui/Container';
@@ -10,7 +11,6 @@ import { Icon } from '@/ui/Icon';
import { Stack } from '@/ui/Stack'; import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text'; import { Text } from '@/ui/Text';
import { Download } from 'lucide-react'; import { Download } from 'lucide-react';
import { TemplateProps } from '@/lib/contracts/components/ComponentContracts';
interface LeagueWalletTemplateProps extends TemplateProps<LeagueWalletViewData> { interface LeagueWalletTemplateProps extends TemplateProps<LeagueWalletViewData> {
onWithdraw?: (amount: number) => void; onWithdraw?: (amount: number) => void;

View File

@@ -1,9 +1,9 @@
'use client'; 'use client';
import React from 'react';
import { NotFoundScreen } from '@/components/errors/NotFoundScreen'; import { NotFoundScreen } from '@/components/errors/NotFoundScreen';
import { ViewData } from '@/lib/contracts/view-data/ViewData';
export interface NotFoundViewData { export interface NotFoundViewData extends ViewData {
errorCode: string; errorCode: string;
title: string; title: string;
message: string; message: string;

View File

@@ -11,8 +11,8 @@ import { Box } from '@/ui/Box';
import { Container } from '@/ui/Container'; import { Container } from '@/ui/Container';
import { Grid } from '@/ui/Grid'; import { Grid } from '@/ui/Grid';
import { GridItem } from '@/ui/GridItem'; import { GridItem } from '@/ui/GridItem';
import { Stack } from '@/ui/Stack';
import { Skeleton } from '@/ui/Skeleton'; import { Skeleton } from '@/ui/Skeleton';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text'; import { Text } from '@/ui/Text';
export interface RaceDetailEntryViewModel { export interface RaceDetailEntryViewModel {
@@ -58,7 +58,7 @@ export interface RaceDetailRegistration {
canRegister: boolean; canRegister: boolean;
} }
export interface RaceDetailViewData { export interface RaceDetailViewData extends ViewData {
race: RaceDetailRace; race: RaceDetailRace;
league?: RaceDetailLeague; league?: RaceDetailLeague;
entryList: RaceDetailEntryViewModel[]; entryList: RaceDetailEntryViewModel[];

View File

@@ -2,12 +2,12 @@
import { RaceDetailsHeader } from '@/components/races/RaceDetailsHeader'; import { RaceDetailsHeader } from '@/components/races/RaceDetailsHeader';
import { RaceResultsTable } from '@/components/races/RaceResultsTable'; import { RaceResultsTable } from '@/components/races/RaceResultsTable';
import type { RaceResultsViewData } from '@/lib/view-data/races/RaceResultsViewData'; import type { RaceResultsViewData } from '@/lib/view-data/RaceResultsViewData';
import { Box } from '@/ui/Box'; import { Box } from '@/ui/Box';
import { Container } from '@/ui/Container'; import { Container } from '@/ui/Container';
import { Icon } from '@/ui/Icon';
import { Grid } from '@/ui/Grid'; import { Grid } from '@/ui/Grid';
import { GridItem } from '@/ui/GridItem'; import { GridItem } from '@/ui/GridItem';
import { Icon } from '@/ui/Icon';
import { Stack } from '@/ui/Stack'; import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text'; import { Text } from '@/ui/Text';
import { AlertTriangle, Trophy, Zap, type LucideIcon } from 'lucide-react'; import { AlertTriangle, Trophy, Zap, type LucideIcon } from 'lucide-react';

View File

@@ -5,12 +5,12 @@ import { StewardingTabs } from '@/components/leagues/StewardingTabs';
import { RaceDetailsHeader } from '@/components/races/RaceDetailsHeader'; import { RaceDetailsHeader } from '@/components/races/RaceDetailsHeader';
import { RacePenaltyRow } from '@/components/races/RacePenaltyRowWrapper'; import { RacePenaltyRow } from '@/components/races/RacePenaltyRowWrapper';
import { RaceStewardingStats } from '@/components/races/RaceStewardingStats'; import { RaceStewardingStats } from '@/components/races/RaceStewardingStats';
import type { RaceStewardingViewData } from '@/lib/view-data/races/RaceStewardingViewData'; import type { RaceStewardingViewData } from '@/lib/view-data/RaceStewardingViewData';
import { Box } from '@/ui/Box'; import { Box } from '@/ui/Box';
import { Container } from '@/ui/Container'; import { Container } from '@/ui/Container';
import { Icon } from '@/ui/Icon';
import { Grid } from '@/ui/Grid'; import { Grid } from '@/ui/Grid';
import { GridItem } from '@/ui/GridItem'; import { GridItem } from '@/ui/GridItem';
import { Icon } from '@/ui/Icon';
import { Stack } from '@/ui/Stack'; import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text'; import { Text } from '@/ui/Text';
import { CheckCircle, Flag, Gavel, Info } from 'lucide-react'; import { CheckCircle, Flag, Gavel, Info } from 'lucide-react';

View File

@@ -2,11 +2,11 @@
import { RulebookTabs, type RulebookSection } from '@/components/leagues/RulebookTabs'; import { RulebookTabs, type RulebookSection } from '@/components/leagues/RulebookTabs';
import { PointsTable } from '@/components/races/PointsTable'; import { PointsTable } from '@/components/races/PointsTable';
import type { RulebookViewData } from '@/lib/view-data/leagues/RulebookViewData'; import type { RulebookViewData } from '@/lib/view-data/RulebookViewData';
import { Box } from '@/ui/Box'; import { Box } from '@/ui/Box';
import { Grid } from '@/ui/Grid';
import { Heading } from '@/ui/Heading'; import { Heading } from '@/ui/Heading';
import { Icon } from '@/ui/Icon'; import { Icon } from '@/ui/Icon';
import { Grid } from '@/ui/Grid';
import { Stack } from '@/ui/Stack'; import { Stack } from '@/ui/Stack';
import { Surface } from '@/ui/Surface'; import { Surface } from '@/ui/Surface';
import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from '@/ui/Table'; import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from '@/ui/Table';

View File

@@ -3,12 +3,13 @@
import { ErrorDetails } from '@/components/errors/ErrorDetails'; import { ErrorDetails } from '@/components/errors/ErrorDetails';
import { RecoveryActions } from '@/components/errors/RecoveryActions'; import { RecoveryActions } from '@/components/errors/RecoveryActions';
import { ServerErrorPanel } from '@/components/errors/ServerErrorPanel'; import { ServerErrorPanel } from '@/components/errors/ServerErrorPanel';
import { ViewData } from '@/lib/contracts/view-data/ViewData';
import { Box } from '@/ui/Box'; import { Box } from '@/ui/Box';
import { Glow } from '@/ui/Glow'; import { Glow } from '@/ui/Glow';
import { Stack } from '@/ui/Stack'; import { Stack } from '@/ui/Stack';
import { Surface } from '@/ui/Surface'; import { Surface } from '@/ui/Surface';
export interface ServerErrorViewData { export interface ServerErrorViewData extends ViewData {
error: Error & { digest?: string }; error: Error & { digest?: string };
incidentId?: string; incidentId?: string;
} }

View File

@@ -15,16 +15,16 @@ import { InfoBanner } from '@/ui/InfoBanner';
import { Stack } from '@/ui/Stack'; import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text'; import { Text } from '@/ui/Text';
import { import {
Building2, Building2,
CreditCard, CreditCard,
Download, Download,
ExternalLink, ExternalLink,
LucideIcon, LucideIcon,
Percent, Percent,
Receipt Receipt
} from 'lucide-react'; } from 'lucide-react';
export interface SponsorBillingViewData { export interface SponsorBillingViewData extends ViewData {
stats: { stats: {
totalSpent: number; totalSpent: number;
pendingAmount: number; pendingAmount: number;

View File

@@ -7,19 +7,19 @@ import { Container } from '@/ui/Container';
import { Icon } from '@/ui/Icon'; import { Icon } from '@/ui/Icon';
import { Stack } from '@/ui/Stack'; import { Stack } from '@/ui/Stack';
import { import {
BarChart3, BarChart3,
Check, Check,
Clock, Clock,
Eye, Eye,
LucideIcon, LucideIcon,
Search Search
} from 'lucide-react'; } from 'lucide-react';
import React from 'react'; import React from 'react';
export type SponsorshipType = 'all' | 'leagues' | 'teams' | 'drivers' | 'races' | 'platform'; export type SponsorshipType = 'all' | 'leagues' | 'teams' | 'drivers' | 'races' | 'platform';
export type SponsorshipStatus = 'all' | 'active' | 'pending_approval' | 'approved' | 'rejected' | 'expired'; export type SponsorshipStatus = 'all' | 'active' | 'pending_approval' | 'approved' | 'rejected' | 'expired';
export interface SponsorCampaignsViewData { export interface SponsorCampaignsViewData extends ViewData {
sponsorships: Array<{ sponsorships: Array<{
id: string; id: string;
type: string; type: string;

View File

@@ -5,36 +5,36 @@ import { PricingTableShell, PricingTier } from '@/components/sponsors/PricingTab
import { SponsorBrandingPreview } from '@/components/sponsors/SponsorBrandingPreview'; import { SponsorBrandingPreview } from '@/components/sponsors/SponsorBrandingPreview';
import { SponsorDashboardHeader } from '@/components/sponsors/SponsorDashboardHeader'; import { SponsorDashboardHeader } from '@/components/sponsors/SponsorDashboardHeader';
import { SponsorStatusChip } from '@/components/sponsors/SponsorStatusChip'; import { SponsorStatusChip } from '@/components/sponsors/SponsorStatusChip';
import { TemplateProps } from '@/lib/contracts/components/ComponentContracts';
import { ViewData } from '@/lib/contracts/view-data/ViewData';
import { routes } from '@/lib/routing/RouteConfig'; import { routes } from '@/lib/routing/RouteConfig';
import { siteConfig } from '@/lib/siteConfig'; import { siteConfig } from '@/lib/siteConfig';
import { Box } from '@/ui/Box'; import { Box } from '@/ui/Box';
import { Button } from '@/ui/Button'; import { Button } from '@/ui/Button';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Icon } from '@/ui/Icon';
import { Card } from '@/ui/Card'; import { Card } from '@/ui/Card';
import { Container } from '@/ui/Container'; import { Container } from '@/ui/Container';
import { Heading } from '@/ui/Heading';
import { Link } from '@/ui/Link';
import { Grid } from '@/ui/Grid'; import { Grid } from '@/ui/Grid';
import { GridItem } from '@/ui/GridItem'; import { GridItem } from '@/ui/GridItem';
import { Heading } from '@/ui/Heading';
import { Icon } from '@/ui/Icon';
import { Link } from '@/ui/Link';
import { Stack } from '@/ui/Stack';
import { Surface } from '@/ui/Surface'; import { Surface } from '@/ui/Surface';
import { Text } from '@/ui/Text';
import { import {
BarChart3, BarChart3,
Calendar, Calendar,
CreditCard, CreditCard,
Eye, Eye,
FileText, FileText,
Flag, Flag,
Megaphone, Megaphone,
TrendingUp, TrendingUp,
Trophy, Trophy,
type LucideIcon type LucideIcon
} from 'lucide-react'; } from 'lucide-react';
import { TemplateProps } from '@/lib/contracts/components/ComponentContracts';
import { ViewData } from '@/lib/contracts/view-data/ViewData';
export interface SponsorLeagueDetailViewData extends ViewData { export interface SponsorLeagueDetailViewData extends ViewData extends ViewData {
league: { league: {
id: string; id: string;
name: string; name: string;

View File

@@ -8,21 +8,21 @@ import { Box } from '@/ui/Box';
import { Button } from '@/ui/Button'; import { Button } from '@/ui/Button';
import { Card } from '@/ui/Card'; import { Card } from '@/ui/Card';
import { Container } from '@/ui/Container'; import { Container } from '@/ui/Container';
import { Grid } from '@/ui/Grid';
import { GridItem } from '@/ui/GridItem';
import { Heading } from '@/ui/Heading'; import { Heading } from '@/ui/Heading';
import { Icon } from '@/ui/Icon'; import { Icon } from '@/ui/Icon';
import { Input } from '@/ui/Input'; import { Input } from '@/ui/Input';
import { Link } from '@/ui/Link'; import { Link } from '@/ui/Link';
import { Grid } from '@/ui/Grid';
import { GridItem } from '@/ui/GridItem';
import { Stack } from '@/ui/Stack'; import { Stack } from '@/ui/Stack';
import { Surface } from '@/ui/Surface'; import { Surface } from '@/ui/Surface';
import { Text } from '@/ui/Text'; import { Text } from '@/ui/Text';
import { import {
Car, Car,
Megaphone, Megaphone,
Search, Search,
Trophy, Trophy,
Users, Users,
} from 'lucide-react'; } from 'lucide-react';
interface AvailableLeague { interface AvailableLeague {
@@ -47,7 +47,7 @@ export type SortOption = 'rating' | 'drivers' | 'price' | 'views';
export type TierFilter = 'all' | 'premium' | 'standard' | 'starter'; export type TierFilter = 'all' | 'premium' | 'standard' | 'starter';
export type AvailabilityFilter = 'all' | 'main' | 'secondary'; export type AvailabilityFilter = 'all' | 'main' | 'secondary';
export interface SponsorLeaguesViewData { export interface SponsorLeaguesViewData extends ViewData {
leagues: AvailableLeague[]; leagues: AvailableLeague[];
stats: { stats: {
total: number; total: number;

View File

@@ -11,15 +11,15 @@ import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text'; import { Text } from '@/ui/Text';
import { Toggle } from '@/ui/Toggle'; import { Toggle } from '@/ui/Toggle';
import { import {
AlertCircle, AlertCircle,
Bell, Bell,
Building2, Building2,
RefreshCw, RefreshCw,
Save Save
} from 'lucide-react'; } from 'lucide-react';
import React from 'react'; import React from 'react';
export interface SponsorSettingsViewData { export interface SponsorSettingsViewData extends ViewData {
profile: { profile: {
companyName: string; companyName: string;
contactName: string; contactName: string;

View File

@@ -6,13 +6,13 @@ import { ReviewProtestModal } from '@/components/leagues/ReviewProtestModal';
import { StewardingQueuePanel } from '@/components/leagues/StewardingQueuePanel'; import { StewardingQueuePanel } from '@/components/leagues/StewardingQueuePanel';
import { StewardingStats } from '@/components/leagues/StewardingStats'; import { StewardingStats } from '@/components/leagues/StewardingStats';
import { PenaltyFAB } from '@/components/races/PenaltyFAB'; import { PenaltyFAB } from '@/components/races/PenaltyFAB';
import type { StewardingViewData } from '@/lib/view-data/leagues/StewardingViewData'; import { TemplateProps } from '@/lib/contracts/components/ComponentContracts';
import type { StewardingViewData } from '@/lib/view-data/StewardingViewData';
import { Box } from '@/ui/Box'; import { Box } from '@/ui/Box';
import { Button } from '@/ui/Button'; import { Button } from '@/ui/Button';
import { Card } from '@/ui/Card';
import { Stack } from '@/ui/Stack'; import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text'; import { Text } from '@/ui/Text';
import { Card } from '@/ui/Card';
import { TemplateProps } from '@/lib/contracts/components/ComponentContracts';
interface StewardingTemplateProps extends TemplateProps<StewardingViewData> { interface StewardingTemplateProps extends TemplateProps<StewardingViewData> {
activeTab: 'pending' | 'history'; activeTab: 'pending' | 'history';

View File

@@ -3,8 +3,8 @@
import { AuthCard } from '@/components/auth/AuthCard'; import { AuthCard } from '@/components/auth/AuthCard';
import { AuthFooterLinks } from '@/components/auth/AuthFooterLinks'; import { AuthFooterLinks } from '@/components/auth/AuthFooterLinks';
import { AuthForm } from '@/components/auth/AuthForm'; import { AuthForm } from '@/components/auth/AuthForm';
import { ForgotPasswordViewData } from '@/lib/builders/view-data/types/ForgotPasswordViewData';
import { routes } from '@/lib/routing/RouteConfig'; import { routes } from '@/lib/routing/RouteConfig';
import { ForgotPasswordViewData } from '@/lib/view-data/ForgotPasswordViewData';
import { Button } from '@/ui/Button'; import { Button } from '@/ui/Button';
import { Group } from '@/ui/Group'; import { Group } from '@/ui/Group';
import { Icon } from '@/ui/Icon'; import { Icon } from '@/ui/Icon';

Some files were not shown because too many files have changed in this diff Show More