import type { CardColor, Hand } from '../types'; import CardView from './CardView'; import { emit } from '../lib/socket'; const COLOR_ORDER: CardColor[] = ['HEARTS', 'LEAVES', 'ACORNS', 'BELLS']; const VALUE_ORDER = ['C7', 'C8', 'C9', 'C10', 'LOWER', 'UPPER', 'KING', 'ACE']; function groupedByColor(hand: Hand): { color: CardColor; keys: string[] }[] { return COLOR_ORDER .map((color) => ({ color, keys: Object.keys(hand) .filter((k) => hand[k].color === color) .sort((a, b) => VALUE_ORDER.indexOf(hand[a].value) - VALUE_ORDER.indexOf(hand[b].value)), })) .filter((g) => g.keys.length > 0); } interface Props { hand: Hand; myTurn: boolean; isPlayPhase: boolean; playableKeys?: Set; desktop?: boolean; } export default function Hand({ hand, myTurn, isPlayPhase, playableKeys, desktop = false }: Props) { const groups = groupedByColor(hand); if (groups.length === 0) return null; const canPlay = isPlayPhase && myTurn; const cardProps = (key: string) => { const legal = playableKeys === undefined || playableKeys.has(key); const playable = canPlay && legal; // Cards stay light by default; darken only the illegal ones, and only while // it's actually your turn to play. const dimmed = canPlay && !legal; return { card: hand[key], highlight: playable, disabled: dimmed, onClick: playable ? () => emit.playCard(key) : undefined, }; }; return (
Tvoje karty
{desktop ? ( // Desktop has room — keep cards grouped by suit, wrap if needed.
{groups.map(({ color, keys }) => (
{keys.map((key) => ( ))}
))}
) : ( )}
); } /** All cards in a single overlapping row that always fits the mobile width: * small gap when few cards, partial overlap when many. */ function MobileHand({ groups, cardProps, }: { groups: { color: CardColor; keys: string[] }[]; cardProps: (key: string) => { card: Hand[string]; highlight: boolean; disabled: boolean; onClick?: () => void }; }) { const keys = groups.flatMap((g) => g.keys); const n = keys.length; const CARD_W = 60; // matches CardView size "lg" const MAX_ROW = 300; // keep within a small phone's usable width (~360px screens) // Horizontal step between successive cards; 1 ? Math.min(CARD_W + 6, (MAX_ROW - CARD_W) / (n - 1)) : 0; const margin = step - CARD_W; // negative → overlap, positive → gap return (
{keys.map((key, i) => (
))}
); }