423 lines
20 KiB
PHP
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§ion=${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>
|