be-components 1.6.0 → 1.6.1

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 (92) hide show
  1. package/lib/commonjs/CompetitionManager/components/AthleteSelector.js +50 -1
  2. package/lib/commonjs/CompetitionManager/components/AthleteSelector.js.map +1 -1
  3. package/lib/commonjs/Components/Icons.js +90 -0
  4. package/lib/commonjs/Components/Icons.js.map +1 -1
  5. package/lib/commonjs/MarketComponents/api/index.js +213 -0
  6. package/lib/commonjs/MarketComponents/api/index.js.map +1 -0
  7. package/lib/commonjs/MarketComponents/components/AthleteMarket/index.js +179 -0
  8. package/lib/commonjs/MarketComponents/components/AthleteMarket/index.js.map +1 -0
  9. package/lib/commonjs/MarketComponents/components/EventMarket/index.js +205 -0
  10. package/lib/commonjs/MarketComponents/components/EventMarket/index.js.map +1 -0
  11. package/lib/commonjs/MarketComponents/components/MarketButton/api/index.js +179 -0
  12. package/lib/commonjs/MarketComponents/components/MarketButton/api/index.js.map +1 -0
  13. package/lib/commonjs/MarketComponents/components/MarketButton/index.js +58 -0
  14. package/lib/commonjs/MarketComponents/components/MarketButton/index.js.map +1 -0
  15. package/lib/commonjs/MarketComponents/components/TeamEventMarket/api/index.js +48 -0
  16. package/lib/commonjs/MarketComponents/components/TeamEventMarket/api/index.js.map +1 -0
  17. package/lib/commonjs/MarketComponents/components/TeamEventMarket/index.js +479 -0
  18. package/lib/commonjs/MarketComponents/components/TeamEventMarket/index.js.map +1 -0
  19. package/lib/commonjs/MarketComponents/index.js +12 -0
  20. package/lib/commonjs/MarketComponents/index.js.map +1 -0
  21. package/lib/commonjs/index.js +7 -0
  22. package/lib/commonjs/index.js.map +1 -1
  23. package/lib/module/CompetitionManager/components/AthleteSelector.js +50 -1
  24. package/lib/module/CompetitionManager/components/AthleteSelector.js.map +1 -1
  25. package/lib/module/Components/Icons.js +90 -0
  26. package/lib/module/Components/Icons.js.map +1 -1
  27. package/lib/module/MarketComponents/api/index.js +207 -0
  28. package/lib/module/MarketComponents/api/index.js.map +1 -0
  29. package/lib/module/MarketComponents/components/AthleteMarket/index.js +172 -0
  30. package/lib/module/MarketComponents/components/AthleteMarket/index.js.map +1 -0
  31. package/lib/module/MarketComponents/components/EventMarket/index.js +198 -0
  32. package/lib/module/MarketComponents/components/EventMarket/index.js.map +1 -0
  33. package/lib/module/MarketComponents/components/MarketButton/api/index.js +172 -0
  34. package/lib/module/MarketComponents/components/MarketButton/api/index.js.map +1 -0
  35. package/lib/module/MarketComponents/components/MarketButton/index.js +51 -0
  36. package/lib/module/MarketComponents/components/MarketButton/index.js.map +1 -0
  37. package/lib/module/MarketComponents/components/TeamEventMarket/api/index.js +42 -0
  38. package/lib/module/MarketComponents/components/TeamEventMarket/api/index.js.map +1 -0
  39. package/lib/module/MarketComponents/components/TeamEventMarket/index.js +470 -0
  40. package/lib/module/MarketComponents/components/TeamEventMarket/index.js.map +1 -0
  41. package/lib/module/MarketComponents/index.js +5 -0
  42. package/lib/module/MarketComponents/index.js.map +1 -0
  43. package/lib/module/index.js +2 -1
  44. package/lib/module/index.js.map +1 -1
  45. package/lib/typescript/src/CompetitionManager/components/AthleteSelector.d.ts.map +1 -1
  46. package/lib/typescript/src/Components/Icons.d.ts +3 -0
  47. package/lib/typescript/src/Components/Icons.d.ts.map +1 -1
  48. package/lib/typescript/src/MarketComponents/api/index.d.ts +22 -0
  49. package/lib/typescript/src/MarketComponents/api/index.d.ts.map +1 -0
  50. package/lib/typescript/src/MarketComponents/components/AthleteMarket/index.d.ts +25 -0
  51. package/lib/typescript/src/MarketComponents/components/AthleteMarket/index.d.ts.map +1 -0
  52. package/lib/typescript/src/MarketComponents/components/EventMarket/index.d.ts +21 -0
  53. package/lib/typescript/src/MarketComponents/components/EventMarket/index.d.ts.map +1 -0
  54. package/lib/typescript/src/MarketComponents/components/MarketButton/api/index.d.ts +15 -0
  55. package/lib/typescript/src/MarketComponents/components/MarketButton/api/index.d.ts.map +1 -0
  56. package/lib/typescript/src/MarketComponents/components/MarketButton/index.d.ts +12 -0
  57. package/lib/typescript/src/MarketComponents/components/MarketButton/index.d.ts.map +1 -0
  58. package/lib/typescript/src/MarketComponents/components/TeamEventMarket/api/index.d.ts +10 -0
  59. package/lib/typescript/src/MarketComponents/components/TeamEventMarket/api/index.d.ts.map +1 -0
  60. package/lib/typescript/src/MarketComponents/components/TeamEventMarket/index.d.ts +25 -0
  61. package/lib/typescript/src/MarketComponents/components/TeamEventMarket/index.d.ts.map +1 -0
  62. package/lib/typescript/src/MarketComponents/index.d.ts +25 -0
  63. package/lib/typescript/src/MarketComponents/index.d.ts.map +1 -0
  64. package/lib/typescript/src/index.d.ts +2 -1
  65. package/lib/typescript/src/index.d.ts.map +1 -1
  66. package/package.json +1 -1
  67. package/src/CompetitionManager/components/AthleteSelector.tsx +36 -0
  68. package/src/Components/Icons.tsx +50 -0
  69. package/src/MarketComponents/api/index.ts +143 -0
  70. package/src/MarketComponents/components/AthleteMarket/index.tsx +109 -0
  71. package/src/MarketComponents/components/EventMarket/index.tsx +115 -0
  72. package/src/MarketComponents/components/MarketButton/api/index.ts +152 -0
  73. package/src/MarketComponents/components/MarketButton/index.tsx +37 -0
  74. package/src/MarketComponents/components/TeamEventMarket/api/index.ts +35 -0
  75. package/src/MarketComponents/components/TeamEventMarket/index.tsx +295 -0
  76. package/src/MarketComponents/index.tsx +5 -0
  77. package/src/index.tsx +2 -0
  78. package/src/types.d.ts +78 -2
  79. package/lib/commonjs/Markets/api/index.js +0 -28
  80. package/lib/commonjs/Markets/api/index.js.map +0 -1
  81. package/lib/commonjs/Markets/components/MarketButton.js +0 -25
  82. package/lib/commonjs/Markets/components/MarketButton.js.map +0 -1
  83. package/lib/module/Markets/api/index.js +0 -23
  84. package/lib/module/Markets/api/index.js.map +0 -1
  85. package/lib/module/Markets/components/MarketButton.js +0 -18
  86. package/lib/module/Markets/components/MarketButton.js.map +0 -1
  87. package/lib/typescript/src/Markets/api/index.d.ts +0 -7
  88. package/lib/typescript/src/Markets/api/index.d.ts.map +0 -1
  89. package/lib/typescript/src/Markets/components/MarketButton.d.ts +0 -11
  90. package/lib/typescript/src/Markets/components/MarketButton.d.ts.map +0 -1
  91. package/src/Markets/api/index.ts +0 -18
  92. package/src/Markets/components/MarketButton.tsx +0 -24
