be-components 1.0.1 → 1.0.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 (114) hide show
  1. package/lib/commonjs/Bracket/api/index.js +439 -0
  2. package/lib/commonjs/Bracket/api/index.js.map +1 -0
  3. package/lib/commonjs/Bracket/components/BracketCompetitionCard.js +570 -0
  4. package/lib/commonjs/Bracket/components/BracketCompetitionCard.js.map +1 -0
  5. package/lib/commonjs/Bracket/components/BracketCompetitionSelector.js +208 -0
  6. package/lib/commonjs/Bracket/components/BracketCompetitionSelector.js.map +1 -0
  7. package/lib/commonjs/Bracket/components/BracketPlay/BracketNavigator.js +142 -0
  8. package/lib/commonjs/Bracket/components/BracketPlay/BracketNavigator.js.map +1 -0
  9. package/lib/commonjs/Bracket/components/BracketPlay/BracketRound.js +94 -0
  10. package/lib/commonjs/Bracket/components/BracketPlay/BracketRound.js.map +1 -0
  11. package/lib/commonjs/Bracket/components/BracketPlay/RoundEvent.js +438 -0
  12. package/lib/commonjs/Bracket/components/BracketPlay/RoundEvent.js.map +1 -0
  13. package/lib/commonjs/Bracket/components/BracketPlay/index.js +350 -0
  14. package/lib/commonjs/Bracket/components/BracketPlay/index.js.map +1 -0
  15. package/lib/commonjs/Bracket/components/BracketSelector.js +138 -0
  16. package/lib/commonjs/Bracket/components/BracketSelector.js.map +1 -0
  17. package/lib/commonjs/Bracket/components/CompetitionLeaderboard.js +237 -0
  18. package/lib/commonjs/Bracket/components/CompetitionLeaderboard.js.map +1 -0
  19. package/lib/commonjs/Bracket/components/JoinCompetitionCard.js +130 -0
  20. package/lib/commonjs/Bracket/components/JoinCompetitionCard.js.map +1 -0
  21. package/lib/commonjs/Bracket/components/PlayerBalanceCard.js +53 -0
  22. package/lib/commonjs/Bracket/components/PlayerBalanceCard.js.map +1 -0
  23. package/lib/commonjs/Bracket/components/PlayerBracketManager.js +452 -0
  24. package/lib/commonjs/Bracket/components/PlayerBracketManager.js.map +1 -0
  25. package/lib/commonjs/Bracket/components/PlayerBrackets.js +179 -0
  26. package/lib/commonjs/Bracket/components/PlayerBrackets.js.map +1 -0
  27. package/lib/commonjs/Bracket/components/RoomMenu.js +118 -0
  28. package/lib/commonjs/Bracket/components/RoomMenu.js.map +1 -0
  29. package/lib/commonjs/Bracket/index.js +368 -0
  30. package/lib/commonjs/Bracket/index.js.map +1 -0
  31. package/lib/commonjs/index.js +7 -0
  32. package/lib/commonjs/index.js.map +1 -1
  33. package/lib/module/Bracket/api/index.js +433 -0
  34. package/lib/module/Bracket/api/index.js.map +1 -0
  35. package/lib/module/Bracket/components/BracketCompetitionCard.js +561 -0
  36. package/lib/module/Bracket/components/BracketCompetitionCard.js.map +1 -0
  37. package/lib/module/Bracket/components/BracketCompetitionSelector.js +199 -0
  38. package/lib/module/Bracket/components/BracketCompetitionSelector.js.map +1 -0
  39. package/lib/module/Bracket/components/BracketPlay/BracketNavigator.js +135 -0
  40. package/lib/module/Bracket/components/BracketPlay/BracketNavigator.js.map +1 -0
  41. package/lib/module/Bracket/components/BracketPlay/BracketRound.js +87 -0
  42. package/lib/module/Bracket/components/BracketPlay/BracketRound.js.map +1 -0
  43. package/lib/module/Bracket/components/BracketPlay/RoundEvent.js +431 -0
  44. package/lib/module/Bracket/components/BracketPlay/RoundEvent.js.map +1 -0
  45. package/lib/module/Bracket/components/BracketPlay/index.js +341 -0
  46. package/lib/module/Bracket/components/BracketPlay/index.js.map +1 -0
  47. package/lib/module/Bracket/components/BracketSelector.js +131 -0
  48. package/lib/module/Bracket/components/BracketSelector.js.map +1 -0
  49. package/lib/module/Bracket/components/CompetitionLeaderboard.js +228 -0
  50. package/lib/module/Bracket/components/CompetitionLeaderboard.js.map +1 -0
  51. package/lib/module/Bracket/components/JoinCompetitionCard.js +123 -0
  52. package/lib/module/Bracket/components/JoinCompetitionCard.js.map +1 -0
  53. package/lib/module/Bracket/components/PlayerBalanceCard.js +46 -0
  54. package/lib/module/Bracket/components/PlayerBalanceCard.js.map +1 -0
  55. package/lib/module/Bracket/components/PlayerBracketManager.js +443 -0
  56. package/lib/module/Bracket/components/PlayerBracketManager.js.map +1 -0
  57. package/lib/module/Bracket/components/PlayerBrackets.js +172 -0
  58. package/lib/module/Bracket/components/PlayerBrackets.js.map +1 -0
  59. package/lib/module/Bracket/components/RoomMenu.js +111 -0
  60. package/lib/module/Bracket/components/RoomMenu.js.map +1 -0
  61. package/lib/module/Bracket/index.js +359 -0
  62. package/lib/module/Bracket/index.js.map +1 -0
  63. package/lib/module/index.js +2 -1
  64. package/lib/module/index.js.map +1 -1
  65. package/lib/typescript/src/Bracket/api/index.d.ts +111 -0
  66. package/lib/typescript/src/Bracket/api/index.d.ts.map +1 -0
  67. package/lib/typescript/src/Bracket/components/BracketCompetitionCard.d.ts +34 -0
  68. package/lib/typescript/src/Bracket/components/BracketCompetitionCard.d.ts.map +1 -0
  69. package/lib/typescript/src/Bracket/components/BracketCompetitionSelector.d.ts +12 -0
  70. package/lib/typescript/src/Bracket/components/BracketCompetitionSelector.d.ts.map +1 -0
  71. package/lib/typescript/src/Bracket/components/BracketPlay/BracketNavigator.d.ts +14 -0
  72. package/lib/typescript/src/Bracket/components/BracketPlay/BracketNavigator.d.ts.map +1 -0
  73. package/lib/typescript/src/Bracket/components/BracketPlay/BracketRound.d.ts +25 -0
  74. package/lib/typescript/src/Bracket/components/BracketPlay/BracketRound.d.ts.map +1 -0
  75. package/lib/typescript/src/Bracket/components/BracketPlay/RoundEvent.d.ts +23 -0
  76. package/lib/typescript/src/Bracket/components/BracketPlay/RoundEvent.d.ts.map +1 -0
  77. package/lib/typescript/src/Bracket/components/BracketPlay/index.d.ts +19 -0
  78. package/lib/typescript/src/Bracket/components/BracketPlay/index.d.ts.map +1 -0
  79. package/lib/typescript/src/Bracket/components/BracketSelector.d.ts +12 -0
  80. package/lib/typescript/src/Bracket/components/BracketSelector.d.ts.map +1 -0
  81. package/lib/typescript/src/Bracket/components/CompetitionLeaderboard.d.ts +14 -0
  82. package/lib/typescript/src/Bracket/components/CompetitionLeaderboard.d.ts.map +1 -0
  83. package/lib/typescript/src/Bracket/components/JoinCompetitionCard.d.ts +17 -0
  84. package/lib/typescript/src/Bracket/components/JoinCompetitionCard.d.ts.map +1 -0
  85. package/lib/typescript/src/Bracket/components/PlayerBalanceCard.d.ts +9 -0
  86. package/lib/typescript/src/Bracket/components/PlayerBalanceCard.d.ts.map +1 -0
  87. package/lib/typescript/src/Bracket/components/PlayerBracketManager.d.ts +18 -0
  88. package/lib/typescript/src/Bracket/components/PlayerBracketManager.d.ts.map +1 -0
  89. package/lib/typescript/src/Bracket/components/PlayerBrackets.d.ts +17 -0
  90. package/lib/typescript/src/Bracket/components/PlayerBrackets.d.ts.map +1 -0
  91. package/lib/typescript/src/Bracket/components/RoomMenu.d.ts +14 -0
  92. package/lib/typescript/src/Bracket/components/RoomMenu.d.ts.map +1 -0
  93. package/lib/typescript/src/Bracket/index.d.ts +17 -0
  94. package/lib/typescript/src/Bracket/index.d.ts.map +1 -0
  95. package/lib/typescript/src/index.d.ts +2 -1
  96. package/lib/typescript/src/index.d.ts.map +1 -1
  97. package/package.json +1 -1
  98. package/src/Bracket/api/index.ts +370 -0
  99. package/src/Bracket/components/BracketCompetitionCard.tsx +351 -0
  100. package/src/Bracket/components/BracketCompetitionSelector.tsx +123 -0
  101. package/src/Bracket/components/BracketPlay/BracketNavigator.tsx +75 -0
  102. package/src/Bracket/components/BracketPlay/BracketRound.tsx +86 -0
  103. package/src/Bracket/components/BracketPlay/RoundEvent.tsx +262 -0
  104. package/src/Bracket/components/BracketPlay/index.tsx +247 -0
  105. package/src/Bracket/components/BracketSelector.tsx +87 -0
  106. package/src/Bracket/components/CompetitionLeaderboard.tsx +165 -0
  107. package/src/Bracket/components/JoinCompetitionCard.tsx +83 -0
  108. package/src/Bracket/components/PlayerBalanceCard.tsx +34 -0
  109. package/src/Bracket/components/PlayerBracketManager.tsx +229 -0
  110. package/src/Bracket/components/PlayerBrackets.tsx +119 -0
  111. package/src/Bracket/components/RoomMenu.tsx +69 -0
  112. package/src/Bracket/index.tsx +291 -0
  113. package/src/index.tsx +3 -1
  114. package/src/types.d.ts +173 -0
