styling
This commit is contained in:
@@ -12,6 +12,8 @@ import { endMatch, startMatch } from "@/features/matches/server";
|
||||
import { tournamentKeys } from "@/features/tournaments/queries";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { useSpotifyPlayback } from "@/lib/spotify/hooks";
|
||||
import { getGroupLabel } from "../utils/group-label";
|
||||
import styles from "./styles.module.css";
|
||||
|
||||
interface MatchCardProps {
|
||||
match: Match;
|
||||
@@ -21,6 +23,8 @@ interface MatchCardProps {
|
||||
num_groups: number;
|
||||
advance_per_group: number;
|
||||
};
|
||||
onTap?: (match: Match) => void;
|
||||
selected?: boolean;
|
||||
}
|
||||
|
||||
export const MatchCard: React.FC<MatchCardProps> = ({
|
||||
@@ -28,50 +32,14 @@ export const MatchCard: React.FC<MatchCardProps> = ({
|
||||
orders,
|
||||
showControls,
|
||||
groupConfig,
|
||||
onTap,
|
||||
selected,
|
||||
}) => {
|
||||
const queryClient = useQueryClient();
|
||||
const editSheet = useSheet();
|
||||
const { playTrack, pause } = useSpotifyPlayback();
|
||||
|
||||
const getGroupLabel = useCallback((seed: number | undefined) => {
|
||||
if (!seed || !groupConfig) return undefined;
|
||||
|
||||
const groupNames = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'];
|
||||
const numGroups = groupConfig.num_groups;
|
||||
const advancePerGroup = groupConfig.advance_per_group;
|
||||
|
||||
const totalQualifiedTeams = numGroups * advancePerGroup;
|
||||
const nextPowerOf2 = Math.pow(2, Math.ceil(Math.log2(totalQualifiedTeams)));
|
||||
const wildcardsNeeded = nextPowerOf2 - totalQualifiedTeams;
|
||||
|
||||
if (seed > totalQualifiedTeams && wildcardsNeeded > 0) {
|
||||
const wildcardNumber = seed - totalQualifiedTeams;
|
||||
return `Wildcard ${wildcardNumber}`;
|
||||
}
|
||||
|
||||
const pairIndex = Math.floor((seed - 1) / 2);
|
||||
const isFirstInPair = (seed - 1) % 2 === 0;
|
||||
|
||||
if (isFirstInPair) {
|
||||
const groupIndex = pairIndex % numGroups;
|
||||
const rankIndex = Math.floor(pairIndex / numGroups);
|
||||
|
||||
const rank = rankIndex + 1;
|
||||
const groupName = groupNames[groupIndex] || `${groupIndex + 1}`;
|
||||
const rankSuffix = rank === 1 ? '1st' : rank === 2 ? '2nd' : rank === 3 ? '3rd' : `${rank}th`;
|
||||
|
||||
return `${groupName} ${rankSuffix}`;
|
||||
} else {
|
||||
const groupIndex = (pairIndex + 1) % numGroups;
|
||||
const rankIndex = advancePerGroup - 1 - Math.floor(pairIndex / numGroups);
|
||||
|
||||
const rank = rankIndex + 1;
|
||||
const groupName = groupNames[groupIndex] || `${groupIndex + 1}`;
|
||||
const rankSuffix = rank === 1 ? '1st' : rank === 2 ? '2nd' : rank === 3 ? '3rd' : `${rank}th`;
|
||||
|
||||
return `${groupName} ${rankSuffix}`;
|
||||
}
|
||||
}, [groupConfig]);
|
||||
const canTap = !!(onTap && match.home && match.away);
|
||||
|
||||
const homeSlot = useMemo(
|
||||
() => ({
|
||||
@@ -85,9 +53,9 @@ export const MatchCard: React.FC<MatchCardProps> = ({
|
||||
match.home_cups !== undefined &&
|
||||
match.away_cups !== undefined &&
|
||||
match.home_cups > match.away_cups,
|
||||
groupLabel: !match.home && match.home_seed ? getGroupLabel(match.home_seed) : undefined,
|
||||
groupLabel: !match.home && match.home_seed ? getGroupLabel(match.home_seed, groupConfig) : undefined,
|
||||
}),
|
||||
[match, getGroupLabel]
|
||||
[match, orders, groupConfig]
|
||||
);
|
||||
const awaySlot = useMemo(
|
||||
() => ({
|
||||
@@ -101,9 +69,9 @@ export const MatchCard: React.FC<MatchCardProps> = ({
|
||||
match.away_cups !== undefined &&
|
||||
match.home_cups !== undefined &&
|
||||
match.away_cups > match.home_cups,
|
||||
groupLabel: !match.away && match.away_seed ? getGroupLabel(match.away_seed) : undefined,
|
||||
groupLabel: !match.away && match.away_seed ? getGroupLabel(match.away_seed, groupConfig) : undefined,
|
||||
}),
|
||||
[match, getGroupLabel]
|
||||
[match, orders, groupConfig]
|
||||
);
|
||||
|
||||
const showToolbar = useMemo(
|
||||
@@ -273,10 +241,31 @@ export const MatchCard: React.FC<MatchCardProps> = ({
|
||||
w={showToolbar || showEditButton ? 200 : 220}
|
||||
withBorder
|
||||
pos="relative"
|
||||
className={canTap ? styles["tappable-card"] : undefined}
|
||||
onClick={canTap ? () => onTap!(match) : undefined}
|
||||
role={canTap ? "button" : undefined}
|
||||
tabIndex={canTap ? 0 : undefined}
|
||||
onKeyDown={
|
||||
canTap
|
||||
? (e: React.KeyboardEvent) => {
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
e.preventDefault();
|
||||
onTap!(match);
|
||||
}
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
aria-label={
|
||||
canTap
|
||||
? `Match ${match.order}: ${match.home!.name} vs ${match.away!.name}`
|
||||
: undefined
|
||||
}
|
||||
style={{
|
||||
overflow: "visible",
|
||||
backgroundColor: 'var(--mantine-color-body)',
|
||||
borderColor: 'var(--mantine-color-default-border)',
|
||||
borderColor: selected
|
||||
? 'var(--mantine-primary-color-filled)'
|
||||
: 'var(--mantine-color-default-border)',
|
||||
boxShadow: 'var(--mantine-shadow-sm)',
|
||||
}}
|
||||
data-match-lid={match.lid}
|
||||
@@ -310,7 +299,10 @@ export const MatchCard: React.FC<MatchCardProps> = ({
|
||||
size="sm"
|
||||
variant="subtle"
|
||||
color="gray"
|
||||
onClick={handleSpeakerClick}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleSpeakerClick();
|
||||
}}
|
||||
aria-label="Announce matchup"
|
||||
>
|
||||
<SpeakerHighIcon size={12} />
|
||||
|
||||
Reference in New Issue
Block a user