@inspirer-dev/crm-dashboard 1.0.11 → 1.0.12

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.
@@ -3,474 +3,7 @@ import React__default, { forwardRef, useState, useMemo, useCallback } from "reac
3
3
  import { Field, Flex, Badge, Button, Box, Typography, Tooltip, IconButton, SingleSelect, SingleSelectOption, Switch, TextInput } from "@strapi/design-system";
4
4
  import { Trash, Plus, Layout } from "@strapi/icons";
5
5
  import { useTheme } from "styled-components";
6
- const OPERATORS = [
7
- { value: "$eq", label: "=", description: "Equals" },
8
- { value: "$ne", label: "≠", description: "Not equals" },
9
- { value: "$gt", label: ">", description: "Greater than" },
10
- { value: "$lt", label: "<", description: "Less than" },
11
- { value: "$gte", label: "≥", description: "Greater or equal" },
12
- { value: "$lte", label: "≤", description: "Less or equal" },
13
- { value: "$in", label: "in", description: "In list" },
14
- { value: "$nin", label: "not in", description: "Not in list" },
15
- { value: "$exists", label: "exists", description: "Field exists" },
16
- { value: "$regex", label: "matches", description: "Regex match" }
17
- ];
18
- const numberOperators = ["$eq", "$ne", "$gt", "$lt", "$gte", "$lte"];
19
- const timeAgoOperators = ["$gt", "$lt", "$gte", "$lte"];
20
- const booleanOperators = ["$eq", "$ne"];
21
- const stringOperators = ["$eq", "$ne", "$regex", "$in", "$nin"];
22
- const existsOperators = ["$exists"];
23
- const METRICS = [
24
- {
25
- key: "deposit_count",
26
- label: "Deposit Count",
27
- category: "counters",
28
- valueType: "number",
29
- description: "Total number of successful deposits",
30
- operators: numberOperators
31
- },
32
- {
33
- key: "case_open_count",
34
- label: "Case Open Count",
35
- category: "counters",
36
- valueType: "number",
37
- description: "Total cases opened",
38
- operators: numberOperators
39
- },
40
- {
41
- key: "upgrade_count",
42
- label: "Upgrade Count",
43
- category: "counters",
44
- valueType: "number",
45
- description: "Total upgrades performed",
46
- operators: numberOperators
47
- },
48
- {
49
- key: "battle_count",
50
- label: "Battle Count",
51
- category: "counters",
52
- valueType: "number",
53
- description: "Total battles created/participated",
54
- operators: numberOperators
55
- },
56
- {
57
- key: "contract_count",
58
- label: "Contract Count",
59
- category: "counters",
60
- valueType: "number",
61
- description: "Total contracts executed",
62
- operators: numberOperators
63
- },
64
- {
65
- key: "withdraw_count",
66
- label: "Withdraw Count",
67
- category: "counters",
68
- valueType: "number",
69
- description: "Total withdrawals",
70
- operators: numberOperators
71
- },
72
- {
73
- key: "session_count",
74
- label: "Session Count",
75
- category: "counters",
76
- valueType: "number",
77
- description: "Total sessions",
78
- operators: numberOperators
79
- },
80
- {
81
- key: "consecutive_active_days",
82
- label: "Consecutive Active Days",
83
- category: "counters",
84
- valueType: "number",
85
- description: "Days active in a row",
86
- operators: numberOperators
87
- },
88
- {
89
- key: "deposit_sum_total",
90
- label: "Total Deposits Sum",
91
- category: "money",
92
- valueType: "number",
93
- description: "Sum of all deposits in RUB",
94
- operators: numberOperators
95
- },
96
- {
97
- key: "withdraw_sum_total",
98
- label: "Total Withdrawals Sum",
99
- category: "money",
100
- valueType: "number",
101
- description: "Sum of all withdrawals",
102
- operators: numberOperators
103
- },
104
- {
105
- key: "win_sum_total",
106
- label: "Total Wins Sum",
107
- category: "money",
108
- valueType: "number",
109
- description: "Sum of all winnings",
110
- operators: numberOperators
111
- },
112
- {
113
- key: "avg_deposit",
114
- label: "Average Deposit",
115
- category: "money",
116
- valueType: "number",
117
- description: "Average deposit amount",
118
- operators: numberOperators
119
- },
120
- {
121
- key: "balance",
122
- label: "Current Balance",
123
- category: "money",
124
- valueType: "number",
125
- description: "Current account balance",
126
- operators: numberOperators
127
- },
128
- {
129
- key: "net_deposit",
130
- label: "Net Deposit",
131
- category: "money",
132
- valueType: "number",
133
- description: "Deposits minus withdrawals",
134
- operators: numberOperators
135
- },
136
- {
137
- key: "last_deposit_at",
138
- label: "Last Deposit",
139
- category: "time",
140
- valueType: "time_ago",
141
- description: "Time since last deposit",
142
- operators: timeAgoOperators
143
- },
144
- {
145
- key: "last_case_open_at",
146
- label: "Last Case Open",
147
- category: "time",
148
- valueType: "time_ago",
149
- description: "Time since last case opened",
150
- operators: timeAgoOperators
151
- },
152
- {
153
- key: "last_upgrade_at",
154
- label: "Last Upgrade",
155
- category: "time",
156
- valueType: "time_ago",
157
- description: "Time since last upgrade",
158
- operators: timeAgoOperators
159
- },
160
- {
161
- key: "last_battle_at",
162
- label: "Last Battle",
163
- category: "time",
164
- valueType: "time_ago",
165
- description: "Time since last battle",
166
- operators: timeAgoOperators
167
- },
168
- {
169
- key: "last_contract_at",
170
- label: "Last Contract",
171
- category: "time",
172
- valueType: "time_ago",
173
- description: "Time since last contract",
174
- operators: timeAgoOperators
175
- },
176
- {
177
- key: "last_withdraw_at",
178
- label: "Last Withdrawal",
179
- category: "time",
180
- valueType: "time_ago",
181
- description: "Time since last withdrawal",
182
- operators: timeAgoOperators
183
- },
184
- {
185
- key: "last_session_at",
186
- label: "Last Activity",
187
- category: "time",
188
- valueType: "time_ago",
189
- description: "Time since last session/activity",
190
- operators: timeAgoOperators
191
- },
192
- {
193
- key: "registered_at",
194
- label: "Registration Date",
195
- category: "time",
196
- valueType: "time_ago",
197
- description: "Time since registration",
198
- operators: timeAgoOperators
199
- },
200
- {
201
- key: "first_deposit_at",
202
- label: "First Deposit Date",
203
- category: "time",
204
- valueType: "time_ago",
205
- description: "Time since first deposit",
206
- operators: [...timeAgoOperators, ...existsOperators]
207
- },
208
- {
209
- key: "is_vip",
210
- label: "Is VIP",
211
- category: "status",
212
- valueType: "boolean",
213
- description: "VIP status",
214
- operators: booleanOperators
215
- },
216
- {
217
- key: "is_ftd",
218
- label: "Is FTD (First-Time Depositor)",
219
- category: "status",
220
- valueType: "boolean",
221
- description: "Has exactly 1 deposit",
222
- operators: booleanOperators
223
- },
224
- {
225
- key: "has_telegram",
226
- label: "Has Telegram",
227
- category: "status",
228
- valueType: "boolean",
229
- description: "Telegram connected",
230
- operators: booleanOperators
231
- },
232
- {
233
- key: "telegram_opt_out",
234
- label: "Telegram Opt-Out",
235
- category: "status",
236
- valueType: "boolean",
237
- description: "User opted out of TG messages",
238
- operators: booleanOperators
239
- },
240
- {
241
- key: "has_free_case",
242
- label: "Has Free Case",
243
- category: "status",
244
- valueType: "boolean",
245
- description: "Has available free case",
246
- operators: booleanOperators
247
- },
248
- {
249
- key: "lifecycle_stage",
250
- label: "Lifecycle Stage",
251
- category: "activity",
252
- valueType: "string",
253
- description: "New, Active, Sleep, Churn, Dead",
254
- operators: stringOperators
255
- },
256
- {
257
- key: "referral_source",
258
- label: "Referral Source",
259
- category: "activity",
260
- valueType: "string",
261
- description: "How user was acquired",
262
- operators: stringOperators
263
- },
264
- {
265
- key: "country",
266
- label: "Country",
267
- category: "activity",
268
- valueType: "string",
269
- description: "User country code",
270
- operators: stringOperators
271
- },
272
- {
273
- key: "timezone",
274
- label: "Timezone",
275
- category: "activity",
276
- valueType: "string",
277
- description: "User timezone",
278
- operators: stringOperators
279
- }
280
- ];
281
- const METRICS_BY_CATEGORY = METRICS.reduce(
282
- (acc, metric) => {
283
- if (!acc[metric.category]) {
284
- acc[metric.category] = [];
285
- }
286
- acc[metric.category].push(metric);
287
- return acc;
288
- },
289
- {}
290
- );
291
- const CATEGORY_LABELS = {
292
- counters: "📊 Counters",
293
- money: "💰 Money",
294
- time: "⏰ Time-based",
295
- status: "🏷️ Status",
296
- activity: "📱 Activity & Profile"
297
- };
298
- const LIFECYCLE_STAGES = ["new", "active", "sleep", "churn", "dead"];
299
- const TIME_UNITS = [
300
- { value: "minutes_ago", label: "minutes ago" },
301
- { value: "hours_ago", label: "hours ago" },
302
- { value: "days_ago", label: "days ago" }
303
- ];
304
- const DEFAULT_RULE = {
305
- field: "deposit_count",
306
- operator: "$eq",
307
- value: 0
308
- };
309
- let idCounter = 0;
310
- const generateId = () => {
311
- idCounter += 1;
312
- return `rule_${Date.now()}_${idCounter}`;
313
- };
314
- const createEmptyRule = () => ({
315
- id: generateId(),
316
- ...DEFAULT_RULE
317
- });
318
- const createEmptyGroup = (logic = "$and") => ({
319
- id: generateId(),
320
- logic,
321
- rules: [createEmptyRule()]
322
- });
323
- const createInitialConfig = () => ({
324
- id: generateId(),
325
- logic: "$and",
326
- rules: []
327
- });
328
- const isRuleGroup = (item) => {
329
- return "logic" in item && "rules" in item;
330
- };
331
- const getMetricDefinition = (key) => {
332
- return METRICS.find((m) => m.key === key);
333
- };
334
- const isTimeAgoValue = (value) => {
335
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
336
- return false;
337
- }
338
- return "hours_ago" in value || "days_ago" in value || "minutes_ago" in value;
339
- };
340
- const parseTimeAgoValue = (value) => {
341
- if (!isTimeAgoValue(value)) {
342
- return { amount: 24, unit: "hours_ago" };
343
- }
344
- if (value.minutes_ago !== void 0) {
345
- return { amount: value.minutes_ago, unit: "minutes_ago" };
346
- }
347
- if (value.hours_ago !== void 0) {
348
- return { amount: value.hours_ago, unit: "hours_ago" };
349
- }
350
- if (value.days_ago !== void 0) {
351
- return { amount: value.days_ago, unit: "days_ago" };
352
- }
353
- return { amount: 24, unit: "hours_ago" };
354
- };
355
- const createTimeAgoValue = (amount, unit) => {
356
- return { [unit]: amount };
357
- };
358
- const serializeConfig = (config) => {
359
- return JSON.stringify(config, null, 2);
360
- };
361
- const deserializeConfig = (json) => {
362
- if (!json) {
363
- return createInitialConfig();
364
- }
365
- try {
366
- const parsed = typeof json === "string" ? JSON.parse(json) : json;
367
- if (parsed && typeof parsed === "object" && "logic" in parsed && "rules" in parsed) {
368
- return parsed;
369
- }
370
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
371
- const rules = Object.entries(parsed).map(([field, condition]) => {
372
- const condObj = condition;
373
- const operator = Object.keys(condObj)[0];
374
- const value = condObj[operator];
375
- return {
376
- id: generateId(),
377
- field,
378
- operator,
379
- value
380
- };
381
- });
382
- return {
383
- id: generateId(),
384
- logic: "$and",
385
- rules
386
- };
387
- }
388
- return createInitialConfig();
389
- } catch {
390
- return createInitialConfig();
391
- }
392
- };
393
- const updateRuleInGroup = (group, ruleId, updater) => {
394
- return {
395
- ...group,
396
- rules: group.rules.map((item) => {
397
- if (isRuleGroup(item)) {
398
- return updateRuleInGroup(item, ruleId, updater);
399
- }
400
- if (item.id === ruleId) {
401
- return updater(item);
402
- }
403
- return item;
404
- })
405
- };
406
- };
407
- const deleteRuleFromGroup = (group, ruleId) => {
408
- const filtered = group.rules.map((item) => {
409
- if (isRuleGroup(item)) {
410
- const updated = deleteRuleFromGroup(item, ruleId);
411
- if (updated.rules.length === 0) {
412
- return null;
413
- }
414
- return updated;
415
- }
416
- if (item.id === ruleId) {
417
- return null;
418
- }
419
- return item;
420
- }).filter(Boolean);
421
- return { ...group, rules: filtered };
422
- };
423
- const addRuleToGroup = (group, groupId, rule) => {
424
- if (group.id === groupId) {
425
- return {
426
- ...group,
427
- rules: [...group.rules, rule]
428
- };
429
- }
430
- return {
431
- ...group,
432
- rules: group.rules.map((item) => {
433
- if (isRuleGroup(item)) {
434
- return addRuleToGroup(item, groupId, rule);
435
- }
436
- return item;
437
- })
438
- };
439
- };
440
- const updateGroupLogic = (group, groupId, logic) => {
441
- if (group.id === groupId) {
442
- return { ...group, logic };
443
- }
444
- return {
445
- ...group,
446
- rules: group.rules.map((item) => {
447
- if (isRuleGroup(item)) {
448
- return updateGroupLogic(item, groupId, logic);
449
- }
450
- return item;
451
- })
452
- };
453
- };
454
- const deleteGroupFromParent = (group, groupId) => {
455
- const filtered = group.rules.map((item) => {
456
- if (isRuleGroup(item)) {
457
- if (item.id === groupId) {
458
- return null;
459
- }
460
- return deleteGroupFromParent(item, groupId);
461
- }
462
- return item;
463
- }).filter(Boolean);
464
- return { ...group, rules: filtered };
465
- };
466
- const countRules = (group) => {
467
- return group.rules.reduce((count, item) => {
468
- if (isRuleGroup(item)) {
469
- return count + countRules(item);
470
- }
471
- return count + 1;
472
- }, 0);
473
- };
6
+ import { d as deserializeConfig, c as countRules, s as serializeConfig, a as createInitialConfig, i as isRuleGroup, u as updateGroupLogic, b as deleteGroupFromParent, g as getMetricDefinition, O as OPERATORS, M as METRICS_BY_CATEGORY, C as CATEGORY_LABELS, e as deleteRuleFromGroup, f as updateRuleInGroup, h as addRuleToGroup, j as createEmptyRule, k as createEmptyGroup, p as parseTimeAgoValue, l as createTimeAgoValue, T as TIME_UNITS, L as LIFECYCLE_STAGES } from "./utils-C6_ndVAZ.mjs";
474
7
  const ValueInput = ({ metric, value, operator, onChange, disabled }) => {
475
8
  if (operator === "$exists") {
476
9
  const boolVal = value === true || value === "true";