Files
flxn-app/src/features/tournaments/components/podium.tsx
T
kyle 0a7b5fa00f
CI/CD Pipeline / Build and Push PocketBase Docker Image (push) Successful in 8s
CI/CD Pipeline / i18n Catalog Check (push) Failing after 10s
CI/CD Pipeline / Build and Push App Docker Image (push) Skipped
CI/CD Pipeline / Deploy to Kubernetes (push) Skipped
i18n
2026-08-08 15:29:40 -07:00

151 lines
4.5 KiB
TypeScript

import { Stack, Group, Text, ThemeIcon } from "@mantine/core";
import { CrownIcon, MedalIcon } from "@phosphor-icons/react";
import { TeamInfo } from "@/features/teams/types";
import { Tournament } from "../types";
import { msg } from "@lingui/core/macro";
import { useLingui } from "@lingui/react/macro";
import type { MessageDescriptor } from "@lingui/core";
interface PodiumProps {
tournament: Tournament;
}
type PodiumTier = "first" | "second" | "third";
const tierStyles: Record<PodiumTier, React.CSSProperties> = {
first: {
background:
"light-dark(color-mix(in srgb, var(--mantine-color-yellow-4) 10%, var(--mantine-color-white)), color-mix(in srgb, var(--mantine-color-yellow-8) 16%, var(--mantine-color-dark-6)))",
border:
"1px solid light-dark(color-mix(in srgb, var(--mantine-color-yellow-6) 45%, var(--mantine-color-gray-3)), color-mix(in srgb, var(--mantine-color-yellow-6) 35%, var(--mantine-color-dark-4)))",
borderRadius: "var(--mantine-radius-md)",
boxShadow: "var(--mantine-shadow-md)",
},
second: {
background:
"light-dark(color-mix(in srgb, var(--mantine-color-gray-5) 10%, var(--mantine-color-white)), color-mix(in srgb, var(--mantine-color-gray-5) 10%, var(--mantine-color-dark-6)))",
border:
"1px solid light-dark(var(--mantine-color-gray-4), var(--mantine-color-dark-4))",
borderRadius: "var(--mantine-radius-md)",
boxShadow: "var(--mantine-shadow-xs)",
},
third: {
background:
"light-dark(color-mix(in srgb, var(--mantine-color-orange-5) 8%, var(--mantine-color-white)), color-mix(in srgb, var(--mantine-color-orange-9) 14%, var(--mantine-color-dark-6)))",
border:
"1px solid light-dark(color-mix(in srgb, var(--mantine-color-orange-6) 35%, var(--mantine-color-gray-3)), color-mix(in srgb, var(--mantine-color-orange-7) 30%, var(--mantine-color-dark-4)))",
borderRadius: "var(--mantine-radius-md)",
boxShadow: "var(--mantine-shadow-xs)",
},
};
const tierConfig: Record<
PodiumTier,
{
color: string;
label: MessageDescriptor;
labelColor: string;
icon: React.ReactNode;
iconSize: "xl" | "lg";
padding: "md" | "xs";
nameSize: "md" | "sm";
}
> = {
first: {
color: "yellow",
label: msg`Champions`,
labelColor:
"light-dark(var(--mantine-color-yellow-8), var(--mantine-color-yellow-4))",
icon: <CrownIcon size={24} />,
iconSize: "xl",
padding: "md",
nameSize: "md",
},
second: {
color: "gray",
label: msg`2nd place`,
labelColor:
"light-dark(var(--mantine-color-gray-6), var(--mantine-color-gray-4))",
icon: <MedalIcon size={20} />,
iconSize: "lg",
padding: "xs",
nameSize: "sm",
},
third: {
color: "orange",
label: msg`3rd place`,
labelColor:
"light-dark(var(--mantine-color-orange-8), var(--mantine-color-orange-4))",
icon: <MedalIcon size={18} />,
iconSize: "lg",
padding: "xs",
nameSize: "sm",
},
};
const PodiumRow = ({ team, tier }: { team: TeamInfo; tier: PodiumTier }) => {
const { t } = useLingui();
const config = tierConfig[tier];
return (
<Group gap="md" p={config.padding} style={tierStyles[tier]}>
<ThemeIcon
size={config.iconSize}
color={config.color}
variant="light"
radius="xl"
>
{config.icon}
</ThemeIcon>
<Stack gap={4} style={{ flex: 1 }}>
<Text size={config.nameSize} fw={tier === "first" ? 700 : 600}>
{team.name}
</Text>
<Group gap="xs">
{team.players?.map((player) => (
<Text
key={player.id}
size={tier === "first" ? "sm" : "xs"}
c="dimmed"
>
{player.first_name} {player.last_name}
</Text>
))}
</Group>
</Stack>
<Text
size="10px"
fw={700}
tt="uppercase"
style={{
letterSpacing: "0.08em",
alignSelf: "flex-start",
color: config.labelColor,
}}
mt={4}
mr={4}
>
{t(config.label)}
</Text>
</Group>
);
};
export const Podium = ({ tournament }: PodiumProps) => {
if (!tournament.first_place) return;
return (
<Stack gap="xs" px="md">
{tournament.first_place && (
<PodiumRow team={tournament.first_place} tier="first" />
)}
{tournament.second_place && (
<PodiumRow team={tournament.second_place} tier="second" />
)}
{tournament.third_place && (
<PodiumRow team={tournament.third_place} tier="third" />
)}
</Stack>
);
};