fix(mental-health): crisis card no longer sends AT/CH users DE-only numbers

The PHQ-9 item-9 crisis card routed every "de" locale to the Germany-only
TelefonSeelsorge freephone lines. Those numbers don't connect from Austria
or Switzerland, so a Swiss or Austrian user in crisis was shown dead numbers
first on the one surface where that costs the most.

Add dedicated Austria (Telefonseelsorge 142) and Switzerland (Die
Dargebotene Hand 143) resource sets. `User.locale` only ever stores a bare
short code today, so an unqualified "de" now resolves to a combined
DE/AT/CH set (112 first, then every country's own line) instead of
defaulting to Germany; a region-qualified tag resolves to the exact country
when one is available.
This commit is contained in:
Marc-André Bombeck committed 2026-07-17 23:12:12 +02:00
1 parent 8c0b200a5b
commit cffebd78db
7 files changed
+84 -1

No files matched your search

+48 -1
View File
@@ -49,6 +49,45 @@ const DE: CrisisResourceSet = {
],
};
/** Austria (at) — Telefonseelsorge Österreich + acute emergency. */
const AT: CrisisResourceSet = {
emergencyNumber: "112",
resources: [
{ id: "telefonSeelsorgeAt", contacts: ["142", "telefonseelsorge.at"] },
{ id: "findahelpline", contacts: ["findahelpline.com"] },
],
};
/** Switzerland (ch) — Die Dargebotene Hand + acute emergency. */
const CH: CrisisResourceSet = {
emergencyNumber: "112",
resources: [
{ id: "dargeboteneHand", contacts: ["143", "143.ch"] },
{ id: "findahelpline", contacts: ["findahelpline.com"] },
],
};
/**
* Combined DE/AT/CH set — used when the locale is the bare "de" code with no
* region hint. `User.locale` in this app is a short code ("de"/"en"/…), so a
* de-AT or de-CH self-hoster is otherwise indistinguishable from a de-DE one.
* Serving the Germany-only freephone numbers to them left a Swiss or
* Austrian user in crisis staring at numbers that don't connect from their
* country. Leads with 112 (works across all three), then every country's
* own line grouped together so nothing here is presented as DE-only.
*/
const DE_AT_CH: CrisisResourceSet = {
emergencyNumber: "112",
resources: [
// Country-specific lines first, each set's own `findahelpline` entry
// dropped so the worldwide directory appears exactly once, at the end.
...DE.resources.filter((r) => r.id !== "findahelpline"),
...AT.resources.filter((r) => r.id !== "findahelpline"),
...CH.resources.filter((r) => r.id !== "findahelpline"),
{ id: "findahelpline", contacts: ["findahelpline.com"] },
],
};
/** United States (en-US region hint) — 988 + Crisis Text Line. */
const US: CrisisResourceSet = {
emergencyNumber: "911",
@@ -63,12 +102,20 @@ const US: CrisisResourceSet = {
* Resolve a crisis-resource set from the user's locale. Region detection is
* coarse (locale prefix) and defaults to the international set — the goal is to
* always surface SOMETHING actionable, never to be exhaustive.
*
* A region-qualified tag ("de-AT", "de_CH", …) resolves to the exact country
* set when the caller has one to give us. `User.locale` today only ever
* stores the bare short code, so in practice every "de" hits the DE_AT_CH
* branch below — that is the safe default for an unqualified "de": never
* assume Germany when the region is unknown.
*/
export function crisisResourcesForLocale(
locale: string | null | undefined,
): CrisisResourceSet {
const lc = (locale ?? "").toLowerCase();
if (lc.startsWith("de")) return DE;
if (lc === "de-at" || lc === "de_at" || lc === "at") return AT;
if (lc === "de-ch" || lc === "de_ch" || lc === "ch") return CH;
if (lc.startsWith("de")) return DE_AT_CH;
if (lc === "en-us" || lc.startsWith("en_us") || lc === "us") return US;
return INTERNATIONAL;
}