be-components 6.2.2 → 6.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/lib/commonjs/Competition/components/CompetitionPlay.js +8 -1
  2. package/lib/commonjs/Competition/components/CompetitionPlay.js.map +1 -1
  3. package/lib/commonjs/Competition/components/MarketsCard.js +1 -0
  4. package/lib/commonjs/Competition/components/MarketsCard.js.map +1 -1
  5. package/lib/commonjs/MarketComponents/api/index.js +189 -0
  6. package/lib/commonjs/MarketComponents/api/index.js.map +1 -1
  7. package/lib/commonjs/MarketComponents/components/AthleteMarket/index.js +19 -5
  8. package/lib/commonjs/MarketComponents/components/AthleteMarket/index.js.map +1 -1
  9. package/lib/commonjs/MarketComponents/components/CreateMarketForm.js +736 -0
  10. package/lib/commonjs/MarketComponents/components/CreateMarketForm.js.map +1 -0
  11. package/lib/commonjs/MarketComponents/components/TeamEventMarket/index.js +23 -8
  12. package/lib/commonjs/MarketComponents/components/TeamEventMarket/index.js.map +1 -1
  13. package/lib/commonjs/MarketComponents/components/WeightProgress.js +53 -0
  14. package/lib/commonjs/MarketComponents/components/WeightProgress.js.map +1 -0
  15. package/lib/commonjs/MarketComponents/index.js +2 -0
  16. package/lib/commonjs/MarketComponents/index.js.map +1 -1
  17. package/lib/commonjs/MarketMaker/api/index.js +3 -0
  18. package/lib/commonjs/MarketMaker/api/index.js.map +1 -1
  19. package/lib/commonjs/Poll/components/PollCard.js +3 -0
  20. package/lib/commonjs/Poll/components/PollCard.js.map +1 -1
  21. package/lib/module/Competition/components/CompetitionPlay.js +8 -1
  22. package/lib/module/Competition/components/CompetitionPlay.js.map +1 -1
  23. package/lib/module/Competition/components/MarketsCard.js +1 -0
  24. package/lib/module/Competition/components/MarketsCard.js.map +1 -1
  25. package/lib/module/MarketComponents/api/index.js +189 -0
  26. package/lib/module/MarketComponents/api/index.js.map +1 -1
  27. package/lib/module/MarketComponents/components/AthleteMarket/index.js +19 -5
  28. package/lib/module/MarketComponents/components/AthleteMarket/index.js.map +1 -1
  29. package/lib/module/MarketComponents/components/CreateMarketForm.js +727 -0
  30. package/lib/module/MarketComponents/components/CreateMarketForm.js.map +1 -0
  31. package/lib/module/MarketComponents/components/TeamEventMarket/index.js +23 -8
  32. package/lib/module/MarketComponents/components/TeamEventMarket/index.js.map +1 -1
  33. package/lib/module/MarketComponents/components/WeightProgress.js +45 -0
  34. package/lib/module/MarketComponents/components/WeightProgress.js.map +1 -0
  35. package/lib/module/MarketComponents/index.js +2 -0
  36. package/lib/module/MarketComponents/index.js.map +1 -1
  37. package/lib/module/MarketMaker/api/index.js +3 -0
  38. package/lib/module/MarketMaker/api/index.js.map +1 -1
  39. package/lib/module/Poll/components/PollCard.js +3 -0
  40. package/lib/module/Poll/components/PollCard.js.map +1 -1
  41. package/lib/typescript/lib/commonjs/Competition/components/CompetitionPlay.d.ts.map +1 -1
  42. package/lib/typescript/lib/commonjs/Competition/components/MarketsCard.d.ts.map +1 -1
  43. package/lib/typescript/lib/commonjs/MarketComponents/api/index.d.ts +6 -0
  44. package/lib/typescript/lib/commonjs/MarketComponents/api/index.d.ts.map +1 -1
  45. package/lib/typescript/lib/commonjs/MarketComponents/components/CreateMarketForm.d.ts +20 -0
  46. package/lib/typescript/lib/commonjs/MarketComponents/components/CreateMarketForm.d.ts.map +1 -0
  47. package/lib/typescript/lib/commonjs/MarketComponents/components/WeightProgress.d.ts +8 -0
  48. package/lib/typescript/lib/commonjs/MarketComponents/components/WeightProgress.d.ts.map +1 -0
  49. package/lib/typescript/lib/commonjs/MarketComponents/index.d.ts +1 -0
  50. package/lib/typescript/lib/commonjs/MarketMaker/api/index.d.ts.map +1 -1
  51. package/lib/typescript/lib/commonjs/Poll/components/PollCard.d.ts.map +1 -1
  52. package/lib/typescript/lib/module/Competition/components/CompetitionPlay.d.ts.map +1 -1
  53. package/lib/typescript/lib/module/Competition/components/MarketsCard.d.ts.map +1 -1
  54. package/lib/typescript/lib/module/MarketComponents/api/index.d.ts +6 -0
  55. package/lib/typescript/lib/module/MarketComponents/api/index.d.ts.map +1 -1
  56. package/lib/typescript/lib/module/MarketComponents/components/AthleteMarket/index.d.ts +2 -1
  57. package/lib/typescript/lib/module/MarketComponents/components/AthleteMarket/index.d.ts.map +1 -1
  58. package/lib/typescript/lib/module/MarketComponents/components/CreateMarketForm.d.ts +20 -0
  59. package/lib/typescript/lib/module/MarketComponents/components/CreateMarketForm.d.ts.map +1 -0
  60. package/lib/typescript/lib/module/MarketComponents/components/TeamEventMarket/index.d.ts +2 -1
  61. package/lib/typescript/lib/module/MarketComponents/components/TeamEventMarket/index.d.ts.map +1 -1
  62. package/lib/typescript/lib/module/MarketComponents/components/WeightProgress.d.ts +8 -0
  63. package/lib/typescript/lib/module/MarketComponents/components/WeightProgress.d.ts.map +1 -0
  64. package/lib/typescript/lib/module/MarketComponents/index.d.ts +2 -0
  65. package/lib/typescript/lib/module/MarketComponents/index.d.ts.map +1 -1
  66. package/lib/typescript/lib/module/MarketMaker/api/index.d.ts.map +1 -1
  67. package/lib/typescript/lib/module/Poll/components/PollCard.d.ts.map +1 -1
  68. package/lib/typescript/src/Competition/components/MarketsCard.d.ts.map +1 -1
  69. package/lib/typescript/src/MarketComponents/api/index.d.ts +6 -0
  70. package/lib/typescript/src/MarketComponents/api/index.d.ts.map +1 -1
  71. package/lib/typescript/src/MarketComponents/components/AthleteMarket/index.d.ts +2 -1
  72. package/lib/typescript/src/MarketComponents/components/AthleteMarket/index.d.ts.map +1 -1
  73. package/lib/typescript/src/MarketComponents/components/CreateMarketForm.d.ts +27 -0
  74. package/lib/typescript/src/MarketComponents/components/CreateMarketForm.d.ts.map +1 -0
  75. package/lib/typescript/src/MarketComponents/components/TeamEventMarket/index.d.ts +2 -1
  76. package/lib/typescript/src/MarketComponents/components/TeamEventMarket/index.d.ts.map +1 -1
  77. package/lib/typescript/src/MarketComponents/components/WeightProgress.d.ts +12 -0
  78. package/lib/typescript/src/MarketComponents/components/WeightProgress.d.ts.map +1 -0
  79. package/lib/typescript/src/MarketComponents/index.d.ts +25 -2
  80. package/lib/typescript/src/MarketComponents/index.d.ts.map +1 -1
  81. package/lib/typescript/src/MarketMaker/api/index.d.ts +1 -1
  82. package/lib/typescript/src/MarketMaker/api/index.d.ts.map +1 -1
  83. package/lib/typescript/src/Poll/components/PollCard.d.ts.map +1 -1
  84. package/package.json +1 -1
  85. package/src/Competition/components/CompetitionPlay.tsx +6 -6
  86. package/src/Competition/components/MarketsCard.tsx +1 -0
  87. package/src/MarketComponents/api/index.ts +166 -3
  88. package/src/MarketComponents/components/AthleteMarket/index.tsx +22 -10
  89. package/src/MarketComponents/components/CreateMarketForm.tsx +444 -0
  90. package/src/MarketComponents/components/TeamEventMarket/index.tsx +31 -18
  91. package/src/MarketComponents/components/WeightProgress.tsx +32 -0
  92. package/src/MarketComponents/index.tsx +2 -0
  93. package/src/MarketMaker/api/index.ts +2 -1
  94. package/src/Poll/components/PollCard.tsx +1 -0
