website refactor
This commit is contained in:
21
apps/website/lib/display-objects/CountryFlagDisplay.ts
Normal file
21
apps/website/lib/display-objects/CountryFlagDisplay.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
export class CountryFlagDisplay {
|
||||
private constructor(private readonly value: string) {}
|
||||
|
||||
static fromCountryCode(countryCode: string | null | undefined): CountryFlagDisplay {
|
||||
if (!countryCode) {
|
||||
return new CountryFlagDisplay('🏁');
|
||||
}
|
||||
|
||||
const code = countryCode.toUpperCase();
|
||||
if (code.length !== 2) {
|
||||
return new CountryFlagDisplay('🏁');
|
||||
}
|
||||
|
||||
const codePoints = [...code].map((char) => 127397 + char.charCodeAt(0));
|
||||
return new CountryFlagDisplay(String.fromCodePoint(...codePoints));
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* DashboardConsistencyDisplay
|
||||
*
|
||||
* Deterministic consistency formatting for dashboard display.
|
||||
*/
|
||||
|
||||
export class DashboardConsistencyDisplay {
|
||||
static format(consistency: number): string {
|
||||
return `${consistency}%`;
|
||||
}
|
||||
}
|
||||
11
apps/website/lib/display-objects/DashboardCountDisplay.ts
Normal file
11
apps/website/lib/display-objects/DashboardCountDisplay.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* DashboardCountDisplay
|
||||
*
|
||||
* Deterministic count formatting for dashboard display.
|
||||
*/
|
||||
|
||||
export class DashboardCountDisplay {
|
||||
static format(count: number): string {
|
||||
return count.toString();
|
||||
}
|
||||
}
|
||||
53
apps/website/lib/display-objects/DashboardDateDisplay.ts
Normal file
53
apps/website/lib/display-objects/DashboardDateDisplay.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* DashboardDateDisplay
|
||||
*
|
||||
* Deterministic date formatting for dashboard display.
|
||||
* No Intl.* or toLocale* methods.
|
||||
*/
|
||||
|
||||
export interface DashboardDateDisplayData {
|
||||
date: string;
|
||||
time: string;
|
||||
relative: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format date for display (deterministic, no Intl)
|
||||
*/
|
||||
export class DashboardDateDisplay {
|
||||
static format(date: Date): DashboardDateDisplayData {
|
||||
const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
||||
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||||
|
||||
const dayName = days[date.getDay()];
|
||||
const month = months[date.getMonth()];
|
||||
const day = date.getDate();
|
||||
const year = date.getFullYear();
|
||||
|
||||
const hours = date.getHours().toString().padStart(2, '0');
|
||||
const minutes = date.getMinutes().toString().padStart(2, '0');
|
||||
|
||||
// Calculate relative time (deterministic)
|
||||
const now = new Date();
|
||||
const diffMs = date.getTime() - now.getTime();
|
||||
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
||||
const diffDays = Math.floor(diffHours / 24);
|
||||
|
||||
let relative: string;
|
||||
if (diffHours < 0) {
|
||||
relative = 'Past';
|
||||
} else if (diffHours === 0) {
|
||||
relative = 'Now';
|
||||
} else if (diffHours < 24) {
|
||||
relative = `${diffHours}h`;
|
||||
} else {
|
||||
relative = `${diffDays}d`;
|
||||
}
|
||||
|
||||
return {
|
||||
date: `${dayName}, ${month} ${day}, ${year}`,
|
||||
time: `${hours}:${minutes}`,
|
||||
relative,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
/**
|
||||
* Dashboard Display Objects
|
||||
*
|
||||
* Deterministic formatting for dashboard data without Intl.* or toLocale*
|
||||
*/
|
||||
|
||||
export interface DashboardStatDisplayData {
|
||||
icon: string;
|
||||
color: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export interface DashboardDateDisplayData {
|
||||
date: string;
|
||||
time: string;
|
||||
relative: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stat card display configurations
|
||||
*/
|
||||
export const dashboardStatDisplay = {
|
||||
wins: {
|
||||
icon: 'Trophy',
|
||||
color: 'bg-performance-green/20 text-performance-green',
|
||||
label: 'Wins',
|
||||
},
|
||||
podiums: {
|
||||
icon: 'Medal',
|
||||
color: 'bg-warning-amber/20 text-warning-amber',
|
||||
label: 'Podiums',
|
||||
},
|
||||
consistency: {
|
||||
icon: 'Target',
|
||||
color: 'bg-primary-blue/20 text-primary-blue',
|
||||
label: 'Consistency',
|
||||
},
|
||||
activeLeagues: {
|
||||
icon: 'Users',
|
||||
color: 'bg-purple-500/20 text-purple-400',
|
||||
label: 'Active Leagues',
|
||||
},
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Format date for display (deterministic, no Intl)
|
||||
*/
|
||||
export function formatDashboardDate(date: Date): DashboardDateDisplayData {
|
||||
const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
||||
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||||
|
||||
const dayName = days[date.getDay()];
|
||||
const month = months[date.getMonth()];
|
||||
const day = date.getDate();
|
||||
const year = date.getFullYear();
|
||||
|
||||
const hours = date.getHours().toString().padStart(2, '0');
|
||||
const minutes = date.getMinutes().toString().padStart(2, '0');
|
||||
|
||||
// Calculate relative time (deterministic)
|
||||
const now = new Date();
|
||||
const diffMs = date.getTime() - now.getTime();
|
||||
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
||||
const diffDays = Math.floor(diffHours / 24);
|
||||
|
||||
let relative: string;
|
||||
if (diffHours < 0) {
|
||||
relative = 'Past';
|
||||
} else if (diffHours === 0) {
|
||||
relative = 'Now';
|
||||
} else if (diffHours < 24) {
|
||||
relative = `${diffHours}h`;
|
||||
} else {
|
||||
relative = `${diffDays}d`;
|
||||
}
|
||||
|
||||
return {
|
||||
date: `${dayName}, ${month} ${day}, ${year}`,
|
||||
time: `${hours}:${minutes}`,
|
||||
relative,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Format rating for display
|
||||
*/
|
||||
export function formatRating(rating: number): string {
|
||||
return rating.toFixed(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format rank for display
|
||||
*/
|
||||
export function formatRank(rank: number): string {
|
||||
return rank.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format consistency percentage
|
||||
*/
|
||||
export function formatConsistency(consistency: number): string {
|
||||
return `${consistency}%`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format race count
|
||||
*/
|
||||
export function formatRaceCount(count: number): string {
|
||||
return count.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format friend count
|
||||
*/
|
||||
export function formatFriendCount(count: number): string {
|
||||
return count.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format league position
|
||||
*/
|
||||
export function formatLeaguePosition(position: number): string {
|
||||
return `#${position}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format points
|
||||
*/
|
||||
export function formatPoints(points: number): string {
|
||||
return points.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format total drivers
|
||||
*/
|
||||
export function formatTotalDrivers(total: number): string {
|
||||
return total.toString();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* DashboardLeaguePositionDisplay
|
||||
*
|
||||
* Deterministic league position formatting for dashboard display.
|
||||
*/
|
||||
|
||||
export class DashboardLeaguePositionDisplay {
|
||||
static format(position: number): string {
|
||||
return `#${position}`;
|
||||
}
|
||||
}
|
||||
11
apps/website/lib/display-objects/DashboardRankDisplay.ts
Normal file
11
apps/website/lib/display-objects/DashboardRankDisplay.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* DashboardRankDisplay
|
||||
*
|
||||
* Deterministic rank formatting for dashboard display.
|
||||
*/
|
||||
|
||||
export class DashboardRankDisplay {
|
||||
static format(rank: number): string {
|
||||
return rank.toString();
|
||||
}
|
||||
}
|
||||
11
apps/website/lib/display-objects/RatingDisplay.ts
Normal file
11
apps/website/lib/display-objects/RatingDisplay.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* RatingDisplay
|
||||
*
|
||||
* Deterministic rating formatting for display.
|
||||
*/
|
||||
|
||||
export class RatingDisplay {
|
||||
static format(rating: number): string {
|
||||
return rating.toFixed(1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user