Promotion #2
@@ -0,0 +1,40 @@
|
|||||||
|
.promotion-overlay {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 100;
|
||||||
|
border-radius: inherit;
|
||||||
|
}
|
||||||
|
.promotion-picker {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
background: white;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 14px;
|
||||||
|
box-shadow: 0 8px 32px rgba(0,0,0,0.35);
|
||||||
|
}
|
||||||
|
.promotion-piece {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 42px;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #fafafa;
|
||||||
|
transition: all 0.15s ease;
|
||||||
|
}
|
||||||
|
.promotion-piece:hover {
|
||||||
|
background: #eff6ff;
|
||||||
|
border-color: #3b82f6;
|
||||||
|
transform: scale(1.08);
|
||||||
|
}
|
||||||
|
.promotion-piece:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
@@ -8,6 +8,8 @@
|
|||||||
@import "../node_modules/chessground/assets/chessground.brown.css";
|
@import "../node_modules/chessground/assets/chessground.brown.css";
|
||||||
@import "../node_modules/chessground/assets/chessground.cburnett.css";
|
@import "../node_modules/chessground/assets/chessground.cburnett.css";
|
||||||
|
|
||||||
|
@import "./_promotion.css";
|
||||||
|
|
||||||
@source "../css";
|
@source "../css";
|
||||||
@source "../js";
|
@source "../js";
|
||||||
@source "../../lib/chesstrainer_web";
|
@source "../../lib/chesstrainer_web";
|
||||||
|
|||||||
@@ -51,27 +51,71 @@ export const ChessBoard = {
|
|||||||
return dests;
|
return dests;
|
||||||
},
|
},
|
||||||
|
|
||||||
handleMove(orig, dest) {
|
// handleMove(orig, dest) {
|
||||||
const { role, color } = this.ground.state.pieces.get(dest);
|
// const { role, color } = this.ground.state.pieces.get(dest);
|
||||||
const destRank = dest.split("").pop()
|
// const destRank = dest.split("").pop()
|
||||||
|
|
||||||
const isPromotion = this.isPromotion(role, destRank)
|
// const isPromotion = this.isPromotion(role, destRank)
|
||||||
|
|
||||||
if (isPromotion) {
|
// if (isPromotion) {
|
||||||
console.log("PROMOTION LOGIC")
|
// this.showPromotionDialog()
|
||||||
this.executeMove(orig, dest, "q");
|
// this.executeMove(orig, dest, "q");
|
||||||
return
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// this.executeMove(orig, dest, "q");
|
||||||
|
// },
|
||||||
|
|
||||||
|
handleMove(orig, dest) {
|
||||||
|
const piece = this.ground.state.pieces.get(dest);
|
||||||
|
const destRank = dest[1];
|
||||||
|
if (piece?.role === 'pawn' && (destRank === '1' || destRank === '8')) {
|
||||||
|
this.showPromotionDialog(orig, dest);
|
||||||
|
return; // don't execute yet — wait for user choice
|
||||||
}
|
}
|
||||||
|
this.executeMove(orig, dest);
|
||||||
this.executeMove(orig, dest, "q");
|
|
||||||
},
|
},
|
||||||
|
|
||||||
isPromotion(piece, rank) {
|
isPromotion(piece, rank) {
|
||||||
return piece === "pawn" && (rank === "1" || rank === "8");
|
return piece === "pawn" && (rank === "1" || rank === "8");
|
||||||
},
|
},
|
||||||
|
|
||||||
showPromotionDialog() {
|
showPromotionDialog(orig, dest) {
|
||||||
console.log("trigger promotion dialog");
|
console.log("trigger promotion dialog");
|
||||||
|
this.pendingPromotion = { orig, dest };
|
||||||
|
const color = this.chess.turn() === 'w' ? 'white' : 'black';
|
||||||
|
const overlay = document.createElement('div');
|
||||||
|
overlay.className = 'promotion-overlay';
|
||||||
|
const picker = document.createElement('div');
|
||||||
|
picker.className = 'promotion-picker';
|
||||||
|
const pieces = [
|
||||||
|
{ type: 'queen', symbol: { white: '♕', black: '♛' } },
|
||||||
|
{ type: 'rook', symbol: { white: '♖', black: '♜' } },
|
||||||
|
{ type: 'bishop', symbol: { white: '♗', black: '♝' } },
|
||||||
|
{ type: 'knight', symbol: { white: '♘', black: '♞' } },
|
||||||
|
];
|
||||||
|
// chess.js promotion codes
|
||||||
|
const code = { queen: 'q', rook: 'r', bishop: 'b', knight: 'n' };
|
||||||
|
pieces.forEach(({ type, symbol }) => {
|
||||||
|
const btn = document.createElement('button');
|
||||||
|
btn.className = 'promotion-piece';
|
||||||
|
btn.textContent = symbol[color];
|
||||||
|
btn.addEventListener('click', () => this.completePromotion(code[type]));
|
||||||
|
picker.appendChild(btn);
|
||||||
|
});
|
||||||
|
overlay.appendChild(picker);
|
||||||
|
const boardContainer = this.el.closest('.shadow-inner');
|
||||||
|
boardContainer.style.position = 'relative';
|
||||||
|
boardContainer.appendChild(overlay);
|
||||||
|
},
|
||||||
|
|
||||||
|
completePromotion(pieceType) {
|
||||||
|
const { orig, dest } = this.pendingPromotion;
|
||||||
|
this.pendingPromotion = null;
|
||||||
|
const picker = this.el.closest('.shadow-inner')
|
||||||
|
?.querySelector('.promotion-overlay');
|
||||||
|
if (picker) picker.remove();
|
||||||
|
this.executeMove(orig, dest, pieceType);
|
||||||
},
|
},
|
||||||
|
|
||||||
executeMove(orig, dest, promotion) {
|
executeMove(orig, dest, promotion) {
|
||||||
|
|||||||
Reference in New Issue
Block a user