be-components 6.7.1 → 6.7.3

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 (94) hide show
  1. package/lib/commonjs/Components/Switch.js +30 -7
  2. package/lib/commonjs/Components/Switch.js.map +1 -1
  3. package/lib/commonjs/Components/Themed.js +2 -0
  4. package/lib/commonjs/Components/Themed.js.map +1 -1
  5. package/lib/commonjs/Group/api/index.js +20 -2
  6. package/lib/commonjs/Group/api/index.js.map +1 -1
  7. package/lib/commonjs/Group/components/CreateGroupWizard.js +8 -0
  8. package/lib/commonjs/Group/components/CreateGroupWizard.js.map +1 -1
  9. package/lib/commonjs/Group/components/GroupPlayerActionForm.js +2 -1
  10. package/lib/commonjs/Group/components/GroupPlayerActionForm.js.map +1 -1
  11. package/lib/commonjs/Group/components/ManageGroupForm.js +68 -1
  12. package/lib/commonjs/Group/components/ManageGroupForm.js.map +1 -1
  13. package/lib/commonjs/Group/components/MySettingsForm.js +215 -0
  14. package/lib/commonjs/Group/components/MySettingsForm.js.map +1 -0
  15. package/lib/commonjs/Group/index.js +255 -19
  16. package/lib/commonjs/Group/index.js.map +1 -1
  17. package/lib/commonjs/constants/useColors.js +2 -0
  18. package/lib/commonjs/constants/useColors.js.map +1 -1
  19. package/lib/commonjs/types.d.js.map +1 -1
  20. package/lib/module/Components/Switch.js +26 -3
  21. package/lib/module/Components/Switch.js.map +1 -1
  22. package/lib/module/Components/Themed.js +2 -0
  23. package/lib/module/Components/Themed.js.map +1 -1
  24. package/lib/module/Group/api/index.js +20 -2
  25. package/lib/module/Group/api/index.js.map +1 -1
  26. package/lib/module/Group/components/CreateGroupWizard.js +8 -0
  27. package/lib/module/Group/components/CreateGroupWizard.js.map +1 -1
  28. package/lib/module/Group/components/GroupPlayerActionForm.js +2 -1
  29. package/lib/module/Group/components/GroupPlayerActionForm.js.map +1 -1
  30. package/lib/module/Group/components/ManageGroupForm.js +68 -1
  31. package/lib/module/Group/components/ManageGroupForm.js.map +1 -1
  32. package/lib/module/Group/components/MySettingsForm.js +208 -0
  33. package/lib/module/Group/components/MySettingsForm.js.map +1 -0
  34. package/lib/module/Group/index.js +256 -20
  35. package/lib/module/Group/index.js.map +1 -1
  36. package/lib/module/constants/useColors.js +2 -0
  37. package/lib/module/constants/useColors.js.map +1 -1
  38. package/lib/module/types.d.js.map +1 -1
  39. package/lib/typescript/lib/commonjs/Components/Switch.d.ts +2 -1
  40. package/lib/typescript/lib/commonjs/Components/Switch.d.ts.map +1 -1
  41. package/lib/typescript/lib/commonjs/Components/Themed.d.ts.map +1 -1
  42. package/lib/typescript/lib/commonjs/Group/api/index.d.ts +2 -1
  43. package/lib/typescript/lib/commonjs/Group/api/index.d.ts.map +1 -1
  44. package/lib/typescript/lib/commonjs/Group/components/CreateGroupWizard.d.ts +3 -1
  45. package/lib/typescript/lib/commonjs/Group/components/CreateGroupWizard.d.ts.map +1 -1
  46. package/lib/typescript/lib/commonjs/Group/components/GroupPlayerActionForm.d.ts.map +1 -1
  47. package/lib/typescript/lib/commonjs/Group/components/ManageGroupForm.d.ts.map +1 -1
  48. package/lib/typescript/lib/commonjs/Group/components/MySettingsForm.d.ts +8 -0
  49. package/lib/typescript/lib/commonjs/Group/components/MySettingsForm.d.ts.map +1 -0
  50. package/lib/typescript/lib/commonjs/Group/index.d.ts +3 -1
  51. package/lib/typescript/lib/commonjs/Group/index.d.ts.map +1 -1
  52. package/lib/typescript/lib/commonjs/constants/useColors.d.ts +1 -0
  53. package/lib/typescript/lib/commonjs/constants/useColors.d.ts.map +1 -1
  54. package/lib/typescript/lib/module/Components/Switch.d.ts +3 -3
  55. package/lib/typescript/lib/module/Components/Switch.d.ts.map +1 -1
  56. package/lib/typescript/lib/module/Components/Themed.d.ts.map +1 -1
  57. package/lib/typescript/lib/module/Group/api/index.d.ts +2 -1
  58. package/lib/typescript/lib/module/Group/api/index.d.ts.map +1 -1
  59. package/lib/typescript/lib/module/Group/components/CreateGroupWizard.d.ts +3 -1
  60. package/lib/typescript/lib/module/Group/components/CreateGroupWizard.d.ts.map +1 -1
  61. package/lib/typescript/lib/module/Group/components/GroupPlayerActionForm.d.ts.map +1 -1
  62. package/lib/typescript/lib/module/Group/components/ManageGroupForm.d.ts.map +1 -1
  63. package/lib/typescript/lib/module/Group/components/MySettingsForm.d.ts +8 -0
  64. package/lib/typescript/lib/module/Group/components/MySettingsForm.d.ts.map +1 -0
  65. package/lib/typescript/lib/module/Group/index.d.ts +3 -1
  66. package/lib/typescript/lib/module/Group/index.d.ts.map +1 -1
  67. package/lib/typescript/lib/module/constants/useColors.d.ts +1 -0
  68. package/lib/typescript/lib/module/constants/useColors.d.ts.map +1 -1
  69. package/lib/typescript/src/Components/Switch.d.ts +2 -1
  70. package/lib/typescript/src/Components/Switch.d.ts.map +1 -1
  71. package/lib/typescript/src/Components/Themed.d.ts +1 -1
  72. package/lib/typescript/src/Components/Themed.d.ts.map +1 -1
  73. package/lib/typescript/src/Group/api/index.d.ts +2 -1
  74. package/lib/typescript/src/Group/api/index.d.ts.map +1 -1
  75. package/lib/typescript/src/Group/components/CreateGroupWizard.d.ts +4 -2
  76. package/lib/typescript/src/Group/components/CreateGroupWizard.d.ts.map +1 -1
  77. package/lib/typescript/src/Group/components/ManageGroupForm.d.ts.map +1 -1
  78. package/lib/typescript/src/Group/components/MySettingsForm.d.ts +10 -0
  79. package/lib/typescript/src/Group/components/MySettingsForm.d.ts.map +1 -0
  80. package/lib/typescript/src/Group/index.d.ts +4 -2
  81. package/lib/typescript/src/Group/index.d.ts.map +1 -1
  82. package/lib/typescript/src/constants/useColors.d.ts +1 -0
  83. package/lib/typescript/src/constants/useColors.d.ts.map +1 -1
  84. package/package.json +1 -1
  85. package/src/Components/Switch.tsx +15 -8
  86. package/src/Components/Themed.tsx +2 -1
  87. package/src/Group/api/index.ts +13 -2
  88. package/src/Group/components/CreateGroupWizard.tsx +11 -5
  89. package/src/Group/components/GroupPlayerActionForm.tsx +1 -1
  90. package/src/Group/components/ManageGroupForm.tsx +41 -1
  91. package/src/Group/components/MySettingsForm.tsx +144 -0
  92. package/src/Group/index.tsx +146 -17
  93. package/src/constants/useColors.tsx +2 -0
  94. package/src/types.d.ts +7 -0
