import type { SudokuBoard, SudokuCell } from './types'; export class SudokuRenderer { static renderBoard(container: HTMLElement, board: SudokuBoard): void { const sudokuDiv = document.createElement('div'); sudokuDiv.id = 'sudoku'; sudokuDiv.className = 'sudoku-board'; for (let row = 0; row < 9; row++) { const rowDiv = document.createElement('div'); rowDiv.className = 'sudoku-row'; for (let col = 0; col < 9; col++) { const cell = board[row][col]; const cellDiv = document.createElement('div'); cellDiv.className = 'sudoku-cell'; cellDiv.dataset.row = row.toString(); cellDiv.dataset.col = col.toString(); cellDiv.textContent = cell.value || ''; if (cell.isGiven) { cellDiv.classList.add('given'); } if (cell.hasConflict) { cellDiv.classList.add('conflict'); } if (col === 2 || col === 5) { cellDiv.classList.add('border-right'); } if (row === 2 || row === 5) { cellDiv.classList.add('border-bottom'); } rowDiv.appendChild(cellDiv); } sudokuDiv.appendChild(rowDiv); } container.innerHTML = ''; container.appendChild(sudokuDiv); } static renderEmptyBoard(container: HTMLElement): void { const emptyBoard: SudokuBoard = Array(9).fill(null).map(() => Array(9).fill(null).map(() => ({ value: '', isGiven: false, hasConflict: false })) ); SudokuRenderer.renderBoard(container, emptyBoard); } static updateCell(container: HTMLElement, row: number, col: number, cell: SudokuCell): void { const cellEl = container.querySelector(`.sudoku-cell[data-row="${row}"][data-col="${col}"]`) as HTMLElement; if (!cellEl) return; cellEl.textContent = cell.value || ''; cellEl.classList.toggle('given', cell.isGiven); cellEl.classList.toggle('conflict', cell.hasConflict); } static highlightCursor(container: HTMLElement, row: number, col: number, editMode: boolean): void { const cells = container.querySelectorAll('.sudoku-cell'); cells.forEach(cell => cell.classList.remove('cursor', 'edit-mode')); const cursorCell = container.querySelector(`.sudoku-cell[data-row="${row}"][data-col="${col}"]`) as HTMLElement; if (cursorCell) { cursorCell.classList.add('cursor'); if (editMode) { cursorCell.classList.add('edit-mode'); } } } static flashCell(container: HTMLElement, row: number, col: number, className: string, duration: number = 300): void { const cellEl = container.querySelector(`.sudoku-cell[data-row="${row}"][data-col="${col}"]`) as HTMLElement; if (!cellEl) return; cellEl.classList.add(className); setTimeout(() => cellEl.classList.remove(className), duration); } static highlightConflicts(container: HTMLElement, conflictIndices: number[], duration: number = 2000): void { conflictIndices.forEach((idx) => { const row = Math.floor(idx / 9); const col = idx % 9; const cellEl = container.querySelector(`.sudoku-cell[data-row="${row}"][data-col="${col}"]`) as HTMLElement; if (cellEl) { cellEl.classList.add('conflict'); } }); setTimeout(() => { conflictIndices.forEach((idx) => { const row = Math.floor(idx / 9); const col = idx % 9; const cellEl = container.querySelector(`.sudoku-cell[data-row="${row}"][data-col="${col}"]`) as HTMLElement; if (cellEl) { cellEl.classList.remove('conflict'); } }); }, duration); } }