@inspirer-dev/crm-dashboard 1.0.37 → 1.0.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/admin/src/components/ButtonsBuilder/index.tsx +4 -4
  2. package/admin/src/components/CancelConditionsField/index.tsx +6 -6
  3. package/admin/src/components/RulesBuilder/index.tsx +4 -4
  4. package/admin/src/components/StepFlowBuilder/flow-canvas/FlowCanvas.tsx +11 -2
  5. package/admin/src/components/StepFlowBuilder/panels/BranchConfig.tsx +5 -5
  6. package/admin/src/components/StepFlowBuilder/panels/EntryConfig.tsx +17 -17
  7. package/admin/src/components/StepFlowBuilder/panels/MessageConfig.tsx +9 -9
  8. package/admin/src/components/StepFlowBuilder/panels/WaitConfig.tsx +4 -4
  9. package/admin/src/components/TriggerConfigField/index.tsx +25 -15
  10. package/dist/_chunks/{FlowCanvas-B24xSTsy.mjs → FlowCanvas-Dosn1PWx.mjs} +48 -43
  11. package/dist/_chunks/{FlowCanvas-CyPjsEVc.js → FlowCanvas-O8LZmpU9.js} +47 -42
  12. package/dist/_chunks/{index-CLv1Ce0a.js → index--0PypLko.js} +4 -4
  13. package/dist/_chunks/{index-DphnHWJg.js → index-BAEkCRvB.js} +1 -1
  14. package/dist/_chunks/{index-D4D9naFd.mjs → index-Bxnf94Nw.mjs} +307 -258
  15. package/dist/_chunks/{index-Cj7L2FNg.js → index-C-Vbihve.js} +1 -1
  16. package/dist/_chunks/{index-DdgfQNw_.mjs → index-C-eKNjo5.mjs} +6 -6
  17. package/dist/_chunks/{index-DkY191XW.mjs → index-CR4G6zrn.mjs} +1 -1
  18. package/dist/_chunks/{index-JOsIDBgU.mjs → index-CuPT2Zxf.mjs} +4 -4
  19. package/dist/_chunks/{index-jwDYIfnW.js → index-CvoXAIng.js} +6 -6
  20. package/dist/_chunks/{index-DGIbwLd4.js → index-CwfIGC3K.js} +23 -15
  21. package/dist/_chunks/{index-CrIUBH7C.mjs → index-D4m1lj0p.mjs} +23 -15
  22. package/dist/_chunks/{index-CipW7YLs.js → index-DDmUtV_B.js} +4 -4
  23. package/dist/_chunks/{index-BTVDaym0.mjs → index-DlqzYMRV.mjs} +4 -4
  24. package/dist/admin/index.js +6 -6
  25. package/dist/admin/index.mjs +6 -6
  26. package/package.json +1 -1
@@ -188,7 +188,7 @@ const ButtonsBuilder = forwardRef<HTMLDivElement, ButtonsBuilderProps>(
188
188
  <Box>
189
189
  <Field.Label>{intlLabel?.defaultMessage || 'Buttons'}</Field.Label>
190
190
  <Typography variant="pi" textColor="neutral500">
191
- Telegram inline keyboard buttons
191
+ Inline-кнопки для Telegram
192
192
  </Typography>
193
193
  </Box>
194
194
  <Button
@@ -213,10 +213,10 @@ const ButtonsBuilder = forwardRef<HTMLDivElement, ButtonsBuilderProps>(
213
213
  }}
214
214
  >
215
215
  <Typography variant="omega" textColor="neutral500">
216
- No buttons yet
216
+ Кнопок пока нет
217
217
  </Typography>
218
218
  <Typography variant="pi" textColor="neutral400" style={{ display: 'block', marginTop: 4 }}>
219
- Add a button to create an inline keyboard for your Telegram message
219
+ Добавьте кнопку для создания inline-клавиатуры в Telegram-сообщении
220
220
  </Typography>
221
221
  </Box>
