Enhance frontend components and introduce new features
- Added a custom light theme in app.css to match the dark theme's palette. - Introduced AdminBreadcrumbs component for improved navigation in admin pages. - Implemented Skeleton component for loading states in various views. - Added ToastContainer for displaying notifications and alerts. - Enhanced MapView with loading indicators and improved marker handling. - Updated MapCoordsDisplay to allow copying of shareable links. - Refactored MapControls and MapContextMenu for better usability. - Improved user experience in profile and admin pages with loading states and search functionality.
This commit is contained in:
@@ -1,5 +1,19 @@
|
||||
<template>
|
||||
<div class="relative h-full w-full" @click="(e: MouseEvent) => e.button === 0 && mapLogic.closeContextMenus()">
|
||||
<div
|
||||
v-if="!mapReady"
|
||||
class="absolute inset-0 z-[400] flex flex-col items-center justify-center gap-6 bg-base-200/95 p-8"
|
||||
aria-busy="true"
|
||||
aria-label="Loading map"
|
||||
>
|
||||
<Skeleton class="h-12 w-48" />
|
||||
<div class="flex gap-3">
|
||||
<Skeleton class="h-10 w-24" />
|
||||
<Skeleton class="h-10 w-32" />
|
||||
<Skeleton class="h-10 w-28" />
|
||||
</div>
|
||||
<Skeleton class="h-64 w-72 max-w-full" />
|
||||
</div>
|
||||
<div
|
||||
v-if="mapsLoaded && maps.length === 0"
|
||||
class="absolute inset-0 z-[500] flex flex-col items-center justify-center gap-4 bg-base-200/90 p-6"
|
||||
@@ -14,9 +28,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<div ref="mapRef" class="map h-full w-full" />
|
||||
<MapMapCoordsDisplay
|
||||
:mapid="mapLogic.state.mapid"
|
||||
:display-coords="mapLogic.state.displayCoords"
|
||||
<MapCoordsDisplay
|
||||
:mapid="mapLogic.state.mapid.value"
|
||||
:display-coords="mapLogic.state.displayCoords.value"
|
||||
/>
|
||||
<MapControls
|
||||
:show-grid-coordinates="mapLogic.state.showGridCoordinates.value"
|
||||
@@ -38,16 +52,16 @@
|
||||
@zoom-out="mapLogic.zoomOutControl(leafletMap)"
|
||||
@reset-view="mapLogic.resetView(leafletMap)"
|
||||
/>
|
||||
<MapMapContextMenu
|
||||
<MapContextMenu
|
||||
:context-menu="mapLogic.contextMenu"
|
||||
@wipe-tile="onWipeTile"
|
||||
@rewrite-coords="onRewriteCoords"
|
||||
@hide-marker="onHideMarker"
|
||||
/>
|
||||
<MapMapCoordSetModal
|
||||
:coord-set-from="mapLogic.coordSetFrom"
|
||||
:coord-set="mapLogic.coordSet"
|
||||
:open="mapLogic.coordSetModalOpen"
|
||||
<MapCoordSetModal
|
||||
:coord-set-from="mapLogic.coordSetFrom.value"
|
||||
:coord-set="mapLogic.coordSet.value"
|
||||
:open="mapLogic.coordSetModalOpen.value"
|
||||
@close="mapLogic.closeCoordSetModal()"
|
||||
@submit="onSubmitCoordSet"
|
||||
/>
|
||||
@@ -56,6 +70,9 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import MapControls from '~/components/map/MapControls.vue'
|
||||
import MapCoordsDisplay from '~/components/map/MapCoordsDisplay.vue'
|
||||
import MapContextMenu from '~/components/map/MapContextMenu.vue'
|
||||
import MapCoordSetModal from '~/components/map/MapCoordSetModal.vue'
|
||||
import { HnHDefaultZoom, HnHMaxZoom, HnHMinZoom, TileSize } from '~/lib/LeafletCustomTypes'
|
||||
import { initLeafletMap, type MapInitResult } from '~/composables/useMapInit'
|
||||
import { startMapUpdates, type UseMapUpdatesReturn } from '~/composables/useMapUpdates'
|
||||
@@ -77,7 +94,16 @@ const props = withDefaults(
|
||||
const mapRef = ref<HTMLElement | null>(null)
|
||||
const api = useMapApi()
|
||||
const mapLogic = useMapLogic()
|
||||
const { resolvePath } = useAppPaths()
|
||||
|
||||
/** Fallback marker icon (simple pin) when the real icon image fails to load. */
|
||||
const FALLBACK_MARKER_ICON =
|
||||
'data:image/svg+xml,' +
|
||||
encodeURIComponent(
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32"><path fill="%236366f1" stroke="%234f46e5" stroke-width="1.5" d="M16 4c-4 0-7 3-7 7 0 5 7 13 7 13s7-8 7-13c0-4-3-7-7-7z"/><circle cx="16" cy="11" r="3" fill="white"/></svg>'
|
||||
)
|
||||
|
||||
const mapReady = ref(false)
|
||||
const maps = ref<MapInfo[]>([])
|
||||
const mapsLoaded = ref(false)
|
||||
const questGivers = ref<Array<{ id: number; name: string }>>([])
|
||||
@@ -203,6 +229,8 @@ onMounted(async () => {
|
||||
getTrackingCharacterId: () => mapLogic.state.trackingCharacterId.value,
|
||||
setTrackingCharacterId: (id: number) => { mapLogic.state.trackingCharacterId.value = id },
|
||||
onMarkerContextMenu: mapLogic.openMarkerContextMenu,
|
||||
resolveIconUrl: (path) => resolvePath(path),
|
||||
fallbackIconUrl: FALLBACK_MARKER_ICON,
|
||||
})
|
||||
|
||||
updatesHandle = startMapUpdates({
|
||||
@@ -245,6 +273,7 @@ onMounted(async () => {
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
if (leafletMap) leafletMap.invalidateSize()
|
||||
mapReady.value = true
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user