do to formatters
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { DateFormatter } from '@/lib/formatters/DateFormatter';
|
||||
import { Card } from '@/ui/Card';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
import { Text } from '@/ui/Text';
|
||||
|
||||
interface AchievementCardProps {
|
||||
title: string;
|
||||
@@ -36,7 +36,7 @@ export function AchievementCard({
|
||||
<Text weight="medium" variant="high">{title}</Text>
|
||||
<Text size="xs" variant="med">{description}</Text>
|
||||
<Text size="xs" variant="low">
|
||||
{DateDisplay.formatShort(unlockedAt)}
|
||||
{DateFormatter.formatShort(unlockedAt)}
|
||||
</Text>
|
||||
</Stack>
|
||||
</Group>
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
import { AchievementDisplay } from '@/lib/display-objects/AchievementDisplay';
|
||||
import { AchievementFormatter } from '@/lib/formatters/AchievementFormatter';
|
||||
import { Card } from '@/ui/Card';
|
||||
import { Grid } from '@/ui/Grid';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { Icon } from '@/ui/Icon';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Surface } from '@/ui/Surface';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Award, Crown, Medal, Star, Target, Trophy, Zap } from 'lucide-react';
|
||||
import React from 'react';
|
||||
|
||||
interface Achievement {
|
||||
id: string;
|
||||
@@ -53,7 +51,7 @@ export function AchievementGrid({ achievements }: AchievementGridProps) {
|
||||
<Grid cols={1} gap={4}>
|
||||
{achievements.map((achievement) => {
|
||||
const AchievementIcon = getAchievementIcon(achievement.icon);
|
||||
const rarity = AchievementDisplay.getRarityVariant(achievement.rarity);
|
||||
const rarity = AchievementFormatter.getRarityVariant(achievement.rarity);
|
||||
return (
|
||||
<Card
|
||||
key={achievement.id}
|
||||
|
||||
@@ -1,26 +1,24 @@
|
||||
'use client';
|
||||
|
||||
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
import { DateFormatter } from '@/lib/formatters/DateFormatter';
|
||||
import { AdminUsersViewData } from '@/lib/view-data/AdminUsersViewData';
|
||||
import { Badge } from '@/ui/Badge';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { DriverIdentity } from '@/ui/DriverIdentity';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { IconButton } from '@/ui/IconButton';
|
||||
import { SimpleCheckbox } from '@/ui/SimpleCheckbox';
|
||||
import { Badge } from '@/ui/Badge';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { DriverIdentity } from '@/ui/DriverIdentity';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow
|
||||
} from '@/ui/Table';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { MoreVertical, Trash2 } from 'lucide-react';
|
||||
import { UserStatusTag } from './UserStatusTag';
|
||||
import React from 'react';
|
||||
|
||||
interface AdminUsersTableProps {
|
||||
users: AdminUsersViewData['users'];
|
||||
@@ -102,7 +100,7 @@ export function AdminUsersTable({
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Text size="sm" variant="low">
|
||||
{user.lastLoginAt ? DateDisplay.formatShort(user.lastLoginAt) : 'Never'}
|
||||
{user.lastLoginAt ? DateFormatter.formatShort(user.lastLoginAt) : 'Never'}
|
||||
</Text>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||
import { CountryFlagDisplay } from '@/lib/display-objects/CountryFlagDisplay';
|
||||
import { CountryFlagFormatter } from '@/lib/formatters/CountryFlagFormatter';
|
||||
import { Badge } from '@/ui/Badge';
|
||||
import { Icon } from '@/ui/Icon';
|
||||
import { Image } from '@/ui/Image';
|
||||
@@ -88,7 +88,7 @@ export function DriverEntryRow({
|
||||
justifyContent="center"
|
||||
fontSize="0.625rem"
|
||||
>
|
||||
{CountryFlagDisplay.fromCountryCode(country).toString()}
|
||||
{CountryFlagFormatter.fromCountryCode(country).toString()}
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
|
||||
|
||||
import { mediaConfig } from '@/lib/config/mediaConfig';
|
||||
import { CountryFlagDisplay } from '@/lib/display-objects/CountryFlagDisplay';
|
||||
import { CountryFlagFormatter } from '@/lib/formatters/CountryFlagFormatter';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { Icon } from '@/ui/Icon';
|
||||
import { Image } from '@/ui/Image';
|
||||
import { Link } from '@/ui/Link';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Surface } from '@/ui/Surface';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Icon } from '@/ui/Icon';
|
||||
import { Calendar, Clock, ExternalLink, Globe, Star, Trophy, UserPlus } from 'lucide-react';
|
||||
|
||||
interface ProfileHeroProps {
|
||||
@@ -93,7 +93,7 @@ export function ProfileHero({
|
||||
<Stack direction="row" align="center" gap={3} wrap mb={2}>
|
||||
<Heading level={1}>{driver.name}</Heading>
|
||||
<Text size="4xl" aria-label={`Country: ${driver.country}`}>
|
||||
{CountryFlagDisplay.fromCountryCode(driver.country).toString()}
|
||||
{CountryFlagFormatter.fromCountryCode(driver.country).toString()}
|
||||
</Text>
|
||||
</Stack>
|
||||
|
||||
|
||||
@@ -11,52 +11,41 @@ import { Input } from '@/ui/Input';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Text } from '@/ui/Text';
|
||||
import {
|
||||
Activity,
|
||||
AlertTriangle,
|
||||
Bug,
|
||||
ChevronDown,
|
||||
Clock,
|
||||
Copy,
|
||||
Cpu,
|
||||
Download,
|
||||
FileText,
|
||||
Globe,
|
||||
RefreshCw,
|
||||
Search,
|
||||
Terminal,
|
||||
Trash2,
|
||||
Zap
|
||||
Activity,
|
||||
AlertTriangle,
|
||||
Bug,
|
||||
ChevronDown,
|
||||
Clock,
|
||||
Copy,
|
||||
Cpu,
|
||||
Download,
|
||||
FileText,
|
||||
Globe,
|
||||
RefreshCw,
|
||||
Search,
|
||||
Terminal,
|
||||
Trash2,
|
||||
Zap
|
||||
} from 'lucide-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
import { DurationDisplay } from '@/lib/display-objects/DurationDisplay';
|
||||
import { MemoryDisplay } from '@/lib/display-objects/MemoryDisplay';
|
||||
import { PercentDisplay } from '@/lib/display-objects/PercentDisplay';
|
||||
import { TimeDisplay } from '@/lib/display-objects/TimeDisplay';
|
||||
import { DateFormatter } from '@/lib/formatters/DateFormatter';
|
||||
import { DurationFormatter } from '@/lib/formatters/DurationFormatter';
|
||||
import { MemoryFormatter } from '@/lib/formatters/MemoryFormatter';
|
||||
import { PercentFormatter } from '@/lib/formatters/PercentFormatter';
|
||||
|
||||
interface ErrorAnalyticsDashboardProps {
|
||||
/**
|
||||
* Auto-refresh interval in milliseconds
|
||||
*/
|
||||
refreshInterval?: number;
|
||||
/**
|
||||
* Whether to show in production (default: false)
|
||||
*/
|
||||
showInProduction?: boolean;
|
||||
}
|
||||
|
||||
function formatDuration(duration: number): string {
|
||||
return DurationDisplay.formatMs(duration);
|
||||
return DurationFormatter.formatMs(duration);
|
||||
}
|
||||
|
||||
function formatPercentage(value: number, total: number): string {
|
||||
if (total === 0) return '0%';
|
||||
return PercentDisplay.format(value / total);
|
||||
return PercentFormatter.format(value / total);
|
||||
}
|
||||
|
||||
function formatMemory(bytes: number): string {
|
||||
return MemoryDisplay.formatMB(bytes);
|
||||
return MemoryFormatter.formatMB(bytes);
|
||||
}
|
||||
|
||||
interface PerformanceWithMemory extends Performance {
|
||||
@@ -327,7 +316,7 @@ export function ErrorAnalyticsDashboard({
|
||||
<Stack display="flex" justifyContent="between" alignItems="start" gap={2} mb={1}>
|
||||
<Text size="xs" font="mono" weight="bold" color="text-red-400" truncate>{error.type}</Text>
|
||||
<Text size="xs" color="text-gray-500" fontSize="10px">
|
||||
{DateDisplay.formatTime(error.timestamp)}
|
||||
{DateFormatter.formatTime(error.timestamp)}
|
||||
</Text>
|
||||
</Stack>
|
||||
<Text size="xs" color="text-gray-300" block mb={1}>{error.message}</Text>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
'use client';
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { TimeFormatter } from '@/lib/formatters/TimeFormatter';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { FeedItem } from '@/ui/FeedItem';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { TimeDisplay } from '@/lib/display-objects/TimeDisplay';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
interface FeedItemData {
|
||||
id: string;
|
||||
@@ -50,7 +50,7 @@ export function FeedItemCard({ item }: FeedItemCardProps) {
|
||||
name: actor?.name || 'Unknown',
|
||||
avatar: actor?.avatarUrl
|
||||
}}
|
||||
timestamp={TimeDisplay.timeAgo(item.timestamp)}
|
||||
timestamp={TimeFormatter.timeAgo(item.timestamp)}
|
||||
content={
|
||||
<Stack gap={2}>
|
||||
<Text weight="bold" variant="high">{item.headline}</Text>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { FeedList } from '@/components/feed/FeedList';
|
||||
import { LatestResultsSidebar } from '@/components/races/LatestResultsSidebar';
|
||||
import { UpcomingRacesSidebar } from '@/components/races/UpcomingRacesSidebar';
|
||||
import { DateFormatter } from '@/lib/formatters/DateFormatter';
|
||||
import { Card } from '@/ui/Card';
|
||||
import { Container } from '@/ui/Container';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { Grid } from '@/ui/Grid';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { Section } from '@/ui/Section';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
|
||||
interface FeedItemData {
|
||||
id: string;
|
||||
@@ -49,12 +49,12 @@ export function FeedLayout({
|
||||
}: FeedLayoutProps) {
|
||||
const formattedUpcomingRaces = upcomingRaces.map(r => ({
|
||||
...r,
|
||||
formattedDate: DateDisplay.formatShort(r.scheduledAt),
|
||||
formattedDate: DateFormatter.formatShort(r.scheduledAt),
|
||||
}));
|
||||
|
||||
const formattedLatestResults = latestResults.map(r => ({
|
||||
...r,
|
||||
formattedDate: DateDisplay.formatShort(r.scheduledAt),
|
||||
formattedDate: DateFormatter.formatShort(r.scheduledAt),
|
||||
}));
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { RankBadge } from '@/components/leaderboards/RankBadge';
|
||||
import { RatingDisplay } from '@/lib/display-objects/RatingDisplay';
|
||||
import { SkillLevelDisplay } from '@/lib/display-objects/SkillLevelDisplay';
|
||||
import { RatingFormatter } from '@/lib/formatters/RatingFormatter';
|
||||
import { SkillLevelFormatter } from '@/lib/formatters/SkillLevelFormatter';
|
||||
import { Avatar } from '@/ui/Avatar';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { LeaderboardList } from '@/ui/LeaderboardList';
|
||||
import { LeaderboardPreviewShell } from '@/ui/LeaderboardPreviewShell';
|
||||
import { LeaderboardRow } from '@/ui/LeaderboardRow';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Trophy } from 'lucide-react';
|
||||
|
||||
@@ -69,8 +69,8 @@ export function DriverLeaderboardPreview({
|
||||
</Text>
|
||||
<Group gap={2}>
|
||||
<Text size="xs" variant="low" uppercase weight="bold" letterSpacing="wider">{driver.nationality}</Text>
|
||||
<Text size="xs" weight="bold" color={SkillLevelDisplay.getColor(driver.skillLevel)} uppercase letterSpacing="wider">
|
||||
{SkillLevelDisplay.getLabel(driver.skillLevel)}
|
||||
<Text size="xs" weight="bold" color={SkillLevelFormatter.getColor(driver.skillLevel)} uppercase letterSpacing="wider">
|
||||
{SkillLevelFormatter.getLabel(driver.skillLevel)}
|
||||
</Text>
|
||||
</Group>
|
||||
</Group>
|
||||
@@ -80,7 +80,7 @@ export function DriverLeaderboardPreview({
|
||||
<Group gap={8}>
|
||||
<Group direction="column" align="end" gap={0}>
|
||||
<Text variant="primary" font="mono" weight="bold" block size="md" align="right">
|
||||
{RatingDisplay.format(driver.rating)}
|
||||
{RatingFormatter.format(driver.rating)}
|
||||
</Text>
|
||||
<Text size="xs" variant="low" block uppercase letterSpacing="widest" weight="bold" fontSize="9px" align="right">
|
||||
Rating
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { MedalDisplay } from '@/lib/display-objects/MedalDisplay';
|
||||
import { RatingDisplay } from '@/lib/display-objects/RatingDisplay';
|
||||
import { MedalFormatter } from '@/lib/formatters/MedalFormatter';
|
||||
import { RatingFormatter } from '@/lib/formatters/RatingFormatter';
|
||||
import { Image } from '@/ui/Image';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Text } from '@/ui/Text';
|
||||
@@ -91,8 +91,8 @@ export function LeaderboardPodium({ podium, onDriverClick }: LeaderboardPodiumPr
|
||||
border
|
||||
transform="translateX(-50%)"
|
||||
borderWidth="2px"
|
||||
bg={MedalDisplay.getBg(position)}
|
||||
color={MedalDisplay.getColor(position)}
|
||||
bg={MedalFormatter.getBg(position)}
|
||||
color={MedalFormatter.getColor(position)}
|
||||
shadow="lg"
|
||||
>
|
||||
<Text size="sm" weight="bold">{position}</Text>
|
||||
@@ -122,7 +122,7 @@ export function LeaderboardPodium({ podium, onDriverClick }: LeaderboardPodiumPr
|
||||
block
|
||||
color={isFirst ? 'text-warning-amber' : 'text-primary-blue'}
|
||||
>
|
||||
{RatingDisplay.format(driver.rating)}
|
||||
{RatingFormatter.format(driver.rating)}
|
||||
</Text>
|
||||
|
||||
<Stack direction="row" align="center" gap={3} mt={1}>
|
||||
@@ -155,7 +155,7 @@ export function LeaderboardPodium({ podium, onDriverClick }: LeaderboardPodiumPr
|
||||
<Text
|
||||
weight="bold"
|
||||
size="4xl"
|
||||
color={MedalDisplay.getColor(position)}
|
||||
color={MedalFormatter.getColor(position)}
|
||||
opacity={0.1}
|
||||
fontSize={isFirst ? '5rem' : '3.5rem'}
|
||||
>
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { MedalDisplay } from '@/lib/display-objects/MedalDisplay';
|
||||
import { RankMedal as UiRankMedal, RankMedalProps } from '@/ui/RankMedal';
|
||||
import React from 'react';
|
||||
import { MedalFormatter } from '@/lib/formatters/MedalFormatter';
|
||||
import { RankMedalProps, RankMedal as UiRankMedal } from '@/ui/RankMedal';
|
||||
|
||||
export function RankMedal(props: RankMedalProps) {
|
||||
const variant = MedalDisplay.getVariant(props.rank);
|
||||
const bg = MedalDisplay.getBg(props.rank);
|
||||
const color = MedalDisplay.getColor(props.rank);
|
||||
const variant = MedalFormatter.getVariant(props.rank);
|
||||
const bg = MedalFormatter.getBg(props.rank);
|
||||
const color = MedalFormatter.getColor(props.rank);
|
||||
|
||||
return (
|
||||
<UiRankMedal
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { RatingDisplay } from '@/lib/display-objects/RatingDisplay';
|
||||
import { RatingFormatter } from '@/lib/formatters/RatingFormatter';
|
||||
import { SkillLevelFormatter } from '@/lib/formatters/SkillLevelFormatter';
|
||||
import { Avatar } from '@/ui/Avatar';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { LeaderboardRow } from '@/ui/LeaderboardRow';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { DeltaChip } from './DeltaChip';
|
||||
import { RankBadge } from './RankBadge';
|
||||
import { LeaderboardRow } from '@/ui/LeaderboardRow';
|
||||
import { SkillLevelDisplay } from '@/lib/display-objects/SkillLevelDisplay';
|
||||
import React from 'react';
|
||||
|
||||
interface RankingRowProps {
|
||||
id: string;
|
||||
@@ -65,8 +64,8 @@ export function RankingRow({
|
||||
</Text>
|
||||
<Group gap={2}>
|
||||
<Text size="xs" variant="low" uppercase weight="bold" letterSpacing="wider">{nationality}</Text>
|
||||
<Text size="xs" weight="bold" style={{ color: SkillLevelDisplay.getColor(skillLevel) }} uppercase letterSpacing="wider">
|
||||
{SkillLevelDisplay.getLabel(skillLevel)}
|
||||
<Text size="xs" weight="bold" style={{ color: SkillLevelFormatter.getColor(skillLevel) }} uppercase letterSpacing="wider">
|
||||
{SkillLevelFormatter.getLabel(skillLevel)}
|
||||
</Text>
|
||||
</Group>
|
||||
</Group>
|
||||
@@ -84,7 +83,7 @@ export function RankingRow({
|
||||
</Group>
|
||||
<Group direction="column" align="end" gap={0}>
|
||||
<Text variant="primary" font="mono" weight="bold" block size="md">
|
||||
{RatingDisplay.format(rating)}
|
||||
{RatingFormatter.format(rating)}
|
||||
</Text>
|
||||
<Text size="xs" variant="low" block uppercase letterSpacing="widest" weight="bold">
|
||||
Rating
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import { RatingFormatter } from '@/lib/formatters/RatingFormatter';
|
||||
import { Avatar } from '@/ui/Avatar';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { RatingDisplay } from '@/lib/display-objects/RatingDisplay';
|
||||
import { MedalDisplay } from '@/lib/display-objects/MedalDisplay';
|
||||
import { Surface } from '@/ui/Surface';
|
||||
import React from 'react';
|
||||
|
||||
interface PodiumDriver {
|
||||
id: string;
|
||||
@@ -20,7 +17,7 @@ interface RankingsPodiumProps {
|
||||
onDriverClick?: (id: string) => void;
|
||||
}
|
||||
|
||||
export function RankingsPodium({ podium, onDriverClick }: RankingsPodiumProps) {
|
||||
export function RankingsPodium({ podium }: RankingsPodiumProps) {
|
||||
return (
|
||||
<Group justify="center" align="end" gap={4}>
|
||||
{[1, 0, 2].map((index) => {
|
||||
@@ -57,7 +54,7 @@ export function RankingsPodium({ podium, onDriverClick }: RankingsPodiumProps) {
|
||||
|
||||
<Text weight="bold" variant="high" size={isFirst ? 'md' : 'sm'}>{driver.name}</Text>
|
||||
<Text font="mono" weight="bold" variant={isFirst ? 'warning' : 'primary'}>
|
||||
{RatingDisplay.format(driver.rating)}
|
||||
{RatingFormatter.format(driver.rating)}
|
||||
</Text>
|
||||
</Group>
|
||||
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { routes } from '@/lib/routing/RouteConfig';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { Icon } from '@/ui/Icon';
|
||||
import { DateFormatter } from '@/lib/formatters/DateFormatter';
|
||||
import { Badge } from '@/ui/Badge';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { Icon } from '@/ui/Icon';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Surface } from '@/ui/Surface';
|
||||
import { ChevronDown, ChevronUp, Calendar, CheckCircle, Trophy, Edit, Clock } from 'lucide-react';
|
||||
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Calendar, CheckCircle, ChevronDown, ChevronUp, Clock, Edit, Trophy } from 'lucide-react';
|
||||
import { useState } from 'react';
|
||||
|
||||
interface RaceEvent {
|
||||
id: string;
|
||||
@@ -50,9 +48,6 @@ interface MonthGroup {
|
||||
|
||||
export function EnhancedLeagueSchedulePanel({
|
||||
events,
|
||||
leagueId,
|
||||
currentDriverId,
|
||||
isAdmin,
|
||||
onRegister,
|
||||
onWithdraw,
|
||||
onEdit,
|
||||
@@ -60,7 +55,6 @@ export function EnhancedLeagueSchedulePanel({
|
||||
onRaceDetail,
|
||||
onResultsClick,
|
||||
}: EnhancedLeagueSchedulePanelProps) {
|
||||
const router = useRouter();
|
||||
const [expandedMonths, setExpandedMonths] = useState<Set<string>>(new Set());
|
||||
|
||||
// Group races by month
|
||||
@@ -109,7 +103,7 @@ export function EnhancedLeagueSchedulePanel({
|
||||
};
|
||||
|
||||
const formatTime = (scheduledAt: string) => {
|
||||
return DateDisplay.formatDateTime(scheduledAt);
|
||||
return DateFormatter.formatDateTime(scheduledAt);
|
||||
};
|
||||
|
||||
const groups = groupRacesByMonth();
|
||||
@@ -158,7 +152,7 @@ export function EnhancedLeagueSchedulePanel({
|
||||
{isExpanded && (
|
||||
<Box p={4}>
|
||||
<Stack gap={3}>
|
||||
{group.races.map((race, raceIndex) => (
|
||||
{group.races.map((race) => (
|
||||
<Surface
|
||||
key={race.id}
|
||||
variant="precision"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { ActivityFeedItem } from '@/components/feed/ActivityFeedItem';
|
||||
import { useLeagueRaces } from "@/hooks/league/useLeagueRaces";
|
||||
import { RelativeTimeFormatter } from '@/lib/formatters/RelativeTimeFormatter';
|
||||
import { LeagueActivityService } from '@/lib/services/league/LeagueActivityService';
|
||||
import { RelativeTimeDisplay } from '@/lib/display-objects/RelativeTimeDisplay';
|
||||
import { Icon } from '@/ui/Icon';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { AlertTriangle, Calendar, Flag, Shield, UserMinus, UserPlus } from 'lucide-react';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
@@ -128,7 +128,7 @@ function ActivityItem({ activity }: { activity: LeagueActivity }) {
|
||||
<ActivityFeedItem
|
||||
icon={getIcon()}
|
||||
content={getContent()}
|
||||
timestamp={RelativeTimeDisplay.format(activity.timestamp, new Date())}
|
||||
timestamp={RelativeTimeFormatter.format(activity.timestamp, new Date())}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { DriverIdentity } from '@/ui/DriverIdentity';
|
||||
import { DateFormatter } from '@/lib/formatters/DateFormatter';
|
||||
import { DriverViewModel } from '@/lib/view-models/DriverViewModel';
|
||||
import { Badge } from '@/ui/Badge';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { DriverIdentity } from '@/ui/DriverIdentity';
|
||||
import { TableCell, TableRow } from '@/ui/Table';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
import React, { ReactNode } from 'react';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
interface LeagueMemberRowProps {
|
||||
driver?: DriverViewModel;
|
||||
@@ -84,7 +84,7 @@ export function LeagueMemberRow({
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Text variant="high" size="sm">
|
||||
{DateDisplay.formatShort(joinedAt)}
|
||||
{DateFormatter.formatShort(joinedAt)}
|
||||
</Text>
|
||||
</TableCell>
|
||||
{actions && (
|
||||
|
||||
@@ -1,39 +1,33 @@
|
||||
'use client';
|
||||
|
||||
import {
|
||||
Users,
|
||||
Calendar,
|
||||
Trophy,
|
||||
Award,
|
||||
Rocket,
|
||||
Gamepad2,
|
||||
User,
|
||||
UsersRound,
|
||||
Clock,
|
||||
Flag,
|
||||
Zap,
|
||||
Timer,
|
||||
Check,
|
||||
Globe,
|
||||
Medal,
|
||||
type LucideIcon,
|
||||
} from 'lucide-react';
|
||||
import type { LeagueConfigFormModel } from '@/lib/types/LeagueConfigFormModel';
|
||||
import type { LeagueScoringPresetViewModel } from '@/lib/view-models/LeagueScoringPresetViewModel';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { Icon } from '@/ui/Icon';
|
||||
import { Card } from '@/ui/Card';
|
||||
import { Grid } from '@/ui/Grid';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { Icon } from '@/ui/Icon';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Text } from '@/ui/Text';
|
||||
import {
|
||||
Award,
|
||||
Calendar,
|
||||
Check,
|
||||
Clock,
|
||||
Flag,
|
||||
Gamepad2,
|
||||
Globe,
|
||||
Medal,
|
||||
Rocket,
|
||||
Timer,
|
||||
Trophy,
|
||||
User,
|
||||
Users,
|
||||
UsersRound,
|
||||
Zap,
|
||||
type LucideIcon,
|
||||
} from 'lucide-react';
|
||||
|
||||
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
import { DurationDisplay } from '@/lib/display-objects/DurationDisplay';
|
||||
import { DateFormatter } from '@/lib/formatters/DateFormatter';
|
||||
|
||||
interface LeagueReviewSummaryProps {
|
||||
form: LeagueConfigFormModel;
|
||||
presets: LeagueScoringPresetViewModel[];
|
||||
}
|
||||
|
||||
// Individual review card component
|
||||
function ReviewCard({
|
||||
@@ -142,7 +136,7 @@ export function LeagueReviewSummary({ form, presets }: LeagueReviewSummaryProps)
|
||||
|
||||
const seasonStartLabel =
|
||||
timings.seasonStartDate
|
||||
? DateDisplay.formatShort(timings.seasonStartDate)
|
||||
? DateFormatter.formatShort(timings.seasonStartDate)
|
||||
: null;
|
||||
|
||||
const stewardingLabel = (() => {
|
||||
|
||||
@@ -1,28 +1,27 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { Surface } from '@/ui/Surface';
|
||||
import { Icon } from '@/ui/Icon';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { DateFormatter } from '@/lib/formatters/DateFormatter';
|
||||
import { Badge } from '@/ui/Badge';
|
||||
import {
|
||||
Calendar,
|
||||
Clock,
|
||||
Car,
|
||||
MapPin,
|
||||
Thermometer,
|
||||
Droplets,
|
||||
Wind,
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { Icon } from '@/ui/Icon';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Surface } from '@/ui/Surface';
|
||||
import { Text } from '@/ui/Text';
|
||||
import {
|
||||
Calendar,
|
||||
Car,
|
||||
CheckCircle,
|
||||
Clock,
|
||||
Cloud,
|
||||
X,
|
||||
Droplets,
|
||||
MapPin,
|
||||
Thermometer,
|
||||
Trophy,
|
||||
CheckCircle
|
||||
Wind,
|
||||
X
|
||||
} from 'lucide-react';
|
||||
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
|
||||
interface RaceDetailModalProps {
|
||||
race: {
|
||||
@@ -55,7 +54,7 @@ export function RaceDetailModal({
|
||||
if (!isOpen) return null;
|
||||
|
||||
const formatTime = (scheduledAt: string) => {
|
||||
return DateDisplay.formatDateTime(scheduledAt);
|
||||
return DateFormatter.formatDateTime(scheduledAt);
|
||||
};
|
||||
|
||||
const getStatusBadge = (status: 'scheduled' | 'completed') => {
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
'use client';
|
||||
|
||||
import { CountryFlagDisplay } from '@/lib/display-objects/CountryFlagDisplay';
|
||||
import { Panel } from '@/ui/Panel';
|
||||
import { Input } from '@/ui/Input';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { TextArea } from '@/ui/TextArea';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { CountryFlagFormatter } from '@/lib/formatters/CountryFlagFormatter';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { Input } from '@/ui/Input';
|
||||
import { Panel } from '@/ui/Panel';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { ProfileStat } from '@/ui/ProfileHero';
|
||||
import React from 'react';
|
||||
import { TextArea } from '@/ui/TextArea';
|
||||
|
||||
interface ProfileDetailsPanelProps {
|
||||
driver: {
|
||||
@@ -50,7 +46,7 @@ export function ProfileDetailsPanel({ driver, isEditing, onUpdate }: ProfileDeta
|
||||
<Text size="xs" variant="low" weight="bold" uppercase block>Nationality</Text>
|
||||
<Group gap={2}>
|
||||
<Text size="xl">
|
||||
{CountryFlagDisplay.fromCountryCode(driver.country).toString()}
|
||||
{CountryFlagFormatter.fromCountryCode(driver.country).toString()}
|
||||
</Text>
|
||||
<Text variant="med">{driver.country}</Text>
|
||||
</Group>
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
'use client';
|
||||
|
||||
import { mediaConfig } from '@/lib/config/mediaConfig';
|
||||
import { CountryFlagDisplay } from '@/lib/display-objects/CountryFlagDisplay';
|
||||
import { CountryFlagFormatter } from '@/lib/formatters/CountryFlagFormatter';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { Image } from '@/ui/Image';
|
||||
import { ProfileHero, ProfileAvatar, ProfileStatsGroup, ProfileStat } from '@/ui/ProfileHero';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { ProfileAvatar, ProfileHero, ProfileStat, ProfileStatsGroup } from '@/ui/ProfileHero';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Calendar, Globe, Star, Trophy, UserPlus } from 'lucide-react';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Calendar, Globe, UserPlus } from 'lucide-react';
|
||||
import React from 'react';
|
||||
|
||||
interface ProfileHeaderProps {
|
||||
@@ -56,7 +56,7 @@ export function ProfileHeader({
|
||||
<Group gap={3}>
|
||||
<Heading level={1}>{driver.name}</Heading>
|
||||
<Text size="2xl" aria-label={`Country: ${driver.country}`}>
|
||||
{CountryFlagDisplay.fromCountryCode(driver.country).toString()}
|
||||
{CountryFlagFormatter.fromCountryCode(driver.country).toString()}
|
||||
</Text>
|
||||
</Group>
|
||||
</Box>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
import { DateFormatter } from '@/lib/formatters/DateFormatter';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { Card, Card as Surface } from '@/ui/Card';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
@@ -64,7 +64,7 @@ export function SponsorshipRequestsPanel({
|
||||
<Text size="xs" color="text-gray-400" block mt={1}>{request.message}</Text>
|
||||
)}
|
||||
<Text size="xs" color="text-gray-500" block mt={2}>
|
||||
{DateDisplay.formatShort(request.createdAtIso)}
|
||||
{DateFormatter.formatShort(request.createdAtIso)}
|
||||
</Text>
|
||||
</Stack>
|
||||
<Stack direction="row" gap={2}>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import { RaceStatusDisplay } from '@/lib/display-objects/RaceStatusDisplay';
|
||||
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
import { DateFormatter } from '@/lib/formatters/DateFormatter';
|
||||
import { RaceStatusFormatter } from '@/lib/formatters/RaceStatusFormatter';
|
||||
import { RaceCard as UiRaceCard } from './RaceCard';
|
||||
|
||||
interface RaceCardProps {
|
||||
@@ -23,11 +22,11 @@ export function RaceCard({ race, onClick }: RaceCardProps) {
|
||||
track={race.track}
|
||||
car={race.car}
|
||||
scheduledAt={race.scheduledAt}
|
||||
scheduledAtLabel={DateDisplay.formatShort(race.scheduledAt)}
|
||||
timeLabel={DateDisplay.formatTime(race.scheduledAt)}
|
||||
scheduledAtLabel={DateFormatter.formatShort(race.scheduledAt)}
|
||||
timeLabel={DateFormatter.formatTime(race.scheduledAt)}
|
||||
status={race.status}
|
||||
statusLabel={RaceStatusDisplay.getLabel(race.status)}
|
||||
statusVariant={RaceStatusDisplay.getVariant(race.status) as any}
|
||||
statusLabel={RaceStatusFormatter.getLabel(race.status)}
|
||||
statusVariant={RaceStatusFormatter.getVariant(race.status) as any}
|
||||
leagueName={race.leagueName}
|
||||
leagueId={race.leagueId}
|
||||
strengthOfField={race.strengthOfField}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
|
||||
import { RaceHero as UiRaceHero } from '@/components/races/RaceHero';
|
||||
import { DateFormatter } from '@/lib/formatters/DateFormatter';
|
||||
import { LucideIcon } from 'lucide-react';
|
||||
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
|
||||
interface RaceHeroProps {
|
||||
track: string;
|
||||
@@ -34,8 +34,8 @@ export function RaceHero(props: RaceHeroProps) {
|
||||
return (
|
||||
<UiRaceHero
|
||||
{...rest}
|
||||
formattedDate={DateDisplay.formatShort(scheduledAt)}
|
||||
formattedTime={DateDisplay.formatTime(scheduledAt)}
|
||||
formattedDate={DateFormatter.formatShort(scheduledAt)}
|
||||
formattedTime={DateFormatter.formatTime(scheduledAt)}
|
||||
statusConfig={mappedConfig}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
|
||||
|
||||
import { routes } from '@/lib/routing/RouteConfig';
|
||||
import { RaceListItem as UiRaceListItem } from '@/components/races/RaceListItem';
|
||||
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
import { StatusDisplay } from '@/lib/display-objects/StatusDisplay';
|
||||
import { DateFormatter } from '@/lib/formatters/DateFormatter';
|
||||
import { StatusFormatter } from '@/lib/formatters/StatusFormatter';
|
||||
import { routes } from '@/lib/routing/RouteConfig';
|
||||
|
||||
interface Race {
|
||||
id: string;
|
||||
@@ -48,11 +48,11 @@ export function RaceListItem({ race, onClick }: RaceListItemProps) {
|
||||
<UiRaceListItem
|
||||
track={race.track}
|
||||
car={race.car}
|
||||
dateLabel={DateDisplay.formatMonthDay(race.scheduledAt).split(' ')[0]}
|
||||
dayLabel={DateDisplay.formatMonthDay(race.scheduledAt).split(' ')[1]}
|
||||
timeLabel={DateDisplay.formatTime(race.scheduledAt)}
|
||||
dateLabel={DateFormatter.formatMonthDay(race.scheduledAt).split(' ')[0]}
|
||||
dayLabel={DateFormatter.formatMonthDay(race.scheduledAt).split(' ')[1]}
|
||||
timeLabel={DateFormatter.formatTime(race.scheduledAt)}
|
||||
status={race.status}
|
||||
statusLabel={StatusDisplay.raceStatus(race.status)}
|
||||
statusLabel={StatusFormatter.raceStatus(race.status)}
|
||||
statusVariant={config.variant}
|
||||
statusIconName={config.iconName}
|
||||
leagueName={race.leagueName}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
|
||||
import { DateFormatter } from '@/lib/formatters/DateFormatter';
|
||||
import { RaceResultViewModel } from '@/lib/view-models/RaceResultViewModel';
|
||||
import { RaceResultCard as UiRaceResultCard } from './RaceResultCard';
|
||||
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
|
||||
interface RaceResultCardProps {
|
||||
race: {
|
||||
@@ -29,7 +29,7 @@ export function RaceResultCard({
|
||||
raceId={race.id}
|
||||
track={race.track}
|
||||
car={race.car}
|
||||
formattedDate={DateDisplay.formatShort(race.scheduledAt)}
|
||||
formattedDate={DateFormatter.formatShort(race.scheduledAt)}
|
||||
position={result.position}
|
||||
positionLabel={result.formattedPosition}
|
||||
startPositionLabel={result.formattedStartPosition}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
'use client';
|
||||
|
||||
import { CountryFlagDisplay } from '@/lib/display-objects/CountryFlagDisplay';
|
||||
import { Image } from '@/ui/Image';
|
||||
import { ResultRow, PositionBadge, ResultPoints } from '@/ui/ResultRow';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { CountryFlagFormatter } from '@/lib/formatters/CountryFlagFormatter';
|
||||
import { Badge } from '@/ui/Badge';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { Image } from '@/ui/Image';
|
||||
import { PositionBadge, ResultPoints, ResultRow } from '@/ui/ResultRow';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Surface } from '@/ui/Surface';
|
||||
import React from 'react';
|
||||
import { Text } from '@/ui/Text';
|
||||
|
||||
interface ResultEntry {
|
||||
position: number;
|
||||
@@ -62,7 +61,7 @@ export function RaceResultRow({ result, points }: RaceResultRowProps) {
|
||||
justifyContent="center"
|
||||
>
|
||||
<Text size="xs" style={{ fontSize: '0.625rem' }}>
|
||||
{CountryFlagDisplay.fromCountryCode(country).toString()}
|
||||
{CountryFlagFormatter.fromCountryCode(country).toString()}
|
||||
</Text>
|
||||
</Surface>
|
||||
</Box>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { mediaConfig } from '@/lib/config/mediaConfig';
|
||||
import { CountryFlagDisplay } from '@/lib/display-objects/CountryFlagDisplay';
|
||||
import { CountryFlagFormatter } from '@/lib/formatters/CountryFlagFormatter';
|
||||
import { routes } from '@/lib/routing/RouteConfig';
|
||||
import { Card, Card as Surface } from '@/ui/Card';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
@@ -68,7 +68,7 @@ export function FriendsPreview({ friends }: FriendsPreviewProps) {
|
||||
/>
|
||||
</Stack>
|
||||
<Text size="sm" color="text-white">{friend.name}</Text>
|
||||
<Text size="lg">{CountryFlagDisplay.fromCountryCode(friend.country).toString()}</Text>
|
||||
<Text size="lg">{CountryFlagFormatter.fromCountryCode(friend.country).toString()}</Text>
|
||||
</Surface>
|
||||
</Link>
|
||||
</Stack>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
'use client';
|
||||
|
||||
import { MinimalEmptyState } from '@/ui/EmptyState';
|
||||
import { TeamRosterItem } from '@/components/teams/TeamRosterItem';
|
||||
import { TeamRosterList } from '@/components/teams/TeamRosterList';
|
||||
import { useTeamRoster } from "@/hooks/team/useTeamRoster";
|
||||
@@ -9,15 +8,16 @@ import { sortMembers } from '@/lib/utilities/roster-utils';
|
||||
import type { DriverViewModel } from '@/lib/view-models/DriverViewModel';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { Card } from '@/ui/Card';
|
||||
import { MinimalEmptyState } from '@/ui/EmptyState';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Select } from '@/ui/Select';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { useMemo, useState } from 'react';
|
||||
|
||||
import { MemberDisplay } from '@/lib/display-objects/MemberDisplay';
|
||||
import { RatingDisplay } from '@/lib/display-objects/RatingDisplay';
|
||||
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
import { DateFormatter } from '@/lib/formatters/DateFormatter';
|
||||
import { MemberFormatter } from '@/lib/formatters/MemberFormatter';
|
||||
import { RatingFormatter } from '@/lib/formatters/RatingFormatter';
|
||||
|
||||
export type TeamRole = 'owner' | 'admin' | 'member';
|
||||
export type TeamMemberRole = 'owner' | 'manager' | 'member';
|
||||
@@ -74,7 +74,7 @@ export function TeamRoster({
|
||||
const teamAverageRatingLabel = useMemo(() => {
|
||||
if (teamMembers.length === 0) return '—';
|
||||
const avg = teamMembers.reduce((sum: number, m: { rating?: number | null }) => sum + (m.rating || 0), 0) / teamMembers.length;
|
||||
return RatingDisplay.format(avg);
|
||||
return RatingFormatter.format(avg);
|
||||
}, [teamMembers]);
|
||||
|
||||
if (loading) {
|
||||
@@ -93,7 +93,7 @@ export function TeamRoster({
|
||||
<Stack>
|
||||
<Heading level={3}>Team Roster</Heading>
|
||||
<Text size="sm" color="text-gray-400" block mt={1}>
|
||||
{MemberDisplay.formatCount(memberships.length)} • Avg Rating:{' '}
|
||||
{MemberFormatter.formatCount(memberships.length)} • Avg Rating:{' '}
|
||||
<Text color="text-primary-blue" weight="medium">{teamAverageRatingLabel}</Text>
|
||||
</Text>
|
||||
</Stack>
|
||||
@@ -129,8 +129,8 @@ export function TeamRoster({
|
||||
driver={driver as DriverViewModel}
|
||||
href={`${routes.driver.detail(driver.id)}?from=team&teamId=${teamId}`}
|
||||
roleLabel={getRoleLabel(role)}
|
||||
joinedAtLabel={DateDisplay.formatShort(joinedAt)}
|
||||
ratingLabel={RatingDisplay.format(rating)}
|
||||
joinedAtLabel={DateFormatter.formatShort(joinedAt)}
|
||||
ratingLabel={RatingFormatter.format(rating)}
|
||||
overallRankLabel={overallRank !== null ? `#${overallRank}` : null}
|
||||
actions={canManageMembership ? (
|
||||
<>
|
||||
|
||||
Reference in New Issue
Block a user