Add progressive web app companion for cross-platform access
Vite + TypeScript PWA that mirrors the Android app's core features: - Pre-processed shelter data (build-time UTM33N→WGS84 conversion) - Leaflet map with shelter markers, user location, and offline tiles - Canvas compass arrow (ported from DirectionArrowView.kt) - IndexedDB shelter cache with 7-day staleness check - Service worker with CacheFirst tiles and precached app shell - i18n for en, nb, nn (ported from Android strings.xml) - iOS/Android compass handling with low-pass filter - Respects user map interaction (no auto-snap on pan/zoom) - Build revision cache-breaker for reliable SW updates Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
46365b713b
commit
e8428de775
12051 changed files with 1799735 additions and 0 deletions
70
pwa/tests/shelter-finder.test.ts
Normal file
70
pwa/tests/shelter-finder.test.ts
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
import { describe, it, expect } from 'vitest';
|
||||
import { findNearest } from '../src/location/shelter-finder';
|
||||
import type { Shelter } from '../src/types';
|
||||
|
||||
const shelters: Shelter[] = [
|
||||
{
|
||||
lokalId: 'a',
|
||||
romnr: 1,
|
||||
plasser: 100,
|
||||
adresse: 'Near',
|
||||
latitude: 59.91,
|
||||
longitude: 10.75,
|
||||
},
|
||||
{
|
||||
lokalId: 'b',
|
||||
romnr: 2,
|
||||
plasser: 200,
|
||||
adresse: 'Mid',
|
||||
latitude: 59.95,
|
||||
longitude: 10.75,
|
||||
},
|
||||
{
|
||||
lokalId: 'c',
|
||||
romnr: 3,
|
||||
plasser: 300,
|
||||
adresse: 'Far',
|
||||
latitude: 60.0,
|
||||
longitude: 10.75,
|
||||
},
|
||||
{
|
||||
lokalId: 'd',
|
||||
romnr: 4,
|
||||
plasser: 400,
|
||||
adresse: 'Very Far',
|
||||
latitude: 61.0,
|
||||
longitude: 10.75,
|
||||
},
|
||||
];
|
||||
|
||||
describe('findNearest', () => {
|
||||
it('returns shelters sorted by distance', () => {
|
||||
const result = findNearest(shelters, 59.9, 10.75);
|
||||
expect(result).toHaveLength(3);
|
||||
expect(result[0].shelter.lokalId).toBe('a');
|
||||
expect(result[1].shelter.lokalId).toBe('b');
|
||||
expect(result[2].shelter.lokalId).toBe('c');
|
||||
});
|
||||
|
||||
it('returns requested count', () => {
|
||||
const result = findNearest(shelters, 59.9, 10.75, 2);
|
||||
expect(result).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('returns all if fewer than count', () => {
|
||||
const result = findNearest(shelters.slice(0, 1), 59.9, 10.75, 5);
|
||||
expect(result).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('calculates distance and bearing', () => {
|
||||
const result = findNearest(shelters, 59.9, 10.75, 1);
|
||||
expect(result[0].distanceMeters).toBeGreaterThan(0);
|
||||
expect(result[0].bearingDegrees).toBeGreaterThanOrEqual(0);
|
||||
expect(result[0].bearingDegrees).toBeLessThan(360);
|
||||
});
|
||||
|
||||
it('handles empty shelter list', () => {
|
||||
const result = findNearest([], 59.9, 10.75);
|
||||
expect(result).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue