50 lines
2.6 KiB
JavaScript
50 lines
2.6 KiB
JavaScript
import { filterUnits, subjectsFor, teacherGuidesFor } from './src/library.mjs';
|
|
|
|
const filters = document.querySelector('#subject-filters');
|
|
const grid = document.querySelector('#unit-grid');
|
|
const status = document.querySelector('#library-status');
|
|
let units = [];
|
|
let selectedSubject = 'All';
|
|
|
|
function resourceLink(material) {
|
|
return `<a class="resource-link" href="/api/pdf/${material.id}" target="_blank" rel="noopener">Open ${material.role}<span aria-hidden="true"> ↗</span></a>`;
|
|
}
|
|
|
|
function renderFilters() {
|
|
filters.innerHTML = subjectsFor(units).map((subject) => `<button class="filter ${subject === selectedSubject ? 'selected' : ''}" type="button" data-subject="${subject}">${subject}</button>`).join('');
|
|
filters.querySelectorAll('button').forEach((button) => button.addEventListener('click', () => {
|
|
selectedSubject = button.dataset.subject;
|
|
renderFilters();
|
|
renderUnits();
|
|
}));
|
|
}
|
|
|
|
function renderUnits() {
|
|
const filtered = filterUnits(units, selectedSubject);
|
|
status.textContent = `${filtered.length} ${selectedSubject === 'All' ? 'units' : selectedSubject + ' units'} shown`;
|
|
grid.innerHTML = filtered.map((unit) => {
|
|
const guides = teacherGuidesFor(unit);
|
|
const student = unit.materials.filter((material) => material.role === 'Student Reader');
|
|
const resources = [...guides, ...student].slice(0, 3).map(resourceLink).join('');
|
|
return `<article class="unit-card"><p class="unit-subject">${unit.subject}</p><h3>${unit.title.replace(/^Grade 3\s*/, '')}</h3><p class="material-count">${guides.length ? `${guides.length} teacher plan${guides.length === 1 ? '' : 's'}` : 'Teacher plan not identified'} · ${student.length} student resource${student.length === 1 ? '' : 's'}</p>${resources ? `<div class="resource-links">${resources}</div>` : '<p class="small">Open the original archive source for supporting materials.</p>'}<a class="source-link" href="${unit.source_url}" target="_blank" rel="noopener">Core Knowledge source ↗</a></article>`;
|
|
}).join('');
|
|
}
|
|
|
|
async function loadLibrary() {
|
|
try {
|
|
const response = await fetch('/api/catalog', { cache: 'no-store' });
|
|
if (!response.ok) throw new Error('catalog unavailable');
|
|
const catalog = await response.json();
|
|
units = catalog.units;
|
|
document.querySelector('#unit-count').textContent = catalog.unit_count;
|
|
document.querySelector('#guide-count').textContent = catalog.teacher_guide_count;
|
|
document.querySelector('#student-count').textContent = catalog.student_material_count;
|
|
renderFilters();
|
|
renderUnits();
|
|
} catch {
|
|
status.textContent = 'The local catalog could not load. Start the private Grade 3 demo server.';
|
|
}
|
|
}
|
|
|
|
loadLibrary();
|