2023-09-12 09:15:28 +00:00
|
|
|
<script setup lang="ts">
|
|
|
|
import { renderOsmTag } from "facilmap-utils";
|
2023-11-06 02:22:33 +00:00
|
|
|
import type { FindOnMapResult, Point, SearchResult, Type } from "facilmap-types";
|
2023-11-01 18:45:16 +00:00
|
|
|
import Icon from "./ui/icon.vue";
|
2023-11-02 14:14:05 +00:00
|
|
|
import type { FileResult } from "../utils/files";
|
2023-11-08 20:31:03 +00:00
|
|
|
import { isFileResult, isMarkerResult } from "../utils/search";
|
|
|
|
import { searchResultsToLinesWithTags, searchResultsToMarkersWithTags } from "../utils/add";
|
2023-11-06 02:22:33 +00:00
|
|
|
import { getZoomDestinationForSearchResult } from "../utils/zoom";
|
2023-11-01 18:45:16 +00:00
|
|
|
import Coordinates from "./ui/coordinates.vue";
|
2023-11-08 20:31:03 +00:00
|
|
|
import { computed } from "vue";
|
2023-11-06 02:22:33 +00:00
|
|
|
import UseAsDropdown from "./ui/use-as-dropdown.vue";
|
|
|
|
import ZoomToObjectButton from "./ui/zoom-to-object-button.vue";
|
2023-11-11 07:01:40 +00:00
|
|
|
import type { RouteDestination } from "./facil-map-context-provider/route-form-tab-context";
|
2023-11-08 20:31:03 +00:00
|
|
|
import AddToMapDropdown from "./ui/add-to-map-dropdown.vue";
|
2023-11-01 18:45:16 +00:00
|
|
|
|
|
|
|
const props = withDefaults(defineProps<{
|
|
|
|
result: SearchResult | FileResult;
|
|
|
|
showBackButton?: boolean;
|
2023-11-06 02:22:33 +00:00
|
|
|
/** If specified, will be passed to the route form as suggestions when using the "Use as" menu */
|
|
|
|
searchResults?: SearchResult[];
|
|
|
|
/** If specified, will be passed to the route form as suggestions when using the "Use as" menu */
|
|
|
|
mapResults?: FindOnMapResult[];
|
2023-11-01 18:45:16 +00:00
|
|
|
}>(), {
|
2023-11-08 20:31:03 +00:00
|
|
|
showBackButton: false
|
2023-11-01 18:45:16 +00:00
|
|
|
});
|
|
|
|
|
2023-11-06 02:22:33 +00:00
|
|
|
const emit = defineEmits<{
|
|
|
|
back: [];
|
|
|
|
"add-to-map": [type: Type];
|
|
|
|
}>();
|
|
|
|
|
2023-11-01 18:45:16 +00:00
|
|
|
const isMarker = computed(() => isMarkerResult(props.result));
|
|
|
|
|
2023-11-06 02:22:33 +00:00
|
|
|
const zoomDestination = computed(() => getZoomDestinationForSearchResult(props.result));
|
|
|
|
|
|
|
|
const routeDestination = computed<RouteDestination | undefined>(() => {
|
|
|
|
if (isFileResult(props.result)) {
|
|
|
|
if (props.result.lat != null && props.result.lon != null) {
|
|
|
|
return { query: `${props.result.lat},${props.result.lon}` };
|
|
|
|
} else if (props.result.geojson?.type === "Point") {
|
|
|
|
return { query: `${props.result.geojson.coordinates[1]},${props.result.geojson.coordinates[0]}` };
|
|
|
|
} else {
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return {
|
|
|
|
query: props.result.short_name,
|
|
|
|
searchSuggestions: (props.searchResults || props.mapResults) ? props.searchResults : [props.result],
|
|
|
|
mapSuggestions: props.mapResults,
|
|
|
|
selectedSuggestion: props.result
|
|
|
|
};
|
|
|
|
}
|
|
|
|
});
|
2023-11-08 20:31:03 +00:00
|
|
|
|
|
|
|
const markersWithTags = computed(() => searchResultsToMarkersWithTags([props.result]));
|
|
|
|
const linesWithTags = computed(() => searchResultsToLinesWithTags([props.result]));
|
2023-09-12 09:15:28 +00:00
|
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
|
|
|
<div class="fm-search-result-info" v-if="result">
|
2024-02-25 20:12:50 +00:00
|
|
|
<h2 class="text-break">
|
2023-11-06 02:22:33 +00:00
|
|
|
<a v-if="showBackButton" href="javascript:" @click="emit('back')"><Icon icon="arrow-left"></Icon></a>
|
2023-09-12 09:15:28 +00:00
|
|
|
{{result.short_name}}
|
|
|
|
</h2>
|
2023-11-16 18:42:50 +00:00
|
|
|
<dl class="fm-search-box-collapse-point fm-search-box-dl">
|
2023-11-01 18:45:16 +00:00
|
|
|
<template v-if="result.type">
|
|
|
|
<dt>Type</dt>
|
2024-02-25 20:12:50 +00:00
|
|
|
<dd class="text-break">{{result.type}}</dd>
|
2023-11-01 18:45:16 +00:00
|
|
|
</template>
|
2023-09-12 09:15:28 +00:00
|
|
|
|
2023-11-01 18:45:16 +00:00
|
|
|
<template v-if="result.address">
|
|
|
|
<dt>Address</dt>
|
2024-02-25 20:12:50 +00:00
|
|
|
<dd class="text-break">{{result.address}}</dd>
|
2023-11-01 18:45:16 +00:00
|
|
|
</template>
|
2023-09-12 09:15:28 +00:00
|
|
|
|
2023-11-01 18:45:16 +00:00
|
|
|
<template v-if="result.type != 'coordinates' && result.lat != null && result.lon != null">
|
|
|
|
<dt>Coordinates</dt>
|
|
|
|
<dd><Coordinates :point="result as Point"></Coordinates></dd>
|
|
|
|
</template>
|
2023-09-12 09:15:28 +00:00
|
|
|
|
2023-11-01 18:45:16 +00:00
|
|
|
<template v-if="result.elevation != null">
|
|
|
|
<dt>Elevation</dt>
|
2023-11-06 02:22:33 +00:00
|
|
|
<dd>{{result.elevation}} m</dd>
|
2023-11-01 18:45:16 +00:00
|
|
|
</template>
|
2023-09-12 09:15:28 +00:00
|
|
|
|
2023-11-01 18:45:16 +00:00
|
|
|
<template v-for="(value, key) in result.extratags" :key="key">
|
2023-09-12 09:15:28 +00:00
|
|
|
<dt>{{key}}</dt>
|
2024-02-25 20:12:50 +00:00
|
|
|
<dd class="text-break" v-html="renderOsmTag(key, value)"></dd>
|
2021-04-04 21:07:12 +00:00
|
|
|
</template>
|
2023-09-12 09:15:28 +00:00
|
|
|
</dl>
|
|
|
|
|
2023-11-11 07:01:40 +00:00
|
|
|
<div class="btn-toolbar">
|
|
|
|
<ZoomToObjectButton
|
|
|
|
v-if="zoomDestination"
|
|
|
|
label="search result"
|
|
|
|
size="sm"
|
|
|
|
:destination="zoomDestination"
|
|
|
|
></ZoomToObjectButton>
|
|
|
|
|
|
|
|
<AddToMapDropdown
|
|
|
|
:markers="markersWithTags"
|
|
|
|
:lines="linesWithTags"
|
|
|
|
size="sm"
|
|
|
|
isSingle
|
|
|
|
></AddToMapDropdown>
|
|
|
|
|
|
|
|
<UseAsDropdown
|
|
|
|
v-if="isMarker && routeDestination"
|
|
|
|
size="sm"
|
|
|
|
:destination="routeDestination"
|
|
|
|
></UseAsDropdown>
|
2023-10-30 00:14:54 +00:00
|
|
|
</div>
|
2023-09-12 09:15:28 +00:00
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<style lang="scss">
|
|
|
|
.fm-search-result-info {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
min-height: 0;
|
|
|
|
|
|
|
|
.fm-search-box-collapse-point {
|
|
|
|
min-height: 1.5em;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|