Initial commit
This commit is contained in:
@@ -0,0 +1,318 @@
|
||||
const API_BASE_URL = 'http://localhost/mon-petit-pari/api';
|
||||
let currentUser = null;
|
||||
let currentMatch = null;
|
||||
|
||||
// Fonction API
|
||||
async function apiCall(endpoint, method = 'GET', data = null) {
|
||||
const options = {
|
||||
method: method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
|
||||
const token = localStorage.getItem('authToken');
|
||||
if (token) {
|
||||
options.headers['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
if (data && (method === 'POST' || method === 'PUT')) {
|
||||
options.body = JSON.stringify(data);
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`${API_BASE_URL}/${endpoint}`, options);
|
||||
const result = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(result.error || 'Erreur serveur');
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('API Error:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Vérification de la session au chargement
|
||||
window.onload = async function() {
|
||||
const token = localStorage.getItem('authToken');
|
||||
if (!token) {
|
||||
window.location.href = 'index.html';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await apiCall('auth.php?action=me');
|
||||
currentUser = result.user;
|
||||
document.getElementById('userName').textContent = currentUser.username;
|
||||
document.getElementById('userPoints').textContent = `${currentUser.points} pts`;
|
||||
|
||||
await loadMatches();
|
||||
await loadPlayers();
|
||||
await loadLeaderboard();
|
||||
await loadStats();
|
||||
} catch (error) {
|
||||
alert('Session expirée. Veuillez vous reconnecter.');
|
||||
localStorage.removeItem('authToken');
|
||||
localStorage.removeItem('currentUser');
|
||||
window.location.href = 'index.html';
|
||||
}
|
||||
};
|
||||
|
||||
function logout() {
|
||||
localStorage.removeItem('authToken');
|
||||
localStorage.removeItem('currentUser');
|
||||
window.location.href = 'index.html';
|
||||
}
|
||||
|
||||
function showSection(sectionId) {
|
||||
document.querySelectorAll('.section').forEach(s => s.classList.remove('active'));
|
||||
document.querySelectorAll('.sidebar li').forEach(l => l.classList.remove('active'));
|
||||
document.getElementById(sectionId).classList.add('active');
|
||||
event.target.classList.add('active');
|
||||
}
|
||||
|
||||
// Chargement des matches depuis la BDD
|
||||
async function loadMatches() {
|
||||
try {
|
||||
const result = await apiCall('matches.php');
|
||||
const container = document.getElementById('matchesList');
|
||||
container.innerHTML = '';
|
||||
|
||||
result.matches.forEach(match => {
|
||||
const matchCard = document.createElement('div');
|
||||
matchCard.className = 'match-card';
|
||||
matchCard.onclick = () => openPredictionModal(match);
|
||||
|
||||
matchCard.innerHTML = `
|
||||
<div class="player-info">
|
||||
<img src="${match.player1.photo}" alt="${match.player1.name}" class="player-photo" onerror="this.src='https://via.placeholder.com/60?text=${encodeURIComponent(match.player1.name.charAt(0))}'">
|
||||
<div class="player-details">
|
||||
<h3>${match.player1.name}</h3>
|
||||
<p>${match.player1.nationality} - ${match.player1.handedness}</p>
|
||||
<p>Ranking: #${match.player1.ranking}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="vs">VS</div>
|
||||
<div class="player-info" style="flex-direction: row-reverse; text-align: right;">
|
||||
<img src="${match.player2.photo}" alt="${match.player2.name}" class="player-photo" onerror="this.src='https://via.placeholder.com/60?text=${encodeURIComponent(match.player2.name.charAt(0))}'">
|
||||
<div class="player-details">
|
||||
<h3>${match.player2.name}</h3>
|
||||
<p>${match.player2.nationality} - ${match.player2.handedness}</p>
|
||||
<p>Ranking: #${match.player2.ranking}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="match-info">
|
||||
<span class="round">${match.round}</span>
|
||||
<p class="date">${new Date(match.date).toLocaleDateString('fr-FR')}</p>
|
||||
<p>${match.court}</p>
|
||||
${match.status === 'completed' ? `<p class="score">${match.score}</p>` : ''}
|
||||
</div>
|
||||
`;
|
||||
|
||||
container.appendChild(matchCard);
|
||||
});
|
||||
} catch (error) {
|
||||
alert('Erreur lors du chargement des matches: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Chargement des joueurs depuis la BDD
|
||||
async function loadPlayers() {
|
||||
try {
|
||||
const result = await apiCall('players.php');
|
||||
const container = document.getElementById('playersGrid');
|
||||
container.innerHTML = '';
|
||||
|
||||
result.players.forEach(player => {
|
||||
const card = document.createElement('div');
|
||||
card.className = 'player-card';
|
||||
|
||||
const strengthsHtml = player.strengths.map(s => `<span class="tag strength">${s}</span>`).join('');
|
||||
const weaknessesHtml = player.weaknesses.map(w => `<span class="tag weakness">${w}</span>`).join('');
|
||||
|
||||
card.innerHTML = `
|
||||
<div class="player-header">
|
||||
<img src="${player.photo_url}" alt="${player.name}" onerror="this.src='https://via.placeholder.com/120?text=${encodeURIComponent(player.name.charAt(0))}'">
|
||||
<h3>${player.name}</h3>
|
||||
<p>#${player.ranking} Mondial</p>
|
||||
</div>
|
||||
<div class="player-body">
|
||||
<div class="stat-row">
|
||||
<span>Âge</span>
|
||||
<strong>${player.age} ans</strong>
|
||||
</div>
|
||||
<div class="stat-row">
|
||||
<span>Nationalité</span>
|
||||
<strong>${player.nationality}</strong>
|
||||
</div>
|
||||
<div class="stat-row">
|
||||
<span>Handedness</span>
|
||||
<strong>${player.handedness}</strong>
|
||||
</div>
|
||||
<div class="stat-row">
|
||||
<span>Terre battue</span>
|
||||
<strong>${(player.clay_win_rate * 100).toFixed(0)}%</strong>
|
||||
</div>
|
||||
<div class="strengths">
|
||||
<h4>Points forts</h4>
|
||||
${strengthsHtml}
|
||||
</div>
|
||||
<div class="weaknesses">
|
||||
<h4>Points faibles</h4>
|
||||
${weaknessesHtml}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
container.appendChild(card);
|
||||
});
|
||||
} catch (error) {
|
||||
alert('Erreur lors du chargement des joueurs: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Modal de pronostic avec analyse depuis la BDD
|
||||
async function openPredictionModal(match) {
|
||||
if (match.status === 'completed') return;
|
||||
|
||||
currentMatch = match;
|
||||
|
||||
try {
|
||||
// Récupérer l'analyse du matchup
|
||||
const result = await apiCall(`players.php?action=matchup&player1=${match.player1.id}&player2=${match.player2.id}`);
|
||||
|
||||
const modal = document.getElementById('predictionModal');
|
||||
const details = document.getElementById('matchDetails');
|
||||
|
||||
details.innerHTML = `
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 2rem; margin-bottom: 2rem;">
|
||||
<div style="text-align: center;">
|
||||
<img src="${match.player1.photo}" style="width: 100px; height: 100px; border-radius: 50%; border: 3px solid #e85d04;" onerror="this.src='https://via.placeholder.com/100?text=${encodeURIComponent(match.player1.name.charAt(0))}'">
|
||||
<h3>${match.player1.name}</h3>
|
||||
<p>${match.player1.nationality}</p>
|
||||
</div>
|
||||
<div style="text-align: center;">
|
||||
<img src="${match.player2.photo}" style="width: 100px; height: 100px; border-radius: 50%; border: 3px solid #e85d04;" onerror="this.src='https://via.placeholder.com/100?text=${encodeURIComponent(match.player2.name.charAt(0))}'">
|
||||
<h3>${match.player2.name}</h3>
|
||||
<p>${match.player2.nationality}</p>
|
||||
</div>
|
||||
</div>
|
||||
<p style="text-align: center; color: #666;">${match.round} - ${match.court}</p>
|
||||
`;
|
||||
|
||||
// Afficher les probabilités
|
||||
document.getElementById('prob1').style.width = `${result.probabilities.player1}%`;
|
||||
document.getElementById('prob2').style.width = `${result.probabilities.player2}%`;
|
||||
document.getElementById('probText1').textContent = `${result.probabilities.player1}%`;
|
||||
document.getElementById('probText2').textContent = `${result.probabilities.player2}%`;
|
||||
|
||||
// Afficher l'analyse
|
||||
const analysisDiv = document.getElementById('matchupAnalysis');
|
||||
analysisDiv.innerHTML = `
|
||||
<h3>Analyse du Matchup</h3>
|
||||
<div class="analysis-grid">
|
||||
<div class="advantage">
|
||||
<h4>Avantages ${match.player1.name}</h4>
|
||||
<ul>
|
||||
${result.analysis.player1_advantages.map(a => `<li>${a}</li>`).join('')}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="advantage">
|
||||
<h4>Avantages ${match.player2.name}</h4>
|
||||
<ul>
|
||||
${result.analysis.player2_advantages.map(a => `<li>${a}</li>`).join('')}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
modal.style.display = 'block';
|
||||
} catch (error) {
|
||||
alert('Erreur lors du chargement de l\'analyse: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
function closePredictionModal() {
|
||||
document.getElementById('predictionModal').style.display = 'none';
|
||||
currentMatch = null;
|
||||
}
|
||||
|
||||
// Faire un pronostic via l'API
|
||||
async function makePrediction(playerNum) {
|
||||
if (!currentMatch || !currentUser) return;
|
||||
|
||||
const winnerId = playerNum === 1 ? currentMatch.player1.id : currentMatch.player2.id;
|
||||
const winnerName = playerNum === 1 ? currentMatch.player1.name : currentMatch.player2.name;
|
||||
|
||||
try {
|
||||
const result = await apiCall('predictions.php', 'POST', {
|
||||
match_id: currentMatch.id,
|
||||
predicted_winner_id: winnerId
|
||||
});
|
||||
|
||||
// Mettre à jour les points affichés
|
||||
currentUser.points += result.points_earned;
|
||||
document.getElementById('userPoints').textContent = `${currentUser.points} pts`;
|
||||
localStorage.setItem('currentUser', JSON.stringify(currentUser));
|
||||
|
||||
alert(`Pronostic enregistré! Vous avez choisi ${winnerName}\n+${result.points_earned} points`);
|
||||
closePredictionModal();
|
||||
await loadStats();
|
||||
await loadLeaderboard();
|
||||
} catch (error) {
|
||||
alert(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Charger le classement depuis la BDD
|
||||
async function loadLeaderboard() {
|
||||
try {
|
||||
const result = await apiCall('predictions.php?action=leaderboard');
|
||||
const tbody = document.getElementById('leaderboardBody');
|
||||
tbody.innerHTML = '';
|
||||
|
||||
result.leaderboard.forEach(user => {
|
||||
const row = document.createElement('tr');
|
||||
const isCurrentUser = user.user_id === currentUser.id;
|
||||
|
||||
row.innerHTML = `
|
||||
<td>${user.rank}</td>
|
||||
<td>${user.username} ${isCurrentUser ? '(Vous)' : ''}</td>
|
||||
<td>${user.points}</td>
|
||||
<td>${user.correct_predictions}</td>
|
||||
`;
|
||||
|
||||
if (isCurrentUser) {
|
||||
row.style.background = '#faf3e0';
|
||||
row.style.fontWeight = 'bold';
|
||||
}
|
||||
|
||||
tbody.appendChild(row);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Erreur leaderboard:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Charger les stats utilisateur depuis la BDD
|
||||
async function loadStats() {
|
||||
try {
|
||||
const result = await apiCall('predictions.php?action=stats');
|
||||
document.getElementById('totalPredictions').textContent = result.stats.total_predictions;
|
||||
document.getElementById('successRate').textContent = `${result.stats.success_rate}%`;
|
||||
document.getElementById('bestStreak').textContent = result.stats.correct_predictions;
|
||||
} catch (error) {
|
||||
console.error('Erreur stats:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Fermer modal en cliquant dehors
|
||||
window.onclick = function(event) {
|
||||
const modal = document.getElementById('predictionModal');
|
||||
if (event.target === modal) {
|
||||
closePredictionModal();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user