163 lines
4.0 KiB
Svelte
163 lines
4.0 KiB
Svelte
<script lang="ts">
|
|
import PisStartEndCard from '$lib/components/ui/cards/pis/PisStartEndCard.svelte';
|
|
import PisCode from '$lib/components/ui/cards/pis/PisCode.svelte';
|
|
import Button from '$lib/components/ui/Button.svelte';
|
|
import type { ApiPisObject } from '@owlboard/owlboard-ts';
|
|
import { OwlClient, ApiError, ValidationError } from '$lib/owlClient';
|
|
import TocStyle from '$lib/components/ui/TocStyle.svelte';
|
|
|
|
let results = $state<ApiPisObject.PisObjects[]>([]);
|
|
let resultsLoaded = $state<boolean>(false);
|
|
let errorState = $state<{ status: number; message: string } | null>(null);
|
|
|
|
async function handleStartEndSearch(start: string, end: string): Promise<void> {
|
|
console.log(`PIS Search: ${start}-${end}`);
|
|
errorState = null;
|
|
|
|
try {
|
|
const response = await OwlClient.pis.getByStartEndCrs(start, end);
|
|
results = response.data || [];
|
|
} catch (e) {
|
|
if (e instanceof ValidationError) {
|
|
errorState = { status: 400, message: e.message };
|
|
} else if (e instanceof ApiError) {
|
|
console.log(e);
|
|
errorState = { status: 20, message: e.message };
|
|
} else {
|
|
errorState = { status: 0, message: `Unknown Error: ${e.message}` };
|
|
}
|
|
} finally {
|
|
resultsLoaded = true;
|
|
}
|
|
}
|
|
|
|
async function handleCodeSearch(code: string) {
|
|
console.log(`PIS Search: ${code}`);
|
|
errorState = null;
|
|
try {
|
|
const response = await OwlClient.pis.getByCode(code);
|
|
results = response.data || [];
|
|
} catch (e) {
|
|
if (e instanceof ValidationError) {
|
|
errorState = { status: 400, message: e.message };
|
|
} else if (e instanceof ApiError) {
|
|
console.log(e);
|
|
errorState = { status: 20, message: e.message };
|
|
} else {
|
|
errorState = { status: 0, message: `Unknown Error: ${e.message}` };
|
|
}
|
|
} finally {
|
|
resultsLoaded = true;
|
|
}
|
|
}
|
|
|
|
function clearResults() {
|
|
console.log('Clearing Results');
|
|
resultsLoaded = false;
|
|
results = [];
|
|
}
|
|
</script>
|
|
|
|
{#if !resultsLoaded}
|
|
<div class="card-container">
|
|
<PisStartEndCard onsearch={handleStartEndSearch} />
|
|
<PisCode onsearch={handleCodeSearch} />
|
|
</div>
|
|
{:else}
|
|
<div class="result-container">
|
|
{#if errorState}
|
|
<span class="errCode">Error: {errorState.status}</span>
|
|
<span class="errMsg">{errorState.message}</span>
|
|
{:else if results.length}
|
|
<h2 class="result-title">
|
|
{results.length} Result{#if results.length > 1}s{/if} found
|
|
</h2>
|
|
<table class="result-table">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:16%">TOC</th>
|
|
<th style="width:14%">Code</th>
|
|
<th style="width:70%">Locations</th>
|
|
</tr></thead
|
|
>
|
|
{#each results as result}
|
|
<tbody
|
|
><tr>
|
|
<td><TocStyle toc={result.toc || ''} /></td>
|
|
<td>{result.code}</td>
|
|
<td class="locations-row">{result.crsStops?.join(' ') || ''}</td>
|
|
</tr></tbody
|
|
>
|
|
{/each}
|
|
</table>
|
|
{:else}
|
|
<p class="no-results">No matching results</p>
|
|
{/if}
|
|
<div class="reset-button-container">
|
|
<Button onclick={clearResults}>Reset</Button>
|
|
</div>
|
|
</div>
|
|
{/if}
|
|
|
|
<style>
|
|
.card-container {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-direction: column;
|
|
gap: 20px;
|
|
justify-content: center;
|
|
padding: 20px 10px;
|
|
}
|
|
|
|
.result-container {
|
|
font-family: 'URW Gothic', sans-serif;
|
|
font-size: 1.2rem;
|
|
font-weight: 600;
|
|
display: flex;
|
|
align-items: center;
|
|
flex-direction: column;
|
|
gap: 5px;
|
|
justify-content: center;
|
|
background: var(--color-accent);
|
|
border-radius: 15px;
|
|
padding: 20px 0 20px 0;
|
|
margin: auto;
|
|
margin-top: 25px;
|
|
margin-bottom: 25px;
|
|
width: 90%;
|
|
max-width: 500px;
|
|
box-shadow: var(--shadow-std);
|
|
}
|
|
|
|
.result-title {
|
|
color: var(--color-brand);
|
|
}
|
|
|
|
.result-table {
|
|
width: 90%;
|
|
max-width: 350px;
|
|
margin: auto;
|
|
text-align: center;
|
|
table-layout: fixed;
|
|
border-collapse: separate;
|
|
border-spacing: 0 20px;
|
|
font-weight: 400;
|
|
}
|
|
|
|
.locations-row {
|
|
font-family: 'Courier New', Courier, monospace;
|
|
text-align: left;
|
|
padding-left: 20px;
|
|
}
|
|
|
|
.errCode {
|
|
color: rgb(255, 54, 54);
|
|
font-weight: 600;
|
|
font-size: 2rem;
|
|
}
|
|
|
|
.reset-button-container {
|
|
padding: 20px 0 3px 0;
|
|
}
|
|
</style>
|