synops/frontend/src/lib/components/LocationMap.svelte
vegard 6729a35435 Lokasjon-input: del posisjon i chat med kartvisning (oppgave 29.9)
Ny «Del posisjon»-knapp i ChatInput ved siden av tale/video-knappene.
Bruker Geolocation API for å hente brukerens posisjon, oppretter en
content-node med metadata.location { lat, lon, address }.

Reverse geocoding via Nominatim (best-effort) gir adresse i metadata.
Kartvisning i chat via Leaflet/OpenStreetMap viser posisjonen inline.

Komponenter:
- LocationShare.svelte: knapp + geolocation + geocoding + node-opprettelse
- LocationMap.svelte: Leaflet-kart med markør og adresse-popup
- Leaflet lastes via CDN (unpkg) i app.html
2026-03-18 22:36:08 +00:00

57 lines
1.3 KiB
Svelte

<script lang="ts">
import { onMount } from 'svelte';
import { browser } from '$app/environment';
interface Props {
lat: number;
lon: number;
address?: string;
/** Map height in pixels */
height?: number;
}
let { lat, lon, address, height = 200 }: Props = $props();
let mapContainer: HTMLDivElement | undefined = $state();
let map: L.Map | undefined;
onMount(() => {
if (!browser || !mapContainer) return;
const L = (window as any).L;
if (!L) return;
map = L.map(mapContainer, {
scrollWheelZoom: false,
dragging: true,
zoomControl: true,
}).setView([lat, lon], 15);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
maxZoom: 19,
}).addTo(map);
const marker = L.marker([lat, lon]).addTo(map);
if (address) {
marker.bindPopup(address);
}
return () => {
map?.remove();
map = undefined;
};
});
</script>
<div class="overflow-hidden rounded-lg">
<div
bind:this={mapContainer}
style="height: {height}px; width: 100%; min-width: 200px;"
></div>
{#if address}
<p class="mt-1 text-xs text-gray-500 truncate" title={address}>{address}</p>
{:else}
<p class="mt-1 text-xs text-gray-400">{lat}, {lon}</p>
{/if}
</div>