strapi-plugin-magic-mail 2.2.6 → 2.3.1
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.
- package/README.md +168 -10
- package/dist/_chunks/{App-Bze8Ixs_.js → App-BMaJu77a.js} +787 -71
- package/dist/_chunks/{App-BZaHrE0R.mjs → App-DxiMl-Zd.mjs} +790 -74
- package/dist/_chunks/{de-DS04rP54.mjs → de-CpIQf94q.mjs} +21 -1
- package/dist/_chunks/{de-CN-G9j1S.js → de-YhjDItIL.js} +21 -1
- package/dist/_chunks/{en-BEFQJXvR.mjs → en-BHmOVzsP.mjs} +21 -1
- package/dist/_chunks/{en-BDc7Jk8u.js → en-BcdTnA2-.js} +21 -1
- package/dist/admin/index.js +2 -2
- package/dist/admin/index.mjs +2 -2
- package/dist/server/index.js +1124 -20
- package/dist/server/index.mjs +1122 -20
- package/package.json +10 -5
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
-
import React, { useRef, useEffect, useState } from "react";
|
|
2
|
+
import React, { useRef, useEffect, useState, useCallback } from "react";
|
|
3
3
|
import { useNavigate, useLocation } from "react-router-dom";
|
|
4
4
|
import { Modal, Typography, Flex, Box, Field, TextInput, Alert, Textarea, NumberInput, Divider, Toggle, Badge, Button, Loader, SingleSelect, SingleSelectOption, Thead, Tr, Th, Tbody, Td, Table, Tabs } from "@strapi/design-system";
|
|
5
|
-
import { EnvelopeIcon, ServerIcon, SparklesIcon, PlusIcon, PencilIcon, PlayIcon, TrashIcon, MagnifyingGlassIcon, FunnelIcon, CheckIcon, Cog6ToothIcon, DocumentTextIcon, ChartBarIcon, BoltIcon, CheckCircleIcon, ArrowUpTrayIcon, ArrowDownTrayIcon, DocumentArrowDownIcon, CodeBracketIcon, DocumentDuplicateIcon, PaperAirplaneIcon, ClipboardDocumentIcon, ArrowLeftIcon, ClockIcon, XMarkIcon, ArrowUturnLeftIcon, EnvelopeOpenIcon, CursorArrowRaysIcon, ExclamationTriangleIcon, XCircleIcon, KeyIcon } from "@heroicons/react/24/outline";
|
|
5
|
+
import { EnvelopeIcon, ServerIcon, SparklesIcon, PlusIcon, PencilIcon, PlayIcon, TrashIcon, MagnifyingGlassIcon, FunnelIcon, CheckIcon, Cog6ToothIcon, DocumentTextIcon, ChartBarIcon, BoltIcon, CheckCircleIcon, ArrowUpTrayIcon, ArrowDownTrayIcon, DocumentArrowDownIcon, CodeBracketIcon, DocumentDuplicateIcon, PaperAirplaneIcon, ClipboardDocumentIcon, ArrowLeftIcon, ClockIcon, XMarkIcon, ArrowUturnLeftIcon, EnvelopeOpenIcon, CursorArrowRaysIcon, ExclamationTriangleIcon, XCircleIcon, KeyIcon, ChatBubbleLeftIcon } from "@heroicons/react/24/outline";
|
|
6
6
|
import { useFetchClient, useNotification } from "@strapi/strapi/admin";
|
|
7
7
|
import styled, { css, keyframes } from "styled-components";
|
|
8
|
-
import { Star, Mail, Server, Lock, Cog, Check, Cloud, Key, ArrowLeft, ArrowRight } from "@strapi/icons";
|
|
8
|
+
import { Star, Mail, Server, Lock, Cog, Check, Cloud, Key, ArrowLeft, ArrowRight, ArrowClockwise, Play, Cross } from "@strapi/icons";
|
|
9
9
|
import * as ReactEmailEditor from "react-email-editor";
|
|
10
10
|
const useAuthRefresh = () => {
|
|
11
11
|
const { get } = useFetchClient();
|
|
@@ -85,7 +85,7 @@ const theme$3 = {
|
|
|
85
85
|
xl: "16px"
|
|
86
86
|
}
|
|
87
87
|
};
|
|
88
|
-
const fadeIn$
|
|
88
|
+
const fadeIn$6 = keyframes`
|
|
89
89
|
from {
|
|
90
90
|
opacity: 0;
|
|
91
91
|
transform: translateY(10px);
|
|
@@ -95,7 +95,7 @@ const fadeIn$5 = keyframes`
|
|
|
95
95
|
transform: translateY(0);
|
|
96
96
|
}
|
|
97
97
|
`;
|
|
98
|
-
const pulse$
|
|
98
|
+
const pulse$3 = keyframes`
|
|
99
99
|
0%, 100% {
|
|
100
100
|
transform: scale(1);
|
|
101
101
|
}
|
|
@@ -113,7 +113,7 @@ const slideIn = keyframes`
|
|
|
113
113
|
opacity: 1;
|
|
114
114
|
}
|
|
115
115
|
`;
|
|
116
|
-
const colors = {
|
|
116
|
+
const colors$1 = {
|
|
117
117
|
primary: "#4945ff",
|
|
118
118
|
// Strapi Primary Blue
|
|
119
119
|
primaryLight: "#f0f0ff",
|
|
@@ -133,7 +133,7 @@ const StepHeader = styled(Box)`
|
|
|
133
133
|
padding-bottom: 24px;
|
|
134
134
|
margin-bottom: 32px;
|
|
135
135
|
position: relative;
|
|
136
|
-
animation: ${fadeIn$
|
|
136
|
+
animation: ${fadeIn$6} 0.4s ease;
|
|
137
137
|
|
|
138
138
|
&::after {
|
|
139
139
|
content: '';
|
|
@@ -142,11 +142,11 @@ const StepHeader = styled(Box)`
|
|
|
142
142
|
left: -24px;
|
|
143
143
|
right: -24px;
|
|
144
144
|
height: 1px;
|
|
145
|
-
background: linear-gradient(90deg, transparent, ${colors.border}, transparent);
|
|
145
|
+
background: linear-gradient(90deg, transparent, ${colors$1.border}, transparent);
|
|
146
146
|
}
|
|
147
147
|
`;
|
|
148
148
|
const StepTitle = styled(Typography)`
|
|
149
|
-
color: ${colors.text};
|
|
149
|
+
color: ${colors$1.text};
|
|
150
150
|
font-size: 24px;
|
|
151
151
|
font-weight: 600;
|
|
152
152
|
margin-bottom: 8px;
|
|
@@ -155,11 +155,11 @@ const StepTitle = styled(Typography)`
|
|
|
155
155
|
gap: 12px;
|
|
156
156
|
`;
|
|
157
157
|
const StepSubtitle = styled(Typography)`
|
|
158
|
-
color: ${colors.textLight};
|
|
158
|
+
color: ${colors$1.textLight};
|
|
159
159
|
font-size: 14px;
|
|
160
160
|
line-height: 1.5;
|
|
161
161
|
`;
|
|
162
|
-
const StepperContainer = styled(Box)`
|
|
162
|
+
const StepperContainer$1 = styled(Box)`
|
|
163
163
|
display: flex;
|
|
164
164
|
align-items: flex-start;
|
|
165
165
|
justify-content: center;
|
|
@@ -169,7 +169,7 @@ const StepperContainer = styled(Box)`
|
|
|
169
169
|
position: relative;
|
|
170
170
|
padding: 0 40px;
|
|
171
171
|
`;
|
|
172
|
-
const StepWrapper = styled.div`
|
|
172
|
+
const StepWrapper$1 = styled.div`
|
|
173
173
|
flex: 1;
|
|
174
174
|
display: flex;
|
|
175
175
|
flex-direction: column;
|
|
@@ -183,18 +183,18 @@ const StepWrapper = styled.div`
|
|
|
183
183
|
left: 50%;
|
|
184
184
|
width: 100%;
|
|
185
185
|
height: 3px;
|
|
186
|
-
background: ${(props) => props.$completed ? colors.success : colors.neutralLight};
|
|
186
|
+
background: ${(props) => props.$completed ? colors$1.success : colors$1.neutralLight};
|
|
187
187
|
transition: all 0.4s ease;
|
|
188
188
|
z-index: 0;
|
|
189
189
|
}
|
|
190
190
|
`;
|
|
191
|
-
const StepDot = styled.div`
|
|
191
|
+
const StepDot$1 = styled.div`
|
|
192
192
|
width: 56px;
|
|
193
193
|
height: 56px;
|
|
194
194
|
border-radius: 50%;
|
|
195
|
-
background: ${(props) => props.$active ? colors.primary : props.$completed ? colors.success : colors.white};
|
|
196
|
-
color: ${(props) => props.$active || props.$completed ? colors.white : colors.textLight};
|
|
197
|
-
border: 4px solid ${(props) => props.$active ? colors.primary : props.$completed ? colors.success : colors.border};
|
|
195
|
+
background: ${(props) => props.$active ? colors$1.primary : props.$completed ? colors$1.success : colors$1.white};
|
|
196
|
+
color: ${(props) => props.$active || props.$completed ? colors$1.white : colors$1.textLight};
|
|
197
|
+
border: 4px solid ${(props) => props.$active ? colors$1.primary : props.$completed ? colors$1.success : colors$1.border};
|
|
198
198
|
display: flex;
|
|
199
199
|
align-items: center;
|
|
200
200
|
justify-content: center;
|
|
@@ -204,20 +204,20 @@ const StepDot = styled.div`
|
|
|
204
204
|
position: relative;
|
|
205
205
|
z-index: 1;
|
|
206
206
|
cursor: ${(props) => props.$completed ? "pointer" : "default"};
|
|
207
|
-
box-shadow: ${(props) => props.$active ? `0 4px 16px ${colors.primary}40, 0 0 0 8px ${colors.primaryLight}` : props.$completed ? `0 4px 12px ${colors.success}30` : "0 2px 8px rgba(0,0,0,0.08)"};
|
|
207
|
+
box-shadow: ${(props) => props.$active ? `0 4px 16px ${colors$1.primary}40, 0 0 0 8px ${colors$1.primaryLight}` : props.$completed ? `0 4px 12px ${colors$1.success}30` : "0 2px 8px rgba(0,0,0,0.08)"};
|
|
208
208
|
|
|
209
209
|
${(props) => props.$active && css`
|
|
210
|
-
animation: ${pulse$
|
|
210
|
+
animation: ${pulse$3} 2s infinite;
|
|
211
211
|
`}
|
|
212
212
|
|
|
213
213
|
&:hover {
|
|
214
214
|
transform: ${(props) => props.$completed ? "scale(1.1)" : props.$active ? "scale(1.05)" : "scale(1)"};
|
|
215
215
|
}
|
|
216
216
|
`;
|
|
217
|
-
const StepLabel = styled(Typography)`
|
|
217
|
+
const StepLabel$1 = styled(Typography)`
|
|
218
218
|
margin-top: 12px;
|
|
219
219
|
font-size: 13px;
|
|
220
|
-
color: ${(props) => props.$active ? colors.primary : props.$completed ? colors.success : colors.textLight};
|
|
220
|
+
color: ${(props) => props.$active ? colors$1.primary : props.$completed ? colors$1.success : colors$1.textLight};
|
|
221
221
|
white-space: nowrap;
|
|
222
222
|
font-weight: ${(props) => props.$active ? 600 : 500};
|
|
223
223
|
text-align: center;
|
|
@@ -234,8 +234,8 @@ const ProvidersGrid = styled(Box)`
|
|
|
234
234
|
margin-right: auto;
|
|
235
235
|
`;
|
|
236
236
|
const ProviderCard = styled(Box)`
|
|
237
|
-
background: ${(props) => props.$selected ? colors.successLight : colors.white};
|
|
238
|
-
border: 2px solid ${(props) => props.$selected ? colors.success : colors.border};
|
|
237
|
+
background: ${(props) => props.$selected ? colors$1.successLight : colors$1.white};
|
|
238
|
+
border: 2px solid ${(props) => props.$selected ? colors$1.success : colors$1.border};
|
|
239
239
|
border-radius: 12px;
|
|
240
240
|
padding: 24px;
|
|
241
241
|
cursor: pointer;
|
|
@@ -266,7 +266,7 @@ const ProviderCard = styled(Box)`
|
|
|
266
266
|
&:hover {
|
|
267
267
|
transform: translateY(-4px);
|
|
268
268
|
box-shadow: 0 8px 24px rgba(73, 69, 255, 0.12);
|
|
269
|
-
border-color: ${(props) => props.$selected ? colors.success : colors.primary};
|
|
269
|
+
border-color: ${(props) => props.$selected ? colors$1.success : colors$1.primary};
|
|
270
270
|
|
|
271
271
|
&::before {
|
|
272
272
|
opacity: 1;
|
|
@@ -281,7 +281,7 @@ const ProviderCard = styled(Box)`
|
|
|
281
281
|
right: 8px;
|
|
282
282
|
width: 24px;
|
|
283
283
|
height: 24px;
|
|
284
|
-
background: ${colors.success};
|
|
284
|
+
background: ${colors$1.success};
|
|
285
285
|
color: white;
|
|
286
286
|
border-radius: 50%;
|
|
287
287
|
display: flex;
|
|
@@ -296,33 +296,33 @@ const ProviderIcon = styled.div`
|
|
|
296
296
|
width: 56px;
|
|
297
297
|
height: 56px;
|
|
298
298
|
border-radius: ${(props) => props.$round ? "50%" : "12px"};
|
|
299
|
-
background: ${(props) => props.$bgColor || colors.primaryLight};
|
|
299
|
+
background: ${(props) => props.$bgColor || colors$1.primaryLight};
|
|
300
300
|
display: flex;
|
|
301
301
|
align-items: center;
|
|
302
302
|
justify-content: center;
|
|
303
303
|
font-size: ${(props) => props.$fontSize || "24px"};
|
|
304
304
|
font-weight: bold;
|
|
305
|
-
color: ${(props) => props.$color || colors.primary};
|
|
305
|
+
color: ${(props) => props.$color || colors$1.primary};
|
|
306
306
|
box-shadow: 0 4px 12px ${(props) => props.$shadowColor || "rgba(73, 69, 255, 0.15)"};
|
|
307
307
|
`;
|
|
308
308
|
const ProviderName = styled(Typography)`
|
|
309
309
|
font-weight: 600;
|
|
310
310
|
font-size: 15px;
|
|
311
|
-
color: ${colors.text};
|
|
311
|
+
color: ${colors$1.text};
|
|
312
312
|
margin: 0;
|
|
313
313
|
`;
|
|
314
314
|
styled(Typography)`
|
|
315
315
|
font-size: 12px;
|
|
316
|
-
color: ${colors.textLight};
|
|
316
|
+
color: ${colors$1.textLight};
|
|
317
317
|
margin: 0;
|
|
318
318
|
`;
|
|
319
319
|
const InfoAlert = styled(Alert)`
|
|
320
|
-
background: ${colors.primaryLight};
|
|
321
|
-
border: 1px solid ${colors.primary}33;
|
|
322
|
-
animation: ${fadeIn$
|
|
320
|
+
background: ${colors$1.primaryLight};
|
|
321
|
+
border: 1px solid ${colors$1.primary}33;
|
|
322
|
+
animation: ${fadeIn$6} 0.4s ease;
|
|
323
323
|
|
|
324
324
|
svg {
|
|
325
|
-
color: ${colors.primary};
|
|
325
|
+
color: ${colors$1.primary};
|
|
326
326
|
}
|
|
327
327
|
`;
|
|
328
328
|
const FormSection = styled(Box)`
|
|
@@ -342,7 +342,7 @@ const FullWidthField = styled(Box)`
|
|
|
342
342
|
}
|
|
343
343
|
`;
|
|
344
344
|
const SectionTitle = styled(Typography)`
|
|
345
|
-
color: ${colors.text};
|
|
345
|
+
color: ${colors$1.text};
|
|
346
346
|
font-weight: 600;
|
|
347
347
|
font-size: 16px;
|
|
348
348
|
margin-bottom: 16px;
|
|
@@ -351,14 +351,14 @@ const SectionTitle = styled(Typography)`
|
|
|
351
351
|
gap: 8px;
|
|
352
352
|
`;
|
|
353
353
|
styled(Box)`
|
|
354
|
-
background: linear-gradient(135deg, ${colors.primaryLight}, ${colors.successLight});
|
|
355
|
-
border: 2px solid ${colors.primary}33;
|
|
354
|
+
background: linear-gradient(135deg, ${colors$1.primaryLight}, ${colors$1.successLight});
|
|
355
|
+
border: 2px solid ${colors$1.primary}33;
|
|
356
356
|
border-radius: 12px;
|
|
357
357
|
padding: 20px;
|
|
358
358
|
transition: all 0.3s;
|
|
359
359
|
|
|
360
360
|
&:hover {
|
|
361
|
-
border-color: ${colors.primary}66;
|
|
361
|
+
border-color: ${colors$1.primary}66;
|
|
362
362
|
box-shadow: 0 4px 12px rgba(73, 69, 255, 0.1);
|
|
363
363
|
}
|
|
364
364
|
`;
|
|
@@ -858,13 +858,13 @@ const AddAccountModal = ({ isOpen, onClose, onAccountAdded, editAccount = null }
|
|
|
858
858
|
currentStep === 4 && "Set rate limits and priority for this account"
|
|
859
859
|
] })
|
|
860
860
|
] }),
|
|
861
|
-
/* @__PURE__ */ jsx(StepperContainer, { children: [1, 2, 3, 4].map((step) => /* @__PURE__ */ jsxs(
|
|
862
|
-
StepWrapper,
|
|
861
|
+
/* @__PURE__ */ jsx(StepperContainer$1, { children: [1, 2, 3, 4].map((step) => /* @__PURE__ */ jsxs(
|
|
862
|
+
StepWrapper$1,
|
|
863
863
|
{
|
|
864
864
|
$completed: currentStep > step,
|
|
865
865
|
children: [
|
|
866
866
|
/* @__PURE__ */ jsx(
|
|
867
|
-
StepDot,
|
|
867
|
+
StepDot$1,
|
|
868
868
|
{
|
|
869
869
|
$active: currentStep === step,
|
|
870
870
|
$completed: currentStep > step,
|
|
@@ -873,7 +873,7 @@ const AddAccountModal = ({ isOpen, onClose, onAccountAdded, editAccount = null }
|
|
|
873
873
|
}
|
|
874
874
|
),
|
|
875
875
|
/* @__PURE__ */ jsx(
|
|
876
|
-
StepLabel,
|
|
876
|
+
StepLabel$1,
|
|
877
877
|
{
|
|
878
878
|
$active: currentStep === step,
|
|
879
879
|
$completed: currentStep > step,
|
|
@@ -1205,7 +1205,7 @@ const AddAccountModal = ({ isOpen, onClose, onAccountAdded, editAccount = null }
|
|
|
1205
1205
|
background: "neutral100",
|
|
1206
1206
|
hasRadius: true,
|
|
1207
1207
|
style: {
|
|
1208
|
-
border: `1px solid ${colors.border}`,
|
|
1208
|
+
border: `1px solid ${colors$1.border}`,
|
|
1209
1209
|
borderRadius: "8px"
|
|
1210
1210
|
},
|
|
1211
1211
|
children: [
|
|
@@ -1222,7 +1222,7 @@ const AddAccountModal = ({ isOpen, onClose, onAccountAdded, editAccount = null }
|
|
|
1222
1222
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
1223
1223
|
/* @__PURE__ */ jsx("strong", { children: "1." }),
|
|
1224
1224
|
" Go to ",
|
|
1225
|
-
/* @__PURE__ */ jsx("a", { href: "https://console.cloud.google.com", target: "_blank", rel: "noopener noreferrer", style: { color: colors.primary, textDecoration: "underline" }, children: "console.cloud.google.com" })
|
|
1225
|
+
/* @__PURE__ */ jsx("a", { href: "https://console.cloud.google.com", target: "_blank", rel: "noopener noreferrer", style: { color: colors$1.primary, textDecoration: "underline" }, children: "console.cloud.google.com" })
|
|
1226
1226
|
] }),
|
|
1227
1227
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
1228
1228
|
/* @__PURE__ */ jsx("strong", { children: "2." }),
|
|
@@ -1248,7 +1248,7 @@ const AddAccountModal = ({ isOpen, onClose, onAccountAdded, editAccount = null }
|
|
|
1248
1248
|
fontFamily: "monospace",
|
|
1249
1249
|
fontSize: "13px",
|
|
1250
1250
|
wordBreak: "break-all",
|
|
1251
|
-
border: `1px solid ${colors.border}`
|
|
1251
|
+
border: `1px solid ${colors$1.border}`
|
|
1252
1252
|
},
|
|
1253
1253
|
children: [
|
|
1254
1254
|
window.location.origin,
|
|
@@ -1349,7 +1349,7 @@ const AddAccountModal = ({ isOpen, onClose, onAccountAdded, editAccount = null }
|
|
|
1349
1349
|
background: "neutral100",
|
|
1350
1350
|
hasRadius: true,
|
|
1351
1351
|
style: {
|
|
1352
|
-
border: `1px solid ${colors.border}`,
|
|
1352
|
+
border: `1px solid ${colors$1.border}`,
|
|
1353
1353
|
borderRadius: "8px"
|
|
1354
1354
|
},
|
|
1355
1355
|
children: [
|
|
@@ -1366,7 +1366,7 @@ const AddAccountModal = ({ isOpen, onClose, onAccountAdded, editAccount = null }
|
|
|
1366
1366
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
1367
1367
|
/* @__PURE__ */ jsx("strong", { children: "1." }),
|
|
1368
1368
|
" Go to ",
|
|
1369
|
-
/* @__PURE__ */ jsx("a", { href: "https://portal.azure.com", target: "_blank", rel: "noopener noreferrer", style: { color: colors.primary, textDecoration: "underline" }, children: "portal.azure.com" })
|
|
1369
|
+
/* @__PURE__ */ jsx("a", { href: "https://portal.azure.com", target: "_blank", rel: "noopener noreferrer", style: { color: colors$1.primary, textDecoration: "underline" }, children: "portal.azure.com" })
|
|
1370
1370
|
] }),
|
|
1371
1371
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
1372
1372
|
/* @__PURE__ */ jsx("strong", { children: "2." }),
|
|
@@ -1400,8 +1400,8 @@ const AddAccountModal = ({ isOpen, onClose, onAccountAdded, editAccount = null }
|
|
|
1400
1400
|
fontFamily: "monospace",
|
|
1401
1401
|
fontSize: "13px",
|
|
1402
1402
|
wordBreak: "break-all",
|
|
1403
|
-
color: colors.textSecondary,
|
|
1404
|
-
border: `1px solid ${colors.border}`
|
|
1403
|
+
color: colors$1.textSecondary,
|
|
1404
|
+
border: `1px solid ${colors$1.border}`
|
|
1405
1405
|
},
|
|
1406
1406
|
children: `${window.location.origin}/magic-mail/oauth/microsoft/callback`
|
|
1407
1407
|
}
|
|
@@ -1526,7 +1526,7 @@ const AddAccountModal = ({ isOpen, onClose, onAccountAdded, editAccount = null }
|
|
|
1526
1526
|
background: "neutral100",
|
|
1527
1527
|
hasRadius: true,
|
|
1528
1528
|
style: {
|
|
1529
|
-
border: `1px solid ${colors.border}`,
|
|
1529
|
+
border: `1px solid ${colors$1.border}`,
|
|
1530
1530
|
borderRadius: "8px"
|
|
1531
1531
|
},
|
|
1532
1532
|
children: [
|
|
@@ -1543,7 +1543,7 @@ const AddAccountModal = ({ isOpen, onClose, onAccountAdded, editAccount = null }
|
|
|
1543
1543
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
1544
1544
|
/* @__PURE__ */ jsx("strong", { children: "1." }),
|
|
1545
1545
|
" Go to ",
|
|
1546
|
-
/* @__PURE__ */ jsx("a", { href: "https://developer.yahoo.com/apps/", target: "_blank", rel: "noopener noreferrer", style: { color: colors.primary, textDecoration: "underline" }, children: "developer.yahoo.com/apps" })
|
|
1546
|
+
/* @__PURE__ */ jsx("a", { href: "https://developer.yahoo.com/apps/", target: "_blank", rel: "noopener noreferrer", style: { color: colors$1.primary, textDecoration: "underline" }, children: "developer.yahoo.com/apps" })
|
|
1547
1547
|
] }),
|
|
1548
1548
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
1549
1549
|
/* @__PURE__ */ jsx("strong", { children: "2." }),
|
|
@@ -1569,8 +1569,8 @@ const AddAccountModal = ({ isOpen, onClose, onAccountAdded, editAccount = null }
|
|
|
1569
1569
|
fontFamily: "monospace",
|
|
1570
1570
|
fontSize: "13px",
|
|
1571
1571
|
wordBreak: "break-all",
|
|
1572
|
-
color: colors.textSecondary,
|
|
1573
|
-
border: `1px solid ${colors.border}`
|
|
1572
|
+
color: colors$1.textSecondary,
|
|
1573
|
+
border: `1px solid ${colors$1.border}`
|
|
1574
1574
|
},
|
|
1575
1575
|
children: `${window.location.origin}/magic-mail/oauth/yahoo/callback`
|
|
1576
1576
|
}
|
|
@@ -1777,7 +1777,7 @@ const AddAccountModal = ({ isOpen, onClose, onAccountAdded, editAccount = null }
|
|
|
1777
1777
|
background: formData.isPrimary ? "#FEF3C7" : "neutral100",
|
|
1778
1778
|
hasRadius: true,
|
|
1779
1779
|
style: {
|
|
1780
|
-
border: formData.isPrimary ? `2px solid #F59E0B` : `1px solid ${colors.border}`,
|
|
1780
|
+
border: formData.isPrimary ? `2px solid #F59E0B` : `1px solid ${colors$1.border}`,
|
|
1781
1781
|
borderRadius: "8px",
|
|
1782
1782
|
transition: "all 0.2s ease"
|
|
1783
1783
|
},
|
|
@@ -1835,7 +1835,7 @@ const AddAccountModal = ({ isOpen, onClose, onAccountAdded, editAccount = null }
|
|
|
1835
1835
|
] }) })
|
|
1836
1836
|
] }) });
|
|
1837
1837
|
};
|
|
1838
|
-
const fadeIn$
|
|
1838
|
+
const fadeIn$5 = keyframes`
|
|
1839
1839
|
from { opacity: 0; transform: translateY(10px); }
|
|
1840
1840
|
to { opacity: 1; transform: translateY(0); }
|
|
1841
1841
|
`;
|
|
@@ -1847,7 +1847,7 @@ const float$3 = keyframes`
|
|
|
1847
1847
|
0%, 100% { transform: translateY(0px); }
|
|
1848
1848
|
50% { transform: translateY(-5px); }
|
|
1849
1849
|
`;
|
|
1850
|
-
const pulse$
|
|
1850
|
+
const pulse$2 = keyframes`
|
|
1851
1851
|
0%, 100% { opacity: 1; }
|
|
1852
1852
|
50% { opacity: 0.5; }
|
|
1853
1853
|
`;
|
|
@@ -1863,7 +1863,7 @@ const breakpoints$3 = {
|
|
|
1863
1863
|
mobile: "768px"
|
|
1864
1864
|
};
|
|
1865
1865
|
const Container$4 = styled(Box)`
|
|
1866
|
-
${css`animation: ${fadeIn$
|
|
1866
|
+
${css`animation: ${fadeIn$5} ${theme$3.transitions.slow};`}
|
|
1867
1867
|
min-height: 100vh;
|
|
1868
1868
|
max-width: 1440px;
|
|
1869
1869
|
margin: 0 auto;
|
|
@@ -1981,7 +1981,7 @@ const StatCard$3 = styled(Box)`
|
|
|
1981
1981
|
position: relative;
|
|
1982
1982
|
overflow: hidden;
|
|
1983
1983
|
transition: all ${theme$3.transitions.normal};
|
|
1984
|
-
${css`animation: ${fadeIn$
|
|
1984
|
+
${css`animation: ${fadeIn$5} ${theme$3.transitions.slow} backwards;`}
|
|
1985
1985
|
animation-delay: ${(props) => props.$delay || "0s"};
|
|
1986
1986
|
box-shadow: ${theme$3.shadows.sm};
|
|
1987
1987
|
border: 1px solid ${(props) => props.theme.colors.neutral200};
|
|
@@ -2107,7 +2107,7 @@ const OnlineBadge$1 = styled.div`
|
|
|
2107
2107
|
background: ${(props) => props.$active ? theme$3.colors.success[500] : props.theme.colors.neutral400};
|
|
2108
2108
|
display: inline-block;
|
|
2109
2109
|
margin-right: 8px;
|
|
2110
|
-
${css`animation: ${(props) => props.$active ? pulse$
|
|
2110
|
+
${css`animation: ${(props) => props.$active ? pulse$2 : "none"} 2s ease-in-out infinite;`}
|
|
2111
2111
|
`;
|
|
2112
2112
|
const StyledTable$3 = styled(Table)`
|
|
2113
2113
|
thead {
|
|
@@ -2798,6 +2798,10 @@ const theme$2 = {
|
|
|
2798
2798
|
danger: {
|
|
2799
2799
|
100: "#FEE2E2",
|
|
2800
2800
|
600: "#DC2626"
|
|
2801
|
+
},
|
|
2802
|
+
neutral: {
|
|
2803
|
+
100: "#F3F4F6",
|
|
2804
|
+
200: "#E5E7EB"
|
|
2801
2805
|
}
|
|
2802
2806
|
},
|
|
2803
2807
|
shadows: {
|
|
@@ -2823,7 +2827,7 @@ const theme$2 = {
|
|
|
2823
2827
|
xl: "16px"
|
|
2824
2828
|
}
|
|
2825
2829
|
};
|
|
2826
|
-
const fadeIn$
|
|
2830
|
+
const fadeIn$4 = keyframes`
|
|
2827
2831
|
from { opacity: 0; transform: translateY(10px); }
|
|
2828
2832
|
to { opacity: 1; transform: translateY(0); }
|
|
2829
2833
|
`;
|
|
@@ -2835,7 +2839,7 @@ const float$2 = keyframes`
|
|
|
2835
2839
|
0%, 100% { transform: translateY(0px); }
|
|
2836
2840
|
50% { transform: translateY(-5px); }
|
|
2837
2841
|
`;
|
|
2838
|
-
const pulse = keyframes`
|
|
2842
|
+
const pulse$1 = keyframes`
|
|
2839
2843
|
0%, 100% { opacity: 1; }
|
|
2840
2844
|
50% { opacity: 0.5; }
|
|
2841
2845
|
`;
|
|
@@ -2851,7 +2855,7 @@ const breakpoints$2 = {
|
|
|
2851
2855
|
mobile: "768px"
|
|
2852
2856
|
};
|
|
2853
2857
|
const Container$3 = styled(Box)`
|
|
2854
|
-
${css`animation: ${fadeIn$
|
|
2858
|
+
${css`animation: ${fadeIn$4} ${theme$2.transitions.slow};`}
|
|
2855
2859
|
min-height: 100vh;
|
|
2856
2860
|
max-width: 1440px;
|
|
2857
2861
|
margin: 0 auto;
|
|
@@ -2969,7 +2973,7 @@ const StatCard$2 = styled(Box)`
|
|
|
2969
2973
|
position: relative;
|
|
2970
2974
|
overflow: hidden;
|
|
2971
2975
|
transition: all ${theme$2.transitions.normal};
|
|
2972
|
-
${css`animation: ${fadeIn$
|
|
2976
|
+
${css`animation: ${fadeIn$4} ${theme$2.transitions.slow} backwards;`}
|
|
2973
2977
|
animation-delay: ${(props) => props.$delay || "0s"};
|
|
2974
2978
|
box-shadow: ${theme$2.shadows.sm};
|
|
2975
2979
|
border: 1px solid ${(props) => props.theme.colors.neutral200};
|
|
@@ -3095,7 +3099,7 @@ const OnlineBadge = styled.div`
|
|
|
3095
3099
|
background: ${(props) => props.$active ? theme$2.colors.success[500] : props.theme.colors.neutral400};
|
|
3096
3100
|
display: inline-block;
|
|
3097
3101
|
margin-right: 8px;
|
|
3098
|
-
${css`animation: ${(props) => props.$active ? pulse : "none"} 2s ease-in-out infinite;`}
|
|
3102
|
+
${css`animation: ${(props) => props.$active ? pulse$1 : "none"} 2s ease-in-out infinite;`}
|
|
3099
3103
|
`;
|
|
3100
3104
|
const StyledTable$2 = styled(Table)`
|
|
3101
3105
|
thead {
|
|
@@ -3394,7 +3398,8 @@ const RoutingRulesPage = () => {
|
|
|
3394
3398
|
rule.fallbackAccountName && /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", children: [
|
|
3395
3399
|
"Fallback: ",
|
|
3396
3400
|
rule.fallbackAccountName
|
|
3397
|
-
] })
|
|
3401
|
+
] }),
|
|
3402
|
+
rule.whatsappFallback && /* @__PURE__ */ jsx(Badge, { backgroundColor: "success100", textColor: "success700", size: "S", children: "+ WhatsApp" })
|
|
3398
3403
|
] }) }),
|
|
3399
3404
|
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(
|
|
3400
3405
|
Badge,
|
|
@@ -3461,7 +3466,8 @@ const RuleModal = ({ rule, accounts, onClose, onSave }) => {
|
|
|
3461
3466
|
matchType: rule?.matchType || "emailType",
|
|
3462
3467
|
matchValue: rule?.matchValue || "",
|
|
3463
3468
|
accountName: rule?.accountName || "",
|
|
3464
|
-
fallbackAccountName: rule?.fallbackAccountName || ""
|
|
3469
|
+
fallbackAccountName: rule?.fallbackAccountName || "",
|
|
3470
|
+
whatsappFallback: rule?.whatsappFallback || false
|
|
3465
3471
|
});
|
|
3466
3472
|
const handleChange = (field, value) => {
|
|
3467
3473
|
setFormData((prev) => ({ ...prev, [field]: value }));
|
|
@@ -3616,6 +3622,36 @@ const RuleModal = ({ rule, accounts, onClose, onSave }) => {
|
|
|
3616
3622
|
),
|
|
3617
3623
|
/* @__PURE__ */ jsx(Field.Hint, { children: "Use this account if the target account is unavailable or rate-limited" })
|
|
3618
3624
|
] }),
|
|
3625
|
+
/* @__PURE__ */ jsx(
|
|
3626
|
+
Box,
|
|
3627
|
+
{
|
|
3628
|
+
padding: 4,
|
|
3629
|
+
background: formData.whatsappFallback ? theme$2.colors.success[100] : theme$2.colors.neutral[100],
|
|
3630
|
+
hasRadius: true,
|
|
3631
|
+
style: {
|
|
3632
|
+
width: "100%",
|
|
3633
|
+
border: formData.whatsappFallback ? `2px solid ${theme$2.colors.success[600]}` : `1px solid ${theme$2.colors.neutral[200]}`,
|
|
3634
|
+
borderRadius: theme$2.borderRadius.md,
|
|
3635
|
+
transition: "all 0.2s ease"
|
|
3636
|
+
},
|
|
3637
|
+
children: /* @__PURE__ */ jsxs(Flex, { gap: 3, alignItems: "center", children: [
|
|
3638
|
+
/* @__PURE__ */ jsx(
|
|
3639
|
+
Toggle,
|
|
3640
|
+
{
|
|
3641
|
+
checked: formData.whatsappFallback,
|
|
3642
|
+
onChange: () => handleChange("whatsappFallback", !formData.whatsappFallback)
|
|
3643
|
+
}
|
|
3644
|
+
),
|
|
3645
|
+
/* @__PURE__ */ jsxs(Box, { style: { flex: 1 }, children: [
|
|
3646
|
+
/* @__PURE__ */ jsxs(Flex, { alignItems: "center", gap: 2, children: [
|
|
3647
|
+
/* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", children: "WhatsApp Fallback" }),
|
|
3648
|
+
formData.whatsappFallback && /* @__PURE__ */ jsx(Badge, { backgroundColor: "success600", textColor: "neutral0", size: "S", children: "ENABLED" })
|
|
3649
|
+
] }),
|
|
3650
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", marginTop: 1, children: formData.whatsappFallback ? "If ALL email accounts fail, message will be sent via WhatsApp (requires connected WhatsApp & phone number in email data)" : "Enable to use WhatsApp as last-resort fallback when email delivery fails" })
|
|
3651
|
+
] })
|
|
3652
|
+
] })
|
|
3653
|
+
}
|
|
3654
|
+
),
|
|
3619
3655
|
/* @__PURE__ */ jsxs(Field.Root, { style: { width: "100%" }, children: [
|
|
3620
3656
|
/* @__PURE__ */ jsx(Field.Label, { children: "Rule Priority" }),
|
|
3621
3657
|
/* @__PURE__ */ jsx(
|
|
@@ -3819,7 +3855,7 @@ const theme$1 = {
|
|
|
3819
3855
|
spacing: { xs: "4px", sm: "8px", md: "16px", lg: "24px", xl: "32px", "2xl": "48px" },
|
|
3820
3856
|
borderRadius: { md: "8px", lg: "12px", xl: "16px" }
|
|
3821
3857
|
};
|
|
3822
|
-
const fadeIn$
|
|
3858
|
+
const fadeIn$3 = keyframes`
|
|
3823
3859
|
from { opacity: 0; transform: translateY(10px); }
|
|
3824
3860
|
to { opacity: 1; transform: translateY(0); }
|
|
3825
3861
|
`;
|
|
@@ -3972,7 +4008,7 @@ const CopyButton = styled(Button)`
|
|
|
3972
4008
|
height: 14px;
|
|
3973
4009
|
}
|
|
3974
4010
|
`;
|
|
3975
|
-
const InfoBox = styled(Box)`
|
|
4011
|
+
const InfoBox$1 = styled(Box)`
|
|
3976
4012
|
background: linear-gradient(135deg, ${theme$1.colors.primary[50]}, ${theme$1.colors.primary[100]});
|
|
3977
4013
|
border-left: 4px solid ${theme$1.colors.primary[500]};
|
|
3978
4014
|
border-radius: 8px;
|
|
@@ -4019,7 +4055,7 @@ const breakpoints$1 = {
|
|
|
4019
4055
|
tablet: "1024px"
|
|
4020
4056
|
};
|
|
4021
4057
|
const Container$2 = styled(Box)`
|
|
4022
|
-
${css`animation: ${fadeIn$
|
|
4058
|
+
${css`animation: ${fadeIn$3} ${theme$1.transitions.slow};`}
|
|
4023
4059
|
min-height: 100vh;
|
|
4024
4060
|
max-width: 1440px;
|
|
4025
4061
|
margin: 0 auto;
|
|
@@ -4132,7 +4168,7 @@ const StatCard$1 = styled(Box)`
|
|
|
4132
4168
|
position: relative;
|
|
4133
4169
|
overflow: hidden;
|
|
4134
4170
|
transition: all ${theme$1.transitions.normal};
|
|
4135
|
-
${css`animation: ${fadeIn$
|
|
4171
|
+
${css`animation: ${fadeIn$3} ${theme$1.transitions.slow} backwards;`}
|
|
4136
4172
|
animation-delay: ${(props) => props.$delay || "0s"};
|
|
4137
4173
|
box-shadow: ${theme$1.shadows.sm};
|
|
4138
4174
|
border: 1px solid ${(props) => props.theme.colors.neutral200};
|
|
@@ -5212,7 +5248,7 @@ const TemplateList = () => {
|
|
|
5212
5248
|
)
|
|
5213
5249
|
] })
|
|
5214
5250
|
] }),
|
|
5215
|
-
/* @__PURE__ */ jsx(InfoBox, { children: /* @__PURE__ */ jsxs(Flex, { alignItems: "center", justifyContent: "space-between", children: [
|
|
5251
|
+
/* @__PURE__ */ jsx(InfoBox$1, { children: /* @__PURE__ */ jsxs(Flex, { alignItems: "center", justifyContent: "space-between", children: [
|
|
5216
5252
|
/* @__PURE__ */ jsxs(Typography, { variant: "pi", style: { color: theme$1.colors.primary[700] }, children: [
|
|
5217
5253
|
/* @__PURE__ */ jsx("strong", { children: "Template ID:" }),
|
|
5218
5254
|
" #",
|
|
@@ -6512,7 +6548,7 @@ const theme = {
|
|
|
6512
6548
|
spacing: { xs: "4px", sm: "8px", md: "16px", lg: "24px", xl: "32px", "2xl": "48px" },
|
|
6513
6549
|
borderRadius: { lg: "12px", xl: "16px" }
|
|
6514
6550
|
};
|
|
6515
|
-
const fadeIn$
|
|
6551
|
+
const fadeIn$2 = keyframes`
|
|
6516
6552
|
from { opacity: 0; transform: translateY(10px); }
|
|
6517
6553
|
to { opacity: 1; transform: translateY(0); }
|
|
6518
6554
|
`;
|
|
@@ -6528,7 +6564,7 @@ const breakpoints = {
|
|
|
6528
6564
|
mobile: "768px"
|
|
6529
6565
|
};
|
|
6530
6566
|
const Container = styled(Box)`
|
|
6531
|
-
${css`animation: ${fadeIn$
|
|
6567
|
+
${css`animation: ${fadeIn$2} ${theme.transitions.slow};`}
|
|
6532
6568
|
min-height: 100vh;
|
|
6533
6569
|
max-width: 1440px;
|
|
6534
6570
|
margin: 0 auto;
|
|
@@ -6641,7 +6677,7 @@ const StatCard = styled(Box)`
|
|
|
6641
6677
|
position: relative;
|
|
6642
6678
|
overflow: hidden;
|
|
6643
6679
|
transition: all ${theme.transitions.normal};
|
|
6644
|
-
${css`animation: ${fadeIn$
|
|
6680
|
+
${css`animation: ${fadeIn$2} ${theme.transitions.slow} backwards;`}
|
|
6645
6681
|
animation-delay: ${(props) => props.$delay || "0s"};
|
|
6646
6682
|
box-shadow: ${theme.shadows.sm};
|
|
6647
6683
|
border: 1px solid ${(props) => props.theme.colors.neutral200};
|
|
@@ -7077,6 +7113,679 @@ const Analytics = () => {
|
|
|
7077
7113
|
] }) })
|
|
7078
7114
|
] });
|
|
7079
7115
|
};
|
|
7116
|
+
const fadeIn$1 = keyframes`
|
|
7117
|
+
from {
|
|
7118
|
+
opacity: 0;
|
|
7119
|
+
transform: translateY(10px);
|
|
7120
|
+
}
|
|
7121
|
+
to {
|
|
7122
|
+
opacity: 1;
|
|
7123
|
+
transform: translateY(0);
|
|
7124
|
+
}
|
|
7125
|
+
`;
|
|
7126
|
+
const pulse = keyframes`
|
|
7127
|
+
0%, 100% {
|
|
7128
|
+
transform: scale(1);
|
|
7129
|
+
}
|
|
7130
|
+
50% {
|
|
7131
|
+
transform: scale(1.05);
|
|
7132
|
+
}
|
|
7133
|
+
`;
|
|
7134
|
+
const spin = keyframes`
|
|
7135
|
+
from {
|
|
7136
|
+
transform: rotate(0deg);
|
|
7137
|
+
}
|
|
7138
|
+
to {
|
|
7139
|
+
transform: rotate(360deg);
|
|
7140
|
+
}
|
|
7141
|
+
`;
|
|
7142
|
+
const colors = {
|
|
7143
|
+
whatsapp: "#25D366",
|
|
7144
|
+
whatsappDark: "#128C7E",
|
|
7145
|
+
whatsappLight: "#DCF8C6",
|
|
7146
|
+
primary: "#4945ff",
|
|
7147
|
+
primaryLight: "#f0f0ff",
|
|
7148
|
+
success: "#5cb176",
|
|
7149
|
+
successLight: "#eafaf1",
|
|
7150
|
+
danger: "#d02b20",
|
|
7151
|
+
neutral: "#8e8ea9",
|
|
7152
|
+
neutralLight: "#f6f6f9",
|
|
7153
|
+
white: "#ffffff",
|
|
7154
|
+
border: "#dcdce4",
|
|
7155
|
+
textLight: "#666687"
|
|
7156
|
+
};
|
|
7157
|
+
const PageContainer = styled(Box)`
|
|
7158
|
+
padding: 40px;
|
|
7159
|
+
max-width: 900px;
|
|
7160
|
+
margin: 0 auto;
|
|
7161
|
+
animation: ${fadeIn$1} 0.4s ease;
|
|
7162
|
+
`;
|
|
7163
|
+
const HeaderSection = styled(Box)`
|
|
7164
|
+
text-align: center;
|
|
7165
|
+
margin-bottom: 48px;
|
|
7166
|
+
`;
|
|
7167
|
+
const WhatsAppLogo = styled.div`
|
|
7168
|
+
width: 80px;
|
|
7169
|
+
height: 80px;
|
|
7170
|
+
border-radius: 50%;
|
|
7171
|
+
background: linear-gradient(135deg, ${colors.whatsapp}, ${colors.whatsappDark});
|
|
7172
|
+
display: flex;
|
|
7173
|
+
align-items: center;
|
|
7174
|
+
justify-content: center;
|
|
7175
|
+
margin: 0 auto 24px;
|
|
7176
|
+
box-shadow: 0 8px 32px ${colors.whatsapp}40;
|
|
7177
|
+
`;
|
|
7178
|
+
const PhoneIcon = styled.div`
|
|
7179
|
+
width: 40px;
|
|
7180
|
+
height: 40px;
|
|
7181
|
+
color: white;
|
|
7182
|
+
font-size: 32px;
|
|
7183
|
+
`;
|
|
7184
|
+
const StepperContainer = styled(Box)`
|
|
7185
|
+
display: flex;
|
|
7186
|
+
align-items: flex-start;
|
|
7187
|
+
justify-content: center;
|
|
7188
|
+
gap: 0;
|
|
7189
|
+
margin-bottom: 48px;
|
|
7190
|
+
position: relative;
|
|
7191
|
+
padding: 0 40px;
|
|
7192
|
+
`;
|
|
7193
|
+
const StepWrapper = styled.div`
|
|
7194
|
+
flex: 1;
|
|
7195
|
+
display: flex;
|
|
7196
|
+
flex-direction: column;
|
|
7197
|
+
align-items: center;
|
|
7198
|
+
position: relative;
|
|
7199
|
+
|
|
7200
|
+
&:not(:last-child)::after {
|
|
7201
|
+
content: '';
|
|
7202
|
+
position: absolute;
|
|
7203
|
+
top: 28px;
|
|
7204
|
+
left: 50%;
|
|
7205
|
+
width: 100%;
|
|
7206
|
+
height: 3px;
|
|
7207
|
+
background: ${(props) => props.$completed ? colors.success : colors.neutralLight};
|
|
7208
|
+
transition: all 0.4s ease;
|
|
7209
|
+
z-index: 0;
|
|
7210
|
+
}
|
|
7211
|
+
`;
|
|
7212
|
+
const StepDot = styled.div`
|
|
7213
|
+
width: 56px;
|
|
7214
|
+
height: 56px;
|
|
7215
|
+
border-radius: 50%;
|
|
7216
|
+
background: ${(props) => props.$active ? colors.whatsapp : props.$completed ? colors.success : colors.white};
|
|
7217
|
+
color: ${(props) => props.$active || props.$completed ? colors.white : colors.textLight};
|
|
7218
|
+
border: 4px solid ${(props) => props.$active ? colors.whatsapp : props.$completed ? colors.success : colors.border};
|
|
7219
|
+
display: flex;
|
|
7220
|
+
align-items: center;
|
|
7221
|
+
justify-content: center;
|
|
7222
|
+
font-weight: 700;
|
|
7223
|
+
font-size: 18px;
|
|
7224
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
7225
|
+
position: relative;
|
|
7226
|
+
z-index: 1;
|
|
7227
|
+
cursor: ${(props) => props.$completed ? "pointer" : "default"};
|
|
7228
|
+
box-shadow: ${(props) => props.$active ? `0 4px 16px ${colors.whatsapp}40, 0 0 0 8px ${colors.whatsappLight}` : props.$completed ? `0 4px 12px ${colors.success}30` : "0 2px 8px rgba(0,0,0,0.08)"};
|
|
7229
|
+
|
|
7230
|
+
${(props) => props.$active && css`
|
|
7231
|
+
animation: ${pulse} 2s infinite;
|
|
7232
|
+
`}
|
|
7233
|
+
|
|
7234
|
+
&:hover {
|
|
7235
|
+
transform: ${(props) => props.$completed ? "scale(1.1)" : props.$active ? "scale(1.05)" : "scale(1)"};
|
|
7236
|
+
}
|
|
7237
|
+
`;
|
|
7238
|
+
const StepLabel = styled(Typography)`
|
|
7239
|
+
margin-top: 12px;
|
|
7240
|
+
font-size: 13px;
|
|
7241
|
+
color: ${(props) => props.$active ? colors.whatsapp : props.$completed ? colors.success : colors.textLight};
|
|
7242
|
+
white-space: nowrap;
|
|
7243
|
+
font-weight: ${(props) => props.$active ? 600 : 500};
|
|
7244
|
+
text-align: center;
|
|
7245
|
+
transition: all 0.3s ease;
|
|
7246
|
+
`;
|
|
7247
|
+
const ContentCard = styled(Box)`
|
|
7248
|
+
background: ${colors.white};
|
|
7249
|
+
border: 1px solid ${colors.border};
|
|
7250
|
+
border-radius: 16px;
|
|
7251
|
+
padding: 32px;
|
|
7252
|
+
margin-bottom: 24px;
|
|
7253
|
+
animation: ${fadeIn$1} 0.4s ease;
|
|
7254
|
+
box-shadow: 0 4px 24px rgba(0,0,0,0.06);
|
|
7255
|
+
`;
|
|
7256
|
+
const QRCodeContainer = styled.div`
|
|
7257
|
+
display: flex;
|
|
7258
|
+
flex-direction: column;
|
|
7259
|
+
align-items: center;
|
|
7260
|
+
padding: 32px;
|
|
7261
|
+
background: ${colors.neutralLight};
|
|
7262
|
+
border-radius: 16px;
|
|
7263
|
+
margin: 24px 0;
|
|
7264
|
+
`;
|
|
7265
|
+
const QRImage = styled.img`
|
|
7266
|
+
width: 280px;
|
|
7267
|
+
height: 280px;
|
|
7268
|
+
border-radius: 12px;
|
|
7269
|
+
box-shadow: 0 4px 24px rgba(0,0,0,0.1);
|
|
7270
|
+
`;
|
|
7271
|
+
const StatusBadge = styled.div`
|
|
7272
|
+
display: inline-flex;
|
|
7273
|
+
align-items: center;
|
|
7274
|
+
gap: 8px;
|
|
7275
|
+
padding: 8px 16px;
|
|
7276
|
+
border-radius: 20px;
|
|
7277
|
+
font-weight: 600;
|
|
7278
|
+
font-size: 14px;
|
|
7279
|
+
background: ${(props) => {
|
|
7280
|
+
switch (props.$status) {
|
|
7281
|
+
case "connected":
|
|
7282
|
+
return colors.successLight;
|
|
7283
|
+
case "connecting":
|
|
7284
|
+
return colors.primaryLight;
|
|
7285
|
+
case "qr_pending":
|
|
7286
|
+
return colors.whatsappLight;
|
|
7287
|
+
case "disconnected":
|
|
7288
|
+
return colors.neutralLight;
|
|
7289
|
+
default:
|
|
7290
|
+
return colors.neutralLight;
|
|
7291
|
+
}
|
|
7292
|
+
}};
|
|
7293
|
+
color: ${(props) => {
|
|
7294
|
+
switch (props.$status) {
|
|
7295
|
+
case "connected":
|
|
7296
|
+
return colors.success;
|
|
7297
|
+
case "connecting":
|
|
7298
|
+
return colors.primary;
|
|
7299
|
+
case "qr_pending":
|
|
7300
|
+
return colors.whatsappDark;
|
|
7301
|
+
case "disconnected":
|
|
7302
|
+
return colors.neutral;
|
|
7303
|
+
default:
|
|
7304
|
+
return colors.neutral;
|
|
7305
|
+
}
|
|
7306
|
+
}};
|
|
7307
|
+
`;
|
|
7308
|
+
const SpinningLoader = styled.div`
|
|
7309
|
+
width: 20px;
|
|
7310
|
+
height: 20px;
|
|
7311
|
+
border: 2px solid ${colors.primary}40;
|
|
7312
|
+
border-top-color: ${colors.primary};
|
|
7313
|
+
border-radius: 50%;
|
|
7314
|
+
animation: ${spin} 1s linear infinite;
|
|
7315
|
+
`;
|
|
7316
|
+
const ConnectedCard = styled(Box)`
|
|
7317
|
+
background: linear-gradient(135deg, ${colors.successLight}, ${colors.whatsappLight});
|
|
7318
|
+
border: 2px solid ${colors.success};
|
|
7319
|
+
border-radius: 16px;
|
|
7320
|
+
padding: 32px;
|
|
7321
|
+
text-align: center;
|
|
7322
|
+
`;
|
|
7323
|
+
const InfoBox = styled(Box)`
|
|
7324
|
+
background: ${colors.primaryLight};
|
|
7325
|
+
border: 1px solid ${colors.primary}33;
|
|
7326
|
+
border-radius: 12px;
|
|
7327
|
+
padding: 20px;
|
|
7328
|
+
margin: 16px 0;
|
|
7329
|
+
`;
|
|
7330
|
+
const TestSection = styled(Box)`
|
|
7331
|
+
background: ${colors.neutralLight};
|
|
7332
|
+
border-radius: 12px;
|
|
7333
|
+
padding: 24px;
|
|
7334
|
+
margin-top: 24px;
|
|
7335
|
+
`;
|
|
7336
|
+
const UseCaseCard = styled(Box)`
|
|
7337
|
+
background: linear-gradient(135deg, ${colors.primaryLight}, ${colors.whatsappLight});
|
|
7338
|
+
border: 2px solid ${colors.whatsapp};
|
|
7339
|
+
border-radius: 16px;
|
|
7340
|
+
padding: 24px;
|
|
7341
|
+
margin-bottom: 32px;
|
|
7342
|
+
`;
|
|
7343
|
+
const ButtonRow = styled(Flex)`
|
|
7344
|
+
margin-top: 32px;
|
|
7345
|
+
padding-top: 24px;
|
|
7346
|
+
border-top: 1px solid ${colors.border};
|
|
7347
|
+
`;
|
|
7348
|
+
const NotInstalledCard = styled(Box)`
|
|
7349
|
+
background: linear-gradient(135deg, #FEF3C7, #FEE2E2);
|
|
7350
|
+
border: 2px solid #F59E0B;
|
|
7351
|
+
border-radius: 16px;
|
|
7352
|
+
padding: 32px;
|
|
7353
|
+
text-align: center;
|
|
7354
|
+
`;
|
|
7355
|
+
const WhatsAppPage = () => {
|
|
7356
|
+
const { get, post } = useFetchClient();
|
|
7357
|
+
const { toggleNotification } = useNotification();
|
|
7358
|
+
const [currentStep, setCurrentStep] = useState(1);
|
|
7359
|
+
const [loading, setLoading] = useState(true);
|
|
7360
|
+
const [connecting, setConnecting] = useState(false);
|
|
7361
|
+
const [isAvailable, setIsAvailable] = useState(false);
|
|
7362
|
+
const [status, setStatus] = useState({
|
|
7363
|
+
status: "disconnected",
|
|
7364
|
+
qrCode: null,
|
|
7365
|
+
isConnected: false,
|
|
7366
|
+
session: null
|
|
7367
|
+
});
|
|
7368
|
+
const [testPhone, setTestPhone] = useState("");
|
|
7369
|
+
const [testMessage, setTestMessage] = useState("");
|
|
7370
|
+
const [sendingTest, setSendingTest] = useState(false);
|
|
7371
|
+
const stepTitles = ["Check Installation", "Connect WhatsApp", "Scan QR Code", "Ready to Use"];
|
|
7372
|
+
const checkAvailability = useCallback(async () => {
|
|
7373
|
+
try {
|
|
7374
|
+
const { data } = await get("/magic-mail/whatsapp/available");
|
|
7375
|
+
setIsAvailable(data.data.available);
|
|
7376
|
+
return data.data.available;
|
|
7377
|
+
} catch (error) {
|
|
7378
|
+
console.error("[MagicMail WhatsApp] Error checking availability:", error);
|
|
7379
|
+
setIsAvailable(false);
|
|
7380
|
+
return false;
|
|
7381
|
+
}
|
|
7382
|
+
}, [get]);
|
|
7383
|
+
const fetchStatus = useCallback(async () => {
|
|
7384
|
+
try {
|
|
7385
|
+
const { data } = await get("/magic-mail/whatsapp/status");
|
|
7386
|
+
setStatus(data.data);
|
|
7387
|
+
if (data.data.isConnected) {
|
|
7388
|
+
setCurrentStep(4);
|
|
7389
|
+
} else if (data.data.qrCode) {
|
|
7390
|
+
setCurrentStep(3);
|
|
7391
|
+
} else if (isAvailable) {
|
|
7392
|
+
setCurrentStep(2);
|
|
7393
|
+
}
|
|
7394
|
+
return data.data;
|
|
7395
|
+
} catch (error) {
|
|
7396
|
+
console.error("[MagicMail WhatsApp] Error fetching status:", error);
|
|
7397
|
+
return null;
|
|
7398
|
+
}
|
|
7399
|
+
}, [get, isAvailable]);
|
|
7400
|
+
useEffect(() => {
|
|
7401
|
+
const init = async () => {
|
|
7402
|
+
setLoading(true);
|
|
7403
|
+
const available = await checkAvailability();
|
|
7404
|
+
if (available) {
|
|
7405
|
+
await fetchStatus();
|
|
7406
|
+
}
|
|
7407
|
+
setLoading(false);
|
|
7408
|
+
};
|
|
7409
|
+
init();
|
|
7410
|
+
}, [checkAvailability, fetchStatus]);
|
|
7411
|
+
useEffect(() => {
|
|
7412
|
+
let pollInterval;
|
|
7413
|
+
if (connecting || status.status === "connecting" || status.status === "qr_pending") {
|
|
7414
|
+
pollInterval = setInterval(async () => {
|
|
7415
|
+
const newStatus = await fetchStatus();
|
|
7416
|
+
if (newStatus?.isConnected) {
|
|
7417
|
+
setConnecting(false);
|
|
7418
|
+
setCurrentStep(4);
|
|
7419
|
+
toggleNotification({
|
|
7420
|
+
type: "success",
|
|
7421
|
+
message: "[SUCCESS] WhatsApp connected successfully!"
|
|
7422
|
+
});
|
|
7423
|
+
}
|
|
7424
|
+
}, 2e3);
|
|
7425
|
+
}
|
|
7426
|
+
return () => {
|
|
7427
|
+
if (pollInterval) clearInterval(pollInterval);
|
|
7428
|
+
};
|
|
7429
|
+
}, [connecting, status.status, fetchStatus, toggleNotification]);
|
|
7430
|
+
const handleConnect = async () => {
|
|
7431
|
+
setConnecting(true);
|
|
7432
|
+
try {
|
|
7433
|
+
const { data } = await post("/magic-mail/whatsapp/connect", {});
|
|
7434
|
+
if (data.data.qrCode) {
|
|
7435
|
+
setStatus((prev) => ({ ...prev, qrCode: data.data.qrCode, status: "qr_pending" }));
|
|
7436
|
+
setCurrentStep(3);
|
|
7437
|
+
} else if (data.data.status === "connected") {
|
|
7438
|
+
setStatus((prev) => ({ ...prev, isConnected: true, status: "connected" }));
|
|
7439
|
+
setCurrentStep(4);
|
|
7440
|
+
toggleNotification({
|
|
7441
|
+
type: "success",
|
|
7442
|
+
message: "[SUCCESS] WhatsApp already connected!"
|
|
7443
|
+
});
|
|
7444
|
+
}
|
|
7445
|
+
} catch (error) {
|
|
7446
|
+
toggleNotification({
|
|
7447
|
+
type: "danger",
|
|
7448
|
+
message: "[ERROR] Failed to connect: " + (error.response?.data?.error?.message || error.message)
|
|
7449
|
+
});
|
|
7450
|
+
setConnecting(false);
|
|
7451
|
+
}
|
|
7452
|
+
};
|
|
7453
|
+
const handleDisconnect = async () => {
|
|
7454
|
+
try {
|
|
7455
|
+
await post("/magic-mail/whatsapp/disconnect", {});
|
|
7456
|
+
setStatus({
|
|
7457
|
+
status: "disconnected",
|
|
7458
|
+
qrCode: null,
|
|
7459
|
+
isConnected: false,
|
|
7460
|
+
session: null
|
|
7461
|
+
});
|
|
7462
|
+
setCurrentStep(2);
|
|
7463
|
+
toggleNotification({
|
|
7464
|
+
type: "success",
|
|
7465
|
+
message: "[SUCCESS] WhatsApp disconnected"
|
|
7466
|
+
});
|
|
7467
|
+
} catch (error) {
|
|
7468
|
+
toggleNotification({
|
|
7469
|
+
type: "danger",
|
|
7470
|
+
message: "[ERROR] Failed to disconnect"
|
|
7471
|
+
});
|
|
7472
|
+
}
|
|
7473
|
+
};
|
|
7474
|
+
const handleSendTest = async () => {
|
|
7475
|
+
if (!testPhone) {
|
|
7476
|
+
toggleNotification({
|
|
7477
|
+
type: "warning",
|
|
7478
|
+
message: "Please enter a phone number"
|
|
7479
|
+
});
|
|
7480
|
+
return;
|
|
7481
|
+
}
|
|
7482
|
+
setSendingTest(true);
|
|
7483
|
+
try {
|
|
7484
|
+
const { data } = await post("/magic-mail/whatsapp/send-test", {
|
|
7485
|
+
phoneNumber: testPhone,
|
|
7486
|
+
message: testMessage || void 0
|
|
7487
|
+
});
|
|
7488
|
+
if (data.success) {
|
|
7489
|
+
toggleNotification({
|
|
7490
|
+
type: "success",
|
|
7491
|
+
message: "[SUCCESS] Test message sent!"
|
|
7492
|
+
});
|
|
7493
|
+
setTestPhone("");
|
|
7494
|
+
setTestMessage("");
|
|
7495
|
+
} else {
|
|
7496
|
+
toggleNotification({
|
|
7497
|
+
type: "danger",
|
|
7498
|
+
message: "[ERROR] " + (data.data.error || "Failed to send message")
|
|
7499
|
+
});
|
|
7500
|
+
}
|
|
7501
|
+
} catch (error) {
|
|
7502
|
+
toggleNotification({
|
|
7503
|
+
type: "danger",
|
|
7504
|
+
message: "[ERROR] " + (error.response?.data?.error?.message || error.message)
|
|
7505
|
+
});
|
|
7506
|
+
} finally {
|
|
7507
|
+
setSendingTest(false);
|
|
7508
|
+
}
|
|
7509
|
+
};
|
|
7510
|
+
const renderStatusBadge = () => {
|
|
7511
|
+
const statusText = {
|
|
7512
|
+
connected: "Connected",
|
|
7513
|
+
connecting: "Connecting...",
|
|
7514
|
+
qr_pending: "Waiting for QR Scan",
|
|
7515
|
+
disconnected: "Disconnected"
|
|
7516
|
+
};
|
|
7517
|
+
return /* @__PURE__ */ jsxs(StatusBadge, { $status: status.status, children: [
|
|
7518
|
+
status.status === "connecting" && /* @__PURE__ */ jsx(SpinningLoader, {}),
|
|
7519
|
+
status.status === "connected" && /* @__PURE__ */ jsx(Check, {}),
|
|
7520
|
+
statusText[status.status] || "Unknown"
|
|
7521
|
+
] });
|
|
7522
|
+
};
|
|
7523
|
+
if (loading) {
|
|
7524
|
+
return /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsx(Flex, { justifyContent: "center", alignItems: "center", style: { minHeight: "400px" }, children: /* @__PURE__ */ jsx(Loader, {}) }) });
|
|
7525
|
+
}
|
|
7526
|
+
return /* @__PURE__ */ jsxs(PageContainer, { children: [
|
|
7527
|
+
/* @__PURE__ */ jsxs(HeaderSection, { children: [
|
|
7528
|
+
/* @__PURE__ */ jsx(WhatsAppLogo, { children: /* @__PURE__ */ jsx(PhoneIcon, { children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "40", height: "40", children: /* @__PURE__ */ jsx("path", { d: "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z" }) }) }) }),
|
|
7529
|
+
/* @__PURE__ */ jsx(Typography, { variant: "alpha", fontWeight: "bold", style: { display: "block", marginBottom: "8px" }, children: "WhatsApp Integration" }),
|
|
7530
|
+
/* @__PURE__ */ jsx(Typography, { variant: "epsilon", textColor: "neutral600", style: { display: "block" }, children: "Send messages via WhatsApp - completely free!" }),
|
|
7531
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 3, children: renderStatusBadge() })
|
|
7532
|
+
] }),
|
|
7533
|
+
/* @__PURE__ */ jsx(StepperContainer, { children: [1, 2, 3, 4].map((step) => /* @__PURE__ */ jsxs(
|
|
7534
|
+
StepWrapper,
|
|
7535
|
+
{
|
|
7536
|
+
$completed: currentStep > step,
|
|
7537
|
+
children: [
|
|
7538
|
+
/* @__PURE__ */ jsx(
|
|
7539
|
+
StepDot,
|
|
7540
|
+
{
|
|
7541
|
+
$active: currentStep === step,
|
|
7542
|
+
$completed: currentStep > step,
|
|
7543
|
+
onClick: () => currentStep > step && setCurrentStep(step),
|
|
7544
|
+
children: currentStep > step ? /* @__PURE__ */ jsx(Check, {}) : step
|
|
7545
|
+
}
|
|
7546
|
+
),
|
|
7547
|
+
/* @__PURE__ */ jsx(
|
|
7548
|
+
StepLabel,
|
|
7549
|
+
{
|
|
7550
|
+
$active: currentStep === step,
|
|
7551
|
+
$completed: currentStep > step,
|
|
7552
|
+
children: stepTitles[step - 1]
|
|
7553
|
+
}
|
|
7554
|
+
)
|
|
7555
|
+
]
|
|
7556
|
+
},
|
|
7557
|
+
step
|
|
7558
|
+
)) }),
|
|
7559
|
+
/* @__PURE__ */ jsxs(UseCaseCard, { children: [
|
|
7560
|
+
/* @__PURE__ */ jsx(Typography, { variant: "delta", fontWeight: "bold", style: { display: "block", marginBottom: "12px" }, children: "What can you do with WhatsApp?" }),
|
|
7561
|
+
/* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral700", style: { display: "block", marginBottom: "16px" }, children: "WhatsApp integration provides free messaging as an alternative or backup to email delivery." }),
|
|
7562
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, children: [
|
|
7563
|
+
/* @__PURE__ */ jsxs(Box, { padding: 3, background: "neutral0", hasRadius: true, style: { border: `1px solid ${colors.border}` }, children: [
|
|
7564
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", style: { display: "block", marginBottom: "4px" }, children: "1. FALLBACK-KANAL" }),
|
|
7565
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", style: { display: "block" }, children: "Wenn alle Email-Accounts fehlschlagen, wird die Nachricht automatisch via WhatsApp zugestellt." })
|
|
7566
|
+
] }),
|
|
7567
|
+
/* @__PURE__ */ jsxs(Box, { padding: 3, background: "neutral0", hasRadius: true, style: { border: `1px solid ${colors.border}` }, children: [
|
|
7568
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", style: { display: "block", marginBottom: "4px" }, children: "2. ADMIN-BENACHRICHTIGUNGEN" }),
|
|
7569
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", style: { display: "block" }, children: "Bei Email-Bounces, Quota-Limits oder Account-Fehlern wird der Admin via WhatsApp benachrichtigt." })
|
|
7570
|
+
] }),
|
|
7571
|
+
/* @__PURE__ */ jsxs(Box, { padding: 3, background: "neutral0", hasRadius: true, style: { border: `1px solid ${colors.border}` }, children: [
|
|
7572
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", style: { display: "block", marginBottom: "4px" }, children: "3. ROUTING-INTEGRATION" }),
|
|
7573
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", style: { display: "block" }, children: "In Routing-Regeln kann WhatsApp als Fallback-Kanal definiert werden (Routing Rules Tab)." })
|
|
7574
|
+
] })
|
|
7575
|
+
] })
|
|
7576
|
+
] }),
|
|
7577
|
+
currentStep === 1 && /* @__PURE__ */ jsxs(ContentCard, { children: [
|
|
7578
|
+
/* @__PURE__ */ jsx(Typography, { variant: "beta", fontWeight: "bold", style: { display: "block", marginBottom: "8px" }, children: "Check Installation" }),
|
|
7579
|
+
/* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral600", style: { display: "block", marginBottom: "24px" }, children: "First, we need to verify that the required dependencies are installed." }),
|
|
7580
|
+
isAvailable ? /* @__PURE__ */ jsx(Alert, { variant: "success", title: "[SUCCESS] Dependencies Installed", children: /* @__PURE__ */ jsx(Typography, { variant: "pi", style: { display: "block" }, children: "Baileys library is installed and ready to use. You can proceed to connect your WhatsApp account." }) }) : /* @__PURE__ */ jsxs(NotInstalledCard, { children: [
|
|
7581
|
+
/* @__PURE__ */ jsx(Typography, { variant: "beta", fontWeight: "bold", style: { display: "block", marginBottom: "12px", color: colors.danger }, children: "[WARNING] Dependencies Not Installed" }),
|
|
7582
|
+
/* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral600", style: { display: "block", marginBottom: "16px" }, children: "The WhatsApp integration requires additional dependencies. Please install them:" }),
|
|
7583
|
+
/* @__PURE__ */ jsx(
|
|
7584
|
+
Box,
|
|
7585
|
+
{
|
|
7586
|
+
padding: 4,
|
|
7587
|
+
background: "neutral0",
|
|
7588
|
+
hasRadius: true,
|
|
7589
|
+
style: {
|
|
7590
|
+
fontFamily: "monospace",
|
|
7591
|
+
fontSize: "14px",
|
|
7592
|
+
border: `1px solid ${colors.border}`,
|
|
7593
|
+
marginBottom: "16px"
|
|
7594
|
+
},
|
|
7595
|
+
children: "npm install @whiskeysockets/baileys pino qrcode"
|
|
7596
|
+
}
|
|
7597
|
+
),
|
|
7598
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: "After installing, restart your Strapi server and refresh this page." })
|
|
7599
|
+
] }),
|
|
7600
|
+
/* @__PURE__ */ jsxs(ButtonRow, { justifyContent: "flex-end", children: [
|
|
7601
|
+
/* @__PURE__ */ jsx(
|
|
7602
|
+
Button,
|
|
7603
|
+
{
|
|
7604
|
+
onClick: () => {
|
|
7605
|
+
checkAvailability();
|
|
7606
|
+
},
|
|
7607
|
+
variant: "secondary",
|
|
7608
|
+
startIcon: /* @__PURE__ */ jsx(ArrowClockwise, {}),
|
|
7609
|
+
style: { marginRight: "12px" },
|
|
7610
|
+
children: "Refresh"
|
|
7611
|
+
}
|
|
7612
|
+
),
|
|
7613
|
+
/* @__PURE__ */ jsx(
|
|
7614
|
+
Button,
|
|
7615
|
+
{
|
|
7616
|
+
onClick: () => setCurrentStep(2),
|
|
7617
|
+
disabled: !isAvailable,
|
|
7618
|
+
endIcon: /* @__PURE__ */ jsx(ArrowRight, {}),
|
|
7619
|
+
children: "Continue"
|
|
7620
|
+
}
|
|
7621
|
+
)
|
|
7622
|
+
] })
|
|
7623
|
+
] }),
|
|
7624
|
+
currentStep === 2 && /* @__PURE__ */ jsxs(ContentCard, { children: [
|
|
7625
|
+
/* @__PURE__ */ jsx(Typography, { variant: "beta", fontWeight: "bold", style: { display: "block", marginBottom: "8px" }, children: "Connect Your WhatsApp" }),
|
|
7626
|
+
/* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral600", style: { display: "block", marginBottom: "24px" }, children: "Click the button below to start the connection process. A QR code will be generated for you to scan." }),
|
|
7627
|
+
/* @__PURE__ */ jsxs(InfoBox, { children: [
|
|
7628
|
+
/* @__PURE__ */ jsx(Typography, { variant: "delta", fontWeight: "bold", style: { display: "block", marginBottom: "12px" }, children: "How it works" }),
|
|
7629
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
|
|
7630
|
+
/* @__PURE__ */ jsx(Typography, { variant: "omega", children: '1. Click "Connect WhatsApp" to generate a QR code' }),
|
|
7631
|
+
/* @__PURE__ */ jsx(Typography, { variant: "omega", children: "2. Open WhatsApp on your phone" }),
|
|
7632
|
+
/* @__PURE__ */ jsx(Typography, { variant: "omega", children: "3. Go to Settings - Linked Devices - Link a Device" }),
|
|
7633
|
+
/* @__PURE__ */ jsx(Typography, { variant: "omega", children: "4. Scan the QR code with your phone" })
|
|
7634
|
+
] })
|
|
7635
|
+
] }),
|
|
7636
|
+
/* @__PURE__ */ jsx(Alert, { variant: "default", title: "Session Persistence", style: { marginTop: "16px" }, children: /* @__PURE__ */ jsx(Typography, { variant: "pi", children: "Your WhatsApp session will be saved. You won't need to scan the QR code again unless you manually disconnect or your session expires." }) }),
|
|
7637
|
+
/* @__PURE__ */ jsxs(ButtonRow, { justifyContent: "space-between", children: [
|
|
7638
|
+
/* @__PURE__ */ jsx(
|
|
7639
|
+
Button,
|
|
7640
|
+
{
|
|
7641
|
+
onClick: () => setCurrentStep(1),
|
|
7642
|
+
variant: "tertiary",
|
|
7643
|
+
startIcon: /* @__PURE__ */ jsx(ArrowLeft, {}),
|
|
7644
|
+
children: "Back"
|
|
7645
|
+
}
|
|
7646
|
+
),
|
|
7647
|
+
/* @__PURE__ */ jsx(
|
|
7648
|
+
Button,
|
|
7649
|
+
{
|
|
7650
|
+
onClick: handleConnect,
|
|
7651
|
+
loading: connecting,
|
|
7652
|
+
style: { background: colors.whatsapp },
|
|
7653
|
+
startIcon: /* @__PURE__ */ jsx(Play, {}),
|
|
7654
|
+
children: "Connect WhatsApp"
|
|
7655
|
+
}
|
|
7656
|
+
)
|
|
7657
|
+
] })
|
|
7658
|
+
] }),
|
|
7659
|
+
currentStep === 3 && /* @__PURE__ */ jsxs(ContentCard, { children: [
|
|
7660
|
+
/* @__PURE__ */ jsx(Typography, { variant: "beta", fontWeight: "bold", style: { display: "block", marginBottom: "8px" }, children: "Scan QR Code" }),
|
|
7661
|
+
/* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral600", style: { display: "block", marginBottom: "24px" }, children: "Open WhatsApp on your phone and scan this QR code to connect." }),
|
|
7662
|
+
/* @__PURE__ */ jsx(QRCodeContainer, { children: status.qrCode ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7663
|
+
/* @__PURE__ */ jsx(QRImage, { src: status.qrCode, alt: "WhatsApp QR Code" }),
|
|
7664
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", style: { marginTop: "16px" }, children: 'QR code expires in 60 seconds. If it expires, click "Refresh QR".' })
|
|
7665
|
+
] }) : /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "center", gap: 3, children: [
|
|
7666
|
+
/* @__PURE__ */ jsx(SpinningLoader, { style: { width: "40px", height: "40px" } }),
|
|
7667
|
+
/* @__PURE__ */ jsx(Typography, { variant: "omega", children: "Generating QR code..." })
|
|
7668
|
+
] }) }),
|
|
7669
|
+
/* @__PURE__ */ jsxs(Alert, { variant: "default", title: "Instructions", children: [
|
|
7670
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", children: "1. Open WhatsApp on your phone" }),
|
|
7671
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", children: "2. Tap Menu or Settings" }),
|
|
7672
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", children: '3. Select "Linked Devices"' }),
|
|
7673
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", children: '4. Tap "Link a Device"' }),
|
|
7674
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", children: "5. Point your phone camera at this QR code" })
|
|
7675
|
+
] }),
|
|
7676
|
+
/* @__PURE__ */ jsxs(ButtonRow, { justifyContent: "space-between", children: [
|
|
7677
|
+
/* @__PURE__ */ jsx(
|
|
7678
|
+
Button,
|
|
7679
|
+
{
|
|
7680
|
+
onClick: () => setCurrentStep(2),
|
|
7681
|
+
variant: "tertiary",
|
|
7682
|
+
startIcon: /* @__PURE__ */ jsx(ArrowLeft, {}),
|
|
7683
|
+
children: "Back"
|
|
7684
|
+
}
|
|
7685
|
+
),
|
|
7686
|
+
/* @__PURE__ */ jsx(
|
|
7687
|
+
Button,
|
|
7688
|
+
{
|
|
7689
|
+
onClick: handleConnect,
|
|
7690
|
+
variant: "secondary",
|
|
7691
|
+
startIcon: /* @__PURE__ */ jsx(ArrowClockwise, {}),
|
|
7692
|
+
children: "Refresh QR"
|
|
7693
|
+
}
|
|
7694
|
+
)
|
|
7695
|
+
] })
|
|
7696
|
+
] }),
|
|
7697
|
+
currentStep === 4 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7698
|
+
/* @__PURE__ */ jsxs(ConnectedCard, { children: [
|
|
7699
|
+
/* @__PURE__ */ jsx(Box, { marginBottom: 4, children: /* @__PURE__ */ jsx(Check, { style: { width: "48px", height: "48px", color: colors.success } }) }),
|
|
7700
|
+
/* @__PURE__ */ jsx(Typography, { variant: "alpha", fontWeight: "bold", style: { display: "block", marginBottom: "8px" }, children: "WhatsApp Connected" }),
|
|
7701
|
+
status.session && /* @__PURE__ */ jsxs(Typography, { variant: "omega", textColor: "neutral600", style: { display: "block" }, children: [
|
|
7702
|
+
"Connected as: ",
|
|
7703
|
+
status.session.phoneNumber,
|
|
7704
|
+
" ",
|
|
7705
|
+
status.session.name && `(${status.session.name})`
|
|
7706
|
+
] })
|
|
7707
|
+
] }),
|
|
7708
|
+
/* @__PURE__ */ jsxs(ContentCard, { style: { marginTop: "24px" }, children: [
|
|
7709
|
+
/* @__PURE__ */ jsx(Typography, { variant: "beta", fontWeight: "bold", style: { display: "block", marginBottom: "8px" }, children: "Send Test Message" }),
|
|
7710
|
+
/* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral600", style: { display: "block", marginBottom: "24px" }, children: "Test your WhatsApp connection by sending a message." }),
|
|
7711
|
+
/* @__PURE__ */ jsx(TestSection, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 4, children: [
|
|
7712
|
+
/* @__PURE__ */ jsxs(Field.Root, { children: [
|
|
7713
|
+
/* @__PURE__ */ jsx(Field.Label, { children: "Phone Number" }),
|
|
7714
|
+
/* @__PURE__ */ jsx(
|
|
7715
|
+
TextInput,
|
|
7716
|
+
{
|
|
7717
|
+
placeholder: "49123456789 (with country code, no +)",
|
|
7718
|
+
value: testPhone,
|
|
7719
|
+
onChange: (e) => setTestPhone(e.target.value)
|
|
7720
|
+
}
|
|
7721
|
+
),
|
|
7722
|
+
/* @__PURE__ */ jsx(Field.Hint, { children: "Enter phone number with country code (e.g., 49 for Germany)" })
|
|
7723
|
+
] }),
|
|
7724
|
+
/* @__PURE__ */ jsxs(Field.Root, { children: [
|
|
7725
|
+
/* @__PURE__ */ jsx(Field.Label, { children: "Message (optional)" }),
|
|
7726
|
+
/* @__PURE__ */ jsx(
|
|
7727
|
+
TextInput,
|
|
7728
|
+
{
|
|
7729
|
+
placeholder: "Leave empty for default test message",
|
|
7730
|
+
value: testMessage,
|
|
7731
|
+
onChange: (e) => setTestMessage(e.target.value)
|
|
7732
|
+
}
|
|
7733
|
+
)
|
|
7734
|
+
] }),
|
|
7735
|
+
/* @__PURE__ */ jsx(
|
|
7736
|
+
Button,
|
|
7737
|
+
{
|
|
7738
|
+
onClick: handleSendTest,
|
|
7739
|
+
loading: sendingTest,
|
|
7740
|
+
style: { background: colors.whatsapp },
|
|
7741
|
+
children: "Send Test Message"
|
|
7742
|
+
}
|
|
7743
|
+
)
|
|
7744
|
+
] }) }),
|
|
7745
|
+
/* @__PURE__ */ jsx(Divider, { style: { margin: "24px 0" } }),
|
|
7746
|
+
/* @__PURE__ */ jsx(Typography, { variant: "beta", fontWeight: "bold", style: { display: "block", marginBottom: "8px" }, children: "Using WhatsApp in Your Code" }),
|
|
7747
|
+
/* @__PURE__ */ jsx(Typography, { variant: "omega", textColor: "neutral600", style: { display: "block", marginBottom: "16px" }, children: "Use the WhatsApp service programmatically in your Strapi code." }),
|
|
7748
|
+
/* @__PURE__ */ jsx(
|
|
7749
|
+
Box,
|
|
7750
|
+
{
|
|
7751
|
+
padding: 4,
|
|
7752
|
+
background: "neutral100",
|
|
7753
|
+
hasRadius: true,
|
|
7754
|
+
style: {
|
|
7755
|
+
fontFamily: "monospace",
|
|
7756
|
+
fontSize: "13px",
|
|
7757
|
+
lineHeight: "1.6",
|
|
7758
|
+
overflow: "auto"
|
|
7759
|
+
},
|
|
7760
|
+
children: /* @__PURE__ */ jsx("pre", { style: { margin: 0 }, children: `// Send a message via WhatsApp
|
|
7761
|
+
const whatsapp = strapi.plugin('magic-mail').service('whatsapp');
|
|
7762
|
+
|
|
7763
|
+
// Send simple message
|
|
7764
|
+
await whatsapp.sendMessage('49123456789', 'Hello from MagicMail!');
|
|
7765
|
+
|
|
7766
|
+
// Send template message
|
|
7767
|
+
await whatsapp.sendTemplateMessage('49123456789', 'welcome', {
|
|
7768
|
+
name: 'John',
|
|
7769
|
+
company: 'ACME Corp',
|
|
7770
|
+
});` })
|
|
7771
|
+
}
|
|
7772
|
+
),
|
|
7773
|
+
/* @__PURE__ */ jsxs(ButtonRow, { justifyContent: "space-between", children: [
|
|
7774
|
+
/* @__PURE__ */ jsx(
|
|
7775
|
+
Button,
|
|
7776
|
+
{
|
|
7777
|
+
onClick: handleDisconnect,
|
|
7778
|
+
variant: "danger",
|
|
7779
|
+
startIcon: /* @__PURE__ */ jsx(Cross, {}),
|
|
7780
|
+
children: "Disconnect WhatsApp"
|
|
7781
|
+
}
|
|
7782
|
+
),
|
|
7783
|
+
/* @__PURE__ */ jsx(Badge, { backgroundColor: "success600", textColor: "neutral0", children: "FREE - No API costs!" })
|
|
7784
|
+
] })
|
|
7785
|
+
] })
|
|
7786
|
+
] })
|
|
7787
|
+
] });
|
|
7788
|
+
};
|
|
7080
7789
|
const fadeIn = keyframes`
|
|
7081
7790
|
from { opacity: 0; }
|
|
7082
7791
|
to { opacity: 1; }
|
|
@@ -7500,6 +8209,7 @@ const App = () => {
|
|
|
7500
8209
|
if (location.pathname.includes("/analytics")) return "analytics";
|
|
7501
8210
|
if (location.pathname.includes("/routing")) return "routing";
|
|
7502
8211
|
if (location.pathname.includes("/designer") && !isEditorRoute) return "templates";
|
|
8212
|
+
if (location.pathname.includes("/whatsapp")) return "whatsapp";
|
|
7503
8213
|
return "accounts";
|
|
7504
8214
|
};
|
|
7505
8215
|
const [activeTab, setActiveTab] = useState(getActiveTab());
|
|
@@ -7509,6 +8219,7 @@ const App = () => {
|
|
|
7509
8219
|
if (tab === "routing") navigate("/plugins/magic-mail/routing");
|
|
7510
8220
|
if (tab === "templates") navigate("/plugins/magic-mail/designer");
|
|
7511
8221
|
if (tab === "analytics") navigate("/plugins/magic-mail/analytics");
|
|
8222
|
+
if (tab === "whatsapp") navigate("/plugins/magic-mail/whatsapp");
|
|
7512
8223
|
};
|
|
7513
8224
|
if (isEditorRoute) {
|
|
7514
8225
|
return /* @__PURE__ */ jsx(LicenseGuard, { children: /* @__PURE__ */ jsx(EditorPage, {}) });
|
|
@@ -7530,12 +8241,17 @@ const App = () => {
|
|
|
7530
8241
|
hasAnalytics && /* @__PURE__ */ jsx(Tabs.Trigger, { value: "analytics", children: /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
|
|
7531
8242
|
/* @__PURE__ */ jsx(ChartBarIcon, { style: { width: 16, height: 16 } }),
|
|
7532
8243
|
"Analytics"
|
|
8244
|
+
] }) }),
|
|
8245
|
+
/* @__PURE__ */ jsx(Tabs.Trigger, { value: "whatsapp", children: /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
|
|
8246
|
+
/* @__PURE__ */ jsx(ChatBubbleLeftIcon, { style: { width: 16, height: 16 } }),
|
|
8247
|
+
"WhatsApp"
|
|
7533
8248
|
] }) })
|
|
7534
8249
|
] }),
|
|
7535
8250
|
/* @__PURE__ */ jsx(Tabs.Content, { value: "accounts", children: /* @__PURE__ */ jsx(HomePage, {}) }),
|
|
7536
8251
|
/* @__PURE__ */ jsx(Tabs.Content, { value: "routing", children: /* @__PURE__ */ jsx(RoutingRulesPage, {}) }),
|
|
7537
8252
|
hasEmailDesigner && /* @__PURE__ */ jsx(Tabs.Content, { value: "templates", children: /* @__PURE__ */ jsx(TemplateList, {}) }),
|
|
7538
|
-
hasAnalytics && /* @__PURE__ */ jsx(Tabs.Content, { value: "analytics", children: /* @__PURE__ */ jsx(Analytics, {}) })
|
|
8253
|
+
hasAnalytics && /* @__PURE__ */ jsx(Tabs.Content, { value: "analytics", children: /* @__PURE__ */ jsx(Analytics, {}) }),
|
|
8254
|
+
/* @__PURE__ */ jsx(Tabs.Content, { value: "whatsapp", children: /* @__PURE__ */ jsx(WhatsAppPage, {}) })
|
|
7539
8255
|
] }) }) });
|
|
7540
8256
|
};
|
|
7541
8257
|
export {
|