159 lines
8.2 KiB
JavaScript
Executable File
159 lines
8.2 KiB
JavaScript
Executable File
import { SCORE_CATEGORIES, ALL_CATEGORIES, calculateTotals, isGameComplete } from './gameLogic.js';
|
|
import { getPlayers, getRecentGames, getHighScores } from './supabase.js';
|
|
|
|
// Funktion för att rendera poängkortet
|
|
export function renderScorecard(gameData, scorecardHead, scorecardBody) {
|
|
const players = gameData.players;
|
|
const scores = gameData.scores;
|
|
const isFinished = gameData.isFinished;
|
|
const currentPlayerId = isFinished ? null : gameData.players[gameData.currentPlayerIndex]?.id;
|
|
|
|
scorecardHead.innerHTML = `
|
|
<tr class="table-header">
|
|
<th class="p-3 text-left w-1/4 min-w-[100px] sm:min-w-[150px] rounded-tl-lg category-col">Kategori</th>
|
|
${players.map(p => `<th class="p-3 text-center min-w-[100px] ${p.id === currentPlayerId ? 'current-player-col' : ''}">${p.name}</th>`).join('')}
|
|
</tr>
|
|
`;
|
|
|
|
const playerTotals = calculateTotals(gameData);
|
|
|
|
let bodyHtml = '';
|
|
|
|
const renderCategoryRow = (cat) => {
|
|
return `<tr>
|
|
<td class="p-3 border-b border-gray-200 dark:border-gray-700 category-col">${cat.name}</td>
|
|
${players.map(p => {
|
|
const score = scores[p.id]?.[cat.id];
|
|
const scoreText = (score === null || score === undefined) ? '' : score;
|
|
const isFilled = (score !== null && score !== undefined);
|
|
const filledClass = isFilled ? 'filled' : '';
|
|
const disabledClass = isFinished ? 'score-cell-disabled' : '';
|
|
const currentColClass = p.id === currentPlayerId ? 'current-player-col' : '';
|
|
|
|
return `<td class="p-1 border-b border-gray-200 dark:border-gray-700 ${currentColClass}">
|
|
<div class="score-cell ${filledClass} ${disabledClass}" data-player-id="${p.id}" data-category-id="${cat.id}">
|
|
${scoreText}
|
|
</div>
|
|
</td>`;
|
|
}).join('')}
|
|
</tr>`;
|
|
};
|
|
|
|
SCORE_CATEGORIES.upper.forEach(cat => bodyHtml += renderCategoryRow(cat));
|
|
|
|
bodyHtml += `
|
|
<tr class="calculated-field bg-gray-100 dark:bg-gray-700"><td class="p-3 border-b border-gray-300 dark:border-gray-600 category-col">Summa</td>${players.map(p => `<td class="p-3 text-center border-b border-gray-300 dark:border-gray-600 ${p.id === currentPlayerId ? 'current-player-col' : ''}">${playerTotals[p.id].upperSum}</td>`).join('')}</tr>
|
|
<tr class="calculated-field bg-gray-100 dark:bg-gray-700"><td class="p-3 border-b border-gray-300 dark:border-gray-600 category-col">Bonus</td>${players.map(p => `<td class="p-3 text-center border-b border-gray-300 dark:border-gray-600 ${p.id === currentPlayerId ? 'current-player-col' : ''}">${playerTotals[p.id].upperBonus}</td>`).join('')}</tr>
|
|
<tr class="calculated-field bg-gray-100 dark:bg-gray-700"><td class="p-3 border-b-2 border-gray-400 dark:border-gray-500 category-col">Övre Summa</td>${players.map(p => `<td class="p-3 text-center border-b-2 border-gray-400 dark:border-gray-500 ${p.id === currentPlayerId ? 'current-player-col' : ''}">${playerTotals[p.id].upperTotal}</td>`).join('')}</tr>
|
|
`;
|
|
|
|
SCORE_CATEGORIES.lower.forEach(cat => bodyHtml += renderCategoryRow(cat));
|
|
|
|
bodyHtml += `<tr class="calculated-field bg-gray-100 dark:bg-gray-700"><td class="p-3 border-b-2 border-gray-400 dark:border-gray-500 category-col">Nedre Summa</td>${players.map(p => `<td class="p-3 text-center border-b-2 border-gray-400 dark:border-gray-500 ${p.id === currentPlayerId ? 'current-player-col' : ''}">${playerTotals[p.id].lowerTotal}</td>`).join('')}</tr>`;
|
|
|
|
if (isFinished) {
|
|
bodyHtml += `<tr class="grand-total bg-indigo-100 dark:bg-indigo-900"><td class="p-3 rounded-bl-lg category-col">Totalsumma</td>${players.map(p => `<td class="p-3 text-center ${p.id === currentPlayerId ? 'current-player-col' : ''}">${playerTotals[p.id].grandTotal}</td>`).join('')}</tr>`;
|
|
}
|
|
|
|
scorecardBody.innerHTML = bodyHtml;
|
|
// Anropa funktionen för att koppla event listeners efter att poängkortet har renderats
|
|
if (typeof attachScorecardEventListeners === 'function') {
|
|
attachScorecardEventListeners();
|
|
}
|
|
}
|
|
|
|
// Funktion för att rendera topplistan för spelare
|
|
export async function renderPlayerLeaderboard() {
|
|
const container = document.getElementById('player-leaderboard');
|
|
if (!container) return;
|
|
|
|
try {
|
|
const players = await getPlayers();
|
|
players.sort((a, b) => (b.wins || 0) - (a.wins || 0));
|
|
|
|
if (players.length === 0) {
|
|
container.innerHTML = '<p class="text-gray-500">Inga spelare har lagts till än.</p>';
|
|
} else {
|
|
let html = '<ul class="space-y-3">';
|
|
players.forEach((p, index) => {
|
|
const medal = index === 0 ? '👑' : '';
|
|
html += `
|
|
<li class="flex items-center justify-between p-3 bg-white dark:bg-gray-700 rounded-lg shadow-sm">
|
|
<span class="font-semibold text-lg text-gray-700 dark:text-gray-200">${index + 1}. ${p.name} ${medal}</span>
|
|
<span class="font-bold text-indigo-600 dark:text-indigo-400">${p.wins || 0} vinster</span>
|
|
</li>
|
|
`;
|
|
});
|
|
html += '</ul>';
|
|
container.innerHTML = html;
|
|
}
|
|
} catch (error) {
|
|
console.error("Error rendering leaderboard:", error);
|
|
container.innerHTML = `<p class="text-red-500">Kunde inte ladda topplistan.</p>`;
|
|
}
|
|
}
|
|
|
|
// Funktion för att rendera topplistan för högsta poäng
|
|
export async function renderHighScores() {
|
|
const container = document.getElementById('high-score-list');
|
|
if (!container) return;
|
|
|
|
try {
|
|
const games = await getHighScores();
|
|
if (games.length === 0) {
|
|
container.innerHTML = '<p class="text-gray-500">Inga avslutade spel än.</p>';
|
|
} else {
|
|
let html = '<ul class="space-y-3 text-left">';
|
|
games.forEach((game, index) => {
|
|
const medal = index === 0 ? '🥇' : (index === 1 ? '🥈' : (index === 2 ? '🥉' : ''));
|
|
html += `
|
|
<li class="p-3 bg-white dark:bg-gray-700 rounded-lg shadow-sm">
|
|
<div class="flex items-center justify-between">
|
|
<span class="font-semibold text-gray-700 dark:text-gray-200">${index + 1}. ${game.winnerName} ${medal}</span>
|
|
<span class="font-bold text-indigo-600 dark:text-indigo-400">${game.winnerScore} p</span>
|
|
</div>
|
|
</li>
|
|
`;
|
|
});
|
|
html += '</ul>';
|
|
container.innerHTML = html;
|
|
}
|
|
} catch (error) {
|
|
console.error("Error rendering high scores:", error);
|
|
container.innerHTML = `<p class="text-red-500">Kunde inte ladda topplistan.</p>`;
|
|
}
|
|
}
|
|
|
|
// Funktion för att rendera de senaste spelen
|
|
export async function renderRecentGames() {
|
|
const container = document.getElementById('recent-games-list');
|
|
if (!container) return;
|
|
|
|
try {
|
|
const games = await getRecentGames();
|
|
if (games.length === 0) {
|
|
container.innerHTML = '<p class="text-gray-500">Inga avslutade spel än.</p>';
|
|
} else {
|
|
let html = '<ul class="space-y-3 text-left">';
|
|
games.forEach(game => {
|
|
const date = new Date(game.finishedAt).toLocaleDateString('sv-SE');
|
|
html += `
|
|
<li class="p-3 bg-white dark:bg-gray-700 rounded-lg shadow-sm">
|
|
<div class="flex items-center justify-between">
|
|
<span class="font-semibold text-gray-700 dark:text-gray-200">${game.winnerName}</span>
|
|
<span class="font-bold text-indigo-600 dark:text-indigo-400">${game.winnerScore} p</span>
|
|
</div>
|
|
<div class="text-sm text-gray-500 dark:text-gray-400 mt-1">${date}</div>
|
|
</li>
|
|
`;
|
|
});
|
|
html += '</ul>';
|
|
container.innerHTML = html;
|
|
}
|
|
} catch (error) {
|
|
console.error("Error rendering recent games:", error);
|
|
container.innerHTML = `<p class="text-red-500">Kunde inte ladda senaste spel.</p>`;
|
|
}
|
|
}
|
|
|