Adjust filtering to enable filtering by map contents

This commit is contained in:
2026-02-10 22:05:25 +00:00
parent fa1da3686f
commit cb9f826943
2 changed files with 54 additions and 26 deletions

View File

@@ -6,6 +6,8 @@ const inputDir = './static/mapFiles/yaml';
const outputDir = './static/mapFiles/json'; const outputDir = './static/mapFiles/json';
const indexFile = './static/map-index.json'; const indexFile = './static/map-index.json';
const noiseRegex = /\s+(single line|junction|jn|junc|jct|gf|north|south|east|west)\.?$/i;
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true }); if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });
const mapList = []; const mapList = [];
@@ -18,12 +20,37 @@ fs.readdirSync(inputDir).forEach((file) => {
const fileName = file.replace('.yaml', '.json'); const fileName = file.replace('.yaml', '.json');
fs.writeFileSync(path.join(outputDir, fileName), JSON.stringify(content)); fs.writeFileSync(path.join(outputDir, fileName), JSON.stringify(content));
const contentSet = new Set();
if (Array.isArray(content.routeDetail)) {
content.routeDetail.forEach(item => {
if ((item.type === 'junction' || item.type === 'station') && item.name) {
let cleanName = item.name;
// Run the replacement in a loop or twice to catch nested noise
// e.g., "Reading West Junction"
// Pass 1: "Reading West"
// Pass 2: "Reading"
let previousName;
do {
previousName = cleanName;
cleanName = cleanName.replace(noiseRegex, '').trim();
} while (cleanName !== previousName);
if (cleanName) {
contentSet.add(cleanName);
}
}
});
}
mapList.push({ mapList.push({
routeId: content.routeId || null, routeId: content.routeId || null,
routeStart: content.routeStart || null, routeStart: content.routeStart || null,
routeEnd: content.routeEnd || null, routeEnd: content.routeEnd || null,
created: content.created || null, created: content.created || null,
checked: content.checked || null checked: content.checked || null,
contents: Array.from(contentSet),
}); });
} }
}); });

View File

@@ -2,19 +2,23 @@
import logo from '$lib/assets/round-logo-text.svg'; import logo from '$lib/assets/round-logo-text.svg';
import type { PageData } from './$types'; import type { PageData } from './$types';
import { resolve } from '$app/paths'; import { resolve } from '$app/paths';
export let data: PageData;
import favicon from '$lib/assets/favicon.svg';
let searchTerm = ''; let { data }: { data: PageData } = $props();
let searchTerm = $state('');
$: filteredMaps = data.maps.filter( let filteredMaps = $derived(
(m) => data.maps.filter((m) => {
m.routeId.toString().includes(searchTerm) || const term = searchTerm.toLowerCase();
m.routeStart.toLowerCase().includes(searchTerm.toLowerCase()) ||
m.routeEnd.toLowerCase().includes(searchTerm.toLowerCase()) if (m.routeId.toString().includes(term)) return true;
return m.contents.some(location =>
location.toLowerCase().includes(term)
);
})
); );
const vibrate = (patern: number | number[] = 10) => { const vibrate = (pattern: number | number[] = 10) => {
if (typeof window !== 'undefined' && window.navigator.vibrate) { if (typeof window !== 'undefined' && window.navigator.vibrate) {
window.navigator.vibrate(pattern); window.navigator.vibrate(pattern);
} }
@@ -53,21 +57,20 @@
alt="OwlBoard Logo" alt="OwlBoard Logo"
class="main-logo" class="main-logo"
/> />
<div class="search-container">
<input
type="text"
bind:value={searchTerm}
placeholder="Search index..."
class="search-input"
/>
</div>
</div> </div>
</header> </header>
<div class="list-container"> <div class="list-container">
<a href="https://owlboard.info" class="button-link">Go to OwlBoard Live Departures & PIS</a> <a href="https://owlboard.info" class="button-link">Go to OwlBoard Live Departures & PIS</a>
<input
type="text"
bind:value={searchTerm}
placeholder="Search"
class="search-input"
/>
{#each filteredMaps as map (map.routeId)} {#each filteredMaps as map (map.routeId)}
<a href={resolve(`/map/${map.routeId.toString().padStart(4, '0')}`)} class="card" on:click={() => vibrate(10)}> <a href={resolve(`/map/${map.routeId.toString().padStart(4, '0')}`)} class="card" onclick={() => vibrate(10)}>
<div class="card-top"> <div class="card-top">
<span class="route-id">{map.routeId.toString().padStart(4, '0')}</span> <span class="route-id">{map.routeId.toString().padStart(4, '0')}</span>
<span class="status-badge {isVerifiedRecently(map.checked)}"> <span class="status-badge {isVerifiedRecently(map.checked)}">
@@ -119,6 +122,7 @@
.main-header { .main-header {
margin-bottom: 1.5rem; margin-bottom: 1.5rem;
position: fixed; position: fixed;
height: 80px;
top: 0; top: 0;
left: 0; left: 0;
box-sizing: border-box; box-sizing: border-box;
@@ -143,17 +147,14 @@
display: block; display: block;
} }
.search-container {
margin-left: auto;
}
.search-input { .search-input {
width: 100%; width: 100%;
margin-left: auto; max-width: 500px;
height: 50px; font-family: "urwgothic";
margin: auto;
height: 40px;
padding: 0.8rem 1rem; padding: 0.8rem 1rem;
text-align: center; text-align: center;
text-transform: uppercase;
border-radius: 30px; border-radius: 30px;
border: none; border: none;
font-size: 1rem; font-size: 1rem;