Files
pdga-rating/public/js/courses.js
T
2026-05-22 21:07:00 +02:00

121 lines
4.1 KiB
JavaScript

function toggleAccordion(accordionId) {
const content = document.getElementById(accordionId);
const icon = document.getElementById(`${accordionId}-icon`);
if (content.classList.contains('expanded')) {
content.classList.remove('expanded');
icon.classList.remove('expanded');
} else {
content.classList.add('expanded');
icon.classList.add('expanded');
}
}
function toggleCourseLayouts(courseId) {
const layoutsRow = document.getElementById(`layouts-${courseId}`);
const layoutsContainer = document.getElementById(`layouts-container-${courseId}`);
if (layoutsRow.style.display === 'table-row') {
layoutsRow.style.display = 'none';
return;
}
layoutsRow.style.display = 'table-row';
if (layoutsContainer.dataset.loaded === 'true') {
return;
}
htmx.ajax('GET', `/partials/course-layouts/${courseId}`, {target: `#layouts-container-${courseId}`, swap: 'innerHTML'});
layoutsContainer.dataset.loaded = 'true';
}
// ── Mobile course card toggle ──────────────────────
var openMobileCourseId = null;
function toggleMobileCourseLayouts(courseId) {
var card = document.getElementById('m-course-' + courseId);
if (!card) return;
var 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');
openMobileCourseId = null;
}
if (isOpen) {
card.classList.remove('is-open');
openMobileCourseId = null;
return;
}
card.classList.add('is-open');
openMobileCourseId = courseId;
// Lazy-load layouts on first expand
var 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';
}
}
async function scrapeCourses() {
const btn = document.getElementById('scrape-courses-btn');
btn.disabled = true;
btn.textContent = 'Scraping...';
try {
const response = await fetch('/api/scrape-courses', { method: 'POST' });
const data = await response.json();
if (data.success) {
alert(data.message);
htmx.ajax('GET', '/partials/course-table', '#courses-table');
} else {
alert('Failed to scrape courses');
}
} catch (error) {
console.error('Error scraping courses:', error);
alert('Error scraping courses');
} finally {
btn.disabled = false;
btn.textContent = 'Scrape Courses';
}
}
async function scrapeLayouts(courseId, courseName) {
const icon = document.querySelector(`#row-${courseId} .refresh-icon`);
icon.classList.add('spinning');
try {
const response = await fetch(`/api/scrape-layouts/${courseId}`, { method: 'POST' });
const data = await response.json();
if (response.status === 409) {
alert(data.message || 'Scrape already in progress for this course. Please wait.');
} else if (data.success) {
const layoutsContainer = document.getElementById(`layouts-container-${courseId}`);
layoutsContainer.dataset.loaded = 'false';
const layoutsRow = document.getElementById(`layouts-${courseId}`);
if (layoutsRow.style.display === 'table-row') {
htmx.ajax('GET', `/partials/course-layouts/${courseId}`, {target: `#layouts-container-${courseId}`, swap: 'innerHTML'});
layoutsContainer.dataset.loaded = 'true';
}
alert(data.message);
} else {
alert('Failed to scrape layouts');
}
} catch (error) {
console.error('Error scraping layouts:', error);
alert('Error scraping layouts');
} finally {
icon.classList.remove('spinning');
}
}