be-components 1.0.0 → 1.0.2

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 (120) hide show
  1. package/lib/commonjs/AdServer/components/CompanyAdCard.js +28 -2
  2. package/lib/commonjs/AdServer/components/CompanyAdCard.js.map +1 -1
  3. package/lib/commonjs/AdServer/index.js +15 -0
  4. package/lib/commonjs/AdServer/index.js.map +1 -1
  5. package/lib/commonjs/Bracket/api/index.js +412 -0
  6. package/lib/commonjs/Bracket/api/index.js.map +1 -0
  7. package/lib/commonjs/Bracket/components/BracketCompetitionCard.js +525 -0
  8. package/lib/commonjs/Bracket/components/BracketCompetitionCard.js.map +1 -0
  9. package/lib/commonjs/Bracket/components/BracketCompetitionSelector.js +208 -0
  10. package/lib/commonjs/Bracket/components/BracketCompetitionSelector.js.map +1 -0
  11. package/lib/commonjs/Bracket/components/BracketPlay/BracketNavigator.js +142 -0
  12. package/lib/commonjs/Bracket/components/BracketPlay/BracketNavigator.js.map +1 -0
  13. package/lib/commonjs/Bracket/components/BracketPlay/BracketRound.js +91 -0
  14. package/lib/commonjs/Bracket/components/BracketPlay/BracketRound.js.map +1 -0
  15. package/lib/commonjs/Bracket/components/BracketPlay/RoundEvent.js +416 -0
  16. package/lib/commonjs/Bracket/components/BracketPlay/RoundEvent.js.map +1 -0
  17. package/lib/commonjs/Bracket/components/BracketPlay/index.js +346 -0
  18. package/lib/commonjs/Bracket/components/BracketPlay/index.js.map +1 -0
  19. package/lib/commonjs/Bracket/components/BracketSelector.js +138 -0
  20. package/lib/commonjs/Bracket/components/BracketSelector.js.map +1 -0
  21. package/lib/commonjs/Bracket/components/CompetitionLeaderboard.js +237 -0
  22. package/lib/commonjs/Bracket/components/CompetitionLeaderboard.js.map +1 -0
  23. package/lib/commonjs/Bracket/components/JoinCompetitionCard.js +108 -0
  24. package/lib/commonjs/Bracket/components/JoinCompetitionCard.js.map +1 -0
  25. package/lib/commonjs/Bracket/components/PlayerBracketManager.js +452 -0
  26. package/lib/commonjs/Bracket/components/PlayerBracketManager.js.map +1 -0
  27. package/lib/commonjs/Bracket/components/PlayerBrackets.js +179 -0
  28. package/lib/commonjs/Bracket/components/PlayerBrackets.js.map +1 -0
  29. package/lib/commonjs/Bracket/components/RoomMenu.js +118 -0
  30. package/lib/commonjs/Bracket/components/RoomMenu.js.map +1 -0
  31. package/lib/commonjs/Bracket/index.js +338 -0
  32. package/lib/commonjs/Bracket/index.js.map +1 -0
  33. package/lib/commonjs/index.js +7 -0
  34. package/lib/commonjs/index.js.map +1 -1
  35. package/lib/module/AdServer/components/CompanyAdCard.js +28 -2
  36. package/lib/module/AdServer/components/CompanyAdCard.js.map +1 -1
  37. package/lib/module/AdServer/index.js +15 -0
  38. package/lib/module/AdServer/index.js.map +1 -1
  39. package/lib/module/Bracket/api/index.js +406 -0
  40. package/lib/module/Bracket/api/index.js.map +1 -0
  41. package/lib/module/Bracket/components/BracketCompetitionCard.js +516 -0
  42. package/lib/module/Bracket/components/BracketCompetitionCard.js.map +1 -0
  43. package/lib/module/Bracket/components/BracketCompetitionSelector.js +199 -0
  44. package/lib/module/Bracket/components/BracketCompetitionSelector.js.map +1 -0
  45. package/lib/module/Bracket/components/BracketPlay/BracketNavigator.js +135 -0
  46. package/lib/module/Bracket/components/BracketPlay/BracketNavigator.js.map +1 -0
  47. package/lib/module/Bracket/components/BracketPlay/BracketRound.js +84 -0
  48. package/lib/module/Bracket/components/BracketPlay/BracketRound.js.map +1 -0
  49. package/lib/module/Bracket/components/BracketPlay/RoundEvent.js +409 -0
  50. package/lib/module/Bracket/components/BracketPlay/RoundEvent.js.map +1 -0
  51. package/lib/module/Bracket/components/BracketPlay/index.js +337 -0
  52. package/lib/module/Bracket/components/BracketPlay/index.js.map +1 -0
  53. package/lib/module/Bracket/components/BracketSelector.js +131 -0
  54. package/lib/module/Bracket/components/BracketSelector.js.map +1 -0
  55. package/lib/module/Bracket/components/CompetitionLeaderboard.js +228 -0
  56. package/lib/module/Bracket/components/CompetitionLeaderboard.js.map +1 -0
  57. package/lib/module/Bracket/components/JoinCompetitionCard.js +101 -0
  58. package/lib/module/Bracket/components/JoinCompetitionCard.js.map +1 -0
  59. package/lib/module/Bracket/components/PlayerBracketManager.js +443 -0
  60. package/lib/module/Bracket/components/PlayerBracketManager.js.map +1 -0
  61. package/lib/module/Bracket/components/PlayerBrackets.js +172 -0
  62. package/lib/module/Bracket/components/PlayerBrackets.js.map +1 -0
  63. package/lib/module/Bracket/components/RoomMenu.js +111 -0
  64. package/lib/module/Bracket/components/RoomMenu.js.map +1 -0
  65. package/lib/module/Bracket/index.js +329 -0
  66. package/lib/module/Bracket/index.js.map +1 -0
  67. package/lib/module/index.js +2 -1
  68. package/lib/module/index.js.map +1 -1
  69. package/lib/typescript/src/AdServer/components/CompanyAdCard.d.ts +5 -1
  70. package/lib/typescript/src/AdServer/components/CompanyAdCard.d.ts.map +1 -1
  71. package/lib/typescript/src/AdServer/index.d.ts.map +1 -1
  72. package/lib/typescript/src/Bracket/api/index.d.ts +107 -0
  73. package/lib/typescript/src/Bracket/api/index.d.ts.map +1 -0
  74. package/lib/typescript/src/Bracket/components/BracketCompetitionCard.d.ts +30 -0
  75. package/lib/typescript/src/Bracket/components/BracketCompetitionCard.d.ts.map +1 -0
  76. package/lib/typescript/src/Bracket/components/BracketCompetitionSelector.d.ts +12 -0
  77. package/lib/typescript/src/Bracket/components/BracketCompetitionSelector.d.ts.map +1 -0
  78. package/lib/typescript/src/Bracket/components/BracketPlay/BracketNavigator.d.ts +14 -0
  79. package/lib/typescript/src/Bracket/components/BracketPlay/BracketNavigator.d.ts.map +1 -0
  80. package/lib/typescript/src/Bracket/components/BracketPlay/BracketRound.d.ts +24 -0
  81. package/lib/typescript/src/Bracket/components/BracketPlay/BracketRound.d.ts.map +1 -0
  82. package/lib/typescript/src/Bracket/components/BracketPlay/RoundEvent.d.ts +22 -0
  83. package/lib/typescript/src/Bracket/components/BracketPlay/RoundEvent.d.ts.map +1 -0
  84. package/lib/typescript/src/Bracket/components/BracketPlay/index.d.ts +19 -0
  85. package/lib/typescript/src/Bracket/components/BracketPlay/index.d.ts.map +1 -0
  86. package/lib/typescript/src/Bracket/components/BracketSelector.d.ts +12 -0
  87. package/lib/typescript/src/Bracket/components/BracketSelector.d.ts.map +1 -0
  88. package/lib/typescript/src/Bracket/components/CompetitionLeaderboard.d.ts +14 -0
  89. package/lib/typescript/src/Bracket/components/CompetitionLeaderboard.d.ts.map +1 -0
  90. package/lib/typescript/src/Bracket/components/JoinCompetitionCard.d.ts +11 -0
  91. package/lib/typescript/src/Bracket/components/JoinCompetitionCard.d.ts.map +1 -0
  92. package/lib/typescript/src/Bracket/components/PlayerBracketManager.d.ts +18 -0
  93. package/lib/typescript/src/Bracket/components/PlayerBracketManager.d.ts.map +1 -0
  94. package/lib/typescript/src/Bracket/components/PlayerBrackets.d.ts +17 -0
  95. package/lib/typescript/src/Bracket/components/PlayerBrackets.d.ts.map +1 -0
  96. package/lib/typescript/src/Bracket/components/RoomMenu.d.ts +14 -0
  97. package/lib/typescript/src/Bracket/components/RoomMenu.d.ts.map +1 -0
  98. package/lib/typescript/src/Bracket/index.d.ts +12 -0
  99. package/lib/typescript/src/Bracket/index.d.ts.map +1 -0
  100. package/lib/typescript/src/index.d.ts +2 -1
  101. package/lib/typescript/src/index.d.ts.map +1 -1
  102. package/package.json +1 -1
  103. package/src/AdServer/components/CompanyAdCard.tsx +14 -3
  104. package/src/AdServer/index.tsx +6 -1
  105. package/src/Bracket/api/index.ts +351 -0
  106. package/src/Bracket/components/BracketCompetitionCard.tsx +312 -0
  107. package/src/Bracket/components/BracketCompetitionSelector.tsx +123 -0
  108. package/src/Bracket/components/BracketPlay/BracketNavigator.tsx +75 -0
  109. package/src/Bracket/components/BracketPlay/BracketRound.tsx +83 -0
  110. package/src/Bracket/components/BracketPlay/RoundEvent.tsx +250 -0
  111. package/src/Bracket/components/BracketPlay/index.tsx +243 -0
  112. package/src/Bracket/components/BracketSelector.tsx +87 -0
  113. package/src/Bracket/components/CompetitionLeaderboard.tsx +165 -0
  114. package/src/Bracket/components/JoinCompetitionCard.tsx +66 -0
  115. package/src/Bracket/components/PlayerBracketManager.tsx +229 -0
  116. package/src/Bracket/components/PlayerBrackets.tsx +119 -0
  117. package/src/Bracket/components/RoomMenu.tsx +69 -0
  118. package/src/Bracket/index.tsx +269 -0
  119. package/src/index.tsx +3 -1
  120. package/src/types.d.ts +173 -0
