Files
web-pwa/src/lib/geohash.svelte.ts

91 lines
2.3 KiB
TypeScript

import { OwlClient, ValidationError, ApiError } from './owlClient';
import type { ApiStationsNearestStations } from '@owlboard/owlboard-ts';
class NearestStationsState {
list = $state<ApiStationsNearestStations.StationsNearestStations[]>([]);
currentHash = $state('');
loading = $state(true);
error = $state<string | null>(null);
private geoConfig: PositionOptions = {
enableHighAccuracy: false,
timeout: 30000,
maximumAge: 120000
};
constructor() {
if (typeof window !== 'undefined' && 'geolocation' in navigator) {
this.jumpstart();
this.initWatcher();
}
}
private jumpstart() {
navigator.geolocation.getCurrentPosition(
(pos) => this.handleUpdate(pos.coords.latitude, pos.coords.longitude),
(err) => this.handleError(err),
this.geoConfig
);
}
private initWatcher() {
navigator.geolocation.watchPosition(
(pos) => this.handleUpdate(pos.coords.latitude, pos.coords.longitude),
(err) => this.handleError(err),
this.geoConfig
);
}
private async handleUpdate(lat: number, lon: number) {
const newHash = OwlClient.stationData.generateGeohash(lat, lon);
if (newHash !== this.currentHash) {
this.loading = true;
try {
const result = await OwlClient.stationData.getNearestStations(newHash);
this.list = result.data;
this.error = null;
this.currentHash = newHash;
} catch (e) {
this.handleApiError(e);
} finally {
this.loading = false;
}
}
}
private handleError(err: GeolocationPositionError) {
if (err.code === 1) {
this.error = 'Location access denied by device';
} else {
this.error = 'Waiting for GPS signal...';
}
}
private handleApiError(e: unknown) {
if (e instanceof ValidationError) {
this.error = `Request Error: ${e.reason} (Field: ${e.field})`;
} else if (e instanceof ApiError) {
switch (e.status) {
case 404:
this.error = 'No stations found nearby';
break;
case 429:
this.error = 'Too many requests, will retry';
break;
case 500:
this.error = 'Server Error, will retry';
break;
default:
this.error = `Service error: ${e.code}`;
}
} else {
this.error = 'Connection lost, waiting for signal';
}
console.error('OwlBoard API Error:', e);
}
}
export const nearestStationsState = new NearestStationsState();