* 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.
65 lines
2 KiB
Vue
65 lines
2 KiB
Vue
<script setup lang="ts">
|
|
// One route serves both the region dashboards (/regions/africa) and the
|
|
// per-country pages (/regions/india): the slug is matched against region slugs
|
|
// first, then country slugs. Both summaries come from /api/regions, which
|
|
// derives them from the prayer API — see config/countries-meta.ts.
|
|
|
|
import type { CountrySummary, RegionSummary } from '~~/config/countries-meta'
|
|
|
|
const route = useRoute()
|
|
const { t, locale } = useI18n()
|
|
|
|
const slug = computed(() => String(route.params.slug || ''))
|
|
|
|
const { data, refresh } = await useAsyncData(
|
|
`region-page-${slug.value}-${locale.value}`,
|
|
async () => {
|
|
const res = await $fetch<{ regions: RegionSummary[] }>('/api/regions', {
|
|
query: { lang: locale.value }
|
|
})
|
|
const region = res.regions.find(r => r.slug === slug.value) ?? null
|
|
const country: CountrySummary | null = region
|
|
? null
|
|
: res.regions.flatMap(r => r.countries).find(c => c.slug === slug.value) ?? null
|
|
return { region, country }
|
|
},
|
|
{ watch: [slug, locale] }
|
|
)
|
|
|
|
if (!data.value?.region && !data.value?.country) {
|
|
throw createError({ statusCode: 404, statusMessage: t('Page Not Found') })
|
|
}
|
|
|
|
// Prerendered dashboards carry build-time figures; refetch on the client so
|
|
// the progress shown is current.
|
|
onMounted(() => {
|
|
if (data.value?.region) refresh()
|
|
})
|
|
|
|
const title = computed(() => {
|
|
const region = data.value?.region
|
|
if (region) return region.label || t('Other')
|
|
return data.value?.country?.name ?? ''
|
|
})
|
|
const count = computed(() => data.value?.region?.count ?? data.value?.country?.count ?? 0)
|
|
|
|
useSeoMeta({
|
|
title: () => `${title.value} — Doxa`,
|
|
description: () => `${title.value}: ${count.value} ${t('People Groups')}`,
|
|
ogTitle: () => `${title.value} — Doxa`,
|
|
ogDescription: () => `${title.value}: ${count.value} ${t('People Groups')}`
|
|
})
|
|
|
|
useTextHighlight()
|
|
</script>
|
|
|
|
<template>
|
|
<RegionDetail
|
|
v-if="data?.region"
|
|
:region="data.region"
|
|
/>
|
|
<CountryDetail
|
|
v-else-if="data?.country"
|
|
:country="data.country"
|
|
/>
|
|
</template>
|