| @@ -16,13 +16,77 @@ | ||
| 16 | 16 | body: string; |
| 17 | 17 | }; |
| 18 | 18 | |
| 19 | 19 | export async function fetchEmailTemplates(): Promise<unknown[]> { |
| 20 | - const raw = await apiClient.get(API_ENDPOINTS.EMAIL_TEMPLATES); | |
| 20 | + // The list is rendered client-side in full (no server paging in the UI); | |
| 21 | + // ask for everything so trip-specific overrides never fall off page 1. | |
| 22 | + const raw = await apiClient.get(API_ENDPOINTS.EMAIL_TEMPLATES, { | |
| 23 | + params: { per_page: 500 }, | |
| 24 | + }); | |
| 21 | 25 | const unwrapped = unwrapApiPayload<unknown>(raw); |
| 22 | 26 | return Array.isArray(unwrapped) ? unwrapped : []; |
| 23 | 27 | } |
| 24 | 28 | |
| 29 | +/** Trip targeting of an override template (mirrors the Pro `settings.targets`). */ | |
| 30 | +export type EmailTemplateTargets = { | |
| 31 | + trips?: number[]; | |
| 32 | + categories?: number[]; | |
| 33 | + trip_types?: string[]; | |
| 34 | +}; | |
| 35 | + | |
| 36 | +/** | |
| 37 | + * Create a trip-specific override of a global template (Pro Email | |
| 38 | + * Automation). Same event and merge tags; used instead of the global | |
| 39 | + * template for bookings on the targeted trips. | |
| 40 | + */ | |
| 41 | +export async function createEmailTemplateOverride( | |
| 42 | + parentId: string | number, | |
| 43 | + data: { | |
| 44 | + targets: EmailTemplateTargets; | |
| 45 | + name?: string; | |
| 46 | + description?: string; | |
| 47 | + copy?: boolean; | |
| 48 | + }, | |
| 49 | +): Promise<unknown> { | |
| 50 | + return apiClient.post(API_ENDPOINTS.EMAIL_TEMPLATE_OVERRIDE(parentId), data); | |
| 51 | +} | |
| 52 | + | |
| 53 | +export async function reorderEmailTemplateOverrides( | |
| 54 | + parentKey: string, | |
| 55 | + ids: number[], | |
| 56 | +): Promise<unknown> { | |
| 57 | + return apiClient.post(API_ENDPOINTS.EMAIL_TEMPLATE_OVERRIDES_REORDER, { | |
| 58 | + parent_key: parentKey, | |
| 59 | + ids, | |
| 60 | + }); | |
| 61 | +} | |
| 62 | + | |
| 63 | +export type EmailTemplateResolution = { | |
| 64 | + trip: { id: number; trip_type: string; categories: number[] }; | |
| 65 | + resolved: Record< | |
| 66 | + string, | |
| 67 | + { | |
| 68 | + id: number; | |
| 69 | + template_key: string; | |
| 70 | + name: string; | |
| 71 | + specificity: number; | |
| 72 | + reason: string; | |
| 73 | + } | null | |
| 74 | + >; | |
| 75 | + overridable: string[]; | |
| 76 | +}; | |
| 77 | + | |
| 78 | +/** "View as a trip": which template each overridable email uses for a trip. */ | |
| 79 | +export async function resolveEmailTemplatesForTrip( | |
| 80 | + tripId: number, | |
| 81 | +): Promise<EmailTemplateResolution> { | |
| 82 | + return unwrapApiPayload<EmailTemplateResolution>( | |
| 83 | + await apiClient.get(API_ENDPOINTS.EMAIL_TEMPLATE_RESOLVE, { | |
| 84 | + params: { trip_id: tripId }, | |
| 85 | + }), | |
| 86 | + ); | |
| 87 | +} | |
| 88 | + | |
| 25 | 89 | export async function fetchEmailTemplate( |
| 26 | 90 | id: string | number, |
| 27 | 91 | ): Promise<Record<string, unknown> | null> { |
| 28 | 92 | return unwrapApiPayload<Record<string, unknown> | null>( |
| @@ -29,14 +93,47 @@ | ||
| 29 | 93 | await apiClient.get(API_ENDPOINTS.EMAIL_TEMPLATE_GET(id)), |
| 30 | 94 | ); |
| 31 | 95 | } |
| 32 | 96 | |
| 33 | -export async function fetchEmailTemplateVariables(): Promise<EmailTemplateVariableMap> { | |
| 34 | - return unwrapApiPayload<EmailTemplateVariableMap>( | |
| 35 | - await apiClient.get(API_ENDPOINTS.EMAIL_TEMPLATE_VARIABLES), | |
| 36 | - ); | |
| 97 | +/** | |
| 98 | + * Fetch the merge-tag catalog for the Template Editor "Available | |
| 99 | + * Variables" sidebar. | |
| 100 | + * | |
| 101 | + * Pass `eventKey` to get only the variables that apply to that | |
| 102 | + * automation event (e.g. `booking.created` returns the booking + | |
| 103 | + * customer + payment tags but skips enquiry / consent). Omit it | |
| 104 | + * (or pass an empty string) to get the full union of all tags — | |
| 105 | + * matches the pre-3.0.5 behavior for callers that haven't been | |
| 106 | + * updated. | |
| 107 | + */ | |
| 108 | +export async function fetchEmailTemplateVariables( | |
| 109 | + eventKey?: string, | |
| 110 | +): Promise<EmailTemplateVariableMap> { | |
| 111 | + const url = | |
| 112 | + eventKey && eventKey.trim() !== "" | |
| 113 | + ? `${API_ENDPOINTS.EMAIL_TEMPLATE_VARIABLES}?event_key=${encodeURIComponent(eventKey.trim())}` | |
| 114 | + : API_ENDPOINTS.EMAIL_TEMPLATE_VARIABLES; | |
| 115 | + return unwrapApiPayload<EmailTemplateVariableMap>(await apiClient.get(url)); | |
| 37 | 116 | } |
| 38 | 117 | |
| 118 | +/** | |
| 119 | + * Live list of trigger events (key/name/description) from the server. | |
| 120 | + * | |
| 121 | + * Fetched instead of relying only on the one-time `window.yatraAdmin.emailEvents` | |
| 122 | + * localize snapshot: that snapshot reflects the module state at PHP render time, | |
| 123 | + * while the module-enabled flag is refreshed client-side (useModules), so the two | |
| 124 | + * can diverge — leaving the event dropdown empty when a template is created right | |
| 125 | + * after enabling the module (no full reload). This endpoint always reflects the | |
| 126 | + * current state. | |
| 127 | + */ | |
| 128 | +export async function fetchEmailTemplateEvents(): Promise< | |
| 129 | + Array<{ key: string; name: string; description?: string }> | |
| 130 | +> { | |
| 131 | + return unwrapApiPayload< | |
| 132 | + Array<{ key: string; name: string; description?: string }> | |
| 133 | + >(await apiClient.get(API_ENDPOINTS.EMAIL_TEMPLATE_EVENTS)); | |
| 134 | +} | |
| 135 | + | |
| 39 | 136 | export async function createEmailTemplate(data: unknown): Promise<unknown> { |
| 40 | 137 | return apiClient.post(API_ENDPOINTS.EMAIL_TEMPLATES, data); |
| 41 | 138 | } |
| 42 | 139 | |
| @@ -63,12 +160,13 @@ | ||
| 63 | 160 | } |
| 64 | 161 | |
| 65 | 162 | export async function previewEmailTemplate( |
| 66 | 163 | id: string | number, |
| 164 | + tripId?: number | null, | |
| 67 | 165 | ): Promise<EmailPreviewPayload> { |
| 68 | 166 | const response = await apiClient.post( |
| 69 | 167 | API_ENDPOINTS.EMAIL_TEMPLATE_PREVIEW(id), |
| 70 | - {}, | |
| 168 | + tripId ? { trip_id: tripId } : {}, | |
| 71 | 169 | ); |
| 72 | 170 | return unwrapApiPayload<EmailPreviewPayload>(response); |
| 73 | 171 | } |
| 74 | 172 | |
| @@ -74,10 +172,14 @@ | ||
| 74 | 172 | |
| 75 | 173 | export async function sendEmailTemplateTest( |
| 76 | 174 | id: string | number, |
| 77 | 175 | email: string, |
| 176 | + tripId?: number | null, | |
| 78 | 177 | ): Promise<unknown> { |
| 79 | - return apiClient.post(API_ENDPOINTS.EMAIL_TEMPLATE_TEST(id), { email }); | |
| 178 | + return apiClient.post(API_ENDPOINTS.EMAIL_TEMPLATE_TEST(id), { | |
| 179 | + email, | |
| 180 | + ...(tripId ? { trip_id: tripId } : {}), | |
| 181 | + }); | |
| 80 | 182 | } |
| 81 | 183 | |
| 82 | 184 | export async function fetchEmailSequences(): Promise<unknown[]> { |
| 83 | 185 | const raw = await apiClient.get(API_ENDPOINTS.EMAIL_SEQUENCES); |