ff75c8ce2f
User Profile info, no game before login/register, menu bar --------- Co-authored-by: Lala, Shahd <Shahd.Lala@sybit.de> Co-authored-by: shahdlala66 <shahd.lala66@gmail.com> Reviewed-on: #2
162 lines
4.2 KiB
TypeScript
162 lines
4.2 KiB
TypeScript
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
|
|
import { ChessPieceComponent } from '../chess-piece/chess-piece.component';
|
|
|
|
interface BoardSquare {
|
|
coordinate: string;
|
|
isLight: boolean;
|
|
pieceCode: string | null;
|
|
}
|
|
|
|
type BoardTheme = 'arabian' | 'classic';
|
|
|
|
@Component({
|
|
selector: 'app-chess-board',
|
|
standalone: true,
|
|
imports: [ChessPieceComponent],
|
|
templateUrl: './chess-board.component.html',
|
|
styleUrl: './chess-board.component.css'
|
|
})
|
|
export class ChessBoardComponent implements OnChanges {
|
|
@Input({ required: true }) fen = '';
|
|
@Input() selectedSquare: string | null = null;
|
|
@Input() highlightedSquares: string[] = [];
|
|
@Input() boardTheme: BoardTheme = 'arabian';
|
|
@Output() squareSelected = new EventEmitter<string>();
|
|
|
|
squares: BoardSquare[] = [];
|
|
private highlightedSquareSet = new Set<string>();
|
|
private draggingFromSquare: string | null = null;
|
|
private dragOverSquare: string | null = null;
|
|
private suppressNextClick = false;
|
|
|
|
ngOnChanges(changes: SimpleChanges): void {
|
|
if (changes['fen']) {
|
|
this.squares = this.buildSquares(this.fen);
|
|
}
|
|
|
|
if (changes['highlightedSquares']) {
|
|
this.highlightedSquareSet = new Set(this.highlightedSquares);
|
|
}
|
|
}
|
|
|
|
trackByCoordinate(_index: number, square: BoardSquare): string {
|
|
return square.coordinate;
|
|
}
|
|
|
|
onSquareClick(square: BoardSquare): void {
|
|
if (this.suppressNextClick) {
|
|
this.suppressNextClick = false;
|
|
return;
|
|
}
|
|
|
|
this.squareSelected.emit(square.coordinate);
|
|
}
|
|
|
|
onPieceDragStart(event: DragEvent, square: BoardSquare): void {
|
|
if (!square.pieceCode) {
|
|
event.preventDefault();
|
|
return;
|
|
}
|
|
|
|
this.draggingFromSquare = square.coordinate;
|
|
if (event.dataTransfer) {
|
|
event.dataTransfer.setData('text/plain', square.coordinate);
|
|
event.dataTransfer.effectAllowed = 'move';
|
|
}
|
|
this.squareSelected.emit(square.coordinate);
|
|
}
|
|
|
|
onSquareDragOver(event: DragEvent, square: BoardSquare): void {
|
|
if (!this.draggingFromSquare) {
|
|
return;
|
|
}
|
|
|
|
event.preventDefault();
|
|
if (event.dataTransfer) {
|
|
event.dataTransfer.dropEffect = 'move';
|
|
}
|
|
this.dragOverSquare = square.coordinate === this.draggingFromSquare ? null : square.coordinate;
|
|
}
|
|
|
|
onSquareDrop(event: DragEvent, square: BoardSquare): void {
|
|
event.preventDefault();
|
|
if (!this.draggingFromSquare) {
|
|
return;
|
|
}
|
|
|
|
const fromSquare = this.draggingFromSquare;
|
|
this.clearDragState();
|
|
|
|
if (fromSquare === square.coordinate) {
|
|
return;
|
|
}
|
|
|
|
this.suppressNextClick = true;
|
|
this.squareSelected.emit(square.coordinate);
|
|
}
|
|
|
|
onSquareDragEnd(): void {
|
|
this.clearDragState();
|
|
}
|
|
|
|
isSelected(square: BoardSquare): boolean {
|
|
return this.selectedSquare === square.coordinate;
|
|
}
|
|
|
|
isHighlighted(square: BoardSquare): boolean {
|
|
return this.highlightedSquareSet.has(square.coordinate);
|
|
}
|
|
|
|
isDraggingSource(square: BoardSquare): boolean {
|
|
return this.draggingFromSquare === square.coordinate;
|
|
}
|
|
|
|
isDragOver(square: BoardSquare): boolean {
|
|
return this.dragOverSquare === square.coordinate;
|
|
}
|
|
|
|
private buildSquares(fen: string): BoardSquare[] {
|
|
const placement = fen.split(' ')[0] ?? '';
|
|
const rows = placement.split('/');
|
|
if (rows.length !== 8) {
|
|
return [];
|
|
}
|
|
|
|
const squares: BoardSquare[] = [];
|
|
|
|
rows.forEach((row, rowIndex) => {
|
|
let column = 0;
|
|
|
|
for (const char of row) {
|
|
if (char >= '1' && char <= '8') {
|
|
const emptyCount = Number(char);
|
|
for (let step = 0; step < emptyCount; step += 1) {
|
|
squares.push(this.createSquare(rowIndex, column, null));
|
|
column += 1;
|
|
}
|
|
} else {
|
|
squares.push(this.createSquare(rowIndex, column, char));
|
|
column += 1;
|
|
}
|
|
}
|
|
});
|
|
|
|
return squares;
|
|
}
|
|
|
|
private createSquare(rowIndex: number, column: number, pieceCode: string | null): BoardSquare {
|
|
const file = String.fromCharCode(97 + column);
|
|
const rank = String(8 - rowIndex);
|
|
return {
|
|
coordinate: `${file}${rank}`,
|
|
isLight: (rowIndex + column) % 2 === 0,
|
|
pieceCode
|
|
};
|
|
}
|
|
|
|
private clearDragState(): void {
|
|
this.draggingFromSquare = null;
|
|
this.dragOverSquare = null;
|
|
}
|
|
}
|