mirror of
https://git.rezel.net/LudoTech/traque.git
synced 2026-04-11 00:30:19 +02:00
Page End + UI adjustments + cleaning
This commit is contained in:
@@ -6,18 +6,18 @@ import LinearGradient from 'react-native-linear-gradient';
|
||||
// Constants
|
||||
import { COLORS } from '@/constants';
|
||||
|
||||
export const Drawer = ({ height, children }) => {
|
||||
export const Drawer = ({ contentContainerStyle = {}, height, children }) => {
|
||||
const [collapsibleState, setCollapsibleState] = useState(true);
|
||||
|
||||
return (
|
||||
<View style={styles.outerDrawerContainer}>
|
||||
<LinearGradient colors={['rgba(0,0,0,0)', 'rgba(0,0,0,0.5)']} style={styles.gradient}/>
|
||||
<View style={styles.innerDrawerContainer}>
|
||||
<TouchableHighlight style={styles.collapsibleButton} underlayColor="#d9d9d9" onPress={() => setCollapsibleState(!collapsibleState)}>
|
||||
<TouchableHighlight style={styles.collapsibleButton} underlayColor="#e9e9e9" onPress={() => setCollapsibleState(!collapsibleState)}>
|
||||
<Image source={require('@/assets/images/arrow.png')} style={[styles.arrow, {transform: [{ scaleY: collapsibleState ? 1 : -1 }]}]} resizeMode="contain"/>
|
||||
</TouchableHighlight>
|
||||
<Collapsible style={[styles.collapsibleWindow, {height: height - 44}]} collapsed={collapsibleState}>
|
||||
<ScrollView contentContainerStyle={styles.collapsibleContent}>
|
||||
<ScrollView style={styles.outerScrollContainer} contentContainerStyle={contentContainerStyle} showsVerticalScrollIndicator={false}>
|
||||
{children}
|
||||
</ScrollView>
|
||||
</Collapsible>
|
||||
@@ -61,7 +61,7 @@ const styles = StyleSheet.create({
|
||||
justifyContent: 'center',
|
||||
backgroundColor: COLORS.background,
|
||||
},
|
||||
collapsibleContent: {
|
||||
paddingHorizontal: 15,
|
||||
outerScrollContainer: {
|
||||
flex: 1
|
||||
}
|
||||
});
|
||||
|
||||
@@ -16,7 +16,6 @@ export const CustomTextInput = ({ style = {}, value, inputMode, placeholder, onC
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
input: {
|
||||
width: "100%",
|
||||
padding: 15,
|
||||
borderColor: '#777',
|
||||
borderRadius: 12,
|
||||
|
||||
@@ -25,7 +25,7 @@ export const Map = ({ children }) => {
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<MapView ref={mapRef} style={styles.mapView} initialRegion={INITIAL_REGIONS.PARIS} mapType={"standard"} onTouchMove={() => setCenterMap(false)} toolbarEnabled={false}>
|
||||
<MapView ref={mapRef} style={styles.mapView} initialRegion={INITIAL_REGIONS.TELECOM_PARIS} mapType={"standard"} onTouchMove={() => setCenterMap(false)} toolbarEnabled={false}>
|
||||
{children}
|
||||
<PositionMarker position={location} />
|
||||
</MapView>
|
||||
@@ -50,8 +50,8 @@ const styles = StyleSheet.create({
|
||||
width: 40,
|
||||
height: 40,
|
||||
borderRadius: 20,
|
||||
backgroundColor: 'white',
|
||||
borderWidth: 2,
|
||||
borderColor: 'black'
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.75)',
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(64, 64, 64, 0.50)'
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
// React
|
||||
import { View, Text, StyleSheet } from 'react-native';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
// Contexts
|
||||
import { useAuth } from '@/contexts/authContext';
|
||||
import { useTeam } from '@/contexts/teamContext';
|
||||
// Components
|
||||
import { IconButton } from '@/components/common/IconButton';
|
||||
|
||||
export const Header = () => {
|
||||
const { t } = useTranslation();
|
||||
const { logout } = useAuth();
|
||||
const { teamInfos } = useTeam();
|
||||
const { name } = teamInfos;
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<IconButton source={require('@/assets/images/logout.png')} onPress={logout} />
|
||||
<View style={styles.nameContainer}>
|
||||
<Text style={styles.name}>{name ?? t("common.no_value")}</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
width: '100%',
|
||||
},
|
||||
nameContainer: {
|
||||
width: '100%',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginBottom: 20
|
||||
},
|
||||
name: {
|
||||
fontSize: 36,
|
||||
fontWeight: "bold"
|
||||
}
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
// React
|
||||
import { useState } from 'react';
|
||||
import { Keyboard, View, Text, Image, StyleSheet, TouchableOpacity, Alert } from 'react-native';
|
||||
import { Keyboard, View, Text, StyleSheet, Alert } from 'react-native';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
// Components
|
||||
import { ExpandableImage } from '@/components/common/Image';
|
||||
@@ -14,6 +14,7 @@ import { useTeam } from '@/contexts/teamContext';
|
||||
// Services
|
||||
import { emitCapture } from '@/services/socket/emitters';
|
||||
import { enemyImage } from '@/services/api/image';
|
||||
import { IconButton } from '../common/IconButton';
|
||||
|
||||
export const TargetInfoDrawer = ({ height }) => {
|
||||
const { t } = useTranslation();
|
||||
@@ -47,24 +48,16 @@ export const TargetInfoDrawer = ({ height }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Drawer height={height}>
|
||||
<Text style={{fontSize: 22, fontWeight: "bold", textAlign: "center"}}>
|
||||
{t("play.drawer.capture_code", {name: name ?? t("common.no_value"), code: String(captureCode).padStart(4,"0")})}
|
||||
</Text>
|
||||
<Drawer contentContainerStyle={styles.drawer} height={height}>
|
||||
<Text style={styles.teamCode}>{t("play.drawer.capture_code", {name: name ?? t("common.no_value"), code: String(captureCode).padStart(4,"0")})}</Text>
|
||||
<Show when={!hasHandicap}>
|
||||
<View style={styles.imageContainer}>
|
||||
<Text style={{fontSize: 15, margin: 5}}>{t("play.drawer.target_name", {name: enemyName ?? t("common.no_value")})}</Text>
|
||||
<View style={styles.targetContainer}>
|
||||
<Text style={styles.targetName}>{t("play.drawer.target_name", {name: enemyName ?? t("common.no_value")})}</Text>
|
||||
<ExpandableImage source={enemyImage(teamId)}/>
|
||||
</View>
|
||||
<View style={styles.actionsContainer}>
|
||||
<View style={styles.actionsLeftContainer}>
|
||||
<CustomTextInput value={enemyCaptureCode} inputMode="numeric" placeholder={t("play.drawer.target_code_input")} onChangeText={setEnemyCaptureCode}/>
|
||||
</View>
|
||||
<View style={styles.actionsRightContainer}>
|
||||
<TouchableOpacity style={styles.button} onPress={handleCapture}>
|
||||
<Image source={require("@/assets/images/target/white.png")} style={{width: 40, height: 40}} resizeMode="contain"/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={styles.captureContainer}>
|
||||
<CustomTextInput style={styles.captureInput} value={enemyCaptureCode} inputMode="numeric" placeholder={t("play.drawer.target_code_input")} onChangeText={setEnemyCaptureCode}/>
|
||||
<IconButton style={styles.captureButton} source={require("@/assets/images/target/white.png")} onPress={handleCapture} />
|
||||
</View>
|
||||
</Show>
|
||||
<TeamStats/>
|
||||
@@ -73,34 +66,42 @@ export const TargetInfoDrawer = ({ height }) => {
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
imageContainer: {
|
||||
drawer: {
|
||||
flexGrow: 1,
|
||||
justifyContent: "space-between",
|
||||
padding: 15,
|
||||
gap: 15,
|
||||
},
|
||||
teamCode: {
|
||||
fontSize: 22,
|
||||
fontWeight: "bold",
|
||||
textAlign: "center"
|
||||
},
|
||||
targetContainer: {
|
||||
width: "100%",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
marginTop: 15
|
||||
justifyContent: "center"
|
||||
},
|
||||
actionsContainer: {
|
||||
targetName: {
|
||||
fontSize: 15,
|
||||
},
|
||||
captureContainer: {
|
||||
flexDirection: "row",
|
||||
width: "100%",
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
marginTop: 15
|
||||
gap: 15
|
||||
},
|
||||
actionsLeftContainer: {
|
||||
flexGrow: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginRight: 15
|
||||
},
|
||||
actionsRightContainer: {
|
||||
width: 100,
|
||||
captureInput: {
|
||||
flex: 3,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
},
|
||||
button: {
|
||||
captureButton: {
|
||||
flex: 1,
|
||||
height: 70,
|
||||
borderRadius: 12,
|
||||
width: '100%',
|
||||
height: 75,
|
||||
padding: 10,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: '#444'
|
||||
|
||||
@@ -37,41 +37,45 @@ export const TeamStats = () => {
|
||||
|
||||
return (
|
||||
<View style={styles.statsContainer}>
|
||||
<Text style={styles.title}>{t("play.drawer.stats_section_title")}</Text>
|
||||
<View style={styles.row}>
|
||||
<Stat source={require('@/assets/images/distance.png')} description={t("play.drawer.stat_distance_label")}>{Math.floor(distance / 100) / 10}km</Stat>
|
||||
<Stat source={require('@/assets/images/distance.png')} description={t("play.drawer.stat_distance_label")}>{Math.floor((distance ?? 0) / 100) / 10}km</Stat>
|
||||
<Stat source={require('@/assets/images/time.png')} description={t("play.drawer.stat_time_label")}>{secondsToHHMMSS((finishDate ? Math.floor((finishDate - startDate) / 1000) : timeSinceGameStart))}</Stat>
|
||||
<Stat source={require('@/assets/images/running.png')} description={t("play.drawer.stat_speed_label")}>{avgSpeed}km/h</Stat>
|
||||
</View>
|
||||
<View style={styles.row}>
|
||||
<Stat source={require('@/assets/images/target/black.png')} description={t("play.drawer.stat_capture_label")}>{nCaptures}</Stat>
|
||||
<Stat source={require('@/assets/images/update_position.png')} description={t("play.drawer.stat_reveal_label")}>{nSentLocation}</Stat>
|
||||
<Stat source={require('@/assets/images/target/black.png')} description={t("play.drawer.stat_capture_label")}>{nCaptures ?? 0}</Stat>
|
||||
<Stat source={require('@/assets/images/update_position.png')} description={t("play.drawer.stat_reveal_label")}>{nSentLocation ?? 0}</Stat>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
statsContainer: {
|
||||
width: "100%",
|
||||
gap: 15,
|
||||
},
|
||||
title: {
|
||||
fontSize: 20,
|
||||
fontWeight: "bold",
|
||||
textAlign: "center",
|
||||
},
|
||||
row: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-around",
|
||||
},
|
||||
statContainer: {
|
||||
height: 30,
|
||||
flexDirection: "row",
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
gap: 5,
|
||||
},
|
||||
image: {
|
||||
width: 30,
|
||||
height: 30,
|
||||
marginRight: 5
|
||||
},
|
||||
text: {
|
||||
fontSize: 15
|
||||
fontSize: 15,
|
||||
},
|
||||
statsContainer: {
|
||||
gap: 15,
|
||||
width: "100%",
|
||||
marginVertical: 15
|
||||
},
|
||||
row: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-around"
|
||||
}
|
||||
});
|
||||
|
||||
@@ -65,16 +65,16 @@ export const Toasts = () => {
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
position: 'absolute',
|
||||
top: 5,
|
||||
top: 0,
|
||||
left: "50%",
|
||||
transform: [{ translateX: '-50%' }],
|
||||
maxWidth: "60%"
|
||||
maxWidth: "60%",
|
||||
padding: 10,
|
||||
gap: 5
|
||||
},
|
||||
toast: {
|
||||
margin: 5,
|
||||
padding: 10,
|
||||
borderRadius: 15,
|
||||
backgroundColor: 'white',
|
||||
elevation: 5
|
||||
},
|
||||
});
|
||||
|
||||
@@ -4,6 +4,12 @@ export const INITIAL_REGIONS = {
|
||||
longitude: 2.342,
|
||||
latitudeDelta: 0,
|
||||
longitudeDelta: 50
|
||||
},
|
||||
TELECOM_PARIS : {
|
||||
latitude: 48.715,
|
||||
longitude: 2.203,
|
||||
latitudeDelta: 0,
|
||||
longitudeDelta: 0.04
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ export const useUserState = () => {
|
||||
case GAME_STATE.PLAYING:
|
||||
return captured ? USER_STATE.CAPTURED : USER_STATE.PLAYING;
|
||||
case GAME_STATE.FINISHED:
|
||||
return USER_STATE.FINISHED;
|
||||
return captured ? USER_STATE.CAPTURED : USER_STATE.FINISHED;
|
||||
default:
|
||||
return USER_STATE.WAITING;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
}
|
||||
},
|
||||
"wait": {
|
||||
"title": "Rules Reminder !",
|
||||
"title": "While waiting for the game to start, here is a recap of the rules.",
|
||||
"placement_rule": "Go to your starting zone and wait for the game to begin.",
|
||||
"capture_rule": "Track your target using their photo and the positions they reveal. To obtain your target's last known position, you must reveal your own. Once captured, enter their code in the app.",
|
||||
"zone_rule": "Move on foot while making sure to stay within the game zone to avoid penalties ! If you stay outside the zone for too long, your interface will be disabled and your hunter will know your exact position.",
|
||||
@@ -26,7 +26,8 @@
|
||||
},
|
||||
"play": {
|
||||
"info": {
|
||||
"zone_reduction_label": "Zone reduction in",
|
||||
"placement_title": "Head to your zone !",
|
||||
"zone_reduction_label": "Next zone in",
|
||||
"send_position_label": "Position sent in"
|
||||
},
|
||||
"toast": {
|
||||
@@ -47,6 +48,7 @@
|
||||
"capture_code": "{{name}}'s code : {{code}}",
|
||||
"target_name": "Target ({{name}})",
|
||||
"target_code_input": "Target code",
|
||||
"stats_section_title": "Your game statistics",
|
||||
"stat_distance_label": "Distance traveled",
|
||||
"stat_time_label": "Elapsed time (HH:MM:SS)",
|
||||
"stat_speed_label": "Average speed",
|
||||
@@ -54,13 +56,18 @@
|
||||
"stat_reveal_label": "Total times your position was sent"
|
||||
}
|
||||
},
|
||||
"end": {
|
||||
"title_captured": "You have been captured...",
|
||||
"title_win": "You won !",
|
||||
"paragraph": "The game ends here for you ! You can head back to the starting point to grab a snack and watch the rest of the game."
|
||||
},
|
||||
"info": {
|
||||
"default": {
|
||||
"title": "Info"
|
||||
},
|
||||
"succes": {
|
||||
"success": {
|
||||
"title": "Success !",
|
||||
"capture_success": "You have successfully captured your target. A new target has been assigned to you."
|
||||
"capture_success": "You have successfully captured your target."
|
||||
},
|
||||
"failure": {
|
||||
"title": "Failure...",
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
}
|
||||
},
|
||||
"wait": {
|
||||
"title": "Rappel des règles !",
|
||||
"title": "En attendant que la partie commence, voici un récap des règles.",
|
||||
"placement_rule": "Rejoignez votre zone de départ et attendez le début de la partie.",
|
||||
"capture_rule": "Traquez votre cible grâce à sa photo et aux positions qu'elle révèle. Pour obtenir la dernière position connue de votre cible, vous devrez révéler la vôtre. Une fois capturée, entrez son code dans l'application.",
|
||||
"zone_rule": "Déplacez-vous à pied tout en veillant à rester dans la zone de jeu pour ne pas être pénalisé ! Si vous restez trop longtemps en dehors de la zone, votre interface sera désactivée et votre chasseur connaîtra précisément votre position.",
|
||||
@@ -26,7 +26,8 @@
|
||||
},
|
||||
"play": {
|
||||
"info": {
|
||||
"zone_reduction_label": "Réduction de la zone dans",
|
||||
"placement_title": "Placez vous dans votre zone !",
|
||||
"zone_reduction_label": "Prochaine zone dans",
|
||||
"send_position_label": "Position envoyée dans"
|
||||
},
|
||||
"toast": {
|
||||
@@ -47,6 +48,7 @@
|
||||
"capture_code": "Code de {{name}} : {{code}}",
|
||||
"target_name": "Cible ({{name}})",
|
||||
"target_code_input": "Code cible",
|
||||
"stats_section_title": "Statistiques de votre partie",
|
||||
"stat_distance_label": "Distance parcourue",
|
||||
"stat_time_label": "Temps écoulé (HH:MM:SS)",
|
||||
"stat_speed_label": "Vitesse moyenne",
|
||||
@@ -54,13 +56,18 @@
|
||||
"stat_reveal_label": "Nombre total d'envois de votre position"
|
||||
}
|
||||
},
|
||||
"end": {
|
||||
"title_captured": "Vous avez été capturé...",
|
||||
"title_win": "Vous avez gagné !",
|
||||
"paragraph": "La partie se termine ici pour vous ! Vous pouvez rejoindre le point de départ pour prendre un goûter et assister au reste de la partie."
|
||||
},
|
||||
"info": {
|
||||
"default": {
|
||||
"title": "Info"
|
||||
},
|
||||
"succes": {
|
||||
"success": {
|
||||
"title": "Bravo !",
|
||||
"capture_success": "Vous avez réussi à capturer votre cible. Une nouvelle cible vient de vous être attribuée."
|
||||
"capture_success": "Vous avez réussi à capturer votre cible."
|
||||
},
|
||||
"failure": {
|
||||
"title": "Raté...",
|
||||
|
||||
Reference in New Issue
Block a user