Adjust filtering to enable filtering by map contents
This commit is contained in:
@@ -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),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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 { data }: { data: PageData } = $props();
|
||||||
|
let searchTerm = $state('');
|
||||||
|
|
||||||
let searchTerm = '';
|
let filteredMaps = $derived(
|
||||||
|
data.maps.filter((m) => {
|
||||||
|
const term = searchTerm.toLowerCase();
|
||||||
|
|
||||||
$: filteredMaps = data.maps.filter(
|
if (m.routeId.toString().includes(term)) return true;
|
||||||
(m) =>
|
|
||||||
m.routeId.toString().includes(searchTerm) ||
|
return m.contents.some(location =>
|
||||||
m.routeStart.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
location.toLowerCase().includes(term)
|
||||||
m.routeEnd.toLowerCase().includes(searchTerm.toLowerCase())
|
);
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
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;
|
||||||
|
|||||||
Reference in New Issue
Block a user