@bettoredge/calcutta 0.2.0
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.
- package/package.json +46 -0
- package/src/components/CalcuttaAuction.tsx +453 -0
- package/src/components/CalcuttaAuctionItem.tsx +292 -0
- package/src/components/CalcuttaBidInput.tsx +214 -0
- package/src/components/CalcuttaCard.tsx +131 -0
- package/src/components/CalcuttaDetail.tsx +377 -0
- package/src/components/CalcuttaEscrow.tsx +464 -0
- package/src/components/CalcuttaItemResults.tsx +207 -0
- package/src/components/CalcuttaLeaderboard.tsx +179 -0
- package/src/components/CalcuttaPayoutPreview.tsx +194 -0
- package/src/components/CalcuttaRoundResults.tsx +250 -0
- package/src/components/CalcuttaTemplateSelector.tsx +124 -0
- package/src/components/sealed/AuctionResultsModal.tsx +165 -0
- package/src/components/sealed/EscrowBottomSheet.tsx +185 -0
- package/src/components/sealed/SealedBidAuction.tsx +541 -0
- package/src/components/sealed/SealedBidHeader.tsx +116 -0
- package/src/components/sealed/SealedBidInfoTab.tsx +247 -0
- package/src/components/sealed/SealedBidItemCard.tsx +385 -0
- package/src/components/sealed/SealedBidItemsTab.tsx +235 -0
- package/src/components/sealed/SealedBidMyBidsTab.tsx +512 -0
- package/src/components/sealed/SealedBidPlayersTab.tsx +220 -0
- package/src/components/sealed/SealedBidStatusBar.tsx +415 -0
- package/src/components/sealed/SealedBidTabBar.tsx +172 -0
- package/src/helpers/formatting.ts +56 -0
- package/src/helpers/lifecycleState.ts +71 -0
- package/src/helpers/payout.ts +39 -0
- package/src/helpers/validation.ts +64 -0
- package/src/hooks/useCalcuttaAuction.ts +164 -0
- package/src/hooks/useCalcuttaBid.ts +43 -0
- package/src/hooks/useCalcuttaCompetition.ts +63 -0
- package/src/hooks/useCalcuttaEscrow.ts +52 -0
- package/src/hooks/useCalcuttaItemImages.ts +79 -0
- package/src/hooks/useCalcuttaPlayers.ts +46 -0
- package/src/hooks/useCalcuttaResults.ts +58 -0
- package/src/hooks/useCalcuttaSocket.ts +131 -0
- package/src/hooks/useCalcuttaTemplates.ts +36 -0
- package/src/index.ts +74 -0
- package/src/types.ts +31 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { useState, useCallback } from 'react';
|
|
2
|
+
import { depositToEscrow, withdrawFromEscrow, getEscrowBalance } from '@bettoredge/api';
|
|
3
|
+
import type { CalcuttaEscrowProps } from '@bettoredge/types';
|
|
4
|
+
|
|
5
|
+
export interface CalcuttaEscrowState {
|
|
6
|
+
loading: boolean;
|
|
7
|
+
error?: string;
|
|
8
|
+
escrow?: CalcuttaEscrowProps;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const useCalcuttaEscrow = (calcutta_competition_id?: string) => {
|
|
12
|
+
const [state, setState] = useState<CalcuttaEscrowState>({ loading: false });
|
|
13
|
+
|
|
14
|
+
const fetchEscrow = useCallback(async () => {
|
|
15
|
+
if (!calcutta_competition_id) return;
|
|
16
|
+
setState(prev => ({ ...prev, loading: true }));
|
|
17
|
+
try {
|
|
18
|
+
const resp = await getEscrowBalance(calcutta_competition_id);
|
|
19
|
+
setState({ loading: false, escrow: resp.escrow });
|
|
20
|
+
} catch {
|
|
21
|
+
setState(prev => ({ ...prev, loading: false }));
|
|
22
|
+
}
|
|
23
|
+
}, [calcutta_competition_id]);
|
|
24
|
+
|
|
25
|
+
const deposit = useCallback(async (amount: number) => {
|
|
26
|
+
if (!calcutta_competition_id) return;
|
|
27
|
+
setState(prev => ({ ...prev, loading: true, error: undefined }));
|
|
28
|
+
try {
|
|
29
|
+
const resp = await depositToEscrow(calcutta_competition_id, amount);
|
|
30
|
+
setState({ loading: false, escrow: resp.escrow });
|
|
31
|
+
return resp.escrow;
|
|
32
|
+
} catch (e: any) {
|
|
33
|
+
setState(prev => ({ ...prev, loading: false, error: e.message }));
|
|
34
|
+
throw e;
|
|
35
|
+
}
|
|
36
|
+
}, [calcutta_competition_id]);
|
|
37
|
+
|
|
38
|
+
const withdraw = useCallback(async (amount: number) => {
|
|
39
|
+
if (!calcutta_competition_id) return;
|
|
40
|
+
setState(prev => ({ ...prev, loading: true, error: undefined }));
|
|
41
|
+
try {
|
|
42
|
+
const resp = await withdrawFromEscrow(calcutta_competition_id, amount);
|
|
43
|
+
setState({ loading: false, escrow: resp.escrow });
|
|
44
|
+
return resp.escrow;
|
|
45
|
+
} catch (e: any) {
|
|
46
|
+
setState(prev => ({ ...prev, loading: false, error: e.message }));
|
|
47
|
+
throw e;
|
|
48
|
+
}
|
|
49
|
+
}, [calcutta_competition_id]);
|
|
50
|
+
|
|
51
|
+
return { ...state, fetchEscrow, deposit, withdraw };
|
|
52
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
2
|
+
import { getBulkTeams, getBulkAthletes } from '@bettoredge/api';
|
|
3
|
+
import type { CalcuttaAuctionItemProps } from '@bettoredge/types';
|
|
4
|
+
|
|
5
|
+
export interface ItemImageMap {
|
|
6
|
+
[item_id: string]: { url: string } | undefined;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Fetches team/athlete images for calcutta auction items.
|
|
11
|
+
* Groups items by type (team vs athlete), bulk-fetches from sr_svc,
|
|
12
|
+
* and returns a map of item_id → image.
|
|
13
|
+
*/
|
|
14
|
+
export const useCalcuttaItemImages = (items: CalcuttaAuctionItemProps[]) => {
|
|
15
|
+
const [images, setImages] = useState<ItemImageMap>({});
|
|
16
|
+
const [loading, setLoading] = useState(false);
|
|
17
|
+
const fetchedRef = useRef<Set<string>>(new Set());
|
|
18
|
+
|
|
19
|
+
const fetchImages = useCallback(async (auctionItems: CalcuttaAuctionItemProps[]) => {
|
|
20
|
+
// Separate by type and dedupe against already-fetched
|
|
21
|
+
const teamIds: string[] = [];
|
|
22
|
+
const athleteIds: string[] = [];
|
|
23
|
+
|
|
24
|
+
for (const item of auctionItems) {
|
|
25
|
+
if (!item.item_id || fetchedRef.current.has(item.item_id)) continue;
|
|
26
|
+
if (item.item_type === 'team') {
|
|
27
|
+
teamIds.push(item.item_id);
|
|
28
|
+
} else if (item.item_type === 'athlete') {
|
|
29
|
+
athleteIds.push(item.item_id);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (teamIds.length === 0 && athleteIds.length === 0) return;
|
|
34
|
+
|
|
35
|
+
setLoading(true);
|
|
36
|
+
const newImages: ItemImageMap = {};
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const [teamsRes, athletesRes] = await Promise.all([
|
|
40
|
+
teamIds.length > 0
|
|
41
|
+
? getBulkTeams({ attribute: 'team_id', values: teamIds }).catch(() => ({ teams: [] }))
|
|
42
|
+
: { teams: [] },
|
|
43
|
+
athleteIds.length > 0
|
|
44
|
+
? getBulkAthletes({ attribute: 'athlete_id', values: athleteIds }).catch(() => ({ athletes: [] }))
|
|
45
|
+
: { athletes: [] },
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
for (const team of (teamsRes.teams || [])) {
|
|
49
|
+
if (team.image?.url) {
|
|
50
|
+
newImages[team.team_id] = team.image;
|
|
51
|
+
}
|
|
52
|
+
fetchedRef.current.add(team.team_id);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
for (const athlete of (athletesRes.athletes || [])) {
|
|
56
|
+
if (athlete.image?.url) {
|
|
57
|
+
newImages[athlete.athlete_id] = athlete.image;
|
|
58
|
+
}
|
|
59
|
+
fetchedRef.current.add(athlete.athlete_id);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (Object.keys(newImages).length > 0) {
|
|
63
|
+
setImages(prev => ({ ...prev, ...newImages }));
|
|
64
|
+
}
|
|
65
|
+
} catch {
|
|
66
|
+
// Silently fail — items will show fallback icons
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
setLoading(false);
|
|
70
|
+
}, []);
|
|
71
|
+
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
if (items.length > 0) {
|
|
74
|
+
fetchImages(items);
|
|
75
|
+
}
|
|
76
|
+
}, [items.map(i => i.item_id).join(','), fetchImages]);
|
|
77
|
+
|
|
78
|
+
return { images, loading };
|
|
79
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useState, useEffect, useRef, useCallback } from 'react';
|
|
2
|
+
import { getPlayersByIds } from '@bettoredge/api';
|
|
3
|
+
import type { PublicPlayerProps } from '@bettoredge/types';
|
|
4
|
+
|
|
5
|
+
export interface CalcuttaPlayersState {
|
|
6
|
+
players: Record<string, PublicPlayerProps>;
|
|
7
|
+
loading: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const useCalcuttaPlayers = (player_ids: string[]) => {
|
|
11
|
+
const [state, setState] = useState<CalcuttaPlayersState>({
|
|
12
|
+
players: {},
|
|
13
|
+
loading: false,
|
|
14
|
+
});
|
|
15
|
+
const fetchedRef = useRef<Set<string>>(new Set());
|
|
16
|
+
|
|
17
|
+
const fetchPlayers = useCallback(async (ids: string[]) => {
|
|
18
|
+
// Dedupe against already-fetched
|
|
19
|
+
const newIds = ids.filter(id => id && !fetchedRef.current.has(id));
|
|
20
|
+
if (newIds.length === 0) return;
|
|
21
|
+
|
|
22
|
+
setState(prev => ({ ...prev, loading: true }));
|
|
23
|
+
try {
|
|
24
|
+
const resp = await getPlayersByIds(newIds);
|
|
25
|
+
const map: Record<string, PublicPlayerProps> = {};
|
|
26
|
+
for (const p of resp.players) {
|
|
27
|
+
map[p.player_id] = p;
|
|
28
|
+
fetchedRef.current.add(p.player_id);
|
|
29
|
+
}
|
|
30
|
+
setState(prev => ({
|
|
31
|
+
players: { ...prev.players, ...map },
|
|
32
|
+
loading: false,
|
|
33
|
+
}));
|
|
34
|
+
} catch {
|
|
35
|
+
setState(prev => ({ ...prev, loading: false }));
|
|
36
|
+
}
|
|
37
|
+
}, []);
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (player_ids.length > 0) {
|
|
41
|
+
fetchPlayers(player_ids);
|
|
42
|
+
}
|
|
43
|
+
}, [player_ids.join(','), fetchPlayers]);
|
|
44
|
+
|
|
45
|
+
return { ...state, fetchPlayers };
|
|
46
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import type {
|
|
3
|
+
CalcuttaRoundProps,
|
|
4
|
+
CalcuttaAuctionItemProps,
|
|
5
|
+
CalcuttaItemResultProps,
|
|
6
|
+
CalcuttaPayoutRuleProps,
|
|
7
|
+
} from '@bettoredge/types';
|
|
8
|
+
|
|
9
|
+
export interface RoundResultSummary {
|
|
10
|
+
round: CalcuttaRoundProps;
|
|
11
|
+
advanced_items: CalcuttaAuctionItemProps[];
|
|
12
|
+
eliminated_items: CalcuttaAuctionItemProps[];
|
|
13
|
+
payout_rule?: CalcuttaPayoutRuleProps;
|
|
14
|
+
total_payout: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const useCalcuttaResults = (
|
|
18
|
+
rounds: CalcuttaRoundProps[],
|
|
19
|
+
items: CalcuttaAuctionItemProps[],
|
|
20
|
+
item_results: CalcuttaItemResultProps[],
|
|
21
|
+
payout_rules: CalcuttaPayoutRuleProps[]
|
|
22
|
+
) => {
|
|
23
|
+
const roundSummaries = useMemo((): RoundResultSummary[] => {
|
|
24
|
+
return rounds.map(round => {
|
|
25
|
+
const roundResults = item_results.filter(r => r.round_number === round.round_number);
|
|
26
|
+
const advancedIds = roundResults.filter(r => r.result === 'advanced' || r.result === 'won').map(r => r.calcutta_auction_item_id);
|
|
27
|
+
const eliminatedIds = roundResults.filter(r => r.result === 'eliminated').map(r => r.calcutta_auction_item_id);
|
|
28
|
+
|
|
29
|
+
const rule = payout_rules.find(r => r.payout_type === 'round' && r.round_number === round.round_number);
|
|
30
|
+
const totalPayout = roundResults.reduce((sum, r) => sum + Number(r.payout_earned), 0);
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
round,
|
|
34
|
+
advanced_items: items.filter(i => advancedIds.includes(i.calcutta_auction_item_id)),
|
|
35
|
+
eliminated_items: items.filter(i => eliminatedIds.includes(i.calcutta_auction_item_id)),
|
|
36
|
+
payout_rule: rule,
|
|
37
|
+
total_payout: totalPayout,
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
}, [rounds, items, item_results, payout_rules]);
|
|
41
|
+
|
|
42
|
+
const itemPerformance = useMemo(() => {
|
|
43
|
+
return items.map(item => {
|
|
44
|
+
const results = item_results.filter(r => r.calcutta_auction_item_id === item.calcutta_auction_item_id);
|
|
45
|
+
const totalEarned = results.reduce((sum, r) => sum + Number(r.payout_earned), 0);
|
|
46
|
+
const lastResult = results[results.length - 1];
|
|
47
|
+
return {
|
|
48
|
+
item,
|
|
49
|
+
results,
|
|
50
|
+
total_earned: totalEarned,
|
|
51
|
+
rounds_survived: results.filter(r => r.result === 'advanced' || r.result === 'won').length,
|
|
52
|
+
final_result: lastResult?.result,
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
}, [items, item_results]);
|
|
56
|
+
|
|
57
|
+
return { roundSummaries, itemPerformance };
|
|
58
|
+
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
2
|
+
import type {
|
|
3
|
+
CalcuttaCompetitionProps,
|
|
4
|
+
CalcuttaAuctionItemProps,
|
|
5
|
+
CalcuttaBidProps,
|
|
6
|
+
} from '@bettoredge/types';
|
|
7
|
+
|
|
8
|
+
export interface CalcuttaPresencePlayer {
|
|
9
|
+
player_id: string;
|
|
10
|
+
username?: string;
|
|
11
|
+
profile_pic?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface CalcuttaPresence {
|
|
15
|
+
count: number;
|
|
16
|
+
players: CalcuttaPresencePlayer[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface CalcuttaSocketCallbacks {
|
|
20
|
+
onBidUpdate?: (data: { item: CalcuttaAuctionItemProps; bid: CalcuttaBidProps; item_deadline?: string; escrow_snapshot?: any }) => void;
|
|
21
|
+
onItemActive?: (data: { item: CalcuttaAuctionItemProps; item_deadline?: string }) => void;
|
|
22
|
+
onItemSold?: (data: { item: CalcuttaAuctionItemProps; winning_bid: CalcuttaBidProps; winning_player_id: string }) => void;
|
|
23
|
+
onItemUnsold?: (data: { item: CalcuttaAuctionItemProps }) => void;
|
|
24
|
+
onAuctionPaused?: () => void;
|
|
25
|
+
onAuctionResumed?: (data: { item?: CalcuttaAuctionItemProps; item_deadline?: string }) => void;
|
|
26
|
+
onAuctionClosed?: (data: { competition: CalcuttaCompetitionProps }) => void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const useCalcuttaSocket = (
|
|
30
|
+
calcutta_competition_id: string,
|
|
31
|
+
player_data: { username: string; profile_pic?: string },
|
|
32
|
+
getSocket: () => WebSocket | null,
|
|
33
|
+
getAccessToken: () => string | undefined,
|
|
34
|
+
getDeviceId: () => string | undefined,
|
|
35
|
+
callbacks?: CalcuttaSocketCallbacks,
|
|
36
|
+
) => {
|
|
37
|
+
const [connected, setConnected] = useState(false);
|
|
38
|
+
const [presence, setPresence] = useState<CalcuttaPresence>({ count: 0, players: [] });
|
|
39
|
+
const joinedRef = useRef(false);
|
|
40
|
+
const callbacksRef = useRef(callbacks);
|
|
41
|
+
callbacksRef.current = callbacks;
|
|
42
|
+
|
|
43
|
+
const handleMessage = useCallback((event: MessageEvent) => {
|
|
44
|
+
try {
|
|
45
|
+
const data = JSON.parse(event.data);
|
|
46
|
+
if (data.calcutta_competition_id && data.calcutta_competition_id !== calcutta_competition_id) return;
|
|
47
|
+
|
|
48
|
+
switch (data.type) {
|
|
49
|
+
case 'CALCUTTA_BID_UPDATE':
|
|
50
|
+
callbacksRef.current?.onBidUpdate?.(data);
|
|
51
|
+
break;
|
|
52
|
+
case 'CALCUTTA_ITEM_ACTIVE':
|
|
53
|
+
callbacksRef.current?.onItemActive?.(data);
|
|
54
|
+
break;
|
|
55
|
+
case 'CALCUTTA_ITEM_SOLD':
|
|
56
|
+
callbacksRef.current?.onItemSold?.(data);
|
|
57
|
+
break;
|
|
58
|
+
case 'CALCUTTA_ITEM_UNSOLD':
|
|
59
|
+
callbacksRef.current?.onItemUnsold?.(data);
|
|
60
|
+
break;
|
|
61
|
+
case 'CALCUTTA_AUCTION_PAUSED':
|
|
62
|
+
callbacksRef.current?.onAuctionPaused?.();
|
|
63
|
+
break;
|
|
64
|
+
case 'CALCUTTA_AUCTION_RESUMED':
|
|
65
|
+
callbacksRef.current?.onAuctionResumed?.(data);
|
|
66
|
+
break;
|
|
67
|
+
case 'CALCUTTA_AUCTION_CLOSED':
|
|
68
|
+
callbacksRef.current?.onAuctionClosed?.(data);
|
|
69
|
+
break;
|
|
70
|
+
case 'CALCUTTA_PRESENCE_UPDATE':
|
|
71
|
+
setPresence({ count: data.count, players: data.players });
|
|
72
|
+
break;
|
|
73
|
+
case 'V1_SOCKET_JOIN_CALCUTTA':
|
|
74
|
+
if (data.status === 'success') {
|
|
75
|
+
setConnected(true);
|
|
76
|
+
if (data.count != null) {
|
|
77
|
+
setPresence({ count: data.count, players: data.players || [] });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
} catch {
|
|
83
|
+
// Ignore non-JSON or malformed messages
|
|
84
|
+
}
|
|
85
|
+
}, [calcutta_competition_id]);
|
|
86
|
+
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
const ws = getSocket();
|
|
89
|
+
if (!ws || ws.readyState !== WebSocket.OPEN) return;
|
|
90
|
+
|
|
91
|
+
const access_token = getAccessToken();
|
|
92
|
+
const device_id = getDeviceId();
|
|
93
|
+
if (!access_token || !device_id) return;
|
|
94
|
+
|
|
95
|
+
// Add listener
|
|
96
|
+
// @ts-expect-error React Native WebSocket type lacks 'message' overload but it works at runtime
|
|
97
|
+
ws.addEventListener('message', handleMessage);
|
|
98
|
+
|
|
99
|
+
// Send join message
|
|
100
|
+
if (!joinedRef.current) {
|
|
101
|
+
ws.send(JSON.stringify({
|
|
102
|
+
type: 'JOIN_CALCUTTA_AUCTION',
|
|
103
|
+
access_token,
|
|
104
|
+
device_id,
|
|
105
|
+
calcutta_competition_id,
|
|
106
|
+
player_data,
|
|
107
|
+
}));
|
|
108
|
+
joinedRef.current = true;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return () => {
|
|
112
|
+
// @ts-expect-error React Native WebSocket type lacks 'message' overload but it works at runtime
|
|
113
|
+
ws.removeEventListener('message', handleMessage);
|
|
114
|
+
|
|
115
|
+
// Send leave message
|
|
116
|
+
if (joinedRef.current && ws.readyState === WebSocket.OPEN) {
|
|
117
|
+
ws.send(JSON.stringify({
|
|
118
|
+
type: 'LEAVE_CALCUTTA_AUCTION',
|
|
119
|
+
access_token,
|
|
120
|
+
device_id,
|
|
121
|
+
calcutta_competition_id,
|
|
122
|
+
}));
|
|
123
|
+
joinedRef.current = false;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
setConnected(false);
|
|
127
|
+
};
|
|
128
|
+
}, [calcutta_competition_id, handleMessage, getSocket, getAccessToken, getDeviceId]);
|
|
129
|
+
|
|
130
|
+
return { connected, presence };
|
|
131
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
2
|
+
import { getActiveCalcuttaTemplates } from '@bettoredge/api';
|
|
3
|
+
import type { CalcuttaTemplateProps } from '@bettoredge/types';
|
|
4
|
+
|
|
5
|
+
export interface CalcuttaTemplatesState {
|
|
6
|
+
loading: boolean;
|
|
7
|
+
templates: CalcuttaTemplateProps[];
|
|
8
|
+
error?: string;
|
|
9
|
+
refresh: () => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const useCalcuttaTemplates = (): CalcuttaTemplatesState => {
|
|
13
|
+
const [loading, setLoading] = useState(true);
|
|
14
|
+
const [templates, setTemplates] = useState<CalcuttaTemplateProps[]>([]);
|
|
15
|
+
const [error, setError] = useState<string | undefined>();
|
|
16
|
+
|
|
17
|
+
const fetchTemplates = useCallback(async () => {
|
|
18
|
+
try {
|
|
19
|
+
setLoading(true);
|
|
20
|
+
setError(undefined);
|
|
21
|
+
const resp = await getActiveCalcuttaTemplates();
|
|
22
|
+
setTemplates(resp.templates || []);
|
|
23
|
+
} catch (e: any) {
|
|
24
|
+
setError(e.message || 'Unable to load templates');
|
|
25
|
+
setTemplates([]);
|
|
26
|
+
} finally {
|
|
27
|
+
setLoading(false);
|
|
28
|
+
}
|
|
29
|
+
}, []);
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
fetchTemplates();
|
|
33
|
+
}, [fetchTemplates]);
|
|
34
|
+
|
|
35
|
+
return { loading, templates, error, refresh: fetchTemplates };
|
|
36
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @bettoredge/calcutta
|
|
3
|
+
*
|
|
4
|
+
* Calcutta auction competition components for BettorEdge applications
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Components
|
|
8
|
+
export { CalcuttaCard } from './components/CalcuttaCard';
|
|
9
|
+
export type { CalcuttaCardProps } from './components/CalcuttaCard';
|
|
10
|
+
export { CalcuttaDetail } from './components/CalcuttaDetail';
|
|
11
|
+
export type { CalcuttaDetailProps } from './components/CalcuttaDetail';
|
|
12
|
+
export { CalcuttaAuction } from './components/CalcuttaAuction';
|
|
13
|
+
export type { CalcuttaAuctionProps } from './components/CalcuttaAuction';
|
|
14
|
+
export { CalcuttaAuctionItem } from './components/CalcuttaAuctionItem';
|
|
15
|
+
export type { CalcuttaAuctionItemComponentProps } from './components/CalcuttaAuctionItem';
|
|
16
|
+
export { CalcuttaLeaderboard } from './components/CalcuttaLeaderboard';
|
|
17
|
+
export type { CalcuttaLeaderboardProps } from './components/CalcuttaLeaderboard';
|
|
18
|
+
export { CalcuttaPayoutPreview } from './components/CalcuttaPayoutPreview';
|
|
19
|
+
export type { CalcuttaPayoutPreviewProps } from './components/CalcuttaPayoutPreview';
|
|
20
|
+
export { CalcuttaBidInput } from './components/CalcuttaBidInput';
|
|
21
|
+
export type { CalcuttaBidInputProps } from './components/CalcuttaBidInput';
|
|
22
|
+
export { CalcuttaEscrow } from './components/CalcuttaEscrow';
|
|
23
|
+
export type { CalcuttaEscrowComponentProps } from './components/CalcuttaEscrow';
|
|
24
|
+
export { CalcuttaRoundResults } from './components/CalcuttaRoundResults';
|
|
25
|
+
export type { CalcuttaRoundResultsProps } from './components/CalcuttaRoundResults';
|
|
26
|
+
export { CalcuttaItemResults } from './components/CalcuttaItemResults';
|
|
27
|
+
export type { CalcuttaItemResultsProps } from './components/CalcuttaItemResults';
|
|
28
|
+
|
|
29
|
+
export { CalcuttaTemplateSelector } from './components/CalcuttaTemplateSelector';
|
|
30
|
+
export type { CalcuttaTemplateSelectorProps } from './components/CalcuttaTemplateSelector';
|
|
31
|
+
|
|
32
|
+
// Sealed Bid Components
|
|
33
|
+
export { SealedBidAuction } from './components/sealed/SealedBidAuction';
|
|
34
|
+
export { SealedBidHeader } from './components/sealed/SealedBidHeader';
|
|
35
|
+
export { SealedBidStatusBar } from './components/sealed/SealedBidStatusBar';
|
|
36
|
+
export { SealedBidTabBar } from './components/sealed/SealedBidTabBar';
|
|
37
|
+
export type { SealedBidTab } from './components/sealed/SealedBidTabBar';
|
|
38
|
+
export { SealedBidItemCard } from './components/sealed/SealedBidItemCard';
|
|
39
|
+
export { SealedBidItemsTab } from './components/sealed/SealedBidItemsTab';
|
|
40
|
+
export { SealedBidMyBidsTab } from './components/sealed/SealedBidMyBidsTab';
|
|
41
|
+
export { SealedBidPlayersTab } from './components/sealed/SealedBidPlayersTab';
|
|
42
|
+
export { SealedBidInfoTab } from './components/sealed/SealedBidInfoTab';
|
|
43
|
+
export { EscrowBottomSheet } from './components/sealed/EscrowBottomSheet';
|
|
44
|
+
export { AuctionResultsModal } from './components/sealed/AuctionResultsModal';
|
|
45
|
+
|
|
46
|
+
// Hooks
|
|
47
|
+
export { useCalcuttaTemplates } from './hooks/useCalcuttaTemplates';
|
|
48
|
+
export type { CalcuttaTemplatesState } from './hooks/useCalcuttaTemplates';
|
|
49
|
+
export { useCalcuttaCompetition } from './hooks/useCalcuttaCompetition';
|
|
50
|
+
export type { CalcuttaCompetitionState } from './hooks/useCalcuttaCompetition';
|
|
51
|
+
export { useCalcuttaAuction } from './hooks/useCalcuttaAuction';
|
|
52
|
+
export type { CalcuttaAuctionState } from './hooks/useCalcuttaAuction';
|
|
53
|
+
export { useCalcuttaBid } from './hooks/useCalcuttaBid';
|
|
54
|
+
export type { CalcuttaBidState } from './hooks/useCalcuttaBid';
|
|
55
|
+
export { useCalcuttaEscrow } from './hooks/useCalcuttaEscrow';
|
|
56
|
+
export type { CalcuttaEscrowState } from './hooks/useCalcuttaEscrow';
|
|
57
|
+
export { useCalcuttaResults } from './hooks/useCalcuttaResults';
|
|
58
|
+
export type { RoundResultSummary } from './hooks/useCalcuttaResults';
|
|
59
|
+
export { useCalcuttaSocket } from './hooks/useCalcuttaSocket';
|
|
60
|
+
export type { CalcuttaPresence, CalcuttaPresencePlayer, CalcuttaSocketCallbacks } from './hooks/useCalcuttaSocket';
|
|
61
|
+
export { useCalcuttaPlayers } from './hooks/useCalcuttaPlayers';
|
|
62
|
+
export type { CalcuttaPlayersState } from './hooks/useCalcuttaPlayers';
|
|
63
|
+
export { useCalcuttaItemImages } from './hooks/useCalcuttaItemImages';
|
|
64
|
+
export type { ItemImageMap } from './hooks/useCalcuttaItemImages';
|
|
65
|
+
|
|
66
|
+
// Helpers
|
|
67
|
+
export { formatCurrency, formatPlace, getStatusLabel, getItemStatusColor, getBidStatusColor } from './helpers/formatting';
|
|
68
|
+
export { calculatePayoutPreview, validatePayoutRules } from './helpers/payout';
|
|
69
|
+
export { validateBidAmount, validateEscrowDeposit, validateEscrowWithdraw } from './helpers/validation';
|
|
70
|
+
export { deriveLifecycleState, canBid, canManageEscrow, showResults } from './helpers/lifecycleState';
|
|
71
|
+
export type { CalcuttaLifecycleState } from './helpers/lifecycleState';
|
|
72
|
+
|
|
73
|
+
// Types
|
|
74
|
+
export type { CalcuttaStatus, AuctionType, PayoutType } from './types';
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CalcuttaCompetitionProps,
|
|
3
|
+
CalcuttaRoundProps,
|
|
4
|
+
CalcuttaAuctionItemProps,
|
|
5
|
+
CalcuttaBidProps,
|
|
6
|
+
CalcuttaParticipantProps,
|
|
7
|
+
CalcuttaEscrowProps,
|
|
8
|
+
CalcuttaPayoutRuleProps,
|
|
9
|
+
CalcuttaItemResultProps,
|
|
10
|
+
CalcuttaTemplateProps,
|
|
11
|
+
CalcuttaTemplateItemProps,
|
|
12
|
+
CalcuttaTemplateRoundProps,
|
|
13
|
+
} from '@bettoredge/types';
|
|
14
|
+
|
|
15
|
+
export type {
|
|
16
|
+
CalcuttaCompetitionProps,
|
|
17
|
+
CalcuttaRoundProps,
|
|
18
|
+
CalcuttaAuctionItemProps,
|
|
19
|
+
CalcuttaBidProps,
|
|
20
|
+
CalcuttaParticipantProps,
|
|
21
|
+
CalcuttaEscrowProps,
|
|
22
|
+
CalcuttaPayoutRuleProps,
|
|
23
|
+
CalcuttaItemResultProps,
|
|
24
|
+
CalcuttaTemplateProps,
|
|
25
|
+
CalcuttaTemplateItemProps,
|
|
26
|
+
CalcuttaTemplateRoundProps,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type CalcuttaStatus = 'pending' | 'scheduled' | 'auction_open' | 'auction_closed' | 'inprogress' | 'closed';
|
|
30
|
+
export type AuctionType = 'sealed_bid' | 'live';
|
|
31
|
+
export type PayoutType = 'round' | 'placement' | 'both';
|