diff --git a/.gitea/workflows/build-push.yaml b/.gitea/workflows/build-push.yaml index ec6d5d6..65ef29f 100644 --- a/.gitea/workflows/build-push.yaml +++ b/.gitea/workflows/build-push.yaml @@ -3,7 +3,7 @@ run-name: ${{ gitea.actor }} is building and pushing on: create: - tags: "*" + tags: '*' env: GITEA_DOMAIN: git.fjla.uk @@ -36,4 +36,4 @@ jobs: push: true tags: | ${{ env.GITEA_DOMAIN }}/${{ env.RESULT_IMAGE_NAME }}:${{ gitea.ref_name }} - ${{ env.GITEA_DOMAIN }}/${{ env.RESULT_IMAGE_NAME }}:latest \ No newline at end of file + ${{ env.GITEA_DOMAIN }}/${{ env.RESULT_IMAGE_NAME }}:latest diff --git a/.gitignore b/.gitignore index 4615b07..875ef67 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ node_modules # Transpiled JSON /static/mapFiles/json/ +/static/map-index.json # Output .output diff --git a/scripts/parse-maps.js b/scripts/parse-maps.js index 3f5d580..eea8161 100644 --- a/scripts/parse-maps.js +++ b/scripts/parse-maps.js @@ -4,13 +4,30 @@ import path from 'path'; const inputDir = './static/mapFiles/yaml'; const outputDir = './static/mapFiles/json'; +const indexFile = './static/map-index.json'; if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true }); +const mapList = []; + fs.readdirSync(inputDir).forEach((file) => { if (file.endsWith('.yaml')) { - const content = yaml.load(fs.readFileSync(path.join(inputDir, file), 'utf8')); + const fullPath = path.join(inputDir, file); + const content = yaml.load(fs.readFileSync(fullPath, 'utf8')); + const fileName = file.replace('.yaml', '.json'); fs.writeFileSync(path.join(outputDir, fileName), JSON.stringify(content)); + + mapList.push({ + routeId: content.routeId || null, + routeStart: content.routeStart || null, + routeEnd: content.routeEnd || null, + created: content.created || null, + checked: content.checked || null, + }); } }); + +fs.writeFileSync(indexFile, JSON.stringify(mapList)); + +console.log(`Generated ${mapList.length} map files and index.`) diff --git a/src/lib/components/mapIcons/Bridge.svelte b/src/lib/components/mapIcons/Bridge.svelte index 5d741ba..a20b0ff 100644 --- a/src/lib/components/mapIcons/Bridge.svelte +++ b/src/lib/components/mapIcons/Bridge.svelte @@ -1,80 +1,194 @@ - {#if !isOver} - - - + {#if isOver} + + + + + + + + {#if s.type === 'road'} + + {:else if s.type === 'rail'} + + + {/if} + + + + + + {:else} - - - - - - - - - + + + {#if s.type === 'road'} + + {:else if s.type === 'rail'} + + + {/if} + + + + + + - {#if feature.roadName} + + {/if} + + {#if feature.roadName} + + 20 ? '10' : '8'} - style="pointer-events: none; text-transform: uppercase; letter-spacing: 0.5px;" + font-family="ui-monospace, monospace" + font-weight="900" + font-size="8" > {feature.roadName} - {/if} + {/if} diff --git a/src/lib/components/mapIcons/ElectrificationChange.svelte b/src/lib/components/mapIcons/ElectrificationChange.svelte index 21e3978..84d4969 100644 --- a/src/lib/components/mapIcons/ElectrificationChange.svelte +++ b/src/lib/components/mapIcons/ElectrificationChange.svelte @@ -1,13 +1,14 @@ - {#each paths as d} - - {/each} - + {#each paths as d} + + {/each} + diff --git a/src/lib/components/mapIcons/RouteEndLink.svelte b/src/lib/components/mapIcons/RouteEndLink.svelte index e9f808a..e4f6d69 100644 --- a/src/lib/components/mapIcons/RouteEndLink.svelte +++ b/src/lib/components/mapIcons/RouteEndLink.svelte @@ -1,93 +1,121 @@ \ No newline at end of file + .wide-button:active { + transform: scale(0.98); + } + diff --git a/src/lib/components/mapIcons/SignallerChange.svelte b/src/lib/components/mapIcons/SignallerChange.svelte index ba6fdbb..4a3c90f 100644 --- a/src/lib/components/mapIcons/SignallerChange.svelte +++ b/src/lib/components/mapIcons/SignallerChange.svelte @@ -6,7 +6,14 @@ to: string; }; + export let reversed: boolean = false; + export let activeElec: any; + + $: effectiveFeature = { + from: reversed ? feature.to : feature.from, + to: reversed ? feature.from : feature.to + }; @@ -24,10 +31,10 @@ - {feature.from} + {effectiveFeature.from} - {feature.to} + {effectiveFeature.to} diff --git a/src/lib/components/mapIcons/Tunnel.svelte b/src/lib/components/mapIcons/Tunnel.svelte index b279252..bee8b12 100644 --- a/src/lib/components/mapIcons/Tunnel.svelte +++ b/src/lib/components/mapIcons/Tunnel.svelte @@ -1,56 +1,59 @@ - + - - {#if effectiveType === 'whole'} - - + + {#if effectiveType === 'whole'} + + + {:else if effectiveType === 'start'} + + {:else if effectiveType === 'end'} + + {/if} + - {:else if effectiveType === 'start'} - - - {:else if effectiveType === 'end'} - - {/if} - - - {#if feature.tunnelType === 'whole' && feature.length} - - - {feature.length} - - {/if} + {#if feature.tunnelType === 'whole' && feature.length} + + + {feature.length} + + {/if} \ No newline at end of file + svg { + display: block; + overflow: visible; + } + .t-text { + font-family: ui-monospace, monospace; + } + diff --git a/src/lib/mapRegistry.ts b/src/lib/mapRegistry.ts index 108a5bb..a358f33 100644 --- a/src/lib/mapRegistry.ts +++ b/src/lib/mapRegistry.ts @@ -23,5 +23,5 @@ export const components = { signallerChange: SignallerChange, electrificationChange: ElectrificationChange, default: BaseTrack, - tunnel: Tunnel, + tunnel: Tunnel }; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 4752aac..2d0c4ff 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,116 +1,236 @@ -

