@bettoredge/calcutta 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useState, useRef, useCallback, useMemo } from 'react';
|
|
2
|
-
import { StyleSheet, TouchableOpacity, ActivityIndicator, FlatList, ScrollView, Image, TextInput } from 'react-native';
|
|
2
|
+
import { StyleSheet, TouchableOpacity, ActivityIndicator, FlatList, ScrollView, Image, TextInput, Platform } from 'react-native';
|
|
3
3
|
import { View, Text, useTheme } from '@bettoredge/styles';
|
|
4
4
|
import { Ionicons } from '@expo/vector-icons';
|
|
5
5
|
import type { CalcuttaEscrowProps } from '@bettoredge/types';
|
|
@@ -380,8 +380,8 @@ const SweepstakesWaiting: React.FC<CalcuttaAuctionProps & { competition: any }>
|
|
|
380
380
|
: '#10B981';
|
|
381
381
|
|
|
382
382
|
return (
|
|
383
|
-
<View variant="
|
|
384
|
-
<ScrollView style={{ flex: 1 }} contentContainerStyle={{ gap: 16, paddingBottom: 40 }}>
|
|
383
|
+
<View variant="base" style={styles.container}>
|
|
384
|
+
<ScrollView style={{ flex: 1 }} contentContainerStyle={{ gap: 16, paddingBottom: Platform.OS === 'web' ? 300 : 40 }} keyboardShouldPersistTaps="handled">
|
|
385
385
|
{/* Hero with embedded title */}
|
|
386
386
|
<View style={{ position: 'relative' }}>
|
|
387
387
|
{competition.image?.url ? (
|
|
@@ -575,6 +575,11 @@ const SweepstakesWaiting: React.FC<CalcuttaAuctionProps & { competition: any }>
|
|
|
575
575
|
onChangeText={setSearchQuery}
|
|
576
576
|
autoCapitalize="none"
|
|
577
577
|
autoCorrect={false}
|
|
578
|
+
onFocus={(e: any) => {
|
|
579
|
+
if (Platform.OS === 'web' && e?.target?.scrollIntoView) {
|
|
580
|
+
setTimeout(() => e.target.scrollIntoView({ behavior: 'smooth', block: 'center' }), 300);
|
|
581
|
+
}
|
|
582
|
+
}}
|
|
578
583
|
/>
|
|
579
584
|
{filteredItems.map((item) => {
|
|
580
585
|
const isMyItem = item.winning_player_id == player_id;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import React, { useState, useMemo } from 'react';
|
|
2
|
-
import { StyleSheet, TouchableOpacity, ActivityIndicator, ScrollView, Image, FlatList } from 'react-native';
|
|
1
|
+
import React, { useState, useMemo, useCallback } from 'react';
|
|
2
|
+
import { StyleSheet, TouchableOpacity, ActivityIndicator, ScrollView, Image, FlatList, TextInput, Platform } from 'react-native';
|
|
3
3
|
import { View, Text, useTheme } from '@bettoredge/styles';
|
|
4
4
|
import { Ionicons } from '@expo/vector-icons';
|
|
5
5
|
import type { CalcuttaParticipantProps } from '@bettoredge/types';
|
|
6
6
|
import { useCalcuttaCompetition } from '../hooks/useCalcuttaCompetition';
|
|
7
7
|
import { useCalcuttaPlayers } from '../hooks/useCalcuttaPlayers';
|
|
8
|
+
import { useCalcuttaItemImages } from '../hooks/useCalcuttaItemImages';
|
|
8
9
|
import { formatCurrency, getStatusLabel, resolveItemImageUrl } from '../helpers/formatting';
|
|
9
10
|
import { startSweepstakesCompetition } from '@bettoredge/api';
|
|
10
11
|
|
|
@@ -51,10 +52,26 @@ export const CalcuttaDetail: React.FC<CalcuttaDetailProps> = ({
|
|
|
51
52
|
|
|
52
53
|
const participantIds = useMemo(() => participants.map(p => p.player_id), [participants]);
|
|
53
54
|
const { players: enrichedPlayers } = useCalcuttaPlayers(participantIds);
|
|
55
|
+
const { images: itemImages } = useCalcuttaItemImages(items);
|
|
54
56
|
|
|
55
57
|
const [joining, setJoining] = useState(false);
|
|
56
58
|
const [leaving, setLeaving] = useState(false);
|
|
57
59
|
const [startingComp, setStartingComp] = useState(false);
|
|
60
|
+
const [itemSearch, setItemSearch] = useState('');
|
|
61
|
+
|
|
62
|
+
const filteredItems = useMemo(() => {
|
|
63
|
+
if (competition?.auction_type !== 'sweepstakes' || !itemSearch.trim()) return items;
|
|
64
|
+
const q = itemSearch.toLowerCase().trim();
|
|
65
|
+
return items.filter(item => {
|
|
66
|
+
if (item.item_name.toLowerCase().includes(q)) return true;
|
|
67
|
+
if (item.winning_player_id) {
|
|
68
|
+
const owner = enrichedPlayers[item.winning_player_id];
|
|
69
|
+
const ownerName = (owner?.username || owner?.show_name || '').toLowerCase();
|
|
70
|
+
if (ownerName.includes(q)) return true;
|
|
71
|
+
}
|
|
72
|
+
return false;
|
|
73
|
+
});
|
|
74
|
+
}, [items, itemSearch, enrichedPlayers, competition?.auction_type]);
|
|
58
75
|
|
|
59
76
|
if (loading && !competition) {
|
|
60
77
|
return (
|
|
@@ -362,6 +379,63 @@ export const CalcuttaDetail: React.FC<CalcuttaDetailProps> = ({
|
|
|
362
379
|
|
|
363
380
|
case 'items':
|
|
364
381
|
if (items.length === 0) return null;
|
|
382
|
+
if (isSweepstakes) {
|
|
383
|
+
return (
|
|
384
|
+
<View variant="transparent" style={{ paddingHorizontal: 16, paddingBottom: 8 }}>
|
|
385
|
+
<TextInput
|
|
386
|
+
style={{
|
|
387
|
+
height: 36,
|
|
388
|
+
borderRadius: 8,
|
|
389
|
+
borderWidth: 1,
|
|
390
|
+
borderColor: theme.colors.border.subtle,
|
|
391
|
+
backgroundColor: theme.colors.surface.input,
|
|
392
|
+
color: theme.colors.text.primary,
|
|
393
|
+
paddingHorizontal: 12,
|
|
394
|
+
fontSize: 14,
|
|
395
|
+
marginBottom: 8,
|
|
396
|
+
}}
|
|
397
|
+
placeholder="Search by team or owner..."
|
|
398
|
+
placeholderTextColor={theme.colors.text.tertiary}
|
|
399
|
+
value={itemSearch}
|
|
400
|
+
onChangeText={setItemSearch}
|
|
401
|
+
autoCapitalize="none"
|
|
402
|
+
autoCorrect={false}
|
|
403
|
+
onFocus={(e: any) => {
|
|
404
|
+
if (Platform.OS === 'web' && e?.target?.scrollIntoView) {
|
|
405
|
+
setTimeout(() => e.target.scrollIntoView({ behavior: 'smooth', block: 'center' }), 300);
|
|
406
|
+
}
|
|
407
|
+
}}
|
|
408
|
+
/>
|
|
409
|
+
{filteredItems.map(item => {
|
|
410
|
+
const imgUrl = resolveItemImageUrl(item.item_image) || itemImages[item.item_id]?.url;
|
|
411
|
+
const owner = item.winning_player_id ? enrichedPlayers[item.winning_player_id] : undefined;
|
|
412
|
+
const ownerName = owner?.username || owner?.show_name;
|
|
413
|
+
const isMe = item.winning_player_id == player_id;
|
|
414
|
+
return (
|
|
415
|
+
<View key={item.calcutta_auction_item_id} variant="transparent" style={{ flexDirection: 'row', alignItems: 'center', paddingVertical: 8, borderBottomWidth: 1, borderColor: theme.colors.border.subtle }}>
|
|
416
|
+
{imgUrl ? (
|
|
417
|
+
<Image source={{ uri: imgUrl }} style={{ width: 28, height: 28, borderRadius: 6 }} resizeMode="cover" />
|
|
418
|
+
) : (
|
|
419
|
+
<View variant="transparent" style={{ width: 28, height: 28, borderRadius: 6, backgroundColor: theme.colors.surface.elevated, alignItems: 'center', justifyContent: 'center' }}>
|
|
420
|
+
<Ionicons name="trophy-outline" size={14} color={theme.colors.text.tertiary} />
|
|
421
|
+
</View>
|
|
422
|
+
)}
|
|
423
|
+
<View variant="transparent" style={{ marginLeft: 8, flex: 1 }}>
|
|
424
|
+
<Text variant="body">{item.item_name}</Text>
|
|
425
|
+
{ownerName ? (
|
|
426
|
+
<Text variant="caption" color="tertiary">{isMe ? 'You' : ownerName}</Text>
|
|
427
|
+
) : (
|
|
428
|
+
<Text variant="caption" color="tertiary">Available</Text>
|
|
429
|
+
)}
|
|
430
|
+
</View>
|
|
431
|
+
{item.seed != null && <Text variant="caption" color="tertiary">#{item.seed}</Text>}
|
|
432
|
+
{isMe && <Text variant="caption" bold style={{ color: theme.colors.primary.default, marginLeft: 8 }}>YOU</Text>}
|
|
433
|
+
</View>
|
|
434
|
+
);
|
|
435
|
+
})}
|
|
436
|
+
</View>
|
|
437
|
+
);
|
|
438
|
+
}
|
|
365
439
|
return (
|
|
366
440
|
<View variant="transparent" style={{ paddingHorizontal: 16 }}>
|
|
367
441
|
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
|
|
@@ -433,20 +507,25 @@ export const CalcuttaDetail: React.FC<CalcuttaDetailProps> = ({
|
|
|
433
507
|
};
|
|
434
508
|
|
|
435
509
|
return (
|
|
436
|
-
<View variant="
|
|
437
|
-
{/* Header bar */}
|
|
438
|
-
|
|
439
|
-
<
|
|
440
|
-
<
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
510
|
+
<View variant="base" style={styles.container}>
|
|
511
|
+
{/* Header bar — hidden for sweepstakes (title is in the hero) */}
|
|
512
|
+
{!isSweepstakes && (
|
|
513
|
+
<View variant="transparent" style={[styles.headerBar, { borderColor: theme.colors.border.subtle }]}>
|
|
514
|
+
<TouchableOpacity onPress={onClose} hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}>
|
|
515
|
+
<Ionicons name="arrow-back" size={24} color={theme.colors.text.primary} />
|
|
516
|
+
</TouchableOpacity>
|
|
517
|
+
<Text variant="body" bold style={{ flex: 1, marginLeft: 12 }} numberOfLines={1}>{competition.competition_name}</Text>
|
|
518
|
+
</View>
|
|
519
|
+
)}
|
|
444
520
|
|
|
445
521
|
<FlatList
|
|
446
522
|
data={sections}
|
|
447
523
|
keyExtractor={(item) => item.key}
|
|
448
524
|
renderItem={renderSection}
|
|
449
525
|
showsVerticalScrollIndicator={false}
|
|
526
|
+
style={{ backgroundColor: theme.colors.surface.base }}
|
|
527
|
+
contentContainerStyle={{ paddingBottom: Platform.OS === 'web' ? 300 : 40 }}
|
|
528
|
+
keyboardShouldPersistTaps="handled"
|
|
450
529
|
/>
|
|
451
530
|
</View>
|
|
452
531
|
);
|