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,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,83 @@
1
+ import React from 'react';
2
+ import { View, Image } from "react-native";
3
+ import { Button, Text } from '../../Components';
4
+ import type { BracketCompetitionProps, CompetitionPlayerBracketProps, MyPlayerProps, PlayerBalanceProps, PlayerBracketProps } from '../../types';
5
+ import { BracketCompetitionHelpers } from '../api';
6
+ import Colors from '../../constants/colors';
7
+ import PlayerBalanceCard from './PlayerBalanceCard';
8
+
9
+ type JoinCompetitionCardProps = {
10
+ player?:MyPlayerProps,
11
+ loading?:boolean,
12
+ player_bracket:PlayerBracketProps,
13
+ player_balance?:PlayerBalanceProps,
14
+ bracket_competition:BracketCompetitionProps,
15
+ onNotEnoughBalance:(data:{ bracket_competition:BracketCompetitionProps }) => void,
16
+ onEnterCompetition:(cpb:CompetitionPlayerBracketProps) => void,
17
+ onClose:() => void
18
+ }
19
+
20
+ const JoinCompetitionCard = ({ player, player_balance, loading, player_bracket, bracket_competition, onNotEnoughBalance, onEnterCompetition, onClose }:JoinCompetitionCardProps) => {
21
+
22
+ const buy_in_label = BracketCompetitionHelpers.getBuyInTitle(bracket_competition)
23
+
24
+ const handleEnter = () => {
25
+ const is_enough_balance = BracketCompetitionHelpers.isEnoughBalance(bracket_competition, player_balance);
26
+ if(!is_enough_balance){ return onNotEnoughBalance({ bracket_competition }) }
27
+ const cpb = BracketCompetitionHelpers.generateCompetitionPlayerBracket(bracket_competition.bracket_competition_id, player_bracket.player_bracket_id)
28
+ onEnterCompetition(cpb)
29
+ }
30
+
31
+ return (
32
+ <View style={{ minWidth:300, backgroundColor:Colors.shades.white, borderRadius:8 }}>
33
+ <View style={{ borderTopRightRadius:8, borderTopLeftRadius:8, backgroundColor:Colors.shades.shade100, padding:15 }}>
34
+ <Text size={16} color={Colors.brand.midnight} weight='bold'>{bracket_competition.competition_name}</Text>
35
+ </View>
36
+ {player && player_balance ?
37
+ <View style={{ padding:5, backgroundColor:Colors.incentive.gold_faded }}>
38
+ <PlayerBalanceCard
39
+ player={player}
40
+ player_balance={player_balance}
41
+ />
42
+ </View>
43
+ :<></>}
44
+ <View style={{ justifyContent:'center', alignItems:'center' }}>
45
+ <Image
46
+ source={{ uri: bracket_competition.image?.url }}
47
+ style={{ height:240, width:240 }}
48
+ resizeMode='cover'
49
+ />
50
+ </View>
51
+ <View style={{ flexDirection:'row', alignItems:'center', padding:10 }}>
52
+ <View style={{ flex:1 }}>
53
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{player_bracket.bracket_name}</Text>
54
+ <Text style={{ marginTop:3 }} size={12} color={Colors.brand.slate} weight='regular'>{(player_bracket.completion_pct*100).toFixed(2)}% Complete</Text>
55
+ </View>
56
+ </View>
57
+ <View style={{ flexDirection:'row', alignItems:'center', padding:10, backgroundColor:Colors.shades.shade100, borderBottomRightRadius:8, borderBottomLeftRadius:8 }}>
58
+ <Button
59
+ title='Close'
60
+ style={{ flex:1, marginRight:5 }}
61
+ padding={15}
62
+ title_color={Colors.brand.electric}
63
+ borderWidth={1}
64
+ borderColor={Colors.brand.electric}
65
+ onPress={() => onClose()}
66
+ />
67
+ <Button
68
+ title={buy_in_label}
69
+ disabled={loading}
70
+ style={{ flex:2, opacity: loading?0.5:1 }}
71
+ loading={loading}
72
+ padding={15}
73
+ title_color={Colors.shades.white}
74
+ backgroundColor={Colors.utility.success}
75
+ onPress={() => handleEnter()}
76
+
77
+ />
78
+ </View>
79
+ </View>
80
+ )
81
+ }
82
+
83
+ export default JoinCompetitionCard
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+ import { Image, View } from "react-native"
3
+ import type { MyPlayerProps, PlayerBalanceProps } from "../../types"
4
+ import Colors from '../../constants/colors';
5
+ import { Text } from '../../Components';
6
+
7
+ type PlayerBalanceCardProps = {
8
+ player_balance:PlayerBalanceProps,
9
+ player:MyPlayerProps
10
+ }
11
+
12
+ const PlayerBalanceCard = ({ player, player_balance }:PlayerBalanceCardProps) => {
13
+
14
+ return (
15
+ <View style={{ flexDirection:'row', alignItems:'center' }}>
16
+ <View>
17
+ <Image
18
+ source={{ uri: player.profile_pic }}
19
+ style={{ height:35, width:35, borderRadius:100 }}
20
+ resizeMode='cover'
21
+ />
22
+ </View>
23
+ <View style={{ flex:1, marginLeft:10 }}>
24
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{player.first_name} {player.last_name}</Text>
25
+ <Text style={{ marginTop:3 }} size={12} color={Colors.brand.slate}>P{player_balance.promo_balance.toFixed(2)} - E{player_balance.free_market_balance.toFixed(2)}</Text>
26
+ </View>
27
+ <View>
28
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>${player_balance.balance.toFixed(2)}</Text>
29
+ </View>
30
+ </View>
31
+ )
32
+ }
33
+
34
+ export default PlayerBalanceCard
@@ -0,0 +1,229 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { View, TouchableOpacity, FlatList, Image } from "react-native";
3
+ import type { AthleteProps, BracketCompetitionProps, CompetitionPlayerBracketProps, PlayerBracketProps, TeamProps } from '../../types';
4
+ import Colors from '../../constants/colors';
5
+ import { Button, Icons, Text, TextInput } from '../../Components';
6
+ import { BracketComeptitionApi, BracketCompetitionHelpers } from '../api';
7
+
8
+ type PlayerBracketManagerProps = {
9
+ visible:boolean,
10
+ width:number,
11
+ teams:TeamProps[],
12
+ athletes:AthleteProps[],
13
+ player_bracket?:PlayerBracketProps,
14
+ competition_player_brackets:CompetitionPlayerBracketProps[],
15
+ bracket_competitions:BracketCompetitionProps[],
16
+ onUpdateBracket: (pb:PlayerBracketProps) => void,
17
+ onEditPicks: (pb:PlayerBracketProps) => void,
18
+ onSelectCompetition: (bc:BracketCompetitionProps) => void,
19
+ onClose: () => void
20
+ }
21
+
22
+ const PlayerBracketManager = ({ visible, teams, athletes, player_bracket, bracket_competitions, competition_player_brackets, onEditPicks, onSelectCompetition, onUpdateBracket, onClose }:PlayerBracketManagerProps) => {
23
+ const [ info_expanded, setInfoExpanded ] = useState(true);
24
+ const [ manage_data, setData ] = useState<{
25
+ loading:boolean,
26
+ draft_bracket?:PlayerBracketProps,
27
+ active_comp_toggle:'entered'|'eligible',
28
+ }>({
29
+ loading: false,
30
+ draft_bracket: player_bracket,
31
+ active_comp_toggle: 'entered'
32
+ })
33
+ const { draft_bracket, active_comp_toggle } = manage_data;
34
+
35
+ useEffect(() => {
36
+ setData({ ...manage_data, draft_bracket: player_bracket })
37
+ },[player_bracket])
38
+
39
+
40
+ const renderCompetitions = (data: { item:BracketCompetitionProps, index:number }) => {
41
+ const payout = BracketCompetitionHelpers.getPayout(data.item)
42
+ return (
43
+ <TouchableOpacity style={{ flexDirection:'row', alignItems:'center', padding:10, borderBottomWidth:1, borderColor:Colors.shades.shade600 }}
44
+ onPress={() => onSelectCompetition(data.item)}>
45
+ <View>
46
+ <Image
47
+ source={{ uri: data.item.image?.url }}
48
+ style={{ height:35, width:35, borderRadius:3 }}
49
+ resizeMode='cover'
50
+ />
51
+ </View>
52
+ <View style={{ flex:1, marginLeft:5 }}>
53
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{data.item.competition_name}</Text>
54
+ <Text style={{ marginTop:5 }} size={14} color={Colors.brand.midnight} weight='regular'>Current Payout: ${payout.toFixed(2)}</Text>
55
+ </View>
56
+ <View style={{ padding:10 }}>
57
+ <Text size={16} weight='bold' color={Colors.brand.midnight} textAlign='center'>${data.item.buy_in}</Text>
58
+ <Text style={{ marginTop:5 }} size={12} weight='bold' color={Colors.brand.slate} textAlign='center'>{data.item.tickets_sold} / {data.item.max_brackets}</Text>
59
+ </View>
60
+ <Icons.ChevronIcon direction='right' color={Colors.brand.midnight} size={12} />
61
+ </TouchableOpacity>
62
+ )
63
+ }
64
+
65
+ const renderCompPlayerBrackets = (data: { item: CompetitionPlayerBracketProps, index:number }) => {
66
+ const bracket_competition = bracket_competitions.find(c => c.bracket_competition_id == data.item.bracket_competition_id);
67
+ if(!bracket_competition){ return <></> }
68
+ return (
69
+ <TouchableOpacity style={{ flexDirection:'row', alignItems:'center', padding:10, borderBottomWidth:1, borderColor:Colors.shades.shade600 }}
70
+ onPress={() => onSelectCompetition(bracket_competition)}>
71
+ <View>
72
+ <Image
73
+ source={{ uri: bracket_competition.image?.url }}
74
+ style={{ height:35, width:35, borderRadius:3 }}
75
+ resizeMode='cover'
76
+ />
77
+ </View>
78
+ <View style={{ flex:1, marginLeft:5 }}>
79
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{bracket_competition.competition_name}</Text>
80
+ <Text style={{ marginTop:5 }} size={14} color={Colors.brand.midnight} weight='regular'>{data.item.points_scored} Points ({data.item.possible_points} possible)</Text>
81
+ </View>
82
+ <View style={{ padding:10 }}>
83
+ <Text size={16} weight='bold' color={Colors.brand.midnight} textAlign='center'>{BracketCompetitionHelpers.formatPlace(data.item.place)}</Text>
84
+ <Text style={{ marginTop:5 }} size={12} weight='bold' color={Colors.brand.slate} textAlign='center'>${data.item.winnings.toFixed(2)}</Text>
85
+ </View>
86
+ <Icons.ChevronIcon direction='right' color={Colors.brand.midnight} size={12} />
87
+ </TouchableOpacity>
88
+ )
89
+ }
90
+
91
+ if(!visible || !player_bracket || !draft_bracket){ return <></> }
92
+
93
+ const is_changed = JSON.stringify(draft_bracket) != JSON.stringify(player_bracket) ? true : false
94
+ const champion_team = player_bracket.champion_id_type == 'team' ? teams.find(t => t.team_id == player_bracket.champion_id) : undefined
95
+ const champion_athlete = player_bracket.champion_id_type == 'athlete' ? athletes.find(t => t.team_id == player_bracket.champion_id) : undefined
96
+ const can_delete = BracketCompetitionHelpers.canDeletePlayerBracket(player_bracket, competition_player_brackets)
97
+
98
+ return (
99
+ <View>
100
+ <TouchableOpacity style={{ flexDirection:'row', alignItems:'center', padding:20, borderBottomWidth:1, borderColor:Colors.shades.shade100 }} onPress={() => onClose()}>
101
+ <Icons.ChevronIcon direction='left' size={12} color={Colors.brand.midnight} />
102
+ <View style={{ flex:1, marginLeft:20 }}>
103
+ <Text size={18} color={Colors.brand.midnight} weight='bold'>{player_bracket.bracket_name}</Text>
104
+ <Text style={{ marginTop:4 }} size={14} color={Colors.brand.slate} weight='regular'>Manage your bracket and enter competitions</Text>
105
+ </View>
106
+ </TouchableOpacity>
107
+ <View nativeID='bracket_info'>
108
+ <TouchableOpacity style={{ padding:20, flexDirection:'row', alignItems:'center', backgroundColor:Colors.shades.shade100 }} onPress={() => setInfoExpanded(!info_expanded)}>
109
+ <Text style={{flex:1}} size={16} color={Colors.brand.midnight} weight='bold'>Bracket Details</Text>
110
+ <Icons.ChevronIcon direction={info_expanded?'up':'down'} color={Colors.brand.midnight} size={10} />
111
+ </TouchableOpacity>
112
+ {info_expanded ?
113
+ <View style={{ padding:10, borderRadius:8, backgroundColor:Colors.shades.white }}>
114
+ <View style={{ flexDirection:'row', alignItems:'center', padding:10 }}>
115
+ <Text style={{ flex:1 }} size={14} weight='bold' color={Colors.brand.midnight}>Name</Text>
116
+ <TextInput
117
+ editable={player_bracket.status == 'active' ? true : false}
118
+ value={draft_bracket.bracket_name}
119
+ style={{ borderRadius:8, padding:10 }}
120
+ onChangeText={(text) => setData({ ...manage_data, draft_bracket: { ...draft_bracket, bracket_name:text } })}
121
+ />
122
+ </View>
123
+ <View style={{ flexDirection:'row', alignItems:'center', padding:10 }}>
124
+ <Text style={{ flex:1 }} size={14} color={Colors.brand.midnight} weight='bold'>% Complete</Text>
125
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{(player_bracket.completion_pct * 100).toFixed(2)}%</Text>
126
+ </View>
127
+ <View style={{ flexDirection:'row', alignItems:'center', padding:10 }}>
128
+ <Text style={{ flex:1 }} size={14} color={Colors.brand.midnight} weight='bold'>Champion</Text>
129
+ {player_bracket.champion_id_type == 'team' && champion_team ?
130
+ <View style={{ flexDirection:'row', alignItems:'center' }}>
131
+ <Image
132
+ source={{ uri: champion_team.image?.url }}
133
+ style={{ height:25, width:25, marginRight:10 }}
134
+ resizeMode='cover'
135
+ />
136
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{champion_team.market_name} {champion_team.name}</Text>
137
+ </View>
138
+ :player_bracket.champion_id_type == 'athlete' && champion_athlete ?
139
+ <View style={{ flexDirection:'row', alignItems:'center' }}>
140
+ <Image
141
+ source={{ uri: champion_athlete.image?.url }}
142
+ style={{ height:25, width:25, marginRight:10 }}
143
+ resizeMode='cover'
144
+ />
145
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{champion_athlete.first_name} {champion_athlete.last_name}</Text>
146
+ </View>
147
+ :<></>}
148
+ </View>
149
+
150
+ <View style={{ padding:10, flexDirection:'row', alignItems:'center' }}>
151
+ <View style={{ flex:1 }} />
152
+ {can_delete ?
153
+ <Button
154
+ title='DELETE'
155
+ style={{ marginRight:4 }}
156
+ title_color={Colors.shades.white}
157
+ backgroundColor={Colors.utility.error}
158
+ onPress={async() => {
159
+ const new_b = await BracketComeptitionApi.deletePlayerBracket(draft_bracket.player_bracket_id);
160
+ onUpdateBracket(new_b)
161
+ }}
162
+ />
163
+ :<></>}
164
+ {is_changed ?
165
+ <Button
166
+ title='SAVE'
167
+ title_color={Colors.shades.white}
168
+ backgroundColor={Colors.utility.success}
169
+ onPress={async() => {
170
+ const new_b = await BracketComeptitionApi.updatePlayerBracket(draft_bracket);
171
+ onUpdateBracket(new_b)
172
+ }}
173
+ />
174
+ : player_bracket.status == 'active' ?
175
+ <Button
176
+ title='UPDATE PICKS'
177
+ title_color={Colors.shades.white}
178
+ backgroundColor={Colors.brand.electric}
179
+ onPress={() => onEditPicks(player_bracket)}
180
+ />
181
+ :<></>}
182
+ </View>
183
+ </View>
184
+ :<></>}
185
+ {player_bracket.status == 'deleted' ?
186
+ <View style={{ position:'absolute', top:0, bottom:0, left:0, right:0, backgroundColor:Colors.shades.black_faded_heavy, justifyContent:'center', alignItems:'center' }}>
187
+ <View style={{ borderRadius:8, backgroundColor:Colors.shades.white, height:120, width:200, padding:10, justifyContent:'center', alignItems:'center' }}>
188
+ <Text size={18} weight='bold' color={Colors.utility.error}>DELETED!</Text>
189
+ </View>
190
+ </View>
191
+ :<></>}
192
+ </View>
193
+ {player_bracket.status != 'deleted' ?
194
+ <View>
195
+ <View nativeID='competitions'>
196
+ <View style={{ padding:10, paddingLeft:20, flexDirection:'row', alignItems:'center', backgroundColor:Colors.shades.shade100 }}>
197
+ <Text style={{flex:1}} size={16} color={Colors.brand.midnight} weight='bold'>Competitions</Text>
198
+ <View style={{ flexDirection:'row', alignItems:'center', borderRadius:22, backgroundColor:Colors.shades.white }}>
199
+ <TouchableOpacity style={{ padding:10, borderTopLeftRadius:22, borderBottomLeftRadius:22, backgroundColor:active_comp_toggle=='entered' ? Colors.brand.midnight: 'transparent' }} onPress={() => setData({ ...manage_data, active_comp_toggle: 'entered' })}>
200
+ <Text size={14} textAlign='center' color={active_comp_toggle=='entered'?Colors.shades.white:Colors.brand.midnight} weight={active_comp_toggle=='entered'?'bold':'regular'}>ENTERED</Text>
201
+ </TouchableOpacity>
202
+ <TouchableOpacity style={{ padding:10, borderTopRightRadius:22, borderBottomRightRadius:22, backgroundColor:active_comp_toggle=='eligible' ? Colors.brand.midnight: 'transparent' }} onPress={() => setData({ ...manage_data, active_comp_toggle: 'eligible' })}>
203
+ <Text size={14} textAlign='center' color={active_comp_toggle=='eligible'?Colors.shades.white:Colors.brand.midnight} weight={active_comp_toggle=='eligible'?'bold':'regular'}>ELIGIBLE</Text>
204
+ </TouchableOpacity>
205
+ </View>
206
+ </View>
207
+ </View>
208
+ <View nativeID='competition_list'>
209
+ {active_comp_toggle == 'entered' ?
210
+ <FlatList
211
+ data={competition_player_brackets.filter(cpb => cpb.player_bracket_id == player_bracket.player_bracket_id)}
212
+ renderItem={renderCompPlayerBrackets}
213
+ keyExtractor={(item) => item.competition_player_bracket_id.toString()}
214
+ />
215
+ : active_comp_toggle == 'eligible' ?
216
+ <FlatList
217
+ data={bracket_competitions}
218
+ keyExtractor={(item) => item.bracket_competition_id.toString()}
219
+ renderItem={renderCompetitions}
220
+ />
221
+ :<></>}
222
+ </View>
223
+ </View>
224
+ :<></>}
225
+ </View>
226
+ )
227
+ }
228
+
229
+ export default PlayerBracketManager
@@ -0,0 +1,119 @@
1
+ import React from 'react';
2
+ import { View, FlatList, TouchableOpacity, Image } from "react-native"
3
+ import type { AthleteProps, BracketCompetitionProps, BracketProps, CompetitionPlayerBracketProps, LeagueProps, PlayerBracketProps, TeamProps } from '../../types';
4
+ import { Button, Icons, Text } from '../../Components';
5
+ import Colors from '../../constants/colors';
6
+ import moment from 'moment-mini';
7
+
8
+ type PlayerBracketSelectorProps = {
9
+ visible:boolean,
10
+ brackets:BracketProps[],
11
+ leagues:LeagueProps[],
12
+ teams:TeamProps[],
13
+ athletes:AthleteProps[],
14
+ player_brackets:PlayerBracketProps[],
15
+ bracket_competitions:BracketCompetitionProps[],
16
+ competition_player_brackets:CompetitionPlayerBracketProps[]
17
+ onClose:() => void,
18
+ onSelect:(pb:PlayerBracketProps) => void,
19
+ }
20
+
21
+ const PlayerBracketSelector = ({ visible, brackets, leagues, teams, athletes, player_brackets, onSelect, onClose }:PlayerBracketSelectorProps) => {
22
+
23
+ const active_brackets = player_brackets.filter(pb => pb.status == 'active');
24
+
25
+ const unique_bracket_ids = [ ...new Set(active_brackets.map(b => b.bracket_id)) ]
26
+
27
+
28
+ const renderPlayerBrackets = (data : { item:PlayerBracketProps, index:number }) => {
29
+ const champion_team = data.item.champion_id_type == 'team' ? teams.find(t => t.team_id == data.item.champion_id) : undefined
30
+ const champion_athlete = data.item.champion_id_type == 'athlete' ? athletes.find(t => t.team_id == data.item.champion_id) : undefined
31
+ return (
32
+ <TouchableOpacity style={{ padding:10, flexDirection:'row', alignItems:'center', borderBottomWidth:1, borderColor:Colors.shades.shade600 }} onPress={() => onSelect(data.item)}>
33
+ {champion_team ?
34
+ <View style={{ marginRight:5 }}>
35
+ <Image
36
+ source={{ uri: champion_team.image?.url }}
37
+ style={{ height:35, width:35, borderRadius:4 }}
38
+ resizeMode='cover'
39
+ />
40
+ </View>
41
+ :champion_athlete ?
42
+ <View style={{ marginRight:5 }}>
43
+ <Image
44
+ source={{ uri: champion_athlete.image?.url }}
45
+ style={{ height:35, width:35, borderRadius:4 }}
46
+ resizeMode='cover'
47
+ />
48
+ </View>
49
+ :<></>}
50
+ <View style={{ flex:1 }}>
51
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{data.item.bracket_name}</Text>
52
+ <Text style={{ marginTop:4 }} size={12} color={Colors.brand.slate} weight='regular'>{(data.item.completion_pct*100).toFixed()}% Complete</Text>
53
+ </View>
54
+ <Button
55
+ title='VIEW'
56
+ title_color={Colors.shades.white}
57
+ backgroundColor={Colors.brand.electric}
58
+ disabled
59
+ onPress={() => console.log('')}
60
+ />
61
+ </TouchableOpacity>
62
+ )
63
+ }
64
+
65
+ const renderBrackets = (data: { item:string, index:number }) => {
66
+ const bracket = brackets.find(b => b.bracket_id == data.item);
67
+ if(!bracket){ return <></> }
68
+ const league= leagues.find(l => l.league_id == bracket.league_id);
69
+ if(!league){ return <></> }
70
+ const b_pbs = player_brackets.filter(pb => pb.bracket_id == data.item);
71
+ const started = moment().isAfter(moment(bracket.scheduled_datetime)) ? true : false
72
+ return (
73
+ <View>
74
+ <TouchableOpacity style={{ padding:10, backgroundColor:Colors.shades.shade100, flexDirection:'row', alignItems:'center' }}>
75
+ <View>
76
+ <Image
77
+ source={{ uri: league.league_image }}
78
+ style={{ height:35, width:35, borderRadius:4 }}
79
+ />
80
+ </View>
81
+ <View style={{ flex:1 }}>
82
+ <Text size={14} color={Colors.brand.midnight} weight='bold'>{bracket.bracket_name}</Text>
83
+ <Text style={{ marginTop:4 }} size={12} color={Colors.brand.slate} weight='bold'>{started?'In Progress':`Starts at ${moment(bracket.scheduled_datetime).format('MMM DD YYYY hh:mm a')}`}</Text>
84
+ </View>
85
+ </TouchableOpacity>
86
+ <View style={{ padding:10 }}>
87
+ <FlatList
88
+ data={b_pbs}
89
+ renderItem={renderPlayerBrackets}
90
+ keyExtractor={(item) => item.player_bracket_id.toString()}
91
+ />
92
+ </View>
93
+ </View>
94
+ )
95
+ }
96
+
97
+ if(!visible){ return <></> }
98
+
99
+ return (
100
+ <View>
101
+ <TouchableOpacity style={{ flexDirection:'row', alignItems:'center', padding:20, borderBottomWidth:1, borderColor:Colors.shades.shade100 }} onPress={() => onClose()}>
102
+ <Icons.ChevronIcon direction='left' size={12} color={Colors.brand.midnight} />
103
+ <View style={{ flex:1, marginLeft:20 }}>
104
+ <Text size={18} color={Colors.brand.midnight} weight='bold'>My Brackets</Text>
105
+ <Text style={{ marginTop:4 }} size={14} color={Colors.brand.slate} weight='regular'>Select a filled bracket below to manage it</Text>
106
+ </View>
107
+ </TouchableOpacity>
108
+ <View>
109
+ <FlatList
110
+ data={unique_bracket_ids}
111
+ renderItem={renderBrackets}
112
+ keyExtractor={(item) => item.toString()}
113
+ />
114
+ </View>
115
+ </View>
116
+ )
117
+ }
118
+
119
+ export default PlayerBracketSelector