feat: update TableBackground and LobbyScreen for improved UI and functionality; add promo code support in LobbyScreen
This commit is contained in:
@@ -6,7 +6,7 @@ export default function TableBackground({ children, style }) {
|
||||
return (
|
||||
<View style={[styles.wrapper, style]}>
|
||||
<LinearGradient
|
||||
colors={[colors.tableEdge, '#3e2a10']}
|
||||
colors={[colors.tableFeltDark, '#0a3a2a']}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 1 }}
|
||||
style={styles.edge}
|
||||
@@ -37,7 +37,7 @@ const styles = StyleSheet.create({
|
||||
borderTopRightRadius: 12,
|
||||
borderBottomLeftRadius: 280,
|
||||
borderBottomRightRadius: 280,
|
||||
padding: 6
|
||||
padding: 4
|
||||
},
|
||||
felt: {
|
||||
flex: 1,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { ActivityIndicator, StyleSheet, Text, TextInput, View } from 'react-native';
|
||||
import { ActivityIndicator, ScrollView, StyleSheet, Text, TextInput, View } from 'react-native';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import { useStripe } from '@stripe/stripe-react-native';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
@@ -13,6 +13,7 @@ export default function LobbyScreen({ user, token, onLogout, onSelectTable, onRe
|
||||
const [depositLoading, setDepositLoading] = useState(false);
|
||||
const [depositError, setDepositError] = useState('');
|
||||
const [customAmount, setCustomAmount] = useState('');
|
||||
const [promoCode, setPromoCode] = useState('');
|
||||
const insets = useSafeAreaInsets();
|
||||
const { initPaymentSheet, presentPaymentSheet } = useStripe();
|
||||
|
||||
@@ -35,9 +36,10 @@ export default function LobbyScreen({ user, token, onLogout, onSelectTable, onRe
|
||||
try {
|
||||
setDepositLoading(true);
|
||||
setDepositError('');
|
||||
const code = promoCode.trim().toUpperCase();
|
||||
const data = await apiFetch('/api/wallet/deposit-intent', token, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ amount })
|
||||
body: JSON.stringify(code ? { amount, promoCode: code } : { amount })
|
||||
});
|
||||
|
||||
const init = await initPaymentSheet({
|
||||
@@ -71,6 +73,7 @@ export default function LobbyScreen({ user, token, onLogout, onSelectTable, onRe
|
||||
}
|
||||
|
||||
await onRefreshUser();
|
||||
setPromoCode('');
|
||||
} catch (err) {
|
||||
setDepositError(err.message || 'Nem sikerult a feltoltes.');
|
||||
} finally {
|
||||
@@ -97,76 +100,95 @@ export default function LobbyScreen({ user, token, onLogout, onSelectTable, onRe
|
||||
}
|
||||
]}
|
||||
>
|
||||
<View style={styles.header}>
|
||||
<View>
|
||||
<Text style={styles.title}>Lobbi</Text>
|
||||
<Text style={styles.balance}>Egyenleg: {user.balance} Ft</Text>
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.scrollContent}
|
||||
showsVerticalScrollIndicator={false}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
>
|
||||
<View style={styles.header}>
|
||||
<View>
|
||||
<Text style={styles.title}>Lobbi</Text>
|
||||
<Text style={styles.balance}>Egyenleg: {user.balance} Ft</Text>
|
||||
</View>
|
||||
<CasinoButton label="Kilépés" onPress={onLogout} variant="red" />
|
||||
</View>
|
||||
<CasinoButton label="Kilépés" onPress={onLogout} variant="red" />
|
||||
</View>
|
||||
|
||||
<View style={styles.depositRow}>
|
||||
<Text style={styles.sectionTitle}>Gyors feltöltés</Text>
|
||||
<View style={styles.chips}>
|
||||
<CasinoButton label="200 Ft" onPress={() => quickDeposit(200)} variant="gold" disabled={depositLoading} />
|
||||
<CasinoButton label="500 Ft" onPress={() => quickDeposit(500)} variant="gold" disabled={depositLoading} />
|
||||
<CasinoButton label="1000 Ft" onPress={() => quickDeposit(1000)} variant="gold" disabled={depositLoading} />
|
||||
</View>
|
||||
<View style={styles.customRow}>
|
||||
<View style={styles.customInputWrap}>
|
||||
<Text style={styles.customLabel}>Egyedi összeg</Text>
|
||||
<View style={styles.customInputRow}>
|
||||
<View style={styles.depositRow}>
|
||||
<Text style={styles.sectionTitle}>Gyors feltöltés</Text>
|
||||
<View style={styles.chips}>
|
||||
<CasinoButton label="200 Ft" onPress={() => quickDeposit(200)} variant="gold" disabled={depositLoading} />
|
||||
<CasinoButton label="500 Ft" onPress={() => quickDeposit(500)} variant="gold" disabled={depositLoading} />
|
||||
<CasinoButton label="1000 Ft" onPress={() => quickDeposit(1000)} variant="gold" disabled={depositLoading} />
|
||||
</View>
|
||||
<View style={styles.customRow}>
|
||||
<View style={styles.customInputWrap}>
|
||||
<Text style={styles.customLabel}>Egyedi összeg</Text>
|
||||
<View style={styles.customInputRow}>
|
||||
<TextInput
|
||||
value={customAmount}
|
||||
onChangeText={(value) => setCustomAmount(value.replace(/[^0-9]/g, ''))}
|
||||
placeholder="pl. 250"
|
||||
placeholderTextColor="rgba(255,255,255,0.35)"
|
||||
keyboardType="number-pad"
|
||||
style={styles.customInput}
|
||||
/>
|
||||
<Text style={styles.customSuffix}>Ft</Text>
|
||||
</View>
|
||||
<Text style={styles.customHint}>Minimum 175 Ft, maximum 1000 Ft.</Text>
|
||||
</View>
|
||||
<CasinoButton
|
||||
label="Feltöltés"
|
||||
onPress={() => handleDeposit(customValue)}
|
||||
variant="gold"
|
||||
disabled={depositLoading || !customValid}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.promoRow}>
|
||||
<Text style={styles.customLabel}>Promó kód</Text>
|
||||
<View style={styles.promoInputRow}>
|
||||
<TextInput
|
||||
value={customAmount}
|
||||
onChangeText={(value) => setCustomAmount(value.replace(/[^0-9]/g, ''))}
|
||||
placeholder="pl. 250"
|
||||
value={promoCode}
|
||||
onChangeText={(value) => setPromoCode(value.replace(/\\s/g, '').toUpperCase())}
|
||||
placeholder="PL. BLACKJACK2025"
|
||||
placeholderTextColor="rgba(255,255,255,0.35)"
|
||||
keyboardType="number-pad"
|
||||
autoCapitalize="characters"
|
||||
style={styles.customInput}
|
||||
/>
|
||||
<Text style={styles.customSuffix}>Ft</Text>
|
||||
</View>
|
||||
<Text style={styles.customHint}>Minimum 175 Ft, maximum 1000 Ft.</Text>
|
||||
</View>
|
||||
<CasinoButton
|
||||
label="Feltöltés"
|
||||
onPress={() => handleDeposit(customValue)}
|
||||
variant="gold"
|
||||
disabled={depositLoading || !customValid}
|
||||
/>
|
||||
{depositError ? <Text style={styles.error}>{depositError}</Text> : null}
|
||||
</View>
|
||||
{depositError ? <Text style={styles.error}>{depositError}</Text> : null}
|
||||
</View>
|
||||
|
||||
<Text style={styles.sectionTitle}>Asztalok</Text>
|
||||
{loading ? (
|
||||
<ActivityIndicator color={colors.goldBright} />
|
||||
) : (
|
||||
<View style={styles.tableList}>
|
||||
{tables.map((table) => {
|
||||
const free = table.seatCount - table.occupied;
|
||||
return (
|
||||
<View key={table.id} style={styles.tableCard}>
|
||||
<View>
|
||||
<Text style={styles.tableName}>Asztal {table.id}</Text>
|
||||
<Text style={styles.tableMeta}>Szabad hely: {free} / {table.seatCount}</Text>
|
||||
<View style={styles.seatRow}>
|
||||
{Array.from({ length: table.seatCount }).map((_, idx) => (
|
||||
<View key={`${table.id}-${idx}`} style={idx < table.occupied ? styles.seatFilled : styles.seatEmpty} />
|
||||
))}
|
||||
<Text style={styles.sectionTitle}>Asztalok</Text>
|
||||
{loading ? (
|
||||
<ActivityIndicator color={colors.goldBright} />
|
||||
) : (
|
||||
<View style={styles.tableList}>
|
||||
{tables.map((table) => {
|
||||
const free = table.seatCount - table.occupied;
|
||||
return (
|
||||
<View key={table.id} style={styles.tableCard}>
|
||||
<View>
|
||||
<Text style={styles.tableName}>Asztal {table.id}</Text>
|
||||
<Text style={styles.tableMeta}>Szabad hely: {free} / {table.seatCount}</Text>
|
||||
<View style={styles.seatRow}>
|
||||
{Array.from({ length: table.seatCount }).map((_, idx) => (
|
||||
<View key={`${table.id}-${idx}`} style={idx < table.occupied ? styles.seatFilled : styles.seatEmpty} />
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
<CasinoButton
|
||||
label={free > 0 ? 'Beülök' : 'Tele'}
|
||||
onPress={() => free > 0 && onSelectTable(table.id)}
|
||||
variant="green"
|
||||
disabled={free === 0}
|
||||
/>
|
||||
</View>
|
||||
<CasinoButton
|
||||
label={free > 0 ? 'Beülök' : 'Tele'}
|
||||
onPress={() => free > 0 && onSelectTable(table.id)}
|
||||
variant="green"
|
||||
disabled={free === 0}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
)}
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
)}
|
||||
</ScrollView>
|
||||
</LinearGradient>
|
||||
);
|
||||
}
|
||||
@@ -176,6 +198,9 @@ const styles = StyleSheet.create({
|
||||
flex: 1,
|
||||
padding: 20
|
||||
},
|
||||
scrollContent: {
|
||||
paddingBottom: 20
|
||||
},
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
@@ -249,6 +274,19 @@ const styles = StyleSheet.create({
|
||||
fontSize: 11,
|
||||
marginTop: 6
|
||||
},
|
||||
promoRow: {
|
||||
marginTop: 12
|
||||
},
|
||||
promoInputRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'rgba(255,255,255,0.08)',
|
||||
borderRadius: 12,
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 10,
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(255,255,255,0.12)'
|
||||
},
|
||||
tableList: {
|
||||
gap: 12
|
||||
},
|
||||
|
||||
@@ -145,6 +145,9 @@ export default function TableScreen({ token, tableId, user, onLeave }) {
|
||||
<View style={styles.rotateWrap}>
|
||||
<Text style={styles.rotateTitle}>Fordítsd el a telefont</Text>
|
||||
<Text style={styles.rotateSubtitle}>A blackjack asztal fekvő nézetben működik jól.</Text>
|
||||
<View style={styles.rotateActions}>
|
||||
<CasinoButton label="Vissza" onPress={onLeave} variant="red" />
|
||||
</View>
|
||||
</View>
|
||||
</LinearGradient>
|
||||
);
|
||||
@@ -270,7 +273,7 @@ const styles = StyleSheet.create({
|
||||
tableContent: {
|
||||
flex: 1,
|
||||
justifyContent: 'space-between',
|
||||
paddingBottom: 8
|
||||
paddingBottom: 120
|
||||
},
|
||||
seatLayer: {
|
||||
flex: 1,
|
||||
@@ -278,14 +281,14 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
seatSpot: {
|
||||
position: 'absolute',
|
||||
width: 96,
|
||||
transform: [{ translateX: -48 }]
|
||||
width: 92,
|
||||
transform: [{ translateX: -46 }]
|
||||
},
|
||||
controlsOverlay: {
|
||||
position: 'absolute',
|
||||
left: 12,
|
||||
right: 12,
|
||||
bottom: 14,
|
||||
left: 18,
|
||||
right: 18,
|
||||
bottom: 12,
|
||||
gap: 10
|
||||
},
|
||||
blurPanel: {
|
||||
@@ -365,15 +368,18 @@ const styles = StyleSheet.create({
|
||||
fontSize: 14,
|
||||
marginTop: 12,
|
||||
textAlign: 'center'
|
||||
},
|
||||
rotateActions: {
|
||||
marginTop: 20
|
||||
}
|
||||
});
|
||||
|
||||
const seatPositions = {
|
||||
0: { left: '8%', top: '62%' },
|
||||
1: { left: '22%', top: '55%' },
|
||||
2: { left: '36%', top: '50%' },
|
||||
3: { left: '50%', top: '48%' },
|
||||
4: { left: '64%', top: '50%' },
|
||||
5: { left: '78%', top: '55%' },
|
||||
6: { left: '92%', top: '62%' }
|
||||
0: { left: '8%', top: '52%' },
|
||||
1: { left: '22%', top: '45%' },
|
||||
2: { left: '36%', top: '40%' },
|
||||
3: { left: '50%', top: '38%' },
|
||||
4: { left: '64%', top: '40%' },
|
||||
5: { left: '78%', top: '45%' },
|
||||
6: { left: '92%', top: '52%' }
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user