improve the comparison search feature
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 56s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 56s
This commit is contained in:
@@ -771,6 +771,58 @@ function setupEventListeners() {
|
||||
|
||||
// Compare search
|
||||
let compareSearchTimeout;
|
||||
let lastCompareSearchData = null;
|
||||
|
||||
function renderCompareResults(data) {
|
||||
if (!data) return;
|
||||
lastCompareSearchData = data;
|
||||
|
||||
const results = data.schools.filter(s => !selectedSchools.some(sel => sel.urn === s.urn));
|
||||
|
||||
const headerHtml = `
|
||||
<div class="compare-results-header">
|
||||
<span>${results.length} school${results.length !== 1 ? 's' : ''} found</span>
|
||||
<button class="compare-results-close" title="Close (Esc)">
|
||||
<svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M12 4L4 12M4 4l8 8"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
if (results.length === 0) {
|
||||
elements.compareResults.innerHTML = headerHtml + '<div class="compare-result-item"><span class="name">No more schools to add</span></div>';
|
||||
} else {
|
||||
elements.compareResults.innerHTML = headerHtml + results.slice(0, 10).map(school => `
|
||||
<div class="compare-result-item" data-urn="${school.urn}" data-name="${escapeHtml(school.school_name)}">
|
||||
<div class="name">${escapeHtml(school.school_name)}</div>
|
||||
<div class="location">${escapeHtml(school.local_authority || '')}${school.postcode ? ' • ' + escapeHtml(school.postcode) : ''}</div>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
elements.compareResults.querySelectorAll('.compare-result-item').forEach(item => {
|
||||
item.addEventListener('click', () => {
|
||||
const urn = parseInt(item.dataset.urn);
|
||||
const school = data.schools.find(s => s.urn === urn);
|
||||
if (school) {
|
||||
addToComparison(school);
|
||||
// Re-render results without closing (filter out newly added school)
|
||||
renderCompareResults(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Add close button handler
|
||||
const closeBtn = elements.compareResults.querySelector('.compare-results-close');
|
||||
if (closeBtn) {
|
||||
closeBtn.addEventListener('click', () => {
|
||||
elements.compareResults.classList.remove('active');
|
||||
elements.compareSearch.value = '';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
elements.compareSearch.addEventListener('input', async () => {
|
||||
clearTimeout(compareSearchTimeout);
|
||||
const query = elements.compareSearch.value.trim();
|
||||
@@ -784,41 +836,14 @@ function setupEventListeners() {
|
||||
const data = await fetchAPI(`/api/schools?search=${encodeURIComponent(query)}`);
|
||||
if (!data) return;
|
||||
|
||||
const results = data.schools.filter(s => !selectedSchools.some(sel => sel.urn === s.urn));
|
||||
|
||||
if (results.length === 0) {
|
||||
elements.compareResults.innerHTML = '<div class="compare-result-item"><span class="name">No schools found</span></div>';
|
||||
} else {
|
||||
elements.compareResults.innerHTML = results.slice(0, 10).map(school => `
|
||||
<div class="compare-result-item" data-urn="${school.urn}" data-name="${escapeHtml(school.school_name)}">
|
||||
<div class="name">${escapeHtml(school.school_name)}</div>
|
||||
<div class="location">${escapeHtml(school.local_authority || '')}${school.postcode ? ' • ' + escapeHtml(school.postcode) : ''}</div>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
elements.compareResults.querySelectorAll('.compare-result-item').forEach(item => {
|
||||
item.addEventListener('click', () => {
|
||||
const urn = parseInt(item.dataset.urn);
|
||||
const school = data.schools.find(s => s.urn === urn);
|
||||
if (school) {
|
||||
addToComparison(school);
|
||||
elements.compareSearch.value = '';
|
||||
elements.compareResults.classList.remove('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
renderCompareResults(data);
|
||||
elements.compareResults.classList.add('active');
|
||||
}, 300);
|
||||
});
|
||||
|
||||
elements.compareSearch.addEventListener('blur', () => {
|
||||
setTimeout(() => elements.compareResults.classList.remove('active'), 200);
|
||||
});
|
||||
|
||||
elements.compareSearch.addEventListener('focus', () => {
|
||||
if (elements.compareSearch.value.trim().length >= 2) {
|
||||
if (elements.compareSearch.value.trim().length >= 2 && lastCompareSearchData) {
|
||||
renderCompareResults(lastCompareSearchData);
|
||||
elements.compareResults.classList.add('active');
|
||||
}
|
||||
});
|
||||
@@ -852,6 +877,13 @@ function setupEventListeners() {
|
||||
// Keyboard
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
// Close compare results if open
|
||||
if (elements.compareResults.classList.contains('active')) {
|
||||
elements.compareResults.classList.remove('active');
|
||||
elements.compareSearch.value = '';
|
||||
return;
|
||||
}
|
||||
// Close modal if open
|
||||
closeModal();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -476,6 +476,38 @@ body {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.compare-results-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0.6rem 1rem;
|
||||
background: var(--bg-secondary);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-muted);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.compare-results-close {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
border-radius: var(--radius-sm);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--text-muted);
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.compare-results-close:hover {
|
||||
background: var(--accent-coral);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.compare-result-item {
|
||||
padding: 0.75rem 1rem;
|
||||
cursor: pointer;
|
||||
|
||||
Reference in New Issue
Block a user