// src/scripts/index.js
// Modularized logic from original index.astro
// --- State ---
let games = [];
let currentGameId = null;
let playerNameHistory = [];
// --- DOM Selectors ---
const screens = {
'new-game-screen': document.getElementById('new-game-screen'),
'game-list-screen': document.getElementById('game-list-screen'),
'game-detail-screen': document.getElementById('game-detail-screen'),
'game-history-screen': document.getElementById('game-history-screen')
};
// --- Screen Management ---
function showScreen(screenId) {
const currentScreen = document.querySelector('.screen.active');
const newScreen = document.getElementById(screenId);
if (currentScreen) {
currentScreen.classList.remove('active');
currentScreen.classList.add('slide-out');
setTimeout(() => {
currentScreen.classList.remove('slide-out');
newScreen.classList.add('active');
newScreen.classList.add('slide-in');
setTimeout(() => {
newScreen.classList.remove('slide-in');
}, 300);
}, 300);
} else {
newScreen.classList.add('active');
}
if (screenId === 'new-game-screen') {
updateNameHistory();
}
}
// --- Loading Overlay ---
function showLoading() {
document.querySelector('.loading-overlay').style.display = 'block';
document.querySelector('.loading-indicator').style.display = 'block';
}
function hideLoading() {
document.querySelector('.loading-overlay').style.display = 'none';
document.querySelector('.loading-indicator').style.display = 'none';
}
// --- Game Data Management ---
function loadGames() {
const savedGames = localStorage.getItem('bscscore_games');
if (savedGames) {
games = JSON.parse(savedGames);
renderGames();
}
}
function saveGames() {
localStorage.setItem('bscscore_games', JSON.stringify(games));
}
// --- Player Name History ---
function updateNameHistory() {
const allNames = games.flatMap(game => [game.player1, game.player2, game.player3].filter(Boolean));
const nameLastUsed = {};
games.forEach(game => {
if (game.player1) nameLastUsed[game.player1] = Math.max(nameLastUsed[game.player1] || 0, new Date(game.updatedAt).getTime());
if (game.player2) nameLastUsed[game.player2] = Math.max(nameLastUsed[game.player2] || 0, new Date(game.updatedAt).getTime());
if (game.player3) nameLastUsed[game.player3] = Math.max(nameLastUsed[game.player3] || 0, new Date(game.updatedAt).getTime());
});
playerNameHistory = [...new Set(Object.keys(nameLastUsed))].sort((a, b) => nameLastUsed[b] - nameLastUsed[a]);
updateNameSelects();
}
function updateNameSelects() {
const player1Select = document.getElementById('player1-select');
const player2Select = document.getElementById('player2-select');
const player3Select = document.getElementById('player3-select');
while (player1Select.options.length > 1) player1Select.remove(1);
while (player2Select.options.length > 1) player2Select.remove(1);
while (player3Select.options.length > 1) player3Select.remove(1);
playerNameHistory.forEach(name => {
const option1 = new Option(name, name);
const option2 = new Option(name, name);
const option3 = new Option(name, name);
player1Select.add(option1);
player2Select.add(option2);
player3Select.add(option3);
});
}
function updatePlayerInput(playerId) {
const select = document.getElementById(`${playerId}-select`);
const input = document.getElementById(playerId);
if (select.value) {
input.value = select.value;
}
}
// --- Validation Modal ---
function showValidationModal(message) {
const modal = document.getElementById('validation-modal');
const modalMessage = document.getElementById('validation-modal-message');
modalMessage.textContent = message;
modal.classList.add('show');
}
function closeValidationModal() {
const modal = document.getElementById('validation-modal');
modal.classList.remove('show');
}
// --- New Game Creation ---
function createNewGame() {
const player1Name = document.getElementById('player1').value.trim();
const player2Name = document.getElementById('player2').value.trim();
const player3Name = document.getElementById('player3').value.trim();
const gameType = document.getElementById('game-type').value;
const raceTo = document.getElementById('race-to').value;
if (!player1Name || !player2Name) {
showValidationModal('Bitte Namen für beide Spieler eingeben');
return;
}
const newGame = {
id: Date.now(),
player1: player1Name,
player2: player2Name,
player3: player3Name || null,
score1: 0,
score2: 0,
score3: 0,
gameType: gameType,
raceTo: raceTo ? parseInt(raceTo) : null,
status: 'active',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
};
games.push(newGame);
saveGames();
updateNameHistory();
renderGames();
showGameDetail(newGame.id);
}
// --- Score Update ---
function updateScore(gameId, player, change) {
const game = games.find(g => g.id === gameId);
if (!game || game.status === 'completed') return;
if (player === 1) {
game.score1 = Math.max(0, game.score1 + change);
} else if (player === 2) {
game.score2 = Math.max(0, game.score2 + change);
} else if (player === 3) {
game.score3 = Math.max(0, game.score3 + change);
}
game.updatedAt = new Date().toISOString();
if (game.raceTo && (game.score1 >= game.raceTo || game.score2 >= game.raceTo || (game.player3 && game.score3 >= game.raceTo))) {
showGameCompletionModal();
}
saveGames();
renderGames();
if (document.getElementById('game-detail-screen').classList.contains('active')) {
document.getElementById('score1').textContent = game.score1;
document.getElementById('score2').textContent = game.score2;
document.getElementById('score3').textContent = game.score3;
}
}
// --- Game Deletion ---
function deleteGame(gameId) {
const game = games.find(g => g.id === gameId);
if (!game) return;
currentGameId = gameId;
const modal = document.getElementById('modal');
const modalTitle = document.getElementById('modal-title');
const modalMessage = document.getElementById('modal-message');
modalTitle.textContent = 'Spiel löschen';
modalMessage.textContent = `Möchten Sie das Spiel zwischen ${game.player1} und ${game.player2} wirklich löschen?`;
modal.classList.add('show');
}
function closeModal() {
const modal = document.getElementById('modal');
modal.classList.remove('show');
currentGameId = null;
}
function confirmDeleteGame(gameId) {
if (!gameId) return;
showLoading();
setTimeout(() => {
const gameIndex = games.findIndex(g => g.id === gameId);
if (gameIndex !== -1) {
games.splice(gameIndex, 1);
saveGames();
renderGames();
if (currentGameId === gameId) {
showScreen('game-list-screen');
}
}
hideLoading();
closeModal();
}, 500);
}
// --- Game Rendering ---
function renderGames(filter = 'all') {
const gamesContainer = document.getElementById('games-container');
const filteredGames = games
.filter(game => {
if (filter === 'active') return game.status === 'active';
if (filter === 'completed') return game.status === 'completed';
return true;
})
.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
if (filteredGames.length === 0) {
gamesContainer.innerHTML = '
Keine Spiele vorhanden
';
return;
}
gamesContainer.innerHTML = filteredGames.map(game => {
const playerNames = game.player3
? `${game.player1} vs ${game.player2} vs ${game.player3}`
: `${game.player1} vs ${game.player2}`;
const scores = game.player3
? `${game.score1} - ${game.score2} - ${game.score3}`
: `${game.score1} - ${game.score2}`;
return `
${game.gameType}${game.raceTo ? ` | ${game.raceTo}` : ''}
${playerNames}
${scores}
`;
}).join('');
}
// --- Game Detail ---
function showGameDetail(gameId) {
const game = games.find(g => g.id === gameId);
if (!game) return;
currentGameId = gameId;
document.getElementById('game-title').textContent = `${game.gameType}${game.raceTo ? ` | Race to ${game.raceTo}` : ''}`;
document.getElementById('player1-name').textContent = game.player1;
document.getElementById('player2-name').textContent = game.player2;
const player3Score = document.getElementById('player3-score');
if (game.player3) {
document.getElementById('player3-name').textContent = game.player3;
document.getElementById('score3').textContent = game.score3;
player3Score.style.display = 'flex';
} else {
player3Score.style.display = 'none';
}
document.getElementById('score1').textContent = game.score1;
document.getElementById('score2').textContent = game.score2;
const player1Container = document.querySelector('.player-score:first-child');
const player2Container = document.querySelector('.player-score:nth-child(2)');
const player3Container = document.getElementById('player3-score');
player1Container.classList.toggle('franky', game.player1 === 'Fränky');
player2Container.classList.toggle('franky', game.player2 === 'Fränky');
player3Container.classList.toggle('franky', game.player3 === 'Fränky');
const controlButton = document.getElementById('game-control');
if (game.status === 'completed') {
controlButton.textContent = 'Zurück zur Liste';
controlButton.onclick = () => showScreen('game-list-screen');
controlButton.classList.add('disabled');
} else {
controlButton.textContent = 'Spiel beenden';
controlButton.onclick = () => finishGame();
controlButton.classList.remove('disabled');
}
const scoreButtons = document.querySelectorAll('.score-button');
scoreButtons.forEach(button => {
button.disabled = game.status === 'completed';
});
showScreen('game-detail-screen');
}
// --- Game Completion Modal ---
function showGameCompletionModal() {
const game = games.find(g => g.id === currentGameId);
if (!game) return;
const modal = document.getElementById('game-completion-modal');
const finalScores = modal.querySelector('.final-scores');
const winnerAnnouncement = modal.querySelector('.winner-announcement');
let scoreHtml = '';
scoreHtml += `
${game.player1}
${game.score1}
`;
scoreHtml += `
${game.player2}
${game.score2}
`;
if (game.player3) {
scoreHtml += `
${game.player3}
${game.score3}
`;
}
finalScores.innerHTML = scoreHtml;
const scores = [game.score1, game.score2];
if (game.player3) scores.push(game.score3);
const maxScore = Math.max(...scores);
const winners = [];
if (game.score1 === maxScore) winners.push(game.player1);
if (game.score2 === maxScore) winners.push(game.player2);
if (game.player3 && game.score3 === maxScore) winners.push(game.player3);
const winnerText = winners.length > 1
? `Unentschieden zwischen ${winners.join(' und ')}`
: `${winners[0]} hat gewonnen!`;
winnerAnnouncement.innerHTML = `${winnerText}
`;
modal.classList.add('show');
}
function closeGameCompletionModal() {
document.getElementById('game-completion-modal').classList.remove('show');
}
function confirmGameCompletion() {
const game = games.find(g => g.id === currentGameId);
if (!game) return;
game.status = 'completed';
game.updatedAt = new Date().toISOString();
saveGames();
renderGames();
showGameDetail(currentGameId);
closeGameCompletionModal();
}
// --- Game Finish ---
function finishGame() {
const game = games.find(g => g.id === currentGameId);
if (!game) return;
showGameCompletionModal();
}
// --- Filter Games ---
function filterGames(filter) {
document.querySelectorAll('.filter-button').forEach(button => {
button.classList.remove('active');
});
document.querySelector(`.filter-button[onclick=\"filterGames('${filter}')\"]`).classList.add('active');
renderGames(filter);
}
// --- Fullscreen ---
function toggleFullscreen() {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen().catch(err => {
console.log(`Error attempting to enable fullscreen: ${err.message}`);
});
} else {
document.exitFullscreen();
}
}
document.addEventListener('fullscreenchange', () => {
const button = document.getElementById('fullscreen-toggle');
if (document.fullscreenElement) {
button.innerHTML = ``;
} else {
button.innerHTML = ``;
}
});
// --- Event Listeners ---
document.addEventListener('DOMContentLoaded', () => {
loadGames();
// Attach event listeners for navigation, game creation, modals, etc.
document.querySelectorAll('.nav-button').forEach(btn => {
if (btn.textContent.includes('Neues Spiel')) btn.onclick = () => showScreen('new-game-screen');
if (btn.textContent.includes('Abbrechen')) btn.onclick = () => showScreen('game-list-screen');
if (btn.textContent.includes('Zurück zur Liste')) btn.onclick = () => showScreen('game-list-screen');
});
document.querySelectorAll('.filter-button').forEach((btn, idx) => {
if (btn.textContent === 'Alle') btn.onclick = () => filterGames('all');
if (btn.textContent === 'Aktiv') btn.onclick = () => filterGames('active');
if (btn.textContent === 'Abgeschlossen') btn.onclick = () => filterGames('completed');
});
// Attach fullscreen toggle event
const fullscreenBtn = document.getElementById('fullscreen-toggle');
if (fullscreenBtn) fullscreenBtn.addEventListener('click', toggleFullscreen);
// Modal buttons
const modal = document.getElementById('modal');
if (modal) {
modal.querySelector('.close-button').onclick = closeModal;
modal.querySelector('.modal-button.cancel').onclick = closeModal;
modal.querySelector('.modal-button.confirm').onclick = () => confirmDeleteGame(currentGameId);
}
const validationModal = document.getElementById('validation-modal');
if (validationModal) {
validationModal.querySelector('.close-button').onclick = closeValidationModal;
validationModal.querySelector('.modal-button.cancel').onclick = closeValidationModal;
}
const gameCompletionModal = document.getElementById('game-completion-modal');
if (gameCompletionModal) {
gameCompletionModal.querySelector('.btn.btn--warning').onclick = confirmGameCompletion;
gameCompletionModal.querySelector('.btn:not(.btn--warning)').onclick = closeGameCompletionModal;
}
// New game creation
const startGameBtn = document.querySelector('.nav-button');
if (startGameBtn && startGameBtn.textContent.includes('Spiel starten')) {
startGameBtn.onclick = createNewGame;
}
// Player name selects
['player1', 'player2', 'player3'].forEach(pid => {
const select = document.getElementById(`${pid}-select`);
if (select) select.onchange = () => updatePlayerInput(pid);
});
// Score buttons
document.querySelectorAll('.score-button').forEach((btn, idx) => {
btn.onclick = () => {
const player = Math.floor(idx / 2) + 1;
const change = idx % 2 === 0 ? -1 : 1;
updateScore(currentGameId, player, change);
};
});
});
// Initial screen
showScreen('game-list-screen');
window.toggleFullscreen = toggleFullscreen;