fix: address mobile UI review findings (#16)
- Hide desktop .card-section on mobile, add .m-search-input with same HTMX attrs for mobile course search (fixes horizontal overflow) - Remove dead layoutCount var and .m-layouts-pill block in course-cards - Remove dead 768px breakpoints from players.css (table hidden at 880px) - Move .mobile-section-head inside else-block for empty state in both ratings-cards and course-cards (fixes section head showing on empty) - Add tabindex, role=button, aria-expanded, onkeydown to .m-card and .m-course-card; toggle aria-expanded in JS toggle functions - Fix data-history attribute to use <%= (HTML-escaped) instead of <%- - Convert var to const/let in all new/changed JS blocks
This commit is contained in:
+11
-6
@@ -31,32 +31,37 @@ function toggleCourseLayouts(courseId) {
|
||||
}
|
||||
|
||||
// ── Mobile course card toggle ──────────────────────
|
||||
var openMobileCourseId = null;
|
||||
let openMobileCourseId = null;
|
||||
|
||||
function toggleMobileCourseLayouts(courseId) {
|
||||
var card = document.getElementById('m-course-' + courseId);
|
||||
const card = document.getElementById('m-course-' + courseId);
|
||||
if (!card) return;
|
||||
|
||||
var isOpen = card.classList.contains('is-open');
|
||||
const isOpen = card.classList.contains('is-open');
|
||||
|
||||
// Close previously open card
|
||||
if (openMobileCourseId !== null && openMobileCourseId !== courseId) {
|
||||
var prevCard = document.getElementById('m-course-' + openMobileCourseId);
|
||||
if (prevCard) prevCard.classList.remove('is-open');
|
||||
const prevCard = document.getElementById('m-course-' + openMobileCourseId);
|
||||
if (prevCard) {
|
||||
prevCard.classList.remove('is-open');
|
||||
prevCard.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
openMobileCourseId = null;
|
||||
}
|
||||
|
||||
if (isOpen) {
|
||||
card.classList.remove('is-open');
|
||||
card.setAttribute('aria-expanded', 'false');
|
||||
openMobileCourseId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
card.classList.add('is-open');
|
||||
card.setAttribute('aria-expanded', 'true');
|
||||
openMobileCourseId = courseId;
|
||||
|
||||
// Lazy-load layouts on first expand
|
||||
var container = document.getElementById('m-layouts-container-' + courseId);
|
||||
const container = document.getElementById('m-layouts-container-' + courseId);
|
||||
if (container && container.dataset.loaded !== 'true') {
|
||||
htmx.ajax('GET', '/partials/course-layouts/' + courseId, { target: '#m-layouts-container-' + courseId, swap: 'innerHTML' });
|
||||
container.dataset.loaded = 'true';
|
||||
|
||||
+18
-13
@@ -31,8 +31,8 @@ function initChartsIn(rootEl) {
|
||||
if (container.dataset.charted === 'true') return;
|
||||
if (!container.dataset.history) return;
|
||||
try {
|
||||
var history = JSON.parse(container.dataset.history);
|
||||
var isMobile = container.dataset.variant === 'mobile';
|
||||
const history = JSON.parse(container.dataset.history);
|
||||
const isMobile = container.dataset.variant === 'mobile';
|
||||
if (isMobile) {
|
||||
createRatingChart(container, history, {
|
||||
w: 360,
|
||||
@@ -782,32 +782,37 @@ async function refreshHistoryThenCalculate(pdgaNumber) {
|
||||
}
|
||||
|
||||
// ── Mobile player card toggle ──────────────────────
|
||||
var openMobilePdgaNumber = null;
|
||||
let openMobilePdgaNumber = null;
|
||||
|
||||
function toggleMobilePlayerCard(pdgaNumber) {
|
||||
var card = document.getElementById('m-card-' + pdgaNumber);
|
||||
const card = document.getElementById('m-card-' + pdgaNumber);
|
||||
if (!card) return;
|
||||
|
||||
var isOpen = card.classList.contains('is-open');
|
||||
const isOpen = card.classList.contains('is-open');
|
||||
|
||||
// Close previously open card
|
||||
if (openMobilePdgaNumber !== null && openMobilePdgaNumber !== pdgaNumber) {
|
||||
var prevCard = document.getElementById('m-card-' + openMobilePdgaNumber);
|
||||
if (prevCard) prevCard.classList.remove('is-open');
|
||||
const prevCard = document.getElementById('m-card-' + openMobilePdgaNumber);
|
||||
if (prevCard) {
|
||||
prevCard.classList.remove('is-open');
|
||||
prevCard.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
openMobilePdgaNumber = null;
|
||||
}
|
||||
|
||||
if (isOpen) {
|
||||
card.classList.remove('is-open');
|
||||
card.setAttribute('aria-expanded', 'false');
|
||||
openMobilePdgaNumber = null;
|
||||
return;
|
||||
}
|
||||
|
||||
card.classList.add('is-open');
|
||||
card.setAttribute('aria-expanded', 'true');
|
||||
openMobilePdgaNumber = pdgaNumber;
|
||||
|
||||
// Init charts inside the expand panel
|
||||
var expand = card.querySelector('.m-card__expand');
|
||||
const expand = card.querySelector('.m-card__expand');
|
||||
if (expand) {
|
||||
initChartsIn(expand);
|
||||
}
|
||||
@@ -816,20 +821,20 @@ function toggleMobilePlayerCard(pdgaNumber) {
|
||||
// ── Mobile add player ──────────────────────────────
|
||||
async function searchAndAddPlayerMobile(event) {
|
||||
if (event) event.preventDefault();
|
||||
var input = document.getElementById('pdga-number-input-mobile');
|
||||
var pdgaNumber = input ? input.value.trim() : '';
|
||||
const input = document.getElementById('pdga-number-input-mobile');
|
||||
const pdgaNumber = input ? input.value.trim() : '';
|
||||
|
||||
if (!pdgaNumber) {
|
||||
alert('Please enter a PDGA number');
|
||||
return;
|
||||
}
|
||||
|
||||
var button = event && event.target ? event.target.querySelector('button[type="submit"]') : null;
|
||||
const button = event && event.target ? event.target.querySelector('button[type="submit"]') : null;
|
||||
if (button) { button.disabled = true; button.textContent = 'Searching...'; }
|
||||
|
||||
try {
|
||||
var response = await fetch('/api/search-player/' + pdgaNumber);
|
||||
var data = await response.json();
|
||||
const response = await fetch('/api/search-player/' + pdgaNumber);
|
||||
const data = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
showErrorModal(data.error || 'Player not found');
|
||||
|
||||
Reference in New Issue
Block a user