"use client"; import { useEffect, useState } from "react"; import type { CrosswordResponse } from "@/lib/types"; type CrosswordPlayerProps = { crossword: CrosswordResponse; labels: { topic: string; difficulty: string; lexicon: string; }; readOnly?: boolean; revealSolution?: boolean; }; type CellState = Record; function cellKey(row: number, col: number) { return `${row}:${col}`; } export function CrosswordPlayer({ crossword, labels, readOnly = false, revealSolution = false, }: CrosswordPlayerProps) { const [activeCell, setActiveCell] = useState(null); const [letters, setLetters] = useState({}); useEffect(() => { const firstCell = crossword.grid.cells.find((cell) => cell.kind === "letter"); if (firstCell) { setActiveCell(cellKey(firstCell.row, firstCell.col)); } }, [crossword]); function writeLetter(row: number, col: number, value: string) { const normalized = value.slice(-1).toUpperCase(); setLetters((current) => ({ ...current, [cellKey(row, col)]: normalized, })); } return (
{labels.topic}: {crossword.generator.topic.join(", ")} {labels.difficulty}: {crossword.generator.difficulty} {labels.lexicon}: {crossword.generator.runtime_lexicon}
{crossword.grid.cells.map((cell) => { const key = cellKey(cell.row, cell.col); if (cell.kind === "block") { return
; } const currentValue = revealSolution ? cell.solution ?? "" : letters[key] ?? ""; const isActive = activeCell === key; const className = [ "grid-cell", isActive && !readOnly ? "grid-cell--active" : "", currentValue ? "grid-cell--filled" : "", revealSolution ? "grid-cell--revealed" : "", ] .filter(Boolean) .join(" "); if (readOnly) { return (
{cell.number ? {cell.number} : null} {currentValue}
); } return ( ); })}
); }