be-components 2.6.0 → 2.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/lib/commonjs/AnalyticComponents/MarketPerformance/index.js +2 -0
  2. package/lib/commonjs/AnalyticComponents/MarketPerformance/index.js.map +1 -0
  3. package/lib/commonjs/AnalyticComponents/api/index.js +20 -0
  4. package/lib/commonjs/AnalyticComponents/api/index.js.map +1 -0
  5. package/lib/commonjs/AnalyticComponents/index.js +2 -0
  6. package/lib/commonjs/AnalyticComponents/index.js.map +1 -0
  7. package/lib/commonjs/Components/Icons.js +56 -0
  8. package/lib/commonjs/Components/Icons.js.map +1 -1
  9. package/lib/commonjs/MarketComponents/api/index.js +12 -0
  10. package/lib/commonjs/MarketComponents/api/index.js.map +1 -1
  11. package/lib/commonjs/MarketComponents/components/PodcastCard.js +30 -0
  12. package/lib/commonjs/MarketComponents/components/PodcastCard.js.map +1 -0
  13. package/lib/commonjs/MarketComponents/components/TeamEventMarket/index.js +69 -5
  14. package/lib/commonjs/MarketComponents/components/TeamEventMarket/index.js.map +1 -1
  15. package/lib/commonjs/SocialComponents/PodcastModule/api/index.js +28 -0
  16. package/lib/commonjs/SocialComponents/PodcastModule/api/index.js.map +1 -1
  17. package/lib/commonjs/SocialComponents/PodcastModule/components/ClaimPodcastModal.js +140 -0
  18. package/lib/commonjs/SocialComponents/PodcastModule/components/ClaimPodcastModal.js.map +1 -0
  19. package/lib/commonjs/SocialComponents/PodcastModule/index.js +235 -33
  20. package/lib/commonjs/SocialComponents/PodcastModule/index.js.map +1 -1
  21. package/lib/module/AnalyticComponents/MarketPerformance/index.js +2 -0
  22. package/lib/module/AnalyticComponents/MarketPerformance/index.js.map +1 -0
  23. package/lib/module/AnalyticComponents/api/index.js +15 -0
  24. package/lib/module/AnalyticComponents/api/index.js.map +1 -0
  25. package/lib/module/AnalyticComponents/index.js +2 -0
  26. package/lib/module/AnalyticComponents/index.js.map +1 -0
  27. package/lib/module/Components/Icons.js +56 -0
  28. package/lib/module/Components/Icons.js.map +1 -1
  29. package/lib/module/MarketComponents/api/index.js +12 -0
  30. package/lib/module/MarketComponents/api/index.js.map +1 -1
  31. package/lib/module/MarketComponents/components/PodcastCard.js +23 -0
  32. package/lib/module/MarketComponents/components/PodcastCard.js.map +1 -0
  33. package/lib/module/MarketComponents/components/TeamEventMarket/index.js +69 -5
  34. package/lib/module/MarketComponents/components/TeamEventMarket/index.js.map +1 -1
  35. package/lib/module/SocialComponents/PodcastModule/api/index.js +28 -0
  36. package/lib/module/SocialComponents/PodcastModule/api/index.js.map +1 -1
  37. package/lib/module/SocialComponents/PodcastModule/components/ClaimPodcastModal.js +131 -0
  38. package/lib/module/SocialComponents/PodcastModule/components/ClaimPodcastModal.js.map +1 -0
  39. package/lib/module/SocialComponents/PodcastModule/index.js +236 -34
  40. package/lib/module/SocialComponents/PodcastModule/index.js.map +1 -1
  41. package/lib/typescript/src/AnalyticComponents/MarketPerformance/index.d.ts +1 -0
  42. package/lib/typescript/src/AnalyticComponents/MarketPerformance/index.d.ts.map +1 -0
  43. package/lib/typescript/src/AnalyticComponents/api/index.d.ts +5 -0
  44. package/lib/typescript/src/AnalyticComponents/api/index.d.ts.map +1 -0
  45. package/lib/typescript/src/AnalyticComponents/index.d.ts +1 -0
  46. package/lib/typescript/src/AnalyticComponents/index.d.ts.map +1 -0
  47. package/lib/typescript/src/Components/Icons.d.ts +1 -0
  48. package/lib/typescript/src/Components/Icons.d.ts.map +1 -1
  49. package/lib/typescript/src/MarketComponents/api/index.d.ts +2 -1
  50. package/lib/typescript/src/MarketComponents/api/index.d.ts.map +1 -1
  51. package/lib/typescript/src/MarketComponents/components/PodcastCard.d.ts +10 -0
  52. package/lib/typescript/src/MarketComponents/components/PodcastCard.d.ts.map +1 -0
  53. package/lib/typescript/src/MarketComponents/components/TeamEventMarket/index.d.ts +4 -2
  54. package/lib/typescript/src/MarketComponents/components/TeamEventMarket/index.d.ts.map +1 -1
  55. package/lib/typescript/src/MarketComponents/index.d.ts +3 -1
  56. package/lib/typescript/src/MarketComponents/index.d.ts.map +1 -1
  57. package/lib/typescript/src/SocialComponents/PodcastModule/api/index.d.ts +4 -1
  58. package/lib/typescript/src/SocialComponents/PodcastModule/api/index.d.ts.map +1 -1
  59. package/lib/typescript/src/SocialComponents/PodcastModule/components/ClaimPodcastModal.d.ts +11 -0
  60. package/lib/typescript/src/SocialComponents/PodcastModule/components/ClaimPodcastModal.d.ts.map +1 -0
  61. package/lib/typescript/src/SocialComponents/PodcastModule/index.d.ts +2 -1
  62. package/lib/typescript/src/SocialComponents/PodcastModule/index.d.ts.map +1 -1
  63. package/package.json +1 -1
  64. package/src/AnalyticComponents/MarketPerformance/index.tsx +0 -0
  65. package/src/AnalyticComponents/api/index.ts +19 -0
  66. package/src/AnalyticComponents/index.tsx +0 -0
  67. package/src/Components/Icons.tsx +20 -0
  68. package/src/MarketComponents/api/index.ts +13 -1
  69. package/src/MarketComponents/components/PodcastCard.tsx +24 -0
  70. package/src/MarketComponents/components/TeamEventMarket/index.tsx +47 -4
  71. package/src/SocialComponents/PodcastModule/api/index.ts +25 -1
  72. package/src/SocialComponents/PodcastModule/components/ClaimPodcastModal.tsx +79 -0
  73. package/src/SocialComponents/PodcastModule/index.tsx +136 -31
  74. package/src/types.d.ts +1 -0
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import type { PodcastEpisodesProps, PodcastProps, PublicPlayerProps } from '../../types';
3
3
  type PodcastModuleProps = {
4
+ player_id?: string;
4
5
  podcast_id: string;
5
6
  padding_insets?: {
6
7
  top: number;
@@ -12,6 +13,6 @@ type PodcastModuleProps = {
12
13
  onSelectEpisode: (pe: PodcastEpisodesProps) => void;
13
14
  onSelectPlayer?: (p: PublicPlayerProps) => void;
14
15
  };
15
- declare const PodcastModule: ({ podcast_id, padding_insets, onSelectEpisode, onBack, onShareEpisode, onSharePodcast, onSelectPlayer }: PodcastModuleProps) => React.JSX.Element;
16
+ declare const PodcastModule: ({ podcast_id, player_id, padding_insets, onSelectEpisode, onBack, onShareEpisode, onSharePodcast, onSelectPlayer }: PodcastModuleProps) => React.JSX.Element;
16
17
  export default PodcastModule;
17
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/SocialComponents/PodcastModule/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAEnD,OAAO,KAAK,EAA6B,oBAAoB,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAUpH,KAAK,kBAAkB,GAAG;IACtB,UAAU,EAAC,MAAM,CAAC;IAClB,cAAc,CAAC,EAAC;QAAE,GAAG,EAAC,MAAM,CAAC;QAAC,MAAM,EAAC,MAAM,CAAA;KAAE,CAAC;IAC9C,MAAM,CAAC,EAAC,MAAM,IAAI,CAAC;IACnB,cAAc,CAAC,EAAC,CAAC,EAAE,EAAC,oBAAoB,KAAK,IAAI,CAAC;IAClD,cAAc,CAAC,EAAC,CAAC,CAAC,EAAC,YAAY,KAAK,IAAI,CAAC;IACzC,eAAe,EAAC,CAAC,EAAE,EAAC,oBAAoB,KAAK,IAAI,CAAA;IACjD,cAAc,CAAC,EAAC,CAAC,CAAC,EAAC,iBAAiB,KAAK,IAAI,CAAA;CAChD,CAAA;AAED,QAAA,MAAM,aAAa,4GAA4G,kBAAkB,sBA8LhJ,CAAA;AAED,eAAe,aAAa,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/SocialComponents/PodcastModule/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAEnD,OAAO,KAAK,EAA4C,oBAAoB,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAWnI,KAAK,kBAAkB,GAAG;IACtB,SAAS,CAAC,EAAC,MAAM,CAAC;IAClB,UAAU,EAAC,MAAM,CAAC;IAClB,cAAc,CAAC,EAAC;QAAE,GAAG,EAAC,MAAM,CAAC;QAAC,MAAM,EAAC,MAAM,CAAA;KAAE,CAAC;IAC9C,MAAM,CAAC,EAAC,MAAM,IAAI,CAAC;IACnB,cAAc,CAAC,EAAC,CAAC,EAAE,EAAC,oBAAoB,KAAK,IAAI,CAAC;IAClD,cAAc,CAAC,EAAC,CAAC,CAAC,EAAC,YAAY,KAAK,IAAI,CAAC;IACzC,eAAe,EAAC,CAAC,EAAE,EAAC,oBAAoB,KAAK,IAAI,CAAA;IACjD,cAAc,CAAC,EAAC,CAAC,CAAC,EAAC,iBAAiB,KAAK,IAAI,CAAA;CAChD,CAAA;AAED,QAAA,MAAM,aAAa,uHAAuH,kBAAkB,sBA8R3J,CAAA;AAED,eAAe,aAAa,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "be-components",
3
- "version": "2.6.0",
3
+ "version": "2.6.2",
4
4
  "description": "Components for BettorEdge Apps",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -0,0 +1,19 @@
1
+ import { APIOverrides } from "../../ApiOverrides";
2
+
3
+ let EVENT_SVC_API = ''
4
+ let AUTH_SVC_API = ''
5
+ let MK_SVC_API = ''
6
+
7
+ export { AnalyticComponentApi }
8
+
9
+ const AnalyticComponentApi = {
10
+ setEnvironment: () => {
11
+ const endpoints = APIOverrides.getEndpoints();
12
+ EVENT_SVC_API = endpoints['EVENT_SVC_API'] as string;
13
+ MK_SVC_API = endpoints['MK_SVC_API'] as string;
14
+ AUTH_SVC_API = endpoints['AUTH_SVC_API'] as string
15
+ console.log(EVENT_SVC_API, MK_SVC_API, AUTH_SVC_API)
16
+ },
17
+
18
+
19
+ }
File without changes
@@ -453,6 +453,25 @@ const NotificationIcon = ({color, size}:IconProps) => {
453
453
  )
454
454
  }
455
455
 
456
+ const HeadphoneIcon = ({ color, size }:IconProps) => {
457
+ let icon_size = size ?? 17
458
+ return (
459
+ <svg width={`${icon_size}px`} height={`${icon_size}px`} viewBox="0 0 22 23" version="1.1" xmlns="http://www.w3.org/2000/svg">
460
+ <title>headphones-round-sound-svgrepo-com</title>
461
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
462
+ <g id="headphones-round-sound-svgrepo-com" transform="translate(1.000000, 1.000000)" stroke={color ?? Colors.brand.midnight} stroke-width="2">
463
+ <path d="M20,15 L20,10 C20,8.1786 19.513,6.47087 18.6622,5 M0,16 L0,10 C0,4.47715 4.47715,0 10,0 C11.8214,0 13.5291,0.48697 15,1.33782" id="Shape" stroke-linecap="round"></path>
464
+ <path d="M6,13.1871 C6,12.6088 6,12.3196 5.93097,12.0899 C5.77135,11.5588 5.35457,11.156 4.83579,11.0313 C4.61143,10.9775 4.33578,11.0002 3.78447,11.0457 C2.82772,11.1247 2.34935,11.1642 1.95934,11.3151 C1.06004,11.6629 0.3739,12.4394 0.1131,13.4044 C0,13.8229 0,14.3248 0,15.3285 L0,15.514 C0,16.5431 0,17.0577 0.12305,17.493 C0.36454,18.3475 0.942,19.0543 1.71133,19.437 C2.10333,19.632 2.58932,19.7123 3.56129,19.8728 C4.20632,19.9793 4.52883,20.0326 4.78984,19.9788 C5.30414,19.8729 5.72826,19.4938 5.90852,18.9791 C6,18.7178 6,18.3763 6,17.6934 L6,13.1871 Z" id="Path"></path>
465
+ <path d="M14,13.1871 C14,12.6088 14,12.3196 14.069,12.0899 C14.2286,11.5588 14.6454,11.156 15.1642,11.0313 C15.3886,10.9775 15.6642,11.0002 16.2155,11.0457 C17.1723,11.1247 17.6506,11.1642 18.0407,11.3151 C18.94,11.6629 19.6261,12.4394 19.8869,13.4044 C20,13.8229 20,14.3248 20,15.3285 L20,15.514 C20,16.5431 20,17.0577 19.877,17.493 C19.6355,18.3475 19.058,19.0543 18.2887,19.437 C17.8967,19.632 17.4107,19.7123 16.4387,19.8728 C15.7937,19.9793 15.4712,20.0326 15.2102,19.9788 C14.6959,19.8729 14.2717,19.4938 14.0915,18.9791 C14,18.7178 14,18.3763 14,17.6934 L14,13.1871 Z" id="Path"></path>
466
+ <line x1="10" y1="4.5" x2="10" y2="9.5" id="Path" stroke-linecap="round"></line>
467
+ <line x1="13" y1="6" x2="13" y2="8" id="Path" stroke-linecap="round"></line>
468
+ <line x1="7" y1="6" x2="7" y2="8" id="Path" stroke-linecap="round"></line>
469
+ </g>
470
+ </g>
471
+ </svg>
472
+ )
473
+ }
474
+
456
475
  const EdgeCoinIcon = ({ color, size }:IconProps) => {
457
476
  let icon_size = size ?? 17
458
477
  return (
@@ -1532,6 +1551,7 @@ export default {
1532
1551
  ChangeIcon,
1533
1552
  USDIcon,
1534
1553
  EyeOffIcon,
1554
+ HeadphoneIcon,
1535
1555
  DiscoverCardIcon,
1536
1556
  ChatIcon,
1537
1557
  AmexCardIcon,
@@ -1,10 +1,11 @@
1
1
  import axios from 'axios';
2
2
  import { APIOverrides } from "../../ApiOverrides"
3
- import type { AthleteProps, BestAvailableResponseProps, ContestStatProps, EventOrderStatProps, EventProps, MarketProps, MarketSideOptionProps, MatchProps, OrderProps, TeamProps, TournamentProps } from "../../types"
3
+ import type { AthleteProps, BestAvailableResponseProps, ContestStatProps, EventOrderStatProps, EventProps, MarketProps, MarketSideOptionProps, MatchProps, OrderProps, PodcastProps, TeamProps, TournamentProps } from "../../types"
4
4
 
5
5
  let EVENT_SVC_API = ''
6
6
  let AUTH_SVC_API = ''
7
7
  let MK_SVC_API = ''
8
+ let SOCIAL_SVC_API = ''
8
9
 
9
10
  export { MarketComponentApi, MarketComponentHelpers }
10
11
 
@@ -14,6 +15,7 @@ const MarketComponentApi = {
14
15
  EVENT_SVC_API = endpoints['EVENT_SVC_API'] as string;
15
16
  MK_SVC_API = endpoints['MK_SVC_API'] as string;
16
17
  AUTH_SVC_API = endpoints['AUTH_SVC_API'] as string;
18
+ SOCIAL_SVC_API = endpoints['SOCIAL_SVC_API'] as string;
17
19
  },
18
20
  getMarkets:async():Promise<MarketProps[]> => {
19
21
  try {
@@ -52,6 +54,16 @@ const MarketComponentApi = {
52
54
  return []
53
55
  }
54
56
  },
57
+ getPodcastsByKeywords: async(keywords:string):Promise<PodcastProps[]> => {
58
+ try {
59
+ console.log(keywords)
60
+ const resp = await axios.get(`${SOCIAL_SVC_API}/v1/podcasts/search/keywords?keywords=${keywords}`);
61
+ console.log(resp.data)
62
+ return resp.data.podcasts
63
+ } catch (e) {
64
+ return []
65
+ }
66
+ },
55
67
  getTeamsByIds: async(team_ids:string[]):Promise<TeamProps[]> => {
56
68
  try {
57
69
  if(team_ids.length == 0){ return [] }
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import { Image, TouchableOpacity } from 'react-native';
3
+ import type { PodcastProps } from "../../types"
4
+ import { SocialPodcastHelpers } from '../../SocialComponents/api';
5
+
6
+ type PodcastCardProps = {
7
+ podcast:PodcastProps,
8
+ size:number,
9
+ onPodcastSelect:(pod:PodcastProps) => void
10
+ }
11
+
12
+ const PodcastCard = ({podcast, size, onPodcastSelect}:PodcastCardProps) => {
13
+
14
+ return (
15
+ <TouchableOpacity onPress={() => onPodcastSelect(podcast)}>
16
+ <Image
17
+ source={{ uri: SocialPodcastHelpers.getPodcastImage(podcast) }}
18
+ style={{ height:size, width:size }}
19
+ resizeMode='cover'
20
+ />
21
+ </TouchableOpacity>
22
+ )
23
+ }
24
+ export default PodcastCard
@@ -1,6 +1,6 @@
1
1
  import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
2
  import { View, Image, FlatList, TouchableOpacity, ActivityIndicator, ScrollView } from 'react-native';
3
- import type { AthleteProps, BEEventProps, BestAvailableOrderProps, CompanyProps, CompetitionProps, EventOrderStatProps, EventProps, MarketProps, MarketSideOptionProps, OrderProps, SquaresCompetitionProps, TradeProps } from '../../../types';
3
+ import type { AthleteProps, BEEventProps, BestAvailableOrderProps, CompanyProps, CompetitionProps, EventOrderStatProps, EventProps, MarketProps, MarketSideOptionProps, OrderProps, PodcastProps, SquaresCompetitionProps, TradeProps } from '../../../types';
4
4
  import { view_styles } from '../../../constants/styles';
5
5
  import { Button, Icons, LinearDiagnal, Text } from '../../../Components';
6
6
  import {TeamEventMarketHelpers} from './api';
@@ -14,6 +14,7 @@ import { MarketButtonHelpers } from '../MarketButton/api';
14
14
  import LinearGradient from 'react-native-linear-gradient';
15
15
  import { useIsInViewport } from '../../../Components/ViewportObserver';
16
16
  import ContestStatsCard from '../ContestStats';
17
+ import PodcastCard from '../PodcastCard';
17
18
 
18
19
  type TeamEventMarketProps = {
19
20
  event:EventProps,
@@ -21,6 +22,7 @@ type TeamEventMarketProps = {
21
22
  init_expanded?:boolean,
22
23
  competitions?:CompetitionProps[],
23
24
  show_id?:string,
25
+ show_podcasts?:boolean,
24
26
  squares_competitions?:SquaresCompetitionProps[],
25
27
  latest_trades:TradeProps[],
26
28
  best_available_orders:BestAvailableOrderProps[],
@@ -32,6 +34,7 @@ type TeamEventMarketProps = {
32
34
  onExpand?:(expanded:boolean) => void,
33
35
  onTeamSelect?:(team_id:string) => void,
34
36
  onShare?:(event:EventProps) => void,
37
+ onPodcastSelect?:(podcast:PodcastProps) => void,
35
38
  show_grades?:boolean,
36
39
  onCompetitionSelect:(competition_id:string) => void,
37
40
  onSquaresSelect: (sq_comp_id:string) => void,
@@ -40,23 +43,25 @@ type TeamEventMarketProps = {
40
43
  onActivate?:(event_id:string, event_type:string) => void
41
44
  activate_loading?:boolean
42
45
  }
43
- const TeamEventMarket = ({ event, init_expanded, show_id, activate_loading, competitions, squares_competitions, show_grades, markets, latest_trades, best_available_orders, event_order_stats, default_price_view, onTeamSelect, onSquaresSelect, onCompetitionSelect, onExpand, onOrder, onView, onViewAdditionalMarkets, onTradeLongPress, onActivate, onEvent, onShare }:TeamEventMarketProps) => {
46
+ const TeamEventMarket = ({ event, init_expanded, show_id, show_podcasts, activate_loading, competitions, squares_competitions, show_grades, markets, latest_trades, best_available_orders, event_order_stats, default_price_view, onTeamSelect, onSquaresSelect, onCompetitionSelect, onExpand, onOrder, onView, onViewAdditionalMarkets, onTradeLongPress, onActivate, onEvent, onShare, onPodcastSelect }:TeamEventMarketProps) => {
44
47
  const [ expanded_data, setExpandedData ] = useState<{
45
48
  expanded:boolean,
46
49
  loaded:boolean,
47
50
  loading:boolean,
51
+ podcasts:PodcastProps[],
48
52
  athletes:AthleteProps[]
49
53
  }>({
50
54
  loaded:false,
51
55
  loading:false,
52
56
  expanded:false,
53
- athletes:[]
57
+ athletes:[],
58
+ podcasts: []
54
59
  })
55
60
  const [ show_stats, setShowStats ] = useState(false);
56
61
  const [ sponsor, setSponsor ] = useState<CompanyProps|undefined>(undefined);
57
62
  const [ competitions_expanded, setCompetitionsExpanded ] = useState(false);
58
63
  const [ squares_expanded, setSquaresExpanded ] = useState(false);
59
- const { expanded, athletes, loaded, loading } = expanded_data;
64
+ const { expanded, athletes, loaded, loading, podcasts } = expanded_data;
60
65
  const event_status = TeamEventMarketHelpers.getEventStatus(event);
61
66
  const ref = useRef(null)
62
67
  const isInViewport = useIsInViewport(ref)
@@ -96,6 +101,11 @@ const TeamEventMarket = ({ event, init_expanded, show_id, activate_loading, comp
96
101
  if(onExpand){ onExpand(expanded ? false : true) }
97
102
  if(expanded){ return setExpandedData({ ...expanded_data, expanded: false }) }
98
103
  //Check if we have any non-primary markets sorted
104
+ let pods:PodcastProps[] = []
105
+ if(show_podcasts){
106
+ let key_words = `${event.away?.market_name} ${event.away?.name},${event.home?.market_name} ${event.home?.name}`
107
+ pods = await MarketComponentApi.getPodcastsByKeywords(key_words)
108
+ }
99
109
 
100
110
  if(loaded){ return setExpandedData({ ...expanded_data, expanded: true }) }
101
111
  setExpandedData({ ...expanded_data, expanded:true, loading:true });
@@ -107,6 +117,7 @@ const TeamEventMarket = ({ event, init_expanded, show_id, activate_loading, comp
107
117
  expanded:true,
108
118
  loaded:true,
109
119
  loading:false,
120
+ podcasts: pods,
110
121
  athletes: away_athletes.concat(home_athletes)
111
122
  })
112
123
  }
@@ -202,6 +213,20 @@ const TeamEventMarket = ({ event, init_expanded, show_id, activate_loading, comp
202
213
  )
203
214
  },[primary_markets.length])
204
215
 
216
+ const renderPodcasts = useCallback((data:{ item:PodcastProps, index:number }) => {
217
+ return (
218
+ <View style={{ margin:3 }}>
219
+ <PodcastCard
220
+ podcast={data.item}
221
+ size={60}
222
+ onPodcastSelect={(pod) => {
223
+ if(onPodcastSelect){ onPodcastSelect(pod) }
224
+ }}
225
+ />
226
+ </View>
227
+ )
228
+ },[podcasts.length])
229
+
205
230
 
206
231
  const renderNonPrimaryMarkets = useCallback((data: { item:EventOrderStatProps, index:number }) => {
207
232
  const market = markets.find(m => m.market_id == data.item.market_id);
@@ -551,6 +576,24 @@ const TeamEventMarket = ({ event, init_expanded, show_id, activate_loading, comp
551
576
  keyExtractor={(item) => `${item.market_id}:${item.side_type}:${item.side_id}`}
552
577
  horizontal
553
578
  />
579
+ {podcasts.length > 0 ?
580
+ <View style={{ flexDirection:'row', marginTop:10, borderBottomRightRadius:8, borderBottomLeftRadius:8, backgroundColor:Colors.shades.shade100 }}>
581
+ <View style={{ padding:5, paddingRight:20, paddingLeft:20, justifyContent:'center', backgroundColor:Colors.brand.midnight, borderBottomLeftRadius:8 }}>
582
+ <Icons.HeadphoneIcon size={36} color={Colors.shades.white} />
583
+ </View>
584
+ <View style={{ flex:1, padding:5 }}>
585
+ <Text style={{ marginBottom:3 }} size={14} weight='semibold' color={Colors.brand.midnight}>Need Help? Checkout these podcasts!</Text>
586
+ <FlatList
587
+ key={`${event.event_id}:pods`}
588
+ data={podcasts}
589
+ horizontal
590
+ showsHorizontalScrollIndicator={false}
591
+ renderItem={renderPodcasts}
592
+ keyExtractor={(item) => item.podcast_id.toString()}
593
+ />
594
+ </View>
595
+ </View>
596
+ :<></>}
554
597
  </View>
555
598
  :<></>}
556
599
  {show_stats ?
@@ -1,6 +1,6 @@
1
1
  import axios from "axios";
2
2
  import { APIOverrides } from "../../../ApiOverrides";
3
- import type { PlayerPodcastEpisodeProps, PodcastEpisodesProps, PodcastProps, PublicPlayerProps } from "../../../types";
3
+ import type { MyPlayerProps, PlayerPodcastEpisodeProps, PodcastEpisodesProps, PodcastProps, PublicPlayerProps } from "../../../types";
4
4
 
5
5
  let SOCIAL_SVC_API = '';
6
6
  let AUTH_SVC_API = '';
@@ -21,6 +21,30 @@ const PodcastApi = {
21
21
  return undefined
22
22
  }
23
23
  },
24
+ getMyDetails: async():Promise<MyPlayerProps | undefined> => {
25
+ try {
26
+ const resp = await axios.get(`${AUTH_SVC_API}/v1/players/player/me`)
27
+ return resp.data.player
28
+ } catch (e) {
29
+ return undefined
30
+ }
31
+ },
32
+ claimPodcast: async(podcast_id:string):Promise<PodcastProps | undefined> => {
33
+ try {
34
+ const resp = await axios.post(`${SOCIAL_SVC_API}/v1/podcasts/podcast/claim`, { podcast_id });
35
+ return resp.data.podcast
36
+ } catch (e) {
37
+ return undefined
38
+ }
39
+ },
40
+ approveClaim: async(podcast_id:string):Promise<PodcastProps | undefined> => {
41
+ try {
42
+ const resp = await axios.post(`${SOCIAL_SVC_API}/v1/podcasts/podcast/approve`, { podcast_id });
43
+ return resp.data.podcast
44
+ } catch (e) {
45
+ return undefined
46
+ }
47
+ },
24
48
  getPodcastEpisodesByPodcast: async(podcast_id:string, offset:number):Promise<{podcast_episodes:PodcastEpisodesProps[], player_podcast_episodes:PlayerPodcastEpisodeProps[]}> => {
25
49
  try {
26
50
  const resp = await axios.get(`${SOCIAL_SVC_API}/v1/podcasts/episodes/podcast/${podcast_id}?offset=${offset}`);
@@ -0,0 +1,79 @@
1
+ import React, { useState } from 'react';
2
+ import { View, Image } from 'react-native';
3
+ import type { PodcastProps } from '../../../types';
4
+ import { view_styles } from '../../../constants/styles';
5
+ import { Button, Text } from '../../../Components';
6
+ import Colors from '../../../constants/colors';
7
+ import { SocialPodcastHelpers } from '../../api';
8
+ import { PodcastApi } from '../api';
9
+
10
+ type ClaimPodcastModalProps = {
11
+ podcast:PodcastProps,
12
+ width:number,
13
+ onClose:() => void,
14
+ onPodcastUpdate:(pod:PodcastProps) => void
15
+ }
16
+
17
+ const ClaimPodcastModal = ({ podcast, onClose, onPodcastUpdate }:ClaimPodcastModalProps) => {
18
+ const [ loading, setLoading ] = useState(false);
19
+
20
+ const handleClaimPodcast = async() => {
21
+ setLoading(true);
22
+ const updated_pod = await PodcastApi.claimPodcast(podcast.podcast_id);
23
+ if(!updated_pod){ return alert('Unable to process claim, please try again later.') }
24
+ onPodcastUpdate(updated_pod)
25
+ setLoading(false);
26
+ }
27
+
28
+ return (
29
+ <View style={{ ...view_styles.section }}>
30
+ <View style={{ ...view_styles.section_header }}>
31
+ <Image
32
+ source={{ uri: SocialPodcastHelpers.getPodcastImage(podcast) }}
33
+ style={{ width:50, height:50, borderRadius:4 }}
34
+ resizeMode='cover'
35
+ />
36
+ <View style={{ flex:1, marginLeft:10 }}>
37
+ <Text theme='header'>Is this your podcast?</Text>
38
+ <Text style={{ marginTop:3 }} theme='body'>Claim this podcast and get it prioritized over other similar podcasts!</Text>
39
+ </View>
40
+ </View>
41
+ <View style={{ ...view_styles.section_body }}>
42
+ <Text style={{ marginBottom:10 }} theme='header'>Benefits of claiming podcast</Text>
43
+ <View style={{ ...view_styles.body_row, alignItems:'flex-start' }}>
44
+ <Text size={40} weight='bold'>*</Text>
45
+ <Text style={{ marginLeft:10 }} theme='header_2'>PodQuest, BettorEdge's proprietary podcast recommendation engine will suggest your podcast to interested parties based on their betting history!</Text>
46
+ </View>
47
+ <View style={{ ...view_styles.body_row, alignItems:'flex-start', paddingTop:0 }}>
48
+ <Text size={40} weight='bold'>*</Text>
49
+ <Text style={{ marginLeft:10 }} theme='header_2'>Adds the podcast to your profile for people to see your bets, takes, and podcasts all in one place!</Text>
50
+ </View>
51
+ <View style={{ ...view_styles.body_row, alignItems:'flex-start', paddingTop:0 }}>
52
+ <Text size={40} weight='bold'>*</Text>
53
+ <Text style={{ marginLeft:10 }} theme='header_2'>Additionally, it gets you a referral code allowing you to make money on users sent to BettorEdge!</Text>
54
+ </View>
55
+ </View>
56
+ <View style={{ ...view_styles.section_footer }}>
57
+ <Button
58
+ title='No Thanks'
59
+ style={{flex:1}}
60
+ padding={15}
61
+ title_color={Colors.shades.white}
62
+ backgroundColor={Colors.utility.error}
63
+ onPress={() => onClose()}
64
+ />
65
+ <Button
66
+ title='Request Claim'
67
+ style={{flex:2, marginLeft:5, opacity:loading?0.5:1}}
68
+ padding={15}
69
+ disabled={loading}
70
+ title_color={Colors.shades.white}
71
+ backgroundColor={Colors.utility.success}
72
+ onPress={() => handleClaimPodcast()}
73
+ />
74
+ </View>
75
+ </View>
76
+ )
77
+ }
78
+
79
+ export default ClaimPodcastModal
@@ -1,16 +1,18 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
  import { View, ActivityIndicator, Image, ScrollView, TouchableOpacity, FlatList } from "react-native"
3
- import type { PlayerPodcastEpisodeProps, PodcastEpisodesProps, PodcastProps, PublicPlayerProps } from '../../types';
3
+ import type { MyPlayerProps, PlayerPodcastEpisodeProps, PodcastEpisodesProps, PodcastProps, PublicPlayerProps } from '../../types';
4
4
  import { PodcastApi } from './api';
5
5
  import Colors from '../../constants/colors';
6
6
  import { SocialPodcastHelpers } from '../api';
7
7
  import { view_styles } from '../../constants/styles';
8
- import { Button, Icons, Text } from '../../Components';
8
+ import { Button, Icons, Spring, Text } from '../../Components';
9
9
  import PodcastEpisodeCard from '../PodcastEpisodeCard';
10
10
  import moment from 'moment-mini';
11
11
  import PlayerCard from '../PlayerCard';
12
+ import ClaimPodcastModal from './components/ClaimPodcastModal';
12
13
 
13
14
  type PodcastModuleProps = {
15
+ player_id?:string,
14
16
  podcast_id:string,
15
17
  padding_insets?:{ top:number, bottom:number },
16
18
  onBack?:() => void,
@@ -20,10 +22,12 @@ type PodcastModuleProps = {
20
22
  onSelectPlayer?:(p:PublicPlayerProps) => void
21
23
  }
22
24
 
23
- const PodcastModule = ({ podcast_id, padding_insets, onSelectEpisode, onBack, onShareEpisode, onSharePodcast, onSelectPlayer }:PodcastModuleProps) => {
25
+ const PodcastModule = ({ podcast_id, player_id, padding_insets, onSelectEpisode, onBack, onShareEpisode, onSharePodcast, onSelectPlayer }:PodcastModuleProps) => {
24
26
  const [ module_size, setModuleSize ] = useState({ height:700, width:330 });
27
+ const [ show_claim, setShowClaim ] = useState(false);
25
28
  const [ pod_data, setPodData ] = useState<{
26
29
  loading:boolean,
30
+ player?:MyPlayerProps,
27
31
  episodes_loading:boolean,
28
32
  podcast?:PodcastProps,
29
33
  podcast_episodes:PodcastEpisodesProps[],
@@ -38,8 +42,8 @@ const PodcastModule = ({ podcast_id, padding_insets, onSelectEpisode, onBack, on
38
42
  players:[],
39
43
  episodes_offset:0
40
44
  });
41
- const { loading, episodes_loading, podcast, podcast_episodes, episodes_offset, players, player_podcast_episodes } = pod_data;
42
-
45
+ const { loading, episodes_loading, podcast, podcast_episodes, episodes_offset, players, player_podcast_episodes, player } = pod_data;
46
+ const claimed_player = pod_data.players.find(p => p.player_id == podcast?.claimed_player_id);
43
47
  useEffect(() => {
44
48
  PodcastApi.setEnvironment();
45
49
  getPodDataFromServer(podcast_id, 0);
@@ -49,13 +53,19 @@ const PodcastModule = ({ podcast_id, padding_insets, onSelectEpisode, onBack, on
49
53
  setPodData({ ...pod_data, loading:true });
50
54
  const pod = await PodcastApi.getPodcastById(id);
51
55
  const pod_ep = await PodcastApi.getPodcastEpisodesByPodcast(id, offset);
52
-
56
+ let me:MyPlayerProps | undefined = undefined;
57
+ if(player_id){
58
+ me = await PodcastApi.getMyDetails();
59
+ }
60
+ let player_ids = pod?.player_ids ?? []
61
+ if(pod?.claimed_player_id){ player_ids.push(pod.claimed_player_id) }
53
62
  const ps = await PodcastApi.getPlayersByPlayerIds(pod?.player_ids);
54
63
  setPodData({
55
64
  ...pod_data,
56
65
  loading: false,
57
66
  episodes_loading: false,
58
67
  podcast: pod,
68
+ player: me,
59
69
  players:ps,
60
70
  podcast_episodes: pod_ep.podcast_episodes,
61
71
  player_podcast_episodes: pod_ep.player_podcast_episodes,
@@ -75,6 +85,15 @@ const PodcastModule = ({ podcast_id, padding_insets, onSelectEpisode, onBack, on
75
85
  })
76
86
  }
77
87
 
88
+ const approveClaim = async() => {
89
+ if(!player || player.role != 'admin'){ return alert('Not eligible to approve this request') }
90
+ const pod = await PodcastApi.approveClaim(podcast_id);
91
+ setPodData({
92
+ ...pod_data,
93
+ podcast: pod
94
+ })
95
+ }
96
+
78
97
  const renderPlayers = (data:{item:PublicPlayerProps, index:number}) => {
79
98
  return (
80
99
  <View style={{ padding:4 }}>
@@ -116,30 +135,75 @@ const PodcastModule = ({ podcast_id, padding_insets, onSelectEpisode, onBack, on
116
135
  )
117
136
  }
118
137
 
138
+ let height = module_size.height * 0.5
139
+ let width = module_size.width
140
+
141
+ let description = `${podcast.description.slice(0,200)}...`
142
+ if(podcast.description_override){ description = `${podcast.description.slice(0,200)}...` }
143
+
119
144
  return (
120
145
  <View style={{ flex:1 }}>
121
- <View style={{ flex:1, backgroundColor:Colors.shades.black_faded }} onLayout={(ev) => {
146
+ <View style={{ flex:1, backgroundColor:Colors.shades.white }} onLayout={(ev) => {
122
147
  const { height, width } = ev.nativeEvent.layout
123
148
  setModuleSize({ width, height });
124
149
  }}>
125
- <View style={{ position:'absolute', top:0, left:0, right:0 }} nativeID='profile_image'>
126
- <Image
127
- source={{ uri: SocialPodcastHelpers.getPodcastImage(podcast) }}
128
- style={{ width: module_size.width, height: module_size.width, borderBottomRightRadius:50, borderBottomLeftRadius:50 }}
129
- resizeMode='cover'
130
- />
131
-
132
- </View>
133
150
  <ScrollView style={{ flex:1 }}>
134
- <View style={{ ...view_styles.section, marginTop:module_size.width - 150 }}>
135
- <View style={{ ...view_styles.section_header }}>
136
- <View style={{ flex:1 }}>
137
- <Text theme='header'>{podcast.title}</Text>
138
- <Text style={{ marginTop:4 }} theme='body_2'>{podcast.description_override ?? podcast.description}</Text>
151
+ <View nativeID='podcast_header'>
152
+ <Image
153
+ source={{ uri: SocialPodcastHelpers.getPodcastImage(podcast) }}
154
+ style={{ width, height }}
155
+ resizeMode='cover'
156
+ />
157
+ <View style={{ padding:20, position:'absolute', bottom:0, left:0, right:0, ...style.blur }}>
158
+ <TouchableOpacity
159
+ onPress={() => {
160
+ let episode = podcast_episodes.sort((a,b) => moment(b.publish_date).unix() - moment(a.publish_date).unix())[0]
161
+ if(!episode){ return alert('Unable to process') }
162
+ onSelectEpisode(episode)
163
+ }}
164
+ disabled={podcast_episodes.length == 0 ? true : false}
165
+ style={{ padding:10, borderRadius:8, width:module_size.width*0.7, flexDirection:'row', alignItems:'center', justifyContent:'center', alignSelf:'center', backgroundColor:Colors.shades.white, ...view_styles.float }}>
166
+ <Icons.PlayIcon size={20} color={Colors.brand.electric}/>
167
+ <Text style={{ marginLeft:15 }} weight='bold' color={Colors.brand.electric}>Play Episode</Text>
168
+ </TouchableOpacity>
169
+ {!podcast.claim_status ?
170
+ <TouchableOpacity
171
+ style={{ padding:10, marginTop:5, borderRadius:8, width:module_size.width*0.7, flexDirection:'row', alignItems:'center', justifyContent:'center', alignSelf:'center', backgroundColor:Colors.utility.success, ...view_styles.float }}
172
+ onPress={() => setShowClaim(true)}>
173
+ <Icons.HeadphoneIcon size={20} color={Colors.shades.white}/>
174
+ <Text style={{ marginLeft:15 }} weight='bold' color={Colors.shades.white}>Claim This Podcast!</Text>
175
+ </TouchableOpacity>
176
+ :podcast.claim_status == 'requested' && player?.role != 'admin' ?
177
+ <View
178
+ style={{ padding:10, marginTop:5, borderRadius:8, width:module_size.width*0.7, flexDirection:'row', alignItems:'center', justifyContent:'center', alignSelf:'center', backgroundColor:Colors.brand.midnight, ...view_styles.float }}>
179
+ <Icons.HeadphoneIcon size={20} color={Colors.shades.white}/>
180
+ <Text style={{ marginLeft:15 }} weight='bold' color={Colors.shades.white}>Claim Requested!</Text>
139
181
  </View>
140
- {onSharePodcast ?
141
- <TouchableOpacity style={{ padding:5, marginLeft:5 }} onPress={() => onSharePodcast(podcast)}>
142
- <Icons.ShareIcon size={14} color={Colors.brand.electric} />
182
+ :podcast.claim_status == 'requested' && player?.role == 'admin' ?
183
+ <TouchableOpacity
184
+ style={{ padding:10, marginTop:5, borderRadius:8, width:module_size.width*0.7, flexDirection:'row', alignItems:'center', justifyContent:'center', alignSelf:'center', backgroundColor:Colors.utility.success, ...view_styles.float }}
185
+ onPress={() => approveClaim()}>
186
+ <Icons.HeadphoneIcon size={20} color={Colors.shades.white}/>
187
+ <Text style={{ marginLeft:15 }} weight='bold' color={Colors.shades.white}>Approve Claim Request!</Text>
188
+ </TouchableOpacity>
189
+ :<></>}
190
+ <View style={{ marginTop:10 }}>
191
+ <Text size={24} weight='bold' color={Colors.shades.white}>{podcast.title}</Text>
192
+ <Text style={{ marginTop:4 }} color={Colors.shades.white} weight='semibold'>{description}</Text>
193
+ </View>
194
+ {podcast.claim_status == 'claimed' ?
195
+ <View style={{ position:'absolute', top:20, left:5, height:40, width:40, borderRadius:100, justifyContent:'center', alignItems:'center' }}>
196
+ <Icons.CheckCirlceIcon size={30} color={Colors.utility.success} />
197
+ </View>
198
+ :<></>}
199
+ {podcast.claim_status == 'claimed' && claimed_player ?
200
+ <TouchableOpacity style={{ position:'absolute', top:20, right:5, justifyContent:'center', alignItems:'center' }}
201
+ onPress={() => onSelectPlayer ? onSelectPlayer(claimed_player) : console.log('')}>
202
+ <Image
203
+ source={{ uri: claimed_player.profile_pic && claimed_player.profile_pic != '' ? claimed_player.profile_pic:'https://res.cloudinary.com/hoabts6mc/image/upload/v1722453927/default_man_n96ofq.webp' }}
204
+ style={{ height:40, width:40, borderRadius:100 }}
205
+ resizeMode='cover'
206
+ />
143
207
  </TouchableOpacity>
144
208
  :<></>}
145
209
  </View>
@@ -200,16 +264,57 @@ const PodcastModule = ({ podcast_id, padding_insets, onSelectEpisode, onBack, on
200
264
  </View>
201
265
  </View>
202
266
  </ScrollView>
203
- {onBack ?
204
- <TouchableOpacity
205
- style={{ position:'absolute', top:padding_insets?.top ?? 0, left:0, ...view_styles.section, backgroundColor:Colors.shades.shade100, height:50, width:50, borderRadius:100, justifyContent:'center', alignItems:'center' }}
206
- onPress={() => onBack()}>
207
- <Icons.ChevronIcon direction='left' color={Colors.brand.midnight} size={14} />
208
- </TouchableOpacity>
209
- :<></>}
267
+ <View style={{ position:'absolute', top:padding_insets?.top ?? 0, left:0, right:0, flexDirection:'row', alignItems:'center' }}>
268
+ {onBack ?
269
+ <TouchableOpacity
270
+ style={{ ...view_styles.section, backgroundColor:Colors.shades.shade100, height:50, width:50, borderRadius:100, justifyContent:'center', alignItems:'center' }}
271
+ onPress={() => onBack()}>
272
+ <Icons.ChevronIcon direction='left' color={Colors.brand.midnight} size={14} />
273
+ </TouchableOpacity>
274
+ :<></>}
275
+ <View style={{ flex:1 }} />
276
+ {onSharePodcast ?
277
+ <TouchableOpacity
278
+ style={{ ...view_styles.section, backgroundColor:Colors.shades.shade100, height:50, width:50, borderRadius:100, justifyContent:'center', alignItems:'center' }}
279
+ onPress={() => onSharePodcast(podcast)}>
280
+ <Icons.ShareIcon color={Colors.brand.electric} size={14} />
281
+ </TouchableOpacity>
282
+ :<></>}
283
+ </View>
284
+
210
285
  </View>
286
+ {show_claim ?
287
+ <View style={{ position:'absolute', flex:1, backgroundColor:Colors.shades.black_faded, top:0, left:0, right:0, bottom:0, justifyContent:'flex-end' }}>
288
+ <Spring
289
+ slide='vertical'
290
+ to={0}
291
+ from={500}
292
+
293
+ >
294
+ <ClaimPodcastModal
295
+ podcast={podcast}
296
+ width={module_size.width - 20}
297
+ onClose={() => setShowClaim(false)}
298
+ onPodcastUpdate={(pod) => {
299
+ setShowClaim(false);
300
+ setPodData({
301
+ ...pod_data,
302
+ podcast: pod
303
+ })
304
+ }}
305
+ />
306
+ </Spring>
307
+ </View>
308
+ :<></>}
211
309
  </View>
212
310
  )
213
311
  }
214
312
 
215
- export default PodcastModule
313
+ export default PodcastModule
314
+
315
+ const style:any = {
316
+ blur: {
317
+ backdropFilter: 'blur(75px)',
318
+ backgroundColor:Colors.shades.black_faded_heavy
319
+ }
320
+ }
package/src/types.d.ts CHANGED
@@ -78,6 +78,7 @@ export interface PodcastProps {
78
78
  lead_contact_name?:string,
79
79
  secondary_contact?:string,
80
80
  last_episode_pull?:any,
81
+ claimed_player_id?:string,
81
82
  title: string,
82
83
  description: string,
83
84
  claim_status?:string,