// Facility floor-map blueprint config, read from the settings table so each // site instance (ADR-004) renders its own floor plan instead of a hardcoded // one. Keys: map_blueprint_light, map_blueprint_dark, map_width, map_height. // Missing keys fall back to the generic placeholder so a fresh or offline // install still renders; each site uploads its own blueprint in Settings. import { reactive } from 'vue' import { settingsApi } from '../api' import { withBase } from '../utils/basePath' // Fallback defaults - match the seeded map_blueprint_* setting defaults. const DEFAULTS = { blueprintLight: '/static/images/floorplan-placeholder.svg', blueprintDark: '/static/images/floorplan-placeholder.svg', width: 3300, height: 2550 } // Shared reactive config. Import as `state` to read width/height/blueprint. export const state = reactive({ ...DEFAULTS, loaded: false }) let inflight = null function applySetting(key, value) { if (value === null || value === undefined || value === '') return if (key === 'map_blueprint_light') state.blueprintLight = value else if (key === 'map_blueprint_dark') state.blueprintDark = value else if (key === 'map_width') { const n = parseInt(value, 10) if (!isNaN(n) && n > 0) state.width = n } else if (key === 'map_height') { const n = parseInt(value, 10) if (!isNaN(n) && n > 0) state.height = n } } function fetchConfig() { inflight = settingsApi.list({ category: 'map' }) .then(({ data }) => { ;(data.data || []).forEach(s => applySetting(s.key, s.value)) state.loaded = true }) .catch(() => { state.loaded = true }) .finally(() => { inflight = null }) return inflight } // Fetch the map config once (shared across all map components). Returns a // promise that resolves when state is populated, so a caller can await it // before initializing a Leaflet map that needs the dimensions. export function loadMapConfig() { if (state.loaded) return Promise.resolve() if (inflight) return inflight return fetchConfig() } // Re-read config from the server after a map setting changes. export function reloadMapConfig() { return fetchConfig() } // Blueprint image URL for the given theme ('light' | 'dark'). export function blueprintUrlFor(theme) { return withBase(theme === 'light' ? state.blueprintLight : state.blueprintDark) } export function useMapConfig() { loadMapConfig() return { state, blueprintUrlFor } }