This commit is contained in:
Flatlogic Bot 2025-09-24 13:47:38 +00:00
parent d63bd85799
commit e6e98182ba
10 changed files with 938 additions and 22 deletions

View File

@ -1,4 +1,16 @@
<?php
require_once 'db/config.php';
// Fetch existing courses
try {
$pdo = db();
$stmt = $pdo->query("SELECT id, name FROM courses ORDER BY name");
$courses = $stmt->fetchAll();
} catch (PDOException $e) {
$courses = [];
// Silently fail, the JS will handle the empty state
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
@ -36,9 +48,33 @@
<div class="card p-4">
<h1 class="text-center mb-4">Enter Round Score</h1>
<div class="form-check form-switch mb-4 d-flex justify-content-center">
<input class="form-check-input" type="checkbox" id="holesToggle">
<label class="form-check-label ms-2" for="holesToggle">Toggle for 18 Holes (9 by default)</label>
<div class="row mb-3">
<div class="col-md-6">
<label for="playerName" class="form-label">Player Name</label>
<input type="text" class="form-control" id="playerName" required>
</div>
<div class="col-md-6">
<label for="teamName" class="form-label">Team Name (Optional)</label>
<input type="text" class="form-control" id="teamName">
</div>
</div>
<div class="row mb-4">
<div class="col-md-6">
<label for="courseSelect" class="form-label">Select Course</label>
<select class="form-select" id="courseSelect">
<option value="">-- Select a Course --</option>
<?php foreach ($courses as $course): ?>
<option value="<?php echo $course['id']; ?>"><?php echo htmlspecialchars($course['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6 d-flex align-items-end justify-content-center">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="holesToggle">
<label class="form-check-label ms-2" for="holesToggle">Play 18 Holes (9 by default)</label>
</div>
</div>
</div>
<form id="scoreForm">
@ -47,7 +83,9 @@
<thead>
<tr>
<th scope="col">Hole</th>
<th scope="col">Par</th>
<th scope="col">Score</th>
<th scope="col">Vs Par</th>
<th scope="col">Putts</th>
<th scope="col">Penalties</th>
<th scope="col">Sand Lie</th>
@ -68,6 +106,7 @@
<div class="card totals-card bg-light p-3">
<h4 class="text-center">Round Totals</h4>
<div class="row text-center">
<div class="col"><strong>To Par:</strong> <span id="totalToPar">E</span></div>
<div class="col"><strong>Score:</strong> <span id="totalScore">0</span></div>
<div class="col"><strong>Putts:</strong> <span id="totalPutts">0</span></div>
<div class="col"><strong>Penalties:</strong> <span id="totalPenalties">0</span></div>
@ -91,4 +130,4 @@
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
</body>
</html>
</html>

187
admin.php Normal file
View File

@ -0,0 +1,187 @@
<?php
session_start();
require_once 'db/config.php';
// Handle form submission for adding a new course
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_course'])) {
$courseName = trim($_POST['courseName']);
$pars = [];
$isValid = true;
if (empty($courseName)) {
$error = "Course name is required.";
$isValid = false;
}
for ($i = 1; $i <= 18; $i++) {
$par_value = filter_input(INPUT_POST, 'par_hole_' . $i, FILTER_VALIDATE_INT);
if ($par_value === false || $par_value < 1 || $par_value > 7) {
$error = "Invalid par value for hole " . $i . ". Please enter a number between 1 and 7.";
$isValid = false;
break;
}
$pars[] = $par_value;
}
if ($isValid) {
try {
$pdo = db();
$sql = "INSERT INTO courses (name, par_hole_1, par_hole_2, par_hole_3, par_hole_4, par_hole_5, par_hole_6, par_hole_7, par_hole_8, par_hole_9, par_hole_10, par_hole_11, par_hole_12, par_hole_13, par_hole_14, par_hole_15, par_hole_16, par_hole_17, par_hole_18) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute(array_merge([$courseName], $pars));
$_SESSION['success_message'] = "Course '{$courseName}' added successfully!";
header("Location: admin.php");
exit;
} catch (PDOException $e) {
$error = "Database error: " . $e->getMessage();
}
}
}
// Fetch existing courses
try {
$pdo = db();
$stmt = $pdo->query("SELECT id, name FROM courses ORDER BY name");
$courses = $stmt->fetchAll();
} catch (PDOException $e) {
$courses = [];
$error = "Could not fetch courses: " . $e->getMessage();
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Dashboard - Golf Tournament</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap">
<link rel="stylesheet" href="assets/css/custom.css">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand" href="index.php">Golf Tournament</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="index.php">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="add_score.php">Add Score</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="admin.php">Admin</a>
</li>
<li class="nav-item">
<a class="nav-link" href="coach.php">Coach</a>
</li>
<li class="nav-item">
<a class="nav-link" href="results.php">Results</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-5">
<h1 class="text-center mb-4">Admin Dashboard</h1>
<?php if (isset($error)): ?>
<div class="alert alert-danger"><?php echo htmlspecialchars($error); ?></div>
<?php endif; ?>
<?php
if (isset($_SESSION['success_message'])) {
echo '<div class="alert alert-success">' . htmlspecialchars($_SESSION['success_message']) . '</div>';
unset($_SESSION['success_message']);
}
?>
<ul class="nav nav-tabs" id="adminTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="courses-tab" data-bs-toggle="tab" data-bs-target="#courses" type="button" role="tab" aria-controls="courses" aria-selected="true">Manage Courses</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="teams-tab" data-bs-toggle="tab" data-bs-target="#teams" type="button" role="tab" aria-controls="teams" aria-selected="false">Manage Teams</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="players-tab" data-bs-toggle="tab" data-bs-target="#players" type="button" role="tab" aria-controls="players" aria-selected="false">Manage Players</button>
</li>
</ul>
<div class="tab-content" id="adminTabContent">
<!-- Courses Tab -->
<div class="tab-pane fade show active" id="courses" role="tabpanel" aria-labelledby="courses-tab">
<div class="card shadow-sm mt-4">
<div class="card-body">
<h2 class="card-title">Add New Course</h2>
<form method="POST" action="admin.php">
<div class="mb-3">
<label for="courseName" class="form-label">Course Name</label>
<input type="text" class="form-control" id="courseName" name="courseName" placeholder="e.g., Pebble Beach" required>
</div>
<div class="row">
<?php for ($i = 1; $i <= 18; $i++): ?>
<div class="col-md-2 col-sm-4 mb-3">
<label for="par_hole_<?php echo $i; ?>" class="form-label">Hole <?php echo $i; ?> Par</label>
<input type="number" class="form-control" id="par_hole_<?php echo $i; ?>" name="par_hole_<?php echo $i; ?>" min="1" max="7" value="4" required>
</div>
<?php endfor; ?>
</div>
<button type="submit" name="add_course" class="btn btn-primary">Add Course</button>
</form>
</div>
</div>
<div class="card shadow-sm mt-4">
<div class="card-body">
<h2 class="card-title">Existing Courses</h2>
<table class="table table-striped">
<thead>
<tr>
<th>Course Name</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php if (empty($courses)): ?>
<tr><td colspan="2">No courses found.</td></tr>
<?php else: ?>
<?php foreach ($courses as $course): ?>
<tr>
<td><?php echo htmlspecialchars($course['name']); ?></td>
<td><button class="btn btn-sm btn-danger">Delete</button></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- Teams Tab -->
<div class="tab-pane fade" id="teams" role="tabpanel" aria-labelledby="teams-tab">
...
</div>
<!-- Players Tab -->
<div class="tab-pane fade" id="players" role="tabpanel" aria-labelledby="players-tab">
...
</div>
</div>
</div>
<footer class="bg-light text-center text-lg-start mt-5">
<div class="text-center p-3" style="background-color: rgba(0, 0, 0, 0.05);">
© 2025 Golf Tournament
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

30
api/get_course_pars.php Normal file
View File

@ -0,0 +1,30 @@
<?php
header('Content-Type: application/json');
require_once __DIR__ . '/../db/config.php';
if (!isset($_GET['course_id'])) {
echo json_encode(['error' => 'Course ID is required.']);
exit;
}
$courseId = filter_input(INPUT_GET, 'course_id', FILTER_VALIDATE_INT);
if ($courseId === false) {
echo json_encode(['error' => 'Invalid Course ID.']);
exit;
}
try {
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM courses WHERE id = ?");
$stmt->execute([$courseId]);
$course = $stmt->fetch();
if ($course) {
echo json_encode($course);
} else {
echo json_encode(['error' => 'Course not found.']);
}
} catch (PDOException $e) {
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
}

View File

@ -1,16 +1,19 @@
document.addEventListener('DOMContentLoaded', function () {
const holesToggle = document.getElementById('holesToggle');
const scoreTable = document.getElementById('scoreTable');
const form = document.getElementById('scoreForm');
const courseSelect = document.getElementById('courseSelect');
if (!holesToggle || !scoreTable || !form) return;
if (!holesToggle || !scoreTable || !form || !courseSelect) return;
let coursePars = null;
const updateTotal = () => {
let totalScore = 0;
let totalPutts = 0;
let totalPenalties = 0;
let totalSandLies = 0;
let totalToPar = 0;
const holes = holesToggle.checked ? 18 : 9;
@ -24,12 +27,56 @@ document.addEventListener('DOMContentLoaded', function () {
totalPutts += putts;
totalPenalties += penalties;
if (sandLie) totalSandLies++;
if (coursePars && score > 0) {
const par = coursePars[`par_hole_${i}`];
totalToPar += score - par;
}
}
document.getElementById('totalScore').textContent = totalScore;
document.getElementById('totalPutts').textContent = totalPutts;
document.getElementById('totalPenalties').textContent = totalPenalties;
document.getElementById('totalSandLies').textContent = totalSandLies;
const toParElement = document.getElementById('totalToPar');
if (totalToPar > 0) {
toParElement.textContent = `+${totalToPar}`;
toParElement.classList.add('text-danger');
toParElement.classList.remove('text-success');
} else if (totalToPar < 0) {
toParElement.textContent = totalToPar;
toParElement.classList.add('text-success');
toParElement.classList.remove('text-danger');
} else {
toParElement.textContent = 'E';
toParElement.classList.remove('text-danger', 'text-success');
}
};
const updateVsPar = (holeNumber) => {
if (!coursePars) return;
const scoreInput = document.getElementById(`hole${holeNumber}_score`);
const score = parseInt(scoreInput.value) || 0;
const vsParCell = document.getElementById(`hole${holeNumber}_vs_par`);
if (score > 0) {
const par = coursePars[`par_hole_${holeNumber}`];
const diff = score - par;
if (diff > 0) {
vsParCell.textContent = `+${diff}`;
vsParCell.className = 'text-danger fw-bold';
} else if (diff < 0) {
vsParCell.textContent = diff;
vsParCell.className = 'text-success fw-bold';
} else {
vsParCell.textContent = 'E';
vsParCell.className = 'text-muted';
}
} else {
vsParCell.textContent = '-';
vsParCell.className = '';
}
};
const renderTable = () => {
@ -37,13 +84,16 @@ document.addEventListener('DOMContentLoaded', function () {
let html = '';
for (let i = 1; i <= 18; i++) {
const hidden = i > holes ? ' style="display: none;"' : '';
const parValue = coursePars ? coursePars[`par_hole_${i}`] : '-';
html += `
<tr id="hole_row_${i}" ${hidden}>
<th scope="row">${i}</th>
<td><input type="number" class="form-control" id="hole${i}_score" min="1"></td>
<td><input type="number" class="form-control" id="hole${i}_putts" min="0"></td>
<td><input type="number" class="form-control" id="hole${i}_penalties" min="0"></td>
<td><div class="form-check form-switch"><input class="form-check-input" type="checkbox" id="hole${i}_sand"></div></td>
<td id="hole${i}_par">${parValue}</td>
<td><input type="number" class="form-control" id="hole${i}_score" min="1" disabled></td>
<td id="hole${i}_vs_par">-</td>
<td><input type="number" class="form-control" id="hole${i}_putts" min="0" disabled></td>
<td><input type="number" class="form-control" id="hole${i}_penalties" min="0" disabled></td>
<td><div class="form-check form-switch"><input class="form-check-input" type="checkbox" id="hole${i}_sand" disabled></div></td>
</tr>
`;
}
@ -52,11 +102,59 @@ document.addEventListener('DOMContentLoaded', function () {
};
const attachInputListeners = () => {
form.querySelectorAll('input').forEach(input => {
form.querySelectorAll('input[type="number"]').forEach(input => {
input.addEventListener('input', () => {
const holeNumber = input.id.match(/\d+/)[0];
updateVsPar(holeNumber);
updateTotal();
});
});
form.querySelectorAll('input[type="checkbox"]').forEach(input => {
input.addEventListener('input', updateTotal);
});
};
const toggleInputs = (disabled) => {
form.querySelectorAll('input').forEach(input => {
if(input.id !== 'holesToggle') {
input.disabled = disabled;
}
});
};
courseSelect.addEventListener('change', async () => {
const courseId = courseSelect.value;
if (courseId) {
try {
const response = await fetch(`api/get_course_pars.php?course_id=${courseId}`);
if(response.ok) {
coursePars = await response.json();
if(coursePars.error) {
console.error(coursePars.error);
coursePars = null;
toggleInputs(true);
} else {
renderTable();
toggleInputs(false);
}
} else {
console.error('Failed to fetch par data');
coursePars = null;
toggleInputs(true);
}
} catch (error) {
console.error('Error fetching par data:', error);
coursePars = null;
toggleInputs(true);
}
} else {
coursePars = null;
renderTable();
toggleInputs(true);
}
updateTotal();
});
holesToggle.addEventListener('change', () => {
const holes = holesToggle.checked ? 18 : 9;
for (let i = 1; i <= 18; i++) {
@ -68,18 +166,63 @@ document.addEventListener('DOMContentLoaded', function () {
updateTotal();
});
form.addEventListener('submit', function(e) {
form.addEventListener('submit', async function(e) {
e.preventDefault();
const successToast = document.getElementById('successToast');
if (successToast) {
const toast = new bootstrap.Toast(successToast);
toast.show();
const playerName = document.getElementById('playerName').value;
if (!playerName) {
alert('Player name is required.');
return;
}
const holes = holesToggle.checked ? 18 : 9;
const scores = {};
for (let i = 1; i <= holes; i++) {
scores[`hole${i}_score`] = parseInt(document.getElementById(`hole${i}_score`).value) || 0;
}
const data = {
playerName: playerName,
teamName: document.getElementById('teamName').value,
courseId: courseSelect.value,
holes: holes,
scores: scores,
totalScore: parseInt(document.getElementById('totalScore').textContent) || 0,
totalToPar: document.getElementById('totalToPar').textContent || 'E',
};
try {
const response = await fetch('submit_score.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
const result = await response.json();
if (response.ok) {
const successToast = document.getElementById('successToast');
if (successToast) {
const toast = new bootstrap.Toast(successToast);
toast.show();
}
form.reset();
courseSelect.value = '';
coursePars = null;
renderTable();
toggleInputs(true);
updateTotal();
} else {
alert(`Error: ${result.error}`);
}
} catch (error) {
console.error('Submission error:', error);
alert('An error occurred while submitting the score.');
}
form.reset();
renderTable();
updateTotal();
});
renderTable();
updateTotal();
});
});

106
coach.php Normal file
View File

@ -0,0 +1,106 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Coach Dashboard - Golf Tournament</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap">
<link rel="stylesheet" href="assets/css/custom.css">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand" href="index.php">Golf Tournament</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="index.php">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="add_score.php">Add Score</a>
</li>
<li class="nav-item">
<a class="nav-link" href="admin.php">Admin</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="coach.php">Coach</a>
</li>
<li class="nav-item">
<a class="nav-link" href="results.php">Results</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-5">
<h1 class="text-center mb-4">Coach's Dashboard</h1>
<div class="card shadow-sm">
<div class="card-body">
<h2 class="card-title">Team: Sharks</h2>
<table class="table table-striped">
<thead>
<tr>
<th>Player</th>
<th>Last Round Score</th>
<th>Handicap</th>
<th>View History</th>
</tr>
</thead>
<tbody>
<tr>
<td>Jane Smith</td>
<td>85</td>
<td>12</td>
<td><a href="#" class="btn btn-sm btn-primary">View Details</a></td>
</tr>
<tr>
<td>Mike Johnson</td>
<td>92</td>
<td>18</td>
<td><a href="#" class="btn btn-sm btn-primary">View Details</a></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card shadow-sm mt-4">
<div class="card-body">
<h2 class="card-title">Team: Bears</h2>
<table class="table table-striped">
<thead>
<tr>
<th>Player</th>
<th>Last Round Score</th>
<th>Handicap</th>
<th>View History</th>
</tr>
</thead>
<tbody>
<tr>
<td>Peter Jones</td>
<td>88</td>
<td>14</td>
<td><a href="#" class="btn btn-sm btn-primary">View Details</a></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<footer class="bg-light text-center text-lg-start mt-5">
<div class="text-center p-3" style="background-color: rgba(0, 0, 0, 0.05);">
© 2025 Golf Tournament
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

68
db/setup.php Normal file
View File

@ -0,0 +1,68 @@
<?php
require_once __DIR__ . '/config.php';
try {
$pdo = db();
$pdo->exec("
CREATE TABLE IF NOT EXISTS courses (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
par_hole_1 INT NOT NULL,
par_hole_2 INT NOT NULL,
par_hole_3 INT NOT NULL,
par_hole_4 INT NOT NULL,
par_hole_5 INT NOT NULL,
par_hole_6 INT NOT NULL,
par_hole_7 INT NOT NULL,
par_hole_8 INT NOT NULL,
par_hole_9 INT NOT NULL,
par_hole_10 INT NOT NULL,
par_hole_11 INT NOT NULL,
par_hole_12 INT NOT NULL,
par_hole_13 INT NOT NULL,
par_hole_14 INT NOT NULL,
par_hole_15 INT NOT NULL,
par_hole_16 INT NOT NULL,
par_hole_17 INT NOT NULL,
par_hole_18 INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
");
echo "Table 'courses' created successfully or already exists.<br>";
$pdo->exec("
CREATE TABLE IF NOT EXISTS scores (
id INT AUTO_INCREMENT PRIMARY KEY,
player_name VARCHAR(255) NOT NULL,
team_name VARCHAR(255),
course_id INT NOT NULL,
holes_played INT NOT NULL DEFAULT 9,
hole_1_score INT,
hole_2_score INT,
hole_3_score INT,
hole_4_score INT,
hole_5_score INT,
hole_6_score INT,
hole_7_score INT,
hole_8_score INT,
hole_9_score INT,
hole_10_score INT,
hole_11_score INT,
hole_12_score INT,
hole_13_score INT,
hole_14_score INT,
hole_15_score INT,
hole_16_score INT,
hole_17_score INT,
hole_18_score INT,
total_score INT,
total_to_par INT,
played_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (course_id) REFERENCES courses(id)
)
");
echo "Table 'scores' created successfully or already exists.<br>";
} catch (PDOException $e) {
die("DB ERROR: " . $e->getMessage());
}

View File

@ -22,9 +22,9 @@
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
<nav class="navbar navbar-expand-lg navbar-dark bg-primary shadow-sm">
<div class="container">
<a class="navbar-brand" href="#">GolfTracker</a>
<a class="navbar-brand" href="index.php">GolfTracker</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
@ -36,6 +36,15 @@
<li class="nav-item">
<a class="nav-link" href="add_score.php">Enter Score</a>
</li>
<li class="nav-item">
<a class="nav-link" href="results.php">Results</a>
</li>
<li class="nav-item">
<a class="nav-link" href="coach.php">Coach</a>
</li>
<li class="nav-item">
<a class="nav-link" href="admin.php">Admin</a>
</li>
</ul>
</div>
</div>
@ -71,6 +80,41 @@
</div>
</section>
<section class="py-5 bg-light">
<div class="container">
<h2 class="text-center mb-4">Interfaces for Every Role</h2>
<div class="row">
<div class="col-md-4">
<div class="card text-center">
<div class="card-body">
<h5 class="card-title">Admin</h5>
<p class="card-text">Manage courses, teams, and players.</p>
<a href="admin.php" class="btn btn-primary">Go to Admin</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-center">
<div class="card-body">
<h5 class="card-title">Coach</h5>
<p class="card-text">View player scores and team progress.</p>
<a href="coach.php" class="btn btn-primary">Go to Coach</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-center">
<div class="card-body">
<h5 class="card-title">Viewer</h5>
<p class="card-text">See live tournament leaderboards.</p>
<a href="results.php" class="btn btn-primary">View Results</a>
</div>
</div>
</div>
</div>
</div>
</section>
<footer class="py-4 bg-light text-center">
<div class="container">
<p class="mb-0">&copy; <?php echo date("Y"); ?> GolfTracker. All Rights Reserved.</p>

97
player.php Normal file
View File

@ -0,0 +1,97 @@
<?php
require_once 'db/config.php';
$playerName = $_GET['player'] ?? null;
if (!$playerName) {
header("Location: results.php");
exit;
}
$rounds = [];
try {
$pdo = db();
$stmt = $pdo->prepare("
SELECT s.*, c.name as course_name
FROM scores s
JOIN courses c ON s.course_id = c.id
WHERE s.player_name = :player_name
ORDER BY s.played_at DESC
");
$stmt->execute([':player_name' => $playerName]);
$rounds = $stmt->fetchAll();
} catch (PDOException $e) {
// Handle DB error
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Player Stats - <?php echo htmlspecialchars($playerName); ?></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">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand" href="index.php">Golf Tournament</a>
<div class="collapse navbar-collapse">
<ul class="navbar-nav ms-auto">
<li class="nav-item"><a class="nav-link" href="index.php">Home</a></li>
<li class="nav-item"><a class="nav-link" href="add_score.php">Add Score</a></li>
<li class="nav-item"><a class="nav-link" href="results.php">Results</a></li>
</ul>
</div>
</div>
</nav>
<div class="container mt-5">
<h1 class="mb-4">Stats for <?php echo htmlspecialchars($playerName); ?></h1>
<?php if (empty($rounds)): ?>
<div class="alert alert-warning">No rounds found for this player.</div>
<?php else: ?>
<?php foreach ($rounds as $round): ?>
<div class="card mb-4">
<div class="card-header">
<h5><?php echo htmlspecialchars($round['course_name']); ?> - <?php echo date("M d, Y", strtotime($round['played_at'])); ?></h5>
</div>
<div class="card-body">
<table class="table table-bordered">
<thead>
<tr>
<th>Hole</th>
<?php for ($i = 1; $i <= $round['holes_played']; $i++): ?>
<th><?php echo $i; ?></th>
<?php endfor; ?>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>Score</td>
<?php for ($i = 1; $i <= $round['holes_played']; $i++): ?>
<td><?php echo $round["hole_{$i}_score"]; ?></td>
<?php endfor; ?>
<td><?php echo $round['total_score']; ?></td>
</tr>
</tbody>
</table>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
<footer class="bg-light text-center text-lg-start mt-5">
<div class="text-center p-3" style="background-color: rgba(0, 0, 0, 0.05);">
© 2025 Golf Tournament
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

146
results.php Normal file
View File

@ -0,0 +1,146 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Live Results - Golf Tournament</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap">
<link rel="stylesheet" href="assets/css/custom.css">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand" href="index.php">Golf Tournament</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="index.php">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="add_score.php">Add Score</a>
</li>
<li class="nav-item">
<a class="nav-link" href="admin.php">Admin</a>
</li>
<li class="nav-item">
<a class="nav-link" href="coach.php">Coach</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="results.php">Results</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-5">
<h1 class="text-center mb-4">Tournament Leaderboard</h1>
<div class="card shadow-sm">
<div class="card-body">
<h2 class="card-title">Individual Standings</h2>
<?php
require_once 'db/config.php';
try {
$pdo = db();
$stmt = $pdo->query("
SELECT player_name, team_name, SUM(total_score) as total_score, SUM(total_to_par) as total_to_par
FROM scores
GROUP BY player_name, team_name
ORDER BY total_to_par ASC
");
$results = $stmt->fetchAll();
} catch (PDOException $e) {
$results = [];
}
?>
<table class="table table-striped">
<thead>
<tr>
<th>Rank</th>
<th>Player</th>
<th>Team</th>
<th>Total Score</th>
<th>To Par</th>
</tr>
</thead>
<tbody>
<?php if (empty($results)): ?>
<tr>
<td colspan="5" class="text-center">No results yet.</td>
</tr>
<?php else: ?>
<?php foreach ($results as $index => $row): ?>
<tr>
<td><?php echo $index + 1; ?></td>
<td><a href="player.php?player=<?php echo urlencode($row['player_name']); ?>"><?php echo htmlspecialchars($row['player_name']); ?></a></td>
<td><?php echo htmlspecialchars($row['team_name']); ?></td>
<td><?php echo $row['total_score']; ?></td>
<td><?php echo ($row['total_to_par'] > 0 ? '+' : '') . $row['total_to_par']; ?></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<div class="card shadow-sm mt-4">
<div class="card-body">
<h2 class="card-title">Team Standings</h2>
<?php
try {
$stmt = $pdo->query("
SELECT team_name, SUM(total_score) as total_score
FROM scores
WHERE team_name IS NOT NULL AND team_name != ''
GROUP BY team_name
ORDER BY total_score ASC
");
$team_results = $stmt->fetchAll();
} catch (PDOException $e) {
$team_results = [];
}
?>
<table class="table table-striped">
<thead>
<tr>
<th>Rank</th>
<th>Team</th>
<th>Total Score</th>
</tr>
</thead>
<tbody>
<?php if (empty($team_results)): ?>
<tr>
<td colspan="3" class="text-center">No team results yet.</td>
</tr>
<?php else: ?>
<?php foreach ($team_results as $index => $row): ?>
<tr>
<td><?php echo $index + 1; ?></td>
<td><?php echo htmlspecialchars($row['team_name']); ?></td>
<td><?php echo $row['total_score']; ?></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<footer class="bg-light text-center text-lg-start mt-5">
<div class="text-center p-3" style="background-color: rgba(0, 0, 0, 0.05);">
© 2025 Golf Tournament
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

56
submit_score.php Normal file
View File

@ -0,0 +1,56 @@
<?php
require_once 'db/config.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['error' => 'Method Not Allowed']);
exit;
}
$data = json_decode(file_get_contents('php://input'), true);
if (!$data) {
http_response_code(400);
echo json_encode(['error' => 'Invalid data']);
exit;
}
$required_fields = ['playerName', 'courseId', 'holes', 'scores'];
foreach ($required_fields as $field) {
if (empty($data[$field])) {
http_response_code(400);
echo json_encode(['error' => "Missing required field: {$field}"]);
exit;
}
}
try {
$pdo = db();
$sql = "INSERT INTO scores (player_name, team_name, course_id, holes_played, total_score, total_to_par";
$params = [
':player_name' => $data['playerName'],
':team_name' => $data['teamName'] ?? null,
':course_id' => $data['courseId'],
':holes_played' => $data['holes'],
':total_score' => $data['totalScore'],
':total_to_par' => $data['totalToPar']
];
for ($i = 1; $i <= $data['holes']; $i++) {
$sql .= ", hole_{$i}_score";
$params[":hole_{$i}_score"] = $data['scores']["hole{$i}_score"] ?? null;
}
$sql .= ") VALUES (" . implode(', ', array_keys($params)) . ")";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
http_response_code(201);
echo json_encode(['success' => 'Score submitted successfully']);
} catch (PDOException $e) {
http_response_code(500);
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
}