services/presentationModes.jsjavascript
/**
 * @typedef {object} PresentationMode
 * @property {string} key
 * @property {string} label
 * @property {string} path
 * @property {"landscape"|"portrait"} orientation
 * @property {?string} [contentFile]
 * @property {string[]} [contentFiles]
 */

/**
 * Single source of truth for the 3 presentation modes/sales apps. `key`
 * doubles as the valid `defaultMode` config value (config-schema.js) and as
 * the route path segment (see Routes.jsx, AppSelection.jsx). `contentFile`
 * is the JSON this mode's route loads via ContentProvider
 * (services/content.jsx); `null` means the page doesn't fetch any content
 * (yet). A mode can use `contentFiles` (array) instead of `contentFile`
 * (single string) when its content is split across several smaller files -
 * ContentProvider fetches all of them and merges the results into one
 * `content` object, so consumers still read e.g.
 * `content.valuePartnership.points` regardless of which file it came from.
 *
 * `orientation` is each app's fixed, content-driven physical orientation
 * (confirmed with the content team, not device-dependent - Rad Enablement is
 * portrait-only, everything else landscape) - consumed by Stage.jsx to pick
 * a landscape vs. portrait reference resolution for the whole-app scale
 * wrapper. `resolveModeForPath()` below is the one place that maps a route
 * to its mode - reused by Stage and GeneralPageTracking so they can never
 * disagree about which mode a given path belongs to.
 *
 * @type {PresentationMode[]}
 */
export const PRESENTATION_MODES = [
  {
    key: "value-partnership",
    label: "Value Partnerships",
    path: "/value-partnership",
    orientation: "landscape",
    // split so GlobePage's large marker dataset and PartnershipsPage's PPT
    // data don't have to be fetched/parsed by pages that don't need them
    contentFiles: [
      "/data/value-partnership-content.json",
      "/data/value-partnership-points.json",
      "/data/value-partnership-partnerships.json",
      "/data/value-partnership-globe-countries.json",
    ],
  },
  {
    key: "value-advisory-services",
    label: "Value Advisory Services",
    path: "/value-advisory-services",
    orientation: "landscape",
    contentFile: "/data/vas-content.json",
  },
  {
    key: "rad-enablement",
    label: "RadEnablement Services",
    path: "/rad-enablement",
    orientation: "portrait",
    contentFile: "/data/rad-content.json",
  },
];

/**
 * Resolves which PRESENTATION_MODES entry a route belongs to, or `null` for
 * a path that isn't any mode's route (currently just "/", the app selection
 * screen - always landscape, see Stage.jsx).
 *
 * @param {string} pathname
 * @returns {?PresentationMode}
 */
export const resolveModeForPath = (pathname) =>
  PRESENTATION_MODES.find(({ path }) => pathname === path || pathname.startsWith(`${path}/`)) ??
  null;