@@ -0,0 +1,243 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { View, ActivityIndicator, TouchableOpacity, ScrollView, Image } from "react-native";
3
+ import type { AthleteProps, BracketGroupProps, BracketProps, BracketRoundProps, CompetitionPlayerBracketProps, EventProps, PlayerBracketPickProps, PlayerBracketProps, RoundEventProps, TeamProps } from '../../../types';
4
+ import { BracketApi, BracketComeptitionApi } from '../../api';
5
+ import { Button, Icons, Text } from '../../../Components';
6
+ import Colors from '../../../constants/colors';
7
+ import BracketRoundSection from './BracketRound';
8
+ import BracketNavigator from './BracketNavigator';
9
+ import { view_styles } from '../../../constants/styles';
10
+
11
+ type BracketPlayProps = {
12
+ visible: boolean,
13
+ room_size:{ width:number, height:number },
14
+ player_bracket_id?:string,
15
+ bracket_id?:string,
16
+ player_id?:string,
17
+ onRequestAuthenticate: () => void,
18
+ onChangePlayerBracket: (bracket_id:string) => void,
19
+ onClose: () => void
20
+ onPlayerBracketUpdate: (pb:PlayerBracketProps, cpbs:CompetitionPlayerBracketProps[]) => void,
21
+ }
22
+ const MIN_ROUND_WIDTH = 175
23
+ const MAX_ROUND_WIDTH = 200;
24
+ const BracketPlay = ({ visible, player_id, room_size, bracket_id, player_bracket_id, onClose, onPlayerBracketUpdate, onChangePlayerBracket, onRequestAuthenticate }:BracketPlayProps) => {
25
+ const [ show_filter, setShowFilter ] = useState(true);
26
+ const [ play_data, setPlayData ] = useState<{
27
+ loading:boolean,
28
+ player_bracket?:PlayerBracketProps,
29
+ player_bracket_picks:PlayerBracketPickProps[]
30
+ }>({
31
+ loading:false,
32
+ player_bracket_picks: []
33
+ });
34
+ const [ bracket_data, setData ] = useState<{
35
+ loaded:boolean,
36
+ bracket?:BracketProps,
37
+ bracket_groups:BracketGroupProps[],
38
+ bracket_rounds:BracketRoundProps[],
39
+ round_events:RoundEventProps[],
40
+ teams:TeamProps[],
41
+ athletes:AthleteProps[],
42
+ selected_group?:BracketGroupProps,
43
+ selected_round?:BracketRoundProps,
44
+ events:EventProps[]
45
+ }>({
46
+ loaded: false,
47
+ bracket_groups: [],
48
+ bracket_rounds: [],
49
+ round_events: [],
50
+ teams: [],
51
+ athletes: [],
52
+ events: []
53
+ })
54
+ const { player_bracket, player_bracket_picks } = play_data;
55
+ const { bracket_groups, bracket_rounds, round_events, bracket, teams, athletes, selected_group, selected_round } = bracket_data;
56
+
57
+ const champion_team = player_bracket?.champion_id_type == 'team' ? teams.find(t => t.team_id == player_bracket?.champion_id) : undefined
58
+ const champion_athlete = player_bracket?.champion_id_type == 'athlete' ? athletes.find(a => a.athlete_id == player_bracket?.champion_id) : undefined
59
+
60
+ let visible_rounds = bracket_rounds
61
+ if(selected_round){
62
+ let next_round = bracket_rounds.findIndex(r => r.bracket_round_id == selected_round.bracket_round_id);
63
+ visible_rounds = bracket_rounds.filter((_, i) => i == next_round || i == next_round + 1)
64
+ }
65
+
66
+ let round_width = (room_size.width / 2) - 15
67
+ if(round_width < MIN_ROUND_WIDTH){ round_width = MIN_ROUND_WIDTH }
68
+ if(round_width > MAX_ROUND_WIDTH){ round_width = MAX_ROUND_WIDTH }
69
+ useEffect(() => {
70
+ if(!bracket_id || !visible){ return }
71
+ getData(bracket_id)
72
+ },[visible, bracket_id])
73
+
74
+ useEffect(() => {
75
+ if(!player_bracket_id){ return }
76
+ getPlayData(player_bracket_id);
77
+ },[player_bracket_id])
78
+
79
+ const getPlayData = async(id:string) => {
80
+ const resp = await BracketComeptitionApi.getPlayerBracketById(id)
81
+ setPlayData({
82
+ ...play_data,
83
+ loading:false,
84
+ player_bracket_picks: resp.player_bracket_picks,
85
+ player_bracket:resp.player_bracket
86
+ })
87
+ }
88
+
89
+ const handlePick = async(pick:PlayerBracketPickProps) => {
90
+ if(!player_id){ return onRequestAuthenticate() }
91
+ if(!bracket_id){ return }
92
+ let new_pick:PlayerBracketPickProps = { ...pick, bracket_id: bracket_id }
93
+ if(!player_bracket){
94
+ const new_pb = await BracketComeptitionApi.createPlayerBracket({
95
+ player_bracket_id: '',
96
+ player_id: '',
97
+ bracket_name: `My Bracket ${Math.random()}`,
98
+ create_datetime: '', last_update_datetime: '',
99
+ bracket_id: bracket_id,
100
+ completion_pct: 0,
101
+ completion_status: 'inprogress',
102
+ status: 'active'
103
+ })
104
+ new_pick.player_bracket_id = new_pb.player_bracket_id
105
+ } else {
106
+ new_pick.player_bracket_id = player_bracket.player_bracket_id
107
+ }
108
+ const resp = await BracketComeptitionApi.savePick(new_pick);
109
+ setPlayData({
110
+ ...play_data,
111
+ player_bracket: resp.player_bracket,
112
+ player_bracket_picks: player_bracket_picks.filter(pbp => !resp.player_bracket_picks.find(npb => npb.player_bracket_pick_id == pbp.player_bracket_pick_id)).concat(resp.player_bracket_picks.filter(pb => pb.status != 'deleted'))
113
+ })
114
+ onPlayerBracketUpdate(resp.player_bracket, resp.competition_player_brackets)
115
+ }
116
+ const getData = async(id:string) => {
117
+ const b = await BracketApi.getBracketById(id);
118
+ let team_ids:string[] = []
119
+ let athlete_ids:string[] = []
120
+
121
+ b.round_events.map(re => {
122
+ if(re.away_side_type == 'team' && re.away_side_id){ team_ids.push(re.away_side_id) }
123
+ if(re.home_side_type == 'team' && re.home_side_id){ team_ids.push(re.home_side_id) }
124
+ if(re.away_side_type == 'athlete' && re.away_side_id){ athlete_ids.push(re.away_side_id) }
125
+ if(re.home_side_type == 'athlete' && re.home_side_id){ athlete_ids.push(re.home_side_id) }
126
+ })
127
+ let ts = await BracketApi.getTeamsByIds(team_ids);
128
+ let aths = await BracketApi.getAthletesByIds(athlete_ids);
129
+
130
+ setData({
131
+ ...bracket_data,
132
+ bracket: b.bracket,
133
+ bracket_groups: b.bracket_groups,
134
+ bracket_rounds: b.bracket_rounds,
135
+ round_events: b.round_events,
136
+ teams: ts,
137
+ athletes: aths
138
+ })
139
+ }
140
+
141
+ const renderBracketRounds = (data: { item:BracketRoundProps, index:number }) => {
142
+ return (
143
+ <BracketRoundSection
144
+ bracket_round={data.item}
145
+ round_events={round_events}
146
+ teams={teams}
147
+ athletes={athletes}
148
+ player_bracket_picks={player_bracket_picks}
149
+ width={round_width}
150
+ orientation='right'
151
+ onPick={(pick) => handlePick(pick)}
152
+ bracket_size={room_size}
153
+
154
+ />
155
+ )
156
+ }
157
+
158
+
159
+ if(!visible){ return <></> }
160
+
161
+ if(!bracket){
162
+ return (
163
+ <View>
164
+ <ActivityIndicator size='large' style={{ padding:20, alignSelf:'center' }} color={Colors.brand.midnight} />
165
+ </View>
166
+ )
167
+ }
168
+ return (
169
+ <View style={{ flex:1 }}>
170
+ <View style={{ zIndex:10, flexDirection:'row', alignItems:'center', padding:20, borderBottomWidth:1, borderColor:Colors.shades.shade100 }}>
171
+ <TouchableOpacity style={{ flex:1, flexDirection:'row', alignItems: 'center' }} onPress={() => onClose()}>
172
+ <Icons.ChevronIcon direction='left' size={12} color={Colors.brand.midnight} />
173
+ <View style={{ flex:1, marginLeft:20, marginRight:10 }}>
174
+ <Text size={18} color={Colors.brand.midnight} weight='bold'>{bracket.bracket_name}</Text>
175
+ </View>
176
+ </TouchableOpacity>
177
+ <View style={{ zIndex:10 }}>
178
+ <Button
179
+ title='Filter'
180
+ backgroundColor={Colors.brand.electric}
181
+ title_color={Colors.shades.white}
182
+ onPress={() => setShowFilter(true)}
183
+ />
184
+ {show_filter ?
185
+ <View style={{ position:'absolute', top:5, right:5, backgroundColor:Colors.shades.white, borderRadius:8, ...view_styles.float }}>
186
+ <BracketNavigator
187
+ bracket_groups={bracket_groups}
188
+ bracket_rounds={bracket_rounds}
189
+ selected_group={selected_group}
190
+ selected_round={selected_round}
191
+ onSelectGroup={(g) => setData({ ...bracket_data, selected_group: selected_group?.bracket_group_id == g.bracket_group_id ? undefined : g })}
192
+ onSelectRound={(r) => setData({ ...bracket_data, selected_round: selected_round?.bracket_round_id == r.bracket_round_id ? undefined : r })}
193
+ onClose={() => setShowFilter(false)}
194
+ />
195
+ </View>
196
+ :<></>}
197
+ </View>
198
+ </View>
199
+ {player_bracket ?
200
+ <View style={{ padding:20, flexDirection:'row', alignItems:'center', backgroundColor:Colors.shades.shade100 }}>
201
+ {champion_team ?
202
+ <View style={{ justifyContent:'center', alignItems:'center', marginRight:10 }}>
203
+ <Image
204
+ source={{ uri: champion_team.image?.url }}
205
+ style={{ height:20, width:20, borderRadius:4 }}
206
+ resizeMode='cover'
207
+ />
208
+ <Text style={{ marginTop:2 }} size={12} color={Colors.brand.midnight} weight='bold' textAlign='center'>{champion_team.abbr}</Text>
209
+ </View>
210
+ :champion_athlete ?
211
+ <View style={{ justifyContent:'center', alignItems:'center', marginRight:10 }}>
212
+ <Image
213
+ source={{ uri: champion_athlete.image?.url }}
214
+ style={{ height:20, width:20, borderRadius:4 }}
215
+ resizeMode='cover'
216
+ />
217
+ <Text style={{ marginTop:2 }} size={12} color={Colors.brand.midnight} weight='bold' textAlign='center'>{champion_athlete.abbr_name}</Text>
218
+ </View>
219
+ :<></>}
220
+ <View style={{ flex:1 }}>
221
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{player_bracket.bracket_name}</Text>
222
+ <Text style={{ marginTop:3 }} size={12} color={Colors.brand.midnight} weight='regular'>{(player_bracket.completion_pct*100).toFixed(2)}% Complete</Text>
223
+ </View>
224
+ <Button
225
+ title='Change'
226
+ backgroundColor={Colors.brand.electric}
227
+ title_color={Colors.shades.white}
228
+ onPress={() => onChangePlayerBracket(bracket.bracket_id)}
229
+ />
230
+ </View>
231
+ :<></>}
232
+ <ScrollView style={{ flex:1, backgroundColor:Colors.shades.shade100 }}>
233
+ <View style={{ flex:1, flexDirection:'row', padding:10, overflow:'scroll' }}>
234
+ {visible_rounds.sort((a,b) => a.round_number - b.round_number).map((br,i) => {
235
+ return renderBracketRounds({ item:br, index:i })
236
+ })}
237
+ </View>
238
+ </ScrollView>
239
+ </View>
240
+ )
241
+ }
242
+
243
+ export default BracketPlay
@@ -0,0 +1,87 @@
1
+ import React from 'react';
2
+ import { TouchableOpacity, FlatList, View, Image } from "react-native"
3
+ import type { BracketProps, LeagueProps } from '../../types';
4
+ import Colors from '../../constants/colors';
5
+ import { Button, Icons, Text } from '../../Components';
6
+ import moment from 'moment-mini';
7
+
8
+ type BracketSelectorProps = {
9
+ visible: boolean,
10
+ brackets: BracketProps[],
11
+ leagues:LeagueProps[],
12
+ onSelectBracket:(bracket:BracketProps) => void,
13
+ onClose:() => void
14
+ }
15
+
16
+ const BracketSelector = ({ visible, leagues, brackets, onSelectBracket, onClose }:BracketSelectorProps) => {
17
+
18
+ const unique_league_ids = [ ...new Set(brackets.map(b => b.league_id)) ]
19
+
20
+
21
+ const renderBrackets = (data: { item:BracketProps, index:number }) => {
22
+ const started = moment().isAfter(moment(data.item.scheduled_datetime)) ? true : false;
23
+ return (
24
+ <TouchableOpacity style={{ flexDirection:'row', alignItems:'center', padding:20, borderBottomColor:Colors.shades.shade600, borderBottomWidth:1 }} onPress={() => onSelectBracket(data.item)}>
25
+ <View style={{ flex:1 }}>
26
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{data.item.bracket_name}</Text>
27
+ <Text style={{ marginTop:3 }} size={12} color={Colors.brand.slate} weight='regular'>{started?'In Progress':`Starts at ${moment(data.item.scheduled_datetime).format('MMM DD YYYY hh:mm a')}`}</Text>
28
+ </View>
29
+ <Button
30
+ title='VIEW'
31
+ title_color={Colors.shades.white}
32
+ backgroundColor={Colors.brand.electric}
33
+ disabled
34
+ onPress={() => console.log('')}
35
+ />
36
+ </TouchableOpacity>
37
+ )
38
+ }
39
+
40
+ const renderLeagues = ( data : { item:string, index:number }) => {
41
+ const league = leagues.find(l => l.league_id == data.item);
42
+ const league_brackets = brackets.filter(b => b.league_id == data.item);
43
+ if(!league){ return <></> }
44
+ return (
45
+ <View>
46
+ <View style={{ flexDirection:'row', alignItems:'center', padding:10, backgroundColor:Colors.shades.shade100 }}>
47
+ <View>
48
+ <Image
49
+ source={{ uri: league.league_image }}
50
+ style={{ height:30, width:30, borderRadius:4 }}
51
+ resizeMode='cover'
52
+ />
53
+ </View>
54
+ <View style={{ flex:1, marginLeft:10 }}>
55
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{league.league_name}</Text>
56
+ <Text style={{ marginTop:3 }} size={12} color={Colors.brand.slate}>{league_brackets.length} Brackets</Text>
57
+ </View>
58
+ </View>
59
+ <FlatList
60
+ data={league_brackets}
61
+ renderItem={renderBrackets}
62
+ keyExtractor={(item) => item.bracket_id.toString()}
63
+ />
64
+ </View>
65
+ )
66
+ }
67
+
68
+ if(!visible){ return <></> }
69
+ return (
70
+ <View>
71
+ <TouchableOpacity style={{ flexDirection:'row', alignItems:'center', padding:20, borderBottomWidth:1, borderColor:Colors.shades.shade100 }} onPress={() => onClose()}>
72
+ <Icons.ChevronIcon direction='left' size={12} color={Colors.brand.midnight} />
73
+ <View style={{ flex:1, marginLeft:20 }}>
74
+ <Text size={18} color={Colors.brand.midnight} weight='bold'>Active Brackets</Text>
75
+ <Text style={{ marginTop:4 }} size={14} color={Colors.brand.slate} weight='regular'>Select a bracket below to make or edit picks</Text>
76
+ </View>
77
+ </TouchableOpacity>
78
+ <FlatList
79
+ data={unique_league_ids}
80
+ renderItem={renderLeagues}
81
+ keyExtractor={(item) => item.toString()}
82
+ />
83
+ </View>
84
+ )
85
+ }
86
+
87
+ export default BracketSelector
@@ -0,0 +1,165 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { FlatList, View, TouchableOpacity, Image } from 'react-native';
3
+ import type { AthleteProps, CompetitionPlayerBracketProps, PlayerBracketProps, PublicPlayerProps, TeamProps } from '../../types';
4
+ import { BracketApi, BracketComeptitionApi } from '../api';
5
+ import Colors from '../../constants/colors';
6
+ import { Button, Text } from '../../Components';
7
+ import { CompetitionHelpers } from '../../Competition/api';
8
+
9
+ type CompetitionLeaderboardProps = {
10
+ bracket_competition_id:string,
11
+ my_competition_player_brackets:CompetitionPlayerBracketProps[],
12
+ my_player_brackets:PlayerBracketProps[],
13
+ view_mode: 'short'|'full',
14
+ show_champions?:boolean,
15
+ onViewFull?: () => void,
16
+ onClose?:() => void
17
+ }
18
+
19
+ const CompetitionLeaderboard = ({ bracket_competition_id, my_competition_player_brackets, my_player_brackets, view_mode, show_champions, onViewFull, onClose }:CompetitionLeaderboardProps) => {
20
+ const [ leaders_data, setData ] = useState<{
21
+ loading:boolean,
22
+ offset:number,
23
+ teams:TeamProps[],
24
+ athletes:AthleteProps[],
25
+ competition_player_brackets:CompetitionPlayerBracketProps[],
26
+ player_brackets:PlayerBracketProps[],
27
+ players:PublicPlayerProps[]
28
+ }>({
29
+ loading:false,
30
+ offset:0,
31
+ teams:[],
32
+ athletes:[],
33
+ competition_player_brackets: [],
34
+ player_brackets:[],
35
+ players:[]
36
+ })
37
+ const { competition_player_brackets, players, player_brackets, teams, athletes } = leaders_data;
38
+
39
+ let visible_leaders = competition_player_brackets.sort((a,b) => a.place - b.place);
40
+ if(view_mode == 'short'){ visible_leaders = competition_player_brackets.slice(0, 3) }
41
+
42
+ useEffect(() => {
43
+ if(!bracket_competition_id){ return }
44
+ getLeaders(bracket_competition_id, 0)
45
+ },[bracket_competition_id])
46
+
47
+ const getLeaders = async(id:string, page:number) => {
48
+ setData({ ...leaders_data, loading: true })
49
+ const resp = await BracketComeptitionApi.getCompetitionPlayerBracketsByCompetitionId(id, page);
50
+
51
+ const ps = await BracketApi.getPlayersByPlayerIds(resp.competition_player_brackets.map(cpb => cpb.player_id).concat(my_competition_player_brackets[0]?.player_id ?? '0'));
52
+ const team_ids = resp.player_brackets.filter(pb => pb.champion_id_type == 'team').map(pb => pb.champion_id ?? '');
53
+ const athlete_ids = resp.player_brackets.filter(pb => pb.champion_id_type == 'athlete').map(pb => pb.champion_id ?? '');
54
+ const ts = await BracketApi.getTeamsByIds(team_ids);
55
+ const aths = await BracketApi.getAthletesByIds(athlete_ids);
56
+ setData({
57
+ ...leaders_data,
58
+ loading:false,
59
+ competition_player_brackets: resp.competition_player_brackets,
60
+ player_brackets: resp.player_brackets.filter(pb => !my_player_brackets.find(mpb => mpb.player_bracket_id == pb.player_bracket_id)).concat(my_player_brackets),
61
+ teams:ts,
62
+ athletes: aths,
63
+ players: ps
64
+ })
65
+ }
66
+
67
+ const renderLeaders = (data: { item:CompetitionPlayerBracketProps, index:number }) => {
68
+ const player = players.find(p => p.player_id == data.item.player_id);
69
+ const player_bracket = player_brackets.find(pb => pb.player_bracket_id == data.item.player_bracket_id);
70
+ if(!player || !player_bracket){ return <></> }
71
+ let champ_team = undefined, champ_athlete = undefined
72
+ if(show_champions && player_bracket.champion_id_type == 'team'){ champ_team = teams.find(t => t.team_id == player_bracket.champion_id) }
73
+ if(show_champions && player_bracket.champion_id_type == 'athlete'){ champ_athlete = athletes.find(t => t.athlete_id == player_bracket.champion_id) }
74
+ return (
75
+ <TouchableOpacity style={{ flexDirection:'row', alignItems:'center', borderRadius:22, borderTopLeftRadius:4, borderBottomLeftRadius:4, margin:3, backgroundColor:Colors.shades.white, padding:4 }}>
76
+ <View style={{ padding:5 }}>
77
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{CompetitionHelpers.formatPlace(data.item.place)}</Text>
78
+ </View>
79
+ <View>
80
+ <Image
81
+ source={{ uri: player.profile_pic }}
82
+ style={{ height:40, width:40, borderRadius:100 }}
83
+ resizeMode='cover'
84
+ />
85
+ </View>
86
+ <View style={{ flex:1, marginLeft:5, marginRight:5 }}>
87
+ <Text size={14} weight='bold' color={Colors.brand.midnight}>{player_bracket.bracket_name}</Text>
88
+ <Text style={{ marginTop:3 }} size={12} weight='regular' color={Colors.brand.slate}>{data.item.points_scored} Points ({data.item.possible_points} Possible)</Text>
89
+ </View>
90
+ {champ_team ?
91
+ <View style={{ padding:5 }}>
92
+ <Image
93
+ source={{ uri: champ_team.image?.url }}
94
+ style={{ height:25, width:25, borderRadius:4 }}
95
+ resizeMode='cover'
96
+ />
97
+ </View>
98
+ :champ_athlete ?
99
+ <View style={{ padding:5 }}>
100
+ <Image
101
+ source={{ uri: champ_athlete.image?.url }}
102
+ style={{ height:25, width:25, borderRadius:4 }}
103
+ resizeMode='cover'
104
+ />
105
+ </View>
106
+ :<></>}
107
+ <View style={{ padding:5 }}>
108
+ <Text size={14} color={Colors.brand.midnight} weight='semibold'>${data.item.winnings.toFixed(2)}</Text>
109
+ </View>
110
+ </TouchableOpacity>
111
+ )
112
+ }
113
+
114
+ return (
115
+ <View style={{ flex:1 }}>
116
+ <View style={{ flex:1 }}>
117
+ {my_competition_player_brackets.length > 0 ?
118
+ <View style={{ backgroundColor:Colors.brand.midnight, padding:10, borderTopRightRadius:8, borderTopLeftRadius:8 }}>
119
+ <View style={{ marginBottom:5 }}>
120
+ <Text size={14} color={Colors.shades.white}>MY RESULTS</Text>
121
+ </View>
122
+ <FlatList
123
+ data={my_competition_player_brackets}
124
+ renderItem={renderLeaders}
125
+ keyExtractor={(item) => item.competition_player_bracket_id.toString()}
126
+ />
127
+ </View>
128
+ :<></>}
129
+ <View style={{ padding:10, backgroundColor:Colors.shades.shade100, borderRadius:8 }}>
130
+ <View style={{ marginBottom:5 }}>
131
+ <Text size={14} color={Colors.brand.midnight}>RESULTS</Text>
132
+ </View>
133
+ <FlatList
134
+ data={visible_leaders}
135
+ renderItem={renderLeaders}
136
+ keyExtractor={(item) => item.competition_player_bracket_id.toString()}
137
+ />
138
+ </View>
139
+ {view_mode == 'short' && onViewFull ?
140
+ <View style={{ padding:10 }}>
141
+ <Button
142
+ title='View Full Leaderboard'
143
+ title_color={Colors.brand.electric}
144
+ backgroundColor='transparent'
145
+ onPress={() => onViewFull()}
146
+ />
147
+ </View>
148
+ :<></>}
149
+ </View>
150
+ {onClose ?
151
+ <View style={{ padding:10 }}>
152
+ <Button
153
+ title='Close'
154
+ style={{ padding:15 }}
155
+ title_color={Colors.shades.white}
156
+ backgroundColor={Colors.utility.error}
157
+ onPress={() => onClose()}
158
+ />
159
+ </View>
160
+ :<></>}
161
+ </View>
162
+ )
163
+ }
164
+
165
+ export default CompetitionLeaderboard
@@ -0,0 +1,66 @@
1
+ import React from 'react';
2
+ import { View, Image } from "react-native";
3
+ import { Button, Text } from '../../Components';
4
+ import type { BracketCompetitionProps, CompetitionPlayerBracketProps, PlayerBracketProps } from '../../types';
5
+ import { BracketCompetitionHelpers } from '../api';
6
+ import Colors from '../../constants/colors';
7
+
8
+ type JoinCompetitionCardProps = {
9
+ player_bracket:PlayerBracketProps,
10
+ bracket_competition:BracketCompetitionProps,
11
+ onEnterCompetition:(cpb:CompetitionPlayerBracketProps) => void,
12
+ onClose:() => void
13
+ }
14
+
15
+ const JoinCompetitionCard = ({ player_bracket, bracket_competition, onEnterCompetition, onClose }:JoinCompetitionCardProps) => {
16
+
17
+ const buy_in_label = BracketCompetitionHelpers.getBuyInTitle(bracket_competition)
18
+
19
+ const handleEnter = () => {
20
+ const cpb = BracketCompetitionHelpers.generateCompetitionPlayerBracket(bracket_competition.bracket_competition_id, player_bracket.player_bracket_id)
21
+ onEnterCompetition(cpb)
22
+ }
23
+
24
+ return (
25
+ <View style={{ minWidth:300, backgroundColor:Colors.shades.white, borderRadius:8 }}>
26
+ <View style={{ borderTopRightRadius:8, borderTopLeftRadius:8, backgroundColor:Colors.shades.shade100, padding:15 }}>
27
+ <Text size={16} color={Colors.brand.midnight} weight='bold'>{bracket_competition.competition_name}</Text>
28
+ </View>
29
+ <View style={{ justifyContent:'center', alignItems:'center' }}>
30
+ <Image
31
+ source={{ uri: bracket_competition.image?.url }}
32
+ style={{ height:240, width:240 }}
33
+ resizeMode='cover'
34
+ />
35
+ </View>
36
+ <View style={{ flexDirection:'row', alignItems:'center', padding:10 }}>
37
+ <View style={{ flex:1 }}>
38
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{player_bracket.bracket_name}</Text>
39
+ <Text style={{ marginTop:3 }} size={12} color={Colors.brand.slate} weight='regular'>{(player_bracket.completion_pct*100).toFixed(2)}% Complete</Text>
40
+ </View>
41
+ </View>
42
+ <View style={{ flexDirection:'row', alignItems:'center', padding:10, backgroundColor:Colors.shades.shade100, borderBottomRightRadius:8, borderBottomLeftRadius:8 }}>
43
+ <Button
44
+ title='Close'
45
+ style={{ flex:1, marginRight:5 }}
46
+ padding={15}
47
+ title_color={Colors.brand.electric}
48
+ borderWidth={1}
49
+ borderColor={Colors.brand.electric}
50
+ onPress={() => onClose()}
51
+ />
52
+ <Button
53
+ title={buy_in_label}
54
+ style={{ flex:2 }}
55
+ padding={15}
56
+ title_color={Colors.shades.white}
57
+ backgroundColor={Colors.utility.success}
58
+ onPress={() => handleEnter()}
59
+
60
+ />
61
+ </View>
62
+ </View>
63
+ )
64
+ }
65
+
66
+ export default JoinCompetitionCard