@@ -0,0 +1,351 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { View, ActivityIndicator, Image, TouchableOpacity, FlatList, StyleSheet } from 'react-native';
3
+ import type { BracketCompetitionProps, BracketCompetitionScoringRuleProps, BracketProps, BracketRoundProps, CompetitionPlayerBracketProps, CompetitionResultTypeProps, MyPlayerProps, PlayerBalanceProps, PlayerBracketProps, PublicPlayerProps } from '../../types';
4
+ import { BracketApi, BracketComeptitionApi, BracketCompetitionHelpers } from '../api';
5
+ import Colors from '../../constants/colors';
6
+ import { Button, Icons, Spring, Text } from '../../Components';
7
+ import moment from 'moment-mini';
8
+ import CompetitionLeaderboard from './CompetitionLeaderboard';
9
+ import JoinCompetitionCard from './JoinCompetitionCard';
10
+ import { view_styles } from '../../constants/styles';
11
+
12
+ type BracketCompetitionCardProps = {
13
+ visible: boolean,
14
+ player?:MyPlayerProps,
15
+ player_balance?:PlayerBalanceProps,
16
+ bracket_competition_id?:string,
17
+ height:number
18
+ onNotEnoughBalance:(data:{ bracket_competition:BracketCompetitionProps }) => void,
19
+ onViewBracket:(bracket_id:string) => void,
20
+ onUpdateMyData: (data: {bracket_id:string, player_brackets:PlayerBracketProps[], competition_player_brackets:CompetitionPlayerBracketProps[]}) => void,
21
+ onShareCompetition:(bracket_competition_id:string) => void,
22
+ onEnterCompetition: (resp: {competition_player_bracket:CompetitionPlayerBracketProps, bracket_competition:BracketCompetitionProps}) => void,
23
+ onLeaveCompetition: (resp: {competition_player_bracket:CompetitionPlayerBracketProps, bracket_competition:BracketCompetitionProps}) => void,
24
+ competition_result_types:CompetitionResultTypeProps[],
25
+ my_comp_player_brackets:CompetitionPlayerBracketProps[],
26
+ my_player_brackets:PlayerBracketProps[],
27
+ onClose:() => void
28
+ }
29
+
30
+ const BracketCompetitionCard = ({ visible, player_balance, player, height, my_comp_player_brackets, competition_result_types, my_player_brackets, bracket_competition_id, onNotEnoughBalance, onUpdateMyData, onViewBracket, onClose, onLeaveCompetition, onShareCompetition, onEnterCompetition }:BracketCompetitionCardProps) => {
31
+ const [ action_loading, setActionLoading ] = useState(false);
32
+ const [ joining_bracket, setJoiningBracket ] = useState<PlayerBracketProps | undefined>(undefined);
33
+ const [ show_rules, setShowRules ] = useState(false);
34
+ const [ show_bracket, setShowBracket ] = useState(true);
35
+ const [ show_leaderboard, setShowLeaderboard ] = useState(false);
36
+ const [ show_info, setShowInfo ] = useState(true);
37
+ const [ show_leaders, setShowLeaders ] = useState(true);
38
+ const [ card_data, setData ] = useState<{
39
+ bracket_competition?:BracketCompetitionProps,
40
+ bracket?:BracketProps,
41
+ bracket_rounds:BracketRoundProps[],
42
+ competition_player_brackets:CompetitionPlayerBracketProps[],
43
+ bracket_competition_scoring_rules:BracketCompetitionScoringRuleProps[],
44
+ player_brackets:PlayerBracketProps[],
45
+ players:PublicPlayerProps[],
46
+ loaded:boolean
47
+ }>({
48
+ loaded:false,
49
+ bracket_rounds: [],
50
+ competition_player_brackets: [],
51
+ bracket_competition_scoring_rules:[],
52
+ player_brackets: [],
53
+ players: []
54
+ })
55
+
56
+ const { loaded, bracket_competition, bracket, bracket_rounds, competition_player_brackets, bracket_competition_scoring_rules } = card_data;
57
+ const result_type = competition_result_types.find(crt => crt.competition_result_type_id == bracket_competition?.competition_result_type_id);
58
+
59
+ useEffect(() => {
60
+ if(!bracket_competition_id){ return }
61
+ getCompetitionData(bracket_competition_id)
62
+ },[bracket_competition_id])
63
+
64
+ const getCompetitionData = async(id:string) => {
65
+ const resp = await BracketComeptitionApi.getBracketCompetitionById(id);
66
+ if(player){
67
+ const my_cpbs = resp.competition_player_brackets.filter(cpb => cpb.player_id == player.player_id)
68
+ const my_pbs = resp.player_brackets.filter(pbs => pbs.player_id == player.player_id)
69
+ onUpdateMyData({ player_brackets: my_pbs, competition_player_brackets: my_cpbs, bracket_id: resp.bracket_competition.bracket_id })
70
+ }
71
+ const br_resp = await BracketApi.getBracketById(resp.bracket_competition.bracket_id);
72
+ const player_ids = resp.competition_player_brackets.map(pb => pb.player_id);
73
+ const ps = await BracketApi.getPlayersByPlayerIds(player_ids);
74
+ setData({
75
+ ...card_data,
76
+ bracket_competition: resp.bracket_competition,
77
+ bracket_competition_scoring_rules: resp.bracket_competition_scoring_rules,
78
+ competition_player_brackets:resp.competition_player_brackets,
79
+ player_brackets: resp.player_brackets,
80
+ players: ps,
81
+ bracket: br_resp.bracket,
82
+ bracket_rounds: br_resp.bracket_rounds,
83
+ loaded: true
84
+ })
85
+ }
86
+
87
+ const can_leave = BracketCompetitionHelpers.canLeave(bracket_competition);
88
+
89
+ const handleEnter = async(cpb:CompetitionPlayerBracketProps) => {
90
+ setActionLoading(true);
91
+ const resp = await BracketComeptitionApi.joinBracketCompetition(cpb);
92
+ setData({
93
+ ...card_data,
94
+ bracket_competition: resp.bracket_competition,
95
+ competition_player_brackets: competition_player_brackets.filter(cpb => cpb.competition_player_bracket_id != resp.competition_player_bracket.competition_player_bracket_id).concat(resp.competition_player_bracket)
96
+ })
97
+ onEnterCompetition(resp);
98
+ setJoiningBracket(undefined)
99
+ setActionLoading(false);
100
+ }
101
+
102
+ const handleLeave = async(cpb_id:string) => {
103
+ setActionLoading(true);
104
+ const resp = await BracketComeptitionApi.leaveBracketCompetition(cpb_id)
105
+ setData({
106
+ ...card_data,
107
+ bracket_competition: resp.bracket_competition,
108
+ competition_player_brackets: competition_player_brackets.filter(cpb => cpb.competition_player_bracket_id != resp.competition_player_bracket.competition_player_bracket_id)
109
+ })
110
+ onLeaveCompetition(resp);
111
+ setActionLoading(false);
112
+ }
113
+
114
+ const renderPlayerBrackets = (data: { item: PlayerBracketProps, index:number }) => {
115
+ const cpb = my_comp_player_brackets.find(mcpb => mcpb.player_bracket_id == data.item.player_bracket_id);
116
+ return (
117
+ <View style={{ flexDirection:'row', padding:5 }}>
118
+ <TouchableOpacity style={{ flex:1 }} onPress={() => onViewBracket(data.item.bracket_id)}>
119
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{data.item.bracket_name}</Text>
120
+ <Text style={{ marginTop:3 }} size={12} color={Colors.brand.midnight} weight='regular'>{(data.item.completion_pct*100).toFixed(2)}% Complete</Text>
121
+ </TouchableOpacity>
122
+ {!cpb ?
123
+ <Button
124
+ title='Join'
125
+ loading={action_loading}
126
+ backgroundColor={Colors.utility.success}
127
+ title_color={Colors.shades.white}
128
+ onPress={() => setJoiningBracket(data.item)}
129
+ />
130
+ :cpb && can_leave ?
131
+ <Button
132
+ title='Leave'
133
+ disabled={action_loading}
134
+ style={{ opacity: action_loading?0.5:1 }}
135
+ loading={action_loading}
136
+ backgroundColor={Colors.utility.error}
137
+ title_color={Colors.shades.white}
138
+ onPress={() => handleLeave(cpb.competition_player_bracket_id)}
139
+ />
140
+ :<></>}
141
+ </View>
142
+ )
143
+ }
144
+
145
+ const renderRules = (data: { item:BracketCompetitionScoringRuleProps, index:number }) => {
146
+ if(!bracket){ return <></> }
147
+ const bracket_round = bracket_rounds.find(br => br.round_number == data.item.round_number);
148
+ if(!bracket_round){ return <></> }
149
+ return (
150
+ <View style={{ flexDirection:'row', padding:10 }}>
151
+ <Text style={{ flex:1 }} size={14} color={Colors.brand.midnight} weight='bold'>{bracket_round.round_name}</Text>
152
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{data.item.win_points} Points</Text>
153
+ </View>
154
+ )
155
+ }
156
+
157
+ if(!visible){ return <></> }
158
+
159
+ if(!loaded || !bracket_competition || !bracket){
160
+ return (
161
+ <View>
162
+ <ActivityIndicator style={{ padding:20, alignSelf:'center' }} size='large' color={Colors.brand.midnight} />
163
+ </View>
164
+ )
165
+ }
166
+
167
+ let payout = BracketCompetitionHelpers.getPayout(bracket_competition);
168
+
169
+ return (
170
+ <View style={{ flex:1, backgroundColor:Colors.shades.shade100 }}>
171
+ <View style={{ borderBottomWidth:1, borderColor:Colors.shades.shade600, backgroundColor:Colors.shades.white }}>
172
+ <View style={{ padding:20, flexDirection:'row', alignItems:'center' }}>
173
+ <TouchableOpacity style={{ flex:1, flexDirection:'row', alignItems:'center' }} onPress={() => onClose()}>
174
+ <View style={{ padding:10 }}>
175
+ <Icons.ChevronIcon size={12} color={Colors.brand.midnight} direction='left' />
176
+ </View>
177
+ <View>
178
+ <Image
179
+ source={{ uri: bracket_competition.image?.url }}
180
+ style={{ height:50, width:50, borderRadius:4 }}
181
+ resizeMode='cover'
182
+ />
183
+ </View>
184
+ <View style={{ flex:1, marginLeft:10 }}>
185
+ <Text weight='bold' size={14} color={Colors.brand.midnight}>{bracket_competition.competition_name}</Text>
186
+ <Text style={{ marginTop:4 }} size={12} color={Colors.brand.slate}>{bracket_competition.competition_description}</Text>
187
+ </View>
188
+ </TouchableOpacity>
189
+ <TouchableOpacity style={{ padding:10 }} onPress={() => onShareCompetition(bracket_competition.bracket_competition_id)}>
190
+ <Icons.ShareIcon color={Colors.brand.electric} size={12} />
191
+ </TouchableOpacity>
192
+ </View>
193
+ </View>
194
+ <View style={local_styles.header}>
195
+ <TouchableOpacity style={local_styles.section_header} onPress={() => setShowBracket(!show_bracket)}>
196
+ <View>
197
+ <Image
198
+ source={{ uri: 'https://res.cloudinary.com/hoabts6mc/image/upload/v1677259366/Bracket_image_h0fkku.webp' }}
199
+ style={{ width:50, height:35, borderRadius:4 }}
200
+ resizeMode='cover'
201
+ />
202
+ </View>
203
+ <View style={{ flex:1, marginLeft:10 }}>
204
+ <Text size={16} color={Colors.brand.midnight} weight='bold'>{bracket.bracket_name}</Text>
205
+ <Text style={{ marginTop:3 }} size={14} color={Colors.brand.slate} weight='regular'>Bracket starts {moment(bracket.scheduled_datetime).format('MMM DD YYYY hh:mm a')}</Text>
206
+ </View>
207
+ <Icons.ChevronIcon size={10} direction={show_bracket ? 'up' : 'down'} color={Colors.brand.midnight} />
208
+ </TouchableOpacity>
209
+ {show_bracket ?
210
+ <View style={{ padding:20 }}>
211
+ {my_player_brackets.length > 0 ?
212
+ <View style={{ borderWidth:1, borderColor:Colors.shades.shade600, borderRadius:8 }}>
213
+ <View style={{ borderBottomWidth:1, borderBottomColor:Colors.shades.shade600, padding:10 }}>
214
+ <Text size={16} color={Colors.brand.slate} weight='regular'>MY ELIGIBLE BRACKETS</Text>
215
+ </View>
216
+ <View style={{ padding:10 }}>
217
+ <FlatList
218
+ data={my_player_brackets}
219
+ renderItem={renderPlayerBrackets}
220
+ keyExtractor={(item) => item.player_bracket_id.toString()}
221
+ />
222
+ </View>
223
+ </View>
224
+ :<></>}
225
+ <View style={{ margin:10, marginBottom:0 }}>
226
+ <Button
227
+ title='Fill Out Bracket'
228
+ padding={15}
229
+ title_color={Colors.shades.white}
230
+ backgroundColor={Colors.brand.electric}
231
+ onPress={() => onViewBracket(bracket.bracket_id)}
232
+ />
233
+ </View>
234
+ </View>
235
+ :<></>}
236
+ </View>
237
+ <View style={local_styles.header}>
238
+ <TouchableOpacity style={local_styles.section_header} onPress={() => setShowInfo(!show_info)}>
239
+ <View style={{ flex:1 }}>
240
+ <Text size={16} color={Colors.brand.midnight} weight='bold'>COMPETITION DETAILS</Text>
241
+ <Text style={{ marginTop:3 }} size={14} color={Colors.brand.slate} weight='regular'>Detailed Information on this competition</Text>
242
+ </View>
243
+ <Icons.ChevronIcon size={10} direction={show_info ? 'up' : 'down'} color={Colors.brand.midnight} />
244
+ </TouchableOpacity>
245
+ {show_info ?
246
+ <View style={{ padding:10, margin:10, borderWidth:1, borderRadius:8, borderColor:Colors.shades.shade600 }}>
247
+ <View style={{ flexDirection:'row', alignItems:'center', padding:5 }}>
248
+ <Text style={{ flex:1 }} size={14} weight='bold' color={Colors.brand.midnight}>Ticket Price</Text>
249
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>${bracket_competition.buy_in.toFixed(2)}</Text>
250
+ </View>
251
+ <View style={{ flexDirection:'row', alignItems:'center', padding:5 }}>
252
+ <Text style={{ flex:1 }} size={14} weight='bold' color={Colors.brand.midnight}>Current Payout</Text>
253
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>${payout.toFixed(2)}</Text>
254
+ </View>
255
+ {result_type ?
256
+ <View style={{ flexDirection:'row', alignItems:'center', padding:5 }}>
257
+ <Text style={{ flex:1 }} size={14} weight='bold' color={Colors.brand.midnight}>Payout Type</Text>
258
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{result_type.label}</Text>
259
+ </View>
260
+ :<></>}
261
+ <View style={{ flexDirection:'row', alignItems:'center', padding:5 }}>
262
+ <Text style={{ flex:1 }} size={14} weight='bold' color={Colors.brand.midnight}>Entries</Text>
263
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{bracket_competition.tickets_sold} / {bracket_competition.max_brackets}</Text>
264
+ </View>
265
+ </View>
266
+ :<></>}
267
+ </View>
268
+ <View style={local_styles.header}>
269
+ <TouchableOpacity style={local_styles.section_header} onPress={() => setShowRules(!show_rules)}>
270
+ <View style={{ flex:1 }}>
271
+ <Text size={16} color={Colors.brand.midnight} weight='bold'>SCORING RULES</Text>
272
+ <Text style={{ marginTop:3 }} size={14} color={Colors.brand.slate} weight='regular'>Rules on how picks are scored within each bracket round</Text>
273
+ </View>
274
+ <Icons.ChevronIcon size={10} direction={show_rules ? 'up' : 'down'} color={Colors.brand.midnight} />
275
+ </TouchableOpacity>
276
+ {show_rules ?
277
+ <View style={{ padding:10, marginBottom:15, backgroundColor:Colors.shades.shade600, borderRadius:8, marginLeft:10, marginRight:10 }}>
278
+ <FlatList
279
+ data={bracket_competition_scoring_rules.sort((a,b) => a.round_number - b.round_number)}
280
+ renderItem={renderRules}
281
+ keyExtractor={(item) => item.bracket_competition_scoring_rule_id.toString()}
282
+ />
283
+ </View>
284
+ :<></>}
285
+ </View>
286
+ <View style={local_styles.header}>
287
+ <TouchableOpacity style={local_styles.section_header} onPress={() => setShowLeaders(!show_leaders)}>
288
+ <View style={{ flex:1 }}>
289
+ <Text size={16} color={Colors.brand.midnight} weight='bold'>LEADERBOARD</Text>
290
+ <Text style={{ marginTop:3 }} size={14} color={Colors.brand.slate} weight='regular'>Leaderboard showing points and the current payouts.</Text>
291
+ </View>
292
+ <Icons.ChevronIcon size={10} direction={show_leaders ? 'up' : 'down'} color={Colors.brand.midnight} />
293
+ </TouchableOpacity>
294
+ {show_leaders ?
295
+ <View style={{ padding:10 }}>
296
+ <CompetitionLeaderboard
297
+ my_competition_player_brackets={my_comp_player_brackets}
298
+ my_player_brackets={my_player_brackets}
299
+ bracket_competition_id={bracket_competition.bracket_competition_id}
300
+ view_mode='short'
301
+ show_champions={BracketCompetitionHelpers.showChampions(bracket_competition)}
302
+ onViewFull={() => setShowLeaderboard(true)}
303
+ />
304
+ </View>
305
+ :<></>}
306
+ </View>
307
+ {show_leaderboard ?
308
+ <View style={{ position: 'absolute', left:0, right:0, bottom:0 }}>
309
+ <Spring
310
+ to={0}
311
+ from={500}
312
+ slide='vertical'
313
+ >
314
+ <View style={{ flex:1, height, backgroundColor:Colors.shades.white }}>
315
+ <CompetitionLeaderboard
316
+ bracket_competition_id={bracket_competition.bracket_competition_id}
317
+ view_mode='full'
318
+ show_champions={BracketCompetitionHelpers.showChampions(bracket_competition)}
319
+ onClose={() => setShowLeaderboard(false)}
320
+ my_competition_player_brackets={my_comp_player_brackets}
321
+ my_player_brackets={my_player_brackets}
322
+ />
323
+ </View>
324
+ </Spring>
325
+ </View>
326
+ :<></>}
327
+ {joining_bracket ?
328
+ <View style={{ position:'absolute', top:0, bottom:0, left:0, right:0, backgroundColor:Colors.shades.black_faded_heavy, justifyContent:'center', alignItems:'center' }}>
329
+ <JoinCompetitionCard
330
+ player={player}
331
+ loading={action_loading}
332
+ player_balance={player_balance}
333
+ bracket_competition={bracket_competition}
334
+ player_bracket={joining_bracket}
335
+ onClose={() => setJoiningBracket(undefined)}
336
+ onNotEnoughBalance={onNotEnoughBalance}
337
+ onEnterCompetition={(cpb) => handleEnter(cpb)}
338
+ />
339
+ </View>
340
+ :<></>}
341
+ </View>
342
+ )
343
+ }
344
+
345
+
346
+ const local_styles = StyleSheet.create({
347
+ header: { margin:10, backgroundColor:Colors.shades.white, borderRadius:8, ...view_styles.float },
348
+ section_header: { padding:10, paddingLeft:20, paddingRight:20, flexDirection:'row', alignItems:'center' }
349
+ })
350
+
351
+ export default BracketCompetitionCard
@@ -0,0 +1,123 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { FlatList, TouchableOpacity, View, Image } from 'react-native';
3
+ import type { BracketCompetitionProps, BracketProps, LeagueProps } from '../../types';
4
+ import { Icons, Text } from '../../Components';
5
+ import { BracketComeptitionApi } from '../api';
6
+ import Colors from '../../constants/colors';
7
+ import moment from 'moment-mini';
8
+
9
+ type BracketCompetitionSelectorProps = {
10
+ visible:boolean,
11
+ leagues:LeagueProps[],
12
+ brackets:BracketProps[],
13
+ onClose:() => void,
14
+ onCompetitionSelect:(bracket_competition:BracketCompetitionProps) => void
15
+ }
16
+ const BracketCompetitionSelector = ({ visible, leagues, brackets, onClose, onCompetitionSelect }:BracketCompetitionSelectorProps) => {
17
+ const [ card_data, setData ] = useState<{
18
+ loading:boolean,
19
+ shown_brackets:string[]
20
+ bracket_competitions:BracketCompetitionProps[]
21
+ }>({
22
+ loading:false,
23
+ shown_brackets: [],
24
+ bracket_competitions: []
25
+ })
26
+ const { loading, bracket_competitions, shown_brackets } = card_data;
27
+
28
+ const unique_bracket_ids = [ ...new Set(bracket_competitions.map(bc => bc.bracket_id)) ]
29
+
30
+ useEffect(() => {
31
+ if(!visible){ return }
32
+ getData();
33
+ },[visible])
34
+
35
+ const getData = async() => {
36
+ const comps = await BracketComeptitionApi.getBracketCompetitions();
37
+ setData({
38
+ ...card_data,
39
+ bracket_competitions: comps
40
+ })
41
+ }
42
+
43
+ const renderCompetitions = (data: { item:BracketCompetitionProps, index:number } ) => {
44
+ return (
45
+ <TouchableOpacity style={{ padding:10, flexDirection:'row', alignItems:'center', borderBottomWidth:1, borderColor:Colors.shades.shade600 }}
46
+ onPress={() => onCompetitionSelect(data.item)}>
47
+ <View>
48
+ <Image
49
+ source={{ uri: data.item.image?.url }}
50
+ style={{ height:40, width:40, borderRadius:4 }}
51
+ resizeMode='cover'
52
+ />
53
+ </View>
54
+ <View style={{ flex:1, marginLeft:5 }}>
55
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{data.item.competition_name}</Text>
56
+ <Text style={{ marginTop:3 }} size={12} color={Colors.brand.slate} weight='regular'>{data.item.competition_description}</Text>
57
+ </View>
58
+ <Icons.ChevronIcon size={10} color={Colors.brand.midnight} direction='right' />
59
+ </TouchableOpacity>
60
+ )
61
+ }
62
+
63
+ const renderBrackets = (data: { item:string, index:number }) => {
64
+ const bracket = brackets.find(b => b.bracket_id == data.item);
65
+ if(!bracket){ return <></> }
66
+ const league = leagues.find(l => l.league_id == bracket.league_id);
67
+ const comps = bracket_competitions.filter(bc => bc.bracket_id == data.item);
68
+ const selected = shown_brackets.includes(data.item)
69
+ const started = moment().isAfter(moment(bracket.scheduled_datetime)) ? true : false;
70
+ return (
71
+ <View>
72
+ <TouchableOpacity style={{ flexDirection:'row', alignItems:'center', padding:10, backgroundColor:Colors.shades.shade100 }}
73
+ onPress={() => selected ? setData({ ...card_data, shown_brackets: shown_brackets.filter(b => b != data.item) }) : setData({ ...card_data, shown_brackets: shown_brackets.concat(data.item) })}>
74
+ <View>
75
+ <Image
76
+ source={{ uri: league?.league_image }}
77
+ style={{ height:40, width:40, borderRadius:4 }}
78
+ resizeMode='cover'
79
+ />
80
+ </View>
81
+ <View style={{ flex:1, marginLeft:5 }}>
82
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{bracket.bracket_name}</Text>
83
+ <Text style={{ marginTop:3 }} size={12} color={Colors.brand.slate}>{started? 'In Progress' : `Starts at ${moment(bracket.scheduled_datetime).format('MMM DD YYYY hh:mm a')}`}</Text>
84
+ </View>
85
+ <View style={{ justifyContent:'center', alignItems:'center', padding:5, paddingRight:15 }}>
86
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{comps.length}</Text>
87
+ <Text style={{ marginTop:3 }} size={12} color={Colors.brand.slate} weight='regular'>COMPETITIONS</Text>
88
+ </View>
89
+ <Icons.ChevronIcon direction={selected?'up':'down'} size={10} color={Colors.brand.midnight} />
90
+ </TouchableOpacity>
91
+ {selected ?
92
+ <View style={{ padding:10 }}>
93
+ <FlatList
94
+ data={comps}
95
+ renderItem={renderCompetitions}
96
+ keyExtractor={(item) => item.bracket_competition_id.toString()}
97
+ />
98
+ </View>
99
+ :<></>}
100
+ </View>
101
+ )
102
+ }
103
+
104
+ if(!visible || loading){ return <></> }
105
+ return (
106
+ <View>
107
+ <TouchableOpacity style={{ flexDirection:'row', alignItems:'center', padding:20, borderBottomWidth:1, borderColor:Colors.shades.shade100 }} onPress={() => onClose()}>
108
+ <Icons.ChevronIcon direction='left' size={12} color={Colors.brand.midnight} />
109
+ <View style={{ flex:1, marginLeft:20 }}>
110
+ <Text size={18} color={Colors.brand.midnight} weight='bold'>Bracket Competitions</Text>
111
+ <Text style={{ marginTop:4 }} size={14} color={Colors.brand.slate} weight='regular'>Select a competition below to see more details</Text>
112
+ </View>
113
+ </TouchableOpacity>
114
+ <FlatList
115
+ data={unique_bracket_ids}
116
+ renderItem={renderBrackets}
117
+ keyExtractor={(item) => item.toString()}
118
+ />
119
+ </View>
120
+ )
121
+ }
122
+
123
+ export default BracketCompetitionSelector
@@ -0,0 +1,75 @@
1
+ import React from 'react';
2
+ import { FlatList, TouchableOpacity, View } from "react-native";
3
+ import type { BracketGroupProps, BracketRoundProps } from '../../../types';
4
+ import { Button, Checkbox, Text } from '../../../Components';
5
+ import Colors from '../../../constants/colors';
6
+
7
+ type BracketNavigatorProps = {
8
+ bracket_rounds:BracketRoundProps[],
9
+ bracket_groups:BracketGroupProps[],
10
+ selected_round?:BracketRoundProps,
11
+ selected_group?:BracketGroupProps,
12
+ onSelectRound:(r:BracketRoundProps) => void,
13
+ onSelectGroup:(g:BracketGroupProps) => void,
14
+ onClose: () => void
15
+ }
16
+
17
+ const BracketNavigator = ({ bracket_rounds, bracket_groups, selected_round, selected_group, onSelectGroup, onSelectRound, onClose }:BracketNavigatorProps) => {
18
+
19
+ const renderRounds = (data : { item:BracketRoundProps, index:number }) => {
20
+ const selected = selected_round?.bracket_round_id == data.item.bracket_round_id ? true : false
21
+ return (
22
+ <TouchableOpacity style={{ flexDirection:'row', alignItems:'center', width:120, padding:10 }} onPress={() => onSelectRound(data.item)}>
23
+ <Checkbox size={20} fill_style={{ borderRadius:100 }} style={{ borderRadius:100, marginRight:5 }} checked={selected} disabled onSelect={() => console.log('')}/>
24
+ <Text size={14} weight={selected?'bold':'regular'} color={Colors.brand.midnight}>{data.item.round_name}</Text>
25
+ </TouchableOpacity>
26
+ )
27
+ }
28
+
29
+ const renderGroups = (data : { item:BracketGroupProps, index:number }) => {
30
+ const selected = selected_group?.bracket_group_id == data.item.bracket_group_id ? true : false
31
+ return (
32
+ <TouchableOpacity style={{ flexDirection:'row', alignItems:'center', width:120, padding:10 }} onPress={() => onSelectGroup(data.item)}>
33
+ <Checkbox size={20} fill_style={{ borderRadius:100 }} style={{ borderRadius:100, marginRight:5 }} checked={selected} disabled onSelect={() => console.log('')}/>
34
+ <Text size={14} weight={selected?'bold':'regular'} color={Colors.brand.midnight}>{data.item.group_name}</Text>
35
+ </TouchableOpacity>
36
+ )
37
+ }
38
+
39
+ return (
40
+ <View style={{ minWidth:200 }}>
41
+ <View style={{ padding:10, flexDirection:'row', alignItems:'center', backgroundColor:Colors.shades.shade100, borderTopRightRadius:8, borderTopLeftRadius:8 }}>
42
+ <Text style={{ flex:1 }} size={14} color={Colors.brand.midnight} weight='bold'>Bracket Filters</Text>
43
+ <Button
44
+ title='X'
45
+ title_color={Colors.utility.error}
46
+ padding={10}
47
+ backgroundColor='transparent'
48
+ onPress={() => onClose()}
49
+ />
50
+ </View>
51
+ <View style={{ borderBottomWidth:1, borderColor:Colors.shades.shade600, padding:10 }}>
52
+ <View style={{ padding:5 }}>
53
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>Groups</Text>
54
+ </View>
55
+ <FlatList
56
+ data={bracket_groups}
57
+ renderItem={renderGroups}
58
+ keyExtractor={(item) => item.bracket_group_id.toString()}
59
+ />
60
+ </View>
61
+ <View style={{ borderBottomWidth:1, borderColor:Colors.shades.shade600, padding:10 }}>
62
+ <View style={{ padding:5 }}>
63
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>Rounds</Text>
64
+ </View>
65
+ <FlatList
66
+ data={bracket_rounds}
67
+ renderItem={renderRounds}
68
+ keyExtractor={(item) => item.bracket_round_id.toString()}
69
+ />
70
+ </View>
71
+ </View>
72
+ )
73
+ }
74
+
75
+ export default BracketNavigator
@@ -0,0 +1,86 @@
1
+ import React from 'react';
2
+ import { View } from "react-native"
3
+ import Colors from "../../../constants/colors"
4
+ import type { AthleteProps, BracketRoundProps, PlayerBracketPickProps, RoundEventProps, TeamProps } from '../../../types';
5
+ import RoundEventCard from './RoundEvent';
6
+ import { view_styles } from '../../../constants/styles';
7
+ import { Text } from '../../../Components';
8
+
9
+ type BracketRoundSectionProps = {
10
+ player_bracket_id?:string,
11
+ round_event_loading?:string,
12
+ player_bracket_picks: PlayerBracketPickProps[],
13
+ bracket_round:BracketRoundProps,
14
+ round_events:RoundEventProps[],
15
+ teams:TeamProps[],
16
+ athletes:AthleteProps[],
17
+ hide_titles?:boolean,
18
+ width:number,
19
+ orientation:'left'|'right',
20
+ active_bracket_group_id?:string,
21
+ onPick: (player_bracket_pick:PlayerBracketPickProps) => void,
22
+ bracket_size: { width:number, height:number },
23
+ left_bar?:boolean,
24
+ right_bar?:boolean
25
+ }
26
+
27
+ const BracketRoundSection = ({ bracket_round, round_event_loading, teams, round_events, width, hide_titles, player_bracket_picks, active_bracket_group_id, onPick }:BracketRoundSectionProps) => {
28
+
29
+ if(active_bracket_group_id){
30
+ round_events = round_events.filter(re => re.bracket_group_id == active_bracket_group_id)
31
+ }
32
+
33
+ const renderRoundEvents = (data: { item:RoundEventProps, index:number}) => {
34
+ const player_bracket_pick = player_bracket_picks.find(pbr => pbr.round_event_id == data.item.round_event_id);
35
+ const away_placeholder_pick = player_bracket_picks.find(pbr => pbr.round_event_id == data.item.away_placeholder);
36
+ const home_placeholder_pick = player_bracket_picks.find(pbr => pbr.round_event_id == data.item.home_placeholder);
37
+ const away_placeholder_team = teams.find(t => t.team_id == away_placeholder_pick?.pick_side_id)
38
+ const home_placeholder_team = teams.find(t => t.team_id == home_placeholder_pick?.pick_side_id)
39
+
40
+ const home_team = teams.find(t => t.team_id == data.item.home_side_id);
41
+ const away_team = teams.find(t => t.team_id == data.item.away_side_id);
42
+ const loading = round_event_loading == data.item.round_event_id ? true : false
43
+ return (
44
+ <View style={{ margin:2, flex:1, flexGrow:1, justifyContent:'center' }}>
45
+ <View style={{ margin:1, ...view_styles.float }}>
46
+ <RoundEventCard
47
+ round_event={data.item}
48
+ loading={loading}
49
+ round_events={round_events}
50
+ away_team={away_team}
51
+ home_team={home_team}
52
+ away_placeholder_team={away_placeholder_team}
53
+ home_placeholder_team={home_placeholder_team}
54
+ player_bracket_pick={player_bracket_pick}
55
+ width={width}
56
+ no_pick={bracket_round.carry_through ? true : false}
57
+ away_placeholder_pick={away_placeholder_pick}
58
+ home_placeholder_pick={home_placeholder_pick}
59
+ onPick={(player_bracket_pick) => {
60
+ if(bracket_round.carry_through){ return alert('Event is not eligible for picks') }
61
+ onPick(player_bracket_pick)
62
+ }}
63
+ />
64
+ </View>
65
+ </View>
66
+ )
67
+ }
68
+
69
+
70
+ return (
71
+ <View style={{ }}>
72
+ {!hide_titles ?
73
+ <View style={{ padding:10 }}>
74
+ <Text size={14} color={Colors.brand.midnight} weight='bold' textAlign="center">{bracket_round.round_name}</Text>
75
+ </View>
76
+ :<></>}
77
+ <View nativeID="round_events" style={{ flex:1 }}>
78
+ {round_events.filter(re => re.bracket_round_id == bracket_round.bracket_round_id).sort((a,b) => a.event_number - b.event_number).map((re, i) => {
79
+ return renderRoundEvents({ item: re, index:i })
80
+ })}
81
+ </View>
82
+ </View>
83
+ )
84
+ }
85
+
86
+ export default BracketRoundSection