222
222
  ) : (
@@ -329,7 +329,7 @@ const ButtonsBuilder = forwardRef<HTMLDivElement, ButtonsBuilderProps>(
329
329
  {!urlOk && (
330
330
  <Box paddingLeft={3} paddingBottom={2}>
331
331
  <Typography variant="pi" textColor="danger600">
332
- Please enter a valid http/https URL
332
+ Введите корректный http/https URL
333
333
  </Typography>
334
334
  </Box>
335
335
  )}
@@ -325,7 +325,7 @@ const CancelConditionsField = forwardRef<HTMLDivElement, CancelConditionsFieldPr
325
325
  <Flex direction="column" gap={3}>
326
326
  <Field.Label>{intlLabel?.defaultMessage || 'Cancel Conditions'}</Field.Label>
327
327
  <Typography variant="pi" textColor="neutral600">
328
- Skip sending if any of these conditions are true (checked right before send)
328
+ Пропустить отправку, если любое из условий истинно (проверяется перед отправкой)
329
329
  </Typography>
330
330
 
331
331
  <Card background="neutral100">
@@ -343,9 +343,9 @@ const CancelConditionsField = forwardRef<HTMLDivElement, CancelConditionsFieldPr
343
343
  {config.logic === '$or' ? 'OR' : 'AND'}
344
344
  </Button>
345
345
  <Typography variant="omega" textColor="neutral600">
346
- {config.logic === '$or'
347
- ? 'Cancel if ANY condition is true'
348
- : 'Cancel if ALL conditions are true'}
346
+ {config.logic === '$or'
347
+ ? 'Отменить, если ЛЮБОЕ условие истинно'
348
+ : 'Отменить, если ВСЕ условия истинны'}
349
349
  </Typography>
350
350
  </Flex>
351
351
  </Flex>
@@ -365,7 +365,7 @@ const CancelConditionsField = forwardRef<HTMLDivElement, CancelConditionsFieldPr
365
365
  {!hasRules && (
366
366
  <Box padding={4} background="neutral0" hasRadius style={{ textAlign: 'center' }}>
367
367
  <Typography variant="omega" textColor="neutral500">
368
- No cancel conditions defined. Message will be sent if segment rules match.
368
+ Условия отмены не заданы. Сообщение будет отправлено, если правила сегмента совпадают.
369
369
  </Typography>
370
370
  </Box>
371
371
  )}
@@ -379,7 +379,7 @@ const CancelConditionsField = forwardRef<HTMLDivElement, CancelConditionsFieldPr
379
379
  disabled={disabled}
380
380
  size="S"
381
381
  >
382
- Add Cancel Condition
382
+ Добавить условие отмены
383
383
  </Button>
384
384
  </Box>
385
385
  </Box>
@@ -380,7 +380,7 @@ const RuleGroupComponent: React.FC<RuleGroupComponentProps> = ({
380
380
  {group.logic === '$and' ? 'AND' : 'OR'}
381
381
  </Button>
382
382
  <Typography variant="pi" textColor="neutral600">
383
- {group.logic === '$and' ? 'All conditions must match' : 'Any condition can match'}
383
+ {group.logic === '$and' ? 'Все условия должны совпадать' : 'Любое условие может совпадать'}
384
384
  </Typography>
385
385
  </Flex>
386
386
  {depth > 0 && onDelete && (
@@ -426,7 +426,7 @@ const RuleGroupComponent: React.FC<RuleGroupComponentProps> = ({
426
426
  onClick={handleAddRule}
427
427
  disabled={disabled}
428
428
  >
429
- Add condition
429
+ Добавить условие
430
430
  </Button>
431
431
  {depth < 2 && (
432
432
  <Button
@@ -436,7 +436,7 @@ const RuleGroupComponent: React.FC<RuleGroupComponentProps> = ({
436
436
  onClick={handleAddGroup}
437
437
  disabled={disabled}
438
438
  >
439
- Add {group.logic === '$and' ? 'OR' : 'AND'} group
439
+ Добавить {group.logic === '$and' ? 'ИЛИ' : 'И'} группу
440
440
  </Button>
441
441
  )}
442
442
  </Flex>
@@ -483,7 +483,7 @@ const RulesBuilder = forwardRef<HTMLDivElement, RulesBuilderProps>(
483
483
  </Badge>
484
484
  {rulesCount > 0 && (
485
485
  <Button variant="ghost" size="S" onClick={handleClear} disabled={disabled}>
486
- Clear all
486
+ Очистить всё
487
487
  </Button>
488
488
  )}
489
489
  </Flex>
@@ -5,6 +5,7 @@ import ReactFlow, {
5
5
  MiniMap,
6
6
  useNodesState,
7
7
  useEdgesState,
8
+ useReactFlow,
8
9
  addEdge,
9
10
  type Connection,
10
11
  type OnNodesChange,
@@ -44,6 +45,7 @@ const FlowCanvas: React.FC<FlowCanvasProps> = ({ steps, onStepsChange, disabled,
44
45
  const isInitialMount = useRef(true);
45
46
  const syncTimeoutRef = useRef<NodeJS.Timeout | null>(null);
46
47
  const lastStepsRef = useRef<string>('');
48
+ const { fitView } = useReactFlow();
47
49
 
48
50
  useEffect(() => {
49
51
  const stepsJson = JSON.stringify(steps);
@@ -60,9 +62,13 @@ const FlowCanvas: React.FC<FlowCanvasProps> = ({ steps, onStepsChange, disabled,
60
62
  const layoutedNodes = applyAutoLayout(n, e);
61
63
  setNodes(layoutedNodes);
62
64
  setEdges(e);
65
+
66
+ setTimeout(() => {
67
+ fitView({ padding: 0.2, duration: 200 });
68
+ }, 50);
63
69
  }
64
70
  isInitialMount.current = false;
65
- }, [steps, setNodes, setEdges]);
71
+ }, [steps, setNodes, setEdges, fitView]);
66
72
 
67
73
  const syncToParent = useCallback(() => {
68
74
  if (isInitialMount.current) return;
@@ -168,7 +174,10 @@ const FlowCanvas: React.FC<FlowCanvasProps> = ({ steps, onStepsChange, disabled,
168
174
  const handleAutoLayout = useCallback(() => {
169
175
  const layoutedNodes = applyAutoLayout(nodes, edges);
170
176
  setNodes(layoutedNodes);
171
- }, [nodes, edges, setNodes]);
177
+ setTimeout(() => {
178
+ fitView({ padding: 0.2, duration: 200 });
179
+ }, 50);
180
+ }, [nodes, edges, setNodes, fitView]);
172
181
 
173
182
  const handleNodeUpdate = useCallback(
174
183
  (nodeId: string, data: Partial<FlowNodeData>) => {
@@ -94,7 +94,7 @@ const BranchConfig: React.FC<BranchConfigProps> = ({ data, onUpdate, disabled })
94
94
  color: theme.textMuted,
95
95
  }}
96
96
  >
97
- CONDITION SEGMENT
97
+ СЕГМЕНТ УСЛОВИЯ
98
98
  </Typography>
99
99
  <div style={{ width: '100%' }}>
100
100
  {fetchError ? (
@@ -106,7 +106,7 @@ const BranchConfig: React.FC<BranchConfigProps> = ({ data, onUpdate, disabled })
106
106
  placeholder="Enter segment ID..."
107
107
  />
108
108
  <Typography variant="pi" style={{ color: theme.textSubtle, fontSize: 11, marginTop: 6 }}>
109
- Enter segment ID manually (API not available in test mode)
109
+ Введите ID сегмента вручную (API недоступен в тестовом режиме)
110
110
  </Typography>
111
111
  </>
112
112
  ) : (
@@ -174,7 +174,7 @@ const BranchConfig: React.FC<BranchConfigProps> = ({ data, onUpdate, disabled })
174
174
  variant="pi"
175
175
  style={{ color: theme.textMuted, fontWeight: 600, marginBottom: 10, display: 'block' }}
176
176
  >
177
- How it works
177
+ Как это работает
178
178
  </Typography>
179
179
  <Flex direction="column" gap={2}>
180
180
  <Flex alignItems="center" gap={2}>
@@ -195,7 +195,7 @@ const BranchConfig: React.FC<BranchConfigProps> = ({ data, onUpdate, disabled })
195
195
  </svg>
196
196
  </span>
197
197
  <Typography variant="pi" style={{ color: theme.textMuted }}>
198
- Matches segment → <strong style={{ color: '#10b981' }}>Yes</strong> path
198
+ Соответствует сегментупуть <strong style={{ color: '#10b981' }}>Да</strong>
199
199
  </Typography>
200
200
  </Flex>
201
201
  <Flex alignItems="center" gap={2}>
@@ -216,7 +216,7 @@ const BranchConfig: React.FC<BranchConfigProps> = ({ data, onUpdate, disabled })
216
216
  </svg>
217
217
  </span>
218
218
  <Typography variant="pi" style={{ color: theme.textMuted }}>
219
- Does not match → <strong style={{ color: '#ef4444' }}>No</strong> path
219
+ Не соответствуетпуть <strong style={{ color: '#ef4444' }}>Нет</strong>
220
220
  </Typography>
221
221
  </Flex>
222
222
  </Flex>
@@ -103,7 +103,7 @@ const EntryConfigInner: React.FC<EntryConfigProps & { theme: FlowThemeColors }>
103
103
  }}
104
104
  >
105
105
  <Typography variant="pi" style={{ color: theme.textSubtle }}>
106
- No trigger configured
106
+ Триггер не настроен
107
107
  </Typography>
108
108
  </div>
109
109
  );
@@ -119,7 +119,7 @@ const EntryConfigInner: React.FC<EntryConfigProps & { theme: FlowThemeColors }>
119
119
  <path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" fill="#8b5cf6" />
120
120
  </svg>
121
121
  }
122
- title="Event-Based Trigger"
122
+ title="Триггер по событию"
123
123
  gradient={
124
124
  theme.isDark
125
125
  ? 'linear-gradient(135deg, #4c1d95 0%, #5b21b6 100%)'
@@ -131,13 +131,13 @@ const EntryConfigInner: React.FC<EntryConfigProps & { theme: FlowThemeColors }>
131
131
  <Flex direction="column" gap={2}>
132
132
  <Flex alignItems="center" gap={2}>
133
133
  <Typography variant="pi" style={{ color: theme.textMuted }}>
134
- Event:
134
+ Событие:
135
135
  </Typography>
136
136
  <Badge
137
137
  background={theme.isDark ? '#7c3aed' : '#ddd6fe'}
138
138
  color={theme.isDark ? '#f5f3ff' : '#6d28d9'}
139
139
  >
140
- {config.eventName || 'Not set'}
140
+ {config.eventName || 'Не задано'}
141
141
  </Badge>
142
142
  </Flex>
143
143
  {config.delayValue && config.delayValue > 0 && (
@@ -152,7 +152,7 @@ const EntryConfigInner: React.FC<EntryConfigProps & { theme: FlowThemeColors }>
152
152
  />
153
153
  </svg>
154
154
  <Typography variant="pi" style={{ color: theme.textMuted }}>
155
- Delay: {config.delayValue} {config.delayUnit || 'minutes'}
155
+ Задержка: {config.delayValue} {config.delayUnit || 'minutes'}
156
156
  </Typography>
157
157
  </Flex>
158
158
  )}
@@ -174,7 +174,7 @@ const EntryConfigInner: React.FC<EntryConfigProps & { theme: FlowThemeColors }>
174
174
  />
175
175
  </svg>
176
176
  }
177
- title="Scheduled Trigger"
177
+ title="Триггер по расписанию"
178
178
  gradient={
179
179
  theme.isDark
180
180
  ? 'linear-gradient(135deg, #78350f 0%, #92400e 100%)'
@@ -186,7 +186,7 @@ const EntryConfigInner: React.FC<EntryConfigProps & { theme: FlowThemeColors }>
186
186
  <Flex direction="column" gap={2}>
187
187
  <Flex alignItems="center" gap={2}>
188
188
  <Typography variant="pi" style={{ color: theme.textMuted }}>
189
- Type:
189
+ Тип:
190
190
  </Typography>
191
191
  <Badge
192
192
  background={theme.isDark ? '#d97706' : '#fde68a'}
@@ -197,13 +197,13 @@ const EntryConfigInner: React.FC<EntryConfigProps & { theme: FlowThemeColors }>
197
197
  </Flex>
198
198
  {config.scheduleType === 'interval' && (
199
199
  <Typography variant="pi" style={{ color: theme.textMuted }}>
200
- Every {config.scheduleEveryMinutes || 5} minutes
200
+ Каждые {config.scheduleEveryMinutes || 5} минут
201
201
  </Typography>
202
202
  )}
203
203
  {(config.scheduleType === 'daily' || config.scheduleType === 'weekly') &&
204
204
  config.scheduleTime && (
205
205
  <Typography variant="pi" style={{ color: theme.textMuted }}>
206
- At {config.scheduleTime} UTC
206
+ В {config.scheduleTime} UTC
207
207
  </Typography>
208
208
  )}
209
209
  {config.scheduleType === 'weekly' && config.scheduleDays && (
@@ -248,7 +248,7 @@ const EntryConfigInner: React.FC<EntryConfigProps & { theme: FlowThemeColors }>
248
248
  }}
249
249
  >
250
250
  <Typography variant="pi" style={{ color: theme.textSubtle }}>
251
- No entry segment (all users can enter)
251
+ Сегмент не задан (все пользователи могут войти)
252
252
  </Typography>
253
253
  </div>
254
254
  );
@@ -268,7 +268,7 @@ const EntryConfigInner: React.FC<EntryConfigProps & { theme: FlowThemeColors }>
268
268
  <path d="M19 8v6M16 11h6" stroke="#0ea5e9" strokeWidth="2" strokeLinecap="round" />
269
269
  </svg>
270
270
  }
271
- title="Entry Segment"
271
+ title="Сегмент входа"
272
272
  gradient={
273
273
  theme.isDark
274
274
  ? 'linear-gradient(135deg, #0c4a6e 0%, #075985 100%)'
@@ -280,7 +280,7 @@ const EntryConfigInner: React.FC<EntryConfigProps & { theme: FlowThemeColors }>
280
280
  <Flex direction="column" gap={2}>
281
281
  <Flex alignItems="center" gap={2}>
282
282
  <Typography variant="pi" style={{ color: theme.textMuted }}>
283
- Segment:
283
+ Сегмент:
284
284
  </Typography>
285
285
  <Badge
286
286
  background={theme.isDark ? '#0284c7' : '#bae6fd'}
@@ -290,7 +290,7 @@ const EntryConfigInner: React.FC<EntryConfigProps & { theme: FlowThemeColors }>
290
290
  </Badge>
291
291
  </Flex>
292
292
  <Typography variant="pi" style={{ color: theme.textSubtle, fontSize: 11 }}>
293
- Only matching users can enter
293
+ Только подходящие пользователи могут войти
294
294
  </Typography>
295
295
  </Flex>
296
296
  </InfoCard>
@@ -310,7 +310,7 @@ const EntryConfigInner: React.FC<EntryConfigProps & { theme: FlowThemeColors }>
310
310
  color: theme.textMuted,
311
311
  }}
312
312
  >
313
- TRIGGER
313
+ ТРИГГЕР
314
314
  </Typography>
315
315
  {renderTriggerInfo()}
316
316
  </Box>
@@ -326,7 +326,7 @@ const EntryConfigInner: React.FC<EntryConfigProps & { theme: FlowThemeColors }>
326
326
  color: theme.textMuted,
327
327
  }}
328
328
  >
329
- ENTRY CONDITIONS
329
+ УСЛОВИЯ ВХОДА
330
330
  </Typography>
331
331
  {renderSegmentInfo()}
332
332
  </Box>
@@ -368,7 +368,7 @@ const EntryConfigInner: React.FC<EntryConfigProps & { theme: FlowThemeColors }>
368
368
  marginBottom: 4,
369
369
  }}
370
370
  >
371
- Journey Entry Point
371
+ Точка входа в кампанию
372
372
  </Typography>
373
373
  <Typography
374
374
  variant="pi"
@@ -378,7 +378,7 @@ const EntryConfigInner: React.FC<EntryConfigProps & { theme: FlowThemeColors }>
378
378
  lineHeight: 1.5,
379
379
  }}
380
380
  >
381
- Configure trigger and entry segment in the main campaign fields above.
381
+ Настройте триггер и сегмент входа в основных полях кампании выше.
382
382
  </Typography>
383
383
  </div>
384
384
  </Flex>
@@ -160,7 +160,7 @@ const MessageConfig: React.FC<MessageConfigProps> = ({ data, onUpdate, disabled
160
160
  color: theme.textMuted,
161
161
  }}
162
162
  >
163
- CHANNEL
163
+ КАНАЛ
164
164
  </Typography>
165
165
  <div style={{ width: '100%' }}>
166
166
  <SingleSelect value={channel} onChange={handleChannelChange} disabled={disabled}>
@@ -179,7 +179,7 @@ const MessageConfig: React.FC<MessageConfigProps> = ({ data, onUpdate, disabled
179
179
  variant="sigma"
180
180
  style={{ fontSize: 11, letterSpacing: '0.05em', color: theme.textMuted }}
181
181
  >
182
- VARIANTS (A/B TESTING)
182
+ ВАРИАНТЫ (A/B ТЕСТИРОВАНИЕ)
183
183
  </Typography>
184
184
  <button
185
185
  type="button"
@@ -217,7 +217,7 @@ const MessageConfig: React.FC<MessageConfigProps> = ({ data, onUpdate, disabled
217
217
  }}
218
218
  >
219
219
  <Typography variant="pi" style={{ color: theme.textSubtle }}>
220
- No variants yet. Add a variant to enable A/B testing.
220
+ Вариантов пока нет. Добавьте вариант для A/B тестирования.
221
221
  </Typography>
222
222
  </div>
223
223
  ) : (
@@ -243,7 +243,7 @@ const MessageConfig: React.FC<MessageConfigProps> = ({ data, onUpdate, disabled
243
243
  variant="pi"
244
244
  style={{ color: theme.textMuted, fontSize: 10, fontWeight: 600 }}
245
245
  >
246
- Variant {index + 1}
246
+ Вариант {index + 1}
247
247
  </Typography>
248
248
  <button
249
249
  type="button"
@@ -276,7 +276,7 @@ const MessageConfig: React.FC<MessageConfigProps> = ({ data, onUpdate, disabled
276
276
  display: 'block',
277
277
  }}
278
278
  >
279
- Name
279
+ Название
280
280
  </Typography>
281
281
  <TextInput
282
282
  value={variant.name}
@@ -297,7 +297,7 @@ const MessageConfig: React.FC<MessageConfigProps> = ({ data, onUpdate, disabled
297
297
  display: 'block',
298
298
  }}
299
299
  >
300
- Weight
300
+ Вес
301
301
  </Typography>
302
302
  <NumberInput
303
303
  value={variant.weight}
@@ -318,7 +318,7 @@ const MessageConfig: React.FC<MessageConfigProps> = ({ data, onUpdate, disabled
318
318
  display: 'block',
319
319
  }}
320
320
  >
321
- Template
321
+ Шаблон
322
322
  </Typography>
323
323
  {loadingTemplates ? (
324
324
  <Flex padding={2}>
@@ -337,7 +337,7 @@ const MessageConfig: React.FC<MessageConfigProps> = ({ data, onUpdate, disabled
337
337
  variant="pi"
338
338
  style={{ color: theme.textSubtle, fontSize: 10, marginTop: 4 }}
339
339
  >
340
- Enter template ID manually
340
+ Введите ID шаблона вручную
341
341
  </Typography>
342
342
  </>
343
343
  ) : (
@@ -369,7 +369,7 @@ const MessageConfig: React.FC<MessageConfigProps> = ({ data, onUpdate, disabled
369
369
  variant="pi"
370
370
  style={{ color: theme.isDark ? '#fcd34d' : '#b45309', fontSize: 11 }}
371
371
  >
372
- No templates for {channel}
372
+ Нет шаблонов для {channel}
373
373
  </Typography>
374
374
  </div>
375
375
  )}
@@ -53,7 +53,7 @@ const WaitConfig: React.FC<WaitConfigProps> = ({ data, onUpdate, disabled }) =>
53
53
  color: theme.textMuted,
54
54
  }}
55
55
  >
56
- DURATION
56
+ ДЛИТЕЛЬНОСТЬ
57
57
  </Typography>
58
58
  <div style={{ width: '100%' }}>
59
59
  <NumberInput
@@ -76,7 +76,7 @@ const WaitConfig: React.FC<WaitConfigProps> = ({ data, onUpdate, disabled }) =>
76
76
  color: theme.textMuted,
77
77
  }}
78
78
  >
79
- UNIT
79
+ ЕДИНИЦА
80
80
  </Typography>
81
81
  <div style={{ width: '100%' }}>
82
82
  <SingleSelect
@@ -112,11 +112,11 @@ const WaitConfig: React.FC<WaitConfigProps> = ({ data, onUpdate, disabled }) =>
112
112
  lineHeight: 1.5,
113
113
  }}
114
114
  >
115
- Users will wait{' '}
115
+ Пользователи будут ждать{' '}
116
116
  <strong>
117
117
  {duration} {durationUnit.toLowerCase()}
118
118
  </strong>{' '}
119
- before proceeding.
119
+ перед продолжением.
120
120
  </Typography>
121
121
  </div>
122
122
  </Flex>
@@ -150,6 +150,15 @@ const WEEKDAYS = [
150
150
  { value: 6, label: 'S', full: 'Saturday' },
151
151
  ];
152
152
 
153
+ const ALL_EVENTS = Object.entries(ANALYTICS_EVENTS).flatMap(([category, events]) =>
154
+ events.map((event) => ({ ...event, category }))
155
+ );
156
+
157
+ const getEventLabel = (eventValue: string): string => {
158
+ const event = ALL_EVENTS.find((e) => e.value === eventValue);
159
+ return event ? `${event.label} (${event.value})` : eventValue;
160
+ };
161
+
153
162
  const parseConfig = (value: string | TriggerConfig | null | undefined): TriggerConfig => {
154
163
  if (!value) return DEFAULT_CONFIG;
155
164
  const normalize = (parsed: Partial<TriggerConfig>): TriggerConfig => ({
@@ -399,8 +408,8 @@ const TriggerConfigField = forwardRef<HTMLDivElement, TriggerConfigFieldProps>(
399
408
  onClick={() => handleUpdate({ type: 'event_based' })}
400
409
  disabled={disabled}
401
410
  icon={<Magic width={24} height={24} />}
402
- title="Event-Based"
403
- description="Triggers on user action"
411
+ title="По событию"
412
+ description="Срабатывает при действии пользователя"
404
413
  color={colors.event.color}
405
414
  gradientActive={colors.event.gradientActive}
406
415
  gradientInactive={colors.card.inactive}
@@ -413,8 +422,8 @@ const TriggerConfigField = forwardRef<HTMLDivElement, TriggerConfigFieldProps>(
413
422
  onClick={() => handleUpdate({ type: 'db_based' })}
414
423
  disabled={disabled}
415
424
  icon={<Calendar width={24} height={24} />}
416
- title="Scheduled"
417
- description="Runs on a schedule"
425
+ title="По расписанию"
426
+ description="Запускается по расписанию"
418
427
  color={colors.schedule.color}
419
428
  gradientActive={colors.schedule.gradientActive}
420
429
  gradientInactive={colors.card.inactive}
@@ -436,7 +445,7 @@ const TriggerConfigField = forwardRef<HTMLDivElement, TriggerConfigFieldProps>(
436
445
  >
437
446
  <SectionHeader
438
447
  icon={<Magic width={18} height={18} />}
439
- title="Event Configuration"
448
+ title="Настройка события"
440
449
  color={colors.event.color}
441
450
  />
442
451
 
@@ -448,11 +457,12 @@ const TriggerConfigField = forwardRef<HTMLDivElement, TriggerConfigFieldProps>(
448
457
  textColor="neutral700"
449
458
  style={{ marginBottom: 8, display: 'block' }}
450
459
  >
451
- Trigger Event
460
+ Событие-триггер
452
461
  </Typography>
453
462
  <Combobox
454
463
  placeholder="Search events..."
455
464
  value={config.eventName || ''}
465
+ textValue={config.eventName ? getEventLabel(config.eventName) : ''}
456
466
  onChange={(val: string) => handleUpdate({ eventName: val })}
457
467
  onClear={() => handleUpdate({ eventName: '' })}
458
468
  disabled={disabled}
@@ -481,7 +491,7 @@ const TriggerConfigField = forwardRef<HTMLDivElement, TriggerConfigFieldProps>(
481
491
  textColor="neutral500"
482
492
  style={{ marginTop: 6, display: 'block' }}
483
493
  >
484
- Select from predefined events or enter a custom event name
494
+ Выберите из списка или введите своё название события
485
495
  </Typography>
486
496
  </Box>
487
497
 
@@ -516,10 +526,10 @@ const TriggerConfigField = forwardRef<HTMLDivElement, TriggerConfigFieldProps>(
516
526
  textColor="neutral700"
517
527
  style={{ marginBottom: 4, display: 'block' }}
518
528
  >
519
- Delay Before Sending
529
+ Задержка перед отправкой
520
530
  </Typography>
521
531
  <Typography variant="pi" textColor="neutral500">
522
- Wait after event before checking rules
532
+ Ожидание после события перед проверкой правил
523
533
  </Typography>
524
534
  </Box>
525
535
  <Flex gap={2} alignItems="center">
@@ -567,7 +577,7 @@ const TriggerConfigField = forwardRef<HTMLDivElement, TriggerConfigFieldProps>(
567
577
  >
568
578
  <SectionHeader
569
579
  icon={<Calendar width={18} height={18} />}
570
- title="Schedule Configuration"
580
+ title="Настройка расписания"
571
581
  color={colors.schedule.color}
572
582
  />
573
583
 
@@ -658,7 +668,7 @@ const TriggerConfigField = forwardRef<HTMLDivElement, TriggerConfigFieldProps>(
658
668
  {config.scheduleType === 'interval' && (
659
669
  <Flex alignItems="center" gap={2} style={{ flex: 1 }}>
660
670
  <Typography variant="omega" textColor="neutral700">
661
- Run every
671
+ Запускать каждые
662
672
  </Typography>
663
673
  <Box style={{ width: 160 }}>
664
674
  <SingleSelect
@@ -682,7 +692,7 @@ const TriggerConfigField = forwardRef<HTMLDivElement, TriggerConfigFieldProps>(
682
692
  {config.scheduleType === 'daily' && (
683
693
  <Flex alignItems="center" gap={2} style={{ flex: 1 }}>
684
694
  <Typography variant="omega" textColor="neutral700">
685
- Every day at
695
+ Каждый день в
686
696
  </Typography>
687
697
  <Box style={{ width: 120 }}>
688
698
  <TextInput
@@ -704,7 +714,7 @@ const TriggerConfigField = forwardRef<HTMLDivElement, TriggerConfigFieldProps>(
704
714
  {config.scheduleType === 'weekly' && (
705
715
  <Flex alignItems="center" gap={2} style={{ flex: 1 }}>
706
716
  <Typography variant="omega" textColor="neutral700">
707
- Every week at
717
+ Каждую неделю в
708
718
  </Typography>
709
719
  <Box style={{ width: 120 }}>
710
720
  <TextInput
@@ -750,7 +760,7 @@ const TriggerConfigField = forwardRef<HTMLDivElement, TriggerConfigFieldProps>(
750
760
  textColor="neutral600"
751
761
  style={{ marginBottom: 8, display: 'block' }}
752
762
  >
753
- Select days
763
+ Выберите дни
754
764
  </Typography>
755
765
  <Flex gap={2}>
756
766
  {WEEKDAYS.map((day) => {
@@ -805,7 +815,7 @@ const TriggerConfigField = forwardRef<HTMLDivElement, TriggerConfigFieldProps>(
805
815
  textColor="neutral500"
806
816
  style={{ marginTop: 8, display: 'block' }}
807
817
  >
808
- Format: minute hour day month weekday (e.g., "0 12 * * *" = daily at 12:00
818
+ Формат: минута час день месяц день_недели (напр., "0 12 * * *" = ежедневно в 12:00
809
819
  UTC)
810
820
  </Typography>
811
821
  )}