Welcome to SvelteKit

-

Visit svelte.dev/docs/kit to read the documentation

+
+
+

ROUTE_DB

+
+ +
+
-
- {#each dummyFeatures as feature} - - {/each} +
+ /* Mobile-First Base Styles */ + :global(body) { + margin: 0; + background-color: #f8fafc; + color: #0f172a; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + } + + .page-wrapper { + padding: 1rem; + max-width: 800px; + margin: 0 auto; + } + + .main-header { + margin-bottom: 1.5rem; + } + + h1 { + font-size: 1.5rem; + font-weight: 900; + letter-spacing: -0.05em; + margin: 0 0 1rem 0; + font-style: italic; + } + + .search-input { + width: 100%; + padding: 0.8rem 1rem; + border: 2px solid #e2e8f0; + border-radius: 12px; + font-size: 1rem; + box-sizing: border-box; /* Ensures padding doesn't break width */ + outline: none; + } + + .search-input:focus { + border-color: #3b82f6; + } + + /* Card Layout (Mobile) */ + .list-container { + display: flex; + flex-direction: column; + gap: 1rem; + } + + .card { + display: block; + background: white; + padding: 1.25rem; + border-radius: 16px; + text-decoration: none; + color: inherit; + border: 1px solid #e2e8f0; + box-shadow: 0 1px 3px rgba(0,0,0,0.05); + transition: transform 0.1s ease; + } + + .card:active { + transform: scale(0.98); /* Tactile feedback for mobile */ + } + + .card-top { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 0.75rem; + } + + .route-id { + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; + font-weight: 800; + color: #3b82f6; + background: #eff6ff; + padding: 0.2rem 0.5rem; + border-radius: 6px; + } + + .card-body { + margin-bottom: 1rem; + } + + .location { + font-size: 1.125rem; + font-weight: 700; + letter-spacing: -0.02em; + } + + .path-arrow { + color: #cbd5e1; + font-size: 0.9rem; + margin: 0.2rem 0; + } + + .card-footer { + font-size: 0.7rem; + color: #64748b; + text-transform: uppercase; + font-weight: 600; + letter-spacing: 0.05em; + border-top: 1px solid #f1f5f9; + padding-top: 0.75rem; + } + +/* Update your existing badge styles */ +.status-badge { + font-size: 0.65rem; + font-weight: 800; + text-transform: uppercase; + padding: 0.3rem 0.6rem; + border-radius: 999px; + white-space: nowrap; /* Prevents label snapping on small screens */ +} + +.verified { + background: #dcfce7; + color: #166534; +} + +.stale { + background: #fef3c7; /* Amber/Yellow background */ + color: #92400e; /* Dark brown/gold text */ + border: 1px solid #fcd34d; +} + +.draft { + background: #f1f5f9; + color: #475569; +} + + /* Desktop Adjustments */ + @media (min-width: 640px) { + .page-wrapper { + padding: 3rem 1.5rem; + } + + .main-header { + display: flex; + justify-content: space-between; + align-items: center; + } + + .search-input { + width: 300px; + } + + .path-arrow { + display: inline-block; + margin: 0 0.5rem; + transform: rotate(-90deg); /* Turn down arrow into right arrow */ + } + + .card-body { + display: flex; + align-items: center; + } + } + \ No newline at end of file diff --git a/src/routes/+page.ts b/src/routes/+page.ts new file mode 100644 index 0000000..2816f68 --- /dev/null +++ b/src/routes/+page.ts @@ -0,0 +1,17 @@ +import type { PageLoad } from "./$types"; + +export const load: PageLoad = async ({ fetch }) => { + const response = await fetch('map-index.json'); + + if (!response.ok) { + return { maps: [] }; + } + + const maps = await response.json(); + + return { + maps: maps.sort((a: any, b: any) => { + return Number(a.routeId) - Number(b.routeId); + }) + }; +}; \ No newline at end of file diff --git a/src/routes/healthz/+server.ts b/src/routes/healthz/+server.ts index f0df974..120c728 100644 --- a/src/routes/healthz/+server.ts +++ b/src/routes/healthz/+server.ts @@ -2,7 +2,10 @@ import { json } from '@sveltejs/kit'; import type { RequestHandler } from './$types'; export const GET: RequestHandler = () => { - return json({ status: 'ok', uptime: process.uptime() }, { - status: 200 - }); -}; \ No newline at end of file + return json( + { status: 'ok', uptime: process.uptime() }, + { + status: 200 + } + ); +}; diff --git a/src/routes/map/[slug]/+page.svelte b/src/routes/map/[slug]/+page.svelte index 429d058..c2dc869 100644 --- a/src/routes/map/[slug]/+page.svelte +++ b/src/routes/map/[slug]/+page.svelte @@ -1,9 +1,9 @@
-
-

{data.route.routeName}

- {data.route.routeId} -
- - -
-
+
+ + +
+ + +
+
{#if showFilters}
(showFilters = false)}>
@@ -108,53 +123,130 @@
{#each filteredFeatures as f, i (`${f.type}-${f.miles}-${f.chains}-${i}`)} - {#if (f.type === 'continues')} - - {:else} - - {/if} + {#if f.type === 'continues'} + + {:else} + + {/if} {/each}
+ diff --git a/static/mapFiles/yaml/0001.yaml b/static/mapFiles/yaml/0001.yaml index 24b5859..95f1bfe 100644 --- a/static/mapFiles/yaml/0001.yaml +++ b/static/mapFiles/yaml/0001.yaml @@ -1,5 +1,8 @@ -routeName: Paddington - Reading West Jn +routeStart: Paddington +routeEnd: Reading West Jn routeId: 0001 +created: 2026-02-04 +checked: 2026-02-06 signallerStart: TVSC Paddington WS signallerEnd: TVSC Reading WS elecStart: @@ -437,7 +440,7 @@ routeDetail: - type: bridge name: Yeading Brook position: under - category: waterway + category: stream miles: 10 chains: 29 @@ -579,7 +582,7 @@ routeDetail: - type: bridge name: Stream position: under - category: waterway + category: stream miles: 14 chains: 10 @@ -627,7 +630,7 @@ routeDetail: - type: bridge name: Stream position: under - category: waterway + category: stream miles: 15 chains: 61 @@ -861,7 +864,7 @@ routeDetail: - type: bridge name: Stream position: under - category: waterway + category: stream miles: 23 chains: 66 @@ -1042,6 +1045,7 @@ routeDetail: diverges: left direction: down description: Henley-on-Thames from Platform 4 only + elecBranch: none miles: 31 chains: 4 diff --git a/static/mapFiles/yaml/0002.yaml b/static/mapFiles/yaml/0002.yaml new file mode 100644 index 0000000..a0d74d0 --- /dev/null +++ b/static/mapFiles/yaml/0002.yaml @@ -0,0 +1,18 @@ +routeStart: Reading West Jn +routeEnd: Bristol TM +routeId: 0002 +created: 2026-02-04 +checked: +signallerStart: TVSC Reading WS +signallerEnd: TVSC Temple Meads WS +elecStart: + elec: 25kvac + eco: Didcot (TVSC) +elecEnd: + elec: none +routeDetail: +- type: crossovers + name: Scours Lane Junction + description: Line diverges + miles: 38 + chains: 90 \ No newline at end of file