@@ -0,0 +1,115 @@
1
+ import React from 'react';
2
+ import { View, Image, TouchableOpacity } from 'react-native';
3
+ import type { BestAvailableOrderProps, EventOrderStatProps, EventProps, MarketProps, MarketSideOptionProps, OrderProps, TradeProps } from '../../../types';
4
+ import { MarketButtonHelpers } from '../MarketButton/api';
5
+ import MarketButton from '../../components/MarketButton';
6
+ import { Icons, LinearDiagnal, Text } from '../../../Components';
7
+ import Colors from '../../../constants/colors';
8
+ import { view_styles } from '../../../constants/styles';
9
+ import { TeamEventMarketHelpers } from '../TeamEventMarket/api';
10
+ import { MarketComponentHelpers } from '../../api';
11
+
12
+ type EventMarketProps = {
13
+ event:EventProps,
14
+ width?:number,
15
+ market:MarketProps,
16
+ hide_market_banner?:boolean,
17
+ latest_trades:TradeProps[],
18
+ best_available_orders:BestAvailableOrderProps[],
19
+ event_order_stats:EventOrderStatProps[],
20
+ default_price_view:'last_trade'|'best_available',
21
+ onOrder:(order:OrderProps) => void,
22
+ onView:(data: { event_id:string, event_type:string, market_id:string }) => void
23
+ }
24
+
25
+ const EventMarket = ({ width, event, market, latest_trades, best_available_orders, hide_market_banner, event_order_stats, default_price_view, onOrder, onView }:EventMarketProps) => {
26
+ const { liquidity, open_order_count } = MarketComponentHelpers.getLiqudity(event_order_stats);
27
+
28
+ const renderSides = (data:{ item:MarketSideOptionProps, index:number, market:MarketProps }) => {
29
+ const side_details = MarketComponentHelpers.getTeamEventSideIds(event, market, data.item, undefined, undefined);
30
+ if(!side_details){ return }
31
+ let trade = MarketButtonHelpers.getVisibleTrade(default_price_view, data.market, data.item, latest_trades, best_available_orders, side_details.side_id, side_details.reversed_side_id);
32
+ if(!trade){
33
+ trade = MarketButtonHelpers.getTradeFromMarket(market, event.event_id, 'team', data.item.side, data.item.id_source, side_details.side_id, side_details.reversed_side_id);
34
+ }
35
+ if(!trade){ return <></> }
36
+ let side_label = event[data.item.side as keyof EventProps].abbr
37
+ return (
38
+ <View style={{ margin:2, height:50, width:75 }}>
39
+ <MarketButton
40
+ side_option={data.item}
41
+ market={data.market}
42
+ side_label={side_label}
43
+ trade={trade}
44
+ onPress={(order) => {
45
+ const order_title = MarketComponentHelpers.getOrderTitleForTeamEvent(order, market, event);
46
+ if(!order_title){ return alert('Unable to process order') }
47
+ onOrder({ ...order, title: order_title })
48
+ }}
49
+ />
50
+ </View>
51
+ )
52
+ }
53
+
54
+ return (
55
+ <View style={{ ...view_styles.section, flex:1, borderWidth:1, borderColor:Colors.shades.shade600, width, maxWidth:175 }}>
56
+ {!hide_market_banner ?
57
+ <LinearDiagnal
58
+ label={market.stat_label ?? market.type}
59
+ label_size={14}
60
+ style={{ borderTopLeftRadius:8, padding:5 }}
61
+ left_color={Colors.incentive.gold}
62
+ right_color={'#ebd197'}
63
+ />
64
+ :<></>}
65
+ <View style={{ ...view_styles.section_body, flex:1, padding:0, justifyContent:'center', alignItems:'center' }}>
66
+ <View style={{flexDirection:'row', alignItems:'center'}}>
67
+ <Image
68
+ source={{ uri: event.away?.image?.url }}
69
+ style={{ height:50, width:50, marginRight:5 }}
70
+ resizeMode='cover'
71
+ />
72
+ <Text theme='body'>VS</Text>
73
+ <Image
74
+ source={{ uri: event.home?.image?.url }}
75
+ style={{ height:50, width:50, marginLeft:5 }}
76
+ resizeMode='cover'
77
+ />
78
+ </View>
79
+ <View style={{ padding:10, paddingBottom:0 }}>
80
+ <Text weight='bold' size={14} color={Colors.brand.midnight} textAlign='center'>{event.event_title}</Text>
81
+ <Text style={{ marginTop:3 }} color={Colors.brand.midnight} weight='regular' textAlign='center' size={12}>{TeamEventMarketHelpers.getTimeDetail(event)}</Text>
82
+ </View>
83
+ </View>
84
+ <View nativeID='market_sides' style={{ flexDirection:'row', justifyContent:'center', alignItems:'center', padding:10 }}>
85
+ {market.side_options.sort((a,b) => {
86
+ let a_t = a.side == market.trade_side ? 1 : 0
87
+ let b_t = b.side == market.trade_side ? 1 : 0
88
+ return a_t - b_t
89
+ }).map((so, index) => {
90
+ return renderSides({ item:so, index, market })
91
+ })}
92
+
93
+ </View>
94
+ <View style={{ backgroundColor:Colors.shades.shade100, padding:10, flexDirection:'row', alignItems:'center', borderBottomLeftRadius:8, borderBottomRightRadius:8 }}>
95
+ <TouchableOpacity style={{ flex:1, flexDirection:'row' }} onPress={() => {
96
+ onView({
97
+ event_id: event.event_id,
98
+ event_type: 'team',
99
+ market_id: market.market_id
100
+ });
101
+ }}>
102
+ <View style={{ backgroundColor:Colors.shades.white, height:30, width:30, borderRadius:100, justifyContent:'center', alignItems:'center', ...view_styles.float }}>
103
+ <Icons.LiquidityIcon color={Colors.brand.midnight} size={30}/>
104
+ </View>
105
+ <View style={{ marginLeft:10 }}>
106
+ <Text theme='body_2'>Liquidity</Text>
107
+ <Text size={12} color={Colors.brand.electric} weight='semibold'>${liquidity.toFixed()} {open_order_count} Orders</Text>
108
+ </View>
109
+ </TouchableOpacity>
110
+ </View>
111
+ </View>
112
+ )
113
+ }
114
+
115
+ export default EventMarket
@@ -0,0 +1,152 @@
1
+ import moment from "moment-mini";
2
+ import Colors from "../../../../constants/colors";
3
+ import type { BestAvailableOrderProps, MarketProps, MarketSideOptionProps, OrderProps, TradeProps } from "../../../../types";
4
+ import { MarketComponentHelpers } from "../../../api";
5
+
6
+
7
+ export const MarketButtonHelpers = {
8
+ getButtonLabel: (market:MarketProps, side_option:MarketSideOptionProps, trade:TradeProps) => {
9
+ let v_1 = MarketComponentHelpers.getVar1Label(market, trade.var_1, side_option.side);
10
+ let o_1 = MarketComponentHelpers.getOddsLabel(trade.odds);
11
+ return { var_1: v_1, odds:o_1, color: trade.draft_liquidity? Colors.highlights.highlight500Faded : Colors.shades.shade100 }
12
+ },
13
+ getVisibleTrade: (default_price_view:'best_available'|'last_trade', market:MarketProps, side_option:MarketSideOptionProps, latest_trades:TradeProps[], best_available_orders:BestAvailableOrderProps[], side_id:string, reversed_side_id:string) => {
14
+ const order = best_available_orders.find(o => o.market_id == market.market_id && o.side == side_option.side && o.show);
15
+ const o_side_order = best_available_orders.find(o => o.market_id == market.market_id && o.side != side_option.side && o.show);
16
+ let trade = latest_trades.find(t => t.market_type == 'FOR_MONEY' && t.market_id == market.market_id && t.side == side_option.side);
17
+ switch(default_price_view){
18
+ case 'best_available':
19
+ if(order){ return MarketButtonHelpers.getTradeFromAvailableOrder(order, reversed_side_id) }
20
+ if(o_side_order){
21
+ //Now lets reverse this order and get a trade for it
22
+ const reversed_order = MarketButtonHelpers.reverseBAOrder(o_side_order, market, side_id);
23
+ if(!reversed_order){ return undefined }
24
+ return MarketButtonHelpers.getTradeFromAvailableOrder(reversed_order, reversed_side_id)
25
+ }
26
+ if(trade){ return trade }
27
+ return undefined
28
+ case 'last_trade':
29
+ if(trade){ return trade }
30
+ return undefined
31
+ default: return undefined
32
+ }
33
+ },
34
+ reverseBAOrder: (order:BestAvailableOrderProps, market:MarketProps, side_id:string):BestAvailableOrderProps | undefined => {
35
+ const side_option = market.side_options.find(so => so.side != order.side);
36
+ if(!side_option){ return undefined }
37
+ return {
38
+ ...order,
39
+ side: side_option.side,
40
+ side_id: side_id,
41
+ odds: order.odds * -1,
42
+ var_1: market.type == 'Spread' ? order.var_1 * -1 : order.var_1,
43
+ probability: 1 - order.probability,
44
+ title: '',
45
+ open_amt: 0,
46
+ called_amt: 0,
47
+ potential_winnings: 0
48
+ }
49
+ },
50
+ getTradeFromMarket: (market:MarketProps, event_id:string, event_type: 'match'|'tournament'|'team', side:string, side_type:string, side_id:string, reversed_side_id:string):TradeProps => {
51
+ return {
52
+ trade_id:'',
53
+ event_id,
54
+ event_type,
55
+ trade_amt: 0,
56
+ cumulative_amt: 0,
57
+ latest:true,
58
+ probability:0.5,
59
+ odds: 100,
60
+ create_datetime:'',
61
+ last_update_datetime: '',
62
+ market_id: market.market_id,
63
+ var_1: 0,
64
+ side_id,
65
+ side_type:side_type as 'team'|'exotic'|'side'|'athlete',
66
+ reversed_side_id,
67
+ side,
68
+ position_ids:[],
69
+ market_type: 'FREE'
70
+ }
71
+ },
72
+ getTradeFromAvailableOrder : (ba:BestAvailableOrderProps, reversed_side_id:string):TradeProps => {
73
+ return {
74
+ trade_id:'',
75
+ event_id: ba.event_id,
76
+ event_type: ba.event_type as 'tournament'|'team'|'match',
77
+ cumulative_amt: 0,
78
+ trade_amt: 0,
79
+ create_datetime: '', last_update_datetime: '',
80
+ market_id: ba.market_id,
81
+ var_1: ba.var_1,
82
+ side: ba.side,
83
+ side_id: ba.side_id,
84
+ draft_liquidity: ba.open_amt,
85
+ reversed_side_id,
86
+ probability: ba.probability,
87
+ odds: ba.odds,
88
+ side_type: ba.side_type as 'team'|'athlete'|'side',
89
+ market_type: 'FOR_MONEY',
90
+ latest: true,
91
+ position_ids: []
92
+ }
93
+ },
94
+ reverseTradeFromOrder: (order:BestAvailableOrderProps, market:MarketProps):TradeProps => {
95
+ return {
96
+ trade_id:'',
97
+ side: order.side,
98
+ side_id: order.side_id,
99
+ reversed_side_id: '',
100
+ market_id: order.market_id,
101
+ event_id: order.event_id,
102
+ event_type: order.event_type as 'team'|'tournament'|'match',
103
+ odds: order.odds * -1,
104
+ var_1: market.type == 'Spread' ? order.var_1 * -1 : order.var_1,
105
+ probability: 1 - order.probability,
106
+ side_type: order.side_type as 'athlete'|'team'|'side',
107
+ market_type: 'FOR_MONEY',
108
+ latest: true,
109
+ trade_amt: 0, cumulative_amt:0,
110
+ position_ids: [],
111
+ last_update_datetime: '', create_datetime:''
112
+ }
113
+ },
114
+ getOrderFromTrade: (trade:TradeProps, unit_size?:number):OrderProps => {
115
+ let open_amt = 10
116
+ if(unit_size){ open_amt = unit_size }
117
+ let draft_liquidity = 0
118
+ if(trade.draft_liquidity){ draft_liquidity = trade.draft_liquidity }
119
+
120
+ return {
121
+ order_id: '',
122
+ player_id: '',
123
+ be_type: 'market', //TODO - Make this dynamic,
124
+ open_amt,
125
+ called_amt: 0,
126
+ buy_sell_ind: 'buy',
127
+ rejections:0,
128
+ commission_pct:0,
129
+ available_for_parlays: false,
130
+ event_id: trade.event_id,
131
+ draft_liquidity,
132
+ event_type: trade.event_type,
133
+ side: trade.side as 'home'|'away'|'over'|'under'|'yes'|'no',
134
+ side_type: trade.side_type as 'team' | 'side' | 'athlete',
135
+ resolution_status: 'inprogress',
136
+ side_id: trade.side_id,
137
+ order_type: trade.limit_override ? 'limit': 'market',
138
+ potential_winnings: 0,
139
+ collar_pct: .01,
140
+ positions: [],
141
+ market_id: trade.market_id,
142
+ title: '',
143
+ probability: trade.probability,
144
+ odds: trade.odds,
145
+ var_1: trade.var_1,
146
+ market_type: trade.market_type,
147
+ position_ids: [],
148
+ status: 'approved',
149
+ expire_datetime: moment().add(1, 'hours')
150
+ }
151
+ }
152
+ }
@@ -0,0 +1,37 @@
1
+ import React from 'react';
2
+ import { TouchableOpacity, View } from "react-native"
3
+ import Text from '../../../Components/Text';
4
+ import type { MarketProps, MarketSideOptionProps, OrderProps, TradeProps } from '../../../types';
5
+ import Colors from '../../../constants/colors';
6
+ import { MarketButtonHelpers } from './api';
7
+
8
+ type MarketButtonProps = {
9
+ market:MarketProps,
10
+ side_option:MarketSideOptionProps,
11
+ side_label?:string,
12
+ trade:TradeProps,
13
+ onPress: (order:OrderProps) => void
14
+ }
15
+ const MarketCard = ({ side_option, market, trade, side_label, onPress }:MarketButtonProps) => {
16
+ const { var_1, odds, color } = MarketButtonHelpers.getButtonLabel(market, side_option, trade);
17
+ const handlePress = () => {
18
+ return onPress(MarketButtonHelpers.getOrderFromTrade(trade))
19
+ }
20
+
21
+ return (
22
+ <TouchableOpacity style={{ flex:1, padding:5, backgroundColor:color, borderRadius:4, justifyContent:'center' }}
23
+ onPress={() => handlePress()}>
24
+ <View>
25
+ {side_label ?
26
+ <Text size={12} color={Colors.brand.midnight} weight='semibold' textAlign='center'>{side_label}</Text>
27
+ :<></>}
28
+ {market.var_1_required ?
29
+ <Text size={12} color={Colors.brand.midnight} weight='semibold' textAlign='center'>{var_1}</Text>
30
+ :<></>}
31
+ <Text style={{ marginTop:2 }} size={12} color={Colors.brand.midnight} weight='semibold' textAlign='center'>{odds}</Text>
32
+ </View>
33
+ </TouchableOpacity>
34
+ )
35
+ }
36
+
37
+ export default MarketCard
@@ -0,0 +1,35 @@
1
+ import moment from "moment-mini";
2
+ import type { AthleteProps, EventOrderStatProps, EventProps, MarketProps, TradeProps } from "../../../../types"
3
+
4
+ export { TeamEventMarketHelpers }
5
+ const TeamEventMarketHelpers = {
6
+ getPrimaryMarkets: (event:EventProps, markets:MarketProps[]):MarketProps[] => {
7
+ if(!event.supported_markets){ return [] }
8
+ let event_markets = markets.filter(m => event.supported_markets?.filter(sm => !sm.removed).map(sm => sm.market_id.toString()).includes(m.market_id.toString()));
9
+ return event_markets.filter(m => m.primary_market);
10
+ },
11
+ getNonPrimaryMarkets:(event:EventProps, markets:MarketProps[]):MarketProps[] => {
12
+ if(!event.supported_markets){ return [] }
13
+ let event_markets = markets.filter(m => event.supported_markets?.filter(sm => !sm.removed).map(sm => sm.market_id.toString()).includes(m.market_id.toString()));
14
+ return event_markets.filter(m => !m.primary_market);
15
+ },
16
+ getTimeDetail: (event:EventProps) => {
17
+ if(['scheduled','created'].includes(event.status)){ return moment(event.scheduled_datetime).format('MM/DD @ hh:mm a') }
18
+ return event.time_detail
19
+ },
20
+ sortNonPrimaryMarkets: (markets:MarketProps[], event_order_stats:EventOrderStatProps[]) => {
21
+ let sorted_stats = event_order_stats.filter(s => s.market_type == 'FOR_MONEY' && markets.map(m => m.market_id.toString()).includes(s.market_id.toString()));
22
+ return sorted_stats.sort((a,b) => parseInt(b.open_order_count as string) - parseInt(a.open_order_count as string))
23
+ },
24
+ sortAthleteMarkets: (market:MarketProps, event_order_stats:EventOrderStatProps[], latest_trades:TradeProps[], athletes:AthleteProps[]):AthleteProps[] => {
25
+ if(!market){ return [] }
26
+ let market_stats = event_order_stats.filter(s => s.market_id == market.market_id && s.market_type == 'FOR_MONEY');
27
+ let market_trades = latest_trades.filter(t => t.market_type == 'FOR_MONEY' && t.market_id == market.market_id && t.side_type == 'athlete');
28
+ let filtered_athletes = athletes.filter(a => market_trades.map(t => t.side_id.toString()).includes(a.athlete_id.toString()));
29
+ return filtered_athletes.sort((a,b) => {
30
+ let old_order_count = market_stats.filter(s => s.side_id == a.athlete_id).reduce((a,b) => a + parseInt(b.open_order_count as string), 0)
31
+ let new_order_count = market_stats.filter(s => s.side_id == b.athlete_id).reduce((a,b) => a + parseInt(b.open_order_count as string), 0)
32
+ return new_order_count - old_order_count
33
+ })
34
+ }
35
+ }
@@ -0,0 +1,295 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { View, Image, FlatList, TouchableOpacity, ActivityIndicator } from 'react-native';
3
+ import type { AthleteProps, BestAvailableOrderProps, CompetitionProps, EventOrderStatProps, EventProps, MarketProps, MarketSideOptionProps, OrderProps, TradeProps } from '../../../types';
4
+ import { view_styles } from '../../../constants/styles';
5
+ import { Button, Icons, LinearDiagnal, Text } from '../../../Components';
6
+ import {TeamEventMarketHelpers} from './api';
7
+ import MarketButton from '../../components/MarketButton';
8
+ import Colors from '../../../constants/colors';
9
+ import moment from 'moment-mini';
10
+ import AthleteMarket from '../../components/AthleteMarket';
11
+ import EventMarket from '../../components/EventMarket';
12
+
13
+ import { MarketComponentApi, MarketComponentHelpers } from '../../api';
14
+ import { MarketButtonHelpers } from '../MarketButton/api';
15
+
16
+ type TeamEventMarketProps = {
17
+ event:EventProps,
18
+ markets:MarketProps[],
19
+ competition?:CompetitionProps,
20
+ latest_trades:TradeProps[],
21
+ best_available_orders:BestAvailableOrderProps[],
22
+ event_order_stats:EventOrderStatProps[],
23
+ default_price_view: 'last_trade'|'best_available',
24
+ onView:(data:{ event_id:string, event_type:string, market_id:string, side_type?:string, side_id?:string }) => void,
25
+ onOrder:(order:OrderProps) => void,
26
+ onExpand?:(expanded:boolean) => void,
27
+ onCompetitionSelect:(competition_id:string) => void,
28
+ onViewAdditionalMarkets: (event_id:string, event_type:string) => void
29
+ }
30
+ const TeamEventMarket = ({ event, competition, markets, latest_trades, best_available_orders, event_order_stats, default_price_view, onCompetitionSelect, onExpand, onOrder, onView, onViewAdditionalMarkets }:TeamEventMarketProps) => {
31
+ const [ expanded_data, setExpandedData ] = useState<{
32
+ expanded:boolean,
33
+ loaded:boolean,
34
+ loading:boolean,
35
+ athletes:AthleteProps[]
36
+ }>({
37
+ loaded:false,
38
+ loading:false,
39
+ expanded:false,
40
+ athletes:[]
41
+ })
42
+ const { expanded, athletes, loaded, loading } = expanded_data;
43
+
44
+ useEffect(() => {
45
+ MarketComponentApi.setEnvironment();
46
+ },[])
47
+
48
+ const expandedEvent = async() => {
49
+ if(onExpand){ onExpand(expanded ? false : true) }
50
+ if(expanded){ return setExpandedData({ ...expanded_data, expanded: false }) }
51
+ if(loaded){ return setExpandedData({ ...expanded_data, expanded: true }) }
52
+ setExpandedData({ ...expanded_data, expanded:true, loading:true });
53
+
54
+ //Need to load our athletes in here!
55
+ const away_athletes = await MarketComponentApi.getAthletesByTeamId(event.away_team_id);
56
+ const home_athletes = await MarketComponentApi.getAthletesByTeamId(event.home_team_id);
57
+ setExpandedData({
58
+ expanded:true,
59
+ loaded:true,
60
+ loading:false,
61
+ athletes: away_athletes.concat(home_athletes)
62
+ })
63
+ }
64
+
65
+ const primary_markets = TeamEventMarketHelpers.getPrimaryMarkets(event, markets);
66
+
67
+
68
+ const renderSides = (data:{ item:MarketSideOptionProps, index:number, market:MarketProps }) => {
69
+ const side_details = MarketComponentHelpers.getTeamEventSideIds(event, data.market, data.item);
70
+ if(!side_details){ return <></> } //Bomb out if we cant get the side details
71
+ let trade = MarketButtonHelpers.getVisibleTrade(default_price_view, data.market, data.item, latest_trades, best_available_orders, side_details.side_id, side_details.reversed_side_id);
72
+ if(!trade){
73
+ trade = MarketButtonHelpers.getTradeFromMarket(data.market, event.event_id, 'team', data.item.side, data.item.id_source, side_details.side_id, side_details.reversed_side_id)
74
+ }
75
+ if(!trade){ return <></> }
76
+ return (
77
+ <View style={{ margin:2, width:50, height:50 }}>
78
+ <MarketButton
79
+ side_option={data.item}
80
+ market={data.market}
81
+ trade={trade}
82
+ onPress={(order) => {
83
+ const order_title = MarketComponentHelpers.getOrderTitleForTeamEvent(order, data.market, event);
84
+ if(!order_title){ return alert('Unable to process order') }
85
+ onOrder({ ...order, title: order_title })
86
+ }}
87
+ />
88
+ </View>
89
+ )
90
+ }
91
+
92
+ const renderMarketHeaders = (data:{ item:MarketProps, index:number }) => {
93
+ return (
94
+ <View style={{ width:50, marginLeft:2, marginRight:2 }}>
95
+ <Text size={12} color={Colors.brand.midnight} textAlign='center'>{data.item.type.toUpperCase()}</Text>
96
+ </View>
97
+ )
98
+ }
99
+
100
+ const renderNonPrimaryMarkets = (data: { item:EventOrderStatProps, index:number }) => {
101
+ const market = markets.find(m => m.market_id == data.item.market_id);
102
+ if(!market){ return <></> }
103
+ switch(market.level){
104
+ case 'athlete':
105
+ const athlete = athletes.find(a => a.athlete_id == data.item.side_id)
106
+ if(!athlete){ return <></> }
107
+ const athlete_trades = latest_trades.filter(t => t.market_type == 'FOR_MONEY' && t.market_id == data.item.market_id && t.side_type == 'athlete' && t.side_id == data.item.side_id);
108
+ const athlete_orders = best_available_orders.filter(t => t.market_id == data.item.market_id && t.side_type == 'athlete' && t.side_id == data.item.side_id);
109
+ return (
110
+ <View>
111
+ <AthleteMarket
112
+ event={event}
113
+ event_type='team'
114
+ athlete={athlete}
115
+ market={market}
116
+ event_order_stats={[data.item]}
117
+ latest_trades={athlete_trades}
118
+ default_price_view={default_price_view}
119
+ best_available_orders={athlete_orders}
120
+ onOrder={onOrder}
121
+ onView={onView}
122
+ />
123
+ </View>
124
+ )
125
+ case 'event':
126
+ const event_trades = latest_trades.filter(t => t.market_type == 'FOR_MONEY' && t.market_id == data.item.market_id);
127
+ const event_orders = best_available_orders.filter(t => t.market_id == data.item.market_id);
128
+ return (
129
+ <View>
130
+ <EventMarket
131
+ event={event}
132
+ market={market}
133
+ event_order_stats={[data.item]}
134
+ latest_trades={event_trades}
135
+ best_available_orders={event_orders}
136
+ default_price_view={default_price_view}
137
+ onOrder={onOrder}
138
+ onView={onView}
139
+ />
140
+ </View>
141
+ )
142
+ default: return<></>
143
+ }
144
+ }
145
+
146
+ const renderPrimaryMarkets = (data:{ item:MarketProps, index:number }) => {
147
+ return (
148
+ <View>
149
+ <FlatList
150
+ key={`${event.event_id}_side_options`}
151
+ data={data.item.side_options.sort((a,b) => {
152
+ let a_t = a.side == data.item.trade_side ? 1 : 0
153
+ let b_t = b.side == data.item.trade_side ? 1 : 0
154
+ return a_t - b_t
155
+ })}
156
+ keyExtractor={(item) => item.side}
157
+ renderItem={({ item, index }) => renderSides({ item, index, market:data.item })}
158
+ />
159
+ </View>
160
+ )
161
+ }
162
+
163
+ if(!event.away || !event.home){ return <></> }
164
+
165
+ const upcoming = moment().isBefore(moment(event.scheduled_datetime)) ? true : false
166
+ const { liquidity, open_order_count } = MarketComponentHelpers.getLiqudity(event_order_stats);
167
+
168
+ const non_primary_markets = TeamEventMarketHelpers.sortNonPrimaryMarkets(TeamEventMarketHelpers.getNonPrimaryMarkets(event, markets), event_order_stats)
169
+
170
+ return (
171
+ <View style={{ ...view_styles.section, borderWidth:1, borderColor:Colors.shades.shade600 }}>
172
+ <View nativeID='event_header_data' style={{ flexDirection:'row', padding:10, borderBottomWidth:1, borderBottomColor:Colors.shades.shade600 }}>
173
+ <View style={{ flex:1 }}>
174
+ {event.event_sub_title ?
175
+ <Text size={12} color={Colors.brand.midnight} weight='semibold'>{event.event_sub_title}</Text>
176
+ :<></>}
177
+ </View>
178
+ <View style={{ flexDirection:'row', alignItems:'center' }}>
179
+ <Icons.TVIcon size={10} color={Colors.brand.midnight} />
180
+ <Text style={{ marginLeft:8 }} size={12} color={Colors.brand.midnight} weight='semibold'>{event.info?.broadcast?.network}</Text>
181
+ </View>
182
+ </View>
183
+ <View nativeID='primary_markets' style={{ flexDirection:'row' }}>
184
+ <View nativeID='team_details' style={{ flex:1, padding:5, paddingRight:0 }}>
185
+ <View style={{ flexDirection:'row', alignItems:'center', marginTop:5, marginBottom:5, marginLeft:10 }}>
186
+ <View style={{ marginRight:5, height:10, width:10, borderRadius:100, backgroundColor:upcoming?Colors.brand.electric:Colors.utility.success }} />
187
+ <Text size={12} color={Colors.brand.midnight}>{TeamEventMarketHelpers.getTimeDetail(event)}</Text>
188
+ </View>
189
+ <View nativeID='away_details' style={{ ...view_styles.body_row, minHeight:48 }}>
190
+ <Image
191
+ source={{ uri: event.away.image?.url }}
192
+ style={{ height:30, width:30 }}
193
+ resizeMode='cover'
194
+ />
195
+ <View style={{ flex:1, flexDirection:'row', alignItems:'center', marginLeft:5 }}>
196
+ <View style={{ flex:1, marginRight:5 }}>
197
+ <Text theme='header_2'>{event.away.market_name} {event.away.name}</Text>
198
+ {event.away_sub_title ?
199
+ <Text style={{ marginTop:3 }} theme='body_2'>{event.away_sub_title}</Text>
200
+ :<></>}
201
+ </View>
202
+ <Text theme='body'>{event.away_team_score}</Text>
203
+ </View>
204
+ </View>
205
+ <View nativeID='home_details' style={{ ...view_styles.body_row, minHeight:48 }}>
206
+ <Image
207
+ source={{ uri: event.home.image?.url }}
208
+ style={{ height:30, width:30 }}
209
+ resizeMode='cover'
210
+ />
211
+ <View style={{ flex:1, flexDirection:'row', alignItems:'center', marginLeft:5 }}>
212
+ <View style={{ flex:1, marginRight:5 }}>
213
+ <Text theme='header_2'>{event.home.market_name} {event.home.name}</Text>
214
+ {event.home_sub_title ?
215
+ <Text style={{ marginTop:3 }} theme='body_2'>{event.home_sub_title}</Text>
216
+ :<></>}
217
+ </View>
218
+ <Text theme='body'>{event.home_team_score}</Text>
219
+ </View>
220
+ </View>
221
+ </View>
222
+ <View nativeID='primary_market_details' style={{ padding:5 }}>
223
+ <View style={{ marginTop:5, marginBottom:5 }}>
224
+ <FlatList
225
+ key={`${event.event_id}_market_headers`}
226
+ data={primary_markets}
227
+ keyExtractor={(item) => item.market_id.toString()}
228
+ horizontal
229
+ renderItem={renderMarketHeaders}
230
+ />
231
+ </View>
232
+ <FlatList
233
+ key={`${event.event_id}_primary_markets`}
234
+ data={primary_markets}
235
+ horizontal
236
+ renderItem={renderPrimaryMarkets}
237
+ keyExtractor={(item) => item.market_id.toString()}
238
+ />
239
+ </View>
240
+ </View>
241
+ <View style={{ backgroundColor:Colors.shades.shade100, padding:10, flexDirection:'row', alignItems:'center', borderBottomLeftRadius:8, borderBottomRightRadius:8 }}>
242
+ <TouchableOpacity style={{ flex:1, flexDirection:'row' }} onPress={() => {
243
+ if(!primary_markets[0]){ return }
244
+ onView({ event_id: event.event_id, event_type:'team', market_id: primary_markets[0].market_id });
245
+ }}>
246
+ <View style={{ backgroundColor:Colors.shades.white, height:30, width:30, borderRadius:100, justifyContent:'center', alignItems:'center', ...view_styles.float }}>
247
+ <Icons.LiquidityIcon color={Colors.brand.midnight} size={30}/>
248
+ </View>
249
+ <View style={{ marginLeft:10 }}>
250
+ <Text theme='body_2'>Liquidity</Text>
251
+ <Text size={12} color={Colors.brand.electric} weight='semibold'>${liquidity.toFixed()} {open_order_count} Orders</Text>
252
+ </View>
253
+ </TouchableOpacity>
254
+ {competition ?
255
+ <TouchableOpacity
256
+ style={{ marginRight:15, flexDirection:'row', alignItems:'center', padding:10, borderRadius:22, backgroundColor:Colors.highlights.highlight500, ...view_styles.float }}
257
+ onPress={() => onCompetitionSelect(competition.competition_id)}>
258
+ <Icons.PickEmIcon size={18} color={Colors.shades.white} />
259
+ <Text style={{ marginLeft:5 }} size={14} color={Colors.shades.white} weight='semibold'>Pick 6 Available</Text>
260
+ </TouchableOpacity>
261
+ :<></>}
262
+ <TouchableOpacity style={{ height:35, width:35, justifyContent:'center', borderRadius:100, alignItems:'center', backgroundColor:Colors.shades.white, ...view_styles.float }} onPress={() => expandedEvent()}>
263
+ <Icons.ChevronIcon direction={expanded ? 'up' : 'down'} size={8} color={Colors.brand.midnight} />
264
+ </TouchableOpacity>
265
+ </View>
266
+ {expanded ?
267
+ <View>
268
+ <View style={{ flexDirection:'row', alignItems:'center' }}>
269
+ <View style={{flex:1}}>
270
+ <LinearDiagnal label_size={12} label={'Hot Markets'} left_color={Colors.utility.warning} right_color={Colors.utility.error}/>
271
+ </View>
272
+ {loading ?
273
+ <ActivityIndicator style={{ paddingRight:20 }} size='small' color={Colors.brand.midnight} />
274
+ :
275
+ <Button
276
+ title='SEE ALL'
277
+ padding={15}
278
+ title_color={Colors.brand.electric}
279
+ onPress={() => onViewAdditionalMarkets(event.event_id, 'team')}
280
+ />
281
+ }
282
+ </View>
283
+ <FlatList
284
+ data={non_primary_markets}
285
+ renderItem={renderNonPrimaryMarkets}
286
+ keyExtractor={(item) => `${item.market_id}:${item.side_type}:${item.side_id}`}
287
+ horizontal
288
+ />
289
+ </View>
290
+ :<></>}
291
+ </View>
292
+ )
293
+ }
294
+
295
+ export default TeamEventMarket
@@ -0,0 +1,5 @@
1
+ import TeamEventMarket from './components/TeamEventMarket';
2
+
3
+ export default {
4
+ TeamEventMarket
5
+ }
package/src/index.tsx CHANGED
@@ -25,6 +25,7 @@ import EngageModule from "./Engage";
25
25
  import SeasonManager from "./CompetitionSeasonManager";
26
26
  import SeasonModule from "./CompetitionSeason";
27
27
  import CreateSeasonForm from "./CompetitionSeasonManager/components/CreateSeasonForm";
28
+ import MarketComponents from './MarketComponents';
28
29
 
29
30
  export {
30
31
  Authenticator,
@@ -42,6 +43,7 @@ export {
42
43
  Colors,
43
44
  MyWallet,
44
45
  Checkout,
46
+ MarketComponents,
45
47
  PollCampaign,
46
48
  PollCampaignApi,
47
49
  PollApi,