Files
pdga-rating/views/pages/tour.ejs
T
Samuel Enocsson 2ccb018bdf feat: add async tour system
Players can create tours with selected courses/layouts and a date range.
Others join via a 6-character tour code, play the courses, and report
their total strokes. Live leaderboard with points and +/- par display.

Includes: database schema, model, service, routes, views, and styling.
2026-03-20 07:39:43 +01:00

91 lines
3.4 KiB
Plaintext

<% if (!tour) { %>
<% var body = `
<div class="card-section">
<h3>Tour Not Found</h3>
<p>The tour code is invalid or the tour has been removed.</p>
<a href="/tours" class="btn"><i class="fas fa-arrow-left"></i> Back to Tours</a>
</div>
`; %>
<%- include('../partials/layout', {
title: 'Tour Not Found',
heading: 'Tour Not Found',
activePage: 'tours',
cssFiles: ['tours.css'],
body: body
}) %>
<% } else { %>
<%
var statusBadge = isActive
? '<span class="badge badge-active">Active</span>'
: isFinished
? '<span class="badge badge-finished">Finished</span>'
: '<span class="badge badge-upcoming">Upcoming</span>';
var courseOptionsHtml = '';
courses.forEach(function(c) {
courseOptionsHtml += '<option value="' + c.tour_course_id + '">'
+ c.course_name.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;')
+ ' - '
+ c.layout_name.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;')
+ ' (Par ' + c.par + ')'
+ '</option>';
});
var escapedCode = tour.code.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
var escapedStartDate = tour.start_date.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
var escapedEndDate = tour.end_date.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
%>
<% var body = `
<div class="tour-header">
<div class="tour-info">
<div class="tour-meta">
${statusBadge}
<span class="tour-dates"><i class="fas fa-calendar"></i> ${escapedStartDate} &mdash; ${escapedEndDate}</span>
<span class="tour-code-label"><i class="fas fa-key"></i> ${escapedCode}</span>
</div>
</div>
</div>
<div class="card-section" id="join-section">
<h3>Join This Tour</h3>
<div class="card-section-form">
<input type="text" class="input" id="pdga-number" placeholder="PDGA Number" style="width: 160px;" />
<input type="text" class="input" id="player-name" placeholder="Your Name" style="width: 200px;" />
<button class="btn" onclick="joinTour()">
<i class="fas fa-user-plus"></i> Join
</button>
</div>
</div>
<div class="card-section" id="result-section" style="display: none;">
<h3>Record Result</h3>
<div class="card-section-form">
<select class="input" id="result-course" style="width: 280px;">
<option value="">Select course...</option>
${courseOptionsHtml}
</select>
<input type="number" class="input" id="result-strokes" placeholder="Total strokes" style="width: 140px;" min="1" />
<button class="btn" onclick="recordResult('${escapedCode}')">
<i class="fas fa-save"></i> Save
</button>
</div>
</div>
<div id="leaderboard-container"
hx-get="/partials/tour-leaderboard/${escapedCode}"
hx-trigger="load">
<div class="loading">Loading leaderboard...</div>
</div>
`; %>
<%- include('../partials/layout', {
title: tour.name + ' - PDGA Tours',
heading: tour.name,
activePage: 'tours',
cssFiles: ['tours.css'],
jsFiles: ['tour.js'],
initScript: 'initTour("' + escapedCode + '");',
body: body
}) %>
<% } %>