| @@ -6,10 +6,21 @@ | ||
| 6 | 6 | declare global { |
| 7 | 7 | interface Window { |
| 8 | 8 | yatraAdmin?: { |
| 9 | 9 | apiUrl?: string; |
| 10 | + restUrl?: string; | |
| 10 | 11 | nonce?: string; |
| 11 | 12 | brandLogoUrl?: string; |
| 13 | + /** | |
| 14 | + * Operator-facing brand name. When the White Label module is | |
| 15 | + * active (Agency-tier only) and the operator has filled in | |
| 16 | + * "Plugin name" in WL settings, this is THAT value — otherwise | |
| 17 | + * it's "Yatra". Use this everywhere instead of hardcoding | |
| 18 | + * "Yatra" so the UI reflects the operator's brand for resellers. | |
| 19 | + * | |
| 20 | + * Injected by AdminAssetsProvider via `yatra_get_brand_name()`. | |
| 21 | + */ | |
| 22 | + brandName?: string; | |
| 12 | 23 | pluginUrl?: string; |
| 13 | 24 | currentUserAvatar?: string; |
| 14 | 25 | currentUser?: number; |
| 15 | 26 | siteUrl?: string; |
| @@ -16,8 +27,10 @@ | ||
| 16 | 27 | permissions?: string[]; |
| 17 | 28 | roles?: string[]; |
| 18 | 29 | capabilities?: Record<string, boolean>; |
| 19 | 30 | isPro?: boolean; |
| 31 | + /** Yatra → Modules → Custom Landing Pages enabled (Pro). */ | |
| 32 | + customLandingPagesModuleEnabled?: boolean; | |
| 20 | 33 | isProActive?: boolean; |
| 21 | 34 | version?: string; |
| 22 | 35 | proVersion?: string | null; |
| 23 | 36 | translations?: Record<string, string>; |
| @@ -22,13 +35,15 @@ | ||
| 22 | 35 | proVersion?: string | null; |
| 23 | 36 | translations?: Record<string, string>; |
| 24 | 37 | locale?: string; |
| 25 | 38 | emailAutomationEnabled?: boolean; |
| 39 | + emailTemplateOverridesEnabled?: boolean; | |
| 26 | 40 | tripConsentEnabled?: boolean; |
| 27 | 41 | additionalServicesEnabled?: boolean; |
| 28 | 42 | abandonedBookingRecoveryEnabled?: boolean; |
| 29 | 43 | dynamicPricingEnabled?: boolean; |
| 30 | 44 | dynamicFormFieldEnabled?: boolean; |
| 45 | + bookingFormConditionsEnabled?: boolean; | |
| 31 | 46 | advancedDiscountEnabled?: boolean; |
| 32 | 47 | showGoogleCalendarSettingsUI?: boolean; |
| 33 | 48 | showMailchimpSettingsUI?: boolean; |
| 34 | 49 | showFacebookPixelSettingsUI?: boolean; |
| @@ -33,8 +48,19 @@ | ||
| 33 | 48 | showMailchimpSettingsUI?: boolean; |
| 34 | 49 | showFacebookPixelSettingsUI?: boolean; |
| 35 | 50 | showGoogleAnalyticsSettingsUI?: boolean; |
| 36 | 51 | flexiblePaymentsEnabled?: boolean; |
| 52 | + // Growth + Agency tier modules — set by their respective Pro | |
| 53 | + // modules via yatra_admin_localized_data filter, OR by the | |
| 54 | + // free plugin's AdminAssetsProvider (canonical source via | |
| 55 | + // ModuleManager::isModuleEnabled). useModules() also writes | |
| 56 | + // these at runtime once /modules resolves. | |
| 57 | + aiAssistantEnabled?: boolean; | |
| 58 | + whiteLabelEnabled?: boolean; | |
| 59 | + whatsappEnabled?: boolean; | |
| 60 | + channelManagerEnabled?: boolean; | |
| 61 | + webhooksEnabled?: boolean; | |
| 62 | + scheduledPaymentsEnabled?: boolean; | |
| 37 | 63 | currency?: string; |
| 38 | 64 | date_format?: string; |
| 39 | 65 | time_format?: string; |
| 40 | 66 | calendar_name?: string; |
| @@ -93,8 +119,33 @@ | ||
| 93 | 119 | connected?: boolean; |
| 94 | 120 | redirect_uri?: string; |
| 95 | 121 | last_sync?: string | null; |
| 96 | 122 | }; |
| 123 | + // Team & Access (Agency-tier) — injected by Team module's | |
| 124 | + // LocalizedData service. Absent when module isn't installed. | |
| 125 | + teamEnabled?: boolean; | |
| 126 | + /** | |
| 127 | + * Forward-looking "keep access on module disable" setting. | |
| 128 | + * Only consulted when the Team & Access module is DISABLED: | |
| 129 | + * - `false` (default): yatra_* caps are stripped for non-admin | |
| 130 | + * users until the module is re-enabled. | |
| 131 | + * - `true`: WP-native role machinery keeps resolving caps from | |
| 132 | + * the stored role records — team members keep their access | |
| 133 | + * even after disabling the module. | |
| 134 | + * | |
| 135 | + * When the module is enabled, this setting is irrelevant — | |
| 136 | + * caps resolve normally through the full layered chain (admin | |
| 137 | + * fallback, expiry, revoke, role, grant). | |
| 138 | + */ | |
| 139 | + teamKeepAccessOnModuleDisable?: boolean; | |
| 140 | + isWpAdmin?: boolean; | |
| 141 | + userCaps?: string[]; | |
| 142 | + userScopes?: { | |
| 143 | + destinations: number[]; | |
| 144 | + activities: number[]; | |
| 145 | + trips: number[]; | |
| 146 | + categories: number[]; | |
| 147 | + }; | |
| 97 | 148 | }; |
| 98 | 149 | } |
| 99 | 150 | } |
| 100 | 151 | |
| @@ -111,8 +162,26 @@ | ||
| 111 | 162 | |
| 112 | 163 | function __(key: string): string; |
| 113 | 164 | function __(key: string, textDomain: string): string; |
| 114 | 165 | function __(key: string, textDomain?: string): string { |
| 166 | + // If the frontend bootstrapped a translations map (e.g., account page), | |
| 167 | + // use it as the highest priority source. This allows Loco Translate / PHP | |
| 168 | + // string catalogs to power React UIs without requiring JS translation JSON files. | |
| 169 | + if (typeof window !== "undefined") { | |
| 170 | + const w = window as unknown as { | |
| 171 | + yatraAccountPage?: { translations?: Record<string, string> }; | |
| 172 | + yatraAdmin?: { translations?: Record<string, string> }; | |
| 173 | + }; | |
| 174 | + const fromAccount = w.yatraAccountPage?.translations?.[key]; | |
| 175 | + if (typeof fromAccount === "string" && fromAccount !== "") { | |
| 176 | + return fromAccount; | |
| 177 | + } | |
| 178 | + const fromAdmin = w.yatraAdmin?.translations?.[key]; | |
| 179 | + if (typeof fromAdmin === "string" && fromAdmin !== "") { | |
| 180 | + return fromAdmin; | |
| 181 | + } | |
| 182 | + } | |
| 183 | + | |
| 115 | 184 | // Use direct WordPress i18n function which is working correctly |
| 116 | 185 | if (typeof window !== "undefined" && (window as any).wp?.i18n?.__) { |
| 117 | 186 | return (window as any).wp.i18n.__(key, textDomain || "yatra"); |
| 118 | 187 | } |
| @@ -140,16 +209,45 @@ | ||
| 140 | 209 | ...args, |
| 141 | 210 | ); |
| 142 | 211 | } |
| 143 | 212 | |
| 144 | -export { __, _x, sprintf }; | |
| 213 | +/** | |
| 214 | + * Operator brand name — "Yatra" by default, or whatever the operator | |
| 215 | + * has set in the White Label module (Agency tier). | |
| 216 | + * | |
| 217 | + * Use this in user-visible strings instead of hardcoding "Yatra": | |
| 218 | + * | |
| 219 | + * const brand = brandName(); | |
| 220 | + * sprintf(__("%s role", "yatra"), brand) // "Acme role" if rebranded | |
| 221 | + * | |
| 222 | + * Always pass the brand as an interpolated argument so the translatable | |
| 223 | + * string stays generic — that keeps `make-pot` extraction working AND | |
| 224 | + * means a translator only has to translate "%s role" once, regardless | |
| 225 | + * of brand. | |
| 226 | + */ | |
| 227 | +function brandName(): string { | |
| 228 | + if (typeof window === "undefined") return "Yatra"; | |
| 229 | + return (window.yatraAdmin?.brandName as string | undefined) || "Yatra"; | |
| 230 | +} | |
| 145 | 231 | |
| 232 | +export { __, _x, sprintf, brandName }; | |
| 233 | + | |
| 146 | 234 | /** |
| 147 | 235 | * Get translated string with number |
| 148 | 236 | * @param single - Single form |
| 149 | 237 | * @param plural - Plural form |
| 150 | 238 | * @param number - Number to determine form |
| 239 | + * @param textDomain - Optional text domain; accepted for API parity with | |
| 240 | + * WordPress's own `_n()` so call sites that already pass | |
| 241 | + * `"yatra"` as a fourth arg type-check. Currently | |
| 242 | + * unused — `__()` does its own domain resolution via | |
| 243 | + * the translations map injected on `window.yatraAdmin`. | |
| 151 | 244 | * @returns Translated string |
| 152 | 245 | */ |
| 153 | -export const _n = (single: string, plural: string, number: number): string => { | |
| 246 | +export const _n = ( | |
| 247 | + single: string, | |
| 248 | + plural: string, | |
| 249 | + number: number, | |
| 250 | + _textDomain?: string, | |
| 251 | +): string => { | |
| 154 | 252 | return number === 1 ? __(single) : __(plural); |
| 155 | 253 | }; |