34109-vm/matches.php
2025-09-19 12:49:02 +00:00

423 lines
20 KiB
PHP

<?php require_once './includes/header.php';
$pdo = db();
function render_match_card($match) {
$pdo = db();
$stmt = $pdo->prepare('
SELECT t.name
FROM teams t
JOIN match_teams mt ON t.id = mt.team_id
WHERE mt.match_id = ?
');
$stmt->execute([$match['id']]);
$teams = $stmt->fetchAll(PDO::FETCH_COLUMN);
$match_date = new DateTime($match['match_datetime']);
$formatted_date = $match_date->format('D, M j, Y ');
$formatted_time = $match_date->format('g:i A');
$teams_html = '';
if (count($teams) > 0) {
$teams_html = '<p class="card-text">Teams: ' . htmlspecialchars(implode(', ', $teams)) . '</p>';
}
return '<div class="card" data-id="' . $match['id'] . '">
<div class="card-body">
<h5 class="card-title">' . htmlspecialchars($match['match_type']) . '</h5>
<p class="card-text">' . htmlspecialchars($match['location']) . '</p>
<p class="card-text">' . $formatted_date . ' at ' . $formatted_time . '</p>'
. $teams_html .
'<a href="match_view.php?id=' . $match['id'] . '" class="btn btn-primary">View Details</a>
<button class="btn btn-secondary btn-sm edit-match-btn">Edit</button>
<button class="btn btn-danger btn-sm delete-match-btn">Delete</button>
</div>
</div>';
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Matches</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css">
<style>
.matches-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 1rem;
}
</style>
</head>
<body>
<div class="container mt-4">
<div class="d-flex justify-content-between align-items-center mb-3">
<h2>Matches</h2>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#createMatchModal">
Create Match
</button>
</div>
<section id="upcoming-matches" class="mb-5">
<h3>Upcoming</h3>
<div id="upcoming-grid" class="matches-grid">
<?php
$stmt = $pdo->prepare("SELECT * FROM matches WHERE match_datetime > NOW() ORDER BY match_datetime ASC LIMIT 5");
$stmt->execute();
$upcoming_matches = $stmt->fetchAll();
if (count($upcoming_matches) == 0) {
echo '<p>No upcoming matches.</p>';
} else {
foreach ($upcoming_matches as $match) {
echo render_match_card($match);
}
}
?>
</div>
<div id="load-more-upcoming" class="card placeholder-glow" style="display: none; cursor: pointer;">
<div class="card-body text-center">
<div class="placeholder col-6"></div>
<p class="card-text">Load more</p>
</div>
</div>
</section>
<?php
$stmt = $pdo->prepare("SELECT * FROM matches WHERE match_datetime <= NOW() AND match_datetime >= NOW() - INTERVAL 2 WEEK ORDER BY match_datetime DESC LIMIT 5");
$stmt->execute();
$recent_matches = $stmt->fetchAll();
if (count($recent_matches) > 0):
?>
<section id="recent-matches" class="mb-5">
<h3>Last 2 Weeks</h3>
<div id="recent-grid" class="matches-grid">
<?php
foreach ($recent_matches as $match) {
echo render_match_card($match);
}
?>
</div>
<div id="load-more-recent" class="card placeholder-glow" style="display: none; cursor: pointer;">
<div class="card-body text-center">
<div class="placeholder col-6"></div>
<p class="card-text">Load more</p>
</div>
</div>
</section>
<?php endif; ?>
<?php
$stmt = $pdo->prepare("SELECT * FROM matches WHERE match_datetime < NOW() - INTERVAL 2 WEEK ORDER BY match_datetime DESC LIMIT 5");
$stmt->execute();
$past_matches = $stmt->fetchAll();
if (count($past_matches) > 0):
?>
<section id="past-matches" class="mb-5">
<h3>Past Games</h3>
<div id="past-grid" class="matches-grid">
<?php
foreach ($past_matches as $match) {
echo render_match_card($match);
}
?>
</div>
<div id="load-more-past" class="card placeholder-glow" style="display: none; cursor: pointer;">
<div class="card-body text-center">
<div class="placeholder col-6"></div>
<p class="card-text">Load more</p>
</div>
</div>
</section>
<?php endif; ?>
</div>
<div class="modal fade" id="createMatchModal" tabindex="-1" aria-labelledby="createMatchModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="createMatchModalLabel">Create New Match</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="createMatchForm">
<div class="mb-3">
<label for="match_datetime" class="form-label">Date and Time</label>
<input type="datetime-local" class="form-control" id="match_datetime" name="match_datetime" required>
</div>
<div class="mb-3">
<label for="location" class="form-label">Location</label>
<input type="text" class="form-control" id="location" name="location" required>
</div>
<div class="mb-3">
<label for="match_type" class="form-label">Match Type</label>
<select class="form-select" id="match_type" name="match_type" required>
<option value="Training">Training</option>
<option value="Friendly">Friendly</option>
<option value="Tournament">Tournament</option>
</select>
</div>
<div class="mb-3">
<label for="teams" class="form-label">Teams</label>
<select multiple class="form-control" id="teams" name="teams[]">
<?php
$stmt = $pdo->query('SELECT * FROM teams ORDER BY name');
while ($team = $stmt->fetch()) {
echo '<option value="' . $team['id'] . '">' . htmlspecialchars($team['name']) . '</option>';
}
?>
</select>
</div>
<div class="mb-3">
<label for="new_team" class="form-label">Add New Team</label>
<div class="input-group">
<input type="text" class="form-control" id="new_team" placeholder="New team name">
<button class="btn btn-outline-secondary" type="button" id="add_team_btn">Add Team</button>
</div>
</div>
<button type="submit" class="btn btn-primary">Create Match</button>
</form>
</div>
</div>
</div>
</div>
<div class="modal fade" id="editMatchModal" tabindex="-1" aria-labelledby="editMatchModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editMatchModalLabel">Edit Match</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="editMatchForm">
<input type="hidden" id="edit_match_id" name="match_id">
<div class="mb-3">
<label for="edit_match_datetime" class="form-label">Date and Time</label>
<input type="datetime-local" class="form-control" id="edit_match_datetime" name="match_datetime" required>
</div>
<div class="mb-3">
<label for="edit_location" class="form-label">Location</label>
<input type="text" class="form-control" id="edit_location" name="location" required>
</div>
<div class="mb-3">
<label for="edit_match_type" class="form-label">Match Type</label>
<select class="form-select" id="edit_match_type" name="match_type" required>
<option value="Training">Training</option>
<option value="Friendly">Friendly</option>
<option value="Tournament">Tournament</option>
</select>
</div>
<div class="mb-3">
<label for="edit_teams" class="form-label">Teams</label>
<select multiple class="form-control" id="edit_teams" name="teams[]">
<?php
$stmt = $pdo->query('SELECT * FROM teams ORDER BY name');
while ($team = $stmt->fetch()) {
echo '<option value="' . $team['id'] . '">' . htmlspecialchars($team['name']) . '</option>';
}
?>
</select>
</div>
<div class="mb-3">
<label for="edit_new_team" class="form-label">Add New Team</label>
<div class="input-group">
<input type="text" class="form-control" id="edit_new_team" placeholder="New team name">
<button class="btn btn-outline-secondary" type="button" id="edit_add_team_btn">Add Team</button>
</div>
</div>
<button type="submit" class="btn btn-primary">Save Changes</button>
</form>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
// Create Match
const createMatchForm = document.getElementById('createMatchForm');
createMatchForm.addEventListener('submit', function (e) {
e.preventDefault();
const formData = new FormData(createMatchForm);
fetch('api/matches.php?action=create', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload(); // Easiest way to show the new match
} else {
alert('Error: ' + data.error);
}
});
});
// Add new team
const addTeamBtn = document.getElementById('add_team_btn');
addTeamBtn.addEventListener('click', function() {
const newTeamInput = document.getElementById('new_team');
const newTeamName = newTeamInput.value.trim();
if (newTeamName) {
const teamsSelect = document.getElementById('teams');
// Check if team already exists
let exists = false;
for (let i = 0; i < teamsSelect.options.length; i++) {
if (teamsSelect.options[i].text.toLowerCase() === newTeamName.toLowerCase()) {
exists = true;
break;
}
}
if (!exists) {
const newOption = new Option(newTeamName, newTeamName, true, true); // The new team will be sent as a string, and pre-selected
teamsSelect.add(newOption);
newTeamInput.value = '';
} else {
alert('Team already exists.');
}
}
});
// Load More
function attachLoadMore(buttonId, gridId, section, initial_count) {
const loadMoreBtn = document.getElementById(buttonId);
const grid = document.getElementById(gridId);
let offset = initial_count;
if (initial_count >= 5) {
loadMoreBtn.style.display = 'block';
}
loadMoreBtn.addEventListener('click', function () {
fetch(`api/matches.php?action=load_more&section=${section}&offset=${offset}`)
.then(response => response.json())
.then(data => {
if (data.matches.length > 0) {
data.matches.forEach(matchHTML => {
const card = document.createElement('div');
card.innerHTML = matchHTML;
grid.appendChild(card.firstChild);
});
offset += data.matches.length;
}
if (!data.has_more) {
loadMoreBtn.style.display = 'none';
}
});
});
}
attachLoadMore('load-more-upcoming', 'upcoming-grid', 'upcoming', <?php echo count($upcoming_matches); ?>);
<?php if (isset($recent_matches)): ?>
attachLoadMore('load-more-recent', 'recent-grid', 'recent', <?php echo count($recent_matches); ?>);
<?php endif; ?>
<?php if (isset($past_matches)): ?>
attachLoadMore('load-more-past', 'past-grid', 'past', <?php echo count($past_matches); ?>);
<?php endif; ?>
// Edit and Delete Match
document.querySelector('.container').addEventListener('click', function(e) {
const target = e.target;
if (target.classList.contains('edit-match-btn')) {
const card = target.closest('.card');
const matchId = card.dataset.id;
// Fetch match details and populate the modal
fetch(`api/matches.php?action=get&id=${matchId}`)
.then(response => response.json())
.then(data => {
if (data.success) {
document.getElementById('edit_match_id').value = data.match.id;
document.getElementById('edit_match_datetime').value = data.match.match_datetime.slice(0, 16);
document.getElementById('edit_location').value = data.match.location;
document.getElementById('edit_match_type').value = data.match.match_type;
const teamsSelect = document.getElementById('edit_teams');
for (let i = 0; i < teamsSelect.options.length; i++) {
teamsSelect.options[i].selected = data.match.teams.map(String).includes(teamsSelect.options[i].value);
}
const editModal = new bootstrap.Modal(document.getElementById('editMatchModal'));
editModal.show();
} else {
alert('Error: ' + data.error);
}
});
}
if (target.classList.contains('delete-match-btn')) {
const card = target.closest('.card');
const matchId = card.dataset.id;
if (confirm('Are you sure you want to delete this match?')) {
fetch(`api/matches.php?action=delete&id=${matchId}`, {
method: 'POST' // Using POST for delete to be safe
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert('Error: ' + data.error);
}
});
}
}
});
// Handle Edit Match Form Submission
const editMatchForm = document.getElementById('editMatchForm');
editMatchForm.addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(editMatchForm);
fetch('api/matches.php?action=update', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert('Error: ' + data.error);
}
});
});
// Add new team (in edit modal)
const editAddTeamBtn = document.getElementById('edit_add_team_btn');
editAddTeamBtn.addEventListener('click', function() {
const newTeamInput = document.getElementById('edit_new_team');
const newTeamName = newTeamInput.value.trim();
if (newTeamName) {
const teamsSelect = document.getElementById('edit_teams');
let exists = false;
for (let i = 0; i < teamsSelect.options.length; i++) {
if (teamsSelect.options[i].text.toLowerCase() === newTeamName.toLowerCase()) {
exists = true;
break;
}
}
if (!exists) {
const newOption = new Option(newTeamName, newTeamName, true, true);
teamsSelect.add(newOption);
newTeamInput.value = '';
} else {
alert('Team already exists.');
}
}
});
});
</script>
</body>
</html>