doxa-maps/plugin-designs/regions-dashboard/country-poster-sections.vue
Doxa Maps edff06b96a Regions: a third view, Country Posters, with one collapsible poster section per region
The view places the library's <dxm-poster-section type="country"> once per region the poster data files its
countries under, in the dashboard's region order, starting shut, in the page's locale. Rebuilt regions-dashboard,
then the tree (the new leaf page) and SRI.
2026-10-02 08:02:55 +00:00

66 lines
3.5 KiB
Vue

<script setup>
/**
* @description Country posters by region: one collapsible poster section per region (the library's <dxm-poster-section>), the Regions dashboard's third view.
*
* country-poster-sections.vue — the Regions dashboard's THIRD view, "Country Posters", beside the regions list and the
* region dashboards. One <dxm-poster-section type="country"> per region, collapsible and starting shut, in the page's
* locale.
*
* ★ THE ELEMENT IS THE LIBRARY'S (library/elements/posterSectionElement.js): the same section, cards and print options as
* the Country Posters wall. This bundle only registers it (a second registration on one page is a no-op) and places it.
*
* ★ THE SECTIONS ARE THE REGIONS THE POSTERS ARE FILED UNDER. The country type groups its cards by the poster data's own
* region (library/data/country-posters.json), so the list of sections comes from that same data, in the dashboard's
* fixed region order (REGION_ORDER). That way every country with a poster lands in exactly one section; a country the
* data files under no WAGF region gets the type's "Other" section instead of disappearing. The scope keys go through
* the type's own regionKey, so this page and the element can never spell a region two ways.
*/
import { computed, h, inject, ref } from 'vue'
import { registerPosterSectionElement } from '@map/elements/posterSectionElement.js'
import { regionKey } from '@map/components/poster/types/countryPosterType.js'
import posterData from '@map/data/country-posters.json'
import { REGION_ORDER } from '@map/colors/wagf-region.js'
import { resolveAssetsBase } from '@map/utils/embedBase.js'
import { getRuntimeLocale, detectLocale } from '@map/i18n/index.js'
import { useShadowStyles } from '@map/composables/useShadowStyles.js'
registerPosterSectionElement()
const profileConfig = inject('profileConfig', ref(null))
const cfg = computed(() => profileConfig.value || {})
const locale = computed(() => cfg.value.locale || cfg.value.lang || cfg.value.languageCode || getRuntimeLocale() || detectLocale() || 'en')
// The people-groups service the Regions list prints from (regions-list.vue's prayBaseUrl), so a section's prayer list
// and cards come from the same records as the list's own country posters.
const apiBase = computed(() => cfg.value.prayBaseUrl || cfg.value.apiBaseUrl || 'https://pray.doxa.life')
const scopes = computed(() => {
const inData = new Set((posterData.countries || []).map((c) => regionKey(c.region)))
const ordered = REGION_ORDER.map(regionKey).filter((k) => inData.has(k))
return [...ordered, ...[...inData].filter((k) => !ordered.includes(k)).sort()]
})
const section = (scope) => h('dxm-poster-section', {
key: scope,
type: 'country',
scope,
locale: locale.value,
collapsed: '',
'assets-base': resolveAssetsBase(cfg.value),
'api-base-url': apiBase.value,
...(cfg.value.isDark === true ? { 'is-dark': '' } : {}),
})
const Page = () => h('div', { class: 'cps' }, h('div', { class: 'cps__inner' }, scopes.value.map(section)))
useShadowStyles(
// The pane gives this element its whole box; the page scrolls here, and the sections stack in it.
':host{ display:block; height:100%; }' +
'.cps{ height:100%; overflow-y:auto; -webkit-overflow-scrolling:touch; box-sizing:border-box; padding:16px 12px 32px; }' +
'.cps__inner{ max-width:1180px; margin:0 auto; display:flex; flex-direction:column; gap:12px; }' +
'.cps__inner > *{ display:block; }',
'country-poster-sections'
)
</script>
<template>
<Page />
</template>