@inspirer-dev/crm-dashboard 1.0.86 → 1.0.89

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.
@@ -93,7 +93,6 @@ export const EDGE_COLORS = {
93
93
  },
94
94
  };
95
95
 
96
-
97
96
  export const STEP_TYPE_LABELS: Record<StepType, string> = {
98
97
  entry: 'Entry Point',
99
98
  message: 'Send Message',
@@ -105,6 +104,7 @@ export const STEP_TYPE_LABELS: Record<StepType, string> = {
105
104
 
106
105
  export const CHANNEL_OPTIONS: { value: ChannelType; label: string }[] = [
107
106
  { value: 'telegram', label: 'Telegram' },
107
+ { value: 'whatsapp', label: 'WhatsApp' },
108
108
  { value: 'email', label: 'Email' },
109
109
  { value: 'push', label: 'Push Notification' },
110
110
  { value: 'sms', label: 'SMS' },
@@ -164,4 +164,3 @@ export const ENTRY_NODE_ID = 'entry';
164
164
  export const PROXIMITY_THRESHOLD = 350;
165
165
 
166
166
  export const AUTO_DISCONNECT_ENABLED = false;
167
-
@@ -26,6 +26,8 @@ const ANALYTICS_EVENTS: Record<string, { value: string; label: string }[]> = {
26
26
  { value: 'battle', label: 'Battle Completed' },
27
27
  { value: 'contract', label: 'Contract Completed' },
28
28
  { value: 'withdrawal', label: 'Withdrawal Completed' },
29
+ { value: 'deposit_abandoned', label: 'Deposit Abandoned' },
30
+ { value: 'balance_low', label: 'Balance Low' },
29
31
  ],
30
32
  Case: [
31
33
  { value: 'gg-case-fav', label: 'Case Favorite' },
@@ -43,12 +45,8 @@ const ANALYTICS_EVENTS: Record<string, { value: string; label: string }[]> = {
43
45
  { value: 'gg-profile-skin-sell', label: 'Profile Skin Sell' },
44
46
  { value: 'gg-profile-skin-trade', label: 'Profile Skin Trade' },
45
47
  ],
46
- Upgrade: [
47
- { value: 'gg-upgrade-launch', label: 'Upgrade Launch' },
48
- ],
49
- Contract: [
50
- { value: 'gg-contract-create', label: 'Contract Create' },
51
- ],
48
+ Upgrade: [{ value: 'gg-upgrade-launch', label: 'Upgrade Launch' }],
49
+ Contract: [{ value: 'gg-contract-create', label: 'Contract Create' }],
52
50
  Deposit: [
53
51
  { value: 'gg-deposit-deppage-refill', label: 'Deposit Page Refill' },
54
52
  { value: 'gg-depositbait-banner-herodepbonus-click', label: 'Hero Deposit Bonus Banner' },
@@ -260,11 +258,7 @@ const EventTriggerConfig: React.FC<EventTriggerConfigProps> = ({ data, onUpdate,
260
258
  }}
261
259
  >
262
260
  <Flex direction="column" gap={1}>
263
- <Typography
264
- variant="omega"
265
- fontWeight="semiBold"
266
- style={{ color: theme.text }}
267
- >
261
+ <Typography variant="omega" fontWeight="semiBold" style={{ color: theme.text }}>
268
262
  {getEventLabel(eventValue)}
269
263
  </Typography>
270
264
  <Typography variant="pi" textColor="neutral500">
@@ -389,11 +383,7 @@ const EventTriggerConfig: React.FC<EventTriggerConfigProps> = ({ data, onUpdate,
389
383
  </SingleSelect>
390
384
  </Box>
391
385
  </Flex>
392
- <Typography
393
- variant="pi"
394
- textColor="neutral500"
395
- style={{ marginTop: 8, display: 'block' }}
396
- >
386
+ <Typography variant="pi" textColor="neutral500" style={{ marginTop: 8, display: 'block' }}>
397
387
  {timeout > 0
398
388
  ? `Если событие не произойдёт за ${timeout} ${timeoutUnit}, кампания продолжится автоматически`
399
389
  : 'Установите 0 для бесконечного ожидания события'}
@@ -422,8 +412,8 @@ const EventTriggerConfig: React.FC<EventTriggerConfigProps> = ({ data, onUpdate,
422
412
  <>
423
413
  {logic === 'or' ? (
424
414
  <>
425
- Кампания продолжится, когда пользователь выполнит{' '}
426
- <strong>любое</strong> из выбранных событий
415
+ Кампания продолжится, когда пользователь выполнит <strong>любое</strong> из
416
+ выбранных событий
427
417
  </>
428
418
  ) : (
429
419
  <>
@@ -433,7 +423,11 @@ const EventTriggerConfig: React.FC<EventTriggerConfigProps> = ({ data, onUpdate,
433
423
  )}
434
424
  {timeout > 0 && (
435
425
  <>
436
- {' '}или через <strong>{timeout} {timeoutUnit}</strong>
426
+ {' '}
427
+ или через{' '}
428
+ <strong>
429
+ {timeout} {timeoutUnit}
430
+ </strong>
437
431
  </>
438
432
  )}
439
433
  .
@@ -1,7 +1,7 @@
1
1
  import type { Node, Edge } from 'reactflow';
2
2
 
3
3
  export type StepType = 'entry' | 'message' | 'wait' | 'branch' | 'exit' | 'event_trigger';
4
- export type ChannelType = 'telegram' | 'email' | 'push' | 'sms';
4
+ export type ChannelType = 'telegram' | 'whatsapp' | 'email' | 'push' | 'sms';
5
5
  export type DurationUnit = 'seconds' | 'minutes' | 'hours' | 'days';
6
6
  export type EventTriggerLogic = 'and' | 'or';
7
7
 
@@ -67,7 +67,10 @@ export interface EventTriggerStepConfig {
67
67
  eventTrigger?: EventTriggerConfig;
68
68
  }
69
69
 
70
- export type StepConfig = MessageStepConfig & WaitStepConfig & BranchStepConfig & EventTriggerStepConfig;
70
+ export type StepConfig = MessageStepConfig &
71
+ WaitStepConfig &
72
+ BranchStepConfig &
73
+ EventTriggerStepConfig;
71
74
 
72
75
  export interface FlowNodeData {
73
76
  stepType: StepType;
@@ -3,6 +3,7 @@ import {
3
3
  Box,
4
4
  Field,
5
5
  Flex,
6
+ NumberInput,
6
7
  TextInput,
7
8
  Typography,
8
9
  SingleSelect,
@@ -25,6 +26,8 @@ const ANALYTICS_EVENTS: Record<string, { value: string; label: string }[]> = {
25
26
  { value: 'battle', label: 'Battle Completed' },
26
27
  { value: 'contract', label: 'Contract Completed' },
27
28
  { value: 'withdrawal', label: 'Withdrawal Completed' },
29
+ { value: 'deposit_abandoned', label: 'Deposit Abandoned' },
30
+ { value: 'balance_low', label: 'Balance Low' },
28
31
  ],
29
32
  Case: [
30
33
  { value: 'gg-case-fav', label: 'Case Favorite' },
@@ -121,6 +124,8 @@ interface TriggerConfig {
121
124
  scheduleDays?: number[];
122
125
  scheduleCron?: string;
123
126
  scheduleEveryMinutes?: number;
127
+ depositAbandonedTimeoutMinutes?: number;
128
+ balanceLowThreshold?: number;
124
129
  }
125
130
 
126
131
  interface TriggerConfigFieldProps {
@@ -206,6 +211,8 @@ const parseConfig = (value: string | TriggerConfig | null | undefined): TriggerC
206
211
  scheduleDays: Array.isArray(parsed.scheduleDays) ? parsed.scheduleDays : [1, 2, 3, 4, 5],
207
212
  scheduleCron: parsed.scheduleCron || '0 12 * * *',
208
213
  scheduleEveryMinutes: parsed.scheduleEveryMinutes ?? 5,
214
+ depositAbandonedTimeoutMinutes: parsed.depositAbandonedTimeoutMinutes ?? 10,
215
+ balanceLowThreshold: parsed.balanceLowThreshold ?? 5,
209
216
  });
210
217
  if (typeof value === 'string') {
211
218
  try {
@@ -566,6 +573,119 @@ const TriggerConfigField = forwardRef<HTMLDivElement, TriggerConfigFieldProps>(
566
573
  </Typography>
567
574
  </Box>
568
575
 
576
+ {config.eventName === 'deposit_abandoned' && (
577
+ <Box
578
+ padding={4}
579
+ hasRadius
580
+ style={{
581
+ background: colors.event.innerCard,
582
+ border: `1px solid ${colors.event.border}`,
583
+ }}
584
+ >
585
+ <Flex alignItems="center" gap={3}>
586
+ <Box
587
+ style={{
588
+ width: 40,
589
+ height: 40,
590
+ borderRadius: 10,
591
+ background: 'linear-gradient(135deg, #f97316 0%, #ea580c 100%)',
592
+ display: 'flex',
593
+ alignItems: 'center',
594
+ justifyContent: 'center',
595
+ color: '#fff',
596
+ flexShrink: 0,
597
+ }}
598
+ >
599
+ <Clock width={20} height={20} />
600
+ </Box>
601
+ <Box style={{ flex: 1 }}>
602
+ <Typography
603
+ variant="pi"
604
+ fontWeight="bold"
605
+ textColor="neutral700"
606
+ style={{ marginBottom: 4, display: 'block' }}
607
+ >
608
+ Таймаут незавершённого депозита
609
+ </Typography>
610
+ <Typography variant="pi" textColor="neutral500">
611
+ Через сколько минут считать депозит брошенным
612
+ </Typography>
613
+ </Box>
614
+ <Box style={{ width: 100 }}>
615
+ <NumberInput
616
+ value={config.depositAbandonedTimeoutMinutes ?? 10}
617
+ onValueChange={(val: number | undefined) =>
618
+ handleUpdate({ depositAbandonedTimeoutMinutes: val ?? 10 })
619
+ }
620
+ disabled={disabled}
621
+ step={1}
622
+ min={1}
623
+ max={60}
624
+ />
625
+ </Box>
626
+ <Typography variant="pi" textColor="neutral500">
627
+ мин
628
+ </Typography>
629
+ </Flex>
630
+ </Box>
631
+ )}
632
+
633
+ {config.eventName === 'balance_low' && (
634
+ <Box
635
+ padding={4}
636
+ hasRadius
637
+ style={{
638
+ background: colors.event.innerCard,
639
+ border: `1px solid ${colors.event.border}`,
640
+ }}
641
+ >
642
+ <Flex alignItems="center" gap={3}>
643
+ <Box
644
+ style={{
645
+ width: 40,
646
+ height: 40,
647
+ borderRadius: 10,
648
+ background: 'linear-gradient(135deg, #ef4444 0%, #dc2626 100%)',
649
+ display: 'flex',
650
+ alignItems: 'center',
651
+ justifyContent: 'center',
652
+ color: '#fff',
653
+ flexShrink: 0,
654
+ }}
655
+ >
656
+ <Clock width={20} height={20} />
657
+ </Box>
658
+ <Box style={{ flex: 1 }}>
659
+ <Typography
660
+ variant="pi"
661
+ fontWeight="bold"
662
+ textColor="neutral700"
663
+ style={{ marginBottom: 4, display: 'block' }}
664
+ >
665
+ Порог баланса
666
+ </Typography>
667
+ <Typography variant="pi" textColor="neutral500">
668
+ Событие сработает когда баланс упадёт ниже этой суммы
669
+ </Typography>
670
+ </Box>
671
+ <Box style={{ width: 100 }}>
672
+ <NumberInput
673
+ value={config.balanceLowThreshold ?? 5}
674
+ onValueChange={(val: number | undefined) =>
675
+ handleUpdate({ balanceLowThreshold: val ?? 5 })
676
+ }
677
+ disabled={disabled}
678
+ step={0.5}
679
+ min={0}
680
+ />
681
+ </Box>
682
+ <Typography variant="pi" textColor="neutral500">
683
+ $
684
+ </Typography>
685
+ </Flex>
686
+ </Box>
687
+ )}
688
+
569
689
  <Box
570
690
  padding={4}
571
691
  hasRadius
@@ -44,11 +44,12 @@ export interface CrmTemplate {
44
44
  id: number;
45
45
  documentId: string;
46
46
  name: string;
47
- channel: 'telegram' | 'email' | 'push' | 'sms';
47
+ channel: 'telegram' | 'whatsapp' | 'email' | 'push' | 'sms';
48
48
  locale?: string;
49
49
  title?: string;
50
50
  body: string;
51
51
  buttons?: TelegramButton[];
52
+ whatsappTemplateName?: string;
52
53
  }
53
54
 
54
55
  export interface CrmVariant {
@@ -98,7 +99,7 @@ export interface CampaignStep {
98
99
  name: string;
99
100
  stepType: 'message' | 'wait' | 'branch' | 'exit';
100
101
  order: number;
101
- channel?: 'telegram' | 'email' | 'push' | 'sms';
102
+ channel?: 'telegram' | 'whatsapp' | 'email' | 'push' | 'sms';
102
103
  variants?: CrmVariant[];
103
104
  duration?: number;
104
105
  durationUnit?: 'minutes' | 'hours' | 'days';
@@ -156,7 +157,7 @@ export type JourneyNodeType = 'entrance' | 'message' | 'wait' | 'branch' | 'exit
156
157
  export type JourneyBranchType = 'default' | 'yes' | 'no';
157
158
  export type JourneyWaitType = 'duration' | 'until_event' | 'until_time';
158
159
  export type JourneyConditionType = 'segment' | 'event_attribute' | 'random_split';
159
- export type JourneyChannel = 'telegram' | 'email' | 'push' | 'sms';
160
+ export type JourneyChannel = 'telegram' | 'whatsapp' | 'email' | 'push' | 'sms';
160
161
 
161
162
  export interface JourneyMessageVariant {
162
163
  name: string;
@@ -100,6 +100,7 @@ const STEP_TYPE_LABELS = {
100
100
  };
101
101
  const CHANNEL_OPTIONS = [
102
102
  { value: "telegram", label: "Telegram" },
103
+ { value: "whatsapp", label: "WhatsApp" },
103
104
  { value: "email", label: "Email" },
104
105
  { value: "push", label: "Push Notification" },
105
106
  { value: "sms", label: "SMS" }
@@ -2365,7 +2366,9 @@ const ANALYTICS_EVENTS = {
2365
2366
  { value: "upgrade", label: "Upgrade Completed" },
2366
2367
  { value: "battle", label: "Battle Completed" },
2367
2368
  { value: "contract", label: "Contract Completed" },
2368
- { value: "withdrawal", label: "Withdrawal Completed" }
2369
+ { value: "withdrawal", label: "Withdrawal Completed" },
2370
+ { value: "deposit_abandoned", label: "Deposit Abandoned" },
2371
+ { value: "balance_low", label: "Balance Low" }
2369
2372
  ],
2370
2373
  Case: [
2371
2374
  { value: "gg-case-fav", label: "Case Favorite" },
@@ -2383,12 +2386,8 @@ const ANALYTICS_EVENTS = {
2383
2386
  { value: "gg-profile-skin-sell", label: "Profile Skin Sell" },
2384
2387
  { value: "gg-profile-skin-trade", label: "Profile Skin Trade" }
2385
2388
  ],
2386
- Upgrade: [
2387
- { value: "gg-upgrade-launch", label: "Upgrade Launch" }
2388
- ],
2389
- Contract: [
2390
- { value: "gg-contract-create", label: "Contract Create" }
2391
- ],
2389
+ Upgrade: [{ value: "gg-upgrade-launch", label: "Upgrade Launch" }],
2390
+ Contract: [{ value: "gg-contract-create", label: "Contract Create" }],
2392
2391
  Deposit: [
2393
2392
  { value: "gg-deposit-deppage-refill", label: "Deposit Page Refill" },
2394
2393
  { value: "gg-depositbait-banner-herodepbonus-click", label: "Hero Deposit Bonus Banner" }
@@ -2571,15 +2570,7 @@ const EventTriggerConfig = ({ data, onUpdate, disabled }) => {
2571
2570
  },
2572
2571
  children: [
2573
2572
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 1, children: [
2574
- /* @__PURE__ */ jsxRuntime.jsx(
2575
- designSystem.Typography,
2576
- {
2577
- variant: "omega",
2578
- fontWeight: "semiBold",
2579
- style: { color: theme.text },
2580
- children: getEventLabel(eventValue)
2581
- }
2582
- ),
2573
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", style: { color: theme.text }, children: getEventLabel(eventValue) }),
2583
2574
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: eventValue })
2584
2575
  ] }),
2585
2576
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -2698,15 +2689,7 @@ const EventTriggerConfig = ({ data, onUpdate, disabled }) => {
2698
2689
  }
2699
2690
  ) })
2700
2691
  ] }),
2701
- /* @__PURE__ */ jsxRuntime.jsx(
2702
- designSystem.Typography,
2703
- {
2704
- variant: "pi",
2705
- textColor: "neutral500",
2706
- style: { marginTop: 8, display: "block" },
2707
- children: timeout > 0 ? `Если событие не произойдёт за ${timeout} ${timeoutUnit}, кампания продолжится автоматически` : "Установите 0 для бесконечного ожидания события"
2708
- }
2709
- )
2692
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", style: { marginTop: 8, display: "block" }, children: timeout > 0 ? `Если событие не произойдёт за ${timeout} ${timeoutUnit}, кампания продолжится автоматически` : "Установите 0 для бесконечного ожидания события" })
2710
2693
  ] }),
2711
2694
  /* @__PURE__ */ jsxRuntime.jsx(
2712
2695
  "div",
@@ -2728,8 +2711,7 @@ const EventTriggerConfig = ({ data, onUpdate, disabled }) => {
2728
2711
  },
2729
2712
  children: events.length === 0 ? "Выберите события, которые должен совершить пользователь для продолжения кампании." : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2730
2713
  logic === "or" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2731
- "Кампания продолжится, когда пользователь выполнит",
2732
- " ",
2714
+ "Кампания продолжится, когда пользователь выполнит ",
2733
2715
  /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "любое" }),
2734
2716
  " из выбранных событий"
2735
2717
  ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -2743,7 +2725,8 @@ const EventTriggerConfig = ({ data, onUpdate, disabled }) => {
2743
2725
  ] }),
2744
2726
  timeout > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2745
2727
  " ",
2746
- "или через ",
2728
+ "или через",
2729
+ " ",
2747
2730
  /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
2748
2731
  timeout,
2749
2732
  " ",
@@ -15,7 +15,9 @@ const ANALYTICS_EVENTS = {
15
15
  { value: "upgrade", label: "Upgrade Completed" },
16
16
  { value: "battle", label: "Battle Completed" },
17
17
  { value: "contract", label: "Contract Completed" },
18
- { value: "withdrawal", label: "Withdrawal Completed" }
18
+ { value: "withdrawal", label: "Withdrawal Completed" },
19
+ { value: "deposit_abandoned", label: "Deposit Abandoned" },
20
+ { value: "balance_low", label: "Balance Low" }
19
21
  ],
20
22
  Case: [
21
23
  { value: "gg-case-fav", label: "Case Favorite" },
@@ -154,7 +156,9 @@ const parseConfig = (value) => {
154
156
  scheduleTime: parsed.scheduleTime || "12:00",
155
157
  scheduleDays: Array.isArray(parsed.scheduleDays) ? parsed.scheduleDays : [1, 2, 3, 4, 5],
156
158
  scheduleCron: parsed.scheduleCron || "0 12 * * *",
157
- scheduleEveryMinutes: parsed.scheduleEveryMinutes ?? 5
159
+ scheduleEveryMinutes: parsed.scheduleEveryMinutes ?? 5,
160
+ depositAbandonedTimeoutMinutes: parsed.depositAbandonedTimeoutMinutes ?? 10,
161
+ balanceLowThreshold: parsed.balanceLowThreshold ?? 5
158
162
  });
159
163
  if (typeof value === "string") {
160
164
  try {
@@ -465,6 +469,115 @@ const TriggerConfigField = React.forwardRef(
465
469
  }
466
470
  )
467
471
  ] }),
472
+ config.eventName === "deposit_abandoned" && /* @__PURE__ */ jsxRuntime.jsx(
473
+ designSystem.Box,
474
+ {
475
+ padding: 4,
476
+ hasRadius: true,
477
+ style: {
478
+ background: colors.event.innerCard,
479
+ border: `1px solid ${colors.event.border}`
480
+ },
481
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "center", gap: 3, children: [
482
+ /* @__PURE__ */ jsxRuntime.jsx(
483
+ designSystem.Box,
484
+ {
485
+ style: {
486
+ width: 40,
487
+ height: 40,
488
+ borderRadius: 10,
489
+ background: "linear-gradient(135deg, #f97316 0%, #ea580c 100%)",
490
+ display: "flex",
491
+ alignItems: "center",
492
+ justifyContent: "center",
493
+ color: "#fff",
494
+ flexShrink: 0
495
+ },
496
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.Clock, { width: 20, height: 20 })
497
+ }
498
+ ),
499
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: 1 }, children: [
500
+ /* @__PURE__ */ jsxRuntime.jsx(
501
+ designSystem.Typography,
502
+ {
503
+ variant: "pi",
504
+ fontWeight: "bold",
505
+ textColor: "neutral700",
506
+ style: { marginBottom: 4, display: "block" },
507
+ children: "Таймаут незавершённого депозита"
508
+ }
509
+ ),
510
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: "Через сколько минут считать депозит брошенным" })
511
+ ] }),
512
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width: 100 }, children: /* @__PURE__ */ jsxRuntime.jsx(
513
+ designSystem.NumberInput,
514
+ {
515
+ value: config.depositAbandonedTimeoutMinutes ?? 10,
516
+ onValueChange: (val) => handleUpdate({ depositAbandonedTimeoutMinutes: val ?? 10 }),
517
+ disabled,
518
+ step: 1,
519
+ min: 1,
520
+ max: 60
521
+ }
522
+ ) }),
523
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: "мин" })
524
+ ] })
525
+ }
526
+ ),
527
+ config.eventName === "balance_low" && /* @__PURE__ */ jsxRuntime.jsx(
528
+ designSystem.Box,
529
+ {
530
+ padding: 4,
531
+ hasRadius: true,
532
+ style: {
533
+ background: colors.event.innerCard,
534
+ border: `1px solid ${colors.event.border}`
535
+ },
536
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "center", gap: 3, children: [
537
+ /* @__PURE__ */ jsxRuntime.jsx(
538
+ designSystem.Box,
539
+ {
540
+ style: {
541
+ width: 40,
542
+ height: 40,
543
+ borderRadius: 10,
544
+ background: "linear-gradient(135deg, #ef4444 0%, #dc2626 100%)",
545
+ display: "flex",
546
+ alignItems: "center",
547
+ justifyContent: "center",
548
+ color: "#fff",
549
+ flexShrink: 0
550
+ },
551
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.Clock, { width: 20, height: 20 })
552
+ }
553
+ ),
554
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: 1 }, children: [
555
+ /* @__PURE__ */ jsxRuntime.jsx(
556
+ designSystem.Typography,
557
+ {
558
+ variant: "pi",
559
+ fontWeight: "bold",
560
+ textColor: "neutral700",
561
+ style: { marginBottom: 4, display: "block" },
562
+ children: "Порог баланса"
563
+ }
564
+ ),
565
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: "Событие сработает когда баланс упадёт ниже этой суммы" })
566
+ ] }),
567
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { width: 100 }, children: /* @__PURE__ */ jsxRuntime.jsx(
568
+ designSystem.NumberInput,
569
+ {
570
+ value: config.balanceLowThreshold ?? 5,
571
+ onValueChange: (val) => handleUpdate({ balanceLowThreshold: val ?? 5 }),
572
+ disabled,
573
+ step: 0.5,
574
+ min: 0
575
+ }
576
+ ) }),
577
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral500", children: "$" })
578
+ ] })
579
+ }
580
+ ),
468
581
  /* @__PURE__ */ jsxRuntime.jsx(
469
582
  designSystem.Box,
470
583
  {
@@ -95,6 +95,7 @@ const STEP_TYPE_LABELS = {
95
95
  };
96
96
  const CHANNEL_OPTIONS = [
97
97
  { value: "telegram", label: "Telegram" },
98
+ { value: "whatsapp", label: "WhatsApp" },
98
99
  { value: "email", label: "Email" },
99
100
  { value: "push", label: "Push Notification" },
100
101
  { value: "sms", label: "SMS" }
@@ -2360,7 +2361,9 @@ const ANALYTICS_EVENTS = {
2360
2361
  { value: "upgrade", label: "Upgrade Completed" },
2361
2362
  { value: "battle", label: "Battle Completed" },
2362
2363
  { value: "contract", label: "Contract Completed" },
2363
- { value: "withdrawal", label: "Withdrawal Completed" }
2364
+ { value: "withdrawal", label: "Withdrawal Completed" },
2365
+ { value: "deposit_abandoned", label: "Deposit Abandoned" },
2366
+ { value: "balance_low", label: "Balance Low" }
2364
2367
  ],
2365
2368
  Case: [
2366
2369
  { value: "gg-case-fav", label: "Case Favorite" },
@@ -2378,12 +2381,8 @@ const ANALYTICS_EVENTS = {
2378
2381
  { value: "gg-profile-skin-sell", label: "Profile Skin Sell" },
2379
2382
  { value: "gg-profile-skin-trade", label: "Profile Skin Trade" }
2380
2383
  ],
2381
- Upgrade: [
2382
- { value: "gg-upgrade-launch", label: "Upgrade Launch" }
2383
- ],
2384
- Contract: [
2385
- { value: "gg-contract-create", label: "Contract Create" }
2386
- ],
2384
+ Upgrade: [{ value: "gg-upgrade-launch", label: "Upgrade Launch" }],
2385
+ Contract: [{ value: "gg-contract-create", label: "Contract Create" }],
2387
2386
  Deposit: [
2388
2387
  { value: "gg-deposit-deppage-refill", label: "Deposit Page Refill" },
2389
2388
  { value: "gg-depositbait-banner-herodepbonus-click", label: "Hero Deposit Bonus Banner" }
@@ -2566,15 +2565,7 @@ const EventTriggerConfig = ({ data, onUpdate, disabled }) => {
2566
2565
  },
2567
2566
  children: [
2568
2567
  /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 1, children: [
2569
- /* @__PURE__ */ jsx(
2570
- Typography,
2571
- {
2572
- variant: "omega",
2573
- fontWeight: "semiBold",
2574
- style: { color: theme.text },
2575
- children: getEventLabel(eventValue)
2576
- }
2577
- ),
2568
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", fontWeight: "semiBold", style: { color: theme.text }, children: getEventLabel(eventValue) }),
2578
2569
  /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", children: eventValue })
2579
2570
  ] }),
2580
2571
  /* @__PURE__ */ jsx(
@@ -2693,15 +2684,7 @@ const EventTriggerConfig = ({ data, onUpdate, disabled }) => {
2693
2684
  }
2694
2685
  ) })
2695
2686
  ] }),
