@codee-sh/medusa-plugin-notification-emails 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/.medusa/server/emails-previews/contact-form.js +14 -8
  2. package/.medusa/server/emails-previews/inventory-level.js +8 -4
  3. package/.medusa/server/emails-previews/order-completed.js +70 -35
  4. package/.medusa/server/emails-previews/order-placed.js +70 -34
  5. package/.medusa/server/src/admin/index.js +1684 -262
  6. package/.medusa/server/src/admin/index.mjs +1684 -262
  7. package/.medusa/server/src/api/admin/notification-plugin/render-template/route.js +9 -5
  8. package/.medusa/server/src/subscribers/order-completed.js +10 -6
  9. package/.medusa/server/src/subscribers/order-placed.js +8 -4
  10. package/.medusa/server/src/templates/emails/contact-form/config.js +5 -1
  11. package/.medusa/server/src/templates/emails/email-template-service.js +210 -0
  12. package/.medusa/server/src/templates/emails/index.js +6 -248
  13. package/.medusa/server/src/templates/emails/inventory-level/config.js +5 -1
  14. package/.medusa/server/src/templates/emails/order/completed/config.js +5 -1
  15. package/.medusa/server/src/templates/emails/order/completed/index.js +1 -2
  16. package/.medusa/server/src/templates/emails/order/placed/config.js +5 -1
  17. package/.medusa/server/src/templates/emails/order/updated/config.js +5 -1
  18. package/.medusa/server/src/templates/emails/types.js +1 -1
  19. package/.medusa/server/src/templates/shared/abstract-template-service.js +104 -0
  20. package/.medusa/server/src/templates/shared/index.js +22 -0
  21. package/.medusa/server/src/templates/shared/types.js +6 -0
  22. package/.medusa/server/src/templates/slack/index.js +12 -0
  23. package/.medusa/server/src/templates/slack/inventory-level/config.js +52 -0
  24. package/.medusa/server/src/templates/slack/inventory-level/index.js +8 -0
  25. package/.medusa/server/src/templates/slack/inventory-level/translations/en.json +18 -0
  26. package/.medusa/server/src/templates/slack/inventory-level/translations/pl.json +18 -0
  27. package/.medusa/server/src/templates/slack/order/archived/config.js +48 -0
  28. package/.medusa/server/src/templates/slack/order/archived/index.js +7 -0
  29. package/.medusa/server/src/templates/slack/order/archived/translations/en.json +11 -0
  30. package/.medusa/server/src/templates/slack/order/archived/translations/index.js +15 -0
  31. package/.medusa/server/src/templates/slack/order/archived/translations/pl.json +11 -0
  32. package/.medusa/server/src/templates/slack/order/canceled/config.js +48 -0
  33. package/.medusa/server/src/templates/slack/order/canceled/index.js +7 -0
  34. package/.medusa/server/src/templates/slack/order/canceled/translations/en.json +11 -0
  35. package/.medusa/server/src/templates/slack/order/canceled/translations/index.js +15 -0
  36. package/.medusa/server/src/templates/slack/order/canceled/translations/pl.json +11 -0
  37. package/.medusa/server/src/templates/slack/order/completed/config.js +48 -0
  38. package/.medusa/server/src/templates/slack/order/completed/index.js +7 -0
  39. package/.medusa/server/src/templates/slack/order/completed/translations/en.json +11 -0
  40. package/.medusa/server/src/templates/slack/order/completed/translations/index.js +15 -0
  41. package/.medusa/server/src/templates/slack/order/completed/translations/pl.json +11 -0
  42. package/.medusa/server/src/templates/slack/order/placed/config.js +48 -0
  43. package/.medusa/server/src/templates/slack/order/placed/index.js +7 -0
  44. package/.medusa/server/src/templates/slack/order/placed/translations/en.json +11 -0
  45. package/.medusa/server/src/templates/slack/order/placed/translations/index.js +15 -0
  46. package/.medusa/server/src/templates/slack/order/placed/translations/pl.json +11 -0
  47. package/.medusa/server/src/templates/slack/order/updated/config.js +48 -0
  48. package/.medusa/server/src/templates/slack/order/updated/index.js +7 -0
  49. package/.medusa/server/src/templates/slack/order/updated/translations/en.json +11 -0
  50. package/.medusa/server/src/templates/slack/order/updated/translations/index.js +15 -0
  51. package/.medusa/server/src/templates/slack/order/updated/translations/pl.json +11 -0
  52. package/.medusa/server/src/templates/slack/product/config.js +48 -0
  53. package/.medusa/server/src/templates/slack/product/index.js +7 -0
  54. package/.medusa/server/src/templates/slack/product/translations/en.json +14 -0
  55. package/.medusa/server/src/templates/slack/product/translations/pl.json +14 -0
  56. package/.medusa/server/src/templates/slack/product-variant/config.js +48 -0
  57. package/.medusa/server/src/templates/slack/product-variant/index.js +7 -0
  58. package/.medusa/server/src/templates/slack/product-variant/translations/en.json +14 -0
  59. package/.medusa/server/src/templates/slack/product-variant/translations/index.js +15 -0
  60. package/.medusa/server/src/templates/slack/product-variant/translations/pl.json +14 -0
  61. package/.medusa/server/src/templates/slack/slack-template-service.js +219 -0
  62. package/.medusa/server/src/templates/slack/types.js +15 -0
  63. package/.medusa/server/src/utils/i18n/i18n.js +7 -10
  64. package/README.md +45 -15
  65. package/package.json +4 -1
  66. package/.medusa/server/src/subscribers/payment-captured.js +0 -86
@@ -143,7 +143,7 @@ const NotificationsDetail = ({ type, data }) => {
143
143
  ] });
144
144
  };
145
145
  const Header = () => {
146
- const { t } = reactI18next.useTranslation();
146
+ const { t: t2 } = reactI18next.useTranslation();
147
147
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between px-6 py-4 border-b", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Notifications - Actions" }) });
148
148
  };
149
149
  const useListNotifications = (params, options) => {
@@ -291,20 +291,20 @@ const config$2 = adminSdk.defineRouteConfig({
291
291
  function _extends() {
292
292
  return _extends = Object.assign ? Object.assign.bind() : function(n) {
293
293
  for (var e = 1; e < arguments.length; e++) {
294
- var t = arguments[e];
295
- for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
294
+ var t2 = arguments[e];
295
+ for (var r in t2) ({}).hasOwnProperty.call(t2, r) && (n[r] = t2[r]);
296
296
  }
297
297
  return n;
298
298
  }, _extends.apply(null, arguments);
299
299
  }
300
300
  function _objectWithoutPropertiesLoose(r, e) {
301
301
  if (null == r) return {};
302
- var t = {};
302
+ var t2 = {};
303
303
  for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
304
304
  if (-1 !== e.indexOf(n)) continue;
305
- t[n] = r[n];
305
+ t2[n] = r[n];
306
306
  }
307
- return t;
307
+ return t2;
308
308
  }
309
309
  var initialState$5 = {};
310
310
  var Context$5 = /* @__PURE__ */ react.createContext(initialState$5);
@@ -769,8 +769,8 @@ var Provider = (_ref) => {
769
769
  });
770
770
  };
771
771
  Provider.displayName = "JVR.Provider";
772
- function _objectDestructuringEmpty(t) {
773
- if (null == t) throw new TypeError("Cannot destructure " + t);
772
+ function _objectDestructuringEmpty(t2) {
773
+ if (null == t2) throw new TypeError("Cannot destructure " + t2);
774
774
  }
775
775
  var _excluded$9 = ["isNumber", "value", "parentValue", "keyName", "keys"], _excluded2$5 = ["as", "render"], _excluded3$1 = ["as", "render"], _excluded4$1 = ["as", "render"], _excluded5$1 = ["as", "style", "render"], _excluded6$1 = ["as", "render"], _excluded7$1 = ["as", "render"], _excluded8$1 = ["as", "render"], _excluded9$1 = ["as", "render"];
776
776
  var Quote$1 = (props) => {
@@ -2257,10 +2257,10 @@ var NestedOpen = (props) => {
2257
2257
  transition: "all 0.3s"
2258
2258
  };
2259
2259
  var len = Object.keys(value).length;
2260
- var isObject = typeof value === "object";
2260
+ var isObject2 = typeof value === "object";
2261
2261
  var isArray = Array.isArray(value);
2262
2262
  var isMySet = value instanceof Set;
2263
- var showArrow = len !== 0 && (isArray || isMySet || isObject);
2263
+ var showArrow = len !== 0 && (isArray || isMySet || isObject2);
2264
2264
  var reset = {
2265
2265
  style
2266
2266
  };
@@ -2622,12 +2622,12 @@ JsonView.KeyName = KeyName;
2622
2622
  JsonView.Row = Row;
2623
2623
  JsonView.displayName = "JVR.JsonView";
2624
2624
  const JsonViewSection = ({ data }) => {
2625
- const { t } = reactI18next.useTranslation();
2625
+ const { t: t2 } = reactI18next.useTranslation();
2626
2626
  const numberOfKeys = Object.keys(data).length;
2627
2627
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "flex items-center justify-between px-6 py-4", children: [
2628
2628
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-4", children: [
2629
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: t("json.header") }),
2630
- /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", rounded: "full", children: t("json.numberOfKeys", {
2629
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: t2("json.header") }),
2630
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", rounded: "full", children: t2("json.numberOfKeys", {
2631
2631
  count: numberOfKeys
2632
2632
  }) })
2633
2633
  ] }),
@@ -2654,7 +2654,7 @@ const JsonViewSection = ({ data }) => {
2654
2654
  ]
2655
2655
  }
2656
2656
  ) }) }),
2657
- /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Description, { className: "sr-only", children: t("json.drawer.description") })
2657
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Description, { className: "sr-only", children: t2("json.drawer.description") })
2658
2658
  ] }),
2659
2659
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2", children: [
2660
2660
  /* @__PURE__ */ jsxRuntime.jsx(ui.Kbd, { className: "bg-ui-contrast-bg-subtle border-ui-contrast-border-base text-ui-contrast-fg-secondary", children: "esc" }),
