From 4f5136211c616aef57ce3ca69b37a1d702f863ee Mon Sep 17 00:00:00 2001 From: doxa-maps-88655c70 <88627970+doxa-maps-88655c70@users.noreply.github.com> Date: Thu, 24 Sep 2026 16:54:14 +0000 Subject: [PATCH 01/10] Show the groups with nothing found and nobody praying MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 213 people groups have no Scripture, audio, film, Bible video or Door43 resource in any pool checked AND zero people praying on doxa.life's counter — 4.67M people, largest Songhai (BFA, 259,000), Kuka (TCD, 250,000), Kimr (SDN, 221,000). That intersection is the sharpest thing in the data and nothing surfaced it. The gap sheet gains a fourth tab whose rows are links straight to each group's prayer page, so the answer to "nobody is praying" is one tap, not a search. The sheet says plainly that "nobody praying" means zero on doxa.life's counter, not a claim nobody in the world prays for them. Two fixes found while proving it: the tab is built from the lazily fetched prayer index, so opening the gap list now loads that index — without it the tab only ever appeared if you had clicked a pin first. And the new branch opened its own v-if chain, which left the old "largest groups" list rendering underneath it, 80 rows where 40 belong. --- .../gospel-resources/resources-map.vue | 60 +++++++++++++++++-- .../gospel-resources/charts/index.html | 2 +- .../gospel-resources/data-tables/index.html | 2 +- .../gospel-dashboard/index.html | 2 +- .../gospel-resources/gospel-resources.js | 40 ++++++------- .../resources-list/index.html | 2 +- .../gospel-resources/resources-map/index.html | 2 +- public/doxa-maps/index.html | 2 +- public/doxa-maps/manifest.json | 12 ++-- 9 files changed, 87 insertions(+), 37 deletions(-) diff --git a/plugin-designs/gospel-resources/resources-map.vue b/plugin-designs/gospel-resources/resources-map.vue index a69c82587..a4fadb9c3 100644 --- a/plugin-designs/gospel-resources/resources-map.vue +++ b/plugin-designs/gospel-resources/resources-map.vue @@ -308,6 +308,27 @@ const gapList = computed(() => { // Papua New Guinea has 469 groups with nothing but only 2.2M people, China has 125 groups // and 150.3M. Ranking by either one alone hides the other question. const gapBy = ref('groups') +// THE SHARPEST INTERSECTION THIS DATA HOLDS: no gospel resource found in any pool checked, +// AND nobody praying. 213 people groups, 4.67M people. Every other view here ends at "this +// group has nothing"; this one ends at a page where the reader can do something about it, +// which is why the rows are links rather than fly-to buttons. +// +// "NOBODY PRAYING" MEANS ZERO ON DOXA.LIFE'S COUNTER. It is not a claim that nobody in the +// world prays for these people — an unknowable thing — and the sheet says so rather than +// letting the number imply it. +const gapNoPrayer = computed(() => { + if (!showGapList.value) return [] + const out = [] + for (let i = 0; i < pinRows.value.length; i++) { + const r = pinRows.value[i] + if (r[6] !== 0) continue + const e = prayIndex.value[prayKey(r[0], r[3])] + if (!e || e.praying > 0) continue + out.push({ i, name: r[0], iso3: r[3], code: r[4], pop: r[5], url: e.u }) + } + return out.sort((a, b) => b.pop - a.pop).slice(0, 40) +}) + // A THIRD AXIS: the RATE. The country tab ranks by how many groups a country holds and // shows population beside it; neither answers "what share of this place is unreached". // Measured, the three disagree completely and each is somebody's question: @@ -346,7 +367,15 @@ const gapCountries = computed(() => { .slice(0, 40) }) -function openGapList() { showGapList.value = true; selected.value = null; selectedGroup.value = null } +function openGapList() { + // The prayer index is fetched lazily and the "Nobody praying" tab is built from it, so + // opening this list without having first clicked a pin left the tab hidden entirely — + // the view existed and was unreachable unless you happened to take the long way round. + ensurePeopleGroups() + showGapList.value = true + selected.value = null + selectedGroup.value = null +} function closeGapList() { showGapList.value = false } // Fly first, THEN open: openPin sets `selected`, which swaps the sheet away from this list, // so doing it the other way round loses the map movement behind a re-render. @@ -905,7 +934,7 @@ useShadowStyles( 'margin-bottom:6px;border-radius:8px;' + 'border:1px solid rgba(0,0,0,.10);background:rgba(0,0,0,.02);color:inherit;font:inherit}' + '.is-dark .gm-pg{border-color:rgba(255,255,255,.10);background:rgba(255,255,255,.03)}' + - '.gm-pg-btn{cursor:pointer}' + + '.gm-pg-btn{cursor:pointer;text-decoration:none;color:inherit}' + // The drill-in control on a resource row: a bare button that inherits the shell's // look, so the row still reads as one tap-target for the name + language line. '.gm-pg-open{display:block;width:100%;text-align:left;padding:0;margin:0;border:0;' + @@ -1066,13 +1095,21 @@ useShadowStyles(