Page End + UI adjustments + cleaning

This commit is contained in:
Sebastien Riviere
2026-02-21 21:45:27 +01:00
parent 28e81894ce
commit 405b2934c8
18 changed files with 395 additions and 272 deletions

View File

@@ -1,8 +1,76 @@
// React
import { View, Text, StyleSheet } from 'react-native';
import { useTranslation } from 'react-i18next';
// Expo
import { Slot } from 'expo-router';
// Contexts
import { useAuth } from '@/contexts/authContext';
import { useTeam } from '@/contexts/teamContext';
// Components
import { IconButton } from '@/components/common/IconButton';
// Constants
import { COLORS } from '@/constants';
const GameLayout = () => {
return <Slot/>;
const { t, i18n } = useTranslation();
const { logout } = useAuth();
const { teamInfos } = useTeam();
const { name } = teamInfos;
const toggleLanguage = () => {
i18n.changeLanguage(i18n.language === 'fr' ? 'en' : 'fr');
};
const formatText = (text, limit) => {
if (text == null) return t("common.no_value");
if (text.length > limit) {
return text.substring(0, limit) + "...";
} else {
return text;
}
};
formatText("les minions du bds qui gagne");
return (
<View style={styles.globalContainer}>
<View style={styles.headerContainer}>
<IconButton style={styles.logoutIcon} source={require('@/assets/images/logout.png')} onPress={logout} />
<Text style={styles.name} numberOfLines={1} adjustsFontSizeToFit>{formatText(name, 22)}</Text>
<IconButton style={styles.traductionIcon} source={require('@/assets/images/language.png')} onPress={toggleLanguage} />
</View>
<Slot/>
</View>
);
};
export default GameLayout;
const styles = StyleSheet.create({
globalContainer: {
flex: 1
},
headerContainer: {
backgroundColor: COLORS.background,
flexDirection: "row",
alignItems: "center",
padding: 10,
gap: 10,
elevation: 10,
},
name: {
fontSize: 30,
fontWeight: "bold",
textAlign: "center",
flex: 1
},
logoutIcon: {
width: 50,
height: 50
},
traductionIcon: {
width: 60,
height: 60
}
});

View File