2696
- /* @__PURE__ */ jsx(
2697
- Typography,
2698
- {
2699
- variant: "pi",
2700
- textColor: "neutral500",
2701
- style: { marginTop: 8, display: "block" },
2702
- children: timeout > 0 ? `Если событие не произойдёт за ${timeout} ${timeoutUnit}, кампания продолжится автоматически` : "Установите 0 для бесконечного ожидания события"
2703
- }
2704
- )
2687
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral500", style: { marginTop: 8, display: "block" }, children: timeout > 0 ? `Если событие не произойдёт за ${timeout} ${timeoutUnit}, кампания продолжится автоматически` : "Установите 0 для бесконечного ожидания события" })
2705
2688
  ] }),
2706
2689
  /* @__PURE__ */ jsx(
2707
2690
  "div",
@@ -2723,8 +2706,7 @@ const EventTriggerConfig = ({ data, onUpdate, disabled }) => {
2723
2706
  },
2724
2707
  children: events.length === 0 ? "Выберите события, которые должен совершить пользователь для продолжения кампании." : /* @__PURE__ */ jsxs(Fragment, { children: [
2725
2708
  logic === "or" ? /* @__PURE__ */ jsxs(Fragment, { children: [
2726
- "Кампания продолжится, когда пользователь выполнит",
2727
- " ",
2709
+ "Кампания продолжится, когда пользователь выполнит ",
2728
2710
  /* @__PURE__ */ jsx("strong", { children: "любое" }),
2729
2711
  " из выбранных событий"
2730
2712
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -2738,7 +2720,8 @@ const EventTriggerConfig = ({ data, onUpdate, disabled }) => {
2738
2720
  ] }),
2739
2721
  timeout > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
2740
2722
  " ",
2741
- "или через ",
2723
+ "или через",
2724
+ " ",
2742
2725
  /* @__PURE__ */ jsxs("strong", { children: [
2743
2726
  timeout,
2744
2727
  " ",