Merge remote-tracking branch 'origin/main' into feat/show-excluded-rounds-count-21

This commit is contained in:
Samuel Enocsson
2026-05-25 11:01:53 +02:00
12 changed files with 1048 additions and 315 deletions
+65 -69
View File
@@ -1,71 +1,67 @@
<% if (layouts.length === 0) { %>
<div class="no-layouts">No layouts found. Click the refresh icon to scrape layouts.</div>
<% if (!layouts || layouts.length === 0) { %>
<div class="no-layouts">No layouts found. Click the refresh button to scrape layouts.</div>
<% } else {
var oneYearAgo = new Date();
oneYearAgo.setDate(oneYearAgo.getDate() - 365);
var activeLayouts = [];
var inactiveLayouts = [];
layouts.forEach(function(layout) {
if (layout.last_played) {
var lastPlayedDate = new Date(layout.last_played);
if (lastPlayedDate >= oneYearAgo) {
activeLayouts.push(layout);
} else {
inactiveLayouts.push(layout);
}
} else {
inactiveLayouts.push(layout);
}
});
var oneYearAgo = new Date();
oneYearAgo.setDate(oneYearAgo.getDate() - 365);
var activeLayouts = [];
var inactiveLayouts = [];
layouts.forEach(function(l) {
if (l.last_played && new Date(l.last_played) >= oneYearAgo) {
activeLayouts.push(l);
} else {
inactiveLayouts.push(l);
}
});
var RATING_TIER_HIGH = 970;
var RATING_TIER_MID = 940;
function ratingTier(r) {
if (r == null) return null;
if (r >= RATING_TIER_HIGH) return 'green';
if (r >= RATING_TIER_MID) return 'amber';
return 'orange';
}
%>
<h4>Layouts:</h4>
<% if (activeLayouts.length > 0) { %>
<% activeLayouts.forEach(function(layout) {
var ratingDisplay = layout.mean_rating ?
'<span style="color: var(--green); font-weight: 700; margin-left: 10px;">Rating: ' + layout.mean_rating + '</span>' : '';
var dateDisplay = layout.last_played ?
'<span style="color: var(--text-muted); font-size: 12px; margin-left: 10px;">Last played: ' + new Date(layout.last_played).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' }) + '</span>' : '';
%>
<div class="layout-item">
<div>
<span class="layout-name"><%= layout.name %></span>
<%- dateDisplay %>
</div>
<span class="layout-par">Par <%= layout.par %><%- ratingDisplay %></span>
</div>
<% }); %>
<% } %>
<% if (inactiveLayouts.length > 0) { %>
<div class="inactive-layouts-accordion">
<div class="accordion-header" onclick="toggleAccordion('accordion-<%= courseId %>')">
<span class="accordion-header-text">Inactive Layouts (<%= inactiveLayouts.length %>) - Not played in last year</span>
<span class="accordion-icon" id="accordion-<%= courseId %>-icon">&#9660;</span>
</div>
<div class="accordion-content" id="accordion-<%= courseId %>">
<% inactiveLayouts.forEach(function(layout) {
var ratingDisplay = layout.mean_rating ?
'<span style="color: var(--green); font-weight: 700; margin-left: 10px;">Rating: ' + layout.mean_rating + '</span>' : '';
var dateDisplay = layout.last_played ?
'<span style="color: var(--text-muted); font-size: 12px; margin-left: 10px;">Last played: ' + new Date(layout.last_played).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' }) + '</span>' :
'<span style="color: var(--red); font-size: 12px; margin-left: 10px;">Never played</span>';
%>
<div class="layout-item inactive">
<div>
<span class="layout-name"><%= layout.name %></span>
<%- dateDisplay %>
</div>
<span class="layout-par">Par <%= layout.par %><%- ratingDisplay %></span>
</div>
<% }); %>
</div>
</div>
<% } %>
<% if (activeLayouts.length === 0 && inactiveLayouts.length === 0) { %>
<div class="no-layouts">No layouts found. Click the refresh icon to scrape layouts.</div>
<% } %>
<% } %>
<div class="layouts-header">
<span class="layouts-kicker">LAYOUTS</span>
<span class="layouts-count"><%= activeLayouts.length %> active &middot; <%= inactiveLayouts.length %> inactive</span>
</div>
<ul class="layout-list">
<% activeLayouts.forEach(function(l) { var tier = ratingTier(l.mean_rating); %>
<li class="layout-card layout-card--active">
<div class="layout-info">
<span class="layout-name"><%= l.name %></span>
<span class="layout-last-played">Last played: <%= l.last_played %></span>
</div>
<div class="layout-chips">
<span class="chip chip-par">Par <%= l.par %></span>
<% if (tier) { %><span class="chip chip-rating chip-rating--<%= tier %>">Rating: <%= Math.round(l.mean_rating) %></span><% } %>
</div>
</li>
<% }); %>
</ul>
<% if (inactiveLayouts.length > 0) { %>
<div class="inactive-layouts">
<button class="inactive-toggle" type="button" onclick="toggleInactiveLayouts(this)" aria-expanded="false">
<span>Inactive layouts (<%= inactiveLayouts.length %>) — Not played in last year</span>
<i class="icon-chev fas fa-chevron-down"></i>
</button>
<ul class="layout-list inactive-layouts-body" hidden>
<% inactiveLayouts.forEach(function(l) { %>
<li class="layout-card layout-card--inactive">
<div class="layout-info">
<span class="layout-name"><%= l.name %></span>
<% if (l.last_played) { %>
<span class="layout-last-played">Last played: <%= l.last_played %></span>
<% } else { %>
<span class="layout-never-played">Never played</span>
<% } %>
</div>
<div class="layout-chips">
<span class="chip chip-par">Par <%= l.par %></span>
</div>
</li>
<% }); %>
</ul>
</div>
<% } %>
<% } %>
+47 -45
View File
@@ -1,47 +1,49 @@
<div id="search-results-info" class="search-results-info">
<% if (typeof query !== 'undefined' && query) { %>
Showing <%= courses.length %> of <%= total %> courses
<% } else { %>
Showing all <%= courses.length %> courses
<% } %>
</div>
<% if (courses.length === 0) { %>
<p>No courses found. Click "Scrape Courses" to load Swedish courses from PDGA.</p>
<% if (!courses || courses.length === 0) { %>
<p style="text-align: center; color: var(--ink-3); padding: 40px 0;">No courses found. Use "Import from Tjing" or scrape courses from PDGA.</p>
<% } else { %>
<table>
<thead>
<tr>
<th>Course Name</th>
<th class="mobile-hide">City</th>
<th class="mobile-hide">Last Updated</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% courses.forEach(function(course) {
var lastUpdated = new Date(course.last_updated).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' });
%>
<tr id="row-<%= course.id %>" class="expandable-row" onclick="toggleCourseLayouts(<%= course.id %>)">
<td>
<a href="<%= course.link %>" target="_blank" onclick="event.stopPropagation()"><%= course.name %></a>
<div class="mobile-only" style="font-size: 11px; color: #999; margin-top: 2px;"><%= course.city %></div>
</td>
<td class="mobile-hide"><%= course.city %></td>
<td class="mobile-hide"><%= lastUpdated %></td>
<td>
<i class="fas fa-sync-alt refresh-icon" onclick="scrapeLayouts(<%= course.id %>, '<%= course.name.replace(/'/g, "\\'") %>'); event.stopPropagation();" title="Scrape layouts for this course"></i>
</td>
</tr>
<tr id="layouts-<%= course.id %>" class="expanded-content">
<td colspan="4">
<div class="layouts-container" id="layouts-container-<%= course.id %>">
<div class="no-layouts">Click to load layouts...</div>
</div>
</td>
</tr>
<% }); %>
</tbody>
</table>
<%- include('course-cards', { courses: courses, query: locals.query, total: locals.total }) %>
<div class="course-grid" data-total-count="<%= courses.length %>">
<div class="course-row course-row--header" role="row">
<div class="course-header-cell">Course</div>
<div class="course-header-cell">City</div>
<div class="course-header-cell">Last updated</div>
<div class="course-header-cell"></div>
</div>
<% courses.forEach(function(course) {
var layoutCount = course.layoutCount || 0;
var activeLayoutCount = course.activeLayoutCount || 0;
%>
<div class="course-row expandable-row" data-course-id="<%= course.id %>" data-course-name="<%= (course.name || '').toLowerCase() %>" data-course-city="<%= (course.city || '').toLowerCase() %>" onclick="toggleCourseLayouts(<%= course.id %>)">
<div class="course-cell">
<span class="course-name"><%= course.name %></span>
<span class="course-meta">
<% if (layoutCount > 0) { %>
<% if (activeLayoutCount !== layoutCount) { %>
<%= layoutCount %> layouts &middot; <%= activeLayoutCount %> active
<% } else { %>
<%= layoutCount %> layouts
<% } %>
<% } else { %>
No layouts
<% } %>
</span>
</div>
<div class="course-city"><%= course.city || '—' %></div>
<div class="course-updated"><%= course.last_updated ? new Date(course.last_updated).toISOString().slice(0,10) : '—' %></div>
<div class="course-actions">
<button class="icon-btn refresh-icon" onclick="event.stopPropagation(); scrapeLayouts(<%= course.id %>, this)" title="Refresh layouts" aria-label="Refresh layouts">
<i class="fas fa-sync-alt"></i>
</button>
<button class="icon-btn icon-chev" onclick="event.stopPropagation(); toggleCourseLayouts(<%= course.id %>)" title="Expand row" aria-label="Expand">
<i class="fas fa-chevron-down"></i>
</button>
</div>
</div>
<div class="expanded-content" id="course-layouts-<%= course.id %>">
<div class="expanded-cell">
<div class="loading">Loading layouts…</div>
</div>
</div>
<% }); %>
</div>
<%- include('course-cards', { courses: courses, total: courses.length }) %>
<% } %>