@@ -1,31 +1,117 @@
// React
import { View, Text, StyleSheet } from 'react-native';
import { Text, StyleSheet, ScrollView } from 'react-native';
import { useTranslation } from 'react-i18next';
// Components
import { Header } from '@/components/game/Header';
import { TeamStats } from '@/components/game/TeamStats';
import { Show } from '@/components/common/Show';
// Hook
import { useUserState } from '@/hooks/useUserState';
// Constants
import { COLORS } from '@/constants';
import { USER_STATE } from '@/constants';
/*
const Leaderboard = ({ teams }) => {
return (
<View style={styles.leaderboardContainer}>
{teams.map((item, index) => {
const isSelected = index+1 == 5;
return (
<View key={`leaderboard-${item}-${index+1}`} style={[styles.item, isSelected && styles.selectedTeam]}>
<Text style={styles.rank}>{index + 1}</Text>
<Text style={[styles.teamName, isSelected && styles.selectedTeam]}>
{item}
</Text>
</View>
);
})}
</View>
);
};
<View style={styles.section}>
<Text style={styles.sectionTitle}>Classement</Text>
<Leaderboard teams={teamsTest}/>
</View>
<View style={styles.section}>
<Text style={styles.sectionTitle}>Parcours</Text>
<View style={styles.mapView}>
<MapView style={styles.map} mapType={"standard"} initialRegion={INITIAL_REGIONS.TELECOM_PARIS} toolbarEnabled={false}>
</MapView>
</View>
</View>
mapView: {
height: 300,
borderRadius: 20,
overflow: "hidden"
},
map: {
flex: 1
},
// Classement
leaderboardContainer: {
gap: 8,
},
item: {
flexDirection: 'row',
alignItems: 'center',
paddingVertical: 10,
paddingHorizontal: 20,
backgroundColor: '#f9f9f9',
borderRadius: 8,
borderWidth: 2,
gap: 20
},
selectedTeam: {
backgroundColor: 'rgb(126, 182, 199)',
},
rank: {
fontSize: 18,
fontWeight: 'bold',
color: '#000000',
},
teamName: {
fontSize: 16,
color: '#000000',
},
*/
const End = () => {
const { t } = useTranslation();
const userState = useUserState();
return (
<View style={styles.globalContainer}>
<View style={styles.topContainer}>
<Header/>
<Text>Fin de la partie !</Text>
</View>
</View>
<ScrollView style={styles.outerScrollview} contentContainerStyle={styles.innerScrollview} showsVerticalScrollIndicator={false}>
<Show when={userState == USER_STATE.CAPTURED}>
<Text style={styles.title}>{t("end.title_captured")}</Text>
</Show>
<Show when={userState == USER_STATE.FINISHED}>
<Text style={styles.title}>{t("end.title_win")}</Text>
</Show>
<Text style={styles.subtitle}>{t("end.paragraph")}</Text>
<TeamStats/>
</ScrollView>
);
};
export default End;
const styles = StyleSheet.create({
globalContainer: {
backgroundColor: COLORS.background,
flex: 1,
outerScrollview: {
flex: 1
},
topContainer: {
width: '100%',
alignItems: 'center',
padding: 15,
innerScrollview: {
padding: 20,
gap: 20,
},
title: {
fontSize: 24,
fontWeight: "bold",
textAlign: "center"
},
subtitle: {
fontSize: 15,
}
});

View File

@@ -1,6 +1,6 @@
// React
import { useState } from 'react';
import { View, Alert, StyleSheet } from 'react-native';
import { Text, View, Alert, StyleSheet } from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import { useTranslation } from 'react-i18next';
// Components
@@ -9,7 +9,6 @@ import { TimerMMSS } from '@/components/common/Timer';
import { Show } from '@/components/common/Show';
import { PositionMarker } from '@/components/common/Layers';
import { IconButton } from '@/components/common/IconButton';
import { Header } from '@/components/game/Header';
import { TargetInfoDrawer } from '@/components/game/TargetInfoDrawer';
import { Toasts } from '@/components/game/Toasts';
import { GameZone, StartZone } from '@/components/game/MapLayers';
@@ -20,7 +19,7 @@ import { useUserState } from '@/hooks/useUserState';
// Services
import { emitSendPosition } from '@/services/socket/emitters';
// Constants
import { COLORS, USER_STATE } from '@/constants';
import { USER_STATE } from '@/constants';
const Play = () => {
const { t } = useTranslation();
@@ -31,16 +30,16 @@ const Play = () => {
return (
<View style={styles.globalContainer}>
<View style={styles.topContainer}>
<Header/>
<Show when={userState == USER_STATE.PLAYING}>
<View style={styles.infoContainer}>
<TimerMMSS style={{width: "50%"}} title={t("play.info.zone_reduction_label")} date={nextZoneDate} />
<TimerMMSS style={{width: "50%"}} title={t("play.info.send_position_label")} date={locationSendDeadline} />
</View>
</Show>
</View>
<View style={styles.bottomContainer} onLayout={(event) => setBottomContainerHeight(event.nativeEvent.layout.height)}>
<Show when={userState == USER_STATE.PLACEMENT}>
<Text style={styles.placementTitle}>{t("play.info.placement_title")}</Text>
</Show>
<Show when={userState == USER_STATE.PLAYING}>
<View style={styles.timerContainer}>
<TimerMMSS style={styles.timer} title={t("play.info.zone_reduction_label")} date={nextZoneDate} />
<TimerMMSS style={styles.timer} title={t("play.info.send_position_label")} date={locationSendDeadline} />
</View>
</Show>
<View style={styles.mapContainer} onLayout={(event) => setBottomContainerHeight(event.nativeEvent.layout.height)}>
<Map>
<Show when={userState == USER_STATE.PLACEMENT}>
<StartZone/>
@@ -70,22 +69,23 @@ export default Play;
const styles = StyleSheet.create({
globalContainer: {
backgroundColor: COLORS.background,
flex: 1,
},
topContainer: {
width: '100%',
alignItems: 'center',
placementTitle: {
textAlign: "center",
padding: 15,
fontSize: 20,
fontWeight: "bold"
},
infoContainer: {
width: '100%',
timerContainer: {
padding: 15,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
marginTop: 15
},
bottomContainer: {
timer: {
width: "50%",
},
mapContainer: {
flex: 1,
borderTopLeftRadius: 30,
borderTopRightRadius: 30,

View File

@@ -1,75 +1,60 @@
// React
import { View, Text, StyleSheet, Image } from 'react-native';
import { ScrollView, View, Text, StyleSheet, Image } from 'react-native';
import { useTranslation } from 'react-i18next';
// Components
import { Header } from '@/components/game/Header';
// Constants
import { COLORS } from '@/constants';
const Section = ({ source, text }) => {
return (
<View style={styles.section}>
<Image style={styles.image} source={source} />
<Text style={styles.description}>{text}</Text>
</View>
);
};
const Wait = () => {
const { t } = useTranslation();
return (
<View style={styles.globalContainer}>
<Header/>
<View style={styles.rulesContainer}>
<Text style={styles.title}>{t("wait.title")}</Text>
<View style={styles.section}>
<Image style={styles.image} source={require("@/assets/images/flag.png")} />
<Text style={styles.description}>{t("wait.placement_rule")}</Text>
</View>
<View style={styles.section}>
<Text style={styles.description}>{t("wait.capture_rule")}</Text>
<Image style={styles.image} source={require("@/assets/images/target/black.png")} />
</View>
<View style={styles.section}>
<Image style={styles.image} source={require("@/assets/images/running.png")} />
<Text style={styles.description}>{t("wait.zone_rule")}</Text>
</View>
<View style={styles.section}>
<Text style={styles.description}>{t("wait.team_rule")}</Text>
<Image style={styles.image} source={require("@/assets/images/team.png")} />
</View>
</View>
</View>
<ScrollView style={styles.outerScrollview} contentContainerStyle={styles.innerScrollview} showsVerticalScrollIndicator={false}>
<Text style={styles.title}>{t("wait.title")}</Text>
<Section source={require("@/assets/images/flag.png")} text={t("wait.placement_rule")} />
<Section source={require("@/assets/images/target/black.png")} text={t("wait.capture_rule")} />
<Section source={require("@/assets/images/running.png")} text={t("wait.zone_rule")} />
<Section source={require("@/assets/images/team.png")} text={t("wait.team_rule")} />
</ScrollView>
);
};
export default Wait;
const styles = StyleSheet.create({
globalContainer: {
backgroundColor: COLORS.background,
flex: 1,
padding: 20,
outerScrollview: {
flex: 1
},
rulesContainer: {
flex: 1,
innerScrollview: {
flexGrow: 1,
justifyContent: "space-between",
alignItems: 'center',
padding: 30,
gap: 30
},
title: {
backgroundColor: "white",
textAlign: 'center',
fontSize: 30,
fontWeight: "bold",
borderWidth: 2,
borderRadius: 10,
padding: 10,
fontSize: 18,
fontWeight: "bold"
},
section: {
width: '100%',
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
gap: 20,
gap: 30,
},
image: {
width: 100,
height: 100,
width: 70,
height: 70,
},
description: {
flex: 1,
fontSize: 15,
}
});