MapComplete/src/UI/Search/GeocodeResult.svelte

115 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 type { GeocodeResult } from "../../Logic/Search/GeocodingProvider"
import { GeocodingUtils } 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 Icon from "../Map/Icon.svelte"
import TagRenderingAnswer from "../Popup/TagRendering/TagRenderingAnswer.svelte"
import DefaultIcon from "../Map/DefaultIcon.svelte"
import type { MapProperties } from "../../Models/MapProperties"
import ThemeConfig from "../../Models/ThemeConfig/ThemeConfig"
import FeaturePropertiesStore from "../../Logic/FeatureSource/Actors/FeaturePropertiesStore"
import SearchState from "../../Logic/State/SearchState"
import ArrowUp from "@babeard/svelte-heroicons/mini/ArrowUp"
import { createEventDispatcher } from "svelte"
export let entry: GeocodeResult
export let state: {
mapProperties: MapProperties
theme?: ThemeConfig
featureProperties?: FeaturePropertiesStore
searchState: Partial<SearchState>
}
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]))
let dispatch = createEventDispatcher<{ select: GeocodeResult }>()
function select() {
dispatch("select", entry)
}
</script>
<button class="unstyled link-no-underline searchresult w-full" on:click={() => select()}>
<div class="flex w-full items-center gap-y-2 p-2">
{#if layer}
<div class="h-6 w-6">
<DefaultIcon {layer} properties={entry.feature.properties} />
</div>
{:else if entry.category}
<Icon
icon={GeocodingUtils.categoryToIcon[entry.category]}
clss="w-6 h-6 shrink-0"
color="#aaa"
/>
{/if}
<div class="flex w-full flex-col items-start pl-2">
<div class="flex w-full flex-wrap justify-between gap-x-2">
<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 items-center gap-x-1">
{#if $bearing && !$inView}
<ArrowUp
class="h-4 w-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 w-full justify-between">
{entry.description}
</div>
{/if}
</div>
</div>
</div>
</button>