* replace country pages with region dashboards - move /countries to /regions, with 301 redirects from the old URLs in every locale - add a region dashboard: a map of the region's countries with pins coloured by prayer coverage, headline figures, and prayer, adoption and engagement progress against the DOXA goals, plus a per-country table - roll up progress stats per country and region in the shared summary and serve them from /api/regions - frame region maps with antimeridian-aware bounds - add Regions to the hamburger menu and translate the new strings in all eight locales * put each region on the regions index in a card with a header band The region name links to its dashboard with the site's chevron icon, and the people-group and country counts sit centred beside it on a brand-green header; the country list is the padded white card body.
69 lines
2.8 KiB
Vue
69 lines
2.8 KiB
Vue
<script setup lang="ts">
|
|
// Per-country page body: a map that highlights the country and plots its
|
|
// people groups (plus surrounding ones, muted), alongside the people-group list
|
|
// locked to this country. The summary (name, code, count, region, map
|
|
// center/zoom) comes from /api/regions via the /regions/[slug] page.
|
|
|
|
import { buildUupgListTranslations } from '~/utils/uupgListTranslations'
|
|
import { regionSlug, type CountrySummary } from '~~/config/countries-meta'
|
|
|
|
const props = defineProps<{ country: CountrySummary }>()
|
|
|
|
const { t, locale } = useI18n()
|
|
const localePath = useLocalePath()
|
|
|
|
const translations = computed(() => buildUupgListTranslations(t))
|
|
|
|
const regionLink = computed(() => localePath(`/regions/${regionSlug(props.country.region.value)}`))
|
|
const regionLabel = computed(() => props.country.region.label || t('Other'))
|
|
|
|
// Map note. Placeholders are substituted manually with %count%/%country%
|
|
// tokens rather than vue-i18n's {0}/{1} slots: vue-i18n empties brace slots
|
|
// when the key resolves with no args (the English source), and leaves them
|
|
// literal when the key is missing (untranslated locales fall back to the
|
|
// English source) — neither path interpolates correctly. Non-brace tokens are
|
|
// passed through untouched in every locale, so a single manual replace works
|
|
// for English now and for Weblate translations later (which keep the tokens).
|
|
const mapNote = computed(() =>
|
|
t('There are %count% people groups in %country%. Check the map for the people groups on the border of this country as well.')
|
|
.replace('%count%', String(props.country.count))
|
|
.replace('%country%', props.country.name)
|
|
)
|
|
</script>
|
|
|
|
<template>
|
|
<div class="container page-content uupgs-page stack stack--3xl">
|
|
<div class="stack stack--xs text-center">
|
|
<NuxtLink class="light-link" :to="localePath('/regions')">← {{ t('All Regions') }}</NuxtLink>
|
|
<h1 class="highlight" data-highlight-last>{{ country.name }}</h1>
|
|
<p class="color-brand-lighter">
|
|
{{ country.count }} {{ t('People Groups') }} ·
|
|
<NuxtLink class="light-link" :to="regionLink">{{ regionLabel }}</NuxtLink>
|
|
</p>
|
|
</div>
|
|
|
|
<div class="stack stack--sm">
|
|
<p class="country-map-note | text-center color-primary font-weight-bold">
|
|
{{ mapNote }}
|
|
</p>
|
|
<ClientOnly>
|
|
<CountryMap
|
|
:country-codes="[country.code]"
|
|
:center="country.center"
|
|
:zoom="country.zoom"
|
|
:language-code="locale"
|
|
:research-url="localePath('/research') + '/'"
|
|
class="rounded-xlg"
|
|
/>
|
|
</ClientOnly>
|
|
</div>
|
|
|
|
<UupgsList
|
|
:language-code="locale"
|
|
:research-url="localePath('/research') + '/'"
|
|
:t="translations"
|
|
:lock-country-code="country.code"
|
|
hide-see-all-link
|
|
/>
|
|
</div>
|
|
</template>
|