Compare commits

..

No commits in common. 'master' and 'Backend/Page/Connexion' have entirely different histories.

@ -7,7 +7,7 @@ import LoginStack from './navigation/LoginStack';
import Navigation from './navigation/Navigation'; import Navigation from './navigation/Navigation';
import ChangePassword from './screens/ChangePassword'; import ChangePassword from './screens/ChangePassword';
import CreateTeam from './screens/CreateTeam'; import CreateTeam from './screens/CreateTeam';
import Team_Info from './screens/Team_Info'; import InfoTeam from './screens/InfoTeam';
import Login from './screens/Login'; import Login from './screens/Login';
import ManageAccount from './screens/ManageAccount'; import ManageAccount from './screens/ManageAccount';
import NewTrack from './screens/NewTrack'; import NewTrack from './screens/NewTrack';
@ -15,18 +15,14 @@ import Register from './screens/Register';
import Session_browser from './screens/Session_browser'; import Session_browser from './screens/Session_browser';
import Team_Browser from './screens/Team_Browser'; import Team_Browser from './screens/Team_Browser';
import Team_Selection from './screens/Team_Selection'; import Team_Selection from './screens/Team_Selection';
import { Provider } from 'react-redux';
import store from './redux/Store';
export default function App() { export default function App() {
return ( return (
<Provider store={store}> <SafeAreaView style={styles.container}>
<SafeAreaView style={styles.container}> <NavigationContainer independent={true}>
<NavigationContainer independent={true}> <LoginStack />
<LoginStack /> </NavigationContainer>
</NavigationContainer> </SafeAreaView>
</SafeAreaView>
</Provider>
); );
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 527 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 594 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 587 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

@ -1,55 +0,0 @@
import React from "react";
import { View,Image,Text, StyleSheet, Touchable } from "react-native";
import { TouchableOpacity } from "react-native-gesture-handler";
import { Session } from "../core/Session";
type SessionListItemProps = {
session: Session;
onPress: (team: Session) => void;
}
export default function SessionListItem(props: SessionListItemProps) {
const timeInSeconds = props.session.getLaps()[props.session.getLaps().length - 1].getTime();
return (
<TouchableOpacity style={styles.container}
onPress={()=> props.onPress(props.session)}>
<Text style={styles.text_style}> {props.session.getName()}</Text>
<View style={styles.container_low}>
<Text style={styles.text_under}> {props.session.getType().toString() }</Text>
<Text style={styles.text_under}> { timeInSeconds }</Text>
</View>
</TouchableOpacity>
)
}
const styles = StyleSheet.create({
container: {
borderRadius:30,
alignItems:'center',
backgroundColor:'#e1e8ee',
padding:1,
flex: 1,
margin:10,
},
container_low: {
borderRadius:30,
alignItems:'center',
backgroundColor:'#e1e8ee',
padding:10,
flex: 1,
flexDirection: "row",
marginBottom:10,
},
text_style:{
textAlign:'center',
fontSize:25,
},
text_under:{
marginLeft:15,
textAlign:'center',
fontSize:20,
}
});

@ -1,43 +0,0 @@
import React from "react";
import { View,Image,Text, StyleSheet, Touchable } from "react-native";
import { TouchableOpacity } from "react-native-gesture-handler";
import { Team } from "../core/Team";
type TeamListItemProps = {
team: Team;
onPress: (team: Team) => void;
}
export default function TeamListItem(props: TeamListItemProps) {
return (
<TouchableOpacity style={styles.container}
onPress={()=> props.onPress(props.team)}>
<Image style={styles.teaserImage} source={props.team.getLogo()} />
<Text style={styles.text_style}> {props.team.getName()}</Text>
</TouchableOpacity>
)
}
const styles = StyleSheet.create({
container: {
alignItems:'center',
backgroundColor:'#e1e8ee',
padding:10,
flex: 1,
flexDirection: "row",
marginBottom:10,
},
text_style:{
marginLeft:15,
textAlign:'center',
fontSize:20,
},
teaserImage: {
borderWidth:1,
borderColor:'black',
borderRadius:50,
width: 50,
height: 50,
}
});

@ -1,12 +1,18 @@
export class Geocalisation { export class Geocalisation {
readonly id: number;
private gpsLat: number; private gpsLat: number;
private gpsLong: number; private gpsLong: number;
constructor(gpsLat: number, gpsLong: number) { constructor(id: number, gpsLat: number, gpsLong: number) {
this.id = id;
this.gpsLat = gpsLat; this.gpsLat = gpsLat;
this.gpsLong = gpsLong; this.gpsLong = gpsLong;
} }
getId() {
return this.id;
}
getGpsLat() { getGpsLat() {
return this.gpsLat; return this.gpsLat;
} }

@ -1,7 +0,0 @@
import { Session } from "./Session";
export interface ILoader{
Load() : Session
LoadFromFile(file : File) : Session
}

@ -1,21 +1,18 @@
import { Point } from "./Point"; import { Point } from "./Point";
export class Lap { export class Lap {
private number : number; readonly id: number;
private points: Point[]; private points: Point[];
private time: string; private time: number;
constructor(number: number,points: Point[], time: string) { constructor(id: number, points: Point[], time: number) {
this.number = number; this.id = id;
this.points = points; this.points = points;
this.time = time; this.time = time;
} }
getNumber(){ getId() {
return this.number; return this.id;
}
setNumber(number :number){
this.number = number;
} }
getPoints() { getPoints() {
@ -30,52 +27,7 @@ export class Lap {
return this.time; return this.time;
} }
getFormattedTime(){ setTime(time: number) {
// const timeInSeconds = this.time;
// const timeInMs = timeInSeconds * 1000;
// const date = new Date(timeInMs);
// const minutes = date.getMinutes().toString().padStart(2, "0");
// const seconds = date.getSeconds().toString().padStart(2, "0");
// const milliseconds = date.getMilliseconds().toString().padStart(2, "0");
// const formattedTime = `${minutes}:${seconds}:${milliseconds}`;
// return formattedTime;
}
setTime(time: string) {
this.time = time; this.time = time;
} }
getAverageSpeed(){
var sum = 0;
this.points.forEach(pt => {
sum += pt.getVCar();
});
return sum/this.points.length;
}
getMaxSpeed(){
var max = 0.0;
this.points.forEach(pt => {
if(max < pt.getVCar()){
max = pt.getVCar();
}
});
return max;
}
getLocationLat(){
var sum = 0.0;
this.points.forEach(pt => {
sum += pt.getGeo().getGpsLat();
});
return sum/this.points.length;
}
getLocationLong(){
var sum = 0.0;
this.points.forEach(pt => {
sum += pt.getGeo().getGpsLong();
});
return sum/this.points.length;
}
} }

@ -1,12 +0,0 @@
import { ILoader } from "./ILoader";
import { Session } from "./Session";
export class LoadDB implements ILoader{
LoadFromFile(file: File): Session {
throw new Error("file argument is not accepted !."); // GARDER EN NON IMPLEMENTED !
}
Load(): Session {
throw new Error("Method not implemented."); // APPEL API
}
}

@ -1,13 +0,0 @@
import { ILoader } from "./ILoader";
import { Session } from "./Session";
export class LoadXLS implements ILoader{
LoadFromFile(file: File): Session {
throw new Error("Method not implemented."); // APPEL API RETOUR JSON
}
Load(): Session {
throw new Error("Cannot load without a file."); // GARDER EN NON IMPLEMENTED !
}
}

@ -3,7 +3,7 @@ import { Team } from "./Team";
import { User } from "./User"; import { User } from "./User";
export class Member extends User { export class Member extends User {
constructor(username: string, password: string, email: string, sessions: Session[],image : HTMLImageElement= require('../assets/images/user.jpg')) { constructor(id: number, pseudo: string, password: string, email: string, sessions: Session[], team: Team) {
super(username, password, email, sessions, image); super(id, pseudo, password, email, sessions, team);
} }
} }

@ -3,11 +3,7 @@ import { Team } from "./Team";
import { User } from "./User"; import { User } from "./User";
export class Owner extends User { export class Owner extends User {
constructor( username: string, password: string, email: string, sessions: Session[],image : HTMLImageElement= require('../assets/images/user.jpg')) { constructor(id: number, pseudo: string, password: string, email: string, sessions: Session[], team: Team) {
super(username, password, email, sessions,image); super(id, pseudo, password, email, sessions, team);
}
IsOwner(): boolean{
return true;
} }
} }

@ -1,6 +1,7 @@
import { Geocalisation } from "./Geocalisation"; import { Geocalisation } from "./Geocalisation";
export class Point { export class Point {
readonly id: number;
private geo: Geocalisation; private geo: Geocalisation;
private timer: number; private timer: number;
private distance: number; private distance: number;
@ -12,7 +13,8 @@ export class Point {
private gLat: number; private gLat: number;
private vCar: number; private vCar: number;
constructor( geo: Geocalisation, timer: number, distance: number, nGear: number, pBrakeF: number, aSteer: number, rPedal: number, gLong: number, gLat: number, vCar: number) { constructor(id: number, geo: Geocalisation, timer: number, distance: number, nGear: number, pBrakeF: number, aSteer: number, rPedal: number, gLong: number, gLat: number, vCar: number) {
this.id = id;
this.geo = geo; this.geo = geo;
this.timer = timer; this.timer = timer;
this.distance = distance; this.distance = distance;
@ -25,6 +27,10 @@ export class Point {
this.vCar = vCar; this.vCar = vCar;
} }
getId() {
return this.id;
}
getGeo() { getGeo() {
return this.geo; return this.geo;
} }
@ -41,17 +47,6 @@ export class Point {
return this.timer; return this.timer;
} }
getFormattedTime(){
const timeInSeconds = this.timer;
const timeInMs = timeInSeconds * 1000;
const date = new Date(timeInMs);
const minutes = date.getMinutes().toString().padStart(2, "0");
const seconds = date.getSeconds().toString().padStart(2, "0");
const milliseconds = date.getMilliseconds().toString().padStart(2, "0");
const formattedTime = `${minutes}:${seconds}:${milliseconds}`;
return formattedTime;
}
getDistance() { getDistance() {
return this.distance; return this.distance;
} }

@ -1,22 +1,18 @@
import { Lap } from "./Lap"; import { Lap } from "./Lap";
import { SessionType } from "./SessionType";
export class Session { export class Session {
readonly id: number;
private name: string; private name: string;
private type: SessionType;
private laps: Lap[]; private laps: Lap[];
constructor( name: string, laps: Lap[], type: SessionType = SessionType.Unknown) { constructor(id: number, name: string, laps: Lap[]) {
this.type = type this.id = id;
this.name = name; this.name = name;
this.laps = laps; this.laps = laps;
} }
getType() {
return this.type;
}
setType(type: SessionType) { getId() {
this.type = type; return this.id;
} }
getName() { getName() {

@ -1,8 +1,8 @@
export enum SessionType { enum SessionType {
Test = "Test", Test,
PrivateTest = "Private Test", PrivateTest,
Qualification = "Qualification", Qualification,
ShortStroke = "Short Stroke", ShortStroke,
LongStroke = "Long Stroke", LongStroke,
Unknown = "Unknown", Unknown,
} }

@ -3,11 +3,11 @@ import { SessionBuilder } from "./SessionBuilder";
export class StandartSessionBuilder extends SessionBuilder { export class StandartSessionBuilder extends SessionBuilder {
BuildSession() { BuildSession() {
//PointBuilder(); PointBuilder();
} }
PointBuilder() { PointBuilder() {
//new Point(); new Point();
} }
} }

@ -1,17 +1,24 @@
import { User } from "./User"; import { User } from "./User";
import { WaitingMember } from "./WaitingMember";
export class Team { export class Team {
readonly id: number;
private name: string; private name: string;
private owner: User; private owner: User;
private users: User[]; private members: User[];
private logo: HTMLImageElement; private logo: File;
private waitList: User[];
constructor(name: string, owner: User ,users: User[] = [], logo: HTMLImageElement = require('../assets/images/people.jpg')) { constructor(id: number, name: string, owner: User,members: User[] = null, logo: File = null, waitList: User[] = null) {
this.id = id;
this.name = name; this.name = name;
this.owner = owner; this.owner = owner;
this.users = users; this.members = members;
this.logo = logo; this.logo = logo;
this.waitList = waitList;
}
getId() {
return this.id;
} }
getName() { getName() {
@ -30,37 +37,27 @@ export class Team {
this.owner = owner; this.owner = owner;
} }
getusers() { getMembers() {
return this.users; return this.members;
} }
setusers(users: User[]) { setMembers(members: User[]) {
this.users = users; this.members = members;
} }
getLogo() { getLogo() {
return this.logo; return this.logo;
} }
setLogo(logo: HTMLImageElement) { setLogo(logo: File) {
this.logo = logo; this.logo = logo;
} }
getWaitList() { getWaitList() {
var waitList : User[] = []; return this.waitList;
this.users.forEach(user => {
if(user as WaitingMember){
waitList.concat(user);
}
});
return waitList;
} }
addToWaitList(user: User) : boolean{ setWaitList(waitList: User[]) {
if(!this.users.includes(user)){ this.waitList = waitList;
this.users.concat(user);
return true;
}
return false;
} }
} }

@ -1,10 +1,16 @@
export class Track { export class Track {
readonly id: number;
private name: string; private name: string;
constructor(name: string) { constructor(id: number, name: string) {
this.id = id;
this.name = name; this.name = name;
} }
getId() {
return this.id;
}
getName() { getName() {
return this.name; return this.name;
} }

@ -2,35 +2,31 @@ import { Session } from "./Session";
import { Team } from "./Team"; import { Team } from "./Team";
export abstract class User { export abstract class User {
private username: string; readonly id: number;
private pseudo: string;
private password: string; private password: string;
private email: string; private email: string;
private sessions: Session[]; private sessions: Session[];
private image : HTMLImageElement; private team: Team;
constructor(username: string, password: string, email: string, sessions: Session[] = [], image : HTMLImageElement) { constructor(id: number, pseudo: string, password: string, email: string, sessions: Session[] = null, team: Team = null) {
this.username = username; this.pseudo = pseudo;
this.password = password; this.password = password;
this.email = email; this.email = email;
this.sessions = sessions; this.sessions = sessions;
this.image = image; this.team = team;
}
getImage(){
return this.image;
} }
setImage(image: HTMLImageElement){ getId() {
this.image = image; return this.id;
} }
getUsername() { getPseudo() {
return this.username; return this.pseudo;
} }
setUsername(username: string) { setPseudo(pseudo: string) {
this.username = username; this.pseudo = pseudo;
} }
getPassword() { getPassword() {
@ -57,4 +53,12 @@ export abstract class User {
this.sessions = sessions; this.sessions = sessions;
} }
getTeam() {
return this.team;
}
setTeam(team: Team) {
this.team = team;
}
} }

@ -1,8 +1,9 @@
import { Session } from "./Session"; import { Session } from "./Session";
import { Team } from "./Team";
import { User } from "./User"; import { User } from "./User";
export class WaitingMember extends User { export class WaitingMember extends User {
constructor( pseudo: string, password: string, email: string, sessions: Session[],image : HTMLImageElement= require('../assets/images/user.jpg')) { constructor(id: number, pseudo: string, password: string, email: string, sessions: Session[], team: Team) {
super(pseudo, password, email, sessions, image); super(id, pseudo, password, email, sessions, team);
} }
} }

@ -1,7 +1,6 @@
import { createStackNavigator } from "@react-navigation/stack"; import { createStackNavigator } from "@react-navigation/stack";
import Lap from "../screens/Lap"; import Lap from "../screens/Lap";
import NewTrack from "../screens/NewTrack"; import NewTrack from "../screens/NewTrack";
import Point_Viewer from "../screens/Point_Viewer";
import Session_browser from "../screens/Session_browser"; import Session_browser from "../screens/Session_browser";
import SettingsStack from "./SettingsStack"; import SettingsStack from "./SettingsStack";
@ -12,7 +11,6 @@ export default function MainStack() {
<Stack.Screen name="Home" component={Session_browser} /> <Stack.Screen name="Home" component={Session_browser} />
<Stack.Screen name="Add" component={NewTrack} /> <Stack.Screen name="Add" component={NewTrack} />
<Stack.Screen name="Lap" component={Lap} /> <Stack.Screen name="Lap" component={Lap} />
<Stack.Screen name="PointInfo" component={Point_Viewer} />
<Stack.Screen name="Settings" component={SettingsStack} /> <Stack.Screen name="Settings" component={SettingsStack} />
</Stack.Navigator> </Stack.Navigator>
) )

@ -1,6 +1,6 @@
import { createStackNavigator } from "@react-navigation/stack"; import { createStackNavigator } from "@react-navigation/stack";
import CreateTeam from "../screens/CreateTeam"; import CreateTeam from "../screens/CreateTeam";
import Team_Info from "../screens/Team_Info"; import InfoTeam from "../screens/InfoTeam";
import Team_Browser from "../screens/Team_Browser"; import Team_Browser from "../screens/Team_Browser";
import Team_Selection from "../screens/Team_Selection"; import Team_Selection from "../screens/Team_Selection";
@ -10,7 +10,7 @@ export default function TeamInfoStack() {
return ( return (
<Stack.Navigator initialRouteName="Home" screenOptions={{ headerShown: false }}> <Stack.Navigator initialRouteName="Home" screenOptions={{ headerShown: false }}>
<Stack.Screen name="Home" component={Team_Browser} /> <Stack.Screen name="Home" component={Team_Browser} />
<Stack.Screen name="Info" component={Team_Info} /> <Stack.Screen name="Info" component={InfoTeam} />
</Stack.Navigator> </Stack.Navigator>
) )
} }

17807
R-Dash/package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -13,25 +13,18 @@
"@react-navigation/bottom-tabs": "^6.5.5", "@react-navigation/bottom-tabs": "^6.5.5",
"@react-navigation/native": "^6.1.6", "@react-navigation/native": "^6.1.6",
"@react-navigation/stack": "^6.3.16", "@react-navigation/stack": "^6.3.16",
"@reduxjs/toolkit": "^1.9.3",
"@rneui/base": "^4.0.0-rc.7", "@rneui/base": "^4.0.0-rc.7",
"expo": "~48.0.6", "expo": "~48.0.6",
"expo-document-picker": "~11.2.2", "expo-document-picker": "~11.2.1",
"expo-status-bar": "~1.4.4", "expo-status-bar": "~1.4.4",
"jsonwebtoken": "^9.0.0", "jsonwebtoken": "^9.0.0",
"react": "18.2.0", "react": "18.2.0",
"react-native": "0.71.4", "react-native": "0.71.3",
"react-native-document-picker": "^8.2.0", "react-native-document-picker": "^8.1.4",
"react-native-fs": "^2.20.0",
"react-native-gesture-handler": "^2.9.0", "react-native-gesture-handler": "^2.9.0",
"react-native-maps": "1.3.2", "react-native-maps": "1.3.2",
"react-native-safe-area-context": "^4.5.0", "react-native-safe-area-context": "^4.5.0",
"react-redux": "^8.0.5", "typescript": "^4.9.4"
"redux": "^4.2.1",
"typescript": "^4.9.4",
"react-native-web": "~0.18.10",
"react-dom": "18.2.0",
"@expo/webpack-config": "^18.0.1"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.20.0", "@babel/core": "^7.20.0",

@ -1,7 +0,0 @@
export const FETCH_USERS = 'FETCH_USERS';
export const FETCH_TEAMS = 'FETCH_TEAMS';
export const FETCH_SESSIONS = 'FETCH_SESSIONS';
export const ADD_TEAM = 'ADD_TEAM';
export const ADD_FILE = 'ADD_FILE';
//export const server_link = "https://codefirst.iut.uca.fr/containers/enzojolys-r-dash_container";
export const server_link = "https://r-dash.azurewebsites.net";

@ -1,18 +0,0 @@
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit'
import appReducer from './reducers/appReducer';
// Reference here all your application reducers
const reducer = {
appReducer: appReducer,
}
const middleware = getDefaultMiddleware({
serializableCheck: false, // Disable serializableCheck
immutableCheck: false
});
const store = configureStore({
reducer,
middleware,
});
export default store;

@ -1,74 +0,0 @@
import { Alert } from "react-native";
import { Geocalisation } from "../../core/Geocalisation";
import { Lap } from "../../core/Lap";
import { Point } from "../../core/Point";
import { Session } from "../../core/Session";
import { User } from "../../core/User";
import { FETCH_SESSIONS, server_link } from "../Constants";
export const setSessionsList = (sessionsList: Session[]) => {
return {
type: FETCH_SESSIONS,
payload: sessionsList,
};
}
// export const addXlsFile = async (file: File) => {
// try {
// const formData = new FormData();
// formData.append('file', file);
// const response = await fetch(
// 'https://r-dash.azurewebsites.net/File?' + "pseudoPilote=test_PILOTE" + "&Email=test@gmail.com" + "&password=test123" + "&nameSession=test_SESSION" + "&nameCircuit=test_CIRCUIT" + "&typeSession=Unknown", {
// method: 'POST',
// body: formData
// });
// const data = await response.json();
// return data;
// } catch (error) {
// console.log('Error---------', error);
// }
// };
export const addXlsFile = (file: File, pseudoPilote: string, email: string, password: string, nameSession: string, nameCircuit: string, typeSession: string) => {
return async dispatch => {
try {
const formData = new FormData();
formData.append('file', file);
const response = await fetch(
server_link+`/File?pseudoPilote=${pseudoPilote}&Email=${email}&password=${password}&nameSession=${nameSession}&nameCircuit=${nameCircuit}&typeSession=${typeSession}`,
{
method: 'POST',
body: formData
}
);
const data = await response.json();
return data;
} catch (error) {
console.log('Error - POST FILE', error);
Alert.alert('Error', 'An error occured while adding a session. (server might be down)');
}
}
};
export const getSessionsList = () => {
return async dispatch => {
try {
const sessionsPromise = await fetch(server_link+'/FullSession');
const sessionsListJson = await sessionsPromise.json();
const sessionsList: Session[] = sessionsListJson.map(elt => {
const laps: Lap[] = elt["tours"].map(lap => {
const points: Point[] = lap["points"].map(point => {
const geo = new Geocalisation(point["longitude"], point["latitude"]);
return new Point(geo, point["timer"] , point["distance"], point["nGear"], point["pBrakeF"], point["aSteer"], point["rPedal"], point["gLong"], point["gLat"], point["vCar"]);
});
return new Lap(lap["numero"], points, lap["temps"]);
});
return new Session(elt["name"], laps, elt["type"]);
});
dispatch(setSessionsList(sessionsList));
} catch (error) {
console.log('Error -- GET SESSIONS', error);
Alert.alert('Error', 'An error occured while getting sessions. (server might be down)');
//dispatch(fetchDataRejected(error))
}
}
}

@ -1,45 +0,0 @@
import { Team } from "../../core/Team";
import { FETCH_TEAMS, ADD_TEAM, server_link } from "../Constants";
export const setTeamsList = (teamsList: Team[]) => {
return {
type: FETCH_TEAMS,
payload: teamsList,
};
}
export const addNewTeam = (newTeam: Team) => {
return async dispatch => {
try {
const response = await fetch(server_link + '/Ecuries?' + "Email=test@gmail.com" + "&password=test123" + "&pseudoPilote=test_PILOTE", {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(newTeam)
});
const team = await response.json();
dispatch({
type: ADD_TEAM,
payload: team
});
} catch (error) {
console.log('Error---------', error);
//dispatch(fetchDataRejected(error))
}
}
}
export const getTeamsList = () => {
return async dispatch => {
try {
const teamsPromise = await fetch(server_link+'/Ecuries');
const teamsListJson = await teamsPromise.json();
const teamsList: Team[] = teamsListJson.map(elt => new Team(elt["name"], elt["owner"], elt["users"], elt["logo"]));
dispatch(setTeamsList(teamsList));
} catch (error) {
console.log('Error---------', error);
//dispatch(fetchDataRejected(error))
}
}
}

@ -1,36 +0,0 @@
import { Member } from "../../core/Member";
import { Owner } from "../../core/Owner";
import { Team } from "../../core/Team";
import { User } from "../../core/User";
import { WaitingMember } from "../../core/WaitingMember";
import { FETCH_USERS } from "../Constants";
import { DtoUserEcurie } from "../dto/dtoUserEcurie";
export const setUsersList = (usersList: User[]) => {
return {
type: FETCH_USERS,
payload: usersList,
};
}
export const getUsersList = (team: Team) => {
return async dispatch => {
try {
const usersPromise = await fetch(server_link+'/Pilotes/'+team);
const usersListJson = await usersPromise.json();
const dto: DtoUserEcurie = usersListJson.map(elt => new DtoUserEcurie(elt["owner"], elt["members"], elt["waitingMember"]));
const usersList: User[] = []
usersList.push(dto.getOwner())
dto.getMembers().forEach(element => {
usersList.push(element);
});
dto.getWaitingMember().forEach(element => {
usersList.push(element)
});
dispatch(setUsersList(usersList));
} catch (error) {
console.log('Error---------', error);
//dispatch(fetchDataRejected(error))
}
}
}

@ -1,37 +0,0 @@
import { Member } from "../../core/Member";
import { Owner } from "../../core/Owner";
import { WaitingMember } from "../../core/WaitingMember";
export class DtoUserEcurie {
private owner: Owner;
private members: Member[];
private waitingMember: WaitingMember[];
constructor(owner: Owner, members: Member[], waitingMember: WaitingMember[]) {
this.owner = owner;
this.members = members;
this.waitingMember = waitingMember;
}
getOwner() {
return this.owner;
}
setOwner(owner: Owner) {
this.owner = owner;
}
getMembers() {
return this.members;
}
setMembers(members: Member[]) {
this.members = members;
}
getWaitingMember() {
return this.waitingMember;
}
setWaitingMember(waitingMember: WaitingMember[]) {
this.waitingMember = waitingMember;
}
}

@ -1,28 +0,0 @@
import { addXlsFile } from "../actions/sessions";
import { addNewTeam } from "../actions/teams";
import { FETCH_SESSIONS, FETCH_TEAMS, FETCH_USERS, ADD_TEAM, ADD_FILE } from "../Constants";
const initialState = {
teams: [],
users: [],
sessions: [],
};
const appReducer = (state = initialState, action: { type: any; payload: any; }) => {
switch (action.type) {
case ADD_TEAM:
return { ...state, teams: [...state.teams, addNewTeam] };
case ADD_FILE:
return { ...state, sessions: [...state.sessions, addXlsFile] };
case FETCH_TEAMS:
return { ...state, teams: action.payload };
case FETCH_USERS:
return { ...state, users: action.payload };
case FETCH_SESSIONS:
return { ...state, sessions: action.payload };
default:
return state;
}
};
export default appReducer;

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { Pressable } from 'react-native'; import { Button, Pressable } from 'react-native';
import { StyleSheet, Text, View, Image, TextInput } from 'react-native'; import { StyleSheet, Text, View, Image, TextInput } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context'; import { SafeAreaView } from 'react-native-safe-area-context';

@ -1,34 +1,10 @@
import React, { useEffect, useState } from 'react'; import React from 'react';
import { Pressable } from 'react-native'; import { Button, Pressable } from 'react-native';
import { StyleSheet, Text, View, Image, TextInput } from 'react-native'; import { StyleSheet, Text, View, Image, TextInput } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context'; import { SafeAreaView } from 'react-native-safe-area-context';
import * as DocumentPicker from 'expo-document-picker';
import { useDispatch, useSelector } from 'react-redux';
import { addNewTeam } from '../redux/actions/teams';
export default function CreateTeam(props: { navigation: any }) { export default function CreateTeam(props: { navigation: any }) {
const { navigation } = props; const { navigation } = props;
const [pickedDocument, setPickedDocument] = useState<DocumentPicker.DocumentResult | null>(null);
const handlePickDocument = async () => {
try {
const result = await DocumentPicker.getDocumentAsync({ type: ['image/png', 'image/jpeg', 'image/jpg'] });
if (result.type === 'success') {
setPickedDocument(result);
}
} catch (err) {
console.log(err);
}
};
const dispatch = useDispatch();
const onPressAddTeam = async () => {
dispatch();
navigation.goBack();
};
return ( return (
<SafeAreaView style={styles.container}> <SafeAreaView style={styles.container}>
<View style={styles.maincard}> <View style={styles.maincard}>
@ -39,11 +15,11 @@ export default function CreateTeam(props: { navigation: any }) {
style={styles.logo} style={styles.logo}
source={require('../assets/images/image.png')} source={require('../assets/images/image.png')}
/> />
<Pressable onPress={handlePickDocument}> <Pressable>
<Image style={styles.import} source={require('../assets/images/import.png')} /> <Image
<Text> style={styles.import}
Picked document: {pickedDocument ? pickedDocument.name : 'none'} source={require('../assets/images/import.png')}
</Text> />
</Pressable> </Pressable>
</View> </View>
@ -63,7 +39,7 @@ export default function CreateTeam(props: { navigation: any }) {
source={require('../assets/images/return.png')} source={require('../assets/images/return.png')}
/> />
</Pressable> </Pressable>
<Pressable style={styles.button} onPress={onPressAddTeam}> <Pressable style={styles.button} onPress={() => navigation.goBack()}>
<Image <Image
style={styles.return} style={styles.return}
source={require('../assets/images/checked.png')} source={require('../assets/images/checked.png')}

@ -1,9 +1,9 @@
import React from 'react'; import React from 'react';
import { Pressable } from 'react-native'; import { Button, Pressable } from 'react-native';
import { StyleSheet, Text, View, Image } from 'react-native'; import { StyleSheet, Text, View, Image } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context'; import { SafeAreaView } from 'react-native-safe-area-context';
export default function Team_Info(props: { navigation: any }) { export default function InfoTeam(props: { navigation: any }) {
const { navigation } = props; const { navigation } = props;
return ( return (
<SafeAreaView style={styles.container}> <SafeAreaView style={styles.container}>

@ -1,59 +1,50 @@
import { BackgroundImage } from '@rneui/base'; import { BackgroundImage } from '@rneui/base';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native'; import { FlatList, StyleSheet, Text, View, Image, TouchableOpacity } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context'; import { SafeAreaView } from 'react-native-safe-area-context';
import MapView, { Polyline } from 'react-native-maps'; import MapView from 'react-native-maps';
import React from 'react'; import PROVIDER_OPENSTREETMAP, { Marker } from 'react-native-maps';
import { Lap as LapModel} from '../core/Lap';
import TopBar from '../components/TopBar';
export default function Lap(props: { navigation: any, route : any}) { export default function Lap() {
const { session } = props.route.params;
const { navigation } = props;
const laps: LapModel[] = session.getLaps().sort((lap1 : LapModel, lap2 : LapModel) => lap1.getNumber() - lap2.getNumber());
const [currentLapIndex, setCurrentLapIndex] = React.useState(0);
const currentLap: LapModel | undefined = laps[currentLapIndex];
const goToPreviousLap = () => {
if (currentLapIndex > 0) {
setCurrentLapIndex(currentLapIndex - 1);
}
};
const goToNextLap = () => {
if (currentLapIndex < laps.length - 1) {
setCurrentLapIndex(currentLapIndex + 1);
}
};
const points : any = [];
currentLap.getPoints().forEach(pt => {
points.push({ latitude: pt.getGeo().getGpsLat(), longitude: pt.getGeo().getGpsLong() });
});
//var currentLap : undefined; // Penser à vérifier si la session ne possède pas de tour !! si c'est le cas afficher une popup d'erreur
return ( return (
<SafeAreaView style={styles.container}> <SafeAreaView style={styles.container}>
<View style={styles.container}> <View style={styles.container}>
{/* Header */} {/* Header */}
<TopBar navigation={navigation} /> <View style={styles.topbar}>
<View>
<TouchableOpacity style={styles.accountContainerButton}>
<View style={styles.ImageContainer}>
<Image source={require('../assets/images/pfp.png')} style={styles.accountImage} />
</View>
<Text style={styles.accountName}>Mr X</Text>
</TouchableOpacity>
</View>
<View style={styles.topbarRight}>
<View style={styles.iconContainer}>
<Image source={require('../assets/images/settings.png')} style={styles.accountSettings} />
</View>
<TouchableOpacity style={styles.accountContainerButton}>
<View style={styles.ImageContainer}>
<Image source={require('../assets/images/rdash.png')} style={styles.accountImage} />
</View>
</TouchableOpacity>
</View>
</View>
{/* Body */} {/* Body */}
<View style={styles.container}> <View style={styles.container}>
<BackgroundImage source={require('../assets/images/rdash.png')} resizeMode="contain" style={styles.backgroundImage}>
<View style={styles.top_lap}> <View style={styles.top_lap}>
<TouchableOpacity style={[styles.LapBrowserButton, currentLapIndex === 0 ? styles.disabled : null]} onPress={goToPreviousLap}> <TouchableOpacity style={styles.LapBrowserButton} >
<View> <View>
<Text style={styles.button_text} >Previous lap</Text> <Text style={styles.button_text} >Previous lap</Text>
</View> </View>
</TouchableOpacity> </TouchableOpacity>
<Text style={styles.text_title}>Lap {currentLap?.getNumber()} </Text> <Text style={styles.text_title}>Lap X</Text>
<TouchableOpacity style={[styles.LapBrowserButton, currentLapIndex === laps.length - 1 ? styles.disabled : null]} onPress={goToNextLap}> <TouchableOpacity style={styles.LapBrowserButton}>
<View> <View>
<Text style={styles.button_text} >Next lap</Text> <Text style={styles.button_text} >Next lap</Text>
</View> </View>
@ -61,61 +52,54 @@ export default function Lap(props: { navigation: any, route : any}) {
</View> </View>
<View style={styles.containerBody}> <View style={styles.container}>
<TouchableOpacity
style={styles.addContainerButton}
onPress={() => navigation.navigate("PointInfo",{"currentLap": currentLap})}
>
<View>
<Text style={styles.button_text}>Point Viewer Mode</Text>
</View>
</TouchableOpacity>
<MapView <MapView
style={styles.map} style={styles.map}
mapType="satellite"
region={{ region={{
latitude: currentLap.getLocationLat(), latitude: 46.863415273862,
longitude: currentLap.getLocationLong(), longitude: 3.161789595537,
latitudeDelta: 0.001, latitudeDelta: 0.001,
longitudeDelta: 0.015, longitudeDelta: 0.01,
}} }}
> >
<Polyline <Marker
coordinates={points}
strokeColor="red" // set the color of the line
strokeWidth={3} // set the width of the line
/>
{/* <Marker
coordinate={{ coordinate={{
latitude: 45.76013484856403, latitude: 46.863415273862,
longitude: 3.112214188782891, longitude: 3.161789595537
}} }}
onPress={() => console.log('pressed')} title="Marker Title"
/> */} description="Marker Description"
/>
<Marker
coordinate={{
latitude: 46.861927477535,
longitude: 3.160353322067
}}
title="Marker Title"
description="Marker Description"
/>
<Marker
coordinate={{
latitude: 46.859745172448,
longitude: 3.164897426081
}}
title="Marker Title"
description="Marker Description"
/>
</MapView> </MapView>
<BackgroundImage source={require('../assets/images/rdash.png')} resizeMode="contain" >
<View style={styles.container2}>
<Text style={styles.header}>Lap Information</Text> <Text style={styles.textStyle} >Time: 1 30,62 seconds</Text>
<View style={styles.infoContainer}> <View style={styles.infoContainer}>
<Text style={styles.infoItem}>Lap Time:</Text> <Text style={styles.textStyle} >Average Speed: {"\n"} 102 km/h</Text>
<Text style={styles.infoValue}>{currentLap.getTime()}</Text> <Text style={styles.textStyle} >G: {"\n"} 0.001 G</Text>
</View>
<View style={styles.infoContainer}>
<Text style={styles.infoItem}>Average Speed:</Text>
<Text style={styles.infoValue}>{currentLap.getAverageSpeed().toFixed()} km/h</Text>
</View>
<View style={styles.infoContainer}> </View>
<Text style={styles.infoItem}>Max Speed:</Text> <Text style={styles.textStyle} ></Text>
<Text style={styles.infoValue}>{currentLap.getMaxSpeed().toFixed()} km/h</Text>
</View>
</View>
</BackgroundImage>
</View> </View>
</BackgroundImage>
</View> </View>
</View> </View>
@ -123,72 +107,57 @@ export default function Lap(props: { navigation: any, route : any}) {
); );
} }
// TROUBLE SHOOTING BORDER :
//borderColor:'red',
//borderWidth:3,
const styles = StyleSheet.create({ const styles = StyleSheet.create({
disabled: { card: {
opacity: 0.5, flexDirection: 'column',
}, height: "80%",
addContainerButton: { width: "80%",
margin:5, backgroundColor: "#fff",
alignItems: "center", borderRadius: 15,
justifyContent: "center",
height: "8%",
borderRadius: 10,
elevation: 3,
backgroundColor: "#BF181F",
},
containerBody:{
flex: 1,
justifyContent: 'space-between',
alignItems: 'stretch',
},
container2: {
backgroundColor: 'rgba(255, 255, 255, 0.9)',
borderColor:'black',
borderWidth:2,
padding: 10, padding: 10,
borderRadius: 10, elevation: 10,
marginBottom: 20,
shadowColor: '#000', shadowColor: '#000',
shadowOffset: { shadowOffset: { width: 0, height: 3 },
width: 0, shadowOpacity: 0.5,
height: 2, shadowRadius: 5,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
},
header: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 10,
}, },
infoContainer: { infoContainer: {
margin: 3,
flex: 1,
flexDirection: 'row', flexDirection: 'row',
justifyContent: 'space-between', justifyContent: 'space-around',
marginBottom: 5,
},
infoItem: {
fontSize: 18,
fontWeight: 'bold',
},
infoValue: {
fontSize: 18,
}, },
map: { map: {
flex:1, height: "40%",
}, },
top_lap: { top_lap: {
height: "8%", height: "8%",
flexDirection: 'row', flexDirection: 'row',
justifyContent: 'space-between', justifyContent: 'space-between'
}, },
backgroundImage: { backgroundImage: {
flex: 1, flex: 1,
width: '100%', width: '100%',
}, },
container: { container: {
flex: 1, flex: 1,
}, },
accountSettings: {
width: '100%',
height: '100%',
},
accountContainerButton: {
flexDirection: 'row',
alignItems: 'center',
},
LapBrowserButton: { LapBrowserButton: {
width: "30%", width: "30%",
margin: 5, margin: 5,
@ -202,9 +171,60 @@ const styles = StyleSheet.create({
color: '#fff', color: '#fff',
fontSize: 20, fontSize: 20,
}, },
ImageContainer: {
backgroundColor: '#fff',
borderRadius: 50,
width: 40,
height: 40,
overflow: 'hidden',
marginRight: 10,
},
accountImage: {
width: '100%',
height: '100%',
},
topbar: {
backgroundColor: '#BF181D',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 20,
height: "8%",
},
accountName: {
color: '#fff',
fontSize: 20,
},
topbarRight: {
flex: 1,
alignItems: 'flex-end',
},
textStyle: {
margin: 3,
fontSize: 20,
backgroundColor: '#BF181D',
color: 'white',
padding: "2%",
borderRadius: 5,
},
text_title: { text_title: {
fontWeight: 'bold',
fontSize: 30, fontSize: 30,
textAlign: 'center', textAlign: 'center',
padding: 10,
textShadowColor: '#fff',
textShadowOffset: { width: 0, height: 0 },
textShadowRadius: 10,
},
iconContainer: {
position: 'absolute',
bottom: 0,
right: 0,
backgroundColor: 'transparent',
width: 24,
height: 24,
}, },
}); });

@ -1,9 +1,9 @@
import { useState } from 'react'; import { useState } from 'react';
import React from 'react'; import React from 'react';
import { Pressable } from 'react-native'; import { Button, Pressable } from 'react-native';
import { StyleSheet, Text, View, Image, TextInput } from 'react-native'; import { StyleSheet, Text, View, Image, TextInput } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context'; import { SafeAreaView } from 'react-native-safe-area-context';
// import { AsyncStorage } from 'react-native'; import { AsyncStorage } from 'react-native';
export default function Login(props: { navigation: any }) { export default function Login(props: { navigation: any }) {
@ -26,7 +26,7 @@ export default function Login(props: { navigation: any }) {
const secretKey = 'SECRET'; // appele API pour récupérer une clé secrete const secretKey = 'SECRET'; // appele API pour récupérer une clé secrete
const handleLogin = () => { const handleLogin = () => {
const isCorrect = true // envoi email + password a l'API, retour bool de l'API const isCorrect = false // envoi email + password a l'API, retour bool de l'API
// If the email and password are correct, generate a JWT // If the email and password are correct, generate a JWT
if(isCorrect){ if(isCorrect){

@ -1,5 +1,5 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Pressable } from 'react-native'; import { Button, Pressable } from 'react-native';
import { StyleSheet, Text, View, Image, TextInput } from 'react-native'; import { StyleSheet, Text, View, Image, TextInput } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context'; import { SafeAreaView } from 'react-native-safe-area-context';
import * as DocumentPicker from 'expo-document-picker'; import * as DocumentPicker from 'expo-document-picker';

@ -1,149 +1,32 @@
import React, { useState } from 'react'; import { StatusBar } from 'expo-status-bar';
import { Pressable, StyleSheet, Text, View, Image, TouchableOpacity, TextInput } from 'react-native'; import React from 'react';
import { Button, Pressable, StyleSheet, Text, View, Image, TouchableOpacity, TextInput } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context'; import { SafeAreaView } from 'react-native-safe-area-context';
import TopBar from '../components/TopBar';
import { addXlsFile } from '../redux/actions/sessions';
import { useDispatch } from 'react-redux';
import * as DocumentPicker from 'expo-document-picker';
import { uploadFiles, DocumentDirectoryPath } from 'react-native-fs';
export default function NewTrack(props: { navigation: any }) { export default function NewTrack(props: { navigation: any }) {
const { navigation } = props; const { navigation } = props;
const dispatch = useDispatch();
const [pickedDocument, setPickedDocument] = useState<DocumentPicker.DocumentResult | null>(null);
const [trackName, setTrackName] = useState('');
const [sessionName, setSessionName] = useState('');
const handlePickDocument = async () => {
try {
const result = await DocumentPicker.getDocumentAsync({});
if (result.type === 'success') {
setPickedDocument(result);
}
else if(result.type === 'cancel'){
console.log("AAA");
setPickedDocument(null);
}
} catch (err) {
console.log(err);
}
};
// var files = [
// {
// name: "file",
// filename: "file.jpg",
// filepath: pickedDocument.uri,
// filetype: "image/jpeg",
// },
// ];
// const handleConfirm = async () => {
// if (!pickedDocument || !trackName || !sessionName) {
// return;
// }
// const formData = new FormData();
// formData.append('file', {
// uri: pickedDocument.uri,
// type: pickedDocument.type,
// name: pickedDocument.name,
// });
// try {
// await dispatch(addXlsFile(formData, 'test_PILOTE', 'test@gmail.com', 'test123', sessionName, trackName, 'Training'));
// navigation.goBack();
// } catch (error) {
// console.log('Error - POST FILE', error);
// }
// };
// const handleConfirm = async () => {
// if (!pickedDocument || !trackName || !sessionName) {
// return;
// }
// try {
// const file = new File([await pickedDocument.uri], pickedDocument.name, { type: pickedDocument.type });
// const url = 'https://r-dash.azurewebsites.net/File?pseudoPilote=test_PILOTE&nameSession=weekend&nameCircuit=test_CIRCUIT&typeSession=Training';
// const options = {
// method: 'POST',
// body: file,
// headers: {
// 'Content-Type': 'application/octet-stream',
// },
// };
// await fetch(url, options);
// navigation.goBack();
// } catch (error) {
// console.log('Error - POST FILE', error);
// }
// };
// const handleConfirm = async () => {
// if (!pickedDocument || !trackName || !sessionName) {
// return;
// }
// try {
// const file = new File([await pickedDocument.uri], pickedDocument.name, { type: pickedDocument.type });
// const url = 'https://r-dash.azurewebsites.net/File?pseudoPilote=test_PILOTE&nameSession=weekend&nameCircuit=test_CIRCUIT&typeSession=Training';
// const options = {
// method: 'POST',
// body: file,
// headers: {
// 'Content-Type': 'application/octet-stream',
// },
// };
// const response = await fetch(url, options);
// const responseData = await response.text(); // or response.text() or response.blob() depending on the expected response type
// navigation.goBack();
// console.log(responseData);
// } catch (error) {
// console.log('Error - POST FILE', error);
// }
// };
const handleConfirm = async () => {
if (!pickedDocument || !trackName || !sessionName) {
return;
}
try {
//const file = new File([await pickedDocument.uri], pickedDocument.name, { type: pickedDocument.type });
const url = 'https://r-dash.azurewebsites.net/File?pseudoPilote=test_PILOTE&nameSession=test%20import&nameCircuit=test_CIRCUIT&typeSession=Training';
const formData = new FormData();
console.log(pickedDocument.type);
console.log(pickedDocument.uri);
formData.append('file',
{
name: pickedDocument.name,
type: "application/vnd.ms-excel",
uri : pickedDocument.uri,
});
const response = await fetch(url, {
method: 'POST',
body: formData,
headers: {
'accept':'*/*',
'Content-Type': 'multipart/form-data',
},
});
const data = await response.json();
console.log('API response:', data);
if (!response.ok) {
throw new Error( JSON.stringify(response) + 'Failed to upload file');
}
navigation.goBack();
} catch (error) {
console.log('Error - POST FILE', error);
}
};
return ( return (
<SafeAreaView> <SafeAreaView>
<View style={styles.container}> <View style={styles.container}>
{/* Header */} <View style={styles.topbar}>
<TopBar navigation={navigation} /> <View>
<TouchableOpacity style={styles.accountContainerButton}>
<View style={styles.ImageContainer}>
</View>
<Text style={styles.accountName}>Name</Text>
</TouchableOpacity>
</View>
<View style={styles.topbarRight}>
<View style={styles.iconContainer}>
<Image source={require('../assets/images/settings.png')} style={styles.accountSettings} />
</View>
<TouchableOpacity style={styles.accountContainerButton}>
<View style={styles.ImageContainer}>
<Image source={require('../assets/images/image.png')} style={styles.accountImage} />
</View>
</TouchableOpacity>
</View>
</View>
{/* Page */} {/* Page */}
<View style={{ alignItems: 'center', width: "100%", height: "80%", justifyContent: 'space-around' }}> <View style={{ alignItems: 'center', width: "100%", height: "80%", justifyContent: 'space-around' }}>
@ -152,8 +35,7 @@ export default function NewTrack(props: { navigation: any }) {
<Text style={{ paddingTop: 20 }}>Track name: </Text> <Text style={{ paddingTop: 20 }}>Track name: </Text>
<TextInput <TextInput
style={styles.textInput} style={styles.textInput}
onChangeText={setTrackName} secureTextEntry={true}
value={trackName}
placeholder="Track name" placeholder="Track name"
/> />
</View> </View>
@ -162,19 +44,18 @@ export default function NewTrack(props: { navigation: any }) {
<Text style={{ paddingTop: 20 }}>Session name: </Text> <Text style={{ paddingTop: 20 }}>Session name: </Text>
<TextInput <TextInput
style={styles.textInput} style={styles.textInput}
onChangeText={setSessionName} secureTextEntry={true}
value={sessionName}
placeholder="Session name" placeholder="Session name"
/> />
</View> </View>
<View style={styles.placement}> <View style={styles.placement}>
<Text style={{ paddingTop: 30 }}>Import file: </Text> <Text style={{ paddingTop: 30 }}>Import file: </Text>
<Pressable onPress={handlePickDocument}> <Pressable>
<Image style={styles.import} source={require('../assets/images/import.png')} /> <Image
<Text> style={styles.import}
Picked document: {pickedDocument ? pickedDocument.name : 'none'} source={require('../assets/images/import.png')}
</Text> />
</Pressable> </Pressable>
</View> </View>
@ -188,7 +69,7 @@ export default function NewTrack(props: { navigation: any }) {
source={require('../assets/images/return.png')} source={require('../assets/images/return.png')}
/> />
</Pressable> </Pressable>
<Pressable style={styles.button} onPress={handleConfirm}> <Pressable style={styles.button} onPress={() => navigation.goBack()}>
<Image <Image
style={styles.return} style={styles.return}
source={require('../assets/images/checked.png')} source={require('../assets/images/checked.png')}

@ -1,256 +0,0 @@
import { BackgroundImage } from '@rneui/base';
import { StyleSheet, Text, View, TouchableOpacity, ScrollView } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import MapView, { MapCallout, Marker } from 'react-native-maps';
import React from 'react';
import TopBar from '../components/TopBar';
import { Point } from '../core/Point';
export default function Lap(props: { navigation: any, route : any}) {
const { currentLap } = props.route.params;
const { navigation } = props;
const points: Point[] = currentLap.getPoints();
points.sort((pt1, pt2) => pt1.getTimer() - pt2.getTimer());
const [currentPointIndex, setCurrentPointIndex] = React.useState(0);
const currentPoint: Point | undefined = points[currentPointIndex];
const goToPreviousPoint = () => {
if (currentPointIndex > 0) {
setCurrentPointIndex(currentPointIndex - 1);
}
};
const goToNextPoint = () => {
if (currentPointIndex < points.length - 1) {
setCurrentPointIndex(currentPointIndex + 1);
}
};
const markers: { id: number; name: string; coordinate: { latitude: number; longitude: number }, image: HTMLImageElement }[] = points.map((pt, index) => {
var img;
const brake = pt.getPBreakF();
if(brake <= 0)
{
img = require("../assets/images/noBrake.png");
}else if(brake > 0 && brake <= 30){
img = require("../assets/images/startBrake.png");
}else if(brake > 0 && brake <= 100){
img = require("../assets/images/midBrake.png");
}else{
img = require("../assets/images/fullBrake.png");
}
return {
id: index,
name: pt.getDistance() + 'm',
coordinate: { latitude: pt.getGeo().getGpsLat(), longitude: pt.getGeo().getGpsLong() },
image: img,
};
});
const handleMarker = (index : number) => {
setCurrentPointIndex(index);
}
// currentLap.getPoints().forEach(pt => {
// points.push({ latitude: pt.getGeo().getGpsLat(), longitude: pt.getGeo().getGpsLong() });
// });
//var currentLap : undefined; // Penser à vérifier si la session ne possède pas de tour !! si c'est le cas afficher une popup d'erreur
return (
<SafeAreaView style={styles.container}>
<View style={styles.container}>
{/* Header */}
<TopBar navigation={navigation} />
{/* Body */}
<View style={styles.container}>
<View style={styles.top_lap}>
<TouchableOpacity style={[styles.LapBrowserButton, currentPointIndex === 0 ? styles.disabled : null]} onPress={goToPreviousPoint}>
<View>
<Text style={styles.button_text} >Previous Point</Text>
</View>
</TouchableOpacity>
<Text style={styles.text_title}>Point {currentPointIndex + 1 } </Text>
<TouchableOpacity style={[styles.LapBrowserButton, currentPointIndex === points.length - 1 ? styles.disabled : null]} onPress={goToNextPoint}>
<View>
<Text style={styles.button_text} >Next Point</Text>
</View>
</TouchableOpacity>
</View>
<View style={styles.containerBody}>
<MapView
style={styles.map}
mapType="satellite"
region={{
latitude: currentLap.getLocationLat(),
longitude: currentLap.getLocationLong(),
latitudeDelta: 0.001,
longitudeDelta: 0.015,
}}
>
{markers.map(({ id, name, coordinate,image }) => (
<Marker key={id} title={name} coordinate={coordinate} onPress={() => handleMarker(id)} icon={image} style={{ width: 1, height: 1 }} />
))}
</MapView>
<ScrollView style={ styles.scrollView}>
<BackgroundImage source={require('../assets/images/rdash.png')} resizeMode="contain" >
<View style={styles.container2}>
<Text style={styles.header}>Point { currentPointIndex + 1} / { points.length} of Lap {currentLap.getNumber()}</Text>
<View style={styles.infoContainer}>
<Text style={styles.infoItem}>Time:</Text>
<Text style={styles.infoValue}>{currentPoint.getFormattedTime()}</Text>
</View>
<View style={styles.infoContainer}>
<Text style={styles.infoItem}>Distance:</Text>
<Text style={styles.infoValue}>{currentPoint.getDistance()} m</Text>
</View>
<View style={styles.infoContainer}>
<Text style={styles.infoItem}>Speed (vCar):</Text>
<Text style={styles.infoValue}>{currentPoint.getVCar()} km/h</Text>
</View>
<View style={styles.infoContainer}>
<Text style={styles.infoItem}>nGear:</Text>
<Text style={styles.infoValue}>{currentPoint.getNGear()} gear</Text>
</View>
<View style={styles.infoContainer}>
<Text style={styles.infoItem}>pBreakF:</Text>
<Text style={styles.infoValue}>{currentPoint.getPBreakF()} bar</Text>
</View>
<View style={styles.infoContainer}>
<Text style={styles.infoItem}>aSteer:</Text>
<Text style={styles.infoValue}>{currentPoint.getASteer()} deg</Text>
</View>
<View style={styles.infoContainer}>
<Text style={styles.infoItem}>rPedal:</Text>
<Text style={styles.infoValue}>{currentPoint.getRPedal()} %</Text>
</View>
<View style={styles.infoContainer}>
<Text style={styles.infoItem}>gLong:</Text>
<Text style={styles.infoValue}>{currentPoint.getGLong()} g</Text>
</View>
<View style={styles.infoContainer}>
<Text style={styles.infoItem}>gLat:</Text>
<Text style={styles.infoValue}>{currentPoint.getGLat()} g</Text>
</View>
</View>
</BackgroundImage>
</ScrollView>
</View>
</View>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
scrollView: {
flex:1,
},
disabled: {
opacity: 0.5,
},
addContainerButton: {
margin:5,
alignItems: "center",
justifyContent: "center",
height: "8%",
borderRadius: 10,
elevation: 3,
backgroundColor: "#BF181F",
},
containerBody:{
flex: 1,
justifyContent: 'space-between',
alignItems: 'stretch',
},
container2: {
backgroundColor: 'rgba(255, 255, 255, 0.9)',
borderColor:'black',
borderWidth:2,
padding: 10,
borderRadius: 10,
marginBottom: 20,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
},
header: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 10,
},
infoContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 5,
},
infoItem: {
fontSize: 18,
fontWeight: 'bold',
},
infoValue: {
fontSize: 18,
},
map: {
flex:1,
},
top_lap: {
height: "8%",
flexDirection: 'row',
justifyContent: 'space-between',
},
backgroundImage: {
flex: 1,
width: '100%',
},
container: {
flex: 1,
},
LapBrowserButton: {
width: "30%",
marginTop:5,
marginBottom:5,
alignContent: 'center',
justifyContent: 'center',
borderRadius: 10,
backgroundColor: '#BF181F',
},
button_text: {
textAlign: 'center',
color: '#fff',
fontSize: 20,
},
text_title: {
fontSize: 30,
textAlign: 'center',
},
});

@ -1,7 +1,9 @@
import { useState } from 'react';
import React from 'react'; import React from 'react';
import { Pressable } from 'react-native'; import { Button, Pressable, Touchable } from 'react-native';
import { StyleSheet, Text, View, Image, TextInput } from 'react-native'; import { StyleSheet, Text, View, Image, TextInput } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context'; import { SafeAreaView } from 'react-native-safe-area-context';
import Navigation from '../navigation/Navigation';
export default function Register(props: { navigation: any }) { export default function Register(props: { navigation: any }) {
const { navigation } = props; const { navigation } = props;

@ -1,102 +1,91 @@
import { BackgroundImage, SearchBar } from "@rneui/base"; import { BackgroundImage } from '@rneui/base';
import React, { useEffect, useState } from "react"; import React from 'react';
import { import { FlatList, StyleSheet, Text, View, Image, TouchableOpacity, TouchableHighlight } from 'react-native';
FlatList, import TopBar from '../components/TopBar';
StyleSheet,
Text, export default function Session_browser(props: {navigation: any}) {
View, type ItemProps = { title: string };
TouchableOpacity, const { navigation } = props;
ActivityIndicator, const Item = ({title}: ItemProps) => (
} from "react-native"; <View style={styles.item}>
import { useDispatch, useSelector } from "react-redux"; <Text style={styles.title}>{title}</Text>
import SessionListItem from "../components/SessionCmp"; </View>
import TopBar from "../components/TopBar"; );
import { Session } from "../core/Session"; const DATA = [
import { getSessionsList } from "../redux/actions/sessions"; {
import { SESSIONS } from "../stub/stub"; id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
export default function Session_browser(props: { navigation: any }) { },
const { navigation } = props; {
const [search, setSearch] = useState(""); id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
const [loading, setLoading] = useState(false); title: 'Second Item',
},
const handlePress = (item: Session) => { {
setSearch(""); id: '58694a0f-3da1-471f-bd96-145571e29d71',
navigation.navigate("Lap", { "session" : item }); title: 'Third Item',
}; },
{
id: '58694a0f-3da1-471f-bd96-145571e29d78',
const sessions = useSelector(state => state.appReducer.sessions); title: 'c Item',
},
const dispatch = useDispatch(); {
useEffect(() => { id: '58694a0f-3da1-471f-bd96-145571e29d76',
setLoading(true); title: 'b Item',
const loadTeams = async () => { },
await dispatch(getSessionsList()); {
setLoading(false); id: '58694a0f-3da1-471f-bd96-145571e29d75',
}; title: 'a Item',
loadTeams(); },
}, [dispatch]); {
id: '58694a0f-3da1-471f-bd96-145571e29d73',
const filteredData = title: 's Item',
search !== "" },
? sessions.filter((item) => {
item.getName().toLowerCase().includes(search.toLowerCase()) id: '58694a0f-3da1-471f-bd96-145571e29d13',
) title: 's Item',
: sessions; },
];
return ( return (
<View style={styles.container}> <View style={styles.container}>
<View style={styles.container}> <View style={styles.container}>
{/* Header */} {/* Header */}
<TopBar navigation={navigation} /> <TopBar navigation={navigation} />
{/* Body */} {/* Body */}
<View style={styles.container}> <View style={styles.container}>
<BackgroundImage <BackgroundImage source={require('../assets/images/rdash.png')} resizeMode="contain" style={styles.backgroundImage}>
source={require("../assets/images/rdash.png")}
resizeMode="contain" <Text style={styles.text_title}>Sessions</Text>
style={styles.backgroundImage}
> <FlatList data={DATA} renderItem={({ item }) =>
<TouchableHighlight onPress={() => navigation.navigate('Lap', { "lap": item })}>
<Text style={styles.text_title}>Sessions</Text> <Item title={item.title} />
<SearchBar </TouchableHighlight>
platform="default" } keyExtractor={(Item) => Item.title} />
lightTheme
value={search} <TouchableOpacity style={styles.addContainerButton} onPress={() => navigation.navigate('Add')}>
onChangeText={setSearch} <View>
/> <Text style={styles.button_text} >Add a session</Text>
{loading ? ( </View>
<ActivityIndicator size="large" color="#BF181F" /> </TouchableOpacity>
) : (
<FlatList </BackgroundImage>
data={filteredData}
renderItem={({ item }) => ( </View>
<SessionListItem session={item} onPress={handlePress} />
)}
keyExtractor={(Item) => Item.getName()}
/>
)}
<TouchableOpacity
style={styles.addContainerButton}
onPress={() => navigation.navigate("Add")}
>
<View>
<Text style={styles.button_text}>Add a session</Text>
</View>
</TouchableOpacity>
</BackgroundImage>
</View> </View>
</View>
</View> </View>
); );
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
item: { item: {
borderRadius: 10, borderRadius:10,
opacity: 0.9, opacity:0.9,
backgroundColor: "#C5C5C5", backgroundColor: '#C5C5C5',
padding: 20, padding: 20,
marginVertical: 8, marginVertical: 8,
marginHorizontal: 16, marginHorizontal: 16,
@ -105,50 +94,51 @@ const styles = StyleSheet.create({
fontSize: 32, fontSize: 32,
}, },
backgroundImage: { backgroundImage: {
flex: 1, flex:1,
width: "100%", width:'100%',
}, },
container: { container: {
flex: 1, flex:1,
}, },
addImageContainer: { addImageContainer:{
backgroundColor: "#fff", backgroundColor: '#fff',
borderRadius: 50, borderRadius: 50,
width: 40, width: 40,
height: 40, height: 40,
overflow: "hidden", overflow: 'hidden',
alignItems: "center", alignItems:'center'
}, },
addContainerButton: { addContainerButton:{
margin: 10, margin:10,
alignItems: "center", alignItems:'center',
justifyContent: "center", justifyContent:'center',
height: "10%", height: "10%",
paddingVertical: 12, paddingVertical: 12,
paddingHorizontal: 32, paddingHorizontal: 32,
borderRadius: 10, borderRadius: 10,
elevation: 3, elevation: 3,
backgroundColor: "#BF181F", backgroundColor: '#BF181F',
}, },
button_text: { button_text: {
color: "#fff", color:'#fff',
fontSize: 20, fontSize:20,
}, },
text_title: { text_title: {
fontWeight: "bold", fontWeight: 'bold',
fontSize: 30, fontSize: 30,
textAlign: "center", textAlign:'center',
padding: 10, padding:10,
textShadowColor: "#fff", textShadowColor: '#fff',
textShadowOffset: { width: 0, height: 0 }, textShadowOffset: { width: 0, height: 0 },
textShadowRadius: 10, textShadowRadius: 10,
}, },
topbar: {
height: '10%',
}
topbar: {
height: "10%",
},
}); });

@ -1,39 +1,49 @@
import { FlatList, StyleSheet, Text, View } from 'react-native'; import { Button, FlatList, Pressable, StyleSheet, Text, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context'; import { SafeAreaView } from 'react-native-safe-area-context';
import { SearchBar } from '@rneui/base'; import { SearchBar } from '@rneui/base';
import React, { useState, useEffect } from 'react'; import { TouchableHighlight } from 'react-native-gesture-handler';
import { TEAMS } from '../stub/stub'; import React from 'react';
import TeamListItem from '../components/TeamCmp';
import { Team } from '../core/Team';
import { useDispatch, useSelector } from 'react-redux';
import { getTeamsList } from "../redux/actions/teams";
export default function Team_Browser(props: { navigation: any }) { export default function Team_Browser(props: { navigation: any }) {
const { navigation } = props; const { navigation } = props;
const [search, setSearch] = useState(''); type ItemProps = { title: string };
const Item = ({title}: ItemProps) => (
const handlePress = (item: Team) => { <View style={styles.item}>
setSearch(''); <Text style={styles.title}>{title}</Text>
navigation.navigate('Info', { "": item }); // A revoir </View>
}; );
const DATA = [
const filteredData = search !== '' ? TEAMS.filter((item) => {
item.getName().toLowerCase().includes(search.toLowerCase()) id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
) : TEAMS; title: 'First Item',
},
const nList = useSelector(state => state.appReducer.teams); {
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
const dispatch = useDispatch(); title: 'Second Item',
},
useEffect(() => { {
const loadTeams = async () => { id: '58694a0f-3da1-471f-bd96-145571e29d71',
await dispatch(getTeamsList()); title: 'Third Item',
}; },
loadTeams(); {
}, [dispatch]); id: '58694a0f-3da1-471f-bd96-145571e29d78',
title: 'c Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d76',
title: 'b Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d75',
title: 'a Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d73',
title: 's Item',
},
];
return ( return (
<SafeAreaView style={styles.container}> <SafeAreaView style={styles.container}>
<View style={styles.card}> <View style={styles.card}>
@ -41,12 +51,12 @@ export default function Team_Browser(props: { navigation: any }) {
<SearchBar <SearchBar
platform="default" platform="default"
lightTheme lightTheme
value={search}
onChangeText={setSearch}
/> />
<FlatList <FlatList data={DATA} renderItem={({ item }) =>
data={nList} <TouchableHighlight onPress={() => navigation.navigate('Info', { "team": item })}>
renderItem={({ item }) => <TeamListItem team={item} onPress={handlePress}/>} /> <Item title={item.title} />
</TouchableHighlight>
}/>
</View> </View>
</SafeAreaView> </SafeAreaView>

@ -1,5 +1,6 @@
import React from 'react'; import React from 'react';
import { Pressable, StyleSheet, Text, View } from 'react-native'; import { Button, Pressable, StyleSheet, Text, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import TopBar from '../components/TopBar'; import TopBar from '../components/TopBar';
export default function Team_Selection(props: { navigation: any }) { export default function Team_Selection(props: { navigation: any }) {

@ -1,53 +0,0 @@
import { Geocalisation } from "../core/Geocalisation";
import { Lap } from "../core/Lap";
import { Member } from "../core/Member";
import { Owner } from "../core/Owner";
import { Point } from "../core/Point";
import { Session } from "../core/Session";
import { SessionType } from "../core/SessionType";
import { Team } from "../core/Team";
import { User } from "../core/User";
import { WaitingMember } from "../core/WaitingMember";
const owner1 = new Owner("eric","PASSWORD123","eric@gmail.com",[]);
const owner2 = new Owner("castor","PASSWORD123","castor@gmail.com",[]);
export const USERS1 : User[] = [
new Member("jean","PASSWORD123","jean@gmail.com",[]),
new WaitingMember("anas","PASSWORD123","anas@gmail.com",[]),
]
export const USERS2 : User[] = [
new Member("stickman","PASSWORD123","stickman@gmail.com",[]),
new Member("crapaud","PASSWORD123","crapaud@gmail.com",[]),
new WaitingMember("mcdo","PASSWORD123","mcdo@gmail.com",[]),
new WaitingMember("bucheron","PASSWORD123","bucheron@gmail.com",[]),
]
export const TEAMS : Team[] = [
new Team("La team 1",owner1, USERS1),
new Team("Bat INFO",owner2,USERS2)
]
const geo1 = new Geocalisation(40.7128, -74.0060);
const geo2 = new Geocalisation(51.5074, -0.1278);
const geo3 = new Geocalisation(35.6895, 139.6917);
const point1 = new Point(geo1, 120, 10, 3, 50, 90, 20, 10, 20, 100);
const point2 = new Point(geo2, 130, 15, 4, 60, 100, 30, 15, 25, 120);
const point3 = new Point(geo3, 140, 20, 5, 70, 110, 40, 20, 30, 140);
const lap1 = new Lap(1, [point1, point2], 250);
const lap2 = new Lap(2, [point2, point3], 300);
const lap3 = new Lap(3, [point3, point1], 350);
const session1 = new Session("First Session", [lap1, lap2], SessionType.PrivateTest);
const session2 = new Session("Second Session", [lap2, lap3], SessionType.Qualification);
const session3 = new Session("Third Session", [lap3, lap1], SessionType.Unknown);
export const SESSIONS : Session[] = [
session1,session2,session3
]
Loading…
Cancel
Save