Files
hnh-map/frontend-nuxt/components/map/MapBookmarks.vue
Nikolay Tatarinov 52c34ef8f2 Enhance map functionality with bookmark features and UI improvements
- Introduced a new MapBookmarkNameModal for adding and editing bookmarks.
- Updated MapView to manage selected markers for bookmarking and handle bookmark name submissions.
- Enhanced MapContextMenu with an option to add markers to bookmarks.
- Improved MapBookmarks component to support editing bookmark names and adding selected markers.
- Refactored MapControls and MapControlsContent to integrate selected marker functionality for bookmarks.
- Updated useMapBookmarks composable to include bookmark updating logic.
- Removed unused grid coordinates toggle from the UI for a cleaner interface.
2026-03-03 20:05:42 +03:00

131 lines
4.4 KiB
Vue
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.
<template>
<section class="flex flex-col gap-2">
<h3 class="text-xs font-semibold uppercase tracking-wider text-base-content/70 flex items-center gap-1.5">
<icons-icon-bookmark class="size-3.5 opacity-80" aria-hidden="true" />
Saved locations
</h3>
<div class="flex flex-col gap-1 max-h-40 overflow-y-auto">
<template v-if="bookmarks.length === 0">
<p class="text-xs text-base-content/60 py-1">No saved locations.</p>
</template>
<template v-else>
<div
v-for="b in bookmarks"
:key="b.id"
class="flex items-center gap-2 group rounded-lg hover:bg-base-200/50 px-2 py-1.5 -mx-2"
>
<button
type="button"
class="btn btn-ghost btn-xs flex-1 min-w-0 justify-start text-left truncate font-normal"
:title="`Go to ${b.name}`"
@click="onGoTo(b)"
>
<span class="truncate">{{ b.name }}</span>
</button>
<button
v-if="openBookmarkModal"
type="button"
class="btn btn-ghost btn-xs btn-square shrink-0 opacity-70 hover:opacity-100"
aria-label="Edit bookmark name"
@click="openBookmarkModal(b.name, 'Edit bookmark name', { kind: 'edit', editId: b.id })"
>
<icons-icon-pencil class="size-3.5" />
</button>
<button
type="button"
class="btn btn-ghost btn-xs btn-square shrink-0 opacity-70 hover:opacity-100 hover:text-error"
aria-label="Remove bookmark"
@click="onRemove(b.id)"
>
×
</button>
</div>
</template>
</div>
<div v-if="openBookmarkModal" class="flex flex-col gap-1">
<button
type="button"
class="btn btn-primary btn-sm w-full"
:class="touchFriendly ? 'min-h-11' : ''"
:disabled="!selectedMarkerForBookmark"
title="Add selected quest giver as bookmark"
@click="onAddSelectedMarker"
>
<icons-icon-plus class="size-4" />
Add selected marker
</button>
<button
type="button"
class="btn btn-outline btn-sm w-full"
:class="touchFriendly ? 'min-h-11' : ''"
:disabled="!canAddCurrent"
title="Save current map position"
@click="onAddCurrent"
>
<icons-icon-plus class="size-4" />
Add current location
</button>
</div>
</section>
</template>
<script setup lang="ts">
import type { MapInfo } from '~/types/api'
import { useMapBookmarks } from '~/composables/useMapBookmarks'
import { useMapNavigate } from '~/composables/useMapNavigate'
export type SelectedMarkerForBookmark = { mapId: number; x: number; y: number; name: string } | null
type BookmarkModalPayload =
| { kind: 'add'; mapId: number; x: number; y: number; zoom?: number }
| { kind: 'edit'; editId: string }
type OpenBookmarkModalFn = (defaultName: string, title: string, data: BookmarkModalPayload) => void
const props = withDefaults(
defineProps<{
maps: MapInfo[]
currentMapId: number | null
currentCoords: { x: number; y: number; z: number } | null
selectedMarkerForBookmark?: SelectedMarkerForBookmark
touchFriendly?: boolean
}>(),
{ selectedMarkerForBookmark: null, touchFriendly: false }
)
const { bookmarks, remove } = useMapBookmarks()
const { goToCoords } = useMapNavigate()
const openBookmarkModal = inject<OpenBookmarkModalFn>('openBookmarkModal')
const canAddCurrent = computed(
() =>
props.currentMapId != null &&
props.currentCoords != null &&
props.currentMapId >= 0
)
function onGoTo(b: { mapId: number; x: number; y: number; zoom?: number }) {
goToCoords(b.mapId, b.x, b.y, b.zoom)
}
function onRemove(id: string) {
remove(id)
}
function onAddSelectedMarker() {
const m = props.selectedMarkerForBookmark
if (!m || !openBookmarkModal) return
openBookmarkModal(m.name, 'Add bookmark', { kind: 'add', mapId: m.mapId, x: m.x, y: m.y })
}
function onAddCurrent() {
if (!canAddCurrent.value || !openBookmarkModal) return
const mapId = props.currentMapId!
const { x, y, z } = props.currentCoords!
openBookmarkModal(
`${props.maps.find((map) => map.ID === mapId)?.Name ?? `Map ${mapId}`} ${x}, ${y}`,
'Add bookmark',
{ kind: 'add', mapId, x, y, zoom: z }
)
}
</script>