be-components 7.6.3 → 7.6.4
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/lib/commonjs/NotificationManager/NotificationManagerTabs.js +188 -0
- package/lib/commonjs/NotificationManager/NotificationManagerTabs.js.map +1 -0
- package/lib/commonjs/NotificationManager/api/index.js +235 -6
- package/lib/commonjs/NotificationManager/api/index.js.map +1 -1
- package/lib/commonjs/NotificationManager/components/GroupManagement.js +1038 -0
- package/lib/commonjs/NotificationManager/components/GroupManagement.js.map +1 -0
- package/lib/commonjs/NotificationManager/components/JobManagement.js +783 -0
- package/lib/commonjs/NotificationManager/components/JobManagement.js.map +1 -0
- package/lib/commonjs/NotificationManager/components/ScheduleNotification.js +407 -0
- package/lib/commonjs/NotificationManager/components/ScheduleNotification.js.map +1 -0
- package/lib/commonjs/NotificationManager/components/index.js +56 -0
- package/lib/commonjs/NotificationManager/components/index.js.map +1 -0
- package/lib/commonjs/NotificationManager/components/shared/DateTimePicker.js +113 -0
- package/lib/commonjs/NotificationManager/components/shared/DateTimePicker.js.map +1 -0
- package/lib/commonjs/NotificationManager/components/shared/GroupSelector.js +191 -0
- package/lib/commonjs/NotificationManager/components/shared/GroupSelector.js.map +1 -0
- package/lib/commonjs/NotificationManager/components/shared/NotificationBuilderForm.js +509 -0
- package/lib/commonjs/NotificationManager/components/shared/NotificationBuilderForm.js.map +1 -0
- package/lib/commonjs/NotificationManager/components/shared/StatusBadge.js +69 -0
- package/lib/commonjs/NotificationManager/components/shared/StatusBadge.js.map +1 -0
- package/lib/commonjs/NotificationManager/index.js +38 -23
- package/lib/commonjs/NotificationManager/index.js.map +1 -1
- package/lib/commonjs/index.js +7 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/types.d.js +2 -0
- package/lib/commonjs/types.d.js.map +1 -1
- package/lib/module/NotificationManager/NotificationManagerTabs.js +180 -0
- package/lib/module/NotificationManager/NotificationManagerTabs.js.map +1 -0
- package/lib/module/NotificationManager/api/index.js +235 -6
- package/lib/module/NotificationManager/api/index.js.map +1 -1
- package/lib/module/NotificationManager/components/GroupManagement.js +1030 -0
- package/lib/module/NotificationManager/components/GroupManagement.js.map +1 -0
- package/lib/module/NotificationManager/components/JobManagement.js +775 -0
- package/lib/module/NotificationManager/components/JobManagement.js.map +1 -0
- package/lib/module/NotificationManager/components/ScheduleNotification.js +399 -0
- package/lib/module/NotificationManager/components/ScheduleNotification.js.map +1 -0
- package/lib/module/NotificationManager/components/index.js +8 -0
- package/lib/module/NotificationManager/components/index.js.map +1 -0
- package/lib/module/NotificationManager/components/shared/DateTimePicker.js +106 -0
- package/lib/module/NotificationManager/components/shared/DateTimePicker.js.map +1 -0
- package/lib/module/NotificationManager/components/shared/GroupSelector.js +184 -0
- package/lib/module/NotificationManager/components/shared/GroupSelector.js.map +1 -0
- package/lib/module/NotificationManager/components/shared/NotificationBuilderForm.js +501 -0
- package/lib/module/NotificationManager/components/shared/NotificationBuilderForm.js.map +1 -0
- package/lib/module/NotificationManager/components/shared/StatusBadge.js +62 -0
- package/lib/module/NotificationManager/components/shared/StatusBadge.js.map +1 -0
- package/lib/module/NotificationManager/index.js +32 -23
- package/lib/module/NotificationManager/index.js.map +1 -1
- package/lib/module/index.js +2 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/types.d.js +2 -0
- package/lib/module/types.d.js.map +1 -1
- package/lib/typescript/lib/commonjs/NotificationManager/NotificationManagerTabs.d.ts +17 -0
- package/lib/typescript/lib/commonjs/NotificationManager/NotificationManagerTabs.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/NotificationManager/api/index.d.ts +17 -2
- package/lib/typescript/lib/commonjs/NotificationManager/api/index.d.ts.map +1 -1
- package/lib/typescript/lib/commonjs/NotificationManager/components/GroupManagement.d.ts +6 -0
- package/lib/typescript/lib/commonjs/NotificationManager/components/GroupManagement.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/NotificationManager/components/JobManagement.d.ts +7 -0
- package/lib/typescript/lib/commonjs/NotificationManager/components/JobManagement.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/NotificationManager/components/ScheduleNotification.d.ts +8 -0
- package/lib/typescript/lib/commonjs/NotificationManager/components/ScheduleNotification.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/NotificationManager/components/index.d.ts +9 -0
- package/lib/typescript/lib/commonjs/NotificationManager/components/index.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/NotificationManager/components/shared/DateTimePicker.d.ts +9 -0
- package/lib/typescript/lib/commonjs/NotificationManager/components/shared/DateTimePicker.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/NotificationManager/components/shared/GroupSelector.d.ts +13 -0
- package/lib/typescript/lib/commonjs/NotificationManager/components/shared/GroupSelector.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/NotificationManager/components/shared/NotificationBuilderForm.d.ts +10 -0
- package/lib/typescript/lib/commonjs/NotificationManager/components/shared/NotificationBuilderForm.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/NotificationManager/components/shared/StatusBadge.d.ts +6 -0
- package/lib/typescript/lib/commonjs/NotificationManager/components/shared/StatusBadge.d.ts.map +1 -0
- package/lib/typescript/lib/commonjs/NotificationManager/index.d.ts +18 -2
- package/lib/typescript/lib/commonjs/NotificationManager/index.d.ts.map +1 -1
- package/lib/typescript/lib/commonjs/index.d.ts +18 -2
- package/lib/typescript/lib/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/lib/module/NotificationManager/NotificationManagerTabs.d.ts +17 -0
- package/lib/typescript/lib/module/NotificationManager/NotificationManagerTabs.d.ts.map +1 -0
- package/lib/typescript/lib/module/NotificationManager/api/index.d.ts +17 -2
- package/lib/typescript/lib/module/NotificationManager/api/index.d.ts.map +1 -1
- package/lib/typescript/lib/module/NotificationManager/components/GroupManagement.d.ts +6 -0
- package/lib/typescript/lib/module/NotificationManager/components/GroupManagement.d.ts.map +1 -0
- package/lib/typescript/lib/module/NotificationManager/components/JobManagement.d.ts +7 -0
- package/lib/typescript/lib/module/NotificationManager/components/JobManagement.d.ts.map +1 -0
- package/lib/typescript/lib/module/NotificationManager/components/ScheduleNotification.d.ts +8 -0
- package/lib/typescript/lib/module/NotificationManager/components/ScheduleNotification.d.ts.map +1 -0
- package/lib/typescript/lib/module/NotificationManager/components/index.d.ts +8 -0
- package/lib/typescript/lib/module/NotificationManager/components/index.d.ts.map +1 -0
- package/lib/typescript/lib/module/NotificationManager/components/shared/DateTimePicker.d.ts +9 -0
- package/lib/typescript/lib/module/NotificationManager/components/shared/DateTimePicker.d.ts.map +1 -0
- package/lib/typescript/lib/module/NotificationManager/components/shared/GroupSelector.d.ts +13 -0
- package/lib/typescript/lib/module/NotificationManager/components/shared/GroupSelector.d.ts.map +1 -0
- package/lib/typescript/lib/module/NotificationManager/components/shared/NotificationBuilderForm.d.ts +10 -0
- package/lib/typescript/lib/module/NotificationManager/components/shared/NotificationBuilderForm.d.ts.map +1 -0
- package/lib/typescript/lib/module/NotificationManager/components/shared/StatusBadge.d.ts +6 -0
- package/lib/typescript/lib/module/NotificationManager/components/shared/StatusBadge.d.ts.map +1 -0
- package/lib/typescript/lib/module/NotificationManager/index.d.ts +1 -0
- package/lib/typescript/lib/module/NotificationManager/index.d.ts.map +1 -1
- package/lib/typescript/lib/module/index.d.ts +2 -1
- package/lib/typescript/lib/module/index.d.ts.map +1 -1
- package/lib/typescript/src/NotificationManager/NotificationManagerTabs.d.ts +20 -0
- package/lib/typescript/src/NotificationManager/NotificationManagerTabs.d.ts.map +1 -0
- package/lib/typescript/src/NotificationManager/api/index.d.ts +74 -3
- package/lib/typescript/src/NotificationManager/api/index.d.ts.map +1 -1
- package/lib/typescript/src/NotificationManager/components/GroupManagement.d.ts +8 -0
- package/lib/typescript/src/NotificationManager/components/GroupManagement.d.ts.map +1 -0
- package/lib/typescript/src/NotificationManager/components/JobManagement.d.ts +9 -0
- package/lib/typescript/src/NotificationManager/components/JobManagement.d.ts.map +1 -0
- package/lib/typescript/src/NotificationManager/components/ScheduleNotification.d.ts +10 -0
- package/lib/typescript/src/NotificationManager/components/ScheduleNotification.d.ts.map +1 -0
- package/lib/typescript/src/NotificationManager/components/index.d.ts +8 -0
- package/lib/typescript/src/NotificationManager/components/index.d.ts.map +1 -0
- package/lib/typescript/src/NotificationManager/components/shared/DateTimePicker.d.ts +12 -0
- package/lib/typescript/src/NotificationManager/components/shared/DateTimePicker.d.ts.map +1 -0
- package/lib/typescript/src/NotificationManager/components/shared/GroupSelector.d.ts +16 -0
- package/lib/typescript/src/NotificationManager/components/shared/GroupSelector.d.ts.map +1 -0
- package/lib/typescript/src/NotificationManager/components/shared/NotificationBuilderForm.d.ts +12 -0
- package/lib/typescript/src/NotificationManager/components/shared/NotificationBuilderForm.d.ts.map +1 -0
- package/lib/typescript/src/NotificationManager/components/shared/StatusBadge.d.ts +8 -0
- package/lib/typescript/src/NotificationManager/components/shared/StatusBadge.d.ts.map +1 -0
- package/lib/typescript/src/NotificationManager/index.d.ts +1 -0
- package/lib/typescript/src/NotificationManager/index.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/NotificationManager/NotificationManagerTabs.tsx +178 -0
- package/src/NotificationManager/api/index.ts +239 -6
- package/src/NotificationManager/components/GroupManagement.tsx +854 -0
- package/src/NotificationManager/components/JobManagement.tsx +569 -0
- package/src/NotificationManager/components/ScheduleNotification.tsx +388 -0
- package/src/NotificationManager/components/index.ts +7 -0
- package/src/NotificationManager/components/shared/DateTimePicker.tsx +94 -0
- package/src/NotificationManager/components/shared/GroupSelector.tsx +130 -0
- package/src/NotificationManager/components/shared/NotificationBuilderForm.tsx +364 -0
- package/src/NotificationManager/components/shared/StatusBadge.tsx +72 -0
- package/src/NotificationManager/index.tsx +43 -24
- package/src/index.tsx +2 -0
- package/src/types.d.ts +38 -3
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import React, { useState, useEffect, useMemo } from 'react';
|
|
2
|
+
import { FlatList, TouchableOpacity } from 'react-native';
|
|
3
|
+
import { View, Text, TextInput } from '../../../Components/Themed';
|
|
4
|
+
import { useColors } from '../../../constants/useColors';
|
|
5
|
+
import { NotificationHelpers } from '../../api';
|
|
6
|
+
import { Icons } from '../../../Components';
|
|
7
|
+
import DropDown from '../../../Components/Dropdown';
|
|
8
|
+
import type { PlayerNotificationProps, FocusPositionProps } from '../../../types';
|
|
9
|
+
|
|
10
|
+
interface NotificationBuilderFormProps {
|
|
11
|
+
notification: Partial<PlayerNotificationProps>;
|
|
12
|
+
onChange: (notification: Partial<PlayerNotificationProps>) => void;
|
|
13
|
+
onFocusPosition?: (pos: FocusPositionProps) => void;
|
|
14
|
+
showPreview?: boolean;
|
|
15
|
+
showType?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const notification_types = [
|
|
19
|
+
{ label: 'Order Notifications', value: 'order_notifications' },
|
|
20
|
+
{ label: 'Competition Notifications', value: 'competition_notifications' },
|
|
21
|
+
{ label: 'Social Notifications', value: 'social_notifications' }
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const NotificationBuilderForm = ({
|
|
25
|
+
notification,
|
|
26
|
+
onChange,
|
|
27
|
+
onFocusPosition,
|
|
28
|
+
showPreview = true,
|
|
29
|
+
showType = true
|
|
30
|
+
}: NotificationBuilderFormProps) => {
|
|
31
|
+
const Colors = useColors();
|
|
32
|
+
const [pathSearch, setPathSearch] = useState('');
|
|
33
|
+
const [selectedPath, setSelectedPath] = useState<typeof NotificationHelpers.app_paths[0] | undefined>(
|
|
34
|
+
NotificationHelpers.app_paths[0]
|
|
35
|
+
);
|
|
36
|
+
const [pathParams, setPathParams] = useState<Record<string, string>>({});
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
// Initialize selectedPath from notification options if exists
|
|
40
|
+
if (notification.options?.data?.path_name) {
|
|
41
|
+
const path = NotificationHelpers.app_paths.find(p => p.path_name === notification.options?.data?.path_name);
|
|
42
|
+
if (path) {
|
|
43
|
+
setSelectedPath(path);
|
|
44
|
+
setPathParams(notification.options?.data?.params || {});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}, []);
|
|
48
|
+
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
// Update notification options when path or params change
|
|
51
|
+
if (selectedPath) {
|
|
52
|
+
const newOptions = {
|
|
53
|
+
...(notification.options || {}),
|
|
54
|
+
id: notification.options?.id || Date.now().toString(),
|
|
55
|
+
body: notification.body || '',
|
|
56
|
+
icon: 'default',
|
|
57
|
+
type: notification.type || 'order_notifications',
|
|
58
|
+
data: {
|
|
59
|
+
...(notification.options?.data || {}),
|
|
60
|
+
id: notification.options?.data?.id || Date.now().toString(),
|
|
61
|
+
player_id: notification.options?.data?.player_id || '',
|
|
62
|
+
pageStack: 'MainStack',
|
|
63
|
+
page: selectedPath.path_name,
|
|
64
|
+
pageParams: pathParams,
|
|
65
|
+
path_name: selectedPath.path_name === 'custom' ? '' : selectedPath.path_name,
|
|
66
|
+
params: pathParams
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
onChange({ ...notification, options: newOptions });
|
|
71
|
+
}
|
|
72
|
+
}, [selectedPath, pathParams]);
|
|
73
|
+
|
|
74
|
+
const filteredPaths = useMemo(() => {
|
|
75
|
+
if (!pathSearch) return [];
|
|
76
|
+
const search = pathSearch.toLowerCase();
|
|
77
|
+
return NotificationHelpers.app_paths.filter(
|
|
78
|
+
(path) =>
|
|
79
|
+
path.label.toLowerCase().includes(search) ||
|
|
80
|
+
path.path_name.toLowerCase().includes(search)
|
|
81
|
+
);
|
|
82
|
+
}, [pathSearch]);
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<View transparent style={{ flex: 1 }}>
|
|
86
|
+
{/* Preview Section */}
|
|
87
|
+
{showPreview && (
|
|
88
|
+
<View float style={{ margin: 5 }}>
|
|
89
|
+
<View type='header' style={{ flexDirection: 'row', alignItems: 'center', padding: 10, borderTopRightRadius: 8, borderTopLeftRadius: 8 }}>
|
|
90
|
+
<View transparent style={{ flex: 1 }}>
|
|
91
|
+
<Text theme='h1'>Preview</Text>
|
|
92
|
+
<Text theme='description' style={{ marginTop: 3 }}>What will this notification look like?</Text>
|
|
93
|
+
</View>
|
|
94
|
+
</View>
|
|
95
|
+
<View
|
|
96
|
+
float
|
|
97
|
+
style={{
|
|
98
|
+
padding: 15,
|
|
99
|
+
margin: 10,
|
|
100
|
+
borderRadius: 8,
|
|
101
|
+
borderWidth: 1,
|
|
102
|
+
borderColor: Colors.borders.light,
|
|
103
|
+
}}
|
|
104
|
+
>
|
|
105
|
+
<View transparent style={{ flexDirection: 'row', alignItems: 'center' }}>
|
|
106
|
+
<View
|
|
107
|
+
style={{
|
|
108
|
+
width: 40,
|
|
109
|
+
height: 40,
|
|
110
|
+
borderRadius: 8,
|
|
111
|
+
justifyContent: 'center',
|
|
112
|
+
alignItems: 'center',
|
|
113
|
+
marginRight: 12,
|
|
114
|
+
}}
|
|
115
|
+
>
|
|
116
|
+
<Icons.NotificationIcon size={20} color={Colors.text.h1} />
|
|
117
|
+
</View>
|
|
118
|
+
<View transparent style={{ flex: 1 }}>
|
|
119
|
+
<Text theme="h1">
|
|
120
|
+
{notification.title || 'Notification Title'}
|
|
121
|
+
</Text>
|
|
122
|
+
<Text theme="description" style={{ marginTop: 4 }}>
|
|
123
|
+
{notification.body || 'Notification message will appear here'}
|
|
124
|
+
</Text>
|
|
125
|
+
</View>
|
|
126
|
+
</View>
|
|
127
|
+
</View>
|
|
128
|
+
</View>
|
|
129
|
+
)}
|
|
130
|
+
|
|
131
|
+
{/* Message Section */}
|
|
132
|
+
<View style={{ flexDirection: 'row', flexWrap: 'wrap' }}>
|
|
133
|
+
<View float style={{ minWidth: 300, flexGrow: 1, margin: 5 }}>
|
|
134
|
+
<View type='header' style={{ flexDirection: 'row', alignItems: 'center', padding: 10, borderTopRightRadius: 8, borderTopLeftRadius: 8 }}>
|
|
135
|
+
<View transparent style={{ flex: 1 }}>
|
|
136
|
+
<Text theme='h1'>Notification Message</Text>
|
|
137
|
+
<Text theme='description' style={{ marginTop: 3 }}>Update notification message below</Text>
|
|
138
|
+
</View>
|
|
139
|
+
</View>
|
|
140
|
+
<View transparent type='body'>
|
|
141
|
+
<View transparent style={{ padding: 10 }}>
|
|
142
|
+
<Text theme="h2" style={{ marginBottom: 10 }}>
|
|
143
|
+
Notification Title
|
|
144
|
+
</Text>
|
|
145
|
+
<TextInput
|
|
146
|
+
value={notification.title}
|
|
147
|
+
onFocusPosition={onFocusPosition}
|
|
148
|
+
placeholder="Enter notification title"
|
|
149
|
+
onChangeText={(title) => onChange({ ...notification, title })}
|
|
150
|
+
/>
|
|
151
|
+
</View>
|
|
152
|
+
<View transparent style={{ padding: 10 }}>
|
|
153
|
+
<Text theme="h2" style={{ marginBottom: 10 }}>
|
|
154
|
+
Notification Body
|
|
155
|
+
</Text>
|
|
156
|
+
<TextInput
|
|
157
|
+
value={notification.body}
|
|
158
|
+
onFocusPosition={onFocusPosition}
|
|
159
|
+
placeholder="Enter notification message"
|
|
160
|
+
onChangeText={(body) => onChange({ ...notification, body })}
|
|
161
|
+
multiline
|
|
162
|
+
numberOfLines={6}
|
|
163
|
+
style={{ padding: 12, borderRadius: 8, minHeight: 120 }}
|
|
164
|
+
/>
|
|
165
|
+
</View>
|
|
166
|
+
</View>
|
|
167
|
+
</View>
|
|
168
|
+
|
|
169
|
+
{/* Settings Section */}
|
|
170
|
+
<View float style={{ flexGrow: 1, minWidth: 300, margin: 5 }}>
|
|
171
|
+
<View type='header' style={{ flexDirection: 'row', alignItems: 'center', padding: 10, borderTopRightRadius: 8, borderTopLeftRadius: 8 }}>
|
|
172
|
+
<View transparent style={{ flex: 1 }}>
|
|
173
|
+
<Text theme='h1'>Notification Settings</Text>
|
|
174
|
+
<Text theme='description' style={{ marginTop: 3 }}>Manage settings below</Text>
|
|
175
|
+
</View>
|
|
176
|
+
</View>
|
|
177
|
+
<View transparent type='body'>
|
|
178
|
+
{showType === true && (
|
|
179
|
+
<View type='row' style={{ padding: 10 }}>
|
|
180
|
+
<Text theme="h2" style={{ flex: 1 }}>
|
|
181
|
+
Notification Type
|
|
182
|
+
</Text>
|
|
183
|
+
<DropDown
|
|
184
|
+
selected_value={
|
|
185
|
+
notification_types.find((t) => t.value === notification.type)?.label ?? ''
|
|
186
|
+
}
|
|
187
|
+
dropdown_options={[
|
|
188
|
+
{ value: 'type', eligible_options: notification_types.map((t) => t.label) },
|
|
189
|
+
]}
|
|
190
|
+
onOptionSelect={(selected) => {
|
|
191
|
+
const type = notification_types.find((t) => t.label === selected)?.value;
|
|
192
|
+
onChange({ ...notification, type: type as any });
|
|
193
|
+
}}
|
|
194
|
+
/>
|
|
195
|
+
</View>
|
|
196
|
+
)}
|
|
197
|
+
<View transparent style={{ padding: 10 }}>
|
|
198
|
+
<Text theme="h2" style={{ marginBottom: 10 }}>
|
|
199
|
+
Link Override (Optional)
|
|
200
|
+
</Text>
|
|
201
|
+
<TextInput
|
|
202
|
+
value={notification.link_override || ''}
|
|
203
|
+
onFocusPosition={onFocusPosition}
|
|
204
|
+
placeholder="https://example.com"
|
|
205
|
+
onChangeText={(link_override) =>
|
|
206
|
+
onChange({ ...notification, link_override })
|
|
207
|
+
}
|
|
208
|
+
style={{ padding: 12, borderRadius: 8 }}
|
|
209
|
+
/>
|
|
210
|
+
</View>
|
|
211
|
+
<View transparent style={{ padding: 10 }}>
|
|
212
|
+
<Text theme="h2" style={{ marginBottom: 10 }}>
|
|
213
|
+
Deep Link Path
|
|
214
|
+
</Text>
|
|
215
|
+
|
|
216
|
+
{/* Selected Path Display */}
|
|
217
|
+
<View
|
|
218
|
+
type="header"
|
|
219
|
+
style={{
|
|
220
|
+
padding: 12,
|
|
221
|
+
borderRadius: 8,
|
|
222
|
+
marginBottom: 8,
|
|
223
|
+
flexDirection: 'row',
|
|
224
|
+
alignItems: 'center',
|
|
225
|
+
justifyContent: 'space-between'
|
|
226
|
+
}}
|
|
227
|
+
>
|
|
228
|
+
<View transparent style={{ flex: 1 }}>
|
|
229
|
+
<Text theme="h1" style={{ marginBottom: 2 }}>
|
|
230
|
+
{selectedPath?.label}
|
|
231
|
+
</Text>
|
|
232
|
+
<Text theme="description" style={{ fontSize: 12 }}>
|
|
233
|
+
{selectedPath?.path_name}
|
|
234
|
+
</Text>
|
|
235
|
+
</View>
|
|
236
|
+
{selectedPath?.primary === true && (
|
|
237
|
+
<View transparent style={{ paddingHorizontal: 8, paddingVertical: 4, borderRadius: 4 }}>
|
|
238
|
+
<Text theme="description" color={Colors.text.white} style={{ fontSize: 10 }}>
|
|
239
|
+
Primary
|
|
240
|
+
</Text>
|
|
241
|
+
</View>
|
|
242
|
+
)}
|
|
243
|
+
</View>
|
|
244
|
+
|
|
245
|
+
{/* Search Box */}
|
|
246
|
+
<TextInput
|
|
247
|
+
value={pathSearch}
|
|
248
|
+
placeholder="Search paths to change..."
|
|
249
|
+
onFocusPosition={onFocusPosition}
|
|
250
|
+
onChangeText={setPathSearch}
|
|
251
|
+
style={{ padding: 12, borderRadius: 8, marginBottom: 8 }}
|
|
252
|
+
/>
|
|
253
|
+
|
|
254
|
+
{/* Path Results List */}
|
|
255
|
+
{pathSearch ? (
|
|
256
|
+
<View
|
|
257
|
+
float
|
|
258
|
+
style={{
|
|
259
|
+
maxHeight: 300,
|
|
260
|
+
borderRadius: 8,
|
|
261
|
+
borderWidth: 1,
|
|
262
|
+
borderColor: Colors.borders.light,
|
|
263
|
+
}}
|
|
264
|
+
>
|
|
265
|
+
<FlatList
|
|
266
|
+
data={filteredPaths}
|
|
267
|
+
keyExtractor={(item) => item.path_name}
|
|
268
|
+
renderItem={({ item }) => (
|
|
269
|
+
<TouchableOpacity
|
|
270
|
+
onPress={() => {
|
|
271
|
+
setSelectedPath(item);
|
|
272
|
+
setPathParams(item.params as any);
|
|
273
|
+
setPathSearch('');
|
|
274
|
+
}}
|
|
275
|
+
style={{
|
|
276
|
+
padding: 12,
|
|
277
|
+
borderBottomWidth: 1,
|
|
278
|
+
borderColor: Colors.borders.light,
|
|
279
|
+
}}
|
|
280
|
+
>
|
|
281
|
+
<View transparent style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' }}>
|
|
282
|
+
<View transparent style={{ flex: 1 }}>
|
|
283
|
+
<Text theme="h2" style={{ marginBottom: 2 }}>
|
|
284
|
+
{item.label}
|
|
285
|
+
</Text>
|
|
286
|
+
<Text theme="description" style={{ fontSize: 11 }}>
|
|
287
|
+
{item.path_name}
|
|
288
|
+
</Text>
|
|
289
|
+
</View>
|
|
290
|
+
{item.primary === true && (
|
|
291
|
+
<View transparent style={{ paddingHorizontal: 6, paddingVertical: 2, borderRadius: 4, marginLeft: 8 }}>
|
|
292
|
+
<Text theme="description" color={Colors.text.white} style={{ fontSize: 9 }}>
|
|
293
|
+
Primary
|
|
294
|
+
</Text>
|
|
295
|
+
</View>
|
|
296
|
+
)}
|
|
297
|
+
</View>
|
|
298
|
+
</TouchableOpacity>
|
|
299
|
+
)}
|
|
300
|
+
ListEmptyComponent={
|
|
301
|
+
<View style={{ padding: 20, alignItems: 'center' }}>
|
|
302
|
+
<Text theme="description">No paths found</Text>
|
|
303
|
+
</View>
|
|
304
|
+
}
|
|
305
|
+
/>
|
|
306
|
+
</View>
|
|
307
|
+
) : null}
|
|
308
|
+
</View>
|
|
309
|
+
{Object.keys(selectedPath?.params ?? {}).length > 0 ? (
|
|
310
|
+
<View style={{ padding: 10 }}>
|
|
311
|
+
<Text theme="h2" style={{ marginBottom: 8 }}>
|
|
312
|
+
Path Parameters
|
|
313
|
+
</Text>
|
|
314
|
+
<View type="header" style={{ padding: 12, borderRadius: 8 }}>
|
|
315
|
+
{Object.keys(selectedPath?.params ?? {}).map((paramKey) => {
|
|
316
|
+
const isRequired = selectedPath?.requiredParams.includes(paramKey);
|
|
317
|
+
return (
|
|
318
|
+
<View key={paramKey} transparent style={{ marginBottom: 12 }}>
|
|
319
|
+
<View transparent style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 4 }}>
|
|
320
|
+
<Text theme="description">
|
|
321
|
+
{paramKey}
|
|
322
|
+
</Text>
|
|
323
|
+
{isRequired ? (
|
|
324
|
+
<View transparent style={{ marginLeft: 4, paddingHorizontal: 6, paddingVertical: 2, backgroundColor: Colors.text.error, borderRadius: 4 }}>
|
|
325
|
+
<Text theme="description" color={Colors.text.white} style={{ fontSize: 10 }}>
|
|
326
|
+
Required
|
|
327
|
+
</Text>
|
|
328
|
+
</View>
|
|
329
|
+
) : (
|
|
330
|
+
<View transparent style={{ marginLeft: 4, paddingHorizontal: 6, paddingVertical: 2, backgroundColor: Colors.borders.light, borderRadius: 4 }}>
|
|
331
|
+
<Text theme="description" style={{ fontSize: 10 }}>
|
|
332
|
+
Optional
|
|
333
|
+
</Text>
|
|
334
|
+
</View>
|
|
335
|
+
)}
|
|
336
|
+
</View>
|
|
337
|
+
<TextInput
|
|
338
|
+
value={pathParams[paramKey] || ''}
|
|
339
|
+
onFocusPosition={onFocusPosition}
|
|
340
|
+
placeholder={`Enter ${paramKey}${isRequired ? ' (required)' : ' (optional)'}`}
|
|
341
|
+
onChangeText={(value) =>
|
|
342
|
+
setPathParams({ ...pathParams, [paramKey]: value })
|
|
343
|
+
}
|
|
344
|
+
style={{
|
|
345
|
+
padding: 10,
|
|
346
|
+
borderRadius: 8,
|
|
347
|
+
borderWidth: isRequired ? 1 : 0,
|
|
348
|
+
borderColor: isRequired ? Colors.text.error : 'transparent'
|
|
349
|
+
}}
|
|
350
|
+
/>
|
|
351
|
+
</View>
|
|
352
|
+
);
|
|
353
|
+
})}
|
|
354
|
+
</View>
|
|
355
|
+
</View>
|
|
356
|
+
) : null}
|
|
357
|
+
</View>
|
|
358
|
+
</View>
|
|
359
|
+
</View>
|
|
360
|
+
</View>
|
|
361
|
+
);
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
export default NotificationBuilderForm;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, Text } from '../../../Components/Themed';
|
|
3
|
+
import { useColors } from '../../../constants/useColors';
|
|
4
|
+
import type { NotificationJobStatus } from '../../../types';
|
|
5
|
+
|
|
6
|
+
interface StatusBadgeProps {
|
|
7
|
+
status: NotificationJobStatus;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const StatusBadge = ({ status }: StatusBadgeProps) => {
|
|
11
|
+
const Colors = useColors();
|
|
12
|
+
|
|
13
|
+
const getStatusColor = () => {
|
|
14
|
+
switch (status) {
|
|
15
|
+
case 'pending':
|
|
16
|
+
return Colors.borders.light;
|
|
17
|
+
case 'ready':
|
|
18
|
+
return Colors.text.action;
|
|
19
|
+
case 'processing':
|
|
20
|
+
return Colors.text.warning;
|
|
21
|
+
case 'sent':
|
|
22
|
+
return Colors.text.success;
|
|
23
|
+
case 'failed':
|
|
24
|
+
return Colors.text.error;
|
|
25
|
+
case 'cancelled':
|
|
26
|
+
return Colors.text.h2;
|
|
27
|
+
default:
|
|
28
|
+
return Colors.borders.light;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const getStatusLabel = () => {
|
|
33
|
+
switch (status) {
|
|
34
|
+
case 'pending':
|
|
35
|
+
return 'Draft';
|
|
36
|
+
case 'ready':
|
|
37
|
+
return 'Scheduled';
|
|
38
|
+
case 'processing':
|
|
39
|
+
return 'Sending';
|
|
40
|
+
case 'sent':
|
|
41
|
+
return 'Sent';
|
|
42
|
+
case 'failed':
|
|
43
|
+
return 'Failed';
|
|
44
|
+
case 'cancelled':
|
|
45
|
+
return 'Cancelled';
|
|
46
|
+
default:
|
|
47
|
+
return status;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<View
|
|
53
|
+
transparent
|
|
54
|
+
style={{
|
|
55
|
+
paddingHorizontal: 8,
|
|
56
|
+
paddingVertical: 4,
|
|
57
|
+
backgroundColor: getStatusColor(),
|
|
58
|
+
borderRadius: 4,
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
<Text
|
|
62
|
+
theme="description"
|
|
63
|
+
color={Colors.text.white}
|
|
64
|
+
style={{ fontSize: 11, fontWeight: '600' }}
|
|
65
|
+
>
|
|
66
|
+
{getStatusLabel()}
|
|
67
|
+
</Text>
|
|
68
|
+
</View>
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export default StatusBadge;
|
|
@@ -251,14 +251,6 @@ const NotificationManager = ({
|
|
|
251
251
|
};
|
|
252
252
|
|
|
253
253
|
const handleSendNotification = async (options?:{ test:boolean }) => {
|
|
254
|
-
// Use only group member IDs (no individual player_ids)
|
|
255
|
-
let player_ids_to_send = [...groupMemberIds];
|
|
256
|
-
|
|
257
|
-
if(options?.test){
|
|
258
|
-
//Change to the admin
|
|
259
|
-
player_ids_to_send = [me.player_id]
|
|
260
|
-
}
|
|
261
|
-
|
|
262
254
|
setLoading(true);
|
|
263
255
|
try {
|
|
264
256
|
// Determine final path_name
|
|
@@ -295,26 +287,48 @@ const NotificationManager = ({
|
|
|
295
287
|
last_update_datetime: new Date().toISOString(),
|
|
296
288
|
};
|
|
297
289
|
|
|
298
|
-
//
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
batches.push(player_ids_to_send.slice(i, i + BATCH_SIZE));
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
// Send notifications in batches
|
|
306
|
-
for (let i = 0; i < batches.length; i++) {
|
|
307
|
-
const batch = batches[i];
|
|
308
|
-
if (!batch) continue;
|
|
290
|
+
// Determine if we should use notification_group_id or player_ids
|
|
291
|
+
const useGroupId = selectedGroup &&
|
|
292
|
+
selectedGroup.notification_group_id !== 'custom_group' &&
|
|
293
|
+
!options?.test;
|
|
309
294
|
|
|
310
|
-
|
|
295
|
+
if (useGroupId) {
|
|
296
|
+
// Use notification_group_id - server handles member fetching
|
|
297
|
+
console.log('Sending to group:', selectedGroup!.notification_group_id);
|
|
311
298
|
await NotificationApi.broadcastNotifications(
|
|
312
299
|
completeNotification,
|
|
313
|
-
|
|
300
|
+
[], // Empty player_ids when using group_id
|
|
301
|
+
selectedGroup!.notification_group_id
|
|
314
302
|
);
|
|
315
|
-
}
|
|
303
|
+
} else {
|
|
304
|
+
// Use player_ids - either custom group or test send
|
|
305
|
+
let player_ids_to_send = options?.test
|
|
306
|
+
? [me.player_id]
|
|
307
|
+
: [...groupMemberIds];
|
|
308
|
+
|
|
309
|
+
console.log('Sending to player_ids:', player_ids_to_send.length);
|
|
310
|
+
|
|
311
|
+
// Split into batches of 500
|
|
312
|
+
const BATCH_SIZE = 500;
|
|
313
|
+
const batches: string[][] = [];
|
|
314
|
+
for (let i = 0; i < player_ids_to_send.length; i += BATCH_SIZE) {
|
|
315
|
+
batches.push(player_ids_to_send.slice(i, i + BATCH_SIZE));
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Send notifications in batches
|
|
319
|
+
for (let i = 0; i < batches.length; i++) {
|
|
320
|
+
const batch = batches[i];
|
|
321
|
+
if (!batch) continue;
|
|
316
322
|
|
|
317
|
-
|
|
323
|
+
setSendingProgress({ current: i + 1, total: batches.length });
|
|
324
|
+
await NotificationApi.broadcastNotifications(
|
|
325
|
+
completeNotification,
|
|
326
|
+
batch
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
setSendingProgress(null);
|
|
331
|
+
}
|
|
318
332
|
|
|
319
333
|
if (onComplete && !options?.test) {
|
|
320
334
|
onComplete(completeNotification);
|
|
@@ -333,7 +347,11 @@ const NotificationManager = ({
|
|
|
333
347
|
}
|
|
334
348
|
|
|
335
349
|
const recipientCount = options?.test ? 1 : groupMemberIds.length;
|
|
336
|
-
const recipientMessage = options?.test
|
|
350
|
+
const recipientMessage = options?.test
|
|
351
|
+
? 'Test notification sent to you!'
|
|
352
|
+
: useGroupId
|
|
353
|
+
? `Notification sent successfully to group "${selectedGroup!.name}"!`
|
|
354
|
+
: `Notification sent successfully to ${recipientCount} user${recipientCount !== 1 ? 's' : ''}!`;
|
|
337
355
|
alert(recipientMessage);
|
|
338
356
|
} catch (error) {
|
|
339
357
|
console.error('Error sending notification:', error);
|
|
@@ -915,3 +933,4 @@ const NotificationManager = ({
|
|
|
915
933
|
|
|
916
934
|
export default NotificationManager;
|
|
917
935
|
export { NotificationApi, NotificationHelpers };
|
|
936
|
+
export { default as NotificationManagerTabs } from './NotificationManagerTabs';
|
package/src/index.tsx
CHANGED
|
@@ -73,6 +73,7 @@ import BettorBotDashboard from './BettorBot';
|
|
|
73
73
|
import NotificationManager from './NotificationManager';
|
|
74
74
|
import { NotificationApi, NotificationHelpers } from './NotificationManager/api';
|
|
75
75
|
import BetRouter from './BetRouter/index';
|
|
76
|
+
import NotificationManagerTabs from './NotificationManager/NotificationManagerTabs';
|
|
76
77
|
|
|
77
78
|
// Charts
|
|
78
79
|
export { LivePriceChart, BaseLineChart, TradeChartAdapter } from './Charts';
|
|
@@ -84,6 +85,7 @@ export {
|
|
|
84
85
|
MyAction,
|
|
85
86
|
CreateEmbed,
|
|
86
87
|
ReferralCodeManager,
|
|
88
|
+
NotificationManagerTabs,
|
|
87
89
|
BetRouter,
|
|
88
90
|
CreateEngagement,
|
|
89
91
|
DiscordConnectionManager,
|
package/src/types.d.ts
CHANGED
|
@@ -910,11 +910,12 @@ export interface NotificationGroupProps {
|
|
|
910
910
|
notification_group_id:string,
|
|
911
911
|
name: string,
|
|
912
912
|
description: string,
|
|
913
|
-
grouping_function
|
|
913
|
+
grouping_function?: string,
|
|
914
914
|
player_count:number,
|
|
915
915
|
status: 'active'|'inactive',
|
|
916
916
|
create_datetime:any,
|
|
917
|
-
last_update_datetime: any
|
|
917
|
+
last_update_datetime: any,
|
|
918
|
+
members?: NotificationGroupMemberProps[]
|
|
918
919
|
}
|
|
919
920
|
|
|
920
921
|
export interface NotificationGroupMemberProps {
|
|
@@ -923,10 +924,44 @@ export interface NotificationGroupMemberProps {
|
|
|
923
924
|
batch_number:number,
|
|
924
925
|
player_ids:string[],
|
|
925
926
|
create_datetime: any,
|
|
926
|
-
player_count:number
|
|
927
|
+
player_count:number,
|
|
928
|
+
status: 'active' | 'inactive',
|
|
929
|
+
last_update_datetime: any
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
export type NotificationJobStatus = 'pending' | 'ready' | 'processing' | 'sent' | 'failed' | 'cancelled';
|
|
933
|
+
|
|
934
|
+
export interface NotificationJobProps {
|
|
935
|
+
notification_job_id: string,
|
|
936
|
+
notification_group_id: string,
|
|
937
|
+
notification: PlayerNotificationProps,
|
|
938
|
+
scheduled_time: any,
|
|
939
|
+
status: NotificationJobStatus,
|
|
940
|
+
sent_datetime?: any,
|
|
941
|
+
error_message?: string | null,
|
|
942
|
+
create_datetime: any,
|
|
927
943
|
last_update_datetime: any
|
|
928
944
|
}
|
|
929
945
|
|
|
946
|
+
// UI-specific types for NotificationManager
|
|
947
|
+
export type NotificationManagerTab = 'send' | 'groups' | 'schedule' | 'jobs';
|
|
948
|
+
|
|
949
|
+
export interface GroupFormData {
|
|
950
|
+
notification_group_id?: string,
|
|
951
|
+
name: string,
|
|
952
|
+
description: string,
|
|
953
|
+
grouping_function?: string,
|
|
954
|
+
status: 'active' | 'inactive'
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
export interface JobFormData {
|
|
958
|
+
notification_job_id?: string,
|
|
959
|
+
notification_group_id: string,
|
|
960
|
+
notification: PlayerNotificationProps,
|
|
961
|
+
scheduled_time: Date,
|
|
962
|
+
status: NotificationJobStatus
|
|
963
|
+
}
|
|
964
|
+
|
|
930
965
|
export interface NotificationOptionProps {
|
|
931
966
|
id:string,
|
|
932
967
|
body:string,
|