@@ -0,0 +1,444 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { Button, Text, TextInput, View } from "../../Components/Themed"
3
+ import type { BestAvailableOrderProps, EventProps, ExternalPriceProps, LocationProps, MarketProps, MatchProps, OrderProps, TournamentProps, TradeProps } from '../../types';
4
+ import { MarketComponentApi, MarketComponentHelpers } from '../api';
5
+ import { ActivityIndicator, FlatList, type ViewStyle } from 'react-native';
6
+ import { Icons } from '../../Components';
7
+ import { useColors } from '../../constants/useColors';
8
+ import { MarketMaketHelpers } from '../../MarketMaker/api';
9
+ import OrderGradeBar from './OrderGradeBar';
10
+ import WeightProgress from './WeightProgress';
11
+
12
+ type CreateMarketFormProps = {
13
+ float?:boolean,
14
+ style?:ViewStyle
15
+ contest_type:'team'|'tournament'|'match',
16
+ contest_id:string,
17
+ best_available_orders:BestAvailableOrderProps[],
18
+ my_orders:OrderProps[],
19
+ action_loading?:boolean,
20
+ market_id:string,
21
+ unit_size?:number,
22
+ location?:LocationProps,
23
+ coordinates?:{ latitude:number, longitude:number, [key:string]:any }
24
+ side_type?:'side'|'team'|'athlete',
25
+ side_id?:string,
26
+ onCancel:() => void,
27
+ onSubmitOrders:(orders:OrderProps[]) => void
28
+ }
29
+
30
+
31
+ const sections = ['o_side', 'submit', 'trade_side', 'draft_orders','my_orders', 'what_if'];
32
+ const CreateMarketForm = ({ float, action_loading, unit_size, location, coordinates, style, my_orders, best_available_orders, contest_type, contest_id, market_id, side_id, side_type, onCancel, onSubmitOrders }:CreateMarketFormProps) => {
33
+ const Colors = useColors();
34
+ const [ draft_orders, setDraftOrders ] = useState<OrderProps[]>([]);
35
+ const [ draft_data, setDraftData ] = useState<{
36
+ stake:string,
37
+ o_side_margin:number,
38
+ trade_side_margin:number
39
+ }>({
40
+ stake:unit_size?.toFixed(2) ?? '10',
41
+ o_side_margin: 0.02,
42
+ trade_side_margin: 0.02
43
+ });
44
+ const { o_side_margin, trade_side_margin, stake } = draft_data;
45
+ const [ form_data, setFormData ] = useState<{
46
+ loading:boolean,
47
+ markets:MarketProps[],
48
+ prices:ExternalPriceProps[],
49
+ trades:TradeProps[],
50
+ event?:EventProps,
51
+ tournament?:TournamentProps,
52
+ match?:MatchProps
53
+ }>({
54
+ loading:false,
55
+ markets: [],
56
+ prices: [],
57
+ trades: []
58
+ });
59
+
60
+ const { loading, markets, prices, event, tournament, match } = form_data;
61
+
62
+ const { contest_title } = MarketComponentHelpers.getContestDetails(contest_type, event, tournament, match);
63
+ const market = markets.find(mk => mk.market_id == market_id);
64
+
65
+ const orders = MarketComponentHelpers.setMarket(parseFloat(stake), contest_type, best_available_orders, prices, o_side_margin, trade_side_margin, market, event, tournament, match, undefined, undefined)
66
+ const no_vig_data = MarketMaketHelpers.getNoVigPrice(prices, market);
67
+
68
+
69
+ useEffect(() => {
70
+ MarketComponentApi.setEnvironment();
71
+ getFormData();
72
+ },[]);
73
+
74
+ const getFormData = async() => {
75
+ setFormData({ ...form_data, loading:true })
76
+ const mks = await MarketComponentApi.getMarkets();
77
+ let ev:EventProps | undefined, tourn:TournamentProps | undefined, mtch:MatchProps|undefined
78
+ if(contest_type == 'team'){
79
+ let evs = await MarketComponentApi.getEventsByEventIds([contest_id]);
80
+ ev = evs[0]
81
+ }
82
+ if(contest_type == 'tournament'){
83
+ let tourns = await MarketComponentApi.getTournamentsByTournamentIds([contest_id]);
84
+ tourn = tourns[0]
85
+ }
86
+ if(contest_type == 'match'){
87
+ let mtchs = await MarketComponentApi.getMatchesByMatchIds([contest_id]);
88
+ mtch = mtchs[0]
89
+ if(mtch){
90
+ let mtch_tourns = await MarketComponentApi.getTournamentsByTournamentIds([mtch.tournament_id]);
91
+ tourn = mtch_tourns[0]
92
+ }
93
+ }
94
+ let contest_prices = await MarketComponentApi.getExternalPrices(contest_type, contest_id, market_id);
95
+ //Get the correct prices
96
+ if(side_type){ contest_prices = contest_prices.filter(p => p.participant_type == side_type && p.participant_id == side_id) }
97
+ //First try to get consensus
98
+ contest_prices = contest_prices.filter(p => p.external_name == 'Consensus');
99
+ if(contest_prices.length == 0){
100
+ let available_books = [ ...new Set(contest_prices.map(p => p.external_name)) ]
101
+ contest_prices = contest_prices.filter(p => p.external_name == available_books[0]);
102
+ }
103
+
104
+ let contest_trades = await MarketComponentApi.getLatestTradesByEvents(contest_type, [contest_id]);
105
+
106
+
107
+ setFormData({
108
+ ...form_data,
109
+ loading:false,
110
+ markets: mks,
111
+ match: mtch,
112
+ event: ev,
113
+ tournament: tourn,
114
+ prices: contest_prices,
115
+ trades: contest_trades
116
+ });
117
+ }
118
+
119
+ const handleSubmitOrder = () => {
120
+ if(action_loading){ return }
121
+ if(draft_orders.length == 0){ return alert('Unable to submit!') }
122
+ if(!location){ return alert('Unable to create order without location') }
123
+ if(!location.legal_ind){ return alert('Unable to create order in this location') }
124
+ if(!coordinates?.latitude){ return alert('Need coordinates') }
125
+ let new_orders = draft_orders.map(o => {
126
+ o.region = location.label
127
+ o.location = coordinates
128
+ return o
129
+ });
130
+ onSubmitOrders(new_orders)
131
+ }
132
+
133
+ const handleUpdateMargin = (side:'other'|'trade', direction: 'increase'|'decrease') => {
134
+ let o_side = o_side_margin
135
+ let trade_side = trade_side_margin
136
+ if(side == 'other' && direction == 'increase'){ o_side += 0.001 }
137
+ if(side == 'other' && direction == 'decrease'){ o_side -= 0.001 }
138
+
139
+ if(side == 'trade' && direction == 'increase'){ trade_side += 0.001 }
140
+ if(side == 'trade' && direction == 'decrease'){ trade_side -= 0.001 }
141
+ let total_margin = o_side + trade_side
142
+ if(total_margin < 0.001){ return } //Cant go negative!!
143
+ setDraftData({ o_side_margin: o_side, trade_side_margin: trade_side, stake })
144
+
145
+ }
146
+
147
+ const renderOrders = (data:{ item:OrderProps, index:number }) => {
148
+ return (
149
+ <View style={{ flexGrow:1 }}>
150
+ <View style={{ padding:10 }}>
151
+ <Text theme='h1' textAlign='center'>{data.item.title}</Text>
152
+ </View>
153
+ </View>
154
+ )
155
+ }
156
+
157
+ const renderSections = (data:{item:string, index:number}) => {
158
+ switch(data.item){
159
+ case 'my_orders':
160
+ if(!market){ return <></> }
161
+ const hedges = MarketMaketHelpers.getHedgesFromPositions(my_orders, markets);
162
+ const hedge = hedges[0]
163
+ const o_side_stats = MarketMaketHelpers.getOrderStats(my_orders.filter(o => o.side != market.trade_side));
164
+ const t_side_stats = MarketMaketHelpers.getOrderStats(my_orders.filter(o => o.side == market.trade_side));
165
+ const stake_weight = MarketMaketHelpers.getWeight(o_side_stats.stake_potential_winnings, t_side_stats.stake_potential_winnings, market);
166
+ const at_risk = o_side_stats.stake_potential_winnings - t_side_stats.stake_potential_winnings
167
+ return (
168
+ <View type='footer' style={{ padding:10 }}>
169
+ <View transparent style={{ flexDirection:'row', alignItems:'center', padding:10 }}>
170
+ <View transparent style={{ flex:1 }}>
171
+ <Text theme='h1'>My Current Position</Text>
172
+ </View>
173
+ {hedge?
174
+ <View transparent>
175
+ {hedge.delayed_cash_draw ?
176
+ <Text theme='error' size={14}>-${hedge.delayed_cash_draw.toFixed(2)}</Text>
177
+ :
178
+ <Text theme='success' size={14}>${hedge.delayed_cash_no_draw.toFixed(2)}</Text>
179
+ }
180
+ <Text theme='description'>Hedged</Text>
181
+ </View>
182
+ :<></>}
183
+ </View>
184
+ <View transparent type='row'>
185
+ <View transparent style={{ flex:1, padding:5 }}>
186
+ <Text theme='h2' textAlign='center'>{o_side_stats.stake_potential_winnings.toFixed(2)}</Text>
187
+ </View>
188
+ <View transparent style={{ flex:1, padding:5 }}>
189
+ <Text theme='h2' textAlign='center'>{t_side_stats.stake_potential_winnings.toFixed(2)}</Text>
190
+ </View>
191
+ </View>
192
+ <WeightProgress
193
+ style={{ margin:10 }}
194
+ min_value={0}
195
+ max_value={100}
196
+ value={stake_weight.weighted_pct}
197
+ bar_height={18}
198
+ />
199
+ <View transparent type='row'>
200
+ {at_risk > 0 ?
201
+ <View transparent style={{ flex:1, padding:5 }}>
202
+ <Text theme='error' textAlign='center' style={{ marginTop:3 }}>${at_risk.toFixed(2)}</Text>
203
+ <Text theme='description' textAlign='center' style={{ marginTop:3 }}>At Risk</Text>
204
+ </View>
205
+ :<View style={{ flex:1 }} />}
206
+ {at_risk < 0 ?
207
+ <View transparent style={{ flex:1, padding:5 }}>
208
+ <Text theme='error' textAlign='center' style={{ marginTop:3 }}>${at_risk.toFixed(2)}</Text>
209
+ <Text theme='description' textAlign='center' style={{ marginTop:3 }}>At Risk</Text>
210
+ </View>
211
+ :<View style={{ flex:1 }} />}
212
+ </View>
213
+ </View>
214
+ )
215
+ case 'o_side':
216
+ if(draft_orders.length > 0){ return <></> }
217
+ if(!market){ return <></> }
218
+ let o_side_option = market.side_options.find(so => so.side != market.trade_side);
219
+ if(!o_side_option){ return <></> }
220
+ const o_side_order = orders.find(o => o.side != market.trade_side);
221
+ if(!o_side_order){ return <></> }
222
+ const o_side_price = prices.find(p => p.side != market.trade_side);
223
+ const o_side_no_vig = no_vig_data?.o_side_odds
224
+ const o_best_available = best_available_orders.find(o => o.market_id == market_id && o.side != market.trade_side)
225
+ //const my_o_side_open = my_orders.filter(o => o.market_id == market_id && o.side != market.trade_side);
226
+ //const my_open_stats = MarketMaketHelpers.getOrderStats(my_o_side_open, o_best_available);
227
+ return (
228
+ <View style={{ borderWidth:1, borderColor:Colors.borders.light, margin:10 }}>
229
+ <View type='row' style={{ padding:10, borderBottomWidth:1, borderColor:Colors.borders.light }}>
230
+ <View transparent style={{ flex:1 }}>
231
+ <Text theme='h2'>{o_side_order.title}</Text>
232
+ <Text theme='description' style={{ marginTop:3 }}>${o_side_order.open_amt.toFixed(2)} to win ${o_side_order.potential_winnings.toFixed(2)}</Text>
233
+ </View>
234
+ <Text theme='h1'>${o_side_order.open_amt.toFixed(2)}</Text>
235
+ <View type='row' style={{ marginLeft:10 }}>
236
+ <Button float onPress={() => handleUpdateMargin('other', 'increase')}>
237
+ <Icons.ChevronIcon direction='left' size={8} color={Colors.text.h1} />
238
+ </Button>
239
+ <View style={{ paddingLeft:10, paddingRight:10 }}>
240
+ <Text theme='h1' textAlign='center'>{(o_side_order.probability * 100).toFixed(2)}%</Text>
241
+ <Text theme='light' style={{ marginTop:3 }} textAlign='center'>{MarketComponentHelpers.getOddsLabel(o_side_order.odds)}</Text>
242
+ </View>
243
+ <Button float onPress={() => handleUpdateMargin('other', 'decrease')}>
244
+ <Icons.ChevronIcon direction='right' size={8} color={Colors.text.h1} />
245
+ </Button>
246
+ </View>
247
+ </View>
248
+ {o_best_available ?
249
+ <View type='row' style={{ padding:10 }}>
250
+ <View transparent style={{flex:1}}>
251
+ <Text theme='h1'>{o_best_available.title}</Text>
252
+ {o_best_available.grade ?
253
+ <OrderGradeBar style={{ alignSelf:'flex-start', marginTop:3 }} grade={o_best_available.grade} view_type='card' onSelectGrade={() => console.log('')}/>
254
+ :<></>}
255
+ </View>
256
+ <View style={{ alignItems:'flex-end' }}>
257
+ <Text theme='h2'>{MarketComponentHelpers.getOddsLabel(o_best_available.odds)}</Text>
258
+ <Text theme='success'>${o_best_available.open_amt.toFixed(2)} Available</Text>
259
+ </View>
260
+ <Button
261
+ title='BUY'
262
+ type='success'
263
+ loading={action_loading}
264
+ style={{ padding:10, marginLeft:10, opacity: action_loading ? 0.5:1 }}
265
+ disabled={action_loading}
266
+ onPress={() => {
267
+ let side_ids = MarketComponentHelpers.getSideIds(contest_type, o_side_option, market, event, tournament, match, undefined, undefined);
268
+ if(!side_ids){ return }
269
+ let trade = MarketMaketHelpers.getTradeFromAvailableOrder(o_best_available, side_ids.reversed_side_id);
270
+ let order = MarketMaketHelpers.getOrderFromTrade(trade, unit_size ?? 10, o_best_available.order_id);
271
+ order.title = o_best_available.title
272
+ setDraftOrders([order])
273
+ }}
274
+ />
275
+ </View>
276
+ :<></>}
277
+ {o_side_price && o_side_no_vig ?
278
+ <View type='footer' style={{ flexDirection:'row', alignItems:'center', padding:10 }}>
279
+ <View transparent style={{ flex:1 }}>
280
+ <Text theme='h1'>{o_side_price.external_name}</Text>
281
+ <Text theme='light' style={{ marginTop:3 }}>External price with vig removed</Text>
282
+ </View>
283
+ <Text theme='h2'>{MarketComponentHelpers.getOddsLabel(o_side_no_vig)}</Text>
284
+ </View>
285
+ :<></>}
286
+ </View>
287
+
288
+ )
289
+ case 'submit':
290
+ if(draft_orders.length > 0){ return <></> }
291
+ return (
292
+ <View type='header' style={{ flexDirection:'row', padding:10 }}>
293
+ <TextInput
294
+ value={stake}
295
+ style={{ width:100, textAlign:'center' }}
296
+ onChangeText={(text) => setDraftData({ ...draft_data, stake:text })}
297
+ />
298
+ <Button
299
+ style={{ flex:2, marginLeft:10, opacity: action_loading?0.5:1 }}
300
+ type='success'
301
+ loading={action_loading}
302
+ disabled={action_loading}
303
+ title='SET MARKET'
304
+ onPress={() => setDraftOrders(orders)}
305
+ />
306
+ </View>
307
+ )
308
+ case 'trade_side':
309
+ if(draft_orders.length > 0){ return <></> }
310
+ if(!market){ return <></> }
311
+ let trade_side_option = market.side_options.find(so => so.side == market.trade_side);
312
+ if(!trade_side_option){ return <></> }
313
+ const trade_side_order = orders.find(o => o.side == market.trade_side);
314
+ if(!trade_side_order){ return <></> }
315
+ const trade_side_price = prices.find(p => p.side == market.trade_side);
316
+ const trade_side_no_vig_odds = no_vig_data?.trade_side_odds
317
+ const t_best_available = best_available_orders.find(o => o.market_id == market_id && o.side == market.trade_side)
318
+ return (
319
+ <View style={{ borderWidth:1, borderColor:Colors.borders.light, margin:10 }}>
320
+ <View type='row' style={{ padding:10 }}>
321
+ <View transparent style={{ flex:1 }}>
322
+ <Text theme='h2'>{trade_side_order.title}</Text>
323
+ <Text theme='description' style={{ marginTop:3 }}>${trade_side_order.open_amt.toFixed(2)} to win ${trade_side_order.potential_winnings.toFixed(2)}</Text>
324
+ </View>
325
+ <Text theme='h1'>${trade_side_order.open_amt.toFixed(2)}</Text>
326
+ <View type='row' style={{ marginLeft:10 }}>
327
+ <Button float onPress={() => handleUpdateMargin('trade', 'increase')}>
328
+ <Icons.ChevronIcon direction='left' size={8} color={Colors.text.h1} />
329
+ </Button>
330
+ <View style={{ paddingLeft:10, paddingRight:10 }}>
331
+ <Text theme='h1'>{(trade_side_order.probability * 100).toFixed(2)}%</Text>
332
+ <Text theme='light' style={{ marginTop:3 }} textAlign='center'>{MarketComponentHelpers.getOddsLabel(trade_side_order.odds)}</Text>
333
+ </View>
334
+ <Button float onPress={() => handleUpdateMargin('trade', 'decrease')}>
335
+ <Icons.ChevronIcon direction='right' size={8} color={Colors.text.h1} />
336
+ </Button>
337
+ </View>
338
+ </View>
339
+ {t_best_available ?
340
+ <View type='row' style={{ padding:10 }}>
341
+ <View transparent style={{flex:1}}>
342
+ <Text theme='h1'>{t_best_available.title}</Text>
343
+ {t_best_available.grade ?
344
+ <OrderGradeBar style={{ alignSelf:'flex-start', marginTop:3 }} grade={t_best_available.grade} view_type='card' onSelectGrade={() => console.log('')}/>
345
+ :<></>}
346
+ </View>
347
+ <View style={{ alignItems:'flex-end' }}>
348
+ <Text theme='h2'>{MarketComponentHelpers.getOddsLabel(t_best_available.odds)}</Text>
349
+ <Text theme='success'>${t_best_available.open_amt.toFixed(2)} Available</Text>
350
+ </View>
351
+ <Button
352
+ title='BUY'
353
+ type='success'
354
+ style={{ padding:10, marginLeft:10, opacity: action_loading ? 0.5:1 }}
355
+ disabled={action_loading}
356
+ onPress={() => {
357
+ let side_ids = MarketComponentHelpers.getSideIds(contest_type, trade_side_option, market, event, tournament, match, undefined, undefined);
358
+ if(!side_ids){ return }
359
+ let trade = MarketMaketHelpers.getTradeFromAvailableOrder(t_best_available, side_ids.reversed_side_id);
360
+ let order = MarketMaketHelpers.getOrderFromTrade(trade, unit_size ?? 10, t_best_available.order_id);
361
+ order.title = t_best_available.title
362
+ setDraftOrders([order])
363
+ }}
364
+ />
365
+ </View>
366
+ :<></>}
367
+ {trade_side_price && trade_side_no_vig_odds ?
368
+ <View type='footer' style={{ flexDirection:'row', alignItems:'center', padding:10 }}>
369
+ <View transparent style={{ flex:1 }}>
370
+ <Text theme='h1'>{trade_side_price.external_name}</Text>
371
+ <Text theme='light' style={{ marginTop:3 }}>External price with vig removed</Text>
372
+ </View>
373
+ <Text theme='h2'>{MarketComponentHelpers.getOddsLabel(trade_side_no_vig_odds)}</Text>
374
+ </View>
375
+ :<></>}
376
+ </View>
377
+ )
378
+ case 'draft_orders':
379
+ if(draft_orders.length == 0){ return <></> }
380
+ return (
381
+ <View style={{ flexDirection:'row', flexWrap:'wrap' }}>
382
+ {draft_orders.map((o,i) => {
383
+ return renderOrders({ item: o, index:i })
384
+ })}
385
+ </View>
386
+ )
387
+ case 'what_if':return <></>
388
+ default: return <></>
389
+ }
390
+ }
391
+
392
+ const total_margin = o_side_margin + trade_side_margin
393
+ return (
394
+ <View float={float} style={{ ...style }}>
395
+ <View type='header' style={{ flexDirection:'row', alignItems:'center', padding:10, borderTopLeftRadius:8, borderTopRightRadius:8 }}>
396
+ <View transparent style={{ flex:1 }}>
397
+ <Text theme='h1'>{contest_title}</Text>
398
+ </View>
399
+ <View transparent style={{ justifyContent:'center', alignItems:'center' }}>
400
+ <Text theme='h2' color={total_margin > 0.06 ? Colors.text.error : total_margin > 0.045 ? Colors.text.warning : Colors.text.success}>{(total_margin*100).toFixed(2)}%</Text>
401
+ <Text theme='description' textAlign='center'>Margin</Text>
402
+ </View>
403
+ </View>
404
+ <View type='body' style={{ flex:1 }}>
405
+ {loading ?
406
+ <ActivityIndicator size='large' color={Colors.text.h1} />
407
+ :<></>}
408
+ <FlatList
409
+ key={'create_market_sections'}
410
+ keyExtractor={item => item}
411
+ renderItem={renderSections}
412
+ data={sections}
413
+ />
414
+ </View>
415
+ {draft_orders.length == 0 ?
416
+ <View type='footer' style={{ flexDirection:'row', alignItems:'center', padding:10, borderBottomRightRadius:8, borderBottomLeftRadius:8 }}>
417
+ <Button
418
+ style={{ flex:1 }}
419
+ type='action'
420
+ title='CLOSE'
421
+ onPress={() => onCancel()}
422
+ />
423
+ </View>
424
+ :
425
+ <View type='footer' style={{ flexDirection:'row', alignItems:'center', padding:10, borderBottomRightRadius:8, borderBottomLeftRadius:8 }}>
426
+ <Button
427
+ style={{ flex:1 }}
428
+ type='error'
429
+ title='CANCEL'
430
+ onPress={() => setDraftOrders([])}
431
+ />
432
+ <Button
433
+ style={{ flex:2, marginLeft:5 }}
434
+ type='success'
435
+ title='SUBMIT ORDERS'
436
+ onPress={() => handleSubmitOrder()}
437
+ />
438
+ </View>
439
+ }
440
+ </View>
441
+ )
442
+ }
443
+
444
+ export default CreateMarketForm
@@ -23,6 +23,7 @@ type TeamEventMarketProps = {
23
23
  markets:MarketProps[],
24
24
  init_expanded?:boolean,
25
25
  onViewMarketStats?:() => void,
26
+ onSetMarket?:(market_id:string, side_type?:string, side_id?:string) => void,
26
27
  league?:LeagueProps,
27
28
  competitions?:CompetitionProps[],
28
29
  show_id?:string,
@@ -55,7 +56,7 @@ type TeamEventMarketProps = {
55
56
  onActivate?:(event_id:string, event_type:string) => void
56
57
  activate_loading?:boolean
57
58
  }
58
- const TeamEventMarket = ({ event, hide_non_primary, flash_markets, league, float, style, init_expanded, hot_markets_direction, show_id, hide_liquidity, show_podcasts, activate_loading, competitions, squares_competitions, show_grades, markets, latest_trades, best_available_orders, event_order_stats, default_price_view, onTeamSelect, onFlashSelect, onSquaresSelect, onCompetitionSelect, onExpand, onOrder, onViewMarketStats, onView, onViewAdditionalMarkets, onTradeLongPress, onTVSelect, onActivate, onEvent, onShare, onPodcastSelect }:TeamEventMarketProps) => {
59
+ const TeamEventMarket = ({ event, hide_non_primary, flash_markets, league, float, style, init_expanded, hot_markets_direction, show_id, hide_liquidity, show_podcasts, activate_loading, competitions, squares_competitions, show_grades, markets, latest_trades, best_available_orders, event_order_stats, default_price_view, onSetMarket, onTeamSelect, onFlashSelect, onSquaresSelect, onCompetitionSelect, onExpand, onOrder, onViewMarketStats, onView, onViewAdditionalMarkets, onTradeLongPress, onTVSelect, onActivate, onEvent, onShare, onPodcastSelect }:TeamEventMarketProps) => {
59
60
  const C = useColors();
60
61
  const [ market_width, setMarketWidth ] = useState(180);
61
62
  const [ expanded_data, setExpandedData ] = useState<{
@@ -214,21 +215,31 @@ const TeamEventMarket = ({ event, hide_non_primary, flash_markets, league, float
214
215
  }
215
216
  if(!trade){ return <></> }
216
217
  return (
217
- <View transparent key={`${event.event_id}_${data.item.side}`} style={{ margin:2, width:primary_width, height:50 }}>
218
- <MarketButton
219
- side_option={data.item}
220
- market={data.market}
221
- trade={trade}
222
- order={ba_order}
223
- locked={data.is_locked}
224
- show_grades={show_grades}
225
- onLongPress={onTradeLongPress}
226
- onPress={(order) => {
227
- const order_title = MarketComponentHelpers.getOrderTitleForTeamEvent(order, data.market, event);
228
- if(!order_title){ return alert('Unable to process order') }
229
- onOrder({ ...order, title: order_title, league_id: event.league_id })
230
- }}
218
+ <View transparent key={`${event.event_id}_${data.item.side}`} style={{ width:primary_width }}>
219
+ <View transparent style={{ height:50, margin:2 }}>
220
+ <MarketButton
221
+ side_option={data.item}
222
+ market={data.market}
223
+ trade={trade}
224
+ order={ba_order}
225
+ locked={data.is_locked}
226
+ show_grades={show_grades}
227
+ onLongPress={onTradeLongPress}
228
+ onPress={(order) => {
229
+ const order_title = MarketComponentHelpers.getOrderTitleForTeamEvent(order, data.market, event);
230
+ if(!order_title){ return alert('Unable to process order') }
231
+ onOrder({ ...order, title: order_title, league_id: event.league_id })
232
+ }}
233
+ />
234
+ </View>
235
+ {onSetMarket && data.item.side != data.market.trade_side ?
236
+ <Button
237
+ title='SET'
238
+ type='success'
239
+ style={{ margin:2, padding:8 }}
240
+ onPress={() => onSetMarket(data.market.market_id)}
231
241
  />
242
+ :<></>}
232
243
  </View>
233
244
  )
234
245
  },[JSON.stringify(best_available_orders), JSON.stringify(latest_trades), primary_width])
@@ -283,6 +294,7 @@ const TeamEventMarket = ({ event, hide_non_primary, flash_markets, league, float
283
294
  best_available_orders={athlete_orders}
284
295
  onOrder={onOrder}
285
296
  onView={onView}
297
+ onSetMarket={onSetMarket}
286
298
  />
287
299
  )
288
300
  case 'event':
@@ -312,6 +324,7 @@ const TeamEventMarket = ({ event, hide_non_primary, flash_markets, league, float
312
324
  }
313
325
  },[athletes.length, JSON.stringify(best_available_orders), JSON.stringify(latest_trades)])
314
326
 
327
+
315
328
  const renderPrimaryMarkets = useCallback((data:{ item:MarketProps, index:number }) => {
316
329
  const is_locked = MarketComponentHelpers.isEventMarketLocked(event, data.item.market_id);
317
330
  return (
@@ -458,7 +471,7 @@ const TeamEventMarket = ({ event, hide_non_primary, flash_markets, league, float
458
471
  }
459
472
  <View type='body' nativeID='primary_markets' style={{ flexDirection:'row' }}>
460
473
  <View transparent nativeID='team_details' style={{ flex:1, padding:5, paddingRight:0 }}>
461
- <View transparent style={{ flexDirection:'row', alignItems:'center', marginTop:5, marginBottom:5, marginLeft:10 }}>
474
+ <View transparent style={{ flexDirection:'row', marginTop:5, marginBottom:5, marginLeft:10 }}>
462
475
  {show_stats ?
463
476
  <Button
464
477
  title='X'
@@ -476,7 +489,7 @@ const TeamEventMarket = ({ event, hide_non_primary, flash_markets, league, float
476
489
  </View>
477
490
  <Button
478
491
  disabled={!onTeamSelect}
479
- style={{ ...view_styles.body_row, minHeight:48 }}
492
+ style={{ ...view_styles.body_row, minHeight:48, flexGrow:1 }}
480
493
  type='text'
481
494
  onPress={() => onTeamSelect ? onTeamSelect(event.away_team_id) : console.log('')}
482
495
  >
@@ -500,7 +513,7 @@ const TeamEventMarket = ({ event, hide_non_primary, flash_markets, league, float
500
513
  </Button>
501
514
  <Button
502
515
  disabled={!onTeamSelect}
503
- style={{ ...view_styles.body_row, minHeight:48 }}
516
+ style={{ ...view_styles.body_row, minHeight:48, flexGrow:1 }}
504
517
  type='text'
505
518
  onPress={() => onTeamSelect ? onTeamSelect(event.home_team_id) : console.log('')}
506
519
  >
@@ -0,0 +1,32 @@
1
+ import React, { useState } from 'react';
2
+ import { View } from '../../Components/Themed';
3
+ import { useColors } from '../../constants/useColors';
4
+ import type { ViewStyle } from 'react-native';
5
+
6
+ type WeightProgressProps = {
7
+ min_value:number,
8
+ max_value:number,
9
+ style?:ViewStyle,
10
+ value: number,
11
+ bar_height?:number
12
+ }
13
+
14
+ const WeightProgress = ({ value, bar_height, style }:WeightProgressProps) => {
15
+ const Colors = useColors();
16
+ const [ width, setWidth ] = useState(0);
17
+ let progress_width = value * width / 2
18
+ let start_point = width/2
19
+ if(progress_width < 0){
20
+ start_point += progress_width
21
+ }
22
+ return (
23
+ <View style={{ borderRadius:2, height: bar_height ? bar_height + 2: 6, backgroundColor:Colors.borders.light, padding:1, justifyContent:'center', ...style }} onLayout={(ev) => {
24
+ const { width } = ev.nativeEvent.layout;
25
+ setWidth(width)
26
+ }}>
27
+ <View style={{ position:'absolute', top:1, bottom:1, left:start_point, width:Math.abs(progress_width), backgroundColor:Colors.text.h1, height:bar_height??4, borderRadius:4 }}/>
28
+ </View>
29
+ )
30
+ }
31
+
32
+ export default WeightProgress
@@ -14,6 +14,7 @@ import MyOrderList from './components/MyOrderList';
14
14
  import ExternalPriceComparison from './components/ExternalPriceComparison';
15
15
  import OrderGradeBar from './components/OrderGradeBar';
16
16
  import MarketManager from './components/MarketManager';
17
+ import CreateMarketForm from './components/CreateMarketForm';
17
18
 
18
19
  export default {
19
20
  TeamEventMarket,
@@ -22,6 +23,7 @@ export default {
22
23
  BestAvailableOrderCard,
23
24
  EventMarket,
24
25
  OrderBookCard,
26
+ CreateMarketForm,
25
27
  MarketManager,
26
28
  OrderBookChart,
27
29
  AthleteTournamentMarket,
@@ -936,7 +936,8 @@ const MarketMaketHelpers = {
936
936
  }
937
937
  return cash
938
938
  },
939
- getNoVigPrice: (prices:ExternalPriceProps[], market:MarketProps) => {
939
+ getNoVigPrice: (prices:ExternalPriceProps[], market?:MarketProps) => {
940
+ if(!market){ return undefined }
940
941
  if(!prices || prices.length != 2){ return undefined }
941
942
  let external_name = prices[0]?.external_name
942
943
  if(!external_name){ return undefined }
@@ -199,6 +199,7 @@ const PollCard = ({ poll_id, height, width, view_mode, poll_response, action_loa
199
199
  )
200
200
  case 'correct_select':
201
201
  if(!poll || poll.poll_type != 'select' || !correct_option){ return <></> }
202
+ if(poll.status != 'closed' && correct_option && !poll_response){ return <></> }
202
203
  return (
203
204
  <View nativeID='selected_option' style={{ marginBottom:10, padding:10 }}>
204
205
  <Text style={{ marginBottom:5 }} size={14} theme='description' weight='semibold'>CORRECT ANSWER</Text>