feat(04-04): the destination resolver — two carriers, one validation, memory only
- resolve-destination.ts: reads ?dest= (URL, primary — the inline web_app-button carrier) then initData's start_param (the signed string, secondary — the direct-link/home-screen carrier), ONE slug validation, dest_ prefix stripped; resolves against the webview's own build-time @araharah/search copy; honest null for unknown ids; module-scope memory-only holder (GEO-03/D-07) - destination-card.ts: the confirmation + honest-unavailable cards, createElement/textContent only, existing theme classes (T-04-32) - webapp.ts: TelegramWebAppLike gains startParam, addToHomeScreen?, checkHomeScreenStatus? + HomeScreenStatus (Bot API 8.0+ members) - telegram-mock.ts: satisfies the extended contract in the same change (startParam initData wiring, homeScreenStatus, __homeScreenAdded) - strings.ts: 5 new copy fields in en+ms; web depends on @araharah/search - DP1-DP12 green (45/45 web suite), web:typecheck green
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* destination-card.ts — the ONBD-02 destination surface (D-11).
|
||||
* -------------------------------------------------------------
|
||||
* The webview's visible confirmation of a PRELOADED destination: the entry's
|
||||
* canonical NAME and its curated ADDRESS (the address VERBATIM from the
|
||||
* gazetteer — never the normalized form; matching normalizes, display does
|
||||
* not, MS 2039 display rule / RESEARCH Pitfall 3). The honest counterpart
|
||||
* renders when an id ARRIVED but does not resolve: "destination unavailable"
|
||||
* — never a blank map (Phase 3 D-09 anti-blank invariant), never a
|
||||
* fabricated coordinate (T-04-34).
|
||||
*
|
||||
* Built with createElement + textContent ONLY — an id-derived string never
|
||||
* reaches innerHTML (T-04-32). Composed from the theme's existing component
|
||||
* classes (.card / .card-header / .card-ref / .text-headline-md /
|
||||
* .text-body-md / .text-body-sm) exactly as web/src/ui/cards.ts does — no
|
||||
* new CSS, no off-token styling, no new screen: this is the Phase 3 card
|
||||
* stack's existing surface carrying a different card. Every string comes
|
||||
* from the strings module (COPY5 law).
|
||||
*/
|
||||
import type { GazetteerEntry } from "@araharah/search/src/types.ts";
|
||||
import { strings, type Locale } from "../i18n/strings.ts";
|
||||
|
||||
/** The destination confirmation card: register line, name headline, the
|
||||
* curated address verbatim. */
|
||||
export function buildDestinationCard(locale: Locale, entry: GazetteerEntry): HTMLElement {
|
||||
const card = document.createElement("div");
|
||||
card.className = "card";
|
||||
|
||||
const header = document.createElement("div");
|
||||
header.className = "card-header";
|
||||
const ref = document.createElement("span");
|
||||
ref.className = "card-ref";
|
||||
ref.textContent = strings[locale].destinationHeadline;
|
||||
header.appendChild(ref);
|
||||
|
||||
const headline = document.createElement("h2");
|
||||
headline.className = "text-headline-md";
|
||||
headline.textContent = entry.name;
|
||||
|
||||
const address = document.createElement("p");
|
||||
address.className = "text-body-sm";
|
||||
address.textContent = entry.address ?? "";
|
||||
|
||||
card.appendChild(header);
|
||||
card.appendChild(headline);
|
||||
card.appendChild(address);
|
||||
return card;
|
||||
}
|
||||
|
||||
/** The honest unavailable card: an id arrived and resolved to nothing.
|
||||
* The boot continues into the normal staged boot around it. */
|
||||
export function buildDestinationUnavailableCard(locale: Locale): HTMLElement {
|
||||
const card = document.createElement("div");
|
||||
card.className = "card";
|
||||
|
||||
const header = document.createElement("div");
|
||||
header.className = "card-header";
|
||||
const ref = document.createElement("span");
|
||||
ref.className = "card-ref";
|
||||
ref.textContent = strings[locale].destinationHeadline;
|
||||
header.appendChild(ref);
|
||||
|
||||
const headline = document.createElement("h2");
|
||||
headline.className = "text-headline-md";
|
||||
headline.textContent = strings[locale].destinationUnavailableHeadline;
|
||||
|
||||
const body = document.createElement("p");
|
||||
body.className = "text-body-md";
|
||||
body.textContent = strings[locale].destinationUnavailableBody;
|
||||
|
||||
card.appendChild(header);
|
||||
card.appendChild(headline);
|
||||
card.appendChild(body);
|
||||
return card;
|
||||
}
|
||||
Reference in New Issue
Block a user