MapComplete/src/UI/Search/GeocodeResult.svelte

101 lines
4 KiB
Svelte
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script lang="ts">
import { GeocodingUtils } from "../../Logic/Search/GeocodingProvider"
import type { GeocodeResult } from "../../Logic/Search/GeocodingProvider"
import { GeoOperations } from "../../Logic/GeoOperations"
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
import { UIEventSource } from "../../Logic/UIEventSource"
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig"
import { createEventDispatcher } from "svelte"
import type { SpecialVisualizationState } from "../SpecialVisualization"
import { BBox } from "../../Logic/BBox"
import ToSvelte from "../Base/ToSvelte.svelte"
import Icon from "../Map/Icon.svelte"
import TagRenderingAnswer from "../Popup/TagRendering/TagRenderingAnswer.svelte"
import ArrowUp from "@babeard/svelte-heroicons/mini/ArrowUp"
export let entry: GeocodeResult
export let state: SpecialVisualizationState
let layer: LayerConfig
let tags: UIEventSource<Record<string, string>>
let descriptionTr: TagRenderingConfig = undefined
if (entry.feature?.properties?.id) {
layer = state.theme.getMatchingLayer(entry.feature.properties)
tags = state.featureProperties.getStore(entry.feature.properties.id)
descriptionTr = layer?.tagRenderings?.find(tr => tr.labels.indexOf("description") >= 0)
}
let distance = state.mapProperties.location.mapD(l => GeoOperations.distanceBetween([l.lon, l.lat], [entry.lon, entry.lat]))
let bearing = state.mapProperties.location.mapD(l => GeoOperations.bearing([l.lon, l.lat], [entry.lon, entry.lat]))
let mapRotation = state.mapProperties.rotation
let inView = state.mapProperties.bounds.mapD(bounds => bounds.contains([entry.lon, entry.lat]))
function select() {
if (entry.boundingbox) {
const [lat0, lat1, lon0, lon1] = entry.boundingbox
state.mapProperties.bounds.set(
new BBox([
[lon0, lat0],
[lon1, lat1],
]).pad(0.01),
)
} else {
state.mapProperties.flyTo(entry.lon, entry.lat, GeocodingUtils.categoryToZoomLevel[entry.category] ?? 17)
}
if (entry.feature?.properties?.id) {
state.selectedElement.set(entry.feature)
}
state.userRelatedState.recentlyVisitedSearch.add(entry)
state.searchState.closeIfFullscreen()
}
</script>
<button class="unstyled w-full link-no-underline searchresult" on:click={() => select() }>
<div class="p-2 flex items-center w-full gap-y-2">
{#if layer}
<div class="h-6">
<ToSvelte construct={() => layer.defaultIcon(entry.feature.properties)?.SetClass("w-6 h-6")} />
</div>
{:else if entry.category}
<Icon icon={GeocodingUtils.categoryToIcon[entry.category]} clss="w-6 h-6 shrink-0" color="#aaa" />
{/if}
<div class="flex flex-col items-start pl-2 w-full">
<div class="flex flex-wrap gap-x-2 justify-between w-full">
<b class="nowrap">
{#if layer && $tags?.id}
<TagRenderingAnswer config={layer.title} selectedElement={entry.feature} {state} {tags} {layer} />
{:else}
{entry.display_name ?? entry.osm_id}
{/if}
</b>
{#if $distance > 50}
<div class="flex gap-x-1 items-center">
{#if $bearing && !$inView}
<ArrowUp class="w-4 h-4 shrink-0" style={`transform: rotate(${$bearing - $mapRotation}deg)`} />
{/if}
{#if $distance}
{GeoOperations.distanceToHuman($distance)}
{/if}
</div>
{/if}
</div>
<div class="flex flex-wrap gap-x-2">
{#if descriptionTr && tags}
<TagRenderingAnswer defaultSize="subtle" noIcons={true} config={descriptionTr} {tags} {state}
selectedElement={entry.feature} {layer} />
{/if}
{#if descriptionTr && tags && entry.description}
{/if}
{#if entry.description}
<div class="subtle flex justify-between w-full">
{entry.description}
</div>
{/if}
</div>
</div>
</div>
</button>