feat: enhance layout with safe area insets and improve table screen structure
This commit is contained in:
@@ -2,9 +2,9 @@ import { StyleSheet, View } from 'react-native';
|
|||||||
import { LinearGradient } from 'expo-linear-gradient';
|
import { LinearGradient } from 'expo-linear-gradient';
|
||||||
import { colors } from '../theme';
|
import { colors } from '../theme';
|
||||||
|
|
||||||
export default function TableBackground({ children }) {
|
export default function TableBackground({ children, style }) {
|
||||||
return (
|
return (
|
||||||
<View style={styles.wrapper}>
|
<View style={[styles.wrapper, style]}>
|
||||||
<LinearGradient
|
<LinearGradient
|
||||||
colors={[colors.tableEdge, '#3e2a10']}
|
colors={[colors.tableEdge, '#3e2a10']}
|
||||||
start={{ x: 0, y: 0 }}
|
start={{ x: 0, y: 0 }}
|
||||||
@@ -27,7 +27,7 @@ export default function TableBackground({ children }) {
|
|||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
wrapper: {
|
wrapper: {
|
||||||
flex: 1,
|
width: '100%',
|
||||||
padding: 12
|
padding: 12
|
||||||
},
|
},
|
||||||
edge: {
|
edge: {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react';
|
|||||||
import { ActivityIndicator, StyleSheet, Text, TextInput, View } from 'react-native';
|
import { ActivityIndicator, StyleSheet, Text, TextInput, View } from 'react-native';
|
||||||
import { LinearGradient } from 'expo-linear-gradient';
|
import { LinearGradient } from 'expo-linear-gradient';
|
||||||
import { useStripe } from '@stripe/stripe-react-native';
|
import { useStripe } from '@stripe/stripe-react-native';
|
||||||
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
import { apiFetch } from '../api';
|
import { apiFetch } from '../api';
|
||||||
import { colors, fonts } from '../theme';
|
import { colors, fonts } from '../theme';
|
||||||
import CasinoButton from '../components/CasinoButton';
|
import CasinoButton from '../components/CasinoButton';
|
||||||
@@ -12,6 +13,7 @@ export default function LobbyScreen({ user, token, onLogout, onSelectTable, onRe
|
|||||||
const [depositLoading, setDepositLoading] = useState(false);
|
const [depositLoading, setDepositLoading] = useState(false);
|
||||||
const [depositError, setDepositError] = useState('');
|
const [depositError, setDepositError] = useState('');
|
||||||
const [customAmount, setCustomAmount] = useState('');
|
const [customAmount, setCustomAmount] = useState('');
|
||||||
|
const insets = useSafeAreaInsets();
|
||||||
const { initPaymentSheet, presentPaymentSheet } = useStripe();
|
const { initPaymentSheet, presentPaymentSheet } = useStripe();
|
||||||
|
|
||||||
const loadTables = async () => {
|
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;
|
const customValid = Number.isFinite(customValue) && customValue >= 50 && customValue <= 100;
|
||||||
|
|
||||||
return (
|
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 style={styles.header}>
|
||||||
<View>
|
<View>
|
||||||
<Text style={styles.title}>Lobbi</Text>
|
<Text style={styles.title}>Lobbi</Text>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { Animated, Pressable, StyleSheet, Text, View } from 'react-native';
|
import { Animated, Pressable, StyleSheet, Text, View } from 'react-native';
|
||||||
import { LinearGradient } from 'expo-linear-gradient';
|
import { LinearGradient } from 'expo-linear-gradient';
|
||||||
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
import { WS_URL } from '../api';
|
import { WS_URL } from '../api';
|
||||||
import { colors, fonts } from '../theme';
|
import { colors, fonts } from '../theme';
|
||||||
import CasinoButton from '../components/CasinoButton';
|
import CasinoButton from '../components/CasinoButton';
|
||||||
@@ -17,6 +18,7 @@ export default function TableScreen({ token, tableId, user, onLeave }) {
|
|||||||
const [turnSeconds, setTurnSeconds] = useState(null);
|
const [turnSeconds, setTurnSeconds] = useState(null);
|
||||||
const wsRef = useRef(null);
|
const wsRef = useRef(null);
|
||||||
const pulse = useRef(new Animated.Value(0)).current;
|
const pulse = useRef(new Animated.Value(0)).current;
|
||||||
|
const insets = useSafeAreaInsets();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const ws = new WebSocket(WS_URL);
|
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 (
|
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 style={styles.topBar}>
|
||||||
<View>
|
<View>
|
||||||
<Text style={styles.tableTitle}>Asztal {tableId}</Text>
|
<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" />
|
<CasinoButton label="Kilépek" onPress={onLeave} variant="red" />
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<TableBackground>
|
<View style={styles.tableWrap}>
|
||||||
<View style={styles.dealerArea}>
|
<TableBackground style={styles.tableSurface}>
|
||||||
<DealerArea hand={table?.dealerHand || []} />
|
<View style={styles.tableContent}>
|
||||||
</View>
|
<View style={styles.dealerArea}>
|
||||||
|
<DealerArea hand={table?.dealerHand || []} />
|
||||||
|
</View>
|
||||||
|
|
||||||
<View style={styles.seatsLayer}>
|
<View style={styles.playersArea}>
|
||||||
{table?.seats?.map((seat) => {
|
<View style={styles.seatRow}>
|
||||||
const position = seatPositions[seat.index];
|
{topRow.map((seat) => (
|
||||||
if (!position) {
|
<View key={seat.index} style={styles.seatCell}>
|
||||||
return null;
|
<Seat seat={seat} highlight={table.currentSeatIndex === seat.index} />
|
||||||
}
|
</View>
|
||||||
return (
|
))}
|
||||||
<View key={seat.index} style={[styles.seatPosition, position]}>
|
|
||||||
<Seat seat={seat} highlight={table.currentSeatIndex === seat.index} />
|
|
||||||
</View>
|
</View>
|
||||||
);
|
<View style={styles.seatRow}>
|
||||||
})}
|
{bottomRow.map((seat) => (
|
||||||
</View>
|
<View key={seat.index} style={styles.seatCell}>
|
||||||
</TableBackground>
|
<Seat seat={seat} highlight={table.currentSeatIndex === seat.index} />
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</TableBackground>
|
||||||
|
</View>
|
||||||
|
|
||||||
<View style={styles.controls}>
|
<View style={styles.controls}>
|
||||||
<View style={styles.betRow}>
|
<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({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingTop: 40
|
paddingHorizontal: 20
|
||||||
},
|
},
|
||||||
topBar: {
|
topBar: {
|
||||||
paddingHorizontal: 20,
|
paddingHorizontal: 20,
|
||||||
@@ -214,16 +226,37 @@ const styles = StyleSheet.create({
|
|||||||
marginTop: 4,
|
marginTop: 4,
|
||||||
fontFamily: fonts.mono
|
fontFamily: fonts.mono
|
||||||
},
|
},
|
||||||
dealerArea: {
|
tableWrap: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'center',
|
||||||
alignItems: 'center'
|
alignItems: 'center'
|
||||||
},
|
},
|
||||||
seatsLayer: {
|
tableSurface: {
|
||||||
flex: 1,
|
aspectRatio: 1.35,
|
||||||
position: 'relative'
|
maxHeight: 420
|
||||||
},
|
},
|
||||||
seatPosition: {
|
dealerArea: {
|
||||||
position: 'absolute',
|
alignItems: 'center',
|
||||||
width: 140
|
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: {
|
controls: {
|
||||||
paddingHorizontal: 20,
|
paddingHorizontal: 20,
|
||||||
|
|||||||
Reference in New Issue
Block a user