@@ -2717,7 +2717,7 @@ const JsonViewSection = ({ data }) => {
2717
2717
  JsonView.CountInfo,
2718
2718
  {
2719
2719
  render: (_props, { value }) => {
2720
- return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-contrast-fg-secondary ml-2", children: t("general.items", {
2720
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-contrast-fg-secondary ml-2", children: t2("general.items", {
2721
2721
  count: Object.keys(value).length
2722
2722
  }) });
2723
2723
  }
@@ -2767,7 +2767,7 @@ const MetadataSection = ({
2767
2767
  data,
2768
2768
  onOpen
2769
2769
  }) => {
2770
- const { t } = reactI18next.useTranslation();
2770
+ const { t: t2 } = reactI18next.useTranslation();
2771
2771
  if (!data) {
2772
2772
  return null;
2773
2773
  }
@@ -2777,8 +2777,8 @@ const MetadataSection = ({
2777
2777
  const numberOfKeys = data.metadata ? Object.keys(data.metadata).length : 0;
2778
2778
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "flex items-center justify-between", children: [
2779
2779
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-3", children: [
2780
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: t("metadata.header") }),
2781
- /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", rounded: "full", children: t("metadata.numberOfKeys", {
2780
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: t2("metadata.header") }),
2781
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", rounded: "full", children: t2("metadata.numberOfKeys", {
2782
2782
  count: numberOfKeys
2783
2783
  }) })
2784
2784
  ] }),
@@ -3029,220 +3029,140 @@ const usePreview = (params, options) => {
3029
3029
  });
3030
3030
  return { data, ...rest };
3031
3031
  };
3032
- function SectionBlock({
3033
- id,
3034
- props,
3035
- data,
3036
- isLastBlock,
3037
- isFirstBlock
3038
- }) {
3039
- return /* @__PURE__ */ jsxRuntime.jsx(components.Section, { className: "m-0 p-0", children: /* @__PURE__ */ jsxRuntime.jsx(BlockRenderer, { blocks: props.blocks || [], data }) });
3040
- }
3041
- function TextBlock({
3042
- id,
3043
- props,
3044
- isLastBlock,
3045
- isFirstBlock
3046
- }) {
3047
- const className = ui.clx(
3048
- isLastBlock ? "mb-0" : "mb-4",
3049
- isFirstBlock && "mt-0"
3050
- );
3051
- return /* @__PURE__ */ jsxRuntime.jsx(components.Text, { className, children: typeof props.value === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { dangerouslySetInnerHTML: { __html: props.value } }) : props.value }, id);
3052
- }
3053
- function RepeaterBlock({
3054
- id,
3055
- props,
3056
- data
3057
- }) {
3058
- const array = props.itemBlocks;
3059
- return /* @__PURE__ */ jsxRuntime.jsx(BlockRenderer, { blocks: array, data });
3060
- }
3061
- function HeadingBlock({
3062
- id,
3063
- props,
3064
- data,
3065
- isLastBlock,
3066
- isFirstBlock
3067
- }) {
3068
- const className = ui.clx(
3069
- "text-xl",
3070
- "font-bold",
3071
- isLastBlock ? "mb-0" : "mb-4",
3072
- isFirstBlock ? "mt-0" : "mt-4"
3073
- );
3074
- return /* @__PURE__ */ jsxRuntime.jsx(components.Heading, { className, children: props.value });
3075
- }
3076
- function RowBlock({
3077
- id,
3078
- props,
3079
- data,
3080
- isLastBlock,
3081
- isFirstBlock
3082
- }) {
3083
- return /* @__PURE__ */ jsxRuntime.jsxs(components.Row, { children: [
3084
- /* @__PURE__ */ jsxRuntime.jsx(components.Column, { className: "font-semibold", children: props.label }),
3085
- /* @__PURE__ */ jsxRuntime.jsx(components.Column, { className: "text-right", children: typeof props.value === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { dangerouslySetInnerHTML: { __html: props.value } }) : props.value })
3086
- ] });
3087
- }
3088
- function SeparatorBlock({
3089
- id,
3090
- props,
3091
- isLastBlock,
3092
- isFirstBlock
3093
- }) {
3094
- return /* @__PURE__ */ jsxRuntime.jsx(components.Hr, { className: "my-4 border-ui-border" });
3032
+ const TEMPLATES_NAMES = {
3033
+ BASE_TEMPLATE: "base-template",
3034
+ INVENTORY_LEVEL: "inventory-level",
3035
+ ORDER_PLACED: "order-placed",
3036
+ ORDER_COMPLETED: "order-completed",
3037
+ ORDER_UPDATED: "order-updated",
3038
+ CONTACT_FORM: "contact-form"
3039
+ };
3040
+ function isDefined(val) {
3041
+ return typeof val !== "undefined";
3095
3042
  }
3096
- function ProductItemBlock({
3097
- props,
3098
- data,
3099
- isLastBlock,
3100
- isFirstBlock
3101
- }) {
3102
- return /* @__PURE__ */ jsxRuntime.jsxs(components.Row, { children: [
3103
- props.thumbnail && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3104
- /* @__PURE__ */ jsxRuntime.jsx(components.Column, { className: "w-[50px]", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: props.thumbnail, width: 50, height: 50 }) }),
3105
- /* @__PURE__ */ jsxRuntime.jsx(components.Column, { className: "w-[12px]" })
3106
- ] }),
3107
- /* @__PURE__ */ jsxRuntime.jsx(components.Column, { className: "text-left", children: typeof props.value === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { dangerouslySetInnerHTML: { __html: props.value } }) : props.value })
3108
- ] });
3043
+ function isObject(obj) {
3044
+ var _a;
3045
+ return obj != null && ((_a = obj == null ? void 0 : obj.constructor) == null ? void 0 : _a.name) === "Object";
3109
3046
  }