@@ -57,6 +57,15 @@ const GroupApi = {
57
57
  return undefined
58
58
  }
59
59
  },
60
+ updateGroupPlayer: async(group_player:GroupPlayerProps):Promise<GroupPlayerProps | undefined> => {
61
+ try {
62
+ const resp = await axios.post(`${SOCIAL_SVC_API}/v2/groups/player/update`, { group_player });
63
+ console.log(resp.data)
64
+ return resp.data.group_player
65
+ } catch (e) {
66
+ return undefined
67
+ }
68
+ },
60
69
  acceptInvite:async(group_player_id:string):Promise<GroupPlayerProps | undefined> => {
61
70
  try {
62
71
  const resp = await axios.post(`${SOCIAL_SVC_API}/v2/groups/player/accept`, { group_player_id });
@@ -89,9 +98,9 @@ const GroupApi = {
89
98
  return undefined
90
99
  }
91
100
  },
92
- join:async(group_id:string):Promise<GroupPlayerProps | undefined> => {
101
+ join:async(group_id:string, invite_code?:string):Promise<GroupPlayerProps | undefined> => {
93
102
  try {
94
- const resp = await axios.post(`${SOCIAL_SVC_API}/v2/groups/player/join`, { group_id });
103
+ const resp = await axios.post(`${SOCIAL_SVC_API}/v2/groups/player/join`, { group_id, invite_code });
95
104
  return resp.data.group_player
96
105
  } catch (e) {
97
106
  return undefined
@@ -230,6 +239,8 @@ const GroupHelpers = {
230
239
  let b_analytcs = player_analytics[b.player_id]
231
240
  let a_analytic = a_analytics ? a_analytics[active_stat as keyof NewOverallAnalytics] ?? 0 : 0
232
241
  let b_analytic = b_analytcs ? b_analytcs[active_stat as keyof NewOverallAnalytics] ?? 0 : 0
242
+ if(!a.leaderboard){ a_analytic = -99999999 }
243
+ if(!b.leaderboard){ b_analytic = -99999999 }
233
244
  return b_active - a_active || parseFloat(b_analytic as string) - parseFloat(a_analytic as string)
234
245
  });
235
246
  return { sorted_players, player_analytics }
@@ -1,7 +1,7 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
  import { Button, Text, TextInput, View } from "../../Components/Themed";
3
3
  import { FlatList, Image, type ViewStyle } from 'react-native';
4
- import type { CreateGroupStepProps, GroupPlayerProps, GroupProps, MyPlayerProps, PublicPlayerProps } from '../../types';
4
+ import type { CreateGroupStepProps, FocusPositionProps, GroupPlayerProps, GroupProps, MyPlayerProps, PublicPlayerProps } from '../../types';
5
5
  import { Icons } from '../../Components';
6
6
  import { useColors } from '../../constants/useColors';
7
7
  import { GroupApi, GroupHelpers } from '../api';
@@ -14,6 +14,8 @@ type CreateGroupWizardProps = {
14
14
  header_style?:ViewStyle,
15
15
  footer_style?:ViewStyle,
16
16
  onInvitePlayers:() => void,
17
+ onFocusPosition?:(pos:FocusPositionProps) => void,
18
+ onCreatedGroup:(group:GroupProps) => void,
17
19
  onRequestAuthenticate:() => void,
18
20
  onClose:() => void,
19
21
  onFinish:(group:GroupProps, group_players:GroupPlayerProps[]) => void
@@ -29,7 +31,7 @@ const wizard_steps:CreateGroupStepProps[] = [
29
31
  { num: 5, step_key: 'success', title: 'Group Successfully Created!', description: 'Your group has been created successfully! Activate it now and start playing with friends.' }
30
32
  ]
31
33
  const sections = ['header', 'intro', 'info', 'input']
32
- const CreateGroupWizard = ({ player, refresh_key, header_style, footer_style, onRequestAuthenticate, onClose, onInvitePlayers, onFinish }:CreateGroupWizardProps) => {
34
+ const CreateGroupWizard = ({ player, refresh_key, header_style, footer_style, onCreatedGroup, onFocusPosition, onRequestAuthenticate, onClose, onInvitePlayers, onFinish }:CreateGroupWizardProps) => {
33
35
  const Colors = useColors();
34
36
  const [ wiz_size, setSize ] = useState({ height: 0, width:0 })
35
37
  const [ wiz_state, setState ] = useState<{
@@ -119,12 +121,13 @@ const CreateGroupWizard = ({ player, refresh_key, header_style, footer_style, on
119
121
  if(draft_group.group_id){
120
122
  new_group = await GroupApi.updateGroup(draft_group);
121
123
  } else {
122
- new_group = await GroupApi.createGroup(draft_group.name, draft_group.description, draft_group.invite_code)
124
+ new_group = await GroupApi.createGroup(draft_group.name, draft_group.description, draft_group.invite_code);
123
125
  }
124
126
  if(!new_group){
125
127
  alert('Unable to create group. Please try again later.')
126
128
  return setState({ ...wiz_state, loading: false })
127
129
  }
130
+ onCreatedGroup(new_group);
128
131
  let next_step = wizard_steps.find(s => s.num == step.num + 1);
129
132
  if(!next_step){ return }
130
133
  setState({
@@ -243,6 +246,7 @@ const CreateGroupWizard = ({ player, refresh_key, header_style, footer_style, on
243
246
  <Text theme='h1' style={{ marginLeft:10 }}>Group Name</Text>
244
247
  <TextInput
245
248
  value={draft_group.name}
249
+ onFocusPosition={onFocusPosition}
246
250
  style={{ margin:10, borderColor:draft_group.name?Colors.text.success:Colors.text.warning }}
247
251
  placeholder='Give your group a name ...'
248
252
  onChangeText={(text) => setState({ ...wiz_state, draft_group: { ...draft_group, name: text } })}
@@ -250,6 +254,7 @@ const CreateGroupWizard = ({ player, refresh_key, header_style, footer_style, on
250
254
  <Text theme='h1' style={{ marginLeft:10 }}>Group Description</Text>
251
255
  <TextInput
252
256
  value={draft_group.description}
257
+ onFocusPosition={onFocusPosition}
253
258
  style={{ margin:10, borderColor:draft_group.description?Colors.text.success:Colors.text.warning }}
254
259
  placeholder='Add a short description ...'
255
260
  onChangeText={(text) => setState({ ...wiz_state, draft_group: { ...draft_group, description: text } })}
@@ -257,6 +262,7 @@ const CreateGroupWizard = ({ player, refresh_key, header_style, footer_style, on
257
262
  <Text theme='h1' style={{ marginLeft:10 }}>Invite Code</Text>
258
263
  <TextInput
259
264
  value={draft_group.invite_code}
265
+ onFocusPosition={onFocusPosition}
260
266
  style={{ margin:10, borderColor:draft_group.invite_code?Colors.text.success:Colors.text.warning }}
261
267
  placeholder='Add a unique code to find your group'
262
268
  onChangeText={(text) => setState({ ...wiz_state, draft_group: { ...draft_group, invite_code: text } })}
@@ -314,8 +320,8 @@ const CreateGroupWizard = ({ player, refresh_key, header_style, footer_style, on
314
320
  }
315
321
 
316
322
  return (
317
- <View style={{ flex:1 }}>
318
- <View style={{ flex:1 }} onLayout={(ev) => {
323
+ <View transparent style={{ flex:1 }}>
324
+ <View transparent style={{ flex:1 }} onLayout={(ev) => {
319
325
  const { height, width } = ev.nativeEvent.layout;
320
326
  setSize({ height, width })
321
327
  }}>
@@ -59,7 +59,7 @@ const GroupPlayerActionForm = ({ me, group, group_player, onResponse, onRequestA
59
59
  return (
60
60
  <View float>
61
61
  <View type='header' style={{ flexDirection:'row', alignItems:'center', padding:10, borderTopRightRadius:8, borderTopLeftRadius:8 }}>
62
- <View transparent style={{ flex:1 }}>
62
+ <View transparent style={{ flex:1, marginRight:10 }}>
63
63
  <Text theme='h1'>{group.name}</Text>
64
64
  <Text theme='description' style={{ marginTop:3 }}>{group.description}</Text>
65
65
  </View>
@@ -6,8 +6,9 @@ import { Icons, Switch, Toggle } from '../../Components';
6
6
  import { GroupApi } from '../api';
7
7
  import ImageUploader from '../../Components/ImageUploader';
8
8
  import { useColors } from '../../constants/useColors';
9
+ import { showConfirmAlert } from '../../Components/ConfirmAlert';
9
10
 
10
- const sections = ['header','toggle','image','information', 'settings', 'invite_button', 'invite', 'options']
11
+ const sections = ['header','toggle','image','information', 'danger', 'settings', 'invite_button', 'invite', 'options']
11
12
  type ManageGroupFormProps = {
12
13
  group:GroupProps,
13
14
  onUpdateGroup:(group:GroupProps) => void,
@@ -46,6 +47,27 @@ const ManageGroupForm = ({ group, onFocusPosition, onUpdateGroup, onClose, onInv
46
47
  setState({ ...manage_state, loading:false })
47
48
  }
48
49
 
50
+ const handleConfirmDelete = () => {
51
+ showConfirmAlert('Are you sure?', 'Once deleted, the group can no longer be activated',
52
+ async() => await handleDelete(),
53
+ () => console.log('')
54
+ )
55
+ }
56
+
57
+ const handleDelete = async() => {
58
+ if(!draft_group){ return }
59
+ if(draft_group.status == 'archived'){ return alert('Goup is already deleted') }
60
+ setState({ ...manage_state, loading: true });
61
+ let deleted_group = await GroupApi.deleteGroup(draft_group.group_id);
62
+ console.log(deleted_group)
63
+ if(!deleted_group){
64
+ setState({ ...manage_state, loading:false })
65
+ return alert('Unable to delete this group. Please refresh and try again')
66
+ }
67
+ onUpdateGroup(deleted_group);
68
+ setState({ ...manage_state, loading:false });
69
+ }
70
+
49
71
  const renderSections = (data:{ item:string, index:number }) => {
50
72
  switch(data.item){
51
73
  case 'header':
@@ -108,6 +130,24 @@ const ManageGroupForm = ({ group, onFocusPosition, onUpdateGroup, onClose, onInv
108
130
  </View>
109
131
  </View>
110
132
  )
133
+ case 'danger':
134
+ return (
135
+ <View float style={{ margin:10 }}>
136
+ <View type='header' style={{ flexDirection:'row', alignItems:'center', padding:10, borderTopRightRadius:8, borderTopLeftRadius:8 }}>
137
+ <View transparent style={{ flex:1 }}>
138
+ <Text theme='h1'>DELETE GROUP</Text>
139
+ <Text theme='description' style={{ marginTop:4 }}>Inactivate and archive this group.</Text>
140
+ </View>
141
+ <Button
142
+ title='DELETE'
143
+ type='error'
144
+ loading={loading}
145
+ style={{ opacity: !loading ? 1 : 0.5, padding:10 }}
146
+ onPress={() => handleConfirmDelete()}
147
+ />
148
+ </View>
149
+ </View>
150
+ )
111
151
  case 'image':
112
152
  if(!draft_group){ return <></> }
113
153
  if(active_toggle != 'information'){ return <></> }
@@ -0,0 +1,144 @@
1
+ import React, { useState } from 'react';
2
+ import { Button, Text, View } from "../../Components/Themed";
3
+ import { FlatList } from 'react-native';
4
+ import type { GroupPlayerProps } from '../../types';
5
+ import { Switch } from '../../Components';
6
+ import { GroupApi } from '../api';
7
+ import { useColors } from '../../constants/useColors';
8
+
9
+ const sections = ['header','settings']
10
+ type MySettingsFormProps = {
11
+ group_player:GroupPlayerProps,
12
+ onUpdateGroupPlayer:(group_player:GroupPlayerProps) => void,
13
+ onClose:() => void
14
+ }
15
+ type GroupSettingProps = {
16
+ group_key:string, label: string, settings: SettingProps[]
17
+ }
18
+ type SettingProps = {
19
+ setting_key:string, label:string, description:string
20
+ }
21
+ const settings = [
22
+ {
23
+ group_key: 'settings', label: 'My Group Settings', settings: [
24
+ { setting_key: 'leaderboard', label: 'Leaderboard', description: "Allow your account to be included in the leaderboard" },
25
+ { setting_key: 'activity', label: 'Show Activity', description: "Show your BettorEdge activity under the activity tab" },
26
+ ]
27
+ },
28
+ {
29
+ group_key: 'notifications', label: 'My Notification Settings', settings: [
30
+ { setting_key: 'chat_notifications', label: 'Chat', description: "Get notified of new messages in this chat" },
31
+ { setting_key: 'member_notifications', label: 'Members', description: "Get notified when new members join the group" },
32
+ { setting_key: 'activity_notifications', label: 'Activity', description: "Get notified of player activity in this group. Once enabled - you can select the individual members to follow from the group screen."}
33
+ ]
34
+ }
35
+ ]
36
+ const MySettingsForm = ({ group_player, onUpdateGroupPlayer, onClose }: MySettingsFormProps ) => {
37
+ const Colors = useColors();
38
+ const [ manage_state, setState ] = useState<{
39
+ loading:string | undefined,
40
+ }>({
41
+ loading:undefined
42
+ });
43
+ const { loading } = manage_state;
44
+
45
+ const handleSave = async(gp:GroupPlayerProps, setting_key:string) => {
46
+ if(!gp){ return }
47
+ if(loading){ return }
48
+ setState({ ...manage_state, loading: setting_key });
49
+ let new_gp = await GroupApi.updateGroupPlayer(gp);
50
+ if(!new_gp){
51
+ alert('Unable to process request')
52
+ return setState({ ...manage_state, loading:undefined })
53
+ }
54
+ onUpdateGroupPlayer(new_gp);
55
+ setState({ ...manage_state, loading: undefined })
56
+ }
57
+
58
+ const renderSettings = (data:{ item: SettingProps, index:number }) => {
59
+ const setting = group_player[data.item.setting_key as keyof GroupPlayerProps]
60
+ const setting_value = setting ? true : false
61
+ const is_loading = loading == data.item.setting_key ? true : false
62
+ return (
63
+ <View transparent type='row' style={{ borderBottomWidth:1, borderColor:Colors.borders.light, padding:10 }}>
64
+ <View transparent style={{ flex:1 }}>
65
+ <Text theme='h1'>{data.item.label}</Text>
66
+ <Text theme='description' style={{ marginTop:3 }}>{data.item.description}</Text>
67
+ </View>
68
+ <Switch loading={is_loading} value={setting_value} switch_type='on_off' onChange={async(val) => {
69
+ if(data.item.setting_key == 'activity_notifications'){
70
+ let new_val = val ? [] : undefined
71
+ console.log(new_val)
72
+ return handleSave({ ...group_player, [data.item.setting_key]: new_val }, data.item.setting_key)
73
+ }
74
+ return handleSave({ ...group_player, [data.item.setting_key]: val }, data.item.setting_key)
75
+ }} />
76
+ </View>
77
+ )
78
+ }
79
+
80
+ const renderGroupSettings = (data:{ item:GroupSettingProps, index:number }) => {
81
+ return (
82
+ <View float style={{ margin:10 }}>
83
+ <View type='header' style={{ flexDirection:'row', alignItems:'center', padding:10, borderTopRightRadius:8, borderTopLeftRadius:8 }}>
84
+ <View transparent style={{ flex:1 }}>
85
+ <Text theme='h1'>{data.item.label}</Text>
86
+ </View>
87
+ </View>
88
+ <View transparent style={{ padding:10 }}>
89
+ <FlatList
90
+ data={data.item.settings}
91
+ key={`${data.item.group_key}_settings`}
92
+ keyExtractor={item => item.setting_key}
93
+ renderItem={renderSettings}
94
+ />
95
+ </View>
96
+ </View>
97
+ )
98
+ }
99
+
100
+ const renderSections = (data:{ item:string, index:number }) => {
101
+ switch(data.item){
102
+ case 'header':
103
+ return (
104
+ <View type='header' style={{ flexDirection:'row', alignItems:'center', padding:10, borderTopRightRadius:8, borderTopLeftRadius:8 }}>
105
+ <View transparent style={{ flex:1 }}>
106
+ <Text theme='h1'>MANAGE YOUR SETTINGS</Text>
107
+ <Text theme='description' style={{ marginTop:3 }}>Use the form below to change your group settings</Text>
108
+ </View>
109
+ <Button
110
+ title='X'
111
+ float
112
+ style={{ padding:10 }}
113
+ onPress={() => onClose()}
114
+ />
115
+ </View>
116
+ )
117
+ case 'settings':
118
+ return (
119
+ <View>
120
+ <FlatList
121
+ data={settings}
122
+ key={'player_settings'}
123
+ keyExtractor={item => item.group_key}
124
+ renderItem={renderGroupSettings}
125
+ />
126
+ </View>
127
+ )
128
+ default: return <></>
129
+ }
130
+ }
131
+
132
+ return (
133
+ <View float style={{ flex:1 }}>
134
+ <FlatList
135
+ data={sections}
136
+ key={'my_settings_sections_manage'}
137
+ keyExtractor={item => item}
138
+ renderItem={renderSections}
139
+ />
140
+ </View>
141
+ )
142
+ }
143
+
144
+ export default MySettingsForm
@@ -1,7 +1,7 @@
1
1
  import React, { useEffect, useState } from 'react';
2
- import { Button, Text, View } from "../Components/Themed"
2
+ import { Button, Text, TextInput, View } from "../Components/Themed"
3
3
  import { GroupApi, GroupHelpers } from './api';
4
- import type { CompetitionPayoutTypeProps, CompetitionPlayerProps, CompetitionProps, CompetitionRecordProps, CompetitionResultProps, CompetitionResultTypeProps, CompetitionTypeProps, EventProps, GroupMessageProps, GroupPlayerProps, GroupProps, MyPlayerProps, NewOverallAnalytics, OrderAnalyticsProps, OrderProps, PollCampaignProps, PostProps, PublicPlayerProps, SquaresCompetitionProps } from '../types';
4
+ import type { CompetitionPayoutTypeProps, CompetitionPlayerProps, CompetitionProps, CompetitionRecordProps, CompetitionResultProps, CompetitionResultTypeProps, CompetitionTypeProps, EventProps, FocusPositionProps, GroupMessageProps, GroupPlayerProps, GroupProps, MyPlayerProps, NewOverallAnalytics, OrderAnalyticsProps, OrderProps, PollCampaignProps, PostProps, PublicPlayerProps, SquaresCompetitionProps } from '../types';
5
5
  import { ActivityIndicator, FlatList, Image } from 'react-native';
6
6
  import { Icons, Toggle } from '../Components';
7
7
  import { useColors } from '../constants/useColors';
@@ -15,11 +15,14 @@ import GroupCTAButton from './components/GroupCTAButton';
15
15
  import PollCampaignCard from '../Engage/components/PollCampaignCard';
16
16
  import SquaresCompetitionCard from '../Engage/components/SquaresCompetitionCard';
17
17
  import { showConfirmAlert } from '../Components/ConfirmAlert';
18
+ import MySettingsForm from './components/MySettingsForm';
18
19
 
19
20
  type GroupComponentProps = {
20
21
  group_id:string,
21
22
  mode:'desktop'|'mobile',
23
+ init_invite_code?:string,
22
24
  refresh_key:string,
25
+ onFocusPosition:(pos:FocusPositionProps) => void,
23
26
  onSelectChat?:(group:GroupProps) => void
24
27
  onInvitePlayer:() => void,
25
28
  onNudgePlayer:(p:PublicPlayerProps, gp:GroupPlayerProps) => void,
@@ -36,7 +39,9 @@ type GroupStateProps = {
36
39
  group?:GroupProps,
37
40
  loading:boolean,
38
41
  editing:boolean,
42
+ invite_code:string,
39
43
  action_loading?:string,
44
+ join_loading:boolean,
40
45
  show_player_status:boolean,
41
46
  active_toggle:string,
42
47
  stats_expanded:boolean,
@@ -44,7 +49,8 @@ type GroupStateProps = {
44
49
  players:PublicPlayerProps[],
45
50
  active_stat?: { stat_key:string, label:string, multiplier:number, prefix?:string, suffix?:string },
46
51
  group_messages: GroupMessageProps[],
47
- my_group_player?:GroupPlayerProps
52
+ my_group_player?:GroupPlayerProps,
53
+ editing_me:boolean
48
54
  }
49
55
  type TimeOptionProps = {
50
56
  to: number,
@@ -61,7 +67,7 @@ const member_stat_options:{ stat_key:string, label:string, multiplier:number, pr
61
67
  { stat_key: 'original_stake', label: 'Betting Volume', multiplier: 1, prefix: '$' }
62
68
  ]
63
69
 
64
- const GroupComponent = ({ refresh_key, group_id, player, mode, onCreateEngagement, onRequestAuthenticate, onShareGroup, onInvitePlayer, onSelectCompetition, onSelectChat, onSelectPlayer, onNudgePlayer, onSelectPollCampaign, onSelectSquaresCompetition } : GroupComponentProps) => {
70
+ const GroupComponent = ({ refresh_key, group_id, player, mode, init_invite_code, onCreateEngagement, onRequestAuthenticate, onFocusPosition, onShareGroup, onInvitePlayer, onSelectCompetition, onSelectChat, onSelectPlayer, onNudgePlayer, onSelectPollCampaign, onSelectSquaresCompetition } : GroupComponentProps) => {
65
71
  const Colors = useColors();
66
72
  const leader_options:TimeOptionProps[] = [
67
73
  { to: moment().subtract(1, 'days').unix(), from: moment().unix(), option: '24_hours', label: '24 Hours' },
@@ -125,14 +131,17 @@ const GroupComponent = ({ refresh_key, group_id, player, mode, onCreateEngagemen
125
131
  loading: false,
126
132
  group_messages: [],
127
133
  editing:false,
134
+ editing_me: false,
128
135
  show_player_status:false,
129
136
  stats_expanded: false,
137
+ invite_code: '',
138
+ join_loading:false,
130
139
  active_toggle: 'members',
131
140
  active_stat: member_stat_options[0],
132
141
  group_players: [],
133
142
  players: []
134
143
  });
135
- const { loading, group, action_loading, stats_expanded, active_toggle, editing,show_player_status, active_stat, group_messages, group_players, my_group_player, players } = group_data;
144
+ const { loading, group, join_loading, action_loading, stats_expanded, active_toggle, editing_me, invite_code, editing,show_player_status, active_stat, group_messages, group_players, my_group_player, players } = group_data;
136
145
  const admin = player?.player_id == group?.group_admin ? true : false;
137
146
  const { sorted_players, player_analytics } = GroupHelpers.sortMembers(group_players, order_analytics, active_stat?.stat_key);
138
147
  const sorted_engagements = GroupHelpers.sortCompetitionAction([], comp_data.active_competitions, [], comp_data.squares_competitions, comp_data.poll_campaigns);
@@ -211,6 +220,7 @@ const GroupComponent = ({ refresh_key, group_id, player, mode, onCreateEngagemen
211
220
  })
212
221
  }
213
222
 
223
+ console.log(my_group_player)
214
224
  const getGroupAnalytics = async(id:string, time_option:TimeOptionProps) => {
215
225
  setGroupAnalytics({ ...group_analytics, loading: true });
216
226
  let analytics = await GroupApi.getGroupAnalytics(id, time_option.to, time_option.from);
@@ -232,15 +242,17 @@ const GroupComponent = ({ refresh_key, group_id, player, mode, onCreateEngagemen
232
242
  }
233
243
  let player_ids = [ ...new Set(g_data.group_players.map(p => p.player_id).concat(g_data.group_messages.map(m => m.player_id)))]
234
244
  let plyers = await GroupApi.getPlayersByIds(player_ids);
245
+ let my_gp = g_data.my_group_player && g_data.my_group_player.status == 'inactive' ? undefined : g_data.my_group_player
235
246
  setGroupData({
236
247
  ...group_data,
237
248
  loading: false,
238
249
  players: plyers,
250
+ invite_code: init_invite_code ?? '',
239
251
  group: g_data.group,
240
- show_player_status: !g_data.my_group_player ? true : g_data.my_group_player.status == 'active' ? false : true, //Show to join if we can
252
+ show_player_status: g_data.group.invite_only ? false : my_gp ? false : true, //Show to join if we can
241
253
  group_messages: g_data.group_messages,
242
254
  group_players: g_data.group_players,
243
- my_group_player: g_data.my_group_player
255
+ my_group_player: my_gp
244
256
  });
245
257
  }
246
258
 
@@ -248,10 +260,14 @@ const GroupComponent = ({ refresh_key, group_id, player, mode, onCreateEngagemen
248
260
  const pl = players.find(p => p.player_id == data.item.player_id);
249
261
  if(!pl){ return <></> }
250
262
  const player_analytic = player_analytics[data.item.player_id]
251
- const analytic = player_analytic ? player_analytic[active_stat?.stat_key as keyof NewOverallAnalytics] : 0
263
+ const analytic = !data.item.leaderboard ? 0 : player_analytic ? player_analytic[active_stat?.stat_key as keyof NewOverallAnalytics] : 0
252
264
  const is_loading = action_loading == data.item.group_player_id ? true : false
265
+
266
+ const show_activity_check = player?.player_id == data.item.player_id ? false : my_group_player?.status == 'active' && my_group_player.activity_notifications && data.item.activity ? true : false
267
+ const following = my_group_player?.activity_notifications?.find(id => id == data.item.player_id) ? true : false
268
+
253
269
  return (
254
- <Button transparent style={{ flexDirection:'row', alignItems:'center', padding:10, borderBottomWidth:1, borderColor:Colors.borders.light, borderRadius:0 }} onPress={() => onSelectPlayer(pl)}>
270
+ <View transparent style={{ flexDirection:'row', alignItems:'center', padding:10, borderBottomWidth:1, borderColor:Colors.borders.light, borderRadius:0 }}>
255
271
  {admin && data.item.player_id != player?.player_id?
256
272
  <Button
257
273
  title='X'
@@ -278,20 +294,40 @@ const GroupComponent = ({ refresh_key, group_id, player, mode, onCreateEngagemen
278
294
  }}
279
295
  />
280
296
  :<></>}
281
- <View float style={{ borderRadius:100, padding:2 }}>
297
+ <Button
298
+ disabled={!show_activity_check || my_group_player?.player_id == data.item.player_id}
299
+ onPress={async() => {
300
+ if(!my_group_player){ return }
301
+ let new_activity = my_group_player.activity_notifications ?? []
302
+ if(!following){ new_activity = new_activity.concat(data.item.player_id) }
303
+ else { new_activity = new_activity.filter(id => id != data.item.player_id) }
304
+ let new_gp = await GroupApi.updateGroupPlayer({ ...my_group_player, activity_notifications: new_activity });
305
+ if(!new_gp){ return alert('Unable to update') }
306
+ setGroupData({
307
+ ...group_data,
308
+ group_players: group_players.filter(gp => gp.group_player_id != new_gp?.group_player_id).concat(new_gp),
309
+ my_group_player: new_gp
310
+ })
311
+ }}
312
+ float
313
+ style={{ borderRadius:100, padding:2, borderColor:following?Colors.text.success:show_activity_check?Colors.text.warning:Colors.borders.light }}>
282
314
  <Image
283
315
  source={{ uri: pl.profile_pic }}
284
316
  style={{ height:45, width:45, borderRadius:100 }}
285
317
  resizeMode='contain'
286
318
  />
287
- </View>
288
- <View transparent style={{ flex:1, marginLeft:10 }}>
319
+ </Button>
320
+ <Button transparent style={{ flex:1, marginLeft:10, padding:0 }} onPress={() => onSelectPlayer(pl)}>
289
321
  <Text theme='h1'>@{pl.username}</Text>
290
322
  <Text theme='description' style={{ marginTop:3 }}>{data.item.status == 'active' ? 'Joined' : 'Invited'} {moment(data.item.last_update_datetime).fromNow()}</Text>
291
- </View>
323
+ </Button>
292
324
  {active_stat && player_analytic && data.item.status == 'active' ?
293
325
  <View style={{ alignItems:'flex-end' }}>
326
+ {data.item.leaderboard ?
294
327
  <Text theme='h1'>{active_stat.prefix}{(parseFloat(analytic as string) * active_stat.multiplier).toFixed(2)}{active_stat.suffix}</Text>
328
+ :
329
+ <Icons.LockClosedIcon size={14} color={Colors.text.h1} />
330
+ }
295
331
  <Text theme='light' style={{ marginTop:3 }}>{active_stat.label}</Text>
296
332
  </View>
297
333
  :<></>}
@@ -328,7 +364,7 @@ const GroupComponent = ({ refresh_key, group_id, player, mode, onCreateEngagemen
328
364
  }}
329
365
  />
330
366
  :<></>}
331
- </Button>
367
+ </View>
332
368
  )
333
369
  }
334
370
 
@@ -430,7 +466,14 @@ const GroupComponent = ({ refresh_key, group_id, player, mode, onCreateEngagemen
430
466
  <Button float style={{ padding:10, marginLeft:10 }} onPress={() => setGroupData({ ...group_data, editing:true })}>
431
467
  <Icons.EditIcon size={14} color={Colors.text.h1} />
432
468
  </Button>
433
- :<></>}
469
+ :
470
+ <Button
471
+ type='success'
472
+ style={{ padding:10, marginLeft:10 }}
473
+ title='INVITE'
474
+ onPress={() => onInvitePlayer()}
475
+ />
476
+ }
434
477
  </View>
435
478
  )
436
479
  case 'chat':
@@ -466,6 +509,7 @@ const GroupComponent = ({ refresh_key, group_id, player, mode, onCreateEngagemen
466
509
  </View>
467
510
  )
468
511
  case 'me':
512
+ if(!group) { return <></> }
469
513
  if(active_toggle != 'members'){ return <></> }
470
514
  return (
471
515
  <View type='row' style={{ padding:10 }}>
@@ -482,6 +526,11 @@ const GroupComponent = ({ refresh_key, group_id, player, mode, onCreateEngagemen
482
526
  <Text theme='h1'>@{player.username}</Text>
483
527
  <Text theme='description' style={{ marginTop:3 }}>Member since {moment(player.create_datetime).format('MM/DD/YYYY')}</Text>
484
528
  </View>
529
+ {my_group_player?.status == 'active' ?
530
+ <Button float style={{ padding:10, marginRight:10 }} onPress={() => setGroupData({ ...group_data, editing_me: true })}>
531
+ <Icons.SettingsIcon size={12} color={Colors.text.h1} />
532
+ </Button>
533
+ :<></>}
485
534
  {my_group_player?.status == 'invited' ?
486
535
  <Button
487
536
  type='action'
@@ -585,6 +634,11 @@ const GroupComponent = ({ refresh_key, group_id, player, mode, onCreateEngagemen
585
634
  }}
586
635
  />
587
636
  </View>
637
+ {my_group_player && my_group_player.activity_notifications ?
638
+ <View style={{ padding:10 }}>
639
+ <Text theme='description' color={Colors.text.warning}>If a player is sharing their activity, their picture is outlined in orange. You can select the player's profile picture to get notified of their activity.</Text>
640
+ </View>
641
+ :<></>}
588
642
  <View style={{ padding:10 }}>
589
643
  <FlatList
590
644
  data={sorted_players}
@@ -654,12 +708,28 @@ const GroupComponent = ({ refresh_key, group_id, player, mode, onCreateEngagemen
654
708
  <View type='blur' style={mode == 'desktop'?{ justifyContent:'center', alignItems:'center', width: 500, height:500 }: { flex:1, justifyContent:'flex-end', padding:10 }}>
655
709
  <ManageGroupForm
656
710
  group={group}
711
+ onFocusPosition={onFocusPosition}
657
712
  onInvitePlayer={() => {
658
713
  setGroupData({ ...group_data, editing: false })
659
714
  onInvitePlayer();
660
715
  }}
661
716
  onClose={() => setGroupData({ ...group_data, editing: false })}
662
- onUpdateGroup={(g) => setGroupData({ ...group_data, group: g })}
717
+ onUpdateGroup={(g) => setGroupData({ ...group_data, group: g, editing: g.status == 'archived' ? false : true })}
718
+ />
719
+ </View>
720
+ </View>
721
+ :<></>}
722
+ {editing_me && group && my_group_player ?
723
+ <View type='blur' style={{ position:'absolute', top:0, left:0, right:0, bottom:0 }}>
724
+ <View type='blur' style={mode == 'desktop'?{ justifyContent:'center', alignItems:'center', width: 500, height:500 }: { flex:1, justifyContent:'flex-end', padding:10 }}>
725
+ <MySettingsForm
726
+ group_player={my_group_player}
727
+ onClose={() => setGroupData({ ...group_data, editing_me: false })}
728
+ onUpdateGroupPlayer={(gp) => setGroupData({
729
+ ...group_data,
730
+ group_players: group_players.filter(p => p.group_player_id != gp.group_player_id).concat(gp),
731
+ my_group_player: { ...gp }
732
+ })}
663
733
  />
664
734
  </View>
665
735
  </View>
@@ -676,7 +746,7 @@ const GroupComponent = ({ refresh_key, group_id, player, mode, onCreateEngagemen
676
746
  setGroupData({
677
747
  ...group_data,
678
748
  group_players: group_players.filter(gp => gp.group_player_id != new_gp.group_player_id).concat(new_gp),
679
- my_group_player: new_gp,
749
+ my_group_player: new_gp.status == 'inactive' ? undefined: new_gp,
680
750
  show_player_status: false
681
751
  })
682
752
  }}
@@ -685,6 +755,65 @@ const GroupComponent = ({ refresh_key, group_id, player, mode, onCreateEngagemen
685
755
  </View>
686
756
  </View>
687
757
  :<></>}
758
+ {group && group.status == 'archived' ?
759
+ <View type='blur' style={{ position:'absolute', top:0, left:0, right:0, bottom:0, justifyContent:'center', alignItems:'center' }}>
760
+ <View float style={{ padding:10 }}>
761
+ <Text theme='h1' textAlign='center'>GROUP NOT ACTIVE</Text>
762
+ <Text theme='description' textAlign='center' style={{ marginTop:5 }}>This group have been deleted by the admin</Text>
763
+ </View>
764
+ </View>
765
+ :<></>}
766
+ {group && group.invite_only && !my_group_player ?
767
+ <View type='dark_blur' style={{ position:'absolute', top:0, left:0, right:0, bottom:0, justifyContent:'flex-end', margin:10 }}>
768
+ <View float>
769
+ <View type='header' style={{ flexDirection:'row', alignItems:'center', padding:10, borderTopRightRadius:8, borderTopLeftRadius:8 }}>
770
+ <Image
771
+ source={{ uri: group.group_image?.url }}
772
+ style={{ height:50, width:50 }}
773
+ resizeMode='cover'
774
+ />
775
+ <View transparent style={{ flex:1, marginLeft:10, marginRight:10 }}>
776
+ <Text theme='h1'>{group.name}</Text>
777
+ <Text theme='warning' style={{ marginTop:3 }}>This is a private group</Text>
778
+ </View>
779
+ <Icons.LockClosedIcon size={20} color={Colors.text.error} />
780
+ </View>
781
+ <View transparent style={{ padding:20 }}>
782
+ <Text theme='h1'>Have an Invite Code?</Text>
783
+ <View transparent type='row' style={{ marginTop:10 }}>
784
+ <TextInput
785
+ style={{flex:1 }}
786
+ onFocusPosition={onFocusPosition}
787
+ placeholder='Enter Code Here...'
788
+ value={invite_code}
789
+ onChangeText={(code) => setGroupData({ ...group_data, invite_code: code })}
790
+ />
791
+ <Button
792
+ type='success'
793
+ title='JOIN'
794
+ disabled={!invite_code}
795
+ style={{ marginLeft:5, opacity: join_loading || !invite_code ? 0.5: 1 }}
796
+ loading={join_loading}
797
+ onPress={async() => {
798
+ setGroupData({ ...group_data, join_loading:true });
799
+ let new_player = await GroupApi.join(group_id, invite_code);
800
+ if(!new_player){
801
+ alert('The code entered is not valid. Please reach out to the admin for the correct code');
802
+ return setGroupData({ ...group_data, join_loading: false })
803
+ }
804
+ setGroupData({
805
+ ...group_data,
806
+ join_loading: false
807
+ });
808
+ getGroupData(group_id);
809
+ //try to join this group!
810
+ }}
811
+ />
812
+ </View>
813
+ </View>
814
+ </View>
815
+ </View>
816
+ :<></>}
688
817
  </View>
689
818
  )
690
819
  }