@embedreach/components 0.2.58 → 0.2.59

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.
@@ -2863,6 +2863,175 @@ function useToast() {
2863
2863
  dismiss: (toastId) => dispatch({ type: "DISMISS_TOAST", toastId })
2864
2864
  };
2865
2865
  }
2866
+ const createCommunicationGroup = async (params) => {
2867
+ const response = await baseRequest(
2868
+ `${COMMUNICATION_GROUP_PATH}`,
2869
+ {
2870
+ method: "POST",
2871
+ body: JSON.stringify(params)
2872
+ }
2873
+ );
2874
+ return response.data;
2875
+ };
2876
+ const updateCommunicationGroup = async (id2, params) => {
2877
+ const response = await baseRequest(
2878
+ `${COMMUNICATION_GROUP_PATH}/${id2}`,
2879
+ {
2880
+ method: "PATCH",
2881
+ body: JSON.stringify(params)
2882
+ }
2883
+ );
2884
+ return response.data;
2885
+ };
2886
+ const getCommunicationGroup = async (id2) => {
2887
+ const response = await baseRequest(
2888
+ `${COMMUNICATION_GROUP_PATH}/${id2}`
2889
+ );
2890
+ return response.data;
2891
+ };
2892
+ const getMergeFields = async (id2) => {
2893
+ if (!id2) {
2894
+ const toReturn = { mergeFields: [] };
2895
+ return toReturn;
2896
+ }
2897
+ const response = await baseRequest(
2898
+ `${COMMUNICATION_GROUP_PATH}/${id2}/merge-fields`
2899
+ );
2900
+ return response.data;
2901
+ };
2902
+ const sendTestCommunication = async (id2, params) => {
2903
+ const response = await baseRequest(
2904
+ `${COMMUNICATION_GROUP_PATH}/${id2}/test`,
2905
+ {
2906
+ method: "POST",
2907
+ body: JSON.stringify(params)
2908
+ }
2909
+ );
2910
+ return response.data;
2911
+ };
2912
+ const resetCommunicationGroupToDefault = async (args) => {
2913
+ const { communicationGroupId, automationId, type } = args;
2914
+ const response = await baseRequest(
2915
+ `${COMMUNICATION_GROUP_PATH}/${communicationGroupId}/${automationId}/reset`,
2916
+ {
2917
+ method: "POST",
2918
+ body: JSON.stringify({ type })
2919
+ }
2920
+ );
2921
+ return response.data;
2922
+ };
2923
+ const stripoKeys = {
2924
+ all: ["stripo"],
2925
+ token: () => [...stripoKeys.all, "token"],
2926
+ editorData: () => [...stripoKeys.all, "editorData"],
2927
+ templates: () => [...stripoKeys.all, "templates"],
2928
+ templateForActionId: (automationId, actionId) => [...stripoKeys.templates(), automationId, actionId]
2929
+ };
2930
+ const getStripoToken = async () => {
2931
+ const response = await baseRequest(`${STRIPO_PATH}/token`);
2932
+ return response.data;
2933
+ };
2934
+ const getEditorData = async () => {
2935
+ const response = await baseRequest(
2936
+ `${STRIPO_PATH}/editor-data`
2937
+ );
2938
+ return response.data;
2939
+ };
2940
+ const getTemplateForActionId = async (args) => {
2941
+ const { automationId, actionId } = args;
2942
+ const response = await baseRequest(
2943
+ `${STRIPO_PATH}/template/${automationId}/${actionId}`
2944
+ );
2945
+ return response.data;
2946
+ };
2947
+ const communicationGroupQueryKeys = {
2948
+ all: ["communication-group"]
2949
+ };
2950
+ const useGetCommunicationGroup = (communicationGroupId) => {
2951
+ const query = useQuery({
2952
+ queryKey: ["communication-group", communicationGroupId],
2953
+ queryFn: () => communicationGroupId ? getCommunicationGroup(communicationGroupId) : null,
2954
+ enabled: !!communicationGroupId
2955
+ });
2956
+ return {
2957
+ communicationGroup: query.data,
2958
+ isGetting: query.isPending,
2959
+ getError: query.error,
2960
+ isGetSuccess: query.isSuccess
2961
+ };
2962
+ };
2963
+ const useUpdateCommunicationGroup = () => {
2964
+ const queryClient = useQueryClient();
2965
+ const updateCommunicationGroupMutation = useMutation({
2966
+ mutationFn: ({
2967
+ groupId,
2968
+ params
2969
+ }) => updateCommunicationGroup(groupId, params),
2970
+ onSuccess: () => {
2971
+ queryClient.invalidateQueries({
2972
+ queryKey: communicationGroupQueryKeys.all
2973
+ });
2974
+ }
2975
+ });
2976
+ return {
2977
+ updateCommunicationGroup: updateCommunicationGroupMutation.mutate,
2978
+ isUpdating: updateCommunicationGroupMutation.isPending,
2979
+ updateError: updateCommunicationGroupMutation.error,
2980
+ isUpdateSuccess: updateCommunicationGroupMutation.isSuccess
2981
+ };
2982
+ };
2983
+ const useGetMergeFields = (id2) => {
2984
+ const getMergeFieldsMutation = useQuery({
2985
+ queryKey: ["merge-fields", id2],
2986
+ queryFn: () => getMergeFields(id2)
2987
+ });
2988
+ return {
2989
+ getMergeFields: getMergeFieldsMutation.data,
2990
+ isGetting: getMergeFieldsMutation.isPending,
2991
+ getError: getMergeFieldsMutation.error,
2992
+ isGetSuccess: getMergeFieldsMutation.isSuccess
2993
+ };
2994
+ };
2995
+ const useSendTestCommunication = () => {
2996
+ const sendTestCommunicationMutation = useMutation({
2997
+ mutationFn: ({
2998
+ id: id2,
2999
+ params
3000
+ }) => sendTestCommunication(id2, params)
3001
+ });
3002
+ return {
3003
+ sendTestCommunication: sendTestCommunicationMutation.mutate,
3004
+ isSending: sendTestCommunicationMutation.isPending,
3005
+ sendError: sendTestCommunicationMutation.error,
3006
+ isSendSuccess: sendTestCommunicationMutation.isSuccess
3007
+ };
3008
+ };
3009
+ const useResetCommunicationGroupToDefault = () => {
3010
+ const queryClient = useQueryClient();
3011
+ const resetCommunicationGroupToDefaultMutation = useMutation({
3012
+ mutationFn: ({
3013
+ communicationGroupId,
3014
+ automationId,
3015
+ type
3016
+ }) => resetCommunicationGroupToDefault({
3017
+ communicationGroupId,
3018
+ automationId,
3019
+ type
3020
+ }),
3021
+ onSuccess: () => {
3022
+ queryClient.invalidateQueries({
3023
+ queryKey: communicationGroupQueryKeys.all
3024
+ });
3025
+ queryClient.invalidateQueries({
3026
+ queryKey: stripoKeys.templates()
3027
+ });
3028
+ }
3029
+ });
3030
+ return {
3031
+ resetCommunicationGroupToDefault: resetCommunicationGroupToDefaultMutation.mutate,
3032
+ isPending: resetCommunicationGroupToDefaultMutation.isPending
3033
+ };
3034
+ };
2866
3035
  const useGetBusinessAutomation = (automationId) => {
2867
3036
  const queryClient = useQueryClient();
2868
3037
  const getAutomationQuery = useQuery({
@@ -2931,6 +3100,9 @@ const useUpdateBusinessAutomation = (automationId) => {
2931
3100
  queryClient.invalidateQueries({
2932
3101
  queryKey: automationKeys.single(automationId)
2933
3102
  });
3103
+ queryClient.invalidateQueries({
3104
+ queryKey: communicationGroupQueryKeys.all
3105
+ });
2934
3106
  queryClient.invalidateQueries({ queryKey: automationKeys.list() });
2935
3107
  },
2936
3108
  onError: () => {
@@ -69179,175 +69351,6 @@ const useAutomationUpdateTracking = (automationId) => {
69179
69351
  }
69180
69352
  }, [isUpdating]);
69181
69353
  };
69182
- const createCommunicationGroup = async (params) => {
69183
- const response = await baseRequest(
69184
- `${COMMUNICATION_GROUP_PATH}`,
69185
- {
69186
- method: "POST",
69187
- body: JSON.stringify(params)
69188
- }
69189
- );
69190
- return response.data;
69191
- };
69192
- const updateCommunicationGroup = async (id2, params) => {
69193
- const response = await baseRequest(
69194
- `${COMMUNICATION_GROUP_PATH}/${id2}`,
69195
- {
69196
- method: "PATCH",
69197
- body: JSON.stringify(params)
69198
- }
69199
- );
69200
- return response.data;
69201
- };
69202
- const getCommunicationGroup = async (id2) => {
69203
- const response = await baseRequest(
69204
- `${COMMUNICATION_GROUP_PATH}/${id2}`
69205
- );
69206
- return response.data;
69207
- };
69208
- const getMergeFields = async (id2) => {
69209
- if (!id2) {
69210
- const toReturn = { mergeFields: [] };
69211
- return toReturn;
69212
- }
69213
- const response = await baseRequest(
69214
- `${COMMUNICATION_GROUP_PATH}/${id2}/merge-fields`
69215
- );
69216
- return response.data;
69217
- };
69218
- const sendTestCommunication = async (id2, params) => {
69219
- const response = await baseRequest(
69220
- `${COMMUNICATION_GROUP_PATH}/${id2}/test`,
69221
- {
69222
- method: "POST",
69223
- body: JSON.stringify(params)
69224
- }
69225
- );
69226
- return response.data;
69227
- };
69228
- const resetCommunicationGroupToDefault = async (args) => {
69229
- const { communicationGroupId, automationId, type } = args;
69230
- const response = await baseRequest(
69231
- `${COMMUNICATION_GROUP_PATH}/${communicationGroupId}/${automationId}/reset`,
69232
- {
69233
- method: "POST",
69234
- body: JSON.stringify({ type })
69235
- }
69236
- );
69237
- return response.data;
69238
- };
69239
- const stripoKeys = {
69240
- all: ["stripo"],
69241
- token: () => [...stripoKeys.all, "token"],
69242
- editorData: () => [...stripoKeys.all, "editorData"],
69243
- templates: () => [...stripoKeys.all, "templates"],
69244
- templateForActionId: (automationId, actionId) => [...stripoKeys.templates(), automationId, actionId]
69245
- };
69246
- const getStripoToken = async () => {
69247
- const response = await baseRequest(`${STRIPO_PATH}/token`);
69248
- return response.data;
69249
- };
69250
- const getEditorData = async () => {
69251
- const response = await baseRequest(
69252
- `${STRIPO_PATH}/editor-data`
69253
- );
69254
- return response.data;
69255
- };
69256
- const getTemplateForActionId = async (args) => {
69257
- const { automationId, actionId } = args;
69258
- const response = await baseRequest(
69259
- `${STRIPO_PATH}/template/${automationId}/${actionId}`
69260
- );
69261
- return response.data;
69262
- };
69263
- const communicationGroupQueryKeys = {
69264
- all: ["communication-group"]
69265
- };
69266
- const useGetCommunicationGroup = (communicationGroupId) => {
69267
- const query = useQuery({
69268
- queryKey: ["communication-group", communicationGroupId],
69269
- queryFn: () => communicationGroupId ? getCommunicationGroup(communicationGroupId) : null,
69270
- enabled: !!communicationGroupId
69271
- });
69272
- return {
69273
- communicationGroup: query.data,
69274
- isGetting: query.isPending,
69275
- getError: query.error,
69276
- isGetSuccess: query.isSuccess
69277
- };
69278
- };
69279
- const useUpdateCommunicationGroup = () => {
69280
- const queryClient = useQueryClient();
69281
- const updateCommunicationGroupMutation = useMutation({
69282
- mutationFn: ({
69283
- groupId,
69284
- params
69285
- }) => updateCommunicationGroup(groupId, params),
69286
- onSuccess: () => {
69287
- queryClient.invalidateQueries({
69288
- queryKey: communicationGroupQueryKeys.all
69289
- });
69290
- }
69291
- });
69292
- return {
69293
- updateCommunicationGroup: updateCommunicationGroupMutation.mutate,
69294
- isUpdating: updateCommunicationGroupMutation.isPending,
69295
- updateError: updateCommunicationGroupMutation.error,
69296
- isUpdateSuccess: updateCommunicationGroupMutation.isSuccess
69297
- };
69298
- };
69299
- const useGetMergeFields = (id2) => {
69300
- const getMergeFieldsMutation = useQuery({
69301
- queryKey: ["merge-fields", id2],
69302
- queryFn: () => getMergeFields(id2)
69303
- });
69304
- return {
69305
- getMergeFields: getMergeFieldsMutation.data,
69306
- isGetting: getMergeFieldsMutation.isPending,
69307
- getError: getMergeFieldsMutation.error,
69308
- isGetSuccess: getMergeFieldsMutation.isSuccess
69309
- };
69310
- };
69311
- const useSendTestCommunication = () => {
69312
- const sendTestCommunicationMutation = useMutation({
69313
- mutationFn: ({
69314
- id: id2,
69315
- params
69316
- }) => sendTestCommunication(id2, params)
69317
- });
69318
- return {
69319
- sendTestCommunication: sendTestCommunicationMutation.mutate,
69320
- isSending: sendTestCommunicationMutation.isPending,
69321
- sendError: sendTestCommunicationMutation.error,
69322
- isSendSuccess: sendTestCommunicationMutation.isSuccess
69323
- };
69324
- };
69325
- const useResetCommunicationGroupToDefault = () => {
69326
- const queryClient = useQueryClient();
69327
- const resetCommunicationGroupToDefaultMutation = useMutation({
69328
- mutationFn: ({
69329
- communicationGroupId,
69330
- automationId,
69331
- type
69332
- }) => resetCommunicationGroupToDefault({
69333
- communicationGroupId,
69334
- automationId,
69335
- type
69336
- }),
69337
- onSuccess: () => {
69338
- queryClient.invalidateQueries({
69339
- queryKey: communicationGroupQueryKeys.all
69340
- });
69341
- queryClient.invalidateQueries({
69342
- queryKey: stripoKeys.templates()
69343
- });
69344
- }
69345
- });
69346
- return {
69347
- resetCommunicationGroupToDefault: resetCommunicationGroupToDefaultMutation.mutate,
69348
- isPending: resetCommunicationGroupToDefaultMutation.isPending
69349
- };
69350
- };
69351
69354
  const useCommunicationGroupFetching = () => {
69352
69355
  const { setCommunicationGroup: setCommunicationGroup2, state } = useContext$1(Context$1);
69353
69356
  const communicationGroupId = state.selectedCommunicationGroupId ?? state.automation?.actionData?.find(
@@ -87859,6 +87862,24 @@ const BackNextButtonGroup = ({
87859
87862
  getInfoTooltipTitle
87860
87863
  }) => {
87861
87864
  const infoTooltipTitle = getInfoTooltipTitle?.();
87865
+ const renderNextButton = (args) => {
87866
+ return /* @__PURE__ */ jsx(
87867
+ Button$1,
87868
+ {
87869
+ asChild: args.tooltip === true ? true : false,
87870
+ onClick: handleNext,
87871
+ disabled: nextDisabled,
87872
+ className: cn$1(
87873
+ "flex items-center gap-2 --reach-destructive",
87874
+ nextDisabled && "opacity-50 cursor-not-allowed"
87875
+ ),
87876
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
87877
+ /* @__PURE__ */ jsx("span", { children: nextText }),
87878
+ /* @__PURE__ */ jsx(IconDefinitions.NextButton, {})
87879
+ ] })
87880
+ }
87881
+ );
87882
+ };
87862
87883
  return /* @__PURE__ */ jsxs("div", { className: "flex gap-4 py-2 items-center", children: [
87863
87884
  !hideBack && /* @__PURE__ */ jsxs(
87864
87885
  Button$1,
@@ -87885,22 +87906,7 @@ const BackNextButtonGroup = ({
87885
87906
  children: "Skip & Save as Draft"
87886
87907
  }
87887
87908
  ),
87888
- /* @__PURE__ */ jsxs(
87889
- Button$1,
87890
- {
87891
- onClick: handleNext,
87892
- disabled: nextDisabled,
87893
- className: cn$1(
87894
- "flex items-center gap-2 --reach-destructive",
87895
- nextDisabled && "opacity-50 cursor-not-allowed"
87896
- ),
87897
- children: [
87898
- /* @__PURE__ */ jsx("span", { children: nextText }),
87899
- /* @__PURE__ */ jsx(IconDefinitions.NextButton, {})
87900
- ]
87901
- }
87902
- ),
87903
- infoTooltipTitle && /* @__PURE__ */ jsx(InfoTooltip, { title: infoTooltipTitle })
87909
+ infoTooltipTitle ? /* @__PURE__ */ jsx(InfoTooltip, { title: infoTooltipTitle, children: renderNextButton({ tooltip: true }) }) : renderNextButton({ tooltip: false })
87904
87910
  ] });
87905
87911
  };
87906
87912
  const WizardContentWrapper = ({ content: content2, className: className2 }) => {
@@ -95853,10 +95859,14 @@ function MultiSelectDialog({
95853
95859
  }, [options]);
95854
95860
  const filteredOptions = React.useMemo(() => {
95855
95861
  if (!searchQuery) return cleanedOptions;
95856
- return cleanedOptions.filter(
95862
+ const selectedItems = cleanedOptions.filter(
95863
+ (option) => tempSelected.includes(option.value)
95864
+ );
95865
+ const unselectedItems = cleanedOptions.filter((option) => !tempSelected.includes(option.value)).filter(
95857
95866
  (option) => option.label.toLowerCase().includes(searchQuery.toLowerCase())
95858
95867
  );
95859
- }, [cleanedOptions, searchQuery]);
95868
+ return [...selectedItems, ...unselectedItems];
95869
+ }, [cleanedOptions, searchQuery, tempSelected]);
95860
95870
  const getSelectedOptionsDisplay = React.useCallback(() => {
95861
95871
  return selectedValues.map((val) => {
95862
95872
  const option = options.find((opt) => opt.value === val);
@@ -98085,6 +98095,7 @@ const SendPreviewPopup = ({ automation: automation2, type, setOpenSendPreviewPop
98085
98095
  const [senderId, setSenderId] = useState(null);
98086
98096
  const [finishedLoading, setFinishedLoading] = useState(false);
98087
98097
  const [selectedPreviewAsRecipientId, setSelectedPreviewAsRecipientId] = useState("");
98098
+ const [isSelectOpen, setIsSelectOpen] = useState(false);
98088
98099
  const { sendTestCommunication: sendTestCommunication2, sendError, isSendSuccess } = useSendTestCommunication();
98089
98100
  const { toast: toast2 } = useToast();
98090
98101
  const actionDataCommunication = automation2.actionData?.find(
@@ -98097,6 +98108,15 @@ const SendPreviewPopup = ({ automation: automation2, type, setOpenSendPreviewPop
98097
98108
  excludeSegments: automation2.excludeSegmentIds,
98098
98109
  automationId: automation2.id
98099
98110
  });
98111
+ const dialogContentRef = useRef(null);
98112
+ const filteredRecipients = React__default.useMemo(() => {
98113
+ return [...countResponse?.recipients ?? []].filter((recipient2) => {
98114
+ if (!recipient2.firstName || !recipient2.lastName) return false;
98115
+ if (type === "email" && !recipient2.email) return false;
98116
+ if (type === "sms" && !recipient2.phone) return false;
98117
+ return true;
98118
+ });
98119
+ }, [countResponse?.recipients, type]);
98100
98120
  const validateInput = () => {
98101
98121
  if (type === "email") {
98102
98122
  return EmailUtils.validateEmail(recipient);
@@ -98158,8 +98178,16 @@ const SendPreviewPopup = ({ automation: automation2, type, setOpenSendPreviewPop
98158
98178
  setRecipient("");
98159
98179
  setError2("");
98160
98180
  setSelectedPreviewAsRecipientId("");
98181
+ setIsSelectOpen(false);
98161
98182
  }
98162
98183
  }, [open]);
98184
+ useEffect(() => {
98185
+ if (!open && isSelectOpen) {
98186
+ setTimeout(() => {
98187
+ document.body.style.pointerEvents = "";
98188
+ }, 0);
98189
+ }
98190
+ }, [open, isSelectOpen]);
98163
98191
  const handleSendPreview = () => {
98164
98192
  if (!validateInput()) {
98165
98193
  setError2(
@@ -98199,7 +98227,7 @@ const SendPreviewPopup = ({ automation: automation2, type, setOpenSendPreviewPop
98199
98227
  /* @__PURE__ */ jsx("p", { className: "text-gray-500", children: "Please update the automation to include a sender for this type" })
98200
98228
  ] }) });
98201
98229
  }
98202
- return /* @__PURE__ */ jsxs("div", { className: "", children: [
98230
+ return /* @__PURE__ */ jsxs("div", { className: "", ref: dialogContentRef, children: [
98203
98231
  /* @__PURE__ */ jsxs("h3", { className: "text-xl font-semibold text-gray-900 mb-4", children: [
98204
98232
  "Send Test ",
98205
98233
  type === "email" ? "Email" : "Text"
@@ -98232,6 +98260,12 @@ const SendPreviewPopup = ({ automation: automation2, type, setOpenSendPreviewPop
98232
98260
  onValueChange: (value) => {
98233
98261
  setSelectedPreviewAsRecipientId(value);
98234
98262
  },
98263
+ onOpenChange: (open2) => {
98264
+ setIsSelectOpen(open2);
98265
+ if (!open2 && dialogContentRef.current) {
98266
+ dialogContentRef.current.focus();
98267
+ }
98268
+ },
98235
98269
  children: [
98236
98270
  /* @__PURE__ */ jsx(
98237
98271
  SelectTrigger,
@@ -98244,7 +98278,7 @@ const SendPreviewPopup = ({ automation: automation2, type, setOpenSendPreviewPop
98244
98278
  )?.lastName : "Preview as" })
98245
98279
  }
98246
98280
  ),
98247
- /* @__PURE__ */ jsx(SelectContent, { children: /* @__PURE__ */ jsx(SelectGroup, { children: (countResponse?.recipients ?? []).map((recipient2) => /* @__PURE__ */ jsx(
98281
+ /* @__PURE__ */ jsx(SelectContent, { position: "popper", className: "z-[100]", children: /* @__PURE__ */ jsx(SelectGroup, { children: filteredRecipients.map((recipient2) => /* @__PURE__ */ jsx(
98248
98282
  SelectItem,
98249
98283
  {
98250
98284
  value: recipient2.id,
@@ -98357,6 +98391,16 @@ const AutomationEditorEmailPreview = ({
98357
98391
  channelSenders: channelSenders?.results ?? [],
98358
98392
  channelAccounts: channelAccounts?.results ?? []
98359
98393
  });
98394
+ let errorText = null;
98395
+ if (!communicationGroup?.emailChannelSenderId) {
98396
+ errorText = "Please first select an email sender";
98397
+ }
98398
+ if (!communicationGroup?.emailSubject) {
98399
+ errorText = "Please first ensure you have an email subject";
98400
+ }
98401
+ if (!communicationGroup?.emailHtmlBody) {
98402
+ errorText = "Please first ensure you have an email content";
98403
+ }
98360
98404
  return /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col items-center w-full", children: [
98361
98405
  /* @__PURE__ */ jsx(
98362
98406
  EditCampaignContentDialog,
@@ -98377,12 +98421,26 @@ const AutomationEditorEmailPreview = ({
98377
98421
  AutomationEditorPreviewContainer,
98378
98422
  {
98379
98423
  actionButtons: /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
98380
- !disablePreview && hasEmailCommunication && /* @__PURE__ */ jsx(
98424
+ !disablePreview && hasEmailCommunication && (errorText ? /* @__PURE__ */ jsx(
98425
+ InfoTooltip,
98426
+ {
98427
+ alertText: "Unable to send preview",
98428
+ title: "There was an error preparing the preview. Please check your automation configuration.",
98429
+ className: "inline-block",
98430
+ asChild: false,
98431
+ children: /* @__PURE__ */ jsx("div", { className: "inline-block", children: /* @__PURE__ */ jsx(
98432
+ PreviewButton,
98433
+ {
98434
+ onClick: () => setOpenSendPreviewEmailPopup(true)
98435
+ }
98436
+ ) })
98437
+ }
98438
+ ) : /* @__PURE__ */ jsx(
98381
98439
  PreviewButton,
98382
98440
  {
98383
98441
  onClick: () => setOpenSendPreviewEmailPopup(true)
98384
98442
  }
98385
- ),
98443
+ )),
98386
98444
  !disableEditContent && automation2.status === AutomationStatus.DRAFT && /* @__PURE__ */ jsx(
98387
98445
  Button$1,
98388
98446
  {
@@ -98529,6 +98587,13 @@ const AutomationEditorSMSPreview = ({
98529
98587
  smsBody
98530
98588
  });
98531
98589
  const imageUrls = communicationGroup?.textMessageMediaUrls ?? [];
98590
+ let errorText = null;
98591
+ if (!communicationGroup?.smsChannelSenderId) {
98592
+ errorText = "Please first select a sms sender";
98593
+ }
98594
+ if (!communicationGroup?.smsMessageBody) {
98595
+ errorText = "Please first ensure you have a sms content";
98596
+ }
98532
98597
  return /* @__PURE__ */ jsx(AnimatePresence, { children: setupRequiredState ? /* @__PURE__ */ jsx("div", { className: "w-full pt-8 mx-auto", children: /* @__PURE__ */ jsx(SMSSetup, {}) }) : /* @__PURE__ */ jsxs(
98533
98598
  motion.div,
98534
98599
  {
@@ -98561,13 +98626,27 @@ const AutomationEditorSMSPreview = ({
98561
98626
  AutomationEditorPreviewContainer,
98562
98627
  {
98563
98628
  actionButtons: /* @__PURE__ */ jsxs(Fragment, { children: [
98564
- !disablePreview && hasSendableSmsContent && /* @__PURE__ */ jsx(
98629
+ !disablePreview && hasSendableSmsContent && (errorText ? /* @__PURE__ */ jsx(
98630
+ InfoTooltip,
98631
+ {
98632
+ alertText: "Unable to send preview",
98633
+ title: "There was an error preparing the preview. Please check your automation configuration.",
98634
+ className: "inline-block",
98635
+ asChild: false,
98636
+ children: /* @__PURE__ */ jsx("div", { className: "inline-block", children: /* @__PURE__ */ jsx(
98637
+ PreviewButton,
98638
+ {
98639
+ onClick: () => setOpenSendPreviewSmsPopup(true)
98640
+ }
98641
+ ) })
98642
+ }
98643
+ ) : /* @__PURE__ */ jsx(
98565
98644
  PreviewButton,
98566
98645
  {
98567
98646
  onClick: () => setOpenSendPreviewSmsPopup(true)
98568
98647
  }
98569
- ),
98570
- (automation2.status === AutomationStatus.DRAFT || !disableEditContent) && /* @__PURE__ */ jsx(
98648
+ )),
98649
+ automation2.status === AutomationStatus.DRAFT && !disableEditContent && /* @__PURE__ */ jsx(
98571
98650
  Button$1,
98572
98651
  {
98573
98652
  variant: "outline",
@@ -98640,6 +98719,8 @@ const AutomationEditorTabs = ({
98640
98719
  if (!communicationGroup || !channelSenders || !value) {
98641
98720
  return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4 pt-4 flex-1 bg-muted rounded-md", children: /* @__PURE__ */ jsx(BasicLoader, { text: ["Loading..."] }) });
98642
98721
  }
98722
+ const finalHideSms = !communicationGroup?.smsChannelSenderId || hideSms;
98723
+ const finalHideEmail = !communicationGroup?.emailChannelSenderId;
98643
98724
  const SMS_SETUP_REQUIRED = smsChannelSenders.length === 0 && !smsApplication;
98644
98725
  return /* @__PURE__ */ jsxs(
98645
98726
  Tabs,
@@ -98652,9 +98733,9 @@ const AutomationEditorTabs = ({
98652
98733
  /* @__PURE__ */ jsx("div", { className: "max-w-[640px] mx-auto w-full", children: /* @__PURE__ */ jsxs(
98653
98734
  TabsList,
98654
98735
  {
98655
- className: `grid w-full ${hideSms ? "grid-cols-1" : "grid-cols-2"}`,
98736
+ className: `grid w-full ${finalHideSms || finalHideEmail ? "grid-cols-1" : "grid-cols-2"}`,
98656
98737
  children: [
98657
- /* @__PURE__ */ jsx(
98738
+ !finalHideEmail && /* @__PURE__ */ jsx(
98658
98739
  TabsTrigger,
98659
98740
  {
98660
98741
  value: "email",
@@ -98666,7 +98747,7 @@ const AutomationEditorTabs = ({
98666
98747
  ] })
98667
98748
  }
98668
98749
  ),
98669
- !hideSms && /* @__PURE__ */ jsx(
98750
+ !finalHideSms && /* @__PURE__ */ jsx(
98670
98751
  TabsTrigger,
98671
98752
  {
98672
98753
  value: "sms",
@@ -102469,6 +102550,28 @@ const AutomationSelectTimeMain = ({ title: title2 = "Edit Schedule Time" }) => {
102469
102550
  automation2,
102470
102551
  isDirty2
102471
102552
  ]);
102553
+ useEffect(() => {
102554
+ if (deliveryOption === null) {
102555
+ if (automation2?.triggerMetadata && // Not needed i know but im terrified of TS errors now :nod_cry:
102556
+ typeof automation2.triggerMetadata === "object" && automation2.triggerMetadata !== null && "scheduledAt" in automation2.triggerMetadata) {
102557
+ console.log(
102558
+ automation2?.triggerMetadata?.scheduledAt,
102559
+ automation2?.triggerType
102560
+ );
102561
+ if (automation2?.triggerMetadata?.scheduledAt === "now" && automation2?.triggerType === AutomationTriggerType.ONE_TIME) {
102562
+ setDeliveryOption("sendNow");
102563
+ } else {
102564
+ if (automation2?.triggerMetadata?.scheduledAt) {
102565
+ setScheduledAt(automation2.triggerMetadata.scheduledAt);
102566
+ }
102567
+ if (automation2?.triggerMetadata?.timezone) {
102568
+ setTimezone(automation2.triggerMetadata.timezone);
102569
+ }
102570
+ setDeliveryOption("schedule");
102571
+ }
102572
+ }
102573
+ }
102574
+ }, [automation2, deliveryOption]);
102472
102575
  if (!automation2) {
102473
102576
  return null;
102474
102577
  }
@@ -105280,13 +105383,26 @@ const OneTimeWizardMain = ({ onFinish, getExtraMergeFields, onBeforeSchedule })
105280
105383
  estimatedSmsRecipients: estimatedMatchesStats?.phones || 0
105281
105384
  });
105282
105385
  if (result === true) {
105283
- updateAutomation2({
105284
- status: AutomationStatus.ACTIVE
105285
- });
105286
- toast({
105287
- title: `${t$2("engage:broadcast")} scheduled!`
105288
- });
105289
- onFinish();
105386
+ updateAutomation2(
105387
+ {
105388
+ status: AutomationStatus.ACTIVE
105389
+ },
105390
+ {
105391
+ onSuccess: () => {
105392
+ toast({
105393
+ title: `${t$2("engage:broadcast")} scheduled!`
105394
+ });
105395
+ onFinish();
105396
+ },
105397
+ onError: () => {
105398
+ toast({
105399
+ title: "Oops!",
105400
+ description: "Please contact your administrator",
105401
+ variant: "destructive"
105402
+ });
105403
+ }
105404
+ }
105405
+ );
105290
105406
  } else {
105291
105407
  toast({
105292
105408
  title: "Oops!",
@@ -108128,7 +108244,6 @@ function BroadcastList() {
108128
108244
  setSearchQuery("");
108129
108245
  };
108130
108246
  const onDialogClose = (result) => {
108131
- console.log("result", result);
108132
108247
  handleDialogClose(
108133
108248
  setCreateDialogOpen,
108134
108249
  toast2,
@@ -108727,7 +108842,7 @@ const AutomationsEditorHeader = ({ showBackButton, onDuplicationCreated, onBefor
108727
108842
  smsApplication
108728
108843
  });
108729
108844
  useEffect(() => {
108730
- if (automation2 && isActive === void 0) {
108845
+ if (automation2) {
108731
108846
  switch (automation2.status) {
108732
108847
  case AutomationStatus.ACTIVE:
108733
108848
  setIsActive(true);
@@ -108751,7 +108866,7 @@ const AutomationsEditorHeader = ({ showBackButton, onDuplicationCreated, onBefor
108751
108866
  throw UnreachableCaseStatement(automation2.status, AutomationStatus);
108752
108867
  }
108753
108868
  }
108754
- }, [automation2, isActive]);
108869
+ }, [automation2]);
108755
108870
  const renderSwitch = useCallback(() => {
108756
108871
  if (!automation2) {
108757
108872
  toast2({
@@ -108759,7 +108874,7 @@ const AutomationsEditorHeader = ({ showBackButton, onDuplicationCreated, onBefor
108759
108874
  description: "Please contact your administrator",
108760
108875
  variant: "destructive"
108761
108876
  });
108762
- return;
108877
+ return null;
108763
108878
  }
108764
108879
  const handleStatusChange = async (newStatus) => {
108765
108880
  if (isActive && !newStatus) {
@@ -108798,7 +108913,7 @@ const AutomationsEditorHeader = ({ showBackButton, onDuplicationCreated, onBefor
108798
108913
  if (communicationGroup?.emailHtmlBody?.includes(DEFAULT_LOGO_URL)) {
108799
108914
  if (numberOfTimesSentClicked === 0) {
108800
108915
  toast2({
108801
- title: DEFAULT_LOGO_WARNING_MESSAGE,
108916
+ title: `${DEFAULT_LOGO_WARNING_MESSAGE}. You can click send again to send anyway.`,
108802
108917
  variant: "warning"
108803
108918
  });
108804
108919
  setNumberOfTimesSentClicked(numberOfTimesSentClicked + 1);
@@ -108871,9 +108986,23 @@ const AutomationsEditorHeader = ({ showBackButton, onDuplicationCreated, onBefor
108871
108986
  );
108872
108987
  }
108873
108988
  };
108874
- if (!automation2) {
108989
+ if (!automation2 || !communicationGroup) {
108875
108990
  return null;
108876
108991
  }
108992
+ const smsChannelSender = smsChannelSenders.find(
108993
+ (sender) => sender.channelSender.id === communicationGroup?.smsChannelSenderId
108994
+ );
108995
+ const noTriggerMetadata = !automation2.triggerMetadata || automation2.triggerMetadata === null;
108996
+ const oneTimeNoScheduledAt = automation2.triggerMetadata?.triggerType === AutomationTriggerType.ONE_TIME && !automation2.triggerMetadata?.scheduledAt;
108997
+ const noEmailANDnoSmsSender = !communicationGroup?.emailChannelSenderId && !communicationGroup?.smsChannelSenderId;
108998
+ const automationOneTime = automation2.triggerType === AutomationTriggerType.ONE_TIME;
108999
+ const smsApplicationNotApproved = (
109000
+ // TRIGGER_BASED can start this even if its pending
109001
+ automationOneTime && smsChannelSender && smsChannelSender?.smsApplication?.application && smsChannelSender?.smsApplication?.status !== SmsRegistrationApplicationStatus.APPROVED
109002
+ );
109003
+ const noEmailSubjectORnoEmailHtmlBody = communicationGroup?.emailChannelSenderId && (!communicationGroup?.emailSubject || !communicationGroup?.emailHtmlBody);
109004
+ const noSmsMessageBody = communicationGroup?.smsChannelSenderId && !communicationGroup?.smsMessageBody;
109005
+ const missingScheduledAt = automationOneTime && (!automation2.triggerMetadata || !("scheduledAt" in automation2.triggerMetadata) || !automation2.triggerMetadata?.scheduledAt);
108877
109006
  let disableSwitch = false;
108878
109007
  let showSwitch = true;
108879
109008
  let infoOnDisabled = void 0;
@@ -108886,22 +109015,22 @@ const AutomationsEditorHeader = ({ showBackButton, onDuplicationCreated, onBefor
108886
109015
  /**
108887
109016
  * If we have a emailChannelSenderId, we need to have a emailSubject and emailHtmlBody
108888
109017
  */
108889
- communicationGroup?.emailChannelSenderId && (!communicationGroup?.emailSubject || !communicationGroup?.emailHtmlBody) || /**
108890
- * If we have a smsChannelSenderId, we need to have a smsMessageBody
108891
- */
108892
- communicationGroup?.smsChannelSenderId && !communicationGroup?.smsMessageBody
109018
+ noEmailANDnoSmsSender || noEmailSubjectORnoEmailHtmlBody || noSmsMessageBody
108893
109019
  ) {
108894
109020
  disableSwitch = true;
108895
- if (!communicationGroup?.emailSubject) {
109021
+ if (noEmailSubjectORnoEmailHtmlBody) {
108896
109022
  infoOnDisabled = "Missing subject in email communication";
108897
109023
  }
108898
- if (!communicationGroup?.emailHtmlBody) {
108899
- infoOnDisabled = "Missing email content in email communication";
108900
- }
108901
- if (!communicationGroup?.smsMessageBody) {
109024
+ if (noSmsMessageBody) {
108902
109025
  infoOnDisabled = "Missing SMS message in SMS communication";
108903
109026
  }
108904
109027
  }
109028
+ if (missingScheduledAt) {
109029
+ disableSwitch = true;
109030
+ }
109031
+ if (smsApplicationNotApproved) {
109032
+ disableSwitch = true;
109033
+ }
108905
109034
  break;
108906
109035
  case AutomationStatus.DEACTIVATED:
108907
109036
  disableSwitch = true;
@@ -108952,11 +109081,9 @@ const AutomationsEditorHeader = ({ showBackButton, onDuplicationCreated, onBefor
108952
109081
  )
108953
109082
  ] });
108954
109083
  case AutomationTriggerType.ONE_TIME: {
108955
- const smsChannelSender = smsChannelSenders.find(
108956
- (sender) => sender.channelSender.id === communicationGroup?.smsChannelSenderId
108957
- );
108958
- if (!automation2.triggerMetadata || automation2.triggerMetadata === null || automation2.triggerMetadata?.triggerType === AutomationTriggerType.ONE_TIME && !automation2.triggerMetadata?.scheduledAt || !communicationGroup?.emailChannelSenderId && !communicationGroup?.smsChannelSenderId || smsChannelSender && smsChannelSender?.smsApplication?.application && smsChannelSender?.smsApplication?.status !== SmsRegistrationApplicationStatus.APPROVED || !communicationGroup?.emailSubject || !communicationGroup?.emailHtmlBody || !communicationGroup?.smsMessageBody || !communicationGroup?.emailChannelSenderId && !communicationGroup?.smsChannelSenderId) {
109084
+ if (noTriggerMetadata || oneTimeNoScheduledAt || noEmailANDnoSmsSender || smsApplicationNotApproved || noEmailSubjectORnoEmailHtmlBody || noSmsMessageBody) {
108959
109085
  const renderInfoTooltip = () => {
109086
+ const sendText = automation2.triggerMetadata && "scheduledAt" in automation2.triggerMetadata && automation2.triggerMetadata?.scheduledAt === "now" ? "Send Now" : "Schedule Send";
108960
109087
  if (automation2.status !== AutomationStatus.DRAFT) {
108961
109088
  if (automation2.triggerMetadata && "scheduledAt" in automation2.triggerMetadata && automation2.triggerMetadata?.scheduledAt !== "now" && // Only active ones can be unscheduled
108962
109089
  automation2.status === AutomationStatus.ACTIVE) {
@@ -108972,19 +109099,16 @@ const AutomationsEditorHeader = ({ showBackButton, onDuplicationCreated, onBefor
108972
109099
  );
108973
109100
  }
108974
109101
  }
108975
- const sendText = automation2.triggerMetadata && "scheduledAt" in automation2.triggerMetadata && automation2.triggerMetadata?.scheduledAt === "now" ? "Send Now" : "Schedule Send";
108976
- if (smsChannelSender?.smsApplication?.application && smsChannelSender.smsApplication?.status !== SmsRegistrationApplicationStatus.APPROVED) {
108977
- return /* @__PURE__ */ jsx(
109102
+ if (smsApplicationNotApproved) {
109103
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(
108978
109104
  InfoTooltip,
108979
109105
  {
108980
109106
  title: "You'll be able to send campaigns once your SMS application is approved.",
108981
109107
  alertText: "SMS number approval pending",
108982
109108
  asChild: false,
108983
- className: "cursor-not-allowed",
108984
109109
  children: /* @__PURE__ */ jsx(
108985
109110
  Button$1,
108986
109111
  {
108987
- asChild: true,
108988
109112
  variant: "outline",
108989
109113
  className: "flex items-center gap-2",
108990
109114
  disabled: true,
@@ -108992,19 +109116,17 @@ const AutomationsEditorHeader = ({ showBackButton, onDuplicationCreated, onBefor
108992
109116
  }
108993
109117
  )
108994
109118
  }
108995
- );
109119
+ ) });
108996
109120
  }
108997
- if (!automation2.triggerMetadata || automation2.triggerMetadata === null || !("scheduledAt" in automation2.triggerMetadata) || "scheduledAt" in automation2.triggerMetadata && !automation2.triggerMetadata?.scheduledAt) {
108998
- return /* @__PURE__ */ jsx(
109121
+ if (missingScheduledAt) {
109122
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(
108999
109123
  InfoTooltip,
109000
109124
  {
109001
109125
  alertText: "Before sending, please select a schedule time on the left sidebar",
109002
109126
  asChild: false,
109003
- className: "cursor-not-allowed",
109004
109127
  children: /* @__PURE__ */ jsx(
109005
109128
  Button$1,
109006
109129
  {
109007
- asChild: true,
109008
109130
  variant: "outline",
109009
109131
  className: "flex items-center gap-2",
109010
109132
  disabled: true,
@@ -109012,44 +109134,42 @@ const AutomationsEditorHeader = ({ showBackButton, onDuplicationCreated, onBefor
109012
109134
  }
109013
109135
  )
109014
109136
  }
109015
- );
109137
+ ) });
109016
109138
  }
109017
- if (!communicationGroup?.emailChannelSenderId && !communicationGroup?.smsChannelSenderId || !communicationGroup?.emailSubject || !communicationGroup?.emailHtmlBody || !communicationGroup?.smsMessageBody) {
109139
+ if (noEmailANDnoSmsSender || noEmailSubjectORnoEmailHtmlBody || noSmsMessageBody) {
109018
109140
  let alertText = "";
109019
- if (!communicationGroup?.emailChannelSenderId && !communicationGroup?.smsChannelSenderId) {
109141
+ if (noEmailANDnoSmsSender) {
109020
109142
  alertText = "Please at least one sender";
109021
- } else if (!communicationGroup?.emailSubject) {
109143
+ } else if (noEmailSubjectORnoEmailHtmlBody) {
109022
109144
  alertText = "Please add a subject to your email communication";
109023
- } else if (!communicationGroup?.emailHtmlBody) {
109024
- alertText = "Please add content to your email communication";
109025
- } else if (!communicationGroup?.smsMessageBody) {
109145
+ } else if (noSmsMessageBody) {
109026
109146
  alertText = "Please add a message to your SMS communication";
109027
109147
  }
109028
- return /* @__PURE__ */ jsx(
109029
- InfoTooltip,
109148
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(InfoTooltip, { alertText, asChild: false, children: /* @__PURE__ */ jsx(
109149
+ Button$1,
109030
109150
  {
109031
- alertText,
109032
- asChild: false,
109033
- className: "cursor-not-allowed",
109034
- children: /* @__PURE__ */ jsx(
109035
- Button$1,
109036
- {
109037
- asChild: true,
109038
- variant: "outline",
109039
- className: "flex items-center gap-2",
109040
- disabled: true,
109041
- children: sendText
109042
- }
109043
- )
109151
+ variant: "outline",
109152
+ className: "flex items-center gap-2",
109153
+ disabled: true,
109154
+ children: sendText
109044
109155
  }
109045
- );
109156
+ ) }) });
109046
109157
  }
109158
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(
109159
+ Button$1,
109160
+ {
109161
+ variant: "outline",
109162
+ className: "flex items-center gap-2",
109163
+ disabled: true,
109164
+ children: sendText
109165
+ }
109166
+ ) });
109047
109167
  };
109048
109168
  return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 cursor-not-allowed", children: renderInfoTooltip() });
109049
109169
  }
109050
109170
  if (!isActive) {
109051
109171
  let sendText = "Schedule Send";
109052
- if (automation2.triggerMetadata.triggerType === AutomationTriggerType.ONE_TIME && automation2.triggerMetadata.scheduledAt && (automation2.triggerMetadata.scheduledAt === "now" || automation2.triggerMetadata.scheduledAt !== "now" && new Date(automation2.triggerMetadata.scheduledAt) < new Date(Date.now() + 5 * 60 * 1e3))) {
109172
+ if (automation2.triggerMetadata && automation2.triggerMetadata.triggerType === AutomationTriggerType.ONE_TIME && automation2.triggerMetadata.scheduledAt && automation2.triggerMetadata.scheduledAt === "now") {
109053
109173
  sendText = "Send Now";
109054
109174
  }
109055
109175
  return /* @__PURE__ */ jsx(
@@ -109081,14 +109201,11 @@ const AutomationsEditorHeader = ({ showBackButton, onDuplicationCreated, onBefor
109081
109201
  );
109082
109202
  }
109083
109203
  };
109084
- if (
109085
- // Only show the tooltip if its trigger based. One time automations will show their own tooltip in renderContent
109086
- // TODO: This is jank as fuck, consolidate it
109087
- disableSwitch && infoOnDisabled && automation2.triggerType === AutomationTriggerType.TRIGGER_BASED
109088
- ) {
109089
- return /* @__PURE__ */ jsx(InfoTooltip, { title: infoOnDisabled, children: renderContent() });
109204
+ const content2 = renderContent();
109205
+ if (disableSwitch && infoOnDisabled && automation2.triggerType === AutomationTriggerType.TRIGGER_BASED) {
109206
+ return /* @__PURE__ */ jsx(InfoTooltip, { alertText: infoOnDisabled, children: content2 });
109090
109207
  } else {
109091
- return renderContent();
109208
+ return content2;
109092
109209
  }
109093
109210
  }, [
109094
109211
  automation2,
@@ -109172,7 +109289,7 @@ const AutomationsEditorHeader = ({ showBackButton, onDuplicationCreated, onBefor
109172
109289
  )
109173
109290
  }
109174
109291
  ) }),
109175
- editingStatus ? /* @__PURE__ */ jsx("div", { className: "flex items-center text-muted-foreground pr-2", children: /* @__PURE__ */ jsx(BasicLoader, { size: "sm" }) }) : renderSwitch()
109292
+ editingStatus ? /* @__PURE__ */ jsx("div", { className: "flex items-center text-muted-foreground pr-2", children: /* @__PURE__ */ jsx(BasicLoader, { size: "sm" }) }) : /* @__PURE__ */ jsx("div", { className: "flex items-center", children: renderSwitch() })
109176
109293
  ] }),
109177
109294
  /* @__PURE__ */ jsx(
109178
109295
  AutomationDuplicateDialog,