3110
- function BlockRenderer({ blocks, data }) {
3111
- return blocks.map((block, index) => {
3112
- const blockKey = block.id || `block-${index}`;
3113
- const isLastBlock = index === blocks.length - 1;
3114
- const isFirstBlock = index === 0;
3115
- switch (block.type) {
3116
- case "section":
3117
- return /* @__PURE__ */ jsxRuntime.jsx(
3118
- SectionBlock,
3119
- {
3120
- id: blockKey,
3121
- props: block.props,
3122
- data,
3123
- isLastBlock,
3124
- isFirstBlock
3125
- },
3126
- blockKey
3127
- );
3128
- case "row":
3129
- return /* @__PURE__ */ jsxRuntime.jsx(
3130
- RowBlock,
3131
- {
3132
- id: blockKey,
3133
- props: block.props,
3134
- data,
3135
- isLastBlock,
3136
- isFirstBlock
3137
- },
3138
- blockKey
3139
- );
3140
- case "product-item":
3141
- return /* @__PURE__ */ jsxRuntime.jsx(
3142
- ProductItemBlock,
3143
- {
3144
- id: blockKey,
3145
- props: block.props,
3146
- data,
3147
- isLastBlock,
3148
- isFirstBlock
3149
- },
3150
- blockKey
3151
- );
3152
- case "heading":
3153
- return /* @__PURE__ */ jsxRuntime.jsx(
3154
- HeadingBlock,
3155
- {
3156
- id: blockKey,
3157
- props: block.props,
3158
- data,
3159
- isLastBlock,
3160
- isFirstBlock
3161
- },
3162
- blockKey
3163
- );
3164
- case "text":
3165
- return /* @__PURE__ */ jsxRuntime.jsx(
3166
- TextBlock,
3167
- {
3168
- id: blockKey,
3169
- props: block.props,
3170
- isLastBlock,
3171
- isFirstBlock
3172
- },
3173
- blockKey
3174
- );
3175
- case "separator":
3176
- return /* @__PURE__ */ jsxRuntime.jsx(
3177
- SeparatorBlock,
3178
- {
3179
- id: blockKey,
3180
- props: block.props,
3181
- isLastBlock,
3182
- isFirstBlock
3183
- },
3184
- blockKey
3185
- );
3186
- case "repeater":
3187
- if (!data) {
3188
- console.warn("RepeaterBlock requires data prop");
3189
- return null;
3190
- }
3191
- return /* @__PURE__ */ jsxRuntime.jsx(
3192
- RepeaterBlock,
3193
- {
3194
- id: blockKey,
3195
- props: block.props,
3196
- data
3197
- },
3198
- blockKey
3199
- );
3200
- default:
3201
- return null;
3047
+ function pickValueFromObject(path, object) {
3048
+ const segments = path.split(".");
3049
+ let result = object;
3050
+ for (let i = 0; i < segments.length; i++) {
3051
+ const segment = segments[i];
3052
+ result = result[segment];
3053
+ if (!isDefined(result)) {
3054
+ return;
3202
3055
  }
3203
- });
3056
+ if (i === segments.length - 1) {
3057
+ return result;
3058
+ }
3059
+ if (Array.isArray(result)) {
3060
+ const subPath = segments.slice(i + 1).join(".");
3061
+ return result.map((item) => pickValueFromObject(subPath, item)).flat();
3062
+ }
3063
+ if (!isObject(result)) {
3064
+ return result;
3065
+ }
3066
+ }
3067
+ return result;
3204
3068
  }
3205
- function renderHTMLReact(data, options) {
3206
- const theme = options.theme || {};
3207
- const blocks = options.blocks || [];
3208
- return /* @__PURE__ */ jsxRuntime.jsxs(components.Html, { children: [
3209
- /* @__PURE__ */ jsxRuntime.jsx(components.Head, {}),
3210
- /* @__PURE__ */ jsxRuntime.jsx(
3211
- components.Tailwind,
3212
- {
3213
- config: {
3214
- presets: [components.pixelBasedPreset],
3215
- theme
3216
- },
3217
- children: /* @__PURE__ */ jsxRuntime.jsx(components.Body, { className: "mx-auto my-auto px-4 font-arial font-normal text-base bg-ui-bg text-ui-text", children: /* @__PURE__ */ jsxRuntime.jsx(components.Container, { className: "py-4", children: /* @__PURE__ */ jsxRuntime.jsx(BlockRenderer, { blocks, data }) }) })
3218
- }
3219
- )
3220
- ] });
3069
+ function flattenTranslations(translations2) {
3070
+ if (!isObject(translations2) || !translations2.general) {
3071
+ return translations2;
3072
+ }
3073
+ const { general: general2, ...rest } = translations2;
3074
+ return { ...general2, ...rest };
3221
3075
  }
3222
- async function renderHTML(data, options) {
3223
- return await render.pretty(await render.render(renderHTMLReact(data, options)));
3076
+ function getVariableValue(text) {
3077
+ if (!text || typeof text !== "string") {
3078
+ return { replaced: text, original: text };
3079
+ }
3080
+ return {
3081
+ replaced: text.replace(
3082
+ /\{\{(\w+(?:\.\w+)*)\}\}/g,
3083
+ (match, key) => {
3084
+ return key;
3085
+ }
3086
+ ),
3087
+ original: text
3088
+ };
3224
3089
  }
3225
- async function renderText(data, options) {
3226
- const html = await render.render(renderHTMLReact(data, options));
3227
- return render.toPlainText(html);
3090
+ function multiInterpolate(text, data = {}, translator, config2) {
3091
+ if (!text || typeof text !== "string") {
3092
+ return text;
3093
+ }
3094
+ const variableRegex = /\{\{((?:data\.|translations\.)?\w+(?:\.\w+)*)\}\}/g;
3095
+ const matches = Array.from(text.matchAll(variableRegex));
3096
+ if (matches.length === 0) {
3097
+ return text;
3098
+ }
3099
+ const dataPrefix = (config2 == null ? void 0 : config2.arrayPath) ? ["data", config2.arrayPath] : ["data"];
3100
+ const dataPrefixString = dataPrefix.join(".");
3101
+ let result = text;
3102
+ for (const match of matches) {
3103
+ const fullMatch = match[0];
3104
+ const variable = match[1];
3105
+ let replacement;
3106
+ if (variable.startsWith(`${dataPrefixString}.`)) {
3107
+ const escapedPrefix = dataPrefixString.replace(/\./g, "\\.");
3108
+ const dataPath = variable.replace(new RegExp(`^${escapedPrefix}\\.`), "");
3109
+ const value = pickValueFromObject(dataPath, data);
3110
+ if (value === void 0 || value === null) {
3111
+ replacement = void 0;
3112
+ } else {
3113
+ replacement = String(value);
3114
+ }
3115
+ } else if (variable.startsWith("translations.")) {
3116
+ const translationKey = variable.replace(/^translations\./, "");
3117
+ replacement = translator.t(translationKey, data);
3118
+ replacement = multiInterpolate(replacement, data, translator);
3119
+ }
3120
+ if (replacement !== void 0) {
3121
+ result = result.replace(fullMatch, replacement);
3122
+ }
3123
+ }
3124
+ return result;
3228
3125
  }
3229
- async function getBaseTemplateHtml(data, options) {
3230
- return await renderHTML(data, options);
3126
+ function t(locale, translations2, key) {
3127
+ const localeTranslations = translations2[locale] || translations2["pl"] || {};
3128
+ const flatTranslations = flattenTranslations(
3129
+ localeTranslations
3130
+ );
3131
+ const { replaced, original } = getVariableValue(key);
3132
+ const translation = pickValueFromObject(replaced, flatTranslations);
3133
+ const text = translation || original;
3134
+ return text;
3231
3135
  }
3232
- async function getBaseTemplateText(data, options) {
3233
- return await renderText(data, options);
3136
+ function createTranslator(locale, translations2) {
3137
+ return {
3138
+ t: (key, data = {}) => {
3139
+ return t(locale, translations2, key);
3140
+ }
3141
+ };
3234
3142
  }
3235
- function getBaseTemplateReactNode(data, options) {
3236
- return renderHTMLReact(data, options);
3143
+ function mergeTranslations(baseTranslations, customTranslations) {
3144
+ var _a;
3145
+ if (!customTranslations || !isObject(customTranslations)) {
3146
+ return baseTranslations;
3147
+ }
3148
+ const merged = {
3149
+ ...baseTranslations
3150
+ };
3151
+ for (const [lang, custom] of Object.entries(
3152
+ customTranslations
3153
+ )) {
3154
+ if (isObject(custom)) {
3155
+ merged[lang] = {
3156
+ ...baseTranslations[lang],
3157
+ general: {
3158
+ ...((_a = baseTranslations[lang]) == null ? void 0 : _a.general) || {},
3159
+ ...(custom == null ? void 0 : custom.general) || custom
3160
+ }
3161
+ };
3162
+ }
3163
+ }
3164
+ return merged;
3237
3165
  }
3238
- const TEMPLATES_NAMES = {
3239
- BASE_TEMPLATE: "base-template",
3240
- INVENTORY_LEVEL: "inventory-level",
3241
- ORDER_PLACED: "order-placed",
3242
- ORDER_COMPLETED: "order-completed",
3243
- ORDER_UPDATED: "order-updated",
3244
- CONTACT_FORM: "contact-form"
3245
- };
3246
3166
  const ORDER_ATTRIBUTES = [
3247
3167
  // Basic fields
3248
3168
  {
@@ -3649,36 +3569,1538 @@ const ORDER_ATTRIBUTES = [
3649
3569
  "order.summary.*",
3650
3570
  "order.payment_collections.*"
3651
3571
  ];
3652
- const baseTemplateConfig = {
3653
- [TEMPLATES_NAMES.BASE_TEMPLATE]: {
3654
- getHtml: async (data, options) => {
3655
- return await getBaseTemplateHtml(data, options);
3656
- },
3657
- getText: async (data, options) => {
3658
- return await getBaseTemplateText(data, options);
3659
- },
3660
- getReactNode: (data, options) => {
3661
- return getBaseTemplateReactNode(data, options);
3572
+ class AbstractTemplateService {
3573
+ constructor() {
3574
+ this.templateRegistry = /* @__PURE__ */ new Map();
3575
+ }
3576
+ /**
3577
+ * Register a template
3578
+ *
3579
+ * @param name - Template name
3580
+ * @param renderer - Template renderer configuration
3581
+ */
3582
+ registerTemplate(name, renderer) {
3583
+ this.templateRegistry.set(name, renderer);
3584
+ }
3585
+ /**
3586
+ * Get template by name
3587
+ *
3588
+ * @param name - Template name
3589
+ * @returns Template renderer
3590
+ * @throws Error if template not found
3591
+ */
3592
+ getTemplate(name) {
3593
+ const template = this.templateRegistry.get(name);
3594
+ if (!template) {
3595
+ throw new Error(
3596
+ `Template "${name}" not found. Available templates: ${Array.from(
3597
+ this.templateRegistry.keys()
3598
+ ).join(", ")}`
3599
+ );
3662
3600
  }
3601
+ return template;
3663
3602
  }
3664
- };
3665
- ({
3666
- [TEMPLATES_NAMES.CONTACT_FORM]: {
3667
- ...baseTemplateConfig[TEMPLATES_NAMES.BASE_TEMPLATE]
3668
- },
3669
- [TEMPLATES_NAMES.ORDER_PLACED]: {
3670
- ...baseTemplateConfig[TEMPLATES_NAMES.BASE_TEMPLATE]
3671
- },
3672
- [TEMPLATES_NAMES.ORDER_COMPLETED]: {
3673
- ...baseTemplateConfig[TEMPLATES_NAMES.BASE_TEMPLATE]
3674
- },
3675
- [TEMPLATES_NAMES.ORDER_UPDATED]: {
3676
- ...baseTemplateConfig[TEMPLATES_NAMES.BASE_TEMPLATE]
3677
- },
3678
- [TEMPLATES_NAMES.INVENTORY_LEVEL]: {
3679
- ...baseTemplateConfig[TEMPLATES_NAMES.BASE_TEMPLATE]
3603
+ /**
3604
+ * Check if template exists
3605
+ *
3606
+ * @param name - Template name
3607
+ * @returns True if template exists
3608
+ */
3609
+ hasTemplate(name) {
3610
+ return this.templateRegistry.has(name);
3680
3611
  }
3681
- });
3612
+ /**
3613
+ * List all registered template names
3614
+ *
3615
+ * @returns Array of template names
3616
+ */
3617
+ listTemplates() {
3618
+ return Array.from(this.templateRegistry.keys());
3619
+ }
3620
+ /**
3621
+ * Get base template configuration
3622
+ *
3623
+ * @returns Base template config
3624
+ */
3625
+ getBaseTemplate() {
3626
+ return this.baseTemplateConfig;
3627
+ }
3628
+ /**
3629
+ * Prepare template data.
3630
+ *
3631
+ * This method prepares the data for the template renderer.
3632
+ * Merge translations from template config and options (if provided),
3633
+ * then interpolate blocks using the interpolate function.
3634
+ *
3635
+ * @param params - Parameters object
3636
+ * @returns Prepared template data
3637
+ */
3638
+ prepareData(params) {
3639
+ var _a, _b, _c, _d;
3640
+ const locale = ((_a = params.options) == null ? void 0 : _a.locale) || "en";
3641
+ const template = this.getTemplate(params.templateName);
3642
+ const config2 = ((_b = template.getConfig) == null ? void 0 : _b.call(template)) || {};
3643
+ const configTranslations = (config2 == null ? void 0 : config2.translations) || {};
3644
+ const configBlocks = (config2 == null ? void 0 : config2.blocks) || [];
3645
+ const optionsBlocks = ((_c = params.options) == null ? void 0 : _c.blocks) || [];
3646
+ const optionsTranslations = (_d = params.options) == null ? void 0 : _d.translations;
3647
+ const blocks = optionsBlocks.length > 0 ? optionsBlocks : configBlocks;
3648
+ const mergedTranslations = mergeTranslations(
3649
+ configTranslations,
3650
+ optionsTranslations
3651
+ );
3652
+ const translator = createTranslator(locale, mergedTranslations);
3653
+ const interpolatedBlocks = blocks.length > 0 ? this.interpolateFunction(blocks, params.data, translator) : blocks;
3654
+ return {
3655
+ template,
3656
+ translator,
3657
+ blocks: interpolatedBlocks
3658
+ };
3659
+ }
3660
+ }
3661
+ function SectionBlock({
3662
+ id,
3663
+ props,
3664
+ data,
3665
+ isLastBlock,
3666
+ isFirstBlock
3667
+ }) {
3668
+ return /* @__PURE__ */ jsxRuntime.jsx(components.Section, { className: "m-0 p-0", children: /* @__PURE__ */ jsxRuntime.jsx(BlockRenderer, { blocks: props.blocks || [], data }) });
3669
+ }
3670
+ function TextBlock({
3671
+ id,
3672
+ props,
3673
+ isLastBlock,
3674
+ isFirstBlock
3675
+ }) {
3676
+ const className = ui.clx(
3677
+ isLastBlock ? "mb-0" : "mb-4",
3678
+ isFirstBlock && "mt-0"
3679
+ );
3680
+ return /* @__PURE__ */ jsxRuntime.jsx(components.Text, { className, children: typeof props.value === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { dangerouslySetInnerHTML: { __html: props.value } }) : props.value }, id);
3681
+ }
3682
+ function RepeaterBlock({
3683
+ id,
3684
+ props,
3685
+ data
3686
+ }) {
3687
+ const array = props.itemBlocks;
3688
+ return /* @__PURE__ */ jsxRuntime.jsx(BlockRenderer, { blocks: array, data });
3689
+ }
3690
+ function HeadingBlock({
3691
+ id,
3692
+ props,
3693
+ data,
3694
+ isLastBlock,
3695
+ isFirstBlock
3696
+ }) {
3697
+ const className = ui.clx(
3698
+ "text-xl",
3699
+ "font-bold",
3700
+ isLastBlock ? "mb-0" : "mb-4",
3701
+ isFirstBlock ? "mt-0" : "mt-4"
3702
+ );
3703
+ return /* @__PURE__ */ jsxRuntime.jsx(components.Heading, { className, children: props.value });
3704
+ }
3705
+ function RowBlock({
3706
+ id,
3707
+ props,
3708
+ data,
3709
+ isLastBlock,
3710
+ isFirstBlock
3711
+ }) {
3712
+ return /* @__PURE__ */ jsxRuntime.jsxs(components.Row, { children: [
3713
+ /* @__PURE__ */ jsxRuntime.jsx(components.Column, { className: "font-semibold", children: props.label }),
3714
+ /* @__PURE__ */ jsxRuntime.jsx(components.Column, { className: "text-right", children: typeof props.value === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { dangerouslySetInnerHTML: { __html: props.value } }) : props.value })
3715
+ ] });
3716
+ }
3717
+ function SeparatorBlock({
3718
+ id,
3719
+ props,
3720
+ isLastBlock,
3721
+ isFirstBlock
3722
+ }) {
3723
+ return /* @__PURE__ */ jsxRuntime.jsx(components.Hr, { className: "my-4 border-ui-border" });
3724
+ }
3725
+ function ProductItemBlock({
3726
+ props,
3727
+ data,
3728
+ isLastBlock,
3729
+ isFirstBlock
3730
+ }) {
3731
+ return /* @__PURE__ */ jsxRuntime.jsxs(components.Row, { children: [
3732
+ props.thumbnail && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3733
+ /* @__PURE__ */ jsxRuntime.jsx(components.Column, { className: "w-[50px]", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: props.thumbnail, width: 50, height: 50 }) }),
3734
+ /* @__PURE__ */ jsxRuntime.jsx(components.Column, { className: "w-[12px]" })
3735
+ ] }),
3736
+ /* @__PURE__ */ jsxRuntime.jsx(components.Column, { className: "text-left", children: typeof props.value === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { dangerouslySetInnerHTML: { __html: props.value } }) : props.value })
3737
+ ] });
3738
+ }
3739
+ function BlockRenderer({ blocks, data }) {
3740
+ return blocks.map((block, index) => {
3741
+ const blockKey = block.id || `block-${index}`;
3742
+ const isLastBlock = index === blocks.length - 1;
3743
+ const isFirstBlock = index === 0;
3744
+ switch (block.type) {
3745
+ case "section":
3746
+ return /* @__PURE__ */ jsxRuntime.jsx(
3747
+ SectionBlock,
3748
+ {
3749
+ id: blockKey,
3750
+ props: block.props,
3751
+ data,
3752
+ isLastBlock,
3753
+ isFirstBlock
3754
+ },
3755
+ blockKey
3756
+ );
3757
+ case "row":
3758
+ return /* @__PURE__ */ jsxRuntime.jsx(
3759
+ RowBlock,
3760
+ {
3761
+ id: blockKey,
3762
+ props: block.props,
3763
+ data,
3764
+ isLastBlock,
3765
+ isFirstBlock
3766
+ },
3767
+ blockKey
3768
+ );
3769
+ case "product-item":
3770
+ return /* @__PURE__ */ jsxRuntime.jsx(
3771
+ ProductItemBlock,
3772
+ {
3773
+ id: blockKey,
3774
+ props: block.props,
3775
+ data,
3776
+ isLastBlock,
3777
+ isFirstBlock
3778
+ },
3779
+ blockKey
3780
+ );
3781
+ case "heading":
3782
+ return /* @__PURE__ */ jsxRuntime.jsx(
3783
+ HeadingBlock,
3784
+ {
3785
+ id: blockKey,
3786
+ props: block.props,
3787
+ data,
3788
+ isLastBlock,
3789
+ isFirstBlock
3790
+ },
3791
+ blockKey
3792
+ );
3793
+ case "text":
3794
+ return /* @__PURE__ */ jsxRuntime.jsx(
3795
+ TextBlock,
3796
+ {
3797
+ id: blockKey,
3798
+ props: block.props,
3799
+ isLastBlock,
3800
+ isFirstBlock
3801
+ },
3802
+ blockKey
3803
+ );
3804
+ case "separator":
3805
+ return /* @__PURE__ */ jsxRuntime.jsx(
3806
+ SeparatorBlock,
3807
+ {
3808
+ id: blockKey,
3809
+ props: block.props,
3810
+ isLastBlock,
3811
+ isFirstBlock
3812
+ },
3813
+ blockKey
3814
+ );
3815
+ case "repeater":
3816
+ if (!data) {
3817
+ console.warn("RepeaterBlock requires data prop");
3818
+ return null;
3819
+ }
3820
+ return /* @__PURE__ */ jsxRuntime.jsx(
3821
+ RepeaterBlock,
3822
+ {
3823
+ id: blockKey,
3824
+ props: block.props,
3825
+ data
3826
+ },
3827
+ blockKey
3828
+ );
3829
+ default:
3830
+ return null;
3831
+ }
3832
+ });
3833
+ }
3834
+ function renderHTMLReact(data, options) {
3835
+ const theme = options.theme || {};
3836
+ const blocks = options.blocks || [];
3837
+ return /* @__PURE__ */ jsxRuntime.jsxs(components.Html, { children: [
3838
+ /* @__PURE__ */ jsxRuntime.jsx(components.Head, {}),
3839
+ /* @__PURE__ */ jsxRuntime.jsx(
3840
+ components.Tailwind,
3841
+ {
3842
+ config: {
3843
+ presets: [components.pixelBasedPreset],
3844
+ theme
3845
+ },
3846
+ children: /* @__PURE__ */ jsxRuntime.jsx(components.Body, { className: "mx-auto my-auto px-4 font-arial font-normal text-base bg-ui-bg text-ui-text", children: /* @__PURE__ */ jsxRuntime.jsx(components.Container, { className: "py-4", children: /* @__PURE__ */ jsxRuntime.jsx(BlockRenderer, { blocks, data }) }) })
3847
+ }
3848
+ )
3849
+ ] });
3850
+ }
3851
+ async function renderHTML(data, options) {
3852
+ return await render.pretty(await render.render(renderHTMLReact(data, options)));
3853
+ }
3854
+ async function renderText(data, options) {
3855
+ const html = await render.render(renderHTMLReact(data, options));
3856
+ return render.toPlainText(html);
3857
+ }
3858
+ async function getBaseTemplateHtml(data, options) {
3859
+ return await renderHTML(data, options);
3860
+ }
3861
+ async function getBaseTemplateText(data, options) {
3862
+ return await renderText(data, options);
3863
+ }
3864
+ function getBaseTemplateReactNode(data, options) {
3865
+ return renderHTMLReact(data, options);
3866
+ }
3867
+ const headerTitle$2 = "Nowa wiadomość z formularza kontaktowego";
3868
+ const labels$2 = {
3869
+ name: "Imię i nazwisko",
3870
+ email: "Email",
3871
+ phone: "Telefon",
3872
+ message: "Wiadomość"
3873
+ };
3874
+ const footer$2 = "Ta wiadomość została wysłana automatycznie z formularza kontaktowego";
3875
+ const pl$4 = {
3876
+ headerTitle: headerTitle$2,
3877
+ labels: labels$2,
3878
+ footer: footer$2
3879
+ };
3880
+ const headerTitle$1 = "New message from contact form";
3881
+ const labels$1 = {
3882
+ name: "Name",
3883
+ email: "Email",
3884
+ phone: "Phone",
3885
+ message: "Message"
3886
+ };
3887
+ const header$1 = {
3888
+ title: "New message from contact form",
3889
+ description: "This message was sent automatically from the contact form"
3890
+ };
3891
+ const footer$1 = "This message was sent automatically from the contact form";
3892
+ const en$4 = {
3893
+ headerTitle: headerTitle$1,
3894
+ labels: labels$1,
3895
+ header: header$1,
3896
+ footer: footer$1
3897
+ };
3898
+ const headerTitle = "New message from contact form";
3899
+ const labels = {
3900
+ name: "Name",
3901
+ email: "Email",
3902
+ phone: "Phone",
3903
+ message: "Message"
3904
+ };
3905
+ const header = {
3906
+ title: "New message from contact form",
3907
+ description: "This message was sent automatically from the contact form"
3908
+ };
3909
+ const footer = "This message was sent automatically from the contact form";
3910
+ const de = {
3911
+ headerTitle,
3912
+ labels,
3913
+ header,
3914
+ footer
3915
+ };
3916
+ const translations$4 = {
3917
+ pl: pl$4,
3918
+ en: en$4,
3919
+ de
3920
+ };
3921
+ const templateBlocks$4 = [
3922
+ {
3923
+ type: "section",
3924
+ id: "section-1",
3925
+ props: {
3926
+ blocks: [
3927
+ {
3928
+ id: "heading-1",
3929
+ type: "heading",
3930
+ props: {
3931
+ value: "{{translations.headerTitle}}"
3932
+ }
3933
+ }
3934
+ ]
3935
+ }
3936
+ },
3937
+ {
3938
+ id: "separator-1",
3939
+ type: "separator"
3940
+ },
3941
+ {
3942
+ type: "section",
3943
+ id: "section-1",
3944
+ props: {
3945
+ blocks: [
3946
+ {
3947
+ id: "row-1",
3948
+ type: "row",
3949
+ props: {
3950
+ label: "{{translations.labels.email}}",
3951
+ value: "{{data.contact_form.email}}"
3952
+ }
3953
+ },
3954
+ {
3955
+ id: "separator-1",
3956
+ type: "separator"
3957
+ },
3958
+ {
3959
+ id: "row-2",
3960
+ type: "row",
3961
+ props: {
3962
+ label: "{{translations.labels.phone}}",
3963
+ value: "{{data.contact_form.phone}}"
3964
+ }
3965
+ },
3966
+ {
3967
+ id: "separator-2",
3968
+ type: "separator"
3969
+ },
3970
+ {
3971
+ id: "row-3",
3972
+ type: "row",
3973
+ props: {
3974
+ label: "{{translations.labels.message}}",
3975
+ value: "{{data.contact_form.message}}"
3976
+ }
3977
+ }
3978
+ ]
3979
+ }
3980
+ }
3981
+ ];
3982
+ const general$7 = {
3983
+ headerTitle: "Poziom magazynowy został zmieniony",
3984
+ headerDescription: "Poziom magazynowy został zmieniony. Sprawdź szczegóły.",
3985
+ labels: {
3986
+ inventoryLevelId: "ID",
3987
+ inventoryLevelLocation: "Lokalizacja",
3988
+ inventoryLevelStockedQuantity: "Ilość na stanie",
3989
+ inventoryLevelReservedQuantity: "Ilość zarezerwowana",
3990
+ inventoryLevelAvailableQuantity: "Ilość dostępna"
3991
+ },
3992
+ footer: "Jeśli masz pytania dotyczące poziomu magazynowego, skontaktuj się z nami."
3993
+ };
3994
+ const pl$3 = {
3995
+ general: general$7
3996
+ };
3997
+ const general$6 = {
3998
+ headerTitle: "#{{inventoryLevelId}} - Inventory level has been updated",
3999
+ headerDescription: "Inventory level has been updated. Check the details.",
4000
+ labels: {
4001
+ inventoryLevelId: "Inventory Level ID",
4002
+ inventoryLevelLocation: "Inventory Level Location",
4003
+ inventoryLevelDate: "Inventory Level Date"
4004
+ },
4005
+ footer: "If you have any questions, please contact us."
4006
+ };
4007
+ const en$3 = {
4008
+ general: general$6
4009
+ };
4010
+ const translations$3 = {
4011
+ pl: pl$3,
4012
+ en: en$3
4013
+ };
4014
+ const templateBlocks$3 = [
4015
+ {
4016
+ type: "section",
4017
+ id: "section-1",
4018
+ props: {
4019
+ blocks: [
4020
+ {
4021
+ id: "heading-1",
4022
+ type: "heading",
4023
+ props: {
4024
+ value: "{{translations.headerTitle}}"
4025
+ }
4026
+ },
4027
+ {
4028
+ id: "text-1",
4029
+ type: "text",
4030
+ props: {
4031
+ value: "{{translations.headerDescription}}"
4032
+ }
4033
+ }
4034
+ ]
4035
+ }
4036
+ },
4037
+ {
4038
+ id: "separator-1",
4039
+ type: "separator"
4040
+ },
4041
+ {
4042
+ type: "section",
4043
+ id: "section-2",
4044
+ props: {
4045
+ blocks: [
4046
+ {
4047
+ id: "row-1",
4048
+ type: "row",
4049
+ props: {
4050
+ label: "{{translations.labels.inventoryLevelId}}",
4051
+ value: "{{data.inventory_level.id}}"
4052
+ }
4053
+ },
4054
+ {
4055
+ id: "separator-1",
4056
+ type: "separator"
4057
+ },
4058
+ {
4059
+ id: "row-2",
4060
+ type: "row",
4061
+ props: {
4062
+ label: "{{translations.labels.inventoryLevelLocation}}",
4063
+ value: "{{data.inventory_level.location_id}}"
4064
+ }
4065
+ },
4066
+ {
4067
+ id: "separator-2",
4068
+ type: "separator"
4069
+ },
4070
+ {
4071
+ id: "row-3",
4072
+ type: "row",
4073
+ props: {
4074
+ label: "{{translations.labels.inventoryLevelStockedQuantity}}",
4075
+ value: "{{data.inventory_level.stocked_quantity}}"
4076
+ }
4077
+ },
4078
+ {
4079
+ id: "separator-3",
4080
+ type: "separator"
4081
+ },
4082
+ {
4083
+ id: "row-4",
4084
+ type: "row",
4085
+ props: {
4086
+ label: "{{translations.labels.inventoryLevelReservedQuantity}}",
4087
+ value: "{{data.inventory_level.reserved_quantity}}"
4088
+ }
4089
+ },
4090
+ {
4091
+ id: "separator-4",
4092
+ type: "separator"
4093
+ },
4094
+ {
4095
+ id: "row-5",
4096
+ type: "row",
4097
+ props: {
4098
+ label: "{{translations.labels.inventoryLevelAvailableQuantity}}",
4099
+ value: "{{data.inventory_level.available_quantity}}"
4100
+ }
4101
+ }
4102
+ ]
4103
+ }
4104
+ },
4105
+ {
4106
+ id: "separator-1",
4107
+ type: "separator"
4108
+ },
4109
+ {
4110
+ type: "section",
4111
+ id: "section-3",
4112
+ props: {
4113
+ blocks: [
4114
+ {
4115
+ id: "text-2",
4116
+ type: "text",
4117
+ props: {
4118
+ value: "{{translations.footer}}"
4119
+ }
4120
+ }
4121
+ ]
4122
+ }
4123
+ }
4124
+ ];
4125
+ const general$5 = {
4126
+ headerTitle: "{{data.order.transformed.order_number}} - Zamówienie zostało złożone",
4127
+ headerDescription: "Twoje zamówienie zostało przyjęte i jest w trakcie realizacji. Wkrótce otrzymasz e-mail z informacją o statusie zamówienia.",
4128
+ labels: {
4129
+ salesChannel: "Kanał sprzedaży",
4130
+ salesChannelDescription: "Opis kanału sprzedaży",
4131
+ orderNumber: "Numer zamówienia",
4132
+ orderDate: "Data zamówienia",
4133
+ products: "Produkty",
4134
+ shippingAddress: "Adres dostawy",
4135
+ orderTotal: "Wartość zamówienia",
4136
+ taxTotal: "VAT",
4137
+ discountTotal: "Rabat",
4138
+ paidTotal: "Zapłacone",
4139
+ currency: "Waluta",
4140
+ currencyCode: "Kod waluty",
4141
+ currencySymbol: "Symbol waluty"
4142
+ },
4143
+ noData: "Brak danych",
4144
+ viewOrderButton: "Zobacz szczegóły zamówienia",
4145
+ footer: "Jeśli masz pytania dotyczące zamówienia, skontaktuj się z nami."
4146
+ };
4147
+ const pl$2 = {
4148
+ general: general$5
4149
+ };
4150
+ const general$4 = {
4151
+ headerTitle: "{{data.orderNumber}} - Order placed",
4152
+ headerDescription: "Your order has been received and is being processed. You will receive an email with information about the status of your order shortly.",
4153
+ labels: {
4154
+ salesChannel: "Sales Channel",
4155
+ salesChannelDescription: "Sales Channel Description",
4156
+ orderNumber: "Order Number",
4157
+ orderDate: "Order Date",
4158
+ products: "Products",
4159
+ shippingAddress: "Shipping Address",
4160
+ orderTotal: "Order Total",
4161
+ taxTotal: "VAT",
4162
+ discountTotal: "Discount",
4163
+ paidTotal: "Paid",
4164
+ currency: "Currency",
4165
+ currencyCode: "Currency Code",
4166
+ currencySymbol: "Currency Symbol"
4167
+ },
4168
+ noData: "No data",
4169
+ viewOrderButton: "View Order Details",
4170
+ footer: "If you have any questions about your order, please contact us."
4171
+ };
4172
+ const en$2 = {
4173
+ general: general$4
4174
+ };
4175
+ const translations$2 = {
4176
+ pl: pl$2,
4177
+ en: en$2
4178
+ };
4179
+ const templateBlocks$2 = [
4180
+ {
4181
+ type: "section",
4182
+ id: "section-1",
4183
+ props: {
4184
+ blocks: [
4185
+ {
4186
+ id: "heading-1",
4187
+ type: "heading",
4188
+ props: {
4189
+ value: "{{translations.headerTitle}}"
4190
+ }
4191
+ },
4192
+ {
4193
+ id: "text-1",
4194
+ type: "text",
4195
+ props: {
4196
+ value: "{{translations.headerDescription}}"
4197
+ }
4198
+ }
4199
+ ]
4200
+ }
4201
+ },
4202
+ {
4203
+ id: "separator-1",
4204
+ type: "separator"
4205
+ },
4206
+ {
4207
+ type: "section",
4208
+ id: "section-2",
4209
+ props: {
4210
+ blocks: [
4211
+ {
4212
+ id: "row-1",
4213
+ type: "row",
4214
+ props: {
4215
+ label: "{{translations.labels.salesChannel}}",
4216
+ value: "{{data.order.sales_channel.name}}"
4217
+ }
4218
+ },
4219
+ {
4220
+ id: "separator-1",
4221
+ type: "separator"
4222
+ },
4223
+ {
4224
+ id: "row-2",
4225
+ type: "row",
4226
+ props: {
4227
+ label: "{{translations.labels.orderNumber}}",
4228
+ value: "{{data.order.transformed.order_number}}"
4229
+ }
4230
+ },
4231
+ {
4232
+ id: "separator-2",
4233
+ type: "separator"
4234
+ },
4235
+ {
4236
+ id: "row-3",
4237
+ type: "row",
4238
+ props: {
4239
+ label: "{{translations.labels.orderDate}}",
4240
+ value: "{{data.order.transformed.order_date}}"
4241
+ }
4242
+ }
4243
+ ]
4244
+ }
4245
+ },
4246
+ {
4247
+ id: "separator-1",
4248
+ type: "separator"
4249
+ },
4250
+ {
4251
+ type: "section",
4252
+ id: "section-3",
4253
+ props: {
4254
+ blocks: [
4255
+ {
4256
+ id: "heading-2",
4257
+ type: "heading",
4258
+ props: {
4259
+ value: "{{translations.labels.products}}"
4260
+ }
4261
+ },
4262
+ {
4263
+ id: "repeater-1",
4264
+ type: "repeater",
4265
+ props: {
4266
+ arrayPath: "order.transformed.items",
4267
+ itemBlocks: [
4268
+ {
4269
+ id: "product-item",
4270
+ type: "product-item",
4271
+ props: {
4272
+ label: "{{translations.labels.product}}",
4273
+ thumbnail: "{{data.order.transformed.items.thumbnail}}",
4274
+ value: "{{data.order.transformed.items.title}} - {{data.order.transformed.items.quantity}}x {{data.order.transformed.items.price}}"
4275
+ }
4276
+ }
4277
+ ]
4278
+ }
4279
+ }
4280
+ ]
4281
+ }
4282
+ },
4283
+ {
4284
+ id: "separator-1",
4285
+ type: "separator"
4286
+ },
4287
+ {
4288
+ type: "section",
4289
+ id: "section-4",
4290
+ props: {
4291
+ blocks: [
4292
+ {
4293
+ id: "heading-3",
4294
+ type: "heading",
4295
+ props: {
4296
+ value: "{{translations.labels.shippingAddress}}"
4297
+ }
4298
+ },
4299
+ {
4300
+ id: "text-2",
4301
+ type: "text",
4302
+ props: {
4303
+ value: "{{data.order.transformed.shipping_address_text}}"
4304
+ }
4305
+ }
4306
+ ]
4307
+ }
4308
+ },
4309
+ {
4310
+ id: "separator-1",
4311
+ type: "separator"
4312
+ },
4313
+ {
4314
+ type: "section",
4315
+ id: "section-5",
4316
+ props: {
4317
+ blocks: [
4318
+ {
4319
+ id: "row-4",
4320
+ type: "row",
4321
+ props: {
4322
+ label: "{{translations.labels.discountTotal}}",
4323
+ value: "{{data.order.transformed.summary.discount_total}}"
4324
+ }
4325
+ },
4326
+ {
4327
+ id: "separator-3",
4328
+ type: "separator"
4329
+ },
4330
+ {
4331
+ id: "row-5",
4332
+ type: "row",
4333
+ props: {
4334
+ label: "{{translations.labels.orderTotal}}",
4335
+ value: "{{data.order.transformed.summary.total}}"
4336
+ }
4337
+ },
4338
+ {
4339
+ id: "separator-4",
4340
+ type: "separator"
4341
+ },
4342
+ {
4343
+ id: "row-6",
4344
+ type: "row",
4345
+ props: {
4346
+ label: "{{translations.labels.paidTotal}}",
4347
+ value: "{{data.order.transformed.summary.paid_total}}"
4348
+ }
4349
+ },
4350
+ {
4351
+ id: "separator-5",
4352
+ type: "separator"
4353
+ },
4354
+ {
4355
+ id: "row-7",
4356
+ type: "row",
4357
+ props: {
4358
+ label: "{{translations.labels.taxTotal}}",
4359
+ value: "{{data.order.transformed.summary.tax_total}}"
4360
+ }
4361
+ }
4362
+ ]
4363
+ }
4364
+ },
4365
+ {
4366
+ id: "separator-1",
4367
+ type: "separator"
4368
+ },
4369
+ {
4370
+ type: "section",
4371
+ id: "section-6",
4372
+ props: {
4373
+ blocks: [
4374
+ {
4375
+ id: "text-3",
4376
+ type: "text",
4377
+ props: {
4378
+ value: "{{translations.footer}}"
4379
+ }
4380
+ }
4381
+ ]
4382
+ }
4383
+ }
4384
+ ];
4385
+ const general$3 = {
4386
+ headerTitle: "{{data.order.transformed.order_number}} - Zamówienie zostało zrealizowane",
4387
+ headerDescription: "Twoje zamówienie zostało zrealizowane i wysłane. Dziękujemy za zakupy!",
4388
+ labels: {
4389
+ product: "Produkt",
4390
+ salesChannel: "Kanał sprzedaży",
4391
+ salesChannelDescription: "Opis kanału sprzedaży",
4392
+ orderNumber: "Numer zamówienia",
4393
+ orderDate: "Data zamówienia",
4394
+ completedDate: "Data realizacji",
4395
+ products: "Produkty",
4396
+ shippingAddress: "Adres dostawy",
4397
+ orderTotal: "Wartość zamówienia",
4398
+ taxTotal: "VAT",
4399
+ discountTotal: "Rabat",
4400
+ paidTotal: "Zapłacone",
4401
+ currency: "Waluta",
4402
+ currencyCode: "Kod waluty",
4403
+ currencySymbol: "Symbol waluty"
4404
+ },
4405
+ noData: "Brak danych",
4406
+ viewOrderButton: "Zobacz szczegóły zamówienia",
4407
+ footer: "Jeśli masz pytania dotyczące zamówienia, skontaktuj się z nami."
4408
+ };
4409
+ const pl$1 = {
4410
+ general: general$3
4411
+ };
4412
+ const general$2 = {
4413
+ headerTitle: "{{data.order.transformed.order_number}} - Order completed",
4414
+ headerDescription: "Your order has been completed and shipped. Thank you for your purchase!",
4415
+ labels: {
4416
+ product: "Product",
4417
+ salesChannel: "Sales Channel",
4418
+ salesChannelDescription: "Sales Channel Description",
4419
+ orderNumber: "Order Number",
4420
+ orderDate: "Order Date",
4421
+ completedDate: "Completion Date",
4422
+ products: "Products",
4423
+ shippingAddress: "Shipping Address",
4424
+ orderTotal: "Order Total",
4425
+ taxTotal: "VAT",
4426
+ discountTotal: "Discount",
4427
+ paidTotal: "Paid",
4428
+ currency: "Currency",
4429
+ currencyCode: "Currency Code",
4430
+ currencySymbol: "Currency Symbol"
4431
+ },
4432
+ noData: "No data",
4433
+ viewOrderButton: "View Order Details",
4434
+ footer: "If you have any questions about your order, please contact us."
4435
+ };
4436
+ const en$1 = {
4437
+ general: general$2
4438
+ };
4439
+ const translations$1 = {
4440
+ pl: pl$1,
4441
+ en: en$1
4442
+ };
4443
+ const templateBlocks$1 = [
4444
+ {
4445
+ type: "section",
4446
+ id: "section-1",
4447
+ props: {
4448
+ blocks: [
4449
+ {
4450
+ id: "heading-1",
4451
+ type: "heading",
4452
+ props: {
4453
+ value: "{{translations.headerTitle}}"
4454
+ }
4455
+ },
4456
+ {
4457
+ id: "text-1",
4458
+ type: "text",
4459
+ props: {
4460
+ value: "{{translations.headerDescription}}"
4461
+ }
4462
+ }
4463
+ ]
4464
+ }
4465
+ },
4466
+ {
4467
+ id: "separator-1",
4468
+ type: "separator"
4469
+ },
4470
+ {
4471
+ type: "section",
4472
+ id: "section-2",
4473
+ props: {
4474
+ blocks: [
4475
+ {
4476
+ id: "row-1",
4477
+ type: "row",
4478
+ props: {
4479
+ label: "{{translations.labels.salesChannel}}",
4480
+ value: "{{data.order.sales_channel.name}}"
4481
+ }
4482
+ },
4483
+ {
4484
+ id: "separator-1",
4485
+ type: "separator"
4486
+ },
4487
+ {
4488
+ id: "row-2",
4489
+ type: "row",
4490
+ props: {
4491
+ label: "{{translations.labels.orderNumber}}",
4492
+ value: "{{data.order.transformed.order_number}}"
4493
+ }
4494
+ },
4495
+ {
4496
+ id: "separator-2",
4497
+ type: "separator"
4498
+ },
4499
+ {
4500
+ id: "row-3",
4501
+ type: "row",
4502
+ props: {
4503
+ label: "{{translations.labels.orderDate}}",
4504
+ value: "{{data.order.transformed.order_date}}"
4505
+ }
4506
+ }
4507
+ ]
4508
+ }
4509
+ },
4510
+ {
4511
+ id: "separator-1",
4512
+ type: "separator"
4513
+ },
4514
+ {
4515
+ type: "section",
4516
+ id: "section-3",
4517
+ props: {
4518
+ blocks: [
4519
+ {
4520
+ id: "heading-2",
4521
+ type: "heading",
4522
+ props: {
4523
+ value: "{{translations.labels.products}}"
4524
+ }
4525
+ },
4526
+ {
4527
+ id: "repeater-1",
4528
+ type: "repeater",
4529
+ props: {
4530
+ arrayPath: "order.transformed.items",
4531
+ itemBlocks: [
4532
+ {
4533
+ id: "product-item",
4534
+ type: "product-item",
4535
+ props: {
4536
+ label: "{{translations.labels.product}}",
4537
+ thumbnail: "{{data.order.transformed.items.thumbnail}}",
4538
+ value: "{{data.order.transformed.items.title}} - {{data.order.transformed.items.quantity}}x {{data.order.transformed.items.price}}"
4539
+ }
4540
+ }
4541
+ ]
4542
+ }
4543
+ }
4544
+ ]
4545
+ }
4546
+ },
4547
+ {
4548
+ id: "separator-1",
4549
+ type: "separator"
4550
+ },
4551
+ {
4552
+ type: "section",
4553
+ id: "section-4",
4554
+ props: {
4555
+ blocks: [
4556
+ {
4557
+ id: "heading-3",
4558
+ type: "heading",
4559
+ props: {
4560
+ value: "{{translations.labels.shippingAddress}}"
4561
+ }
4562
+ },
4563
+ {
4564
+ id: "text-2",
4565
+ type: "text",
4566
+ props: {
4567
+ value: "{{data.order.transformed.shipping_address_text}}"
4568
+ }
4569
+ }
4570
+ ]
4571
+ }
4572
+ },
4573
+ {
4574
+ id: "separator-1",
4575
+ type: "separator"
4576
+ },
4577
+ {
4578
+ type: "section",
4579
+ id: "section-5",
4580
+ props: {
4581
+ blocks: [
4582
+ {
4583
+ id: "row-4",
4584
+ type: "row",
4585
+ props: {
4586
+ label: "{{translations.labels.discountTotal}}",
4587
+ value: "{{data.order.transformed.summary.discount_total}}"
4588
+ }
4589
+ },
4590
+ {
4591
+ id: "separator-3",
4592
+ type: "separator"
4593
+ },
4594
+ {
4595
+ id: "row-5",
4596
+ type: "row",
4597
+ props: {
4598
+ label: "{{translations.labels.orderTotal}}",
4599
+ value: "{{data.order.transformed.summary.total}}"
4600
+ }
4601
+ },
4602
+ {
4603
+ id: "separator-4",
4604
+ type: "separator"
4605
+ },
4606
+ {
4607
+ id: "row-6",
4608
+ type: "row",
4609
+ props: {
4610
+ label: "{{translations.labels.paidTotal}}",
4611
+ value: "{{data.order.transformed.summary.paid_total}}"
4612
+ }
4613
+ },
4614
+ {
4615
+ id: "separator-5",
4616
+ type: "separator"
4617
+ },
4618
+ {
4619
+ id: "row-7",
4620
+ type: "row",
4621
+ props: {
4622
+ label: "{{translations.labels.taxTotal}}",
4623
+ value: "{{data.order.transformed.summary.tax_total}}"
4624
+ }
4625
+ }
4626
+ ]
4627
+ }
4628
+ },
4629
+ {
4630
+ id: "separator-1",
4631
+ type: "separator"
4632
+ },
4633
+ {
4634
+ type: "section",
4635
+ id: "section-6",
4636
+ props: {
4637
+ blocks: [
4638
+ {
4639
+ id: "text-3",
4640
+ type: "text",
4641
+ props: {
4642
+ value: "{{translations.footer}}"
4643
+ }
4644
+ }
4645
+ ]
4646
+ }
4647
+ }
4648
+ ];
4649
+ const general$1 = {
4650
+ headerTitle: "{{data.order.transformed.order_number}} - Zamówienie zostało zaktualizowane",
4651
+ headerDescription: "Twoje zamówienie zostało zaktualizowane. Sprawdź szczegóły zamówienia.",
4652
+ labels: {
4653
+ salesChannel: "Kanał sprzedaży",
4654
+ salesChannelDescription: "Opis kanału sprzedaży",
4655
+ orderNumber: "Numer zamówienia",
4656
+ orderDate: "Data zamówienia",
4657
+ products: "Produkty",
4658
+ shippingAddress: "Adres dostawy",
4659
+ orderTotal: "Wartość zamówienia",
4660
+ taxTotal: "VAT",
4661
+ discountTotal: "Rabat",
4662
+ paidTotal: "Zapłacone",
4663
+ currency: "Waluta",
4664
+ currencyCode: "Kod waluty",
4665
+ currencySymbol: "Symbol waluty"
4666
+ },
4667
+ noData: "Brak danych",
4668
+ viewOrderButton: "Zobacz szczegóły zamówienia",
4669
+ footer: "Jeśli masz pytania dotyczące zamówienia, skontaktuj się z nami."
4670
+ };
4671
+ const pl = {
4672
+ general: general$1
4673
+ };
4674
+ const general = {
4675
+ headerTitle: "{{data.order.transformed.order_number}} - Order placed",
4676
+ headerDescription: "Your order has been received and is being processed. You will receive an email with information about the status of your order shortly.",
4677
+ labels: {
4678
+ salesChannel: "Sales Channel",
4679
+ salesChannelDescription: "Sales Channel Description",
4680
+ orderNumber: "Order Number",
4681
+ orderDate: "Order Date",
4682
+ products: "Products",
4683
+ shippingAddress: "Shipping Address",
4684
+ orderTotal: "Order Total",
4685
+ taxTotal: "VAT",
4686
+ discountTotal: "Discount",
4687
+ paidTotal: "Paid",
4688
+ currency: "Currency",
4689
+ currencyCode: "Currency Code",
4690
+ currencySymbol: "Currency Symbol"
4691
+ },
4692
+ noData: "No data",
4693
+ viewOrderButton: "View Order Details",
4694
+ footer: "If you have any questions about your order, please contact us."
4695
+ };
4696
+ const en = {
4697
+ general
4698
+ };
4699
+ const translations = {
4700
+ pl,
4701
+ en
4702
+ };
4703
+ const templateBlocks = [
4704
+ {
4705
+ type: "section",
4706
+ id: "section-1",
4707
+ props: {
4708
+ blocks: [
4709
+ {
4710
+ id: "heading-1",
4711
+ type: "heading",
4712
+ props: {
4713
+ value: "{{translations.headerTitle}}"
4714
+ }
4715
+ },
4716
+ {
4717
+ id: "text-1",
4718
+ type: "text",
4719
+ props: {
4720
+ value: "{{translations.headerDescription}}"
4721
+ }
4722
+ }
4723
+ ]
4724
+ }
4725
+ },
4726
+ {
4727
+ id: "separator-1",
4728
+ type: "separator"
4729
+ },
4730
+ {
4731
+ type: "section",
4732
+ id: "section-2",
4733
+ props: {
4734
+ blocks: [
4735
+ {
4736
+ id: "row-1",
4737
+ type: "row",
4738
+ props: {
4739
+ label: "{{translations.labels.salesChannel}}",
4740
+ value: "{{data.order.sales_channel.name}}"
4741
+ }
4742
+ },
4743
+ {
4744
+ id: "separator-1",
4745
+ type: "separator"
4746
+ },
4747
+ {
4748
+ id: "row-2",
4749
+ type: "row",
4750
+ props: {
4751
+ label: "{{translations.labels.orderNumber}}",
4752
+ value: "{{data.order.transformed.order_number}}"
4753
+ }
4754
+ },
4755
+ {
4756
+ id: "separator-2",
4757
+ type: "separator"
4758
+ },
4759
+ {
4760
+ id: "row-3",
4761
+ type: "row",
4762
+ props: {
4763
+ label: "{{translations.labels.orderDate}}",
4764
+ value: "{{data.order.transformed.order_date}}"
4765
+ }
4766
+ }
4767
+ ]
4768
+ }
4769
+ },
4770
+ {
4771
+ id: "separator-1",
4772
+ type: "separator"
4773
+ },
4774
+ {
4775
+ type: "section",
4776
+ id: "section-3",
4777
+ props: {
4778
+ blocks: [
4779
+ {
4780
+ id: "heading-2",
4781
+ type: "heading",
4782
+ props: {
4783
+ value: "{{translations.labels.products}}"
4784
+ }
4785
+ },
4786
+ {
4787
+ id: "repeater-1",
4788
+ type: "repeater",
4789
+ props: {
4790
+ arrayPath: "order.transformed.items",
4791
+ itemBlocks: [
4792
+ {
4793
+ id: "product-item",
4794
+ type: "product-item",
4795
+ props: {
4796
+ label: "{{translations.labels.product}}",
4797
+ thumbnail: "{{data.order.transformed.items.thumbnail}}",
4798
+ value: "{{data.order.transformed.items.title}} - {{data.order.transformed.items.quantity}}x {{data.order.transformed.items.price}}"
4799
+ }
4800
+ }
4801
+ ]
4802
+ }
4803
+ }
4804
+ ]
4805
+ }
4806
+ },
4807
+ {
4808
+ id: "separator-1",
4809
+ type: "separator"
4810
+ },
4811
+ {
4812
+ type: "section",
4813
+ id: "section-4",
4814
+ props: {
4815
+ blocks: [
4816
+ {
4817
+ id: "heading-3",
4818
+ type: "heading",
4819
+ props: {
4820
+ value: "{{translations.labels.shippingAddress}}"
4821
+ }
4822
+ },
4823
+ {
4824
+ id: "text-2",
4825
+ type: "text",
4826
+ props: {
4827
+ value: "{{data.order.transformed.shipping_address_text}}"
4828
+ }
4829
+ }
4830
+ ]
4831
+ }
4832
+ },
4833
+ {
4834
+ id: "separator-1",
4835
+ type: "separator"
4836
+ },
4837
+ {
4838
+ type: "section",
4839
+ id: "section-5",
4840
+ props: {
4841
+ blocks: [
4842
+ {
4843
+ id: "row-4",
4844
+ type: "row",
4845
+ props: {
4846
+ label: "{{translations.labels.discountTotal}}",
4847
+ value: "{{data.order.transformed.summary.discount_total}}"
4848
+ }
4849
+ },
4850
+ {
4851
+ id: "separator-3",
4852
+ type: "separator"
4853
+ },
4854
+ {
4855
+ id: "row-5",
4856
+ type: "row",
4857
+ props: {
4858
+ label: "{{translations.labels.orderTotal}}",
4859
+ value: "{{data.order.transformed.summary.total}}"
4860
+ }
4861
+ },
4862
+ {
4863
+ id: "separator-4",
4864
+ type: "separator"
4865
+ },
4866
+ {
4867
+ id: "row-6",
4868
+ type: "row",
4869
+ props: {
4870
+ label: "{{translations.labels.paidTotal}}",
4871
+ value: "{{data.order.transformed.summary.paid_total}}"
4872
+ }
4873
+ },
4874
+ {
4875
+ id: "separator-5",
4876
+ type: "separator"
4877
+ },
4878
+ {
4879
+ id: "row-7",
4880
+ type: "row",
4881
+ props: {
4882
+ label: "{{translations.labels.taxTotal}}",
4883
+ value: "{{data.order.transformed.summary.tax_total}}"
4884
+ }
4885
+ }
4886
+ ]
4887
+ }
4888
+ },
4889
+ {
4890
+ id: "separator-1",
4891
+ type: "separator"
4892
+ },
4893
+ {
4894
+ type: "section",
4895
+ id: "section-6",
4896
+ props: {
4897
+ blocks: [
4898
+ {
4899
+ id: "text-3",
4900
+ type: "text",
4901
+ props: {
4902
+ value: "{{translations.footer}}"
4903
+ }
4904
+ }
4905
+ ]
4906
+ }
4907
+ }
4908
+ ];
4909
+ class EmailTemplateService extends AbstractTemplateService {
4910
+ constructor() {
4911
+ super();
4912
+ this.baseTemplateConfig = {
4913
+ getHtml: async (data, options) => {
4914
+ return await getBaseTemplateHtml(data, options);
4915
+ },
4916
+ getText: async (data, options) => {
4917
+ return await getBaseTemplateText(data, options);
4918
+ },
4919
+ getReactNode: (data, options) => {
4920
+ return getBaseTemplateReactNode(data, options);
4921
+ }
4922
+ };
4923
+ this.interpolateFunction = this.interpolateBlocks.bind(this);
4924
+ this.registerTemplate(
4925
+ TEMPLATES_NAMES.BASE_TEMPLATE,
4926
+ this.baseTemplateConfig
4927
+ );
4928
+ this.initializeDefaultTemplates();
4929
+ }
4930
+ /**
4931
+ * Initialize default email templates
4932
+ */
4933
+ initializeDefaultTemplates() {
4934
+ this.registerTemplate(TEMPLATES_NAMES.CONTACT_FORM, {
4935
+ ...this.baseTemplateConfig,
4936
+ getConfig: () => {
4937
+ return {
4938
+ blocks: templateBlocks$4,
4939
+ translations: translations$4
4940
+ };
4941
+ }
4942
+ });
4943
+ this.registerTemplate(TEMPLATES_NAMES.ORDER_PLACED, {
4944
+ ...this.baseTemplateConfig,
4945
+ getConfig: () => {
4946
+ return {
4947
+ blocks: templateBlocks$2,
4948
+ translations: translations$2
4949
+ };
4950
+ }
4951
+ });
4952
+ this.registerTemplate(TEMPLATES_NAMES.ORDER_COMPLETED, {
4953
+ ...this.baseTemplateConfig,
4954
+ getConfig: () => {
4955
+ return {
4956
+ blocks: templateBlocks$1,
4957
+ translations: translations$1
4958
+ };
4959
+ }
4960
+ });
4961
+ this.registerTemplate(TEMPLATES_NAMES.ORDER_UPDATED, {
4962
+ ...this.baseTemplateConfig,
4963
+ getConfig: () => {
4964
+ return {
4965
+ blocks: templateBlocks,
4966
+ translations
4967
+ };
4968
+ }
4969
+ });
4970
+ this.registerTemplate(TEMPLATES_NAMES.INVENTORY_LEVEL, {
4971
+ ...this.baseTemplateConfig,
4972
+ getConfig: () => {
4973
+ return {
4974
+ blocks: templateBlocks$3,
4975
+ translations: translations$3
4976
+ };
4977
+ }
4978
+ });
4979
+ }
4980
+ /**
4981
+ * Recursively interpolate text in blocks using the multiInterpolate function
4982
+ * Processes props.[property] in each block and nested blocks
4983
+ *
4984
+ * @param blocks - Blocks to interpolate
4985
+ * @param data - Data object for interpolation
4986
+ * @param translator - Translator instance with t method (created using createTranslator function)
4987
+ * @param config - Configuration object
4988
+ * @returns Interpolated blocks
4989
+ *
4990
+ * @example
4991
+ *
4992
+ * const blocks = [ { type: "text", props: { value: "Order {{data.order.id}} - {{translations.headerTitle}}" } } ]
4993
+ * const data = { order: { id: "123" } }
4994
+ * const translator = translator instance (created using createTranslator function)
4995
+ * const config = {}
4996
+ *
4997
+ * const interpolatedBlocks = interpolateBlocks(blocks, data, translator, config)
4998
+ *
4999
+ * Return: [ { type: "text", props: { value: "Order 123 - Order Confirmation" } } ]
5000
+ *
5001
+ */
5002
+ interpolateBlocks(blocks, data, translator, config2) {
5003
+ return blocks.map((block) => {
5004
+ var _a;
5005
+ const processedBlock = { ...block };
5006
+ if (processedBlock.props && typeof processedBlock.props === "object") {
5007
+ const processedProps = { ...processedBlock.props };
5008
+ for (const [key, value] of Object.entries(processedProps)) {
5009
+ if (typeof value === "string" && key !== "blocks" && key !== "itemBlocks" && key !== "arrayPath") {
5010
+ processedProps[key] = multiInterpolate(
5011
+ value,
5012
+ data,
5013
+ translator,
5014
+ config2
5015
+ );
5016
+ }
5017
+ }
5018
+ processedBlock.props = processedProps;
5019
+ }
5020
+ if (((_a = processedBlock.props) == null ? void 0 : _a.blocks) && Array.isArray(processedBlock.props.blocks)) {
5021
+ processedBlock.props = {
5022
+ ...processedBlock.props,
5023
+ blocks: this.interpolateBlocks(
5024
+ processedBlock.props.blocks,
5025
+ data,
5026
+ translator
5027
+ )
5028
+ };
5029
+ }
5030
+ if (processedBlock.type === "repeater") {
5031
+ const { arrayPath, itemBlocks } = processedBlock.props || {};
5032
+ if (arrayPath && itemBlocks) {
5033
+ const array = pickValueFromObject(arrayPath, data);
5034
+ if (Array.isArray(array) && array.length > 0) {
5035
+ const interpolatedItemBlocks = array.map(
5036
+ (item) => this.interpolateBlocks(itemBlocks, item, translator, {
5037
+ arrayPath
5038
+ })[0]
5039
+ );
5040
+ processedBlock.props = {
5041
+ ...processedBlock.props,
5042
+ itemBlocks: interpolatedItemBlocks
5043
+ };
5044
+ }
5045
+ }
5046
+ }
5047
+ return processedBlock;
5048
+ });
5049
+ }
5050
+ /**
5051
+ * Render email template
5052
+ *
5053
+ * @param params - Render parameters
5054
+ * @returns Rendered email with html, text, and subject
5055
+ */
5056
+ async render(params) {
5057
+ if (!params.templateName) {
5058
+ throw new Error("Template name is required");
5059
+ }
5060
+ const { template, blocks, translator } = this.prepareData({
5061
+ templateName: params.templateName,
5062
+ data: params.data,
5063
+ options: params.options
5064
+ });
5065
+ const options = {
5066
+ ...params.options,
5067
+ blocks
5068
+ };
5069
+ return {
5070
+ html: await template.getHtml(params.data, options),
5071
+ text: await template.getText(params.data, options),
5072
+ subject: multiInterpolate(
5073
+ "{{translations.headerTitle}}",
5074
+ params.data,
5075
+ translator
5076
+ )
5077
+ };
5078
+ }
5079
+ /**
5080
+ * Render email template synchronously (for previews)
5081
+ *
5082
+ * @param params - Render parameters
5083
+ * @returns React node
5084
+ */
5085
+ renderSync(params) {
5086
+ if (!params.templateName) {
5087
+ throw new Error("Template name is required");
5088
+ }
5089
+ const { template, blocks } = this.prepareData({
5090
+ templateName: params.templateName,
5091
+ data: params.data,
5092
+ options: params.options
5093
+ });
5094
+ const options = {
5095
+ ...params.options,
5096
+ blocks
5097
+ };
5098
+ return {
5099
+ reactNode: template.getReactNode ? template.getReactNode(params.data, options) : void 0
5100
+ };
5101
+ }
5102
+ }
5103
+ new EmailTemplateService();
3682
5104
  const OrderPlacedTemplate = ({ orderId }) => {
3683
5105
  const [context, setContext] = react.useState(null);
3684
5106
  const [previewContext, setPreviewData] = react.useState(null);
@@ -3757,18 +5179,18 @@ const OrderTemplateGroup = () => {
3757
5179
  ] });
3758
5180
  };
3759
5181
  const contactFormMockData = {
3760
- name: "Test Name",
3761
- email: "test@test.com",
3762
- phone: "1234567890",
3763
- message: "Test messages"
5182
+ contact_form: {
5183
+ name: "Test Name",
5184
+ email: "test@test.com",
5185
+ phone: "1234567890",
5186
+ message: "Test messages"
5187
+ }
3764
5188
  };
3765
5189
  const ContactFormTemplate = () => {
3766
5190
  const [context, setContext] = react.useState(null);
3767
5191
  const [previewContext, setPreviewData] = react.useState(null);
3768
5192
  react.useEffect(() => {
3769
- setContext({
3770
- contact_form: contactFormMockData
3771
- });
5193
+ setContext(contactFormMockData);
3772
5194
  }, []);
3773
5195
  const { data: preview, isLoading: isPreviewLoading } = usePreview({
3774
5196
  templateName: TEMPLATES_NAMES.CONTACT_FORM,
@@ -3873,17 +5295,17 @@ const menuItemModule = {
3873
5295
  path: "/notifications-emails",
3874
5296
  nested: void 0
3875
5297
  },
3876
- {
3877
- label: config.label,
3878
- icon: config.icon,
3879
- path: "/notifications-emails/render",
3880
- nested: void 0
3881
- },
3882
5298
  {
3883
5299
  label: config$1.label,
3884
5300
  icon: config$1.icon,
3885
5301
  path: "/notifications-emails/list",
3886
5302
  nested: void 0
5303
+ },
5304
+ {
5305
+ label: config.label,
5306
+ icon: config.icon,
5307
+ path: "/notifications-emails/render",
5308
+ nested: void 0
3887
5309
  }
3888
5310
  ]
3889
5311
  };