feat: enhance layout with safe area insets and improve table screen structure

This commit is contained in:
2025-12-21 00:20:20 +01:00
parent 65d61a0359
commit e5fdc0c54f
3 changed files with 84 additions and 40 deletions

View File

@@ -2,9 +2,9 @@ import { StyleSheet, View } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import { colors } from '../theme';
export default function TableBackground({ children }) {
export default function TableBackground({ children, style }) {
return (
<View style={styles.wrapper}>
<View style={[styles.wrapper, style]}>
<LinearGradient
colors={[colors.tableEdge, '#3e2a10']}
start={{ x: 0, y: 0 }}
@@ -27,7 +27,7 @@ export default function TableBackground({ children }) {
const styles = StyleSheet.create({
wrapper: {
flex: 1,
width: '100%',
padding: 12
},
edge: {

View File

@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react';
import { ActivityIndicator, 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';
import { apiFetch } from '../api';
import { colors, fonts } from '../theme';
import CasinoButton from '../components/CasinoButton';
@@ -12,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 insets = useSafeAreaInsets();
const { initPaymentSheet, presentPaymentSheet } = useStripe();
const loadTables = async () => {
@@ -80,7 +82,16 @@ export default function LobbyScreen({ user, token, onLogout, onSelectTable, onRe
const customValid = Number.isFinite(customValue) && customValue >= 50 && customValue <= 100;
return (
<LinearGradient colors={[colors.backgroundTop, colors.backgroundBottom]} style={styles.container}>
<LinearGradient
colors={[colors.backgroundTop, colors.backgroundBottom]}
style={[
styles.container,
{
paddingTop: insets.top + 12,
paddingBottom: insets.bottom + 16
}
]}
>
<View style={styles.header}>
<View>
<Text style={styles.title}>Lobbi</Text>

View File

@@ -1,6 +1,7 @@
import { useEffect, useMemo, useRef, useState } from 'react';
import { Animated, Pressable, StyleSheet, Text, View } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { WS_URL } from '../api';
import { colors, fonts } from '../theme';
import CasinoButton from '../components/CasinoButton';
@@ -17,6 +18,7 @@ export default function TableScreen({ token, tableId, user, onLeave }) {
const [turnSeconds, setTurnSeconds] = useState(null);
const wsRef = useRef(null);
const pulse = useRef(new Animated.Value(0)).current;
const insets = useSafeAreaInsets();
useEffect(() => {
const ws = new WebSocket(WS_URL);
@@ -122,8 +124,21 @@ export default function TableScreen({ token, tableId, user, onLeave }) {
});
};
const seats = table?.seats || [];
const topRow = seats.slice(0, 3);
const bottomRow = seats.slice(3);
return (
<LinearGradient colors={[colors.backgroundTop, colors.backgroundBottom]} style={styles.container}>
<LinearGradient
colors={[colors.backgroundTop, colors.backgroundBottom]}
style={[
styles.container,
{
paddingTop: insets.top + 12,
paddingBottom: insets.bottom + 16
}
]}
>
<View style={styles.topBar}>
<View>
<Text style={styles.tableTitle}>Asztal {tableId}</Text>
@@ -132,25 +147,32 @@ export default function TableScreen({ token, tableId, user, onLeave }) {
<CasinoButton label="Kilépek" onPress={onLeave} variant="red" />
</View>
<TableBackground>
<View style={styles.tableWrap}>
<TableBackground style={styles.tableSurface}>
<View style={styles.tableContent}>
<View style={styles.dealerArea}>
<DealerArea hand={table?.dealerHand || []} />
</View>
<View style={styles.seatsLayer}>
{table?.seats?.map((seat) => {
const position = seatPositions[seat.index];
if (!position) {
return null;
}
return (
<View key={seat.index} style={[styles.seatPosition, position]}>
<View style={styles.playersArea}>
<View style={styles.seatRow}>
{topRow.map((seat) => (
<View key={seat.index} style={styles.seatCell}>
<Seat seat={seat} highlight={table.currentSeatIndex === seat.index} />
</View>
);
})}
))}
</View>
<View style={styles.seatRow}>
{bottomRow.map((seat) => (
<View key={seat.index} style={styles.seatCell}>
<Seat seat={seat} highlight={table.currentSeatIndex === seat.index} />
</View>
))}
</View>
</View>
</View>
</TableBackground>
</View>
<View style={styles.controls}>
<View style={styles.betRow}>
@@ -182,20 +204,10 @@ export default function TableScreen({ token, tableId, user, onLeave }) {
);
}
const seatPositions = {
0: { bottom: 10, left: '38%' },
1: { bottom: 20, left: '8%' },
2: { bottom: 20, right: '8%' },
3: { top: '52%', left: 0 },
4: { top: '52%', right: 0 },
5: { top: '22%', left: '6%' },
6: { top: '22%', right: '6%' }
};
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 40
paddingHorizontal: 20
},
topBar: {
paddingHorizontal: 20,
@@ -214,16 +226,37 @@ const styles = StyleSheet.create({
marginTop: 4,
fontFamily: fonts.mono
},
dealerArea: {
tableWrap: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
seatsLayer: {
flex: 1,
position: 'relative'
tableSurface: {
aspectRatio: 1.35,
maxHeight: 420
},
seatPosition: {
position: 'absolute',
width: 140
dealerArea: {
alignItems: 'center',
paddingTop: 8
},
tableContent: {
flex: 1,
justifyContent: 'space-between',
paddingBottom: 8
},
playersArea: {
paddingHorizontal: 10,
paddingBottom: 8
},
seatRow: {
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 10
},
seatCell: {
flex: 1,
marginHorizontal: 4,
minWidth: 82
},
controls: {
paddingHorizontal: 20,