diff --git a/.env.dev b/.env.dev
deleted file mode 100644
index 6aceb95..0000000
--- a/.env.dev
+++ /dev/null
@@ -1,2 +0,0 @@
-API_URL="http://smtp-dev-env.eba-5jqrxjhz.eu-west-3.elasticbeanstalk.com/"
-VERSION="development"
diff --git a/.gitignore b/.gitignore
index 8d96fd9..fd0add4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -283,3 +283,9 @@ buck-out/
web-build/
android/java_pid13560.hprof
android/java_pid22412.hprof
+.idea/smtp-pi.iml
+
+# environment variable
+.env.dev
+.env.local
+.env.prod
diff --git a/.idea/smtp-pi.iml b/.idea/smtp-pi.iml
index c0ca3af..986b696 100644
--- a/.idea/smtp-pi.iml
+++ b/.idea/smtp-pi.iml
@@ -18,7 +18,7 @@
-
+
\ No newline at end of file
diff --git a/App.js b/App.js
index f644b03..5c447bc 100644
--- a/App.js
+++ b/App.js
@@ -8,7 +8,6 @@ import { createStackNavigator } from '@react-navigation/stack';
import Login from './components/Login';
import Chart from "./components/Chart";
import MapAdmin from './components/Map/MapAdmin';
-import SetGPSLocation from "./components/Place/SetGPSLocation";
import MapTruck from './components/Map/MapTruck';
import BottomTabNavigator from './navigation/BottomTabNavigator';
import useLinking from './navigation/useLinking';
@@ -17,6 +16,7 @@ import TruckScreen from "./screens/Truck/TruckScreen";
import CraneScreen from "./screens/Crane/CraneScreen";
import { navigationRef } from './navigation/RootNavigation';
import LogoutButton from "./components/LogoutButton";
+import BottomTabTruckNavigator from "./navigation/BottomTabTruckNavigator";
const Stack = createStackNavigator();
@@ -64,7 +64,7 @@ export default function App(props) {
-
+
diff --git a/Style.js b/Style.js
index cfe0507..d6d9931 100644
--- a/Style.js
+++ b/Style.js
@@ -1,3 +1,8 @@
+import { Dimensions} from "react-native";
+
+const { width, height } = Dimensions.get("window");
+const CARD_HEIGHT = 220;
+const CARD_WIDTH = width * 0.8;
export default {
container:{
@@ -8,10 +13,11 @@ export default {
containerForm:{
alignItems: 'center',
},
-
+ progressBar:{
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
input : {
- height : 40 ,
- padding : 10,
borderColor: 'gray',
borderWidth:1 ,
marginHorizontal : 5
@@ -48,18 +54,17 @@ export default {
},
previewPlace : {
+ borderWidth:1,
backgroundColor : '#FFFFFF',
- borderBottomColor : '#202340',
- marginTop : 30,
- height : 37,
- flex : 1,
+ borderColor : '#aaa5a5',
+ height : 50,
+ marginHorizontal : 15,
flexDirection : 'row',
- justifyContent : 'space-between',
alignItems: 'center',
},
rightWorksite : {
color : '#FFF',
- fontweight : 'bold',
+ fontWeight : 'bold',
fontSize : 22
},
button : {
@@ -101,6 +106,17 @@ export default {
color: 'rgba(96,100,109, 1)',
lineHeight: 24,
textAlign: 'center',
+ justifyContent : 'center'
+ },
+
+ previewText: {
+ flex : 2,
+ paddingVertical : 50,
+ fontSize: 17,
+ color: 'rgba(96,100,109, 1)',
+ lineHeight: 24,
+ textAlign: 'center',
+ justifyContent : 'center'
},
textinput : {
alignSelf: 'stretch',
@@ -113,4 +129,87 @@ export default {
marginBottom: 15,
},
+ cardFuel: {
+ flexDirection : "row",
+ position : "absolute",
+ backgroundColor: "#FFF",
+ borderRadius : 5,
+ marginHorizontal: 10,
+ shadowColor: "#000",
+ shadowRadius: 5,
+ shadowOpacity: 0.3,
+ bottom: 200,
+ left: width*0.14,
+ right: 0,
+ height: CARD_HEIGHT*1.9,
+ width: CARD_WIDTH*0.85,
+ overflow: "hidden",
+ },
+
+ // Marker Custom
+ bubble : {
+ flexDirection : 'column',
+ alignSelf: "flex-start",
+ backgroundColor : '#fff',
+ borderColor: "#cccccc",
+ width: 150,
+ },
+
+ arrow: {
+ backgroundColor: "transparent",
+ borderColor : "transparent",
+ borderTopColor : "#fff",
+ borderWidth: 16,
+ alignSelf: 'center',
+ marginTop : -32,
+ },
+
+ arrowBorder: {
+ backgroundColor: "transparent",
+ borderColor : "transparent",
+ borderTopColor : "#007a87",
+ borderWidth: 16,
+ alignSelf: 'center',
+ marginTop : -0.5,
+ },
+
+ name : {
+ fontSize: 16,
+ marginBottom: 5,
+ },
+
+ card: {
+ flexDirection : "row",
+ position : "absolute",
+ backgroundColor: "#FFF",
+ borderRadius : 5,
+ marginHorizontal: 10,
+ shadowColor: "#000",
+ shadowRadius: 5,
+ shadowOpacity: 0.3,
+ bottom: 5,
+ left: width*0.07,
+ right: 0,
+ height: CARD_HEIGHT,
+ width: CARD_WIDTH,
+ overflow: "hidden",
+ },
+ timePicker : {
+ flexDirection : "column",
+ width: CARD_WIDTH*0.66,
+
+ },
+ textContent: {
+ flex: 2,
+ padding: 10,
+ },
+ cardTitle: {
+ fontSize: 12,
+ fontWeight: "bold",
+ },
+ cardDescription: {
+ fontSize: 12,
+ paddingVertical:5,
+ color: "#444",
+ },
}
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 79ab137..7f65467 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -142,8 +142,8 @@ android {
applicationId 'com.smtp.smtp'
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
- versionCode 13
- versionName "1.0.13"
+ versionCode 17
+ versionName "1.0.17"
resValue "string", "build_config_package", "com.smtp.smtp"
}
splits {
@@ -201,7 +201,8 @@ android {
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "com.facebook.react:react-native:+"
- implementation 'androidx.coordinatorlayout:coordinatorlayout:1.1.0'// From node_modules
+ implementation 'androidx.coordinatorlayout:coordinatorlayout:1.1.0'
+ implementation 'junit:junit:4.12'// From node_modules
addUnimodulesDependencies()
implementation 'com.google.android.material:material:1.0.0'
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 96a8991..afc2d1d 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -40,12 +40,8 @@
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true"
android:largeHeap="true">
-
-
+
@@ -85,9 +81,9 @@
-
+
gettingLocation = this.fusedLocationClient.getLastLocation();
- while(!gettingLocation.isSuccessful()) {}
- location = gettingLocation.getResult();
-
- //save location in coordinates JSON Object
- coordinates = new JSONObject();
- try {
- coordinates.put("longitude", location.getLongitude());
- coordinates.put("latitude", location.getLatitude());
- sendCoordinates();
- Log.e(TAG, "send coordinates :" + location.getLatitude());
- Thread.sleep(10000);
- } catch (JSONException | InterruptedException e) {
- Log.e(TAG, e.getMessage());
- }
-
- */
- }
- }
-
- // stop thread
- public void stop() {
- running = false;
- reprendre();
- }
-
- // pause thread
- public void pause() {
- Log.d(TAG, "thread paused");
- paused = true;
- }
-
- // resume thread
- public void reprendre() {
- Log.d(TAG, "thread resume");
- synchronized (pauseLock) {
- paused = false;
- pauseLock.notifyAll();
- }
- }
-
- // to send coordinates
- private void sendCoordinates() {
- JSONObject obj = new JSONObject();
- try {
- obj.put("coordinates", coordinates);
- obj.put("etat", "pause");
- obj.put("ETA", 0);
- } catch (JSONException e) {
- Log.e(TAG, e.getMessage());
- return;
- }
- this.mSocket.emit("chantier/sendCoordinates", obj);
- }
-}
diff --git a/android/app/src/main/java/com/smtp/smtp/Sortie.java b/android/app/src/main/java/com/smtp/smtp/Sortie.java
new file mode 100644
index 0000000..4e0ec67
--- /dev/null
+++ b/android/app/src/main/java/com/smtp/smtp/Sortie.java
@@ -0,0 +1,220 @@
+package com.smtp.smtp;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.android.volley.AuthFailureError;
+import com.android.volley.NetworkResponse;
+import com.android.volley.Request;
+import com.android.volley.Response;
+import com.android.volley.VolleyError;
+import com.android.volley.VolleyLog;
+import com.android.volley.toolbox.HttpHeaderParser;
+import com.android.volley.toolbox.StringRequest;
+import com.smtp.smtp.http.RequestManager;
+
+import org.json.JSONObject;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+public class Sortie extends AppCompatActivity {
+ private static final String BASE_URL = "http://smtp-dev-env.eba-5jqrxjhz.eu-west-3.elasticbeanstalk.com/";
+ String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImJiYTg0YmM3LTlmNDMtNDAxZS04ZjAyLTQ3ZTAyZDc4NDQ2OCIsInJvbGUiOiJhZG1pbiIsImlhdCI6MTU4NzQxODQ0MX0.zRTuqPl0UbiwJn7zZSxErvBYhkhPibEZ51S4Aqgd6LI";
+ private String sortieId;
+ private long dateDebut;
+ private long dateFin;
+ private String chantierId;
+ private String typeRoute;
+ private String camionneurId;
+ private Context ctx;
+ private int ordre = 0;
+
+ public Sortie(String chantierId, String camionneurId, String typeRoute, Context context){
+ this.sortieId = UUID.randomUUID().toString();
+ this.dateDebut = System.currentTimeMillis();
+ this.chantierId = chantierId;
+ this.typeRoute = typeRoute;
+ this.camionneurId = camionneurId;
+ ctx = context;
+ sendDebutSortie();
+ }
+
+ public void addWaypoint(Double lon, Double lat){
+ Map send = new HashMap<>();
+ send.put("id", UUID.randomUUID().toString());
+ send.put("longitude",lon);
+ send.put("latitude",lat);
+ send.put("SortieId",this.sortieId);
+ send.put("ordre",this.ordre);
+ JSONObject sortie = new JSONObject(send);
+ ordre++;
+ final String requestBody = sortie.toString();
+ final String URL = BASE_URL+"sorties/point";
+ Log.d("Sortie", requestBody);
+
+ StringRequest stringRequest = new StringRequest(Request.Method.POST, URL, new Response.Listener() {
+ @Override
+ public void onResponse(String response) {
+ Log.d("Sortie", response);
+ }
+ }, new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError error) {
+ Log.e("Sortie", error.toString());
+ }
+ }) {
+ //This is for Headers If You Needed
+ @Override
+ public Map getHeaders() throws AuthFailureError {
+ Map params = new HashMap();
+ params.put("Content-Type", "application/json; charset=UTF-8");
+ params.put("Authorization", "Bearer " + token);
+ return params;
+ }
+
+ @Override
+ public byte[] getBody() throws AuthFailureError {
+ try {
+ return requestBody == null ? null : requestBody.getBytes("utf-8");
+ } catch (UnsupportedEncodingException uee) {
+ VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
+ return null;
+ }
+ }
+
+ @Override
+ protected Response parseNetworkResponse(NetworkResponse response) {
+ String responseString = "";
+ if (response != null) {
+ responseString = String.valueOf(response.statusCode);
+ // can get more details such as response.headers
+ }
+ return Response.success(responseString, HttpHeaderParser.parseCacheHeaders(response));
+ }
+ };
+ RequestManager.getInstance(ctx).addToRequestQueue(stringRequest);
+}
+
+ public void sendDebutSortie(){
+ Map send = new HashMap<>();
+ send.put("ouvert",0);
+ send.put("dateDebut",this.dateDebut);
+ send.put("id",this.sortieId);
+ send.put("ChantierId",this.chantierId);
+ send.put("CamionneurId",this.camionneurId);
+ send.put("type",this.typeRoute);
+ JSONObject sortie = new JSONObject(send);
+
+ final String requestBody = sortie.toString();
+ final String URL = BASE_URL+"sorties";
+
+ Log.d("Sortie", requestBody);
+
+ StringRequest stringRequest = new StringRequest(Request.Method.POST, URL, new Response.Listener() {
+ @Override
+ public void onResponse(String response) {
+ Log.d("Sortie", response);
+ }
+ }, new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError error) {
+ Log.e("Sortie", error.toString());
+ }
+ }) {
+ //This is for Headers If You Needed
+ @Override
+ public Map getHeaders() throws AuthFailureError {
+ Map params = new HashMap();
+ params.put("Content-Type", "application/json; charset=UTF-8");
+ params.put("Authorization", "Bearer " + token);
+ return params;
+ }
+
+ @Override
+ public byte[] getBody() throws AuthFailureError {
+ try {
+ return requestBody == null ? null : requestBody.getBytes("utf-8");
+ } catch (UnsupportedEncodingException uee) {
+ VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
+ return null;
+ }
+ }
+
+ @Override
+ protected Response parseNetworkResponse(NetworkResponse response) {
+ String responseString = "";
+ if (response != null) {
+ responseString = String.valueOf(response.statusCode);
+ // can get more details such as response.headers
+ }
+ return Response.success(responseString, HttpHeaderParser.parseCacheHeaders(response));
+ }
+ };
+ RequestManager.getInstance(ctx).addToRequestQueue(stringRequest);
+ }
+
+ public void sendFinSortie(){
+ Map send = new HashMap<>();
+
+ send.put("dateFin",System.currentTimeMillis());
+ JSONObject sortie = new JSONObject(send);
+
+ final String requestBody = sortie.toString();
+ final String URL = BASE_URL+"sorties/"+sortieId;
+
+ Log.d("Sortie", requestBody);
+
+ StringRequest stringRequest = new StringRequest(Request.Method.PATCH, URL, new Response.Listener() {
+ @Override
+ public void onResponse(String response) {
+ Log.d("Sortie", response);
+ }
+ }, new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError error) {
+ Log.e("Sortie", error.toString());
+ }
+ }) {
+ //This is for Headers If You Needed
+ @Override
+ public Map getHeaders() throws AuthFailureError {
+ Map params = new HashMap();
+ params.put("Content-Type", "application/json; charset=UTF-8");
+ params.put("Authorization", "Bearer " + token);
+ return params;
+ }
+
+ @Override
+ public byte[] getBody() throws AuthFailureError {
+ try {
+ return requestBody == null ? null : requestBody.getBytes("utf-8");
+ } catch (UnsupportedEncodingException uee) {
+ VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
+ return null;
+ }
+ }
+
+ @Override
+ protected Response parseNetworkResponse(NetworkResponse response) {
+ String responseString = "";
+ if (response != null) {
+ responseString = String.valueOf(response.statusCode);
+ // can get more details such as response.headers
+ }
+ return Response.success(responseString, HttpHeaderParser.parseCacheHeaders(response));
+ }
+ };
+ RequestManager.getInstance(ctx).addToRequestQueue(stringRequest);;
+ }
+
+ public String getSortieId() {
+ return sortieId;
+ }
+}
diff --git a/android/app/src/main/java/com/smtp/smtp/http/CoefJSONAsyncRequest.java b/android/app/src/main/java/com/smtp/smtp/http/CoefJSONAsyncRequest.java
new file mode 100644
index 0000000..adccc08
--- /dev/null
+++ b/android/app/src/main/java/com/smtp/smtp/http/CoefJSONAsyncRequest.java
@@ -0,0 +1,64 @@
+package com.smtp.smtp.http;
+
+import android.content.Context;
+
+import com.smtp.smtp.http.JSONAsyncRequest;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.HashMap;
+import java.util.function.Consumer;
+
+public class CoefJSONAsyncRequest extends JSONAsyncRequest {
+ private Double value;
+ private String chantierId;
+ private String typeRoute;
+ private String day;
+ private Consumer callback;
+ public CoefJSONAsyncRequest(Context ctx, String token) {
+ super(ctx, token);
+ }
+
+ @Override
+ protected String getTag() {
+ return "CoefAsyncRequest";
+ }
+
+ @Override
+ protected String getURL() {
+ return BASE_URL + "chantiers/" + chantierId + "/route/" + typeRoute + "/coefs";
+ }
+
+ @Override
+ protected void onGetResponse(JSONObject response) {
+ try {
+ JSONObject route = response.getJSONObject(typeRoute);
+ JSONArray jours = route.getJSONArray("JourSemaines");
+ for(int i=0; i requestArgs, Consumer callback){
+ this.callback = callback;
+ this.chantierId = requestArgs.get("chantierId");
+ this.typeRoute = requestArgs.get("typeRoute");
+ this.day = requestArgs.get("day");
+ super.get();
+ }
+}
diff --git a/android/app/src/main/java/com/smtp/smtp/http/JSONAsyncRequest.java b/android/app/src/main/java/com/smtp/smtp/http/JSONAsyncRequest.java
new file mode 100644
index 0000000..b149460
--- /dev/null
+++ b/android/app/src/main/java/com/smtp/smtp/http/JSONAsyncRequest.java
@@ -0,0 +1,49 @@
+package com.smtp.smtp.http;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.android.volley.Request;
+import com.android.volley.toolbox.JsonObjectRequest;
+
+import org.json.JSONObject;
+
+import java.util.HashMap;
+
+import java.util.Map;
+
+public abstract class JSONAsyncRequest {
+ protected Context ctx;
+ protected final String BASE_URL = "http://smtp-dev-env.eba-5jqrxjhz.eu-west-3.elasticbeanstalk.com/";
+ protected String token;
+ protected JSONAsyncRequest(Context ctx, String token){
+ this.ctx = ctx;
+ this.token = token;
+ }
+
+ protected void get() {
+ JsonObjectRequest getRequest = new JsonObjectRequest(Request.Method.GET, getURL(), null,
+ response -> {
+ Log.d(getTag(), response.toString());
+ onGetResponse(response);
+ },
+ error -> {
+ Log.e(getTag(), error.getMessage());
+ onError();
+ }
+ ) {
+ @Override
+ public Map getHeaders() {
+ Map params = new HashMap();
+ params.put("Content-Type", "application/json; charset=UTF-8");
+ params.put("Authorization", "Bearer " + token);
+ return params;
+ }
+ };
+ RequestManager.getInstance(ctx).addToRequestQueue(getRequest);
+ }
+ protected abstract String getTag();
+ protected abstract String getURL();
+ protected abstract void onGetResponse(JSONObject response);
+ protected abstract void onError();
+}
diff --git a/android/app/src/main/java/com/smtp/smtp/RequestManager.java b/android/app/src/main/java/com/smtp/smtp/http/RequestManager.java
similarity index 97%
rename from android/app/src/main/java/com/smtp/smtp/RequestManager.java
rename to android/app/src/main/java/com/smtp/smtp/http/RequestManager.java
index 4901265..7f60dbe 100644
--- a/android/app/src/main/java/com/smtp/smtp/RequestManager.java
+++ b/android/app/src/main/java/com/smtp/smtp/http/RequestManager.java
@@ -1,4 +1,4 @@
-package com.smtp.smtp;
+package com.smtp.smtp.http;
import android.content.Context;
diff --git a/android/app/src/main/java/com/smtp/smtp/navigation/AndroidLoggingHandler.java b/android/app/src/main/java/com/smtp/smtp/navigation/AndroidLoggingHandler.java
new file mode 100644
index 0000000..47554b7
--- /dev/null
+++ b/android/app/src/main/java/com/smtp/smtp/navigation/AndroidLoggingHandler.java
@@ -0,0 +1,60 @@
+package com.smtp.smtp.navigation;
+
+import android.util.Log;
+import java.util.logging.*;
+
+/**
+ * Make JUL work on Android.
+ */
+public class AndroidLoggingHandler extends Handler {
+
+ public static void reset(Handler rootHandler) {
+ Logger rootLogger = LogManager.getLogManager().getLogger("");
+ Handler[] handlers = rootLogger.getHandlers();
+ for (Handler handler : handlers) {
+ rootLogger.removeHandler(handler);
+ }
+ LogManager.getLogManager().getLogger("").addHandler(rootHandler);
+ }
+
+ @Override
+ public void close() {
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public void publish(LogRecord record) {
+ if (!super.isLoggable(record))
+ return;
+
+ String name = record.getLoggerName();
+ int maxLength = 30;
+ String tag = name.length() > maxLength ? name.substring(name.length() - maxLength) : name;
+
+ try {
+ int level = getAndroidLevel(record.getLevel());
+ Log.println(level, tag, record.getMessage());
+ if (record.getThrown() != null) {
+ Log.println(level, tag, Log.getStackTraceString(record.getThrown()));
+ }
+ } catch (RuntimeException e) {
+ Log.e("AndroidLoggingHandler", "Error logging message.", e);
+ }
+ }
+
+ static int getAndroidLevel(Level level) {
+ int value = level.intValue();
+ if (value >= 1000) {
+ return Log.ERROR;
+ } else if (value >= 900) {
+ return Log.WARN;
+ } else if (value >= 800) {
+ return Log.INFO;
+ } else {
+ return Log.DEBUG;
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/java/com/smtp/smtp/CustomUEH.java b/android/app/src/main/java/com/smtp/smtp/navigation/CustomUEH.java
similarity index 93%
rename from android/app/src/main/java/com/smtp/smtp/CustomUEH.java
rename to android/app/src/main/java/com/smtp/smtp/navigation/CustomUEH.java
index 3054a52..dc04605 100644
--- a/android/app/src/main/java/com/smtp/smtp/CustomUEH.java
+++ b/android/app/src/main/java/com/smtp/smtp/navigation/CustomUEH.java
@@ -1,4 +1,4 @@
-package com.smtp.smtp;
+package com.smtp.smtp.navigation;
import android.util.Log;
diff --git a/android/app/src/main/java/com/smtp/smtp/navigation/Cycle.java b/android/app/src/main/java/com/smtp/smtp/navigation/Cycle.java
new file mode 100644
index 0000000..e5a834c
--- /dev/null
+++ b/android/app/src/main/java/com/smtp/smtp/navigation/Cycle.java
@@ -0,0 +1,178 @@
+package com.smtp.smtp.navigation;
+
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class Cycle implements Cloneable, Comparable {
+ private ArrayList users;
+ private int myIndice;
+ private String myUserId;
+ private String myEtat;
+
+ public Cycle(String myUserId, String myEtat) {
+ this.users = new ArrayList<>();
+ this.myUserId = myUserId;
+ this.myEtat = myEtat;
+ }
+
+ public void clear(){
+ this.users.clear();
+ }
+
+ public int addUser(User user) {
+ if (sameEtat(user) && !isContainedUser(user.getUserId())) {
+ users.add(user);
+ Collections.sort(users, new EtaSorter());
+ return 1;
+ } else {
+ return -1;
+ }
+ }
+
+ public boolean isContainedUser(String userId) {
+ boolean res = false;
+ for (int i = 0; i < users.size(); i++) {
+ if (users.get(i).getUserId().equals(userId)) {
+ res = true;
+ }
+ }
+ return res;
+ }
+ public boolean isMyUserId(String userId) {
+ return userId.equals(myUserId);
+ }
+ public void updateMyIndice(String userId) {
+ for (int i = 0; i < users.size(); i++) {
+ if (isMyUserId(users.get(i).getUserId())) {
+ myIndice = i;
+ Log.d(Navigation.TAG, "changement indice : " + myIndice);
+ }
+ }
+ }
+
+ public boolean sameEtat(User user) {
+ return user.getEtat().equals(myEtat);
+ }
+
+ public void updateCycle(User user) {
+ if (!sameEtat(user)) {
+ this.deleteUser(user.getUserId());
+ } else {
+ updateUserETA(user);
+ }
+ Collections.sort(users, new EtaSorter());
+ }
+
+ private void updateUserETA(User user) {
+ int uIndex = getUsers().indexOf(user);
+ if(uIndex == -1) {
+ throw new UserNotInCycleException("Cannot update user ETA that is not in cycle");
+ }
+ getUsers().get(uIndex).setETA(user.getETA());
+ }
+
+ public User getUserAhead(){
+ if(getMyIndice() == 0) {
+ throw new NoUserAheadException("Cannot get user ahead when I'm first");
+ }
+ return users.get(getMyIndice() -1);
+ }
+
+ public int getMyIndice() {
+ int res = -1;
+ for (int i = 0; i < users.size(); i++) {
+ if (isMyUserId(users.get(i).getUserId())) {
+ res = i;
+ Log.d(Navigation.TAG, "changement indice : " + myIndice);
+ }
+ }
+ if(res == -1 ) {
+ throw new RuntimeException("User not in the cycle");
+ }
+ return res;
+ }
+
+ public void deleteUser(String userId) {
+ int res = -1;
+ for (int i = 0; i < users.size(); i++) {
+ if (users.get(i).getUserId().equals(userId)) {
+ res = i;
+ }
+ }
+ users.remove(res);
+ Collections.sort(users, new EtaSorter());
+ }
+
+ @Override
+ protected Cycle clone() throws CloneNotSupportedException {
+ Cycle clone = new Cycle(myUserId, myEtat);
+ clone.setUsers(new ArrayList<>(getUsers()));
+ return clone;
+ }
+
+ public Cycle cloneMe() throws CloneNotSupportedException {
+ return clone();
+ }
+
+ public void setUsers(ArrayList users) {
+ this.users = users;
+ }
+
+ public List getUsers() {
+ return this.users;
+ }
+
+ public void setMyEtat(String etat) {
+ this.myEtat = etat;
+ }
+
+ public String getMyEtat() {
+ return this.myEtat;
+ }
+
+ public boolean someOneIsAheadMe(){
+ return getMyIndice() > 0;
+ }
+
+ @Override
+ public int compareTo(Object o) {
+ Cycle c = (Cycle)o;
+ if(c.getUsers().containsAll(getUsers())
+ && c.getUsers().size() == getUsers().size()) {
+ return 0;
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ return compareTo(obj) == 0;
+ }
+
+ class EtaSorter implements Comparator {
+ @Override
+ public int compare(User o1, User o2) {
+ return (int) (o1.getETA() - o2.getETA());
+ }
+ }
+
+ private class UserNotInCycleException extends RuntimeException {
+ public UserNotInCycleException(String msg) {
+ super(msg);
+ }
+ }
+
+ private class NoUserAheadException extends RuntimeException {
+ public NoUserAheadException(String msg) {
+ super(msg);
+ }
+ };
+
+
+}
diff --git a/android/app/src/main/java/com/smtp/smtp/navigation/CycleManager.java b/android/app/src/main/java/com/smtp/smtp/navigation/CycleManager.java
new file mode 100644
index 0000000..8c298b7
--- /dev/null
+++ b/android/app/src/main/java/com/smtp/smtp/navigation/CycleManager.java
@@ -0,0 +1,46 @@
+package com.smtp.smtp.navigation;
+
+public class CycleManager extends Thread {
+ private final String TAG = "CycleManager";
+ Runnable callback;
+ Cycle cycle;
+ Cycle previousCycle;
+ boolean newRouteHasBeenFetched;
+ public CycleManager(Runnable callback, Cycle cycle){
+ super("CycleManager");
+ this.callback = callback;
+ this.cycle = cycle;
+ newRouteHasBeenFetched = false;
+ try {
+ this.previousCycle = cycle.cloneMe();
+ } catch (Exception e) {
+ throw new RuntimeException("Cannot clone cycle");
+ }
+
+ }
+
+ private boolean newCycleIsDifferentThanPrevious() {
+ return !previousCycle.equals(cycle);
+ }
+
+ public boolean newRouteHasBeenFetched() {
+ return newRouteHasBeenFetched;
+ }
+
+ @Override
+ public void run() {
+ while(true){
+ try {
+ if(newCycleIsDifferentThanPrevious()){
+ newRouteHasBeenFetched = true;
+ this.callback.run();
+ previousCycle = cycle.cloneMe();
+ }
+ Thread.sleep(5000);
+ newRouteHasBeenFetched = false;
+ } catch (InterruptedException | CloneNotSupportedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/android/app/src/main/java/com/smtp/smtp/navigation/Etape.java b/android/app/src/main/java/com/smtp/smtp/navigation/Etape.java
new file mode 100644
index 0000000..5601084
--- /dev/null
+++ b/android/app/src/main/java/com/smtp/smtp/navigation/Etape.java
@@ -0,0 +1,289 @@
+package com.smtp.smtp.navigation;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.android.volley.AuthFailureError;
+import com.android.volley.Cache;
+import com.android.volley.Network;
+import com.android.volley.NetworkResponse;
+import com.android.volley.Request;
+import com.android.volley.RequestQueue;
+import com.android.volley.Response;
+import com.android.volley.VolleyError;
+import com.android.volley.VolleyLog;
+import com.android.volley.toolbox.BasicNetwork;
+import com.android.volley.toolbox.DiskBasedCache;
+import com.android.volley.toolbox.HttpHeaderParser;
+import com.android.volley.toolbox.HurlStack;
+import com.android.volley.toolbox.JsonObjectRequest;
+import com.android.volley.toolbox.StringRequest;
+import com.android.volley.toolbox.Volley;
+import com.google.android.material.snackbar.Snackbar;
+import com.smtp.smtp.BuildConfig;
+import com.smtp.smtp.http.RequestManager;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Map;
+import java.sql.Timestamp;
+
+import java.util.UUID;
+
+public class Etape extends AppCompatActivity {
+ private static final String BASE_URL = BuildConfig.API_URL;
+ String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImJiYTg0YmM3LTlmNDMtNDAxZS04ZjAyLTQ3ZTAyZDc4NDQ2OCIsInJvbGUiOiJhZG1pbiIsImlhdCI6MTU4NzQxODQ0MX0.zRTuqPl0UbiwJn7zZSxErvBYhkhPibEZ51S4Aqgd6LI";
+ private String etapeId;
+ private long dateDebut;
+ private long dateFin;
+ private String chantierId;
+ private String camionneurId;
+ private String type;
+ private String etapePrec;
+ private Context ctx;
+ private long debutPause;
+ private long finPause;
+
+ public Etape(String chantierId, String camionneurId, String type, String etapePrec, Context context){
+ this.etapeId = UUID.randomUUID().toString();
+ this.dateDebut = System.currentTimeMillis();
+ this.chantierId = chantierId;
+ this.camionneurId = camionneurId;
+ this.type = type;
+ this.etapePrec = etapePrec;
+ ctx = context;
+ sendDebutEtape();
+ }
+
+ public void sendDebutEtape(){
+ Map send = new HashMap<>();
+
+ send.put("dateDebut",this.dateDebut);
+ send.put("id",this.etapeId);
+ send.put("ChantierId",this.chantierId);
+ send.put("CamionneurId",this.camionneurId);
+ send.put("type",this.type);
+ send.put("etapePrecId",this.etapePrec);
+ JSONObject etape = new JSONObject(send);
+
+ final String requestBody = etape.toString();
+ final String URL = BASE_URL+"etapes";
+
+ Log.d("Etape", requestBody);
+
+ StringRequest stringRequest = new StringRequest(Request.Method.POST, URL, new Response.Listener() {
+ @Override
+ public void onResponse(String response) {
+
+ Log.d("Etape", "res" + response);
+ }
+ }, new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError error) {
+ Log.e("Etape", error.toString());
+ }
+ }) {
+ //This is for Headers If You Needed
+ @Override
+ public Map getHeaders() throws AuthFailureError {
+ Map params = new HashMap();
+ params.put("Content-Type", "application/json; charset=UTF-8");
+ params.put("Authorization", "Bearer " + token);
+ return params;
+ }
+
+ @Override
+ public byte[] getBody() throws AuthFailureError {
+ try {
+ return requestBody == null ? null : requestBody.getBytes("utf-8");
+ } catch (UnsupportedEncodingException uee) {
+ VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
+ return null;
+ }
+ }
+
+ @Override
+ protected Response parseNetworkResponse(NetworkResponse response) {
+ String responseString = "";
+ if (response != null) {
+ responseString = String.valueOf(response.statusCode);
+ // can get more details such as response.headers
+ }
+ return Response.success(responseString, HttpHeaderParser.parseCacheHeaders(response));
+ }
+ };
+ RequestManager.getInstance(ctx).addToRequestQueue(stringRequest);
+ }
+
+ public void sendDebutPause(){
+ Map send = new HashMap<>();
+ this.debutPause = System.currentTimeMillis();
+ send.put("debutPause",this.debutPause);
+ JSONObject etape = new JSONObject(send);
+
+ final String requestBody = etape.toString();
+ final String URL = BASE_URL+"etapes/"+etapeId + "/debutPause";
+
+ Log.d("Etape", requestBody);
+
+ StringRequest stringRequest = new StringRequest(Request.Method.PATCH, URL, new Response.Listener() {
+ @Override
+ public void onResponse(String response) {
+ Log.d("Etape", response);
+ }
+ }, new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError error) {
+ Log.e("Etape", error.toString());
+ }
+ }) {
+ //This is for Headers If You Needed
+ @Override
+ public Map getHeaders() throws AuthFailureError {
+ Map params = new HashMap();
+ params.put("Content-Type", "application/json; charset=UTF-8");
+ params.put("Authorization", "Bearer " + token);
+ return params;
+ }
+
+ @Override
+ public byte[] getBody() throws AuthFailureError {
+ try {
+ return requestBody == null ? null : requestBody.getBytes("utf-8");
+ } catch (UnsupportedEncodingException uee) {
+ VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
+ return null;
+ }
+ }
+
+ @Override
+ protected Response parseNetworkResponse(NetworkResponse response) {
+ String responseString = "";
+ if (response != null) {
+ responseString = String.valueOf(response.statusCode);
+ // can get more details such as response.headers
+ }
+ return Response.success(responseString, HttpHeaderParser.parseCacheHeaders(response));
+ }
+ };
+ RequestManager.getInstance(ctx).addToRequestQueue(stringRequest);;
+ }
+
+ public void sendFinPause(){
+ Map send = new HashMap<>();
+ this.finPause = System.currentTimeMillis();
+ send.put("finPause",this.finPause);
+ JSONObject etape = new JSONObject(send);
+
+ final String requestBody = etape.toString();
+ final String URL = BASE_URL+"etapes/"+etapeId +"/finPause";
+
+ Log.d("Etape", requestBody);
+
+ StringRequest stringRequest = new StringRequest(Request.Method.PATCH, URL, new Response.Listener() {
+ @Override
+ public void onResponse(String response) {
+ Log.d("Etape", response);
+ }
+ }, new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError error) {
+ Log.e("Etape", error.toString());
+ }
+ }) {
+ //This is for Headers If You Needed
+ @Override
+ public Map getHeaders() throws AuthFailureError {
+ Map params = new HashMap();
+ params.put("Content-Type", "application/json; charset=UTF-8");
+ params.put("Authorization", "Bearer " + token);
+ return params;
+ }
+
+ @Override
+ public byte[] getBody() throws AuthFailureError {
+ try {
+ return requestBody == null ? null : requestBody.getBytes("utf-8");
+ } catch (UnsupportedEncodingException uee) {
+ VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
+ return null;
+ }
+ }
+
+ @Override
+ protected Response parseNetworkResponse(NetworkResponse response) {
+ String responseString = "";
+ if (response != null) {
+ responseString = String.valueOf(response.statusCode);
+ // can get more details such as response.headers
+ }
+ return Response.success(responseString, HttpHeaderParser.parseCacheHeaders(response));
+ }
+ };
+ RequestManager.getInstance(ctx).addToRequestQueue(stringRequest);;
+ }
+
+ public void sendFinEtape(){
+ Map send = new HashMap<>();
+
+ send.put("dateFin",System.currentTimeMillis());
+ JSONObject etape = new JSONObject(send);
+
+ final String requestBody = etape.toString();
+ final String URL = BASE_URL+"etapes/"+etapeId;
+
+ Log.d("Etape", requestBody);
+
+ StringRequest stringRequest = new StringRequest(Request.Method.PATCH, URL, new Response.Listener() {
+ @Override
+ public void onResponse(String response) {
+ Log.d("Etape", response);
+ }
+ }, new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError error) {
+ Log.e("Etape", error.toString());
+ }
+ }) {
+ //This is for Headers If You Needed
+ @Override
+ public Map getHeaders() throws AuthFailureError {
+ Map params = new HashMap();
+ params.put("Content-Type", "application/json; charset=UTF-8");
+ params.put("Authorization", "Bearer " + token);
+ return params;
+ }
+
+ @Override
+ public byte[] getBody() throws AuthFailureError {
+ try {
+ return requestBody == null ? null : requestBody.getBytes("utf-8");
+ } catch (UnsupportedEncodingException uee) {
+ VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
+ return null;
+ }
+ }
+
+ @Override
+ protected Response parseNetworkResponse(NetworkResponse response) {
+ String responseString = "";
+ if (response != null) {
+ responseString = String.valueOf(response.statusCode);
+ // can get more details such as response.headers
+ }
+ return Response.success(responseString, HttpHeaderParser.parseCacheHeaders(response));
+ }
+ };
+ RequestManager.getInstance(ctx).addToRequestQueue(stringRequest);;
+ }
+
+
+
+ public String getEtapeId() {
+ return etapeId;
+ }
+}
diff --git a/android/app/src/main/java/com/smtp/smtp/navigation/Helper.java b/android/app/src/main/java/com/smtp/smtp/navigation/Helper.java
new file mode 100644
index 0000000..4c33eb8
--- /dev/null
+++ b/android/app/src/main/java/com/smtp/smtp/navigation/Helper.java
@@ -0,0 +1,29 @@
+package com.smtp.smtp.navigation;
+import android.location.Location;
+
+import com.mapbox.mapboxsdk.geometry.LatLng;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+public class Helper {
+ public static String getDayString(){
+ Date date = new Date();
+ DateFormat formatter = new SimpleDateFormat("EEEE", Locale.FRANCE);
+ return formatter.format(date);
+ }
+
+ public static float distance(LatLng firstPosition, LatLng secondPosition) {
+ float[] distanceFromDestination = new float[3];
+ Location.distanceBetween(
+ firstPosition.getLatitude(),
+ firstPosition.getLongitude(),
+ secondPosition.getLatitude(),
+ secondPosition.getLongitude(),
+ distanceFromDestination
+ );
+ return distanceFromDestination[0];
+ }
+}
diff --git a/android/app/src/main/java/com/smtp/smtp/navigation/LocationRequester.java b/android/app/src/main/java/com/smtp/smtp/navigation/LocationRequester.java
new file mode 100644
index 0000000..ee7e4d2
--- /dev/null
+++ b/android/app/src/main/java/com/smtp/smtp/navigation/LocationRequester.java
@@ -0,0 +1,43 @@
+package com.smtp.smtp.navigation;
+
+import android.content.Context;
+import android.location.Location;
+import android.os.Looper;
+
+import com.google.android.gms.location.FusedLocationProviderClient;
+import com.google.android.gms.location.LocationCallback;
+import com.google.android.gms.location.LocationRequest;
+import com.google.android.gms.location.LocationResult;
+import com.google.android.gms.location.LocationServices;
+
+import java.util.concurrent.Callable;
+
+public class LocationRequester implements Callable {
+ FusedLocationProviderClient fusedLocationClient;
+ public LocationRequester(Context ctx) {
+ fusedLocationClient = LocationServices.getFusedLocationProviderClient(ctx);
+
+ LocationRequest locationRequest = LocationRequest.create();
+ // Location is requested every 0.5 seconds
+ locationRequest.setInterval(500);
+ locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
+
+ LocationCallback locationCallback = new LocationCallback() {
+ @Override
+ public void onLocationResult(LocationResult locationResult) {
+ if(locationResult == null){
+ return;
+ }
+ //onLocationRetrieved(locationResult.getLastLocation(), this);
+ }
+ };
+
+ //fusedLocationClient.requestLocationUpdates(locationRequest,
+ //locationCallback,
+ //Looper.getMainLooper());
+ }
+ @Override
+ public Location call() throws Exception {
+ return null;
+ }
+}
diff --git a/android/app/src/main/java/com/smtp/smtp/navigation/MapMatcher.java b/android/app/src/main/java/com/smtp/smtp/navigation/MapMatcher.java
new file mode 100644
index 0000000..f88a6e6
--- /dev/null
+++ b/android/app/src/main/java/com/smtp/smtp/navigation/MapMatcher.java
@@ -0,0 +1,70 @@
+package com.smtp.smtp.navigation;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.mapbox.api.directions.v5.DirectionsCriteria;
+import com.mapbox.api.directions.v5.models.DirectionsRoute;
+import com.mapbox.api.matching.v5.MapboxMapMatching;
+import com.mapbox.api.matching.v5.models.MapMatchingResponse;
+import com.mapbox.geojson.Point;
+import com.mapbox.geojson.utils.PolylineUtils;
+import com.smtp.smtp.BuildConfig;
+import com.smtp.smtp.R;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.function.Consumer;
+
+import retrofit2.Call;
+import retrofit2.Callback;
+
+public class MapMatcher {
+ private String TAG = "MapMatcher";
+ private Context ctx;
+ private DirectionsRoute route;
+
+ public MapMatcher(Context ctx, DirectionsRoute route){
+ this.ctx = ctx;
+ this.route = route;
+ }
+
+ public void getMatch(Consumer success, Consumer failure) {
+ List pts = PolylineUtils.decode(route.geometry(), 6);
+ List lessThan100_Points = new ArrayList<>();
+ int indice = 0;
+ lessThan100_Points.add(pts.get(indice));
+ for (int i=1; i<99; i++){
+ indice = Math.round(i*pts.size()/100);
+ lessThan100_Points.add(pts.get(indice));
+ }
+ lessThan100_Points.add(pts.get(pts.size()-1));
+ Log.d(TAG, "Geometry points number: " + lessThan100_Points.size());
+
+ MapboxMapMatching.Builder mapMatchingBuilder = MapboxMapMatching.builder()
+ .accessToken(ctx.getString(R.string.mapbox_access_token))
+ .baseUrl(BuildConfig.API_URL)
+ .steps(true)
+ .voiceInstructions(true)
+ .bannerInstructions(true)
+ .coordinates(lessThan100_Points)
+ .profile(DirectionsCriteria.PROFILE_DRIVING_TRAFFIC)
+ .overview(DirectionsCriteria.OVERVIEW_FULL)
+ .language(Locale.FRENCH);
+
+ mapMatchingBuilder.build().enqueueCall(new Callback() {
+ @Override
+ public void onResponse(Call call, retrofit2.Response response) {
+ Log.d(TAG, "Matching URL: " + response.toString());
+ route = response.body().matchings().get(0).toDirectionRoute();
+ success.accept(route);
+ }
+
+ @Override
+ public void onFailure(Call call, Throwable t) {
+ Log.e(TAG, "Error getting matching: " + t.getLocalizedMessage());
+ failure.accept(t);
+ }
+ });
+ }
+}
diff --git a/android/app/src/main/java/com/smtp/smtp/Navigation.java b/android/app/src/main/java/com/smtp/smtp/navigation/Navigation.java
similarity index 70%
rename from android/app/src/main/java/com/smtp/smtp/Navigation.java
rename to android/app/src/main/java/com/smtp/smtp/navigation/Navigation.java
index bc2805a..469bf21 100644
--- a/android/app/src/main/java/com/smtp/smtp/Navigation.java
+++ b/android/app/src/main/java/com/smtp/smtp/navigation/Navigation.java
@@ -1,4 +1,4 @@
-package com.smtp.smtp;
+package com.smtp.smtp.navigation;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
@@ -10,9 +10,16 @@
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.location.Location;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
import android.net.ConnectivityManager;
+import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
import android.os.Looper;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
import android.util.Log;
import android.view.View;
import android.widget.Button;
@@ -34,7 +41,6 @@
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.material.snackbar.Snackbar;
-import com.mapbox.api.directions.v5.models.DirectionsResponse;
import com.mapbox.api.directions.v5.models.DirectionsRoute;
import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.Mapbox;
@@ -48,7 +54,6 @@
import com.mapbox.services.android.navigation.ui.v5.OnNavigationReadyCallback;
import com.mapbox.services.android.navigation.ui.v5.listeners.NavigationListener;
import com.mapbox.services.android.navigation.v5.navigation.MapboxNavigationOptions;
-import com.mapbox.services.android.navigation.v5.navigation.NavigationRoute;
import com.mapbox.services.android.navigation.v5.navigation.camera.Camera;
import com.mapbox.services.android.navigation.v5.navigation.camera.RouteInformation;
import com.mapbox.services.android.navigation.v5.offroute.OffRoute;
@@ -56,6 +61,11 @@
import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress;
import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgressState;
import com.mapbox.services.android.navigation.v5.utils.RouteUtils;
+import com.smtp.smtp.BuildConfig;
+import com.smtp.smtp.R;
+import com.smtp.smtp.Sortie;
+import com.smtp.smtp.http.CoefJSONAsyncRequest;
+import com.smtp.smtp.http.RequestManager;
import org.json.JSONArray;
import org.json.JSONException;
@@ -64,21 +74,21 @@
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Consumer;
+import java.util.logging.Level;
import io.socket.client.IO;
+import io.socket.client.Manager;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
-import retrofit2.Call;
-import retrofit2.Callback;
-import retrofit2.Response;
@SuppressLint("MissingPermission")
public class Navigation extends AppCompatActivity implements NavigationListener, OnNavigationReadyCallback, ProgressChangeListener{
+ private static final int ONE_HUNDRED_MILLISECONDS = 100;
private NavigationView navigationView;
private TextView timeDiffTextView;
private DirectionsRoute route;
@@ -86,30 +96,26 @@ public class Navigation extends AppCompatActivity implements NavigationListener,
private final int INITIAL_ZOOM = 18;
private final double INITIAL_TILT = 30;
private final int DISTANCE_TOLERANCE = 5000;
- private static final String TAG = "Navigation";
+ static final String TAG = "Navigation";
private boolean isOffRoute = false;
private String preOffRoute = "";
- private OffRoute neverOffRouteEngine = new OffRoute() {
- @Override
- public boolean isUserOffRoute(Location location, RouteProgress routeProgress, MapboxNavigationOptions options) {
- // User will never be off-route
-
- return false;
- }
- };
-
- private Point ORIGIN;
- private Point DESTINATION;
-
+ private Boolean sendingOffRoute = false;
+ private OffRoute neverOffRouteEngine;
+ private Point CHARGEMENT;
+ private Point DECHARGEMENT;
+ private Point destination;
private String userId;
private String chantierId;
private String typeRoute;
private String token;
private JSONObject coordinates;
private double remainingTime;
+ private Double remainingTimeCoef;
private double timeDiffTruckAhead = Double.POSITIVE_INFINITY;
- private String myEtat;
+ String myEtat;
private Etape etape = null;
+ private Sortie sortie = null;
+ private Pause pause = null;
private String etapeIdPrecedente = null;
private int rayonChargement;
private int rayonDéchargement;
@@ -121,21 +127,25 @@ public boolean isUserOffRoute(Location location, RouteProgress routeProgress, Ma
private List roadPoint = new ArrayList<>();
private Location location;
private int remainingWaypoints = -1;
-
private int timeToSend = 3;
private int delay = timeToSend;
+ //
+ private Cycle cycle;
+
// for paused button
private String previousEtat;
private Button buttonPause;
private Button buttonReprendre;
private boolean onPause = false;
private NetworkStateReceiver networkStateReceiver = new NetworkStateReceiver();
+ private List initialWaypoints;
+ private CycleManager cycleManager;
// Connection to the socket server
{
try {
- Log.i(TAG, "Instanciating a new socket");
+ Log.d(TAG, "Instanciating a new socket");
mSocket = IO.socket(BuildConfig.API_URL);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
@@ -146,122 +156,18 @@ public boolean isUserOffRoute(Location location, RouteProgress routeProgress, Ma
private CustomUEH UEH = new CustomUEH(new Runnable() {
@Override
public void run() {
+ try {
+ cycleManager.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
disconnectFromChantier();
}
});
- public boolean isMyUserId(String userId) {
- return userId.equals(this.userId);
- }
-
- class User {
- public String userId;
- public Double ETA;
- public String etat;
-
- public User(String userId, Double ETA, String etat) {
- this.userId = userId;
- this.ETA = ETA;
- this.etat = etat;
- }
- public Double getETA() {
- return ETA;
- }
- public String getUserId() {
- return userId;
- }
- public String getEtat() {
- return etat;
- }
-
-
- @Override
- public String toString() {
- return "User{ moi ?" + isMyUserId(this.userId) + ", ETA=" + ETA + ", etat='" + etat + '}';
- }
- }
-
- class EtaSorter implements Comparator {
- @Override
- public int compare(User o1, User o2) {
- return (int) (o1.getETA() - o2.getETA());
- }
- }
-
- public class ListUser {
- public ArrayList list;
-
- public ListUser() {
- this.list = new ArrayList<>();
- }
-
- public boolean isAddable(User user) {
- return user.getEtat().equals(myEtat);
- }
-
- public int addList(User user) {
- if (isAddable(user) && !isContainedUser(user.getUserId())) {
- list.add(user);
- Collections.sort(list, new EtaSorter());
- return 1;
- } else {
- return -1;
- }
- }
-
- public boolean isContainedUser(String userId) {
- boolean res = false;
- for (int i = 0; i < list.size(); i++) {
- if (list.get(i).getUserId().equals(userId)) {
- res = true;
- }
- }
- return res;
- }
-
- public void updateMyIndice(String userId) {
- for (int i = 0; i < list.size(); i++) {
- if (isMyUserId(list.get(i).getUserId())) {
- myIndice = i;
- Log.d(TAG, "changement indice : " + myIndice);
- }
- }
- }
-
- public boolean sameEtat(User user) {
- return user.getEtat().equals(myEtat);
- }
-
- public void updateList(User user) {
- if (!sameEtat(user)) {
- this.deleteUser(user.getUserId());
- } else {
- for (int i = 0; i < list.size(); i++) {
- if (list.get(i).getUserId().equals(user.getUserId())) {
- list.get(i).ETA = user.getETA();
- }
- }
- }
- Collections.sort(list, new EtaSorter());
- }
-
- public void deleteUser(String userId) {
- int res = -1;
- for (int i = 0; i < list.size(); i++) {
- if (list.get(i).getUserId().equals(userId)) {
- res = i;
- }
- }
- list.remove(res);
- Collections.sort(list, new EtaSorter());
- }
- }
-
- private ListUser myList = new ListUser();
- private int myIndice;
@SuppressLint("MissingPermission")
@Override
@@ -269,7 +175,11 @@ protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "OnCreate");
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
- Log.d(TAG, "LargeMemoryClass : " + am.getLargeMemoryClass());
+
+ AndroidLoggingHandler.reset(new AndroidLoggingHandler());
+ java.util.logging.Logger.getLogger(Socket.class.getName()).setLevel(Level.FINEST);
+ java.util.logging.Logger.getLogger(io.socket.engineio.client.Socket.class.getName()).setLevel(Level.FINEST);
+ java.util.logging.Logger.getLogger(Manager.class.getName()).setLevel(Level.FINEST);
Thread.setDefaultUncaughtExceptionHandler(UEH);
@@ -277,15 +187,13 @@ protected void onCreate(Bundle savedInstanceState) {
double[] origin = i.getDoubleArrayExtra("origin");
double[] destination = i.getDoubleArrayExtra("destination");
- ORIGIN = Point.fromLngLat(origin[0], origin[1]);
- DESTINATION = Point.fromLngLat(destination[0], destination[1]);
+ CHARGEMENT = Point.fromLngLat(origin[0], origin[1]);
+ DECHARGEMENT = Point.fromLngLat(destination[0], destination[1]);
userId = i.getStringExtra("userId");
chantierId = i.getStringExtra("chantierId");
- typeRoute = i.getStringExtra("typeRoute");
token = i.getStringExtra("token");
myEtat = i.getStringExtra("myEtat");
previousEtat = myEtat;
- myList.addList(new User(userId, Double.POSITIVE_INFINITY, myEtat));
Mapbox.getInstance(this, getString(R.string.mapbox_access_token));
@@ -297,11 +205,14 @@ protected void onCreate(Bundle savedInstanceState) {
navigationView.onCreate(savedInstanceState);
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
- //filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(networkStateReceiver, filter);
registerReceiver(broadcastReceiver, new IntentFilter("NO_INTERNET"));
retrieveLocation();
+
+ cycle = new Cycle(userId, myEtat);
+ cycle.addUser(new User(userId, Double.POSITIVE_INFINITY, myEtat));
+ cycleManager = new CycleManager(this::fetchRoute, cycle);
}
private void retrieveLocation() {
@@ -310,6 +221,7 @@ private void retrieveLocation() {
LocationRequest locationRequest = LocationRequest.create();
// Location is requested every 0.5 seconds
locationRequest.setInterval(500);
+ locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationCallback locationCallback = new LocationCallback() {
@Override
@@ -338,6 +250,7 @@ private void onLocationRetrieved(Location l, LocationCallback locationCallback)
mSocket.on("chantier/user/sentCoordinates", onUserSentCoordinates);
mSocket.on("chantier/connect/success", onConnectToChantierSuccess);
mSocket.on("chantier/user/disconnected", onUserDisconnected);
+ mSocket.on("chantier/detournement",onDetournement);
mSocket.connect();
connectToChantier();
@@ -358,6 +271,11 @@ protected void onDestroy() {
unregisterReceiver(broadcastReceiver);
unregisterReceiver(networkStateReceiver);
+ mSocket.off("chantier/user/sentCoordinates", onUserSentCoordinates);
+ mSocket.off("chantier/connect/success", onConnectToChantierSuccess);
+ mSocket.off("chantier/user/disconnected", onUserDisconnected);
+ mSocket.off("chantier/detournement", onUserDisconnected);
+
navigationView.onDestroy();
}
@@ -405,12 +323,18 @@ protected void onSaveInstanceState(@NonNull Bundle outState) {
public void onCancelNavigation() {
Log.d(TAG, "OnCancelNavigation");
disconnectFromChantier();
+ try {
+ cycleManager.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
this.finish();
}
@Override
public void onNavigationFinished() {
Log.d(TAG, "OnNavigationFinished");
+
}
@Override
@@ -421,7 +345,7 @@ public void onNavigationRunning() {
@Override
public void onNavigationReady(boolean isRunning) {
Log.d(TAG, "OnNavigationReady");
-
+ navigationView.retrieveNavigationMapboxMap().retrieveMap().getMarkers().clear();
fetchRayon();
fetchRoute();
modifyTimeDiffTruckAheadIfNecessary();
@@ -431,15 +355,21 @@ public void onNavigationReady(boolean isRunning) {
Icon icon2 = iconFactory.fromResource(R.drawable.icon_dechargement);
navigationView.retrieveNavigationMapboxMap().retrieveMap().addMarker(new MarkerOptions().title("Chargement")
- .position(new LatLng(ORIGIN.latitude(), ORIGIN.longitude()))
+ .position(new LatLng(CHARGEMENT.latitude(), CHARGEMENT.longitude()))
.icon(icon)
);
navigationView.retrieveNavigationMapboxMap().retrieveMap().addMarker(new MarkerOptions().title("Déchargement")
- .position(new LatLng(DESTINATION.latitude(), DESTINATION.longitude()))
+ .position(new LatLng(DECHARGEMENT.latitude(), DECHARGEMENT.longitude()))
.icon(icon2)
);
+ cycleManager.start();
+
+ }
+
+ public void print(){
+ Log.d("CycleManager", "Hello");
}
@@ -447,26 +377,10 @@ public void onNavigationReady(boolean isRunning) {
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- navigationView.stopNavigation();
- showAlertDialog();
+ showAlertDetournementWithAutoDismiss("Pas de connexion internet","Pas de connexion internet","Fermer",10000);
}
};
- // Alert to show when internet is disabled
- private void showAlertDialog() {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle("Erreur Réseaux");
- builder.setMessage("Pas de connexion internet")
- .setCancelable(false);
- builder.setPositiveButton("Quitter", new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- finish();
- }
- });
- AlertDialog alert = builder.create();
- alert.show();
- }
-
// listener for paused and reprendre buttons
private void addListenerOnButton() {
@@ -480,11 +394,15 @@ public void onClick(View arg0) {
buttonPause.setEnabled(false);
buttonReprendre.setVisibility(View.VISIBLE);
buttonReprendre.setEnabled(true);
+
if(isOffRoute){
previousEtat = preOffRoute;
}else{
previousEtat = myEtat;
}
+ if(etape != null){
+ pause = new Pause(etape.getEtapeId(),getApplicationContext());
+ }
myEtat = "pause";
onPause = true;
}
@@ -501,7 +419,17 @@ public void onClick(View view) {
buttonPause.setEnabled(true);
buttonPause.setVisibility(View.VISIBLE);
timeDiffTextView.setVisibility(View.VISIBLE);
- myEtat = previousEtat;
+ if(etape != null && pause != null){
+ pause.sendFinPause();
+ }
+ if(isOffRoute){
+ myEtat = "offRoute";
+ preOffRoute = previousEtat;
+ }else{
+ myEtat = previousEtat;
+ preOffRoute = "";
+ }
+
}
}
});
@@ -518,7 +446,6 @@ private void fetchRayon() {
} catch (JSONException e) {
e.printStackTrace();
}
- Log.d(TAG, response.toString());
},
new com.android.volley.Response.ErrorListener() {
@Override
@@ -540,45 +467,23 @@ public Map getHeaders() throws AuthFailureError {
private float getDistanceFromDestination(Location location) {
float[] distanceFromDestination = new float[3];
- Point destination = null;
+
Log.d("offT", " myEtat "+ myEtat);
- Log.d("offT", " isOfRoute "+ isOffRoute);
+ Log.d("offT", " isOffRoute "+ isOffRoute);
Log.d("offT", " preOffRoute "+ preOffRoute);
+
if(isOffRoute){
- if (myEtat.equals("chargé") || preOffRoute.equals("chargé")) {
- destination = DESTINATION;
- }
if(preOffRoute.equals("enDéchargement") || myEtat.equals("enDéchargement")){
myEtat = "enDéchargement";
preOffRoute = "";
isOffRoute = false;
- destination = DESTINATION;
- }
- if (myEtat.equals("déchargé") || preOffRoute.equals("déchargé") ) {
- destination = ORIGIN;
}
if(preOffRoute.equals("enChargement") || myEtat.equals("enChargement")){
myEtat = "enChargement";
preOffRoute = "";
isOffRoute = false;
- destination = DESTINATION;
- }
- }else if(myEtat.equals("pause")) {
- if(previousEtat.equals("chargé") || previousEtat.equals("enDéchargement")){
- destination = DESTINATION;
- }else if (previousEtat.equals("déchargé") || previousEtat.equals("enChargement")) {
- destination = ORIGIN;
- }
- }else{
- if (myEtat.equals("chargé") || myEtat.equals("enDéchargement")) {
- destination = DESTINATION;
- }else if (myEtat.equals("déchargé") || myEtat.equals("enChargement")) {
- destination = ORIGIN;
}
}
- if (destination == null) {
- throw new Error("getDistanceFromDestination: destination cannot be null");
- }
Location.distanceBetween(
location.getLatitude(),
location.getLongitude(),
@@ -589,16 +494,11 @@ private float getDistanceFromDestination(Location location) {
return distanceFromDestination[0];
}
- public void handleOffRoute(RouteProgress routeProgress){
- Log.d("offR", " preOffRoute : " + preOffRoute);
- Log.d("offR", " isOffRoute : " + isOffRoute);
- Log.d("offR", " routeProgress? : " + (routeProgress.currentState() != null));
- Log.d("offR", " previousEtat : " + previousEtat);
-
+ public void handleOffRoute(Location location, RouteProgress routeProgress){
if(myEtat.equals("enChargement") || myEtat.equals("enDéchargement") || myEtat.equals("pause") ){
preOffRoute = "";
isOffRoute = false;
- }else{
+ } else {
// je suis sur la route et isOffRoute = true => je change isOfRoute en false
if(routeProgress.currentState() != null && isOffRoute) {
myEtat = preOffRoute;
@@ -606,7 +506,7 @@ public void handleOffRoute(RouteProgress routeProgress){
isOffRoute = false;
Log.d("offR", " sortie de route " + isOffRoute);
}else{
- // je ne suis pas sur la route
+ // je ne suis plus sur la route et isOffRoute = false
if(routeProgress.currentState() == null && !isOffRoute){
preOffRoute = myEtat;
myEtat = "offRoute";
@@ -617,22 +517,49 @@ public void handleOffRoute(RouteProgress routeProgress){
}
}
}
+ sendOffRoute(location);
+ }
+
+ public void sendOffRoute(Location location){
+ // on commence un offRoute
+ if(!sendingOffRoute && isOffRoute){
+ Log.d("Sortie", "débutSortie");
+ sendingOffRoute = true;
+ sortie = new Sortie(chantierId,userId,typeRoute,getApplicationContext());
+ sortie.addWaypoint(location.getLatitude(),location.getLongitude());
+ }
+ // on continue
+ if(sendingOffRoute && isOffRoute){
+ Log.d("Sortie", "ajoutPointSortie");
+ // on conserve la meme Sortie ( ajout d'un Point)
+ sortie.addWaypoint(location.getLongitude(),location.getLatitude());
+ }
+ // on arrete
+ if(sendingOffRoute && !isOffRoute){
+ sendingOffRoute = false;
+ sortie.sendFinSortie();
+ Log.d("Sortie", "finSortie");
+ // on termine la Sortie ( dateFin)
+ }
+
}
@Override
public void onProgressChange(Location location, RouteProgress routeProgress) {
- handleOffRoute(routeProgress);
+ handleOffRoute(location,routeProgress);
boolean didEtatChanged;
float distanceFromDestination = getDistanceFromDestination(location);
this.location = location;
- this.remainingTime = routeProgress.durationRemaining() * 1.25;
+ this.remainingTime = Math.max(0, routeProgress.durationRemaining() * this.remainingTimeCoef);
didEtatChanged = changeMyEtatIfNecessary(distanceFromDestination);
if (rerouteUserIfNecessary(didEtatChanged)) {
return;
}
+
modifyTimeDiffTruckAheadIfNecessary();
+ Log.d(TAG, "Number of remaining waypoints: " + routeProgress.remainingWaypoints());
//Register remaining waypoints in SharedPreferences
if(remainingWaypoints != routeProgress.remainingWaypoints()) {
@@ -654,7 +581,7 @@ public void onProgressChange(Location location, RouteProgress routeProgress) {
Log.d(TAG, Integer.toString(remainingWaypoints));
for (Point p: remaininPoints
) {
- Log.d(TAG, p.toString());
+ Log.d(TAG, "Remaining waypoints: " + p.toString());
}
coordinates = new JSONObject();
@@ -670,7 +597,7 @@ public void onProgressChange(Location location, RouteProgress routeProgress) {
if(timeToSend()){
sendCoordinates();
}
- myList.updateList(new User(userId, remainingTime, myEtat));
+ cycle.updateCycle(new User(userId, remainingTime, myEtat));
}
}
@@ -687,7 +614,7 @@ private boolean timeToSend() {
public void prepareRoute(JSONArray array) throws JSONException {
// Ajoute chaque donnée à la liste de waypoint
- List initialWaypoints = new ArrayList<>();
+ initialWaypoints = new ArrayList<>();
for (int i = 0; i < array.length(); i++) {
JSONObject waypoint = array.getJSONObject(i);
initialWaypoints.add(
@@ -704,13 +631,13 @@ public void prepareRoute(JSONArray array) throws JSONException {
initialWaypoints,
location,
DISTANCE_TOLERANCE,
- getRemainingWaypointsFromSharedPreferences(initialWaypoints)
+ getRemainingWaypointsFromSharedPreferences()
);
initialWaypoints = filter.cleanWaypoints();
for (Waypoint wp:
- initialWaypoints) {
+ initialWaypoints) {
Log.d(TAG, "Cleaned waypoints: " + wp.toString());
}
@@ -719,6 +646,7 @@ public void prepareRoute(JSONArray array) throws JSONException {
for (Waypoint waypoint : initialWaypoints) {
points.add(waypoint.getPoint());
}
+ points.add(destination);
roadPoint = points;
}
@@ -730,18 +658,18 @@ private void registerRemainingWaypointInSharedPreferences() {
editor.apply();
}
- public List getRemainingWaypointsFromSharedPreferences(List initialWaypointList){
+ public List getRemainingWaypointsFromSharedPreferences(){
Log.d(TAG, "Getting remaining points in " + chantierId + typeRoute + "remainingWaypoints");
SharedPreferences sharedPref = getPreferences(MODE_PRIVATE);
int nbRemainingWp = sharedPref.getInt(chantierId + typeRoute + "remainingWaypoints", -1);
Log.d(TAG, "nbRemainingWaypoints:" + nbRemainingWp);
if (nbRemainingWp == -1) {
- return initialWaypointList;
- } else if (nbRemainingWp > initialWaypointList.size()) {
+ return initialWaypoints;
+ } else if (nbRemainingWp > initialWaypoints.size()) {
removeRemainingWaypointsFromSharedPreferences();
- return initialWaypointList;
+ return initialWaypoints;
}
- List res = new ArrayList<>(initialWaypointList.subList(initialWaypointList.size()-nbRemainingWp, initialWaypointList.size()));
+ List res = new ArrayList<>(initialWaypoints.subList(initialWaypoints.size()-nbRemainingWp, initialWaypoints.size()));
Collections.sort(res);
return res;
}
@@ -757,51 +685,46 @@ private void removeRemainingWaypointsFromSharedPreferences() {
private void fetchRoute() {
if (myEtat.equals("chargé") || myEtat.equals("enDéchargement")) {
typeRoute = "aller";
+ destination = DECHARGEMENT;
}
if (myEtat.equals("déchargé") || myEtat.equals("enChargement")) {
typeRoute = "retour";
+ destination = CHARGEMENT;
}
- initWaypoints();
+
+ fetchCoef(() -> initWaypoints());
}
- private void buildRoute() {
+ private void fetchCoef(Runnable then) {
+ CoefJSONAsyncRequest coefAsyncRequest = new CoefJSONAsyncRequest(getApplicationContext(), token);
+ HashMap coefRequestArgs = new HashMap<>();
+ coefRequestArgs.put("chantierId", this.chantierId);
+ coefRequestArgs.put("typeRoute", this.typeRoute);
+ coefRequestArgs.put("day", Helper.getDayString());
+ coefAsyncRequest.getByChantierAndTypeRouteAndDay(coefRequestArgs, fetchedCoef -> {
+ this.remainingTimeCoef = fetchedCoef;
+ then.run();
+ });
+ }
- NavigationRoute.Builder builder = NavigationRoute.builder(this)
- .accessToken("pk." + getString(R.string.gh_key))
- .baseUrl(getString(R.string.base_url))
- //.baseUrl("https://router.project-osrm.org/route/v1/")
- .user("gh")
- .origin(roadPoint.get(0))
- .destination(roadPoint.get(roadPoint.size() - 1))
- .profile("car");
- // add waypoints without first and last point
- if (roadPoint.size() > 2) {
- for (int i = 1; i < roadPoint.size() - 1; i++) {
- builder.addWaypoint(roadPoint.get(i));
- }
- }
- NavigationRoute navRoute = builder.build();
+ private void buildRoute() {
+ Consumer matchGetSuccess = (route) -> {
+ Navigation.this.route = route;
+ launchNavigation();
+ };
- navRoute.getRoute(
- new Callback() {
- @Override
- public void onResponse(Call call, Response response) {
- Log.d(TAG, call.request().url().toString());
- Log.d(TAG, response.message());
- if (validRouteResponse(response)) {
- route = response.body().routes().get(0);
- launchNavigation();
- } else {
- Snackbar.make(navigationView, "Erreur au calcul de la route", Snackbar.LENGTH_LONG).show();
- }
- }
+ Consumer routeGetFailure = (t) -> {
+ Snackbar.make(navigationView, "Error getting the route", Snackbar.LENGTH_LONG).show();
+ Log.e(TAG, t.getLocalizedMessage());
+ };
+ Consumer routeGetSuccess = (route) -> {
+ MapMatcher mapMatcher = new MapMatcher(getApplicationContext(), route);
+ mapMatcher.getMatch( matchGetSuccess, routeGetFailure);
+ };
- @Override
- public void onFailure(Call call, Throwable throwable) {
- Snackbar.make(navigationView, "Erreur au calcul de la route", Snackbar.LENGTH_LONG).show();
- }
- });
+ RouteGetter routeGetter = new RouteGetter(getApplicationContext(), roadPoint);
+ routeGetter.getRoute(routeGetSuccess, routeGetFailure);
}
private void launchNavigation() {
@@ -829,13 +752,20 @@ public List overview(RouteInformation routeInformation) {
}
};
+
navigationView.startNavigation(navViewBuilderOptions.build());
navigationView.retrieveMapboxNavigation().setCameraEngine(camera);
- navigationView.retrieveMapboxNavigation().setOffRouteEngine(neverOffRouteEngine);
+ setOffRouteEngine();
}
- private boolean validRouteResponse(Response response) {
- return response.body() != null && !response.body().routes().isEmpty();
+ private void setOffRouteEngine() {
+ neverOffRouteEngine = new OffRoute() {
+ @Override
+ public boolean isUserOffRoute(Location location, RouteProgress routeProgress, MapboxNavigationOptions options) {
+ return false;
+ }
+ };
+ navigationView.retrieveMapboxNavigation().setOffRouteEngine(neverOffRouteEngine);
}
public void initWaypoints() {
@@ -851,12 +781,11 @@ public void initWaypoints() {
} catch (JSONException e) {
e.printStackTrace();
}
- Log.d(TAG, response.toString());
},
new com.android.volley.Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
- Log.d(TAG, error.toString() + error.networkResponse);
+ Log.e(TAG, error.toString() + " " + error.networkResponse.toString());
}
}
) {
@@ -885,8 +814,6 @@ private void changeEtape(){
}
private boolean changeMyEtatIfNecessary(double distanceRemaining) {
- boolean etatChanged = false;
- String previousEtat = myEtat;
int rayonChangementEtat = 0;
if (typeRoute.equals("aller")) {
rayonChangementEtat = rayonDéchargement;
@@ -898,57 +825,55 @@ private boolean changeMyEtatIfNecessary(double distanceRemaining) {
if (myEtat.equals("chargé") || preOffRoute.equals("chargé")) {
myEtat = "enDéchargement";
changeEtape();
- etatChanged = true;
return true;
} else if (myEtat.equals("déchargé") || preOffRoute.equals("déchargé")) {
myEtat = "enChargement";
changeEtape();
- etatChanged = true;
return true;
}
} else {
if (myEtat.equals("enChargement")) {
myEtat = "chargé";
changeEtape();
- etatChanged = true;
return true;
} else if (myEtat.equals("enDéchargement")) {
myEtat = "déchargé";
changeEtape();
- etatChanged = true;
return true;
}
}
- if (etatChanged) {
- Log.d(TAG, "Etat changed: from " + previousEtat + " to " + myEtat);
- }
return false;
}
private boolean rerouteUserIfNecessary(boolean etatChanged) {
boolean userRerouted = false;
- if (etatChanged) {
- if (myEtat.equals("chargé") || myEtat.equals("déchargé")) {
- roadPoint.clear();
- navigationView.stopNavigation();
- navigationView.retrieveNavigationMapboxMap().clearMarkers();
- Log.d(TAG, "User rerouted");
- userRerouted = true;
- }
- }
+ if(!etatChanged) return userRerouted;
+ if(!userIsInReroutableState()) return userRerouted;
+
+ roadPoint.clear();
+ navigationView.stopNavigation();
+ navigationView.retrieveNavigationMapboxMap().clearMarkers();
+ Log.d(TAG, "User rerouted");
+ userRerouted = true;
+
+
if (userRerouted) {
fetchRoute();
}
return userRerouted;
}
+ private boolean userIsInReroutableState() {
+ return myEtat.equals("chargé") || myEtat.equals("déchargé");
+ }
+
private void modifyTimeDiffTruckAheadIfNecessary() {
if (myEtat.equals("enChargement")) {
timeDiffTextView.setText("Vous êtes en cours de chargement \nQuittez la zone une fois chargé");
} else if (myEtat.equals("enDéchargement")) {
timeDiffTextView.setText("Vous êtes en cours de déchargement \nQuittez la zone une fois déchargé");
- } else if (myIndice > 0 && myList.list.size() > 1) {
- User userAhead = myList.list.get(myIndice - 1);
+ } else if (cycle.someOneIsAheadMe()) {
+ User userAhead = cycle.getUserAhead();
timeDiffTruckAhead = Math.abs(remainingTime - userAhead.getETA());
int minutes = (int) Math.floor(timeDiffTruckAhead / 60);
int secondes = (int) Math.floor(timeDiffTruckAhead % 60);
@@ -1006,12 +931,12 @@ private void connectToChantier() {
senderEtat = data.getString("etat");
senderId = data.getString("userId");
User sender = new User(senderId, senderETA, senderEtat);
- if (myList.isContainedUser(senderId)) {
- myList.updateList(sender);
+ if (cycle.isContainedUser(senderId)) {
+ cycle.updateCycle(sender);
} else {
- myList.addList(sender);
+ cycle.addUser(sender);
}
- myList.updateMyIndice(Navigation.this.userId);
+ cycle.updateMyIndice(Navigation.this.userId);
modifyTimeDiffTruckAheadIfNecessary();
} catch (JSONException e) {
Log.e(TAG, e.getMessage());
@@ -1030,12 +955,65 @@ private void connectToChantier() {
String senderId;
try {
senderId = data.getString("userId");
- if (myList.isContainedUser(senderId)) {
- myList.deleteUser(senderId);
+ if (cycle.isContainedUser(senderId)) {
+ cycle.deleteUser(senderId);
} else {
Log.d(TAG, " impossible to delete : user not in the list ");
}
+ } catch (JSONException e) {
+ Log.e(TAG, e.getMessage());
+ return;
+ }
+ modifyTimeDiffTruckAheadIfNecessary();
+ });
+
+ private void rerouting(JSONObject data) throws JSONException {
+ navigationView.stopNavigation();
+ connectedToChantier = false;
+ mSocket.emit("chantier/disconnect");
+ chantierId = data.getString("chantierId");
+ Double originLong = data.getDouble("originLong");
+ Double originLat = data.getDouble("originLat");
+ Double destinationLong = data.getDouble("destinationLong");
+ Double destinationLat = data.getDouble("destinationLat");
+ CHARGEMENT = Point.fromLngLat(originLong,originLat);
+ DECHARGEMENT = Point.fromLngLat(destinationLong,destinationLat);
+ cycle.clear();
+ cycle.addUser(new User(userId, Double.POSITIVE_INFINITY, myEtat));
+ connectToChantier();
+ navigationView.retrieveNavigationMapboxMap().clearMarkers();
+ navigationView.retrieveNavigationMapboxMap().retrieveMap().getMarkers().clear();
+ fetchRayon();
+ fetchRoute();
+ modifyTimeDiffTruckAheadIfNecessary();
+
+ IconFactory iconFactory = IconFactory.getInstance(getApplicationContext());
+ Icon icon = iconFactory.fromResource(R.drawable.icon_chargement);
+ Icon icon2 = iconFactory.fromResource(R.drawable.icon_dechargement);
+
+ navigationView.retrieveNavigationMapboxMap().retrieveMap().addMarker(new MarkerOptions().title("Chargement")
+ .position(new LatLng(CHARGEMENT.latitude(), CHARGEMENT.longitude()))
+ .icon(icon)
+ );
+
+ navigationView.retrieveNavigationMapboxMap().retrieveMap().addMarker(new MarkerOptions().title("Déchargement")
+ .position(new LatLng(DECHARGEMENT.latitude(), DECHARGEMENT.longitude()))
+ .icon(icon2)
+ );
+ }
+ private Emitter.Listener onDetournement = args -> runOnUiThread(() -> {
+ Log.e("Detournement", "onDetournement");
+ JSONObject data = (JSONObject) args[0];
+ Log.e("Detournement", "data "+ data.toString());
+ String userIdToMove;
+ try {
+ userIdToMove = data.getString("userId");
+ if (userIdToMove.equals(userId)) {
+ rerouting(data);
+ vibrateAndNotify();
+ showAlertDetournementWithAutoDismiss("Détournement !","Vous avez été détourné vers un autre chantier","Fermer",5000);
+ }
} catch (JSONException e) {
Log.e(TAG, e.getMessage());
return;
@@ -1043,4 +1021,46 @@ private void connectToChantier() {
modifyTimeDiffTruckAheadIfNecessary();
});
+ @SuppressLint("MissingPermission")
+ private void vibrateAndNotify() {
+ Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
+ if (vibrator == null) {
+ return;
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ vibrator.vibrate(VibrationEffect.createOneShot(ONE_HUNDRED_MILLISECONDS, VibrationEffect.DEFAULT_AMPLITUDE));
+ } else {
+ vibrator.vibrate(ONE_HUNDRED_MILLISECONDS);
+ }
+ try {
+ Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
+ Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
+ r.play();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void showAlertDetournementWithAutoDismiss(String title, String message, String messageButton, int delayTime) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(Navigation.this);
+ builder.setTitle(title)
+ .setMessage(message)
+ .setCancelable(false).setCancelable(false)
+ .setPositiveButton(messageButton, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ //this for skip dialog
+ dialog.cancel();
+ }
+ });
+ final AlertDialog alertDialog = builder.create();
+ alertDialog.show();
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (alertDialog.isShowing()){
+ alertDialog.dismiss();
+ }
+ }
+ }, delayTime); //change 5000 with a specific time you want
+ }
}
diff --git a/android/app/src/main/java/com/smtp/smtp/NetworkStateReceiver.java b/android/app/src/main/java/com/smtp/smtp/navigation/NetworkStateReceiver.java
similarity index 96%
rename from android/app/src/main/java/com/smtp/smtp/NetworkStateReceiver.java
rename to android/app/src/main/java/com/smtp/smtp/navigation/NetworkStateReceiver.java
index b4cfa77..71dc0b0 100644
--- a/android/app/src/main/java/com/smtp/smtp/NetworkStateReceiver.java
+++ b/android/app/src/main/java/com/smtp/smtp/navigation/NetworkStateReceiver.java
@@ -1,4 +1,4 @@
-package com.smtp.smtp;
+package com.smtp.smtp.navigation;
import android.content.BroadcastReceiver;
import android.content.Context;
diff --git a/android/app/src/main/java/com/smtp/smtp/Etape.java b/android/app/src/main/java/com/smtp/smtp/navigation/Pause.java
similarity index 69%
rename from android/app/src/main/java/com/smtp/smtp/Etape.java
rename to android/app/src/main/java/com/smtp/smtp/navigation/Pause.java
index a28e4f0..bba982c 100644
--- a/android/app/src/main/java/com/smtp/smtp/Etape.java
+++ b/android/app/src/main/java/com/smtp/smtp/navigation/Pause.java
@@ -1,83 +1,66 @@
-package com.smtp.smtp;
+package com.smtp.smtp.navigation;
import android.content.Context;
import android.util.Log;
-import androidx.appcompat.app.AppCompatActivity;
-
import com.android.volley.AuthFailureError;
-import com.android.volley.Cache;
-import com.android.volley.Network;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
-import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;
-import com.android.volley.toolbox.BasicNetwork;
-import com.android.volley.toolbox.DiskBasedCache;
import com.android.volley.toolbox.HttpHeaderParser;
-import com.android.volley.toolbox.HurlStack;
import com.android.volley.toolbox.StringRequest;
-import com.android.volley.toolbox.Volley;
-import com.google.android.material.snackbar.Snackbar;
+import com.smtp.smtp.BuildConfig;
+import com.smtp.smtp.http.RequestManager;
import org.json.JSONObject;
+
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
-import java.sql.Timestamp;
-
import java.util.UUID;
-public class Etape extends AppCompatActivity {
- private static final String BASE_URL = "http://smtp-dev-env.eba-5jqrxjhz.eu-west-3.elasticbeanstalk.com/";
+public class Pause {
String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImJiYTg0YmM3LTlmNDMtNDAxZS04ZjAyLTQ3ZTAyZDc4NDQ2OCIsInJvbGUiOiJhZG1pbiIsImlhdCI6MTU4NzQxODQ0MX0.zRTuqPl0UbiwJn7zZSxErvBYhkhPibEZ51S4Aqgd6LI";
- private String etapeId;
+
+ private String pauseId;
private long dateDebut;
private long dateFin;
- private String chantierId;
- private String camionneurId;
- private String type;
- private String etapePrec;
private Context ctx;
+ private String etapeId;
- public Etape(String chantierId, String camionneurId, String type, String etapePrec, Context context){
- this.etapeId = UUID.randomUUID().toString();
+ public Pause(String etapeId, Context ctx){
+ this.pauseId = UUID.randomUUID().toString();
this.dateDebut = System.currentTimeMillis();
- this.chantierId = chantierId;
- this.camionneurId = camionneurId;
- this.type = type;
- this.etapePrec = etapePrec;
- ctx = context;
- sendDebutEtape();
+ this.etapeId = etapeId;
+ this.ctx = ctx;
+ this.sendDebutPause();
}
- public void sendDebutEtape(){
+ public void sendDebutPause(){
Map send = new HashMap<>();
send.put("dateDebut",this.dateDebut);
- send.put("id",this.etapeId);
- send.put("ChantierId",this.chantierId);
- send.put("CamionneurId",this.camionneurId);
- send.put("type",this.type);
- send.put("etapePrecId",this.etapePrec);
- JSONObject etape = new JSONObject(send);
+ send.put("id",this.pauseId);
+ send.put("EtapeId",this.etapeId);
+ JSONObject pause = new JSONObject(send);
- final String requestBody = etape.toString();
- final String URL = BASE_URL+"etapes";
+ final String requestBody = pause.toString();
+ final String URL = BuildConfig.API_URL +"pauses";
- Log.d("Etape", requestBody);
+ Log.d("Pause", requestBody);
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL, new Response.Listener() {
@Override
public void onResponse(String response) {
- Log.d("Etape", response);
+
+ Log.d("Pause", "res" + response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
- Log.e("Etape", error.toString());
+ Log.e("Pause", error.toString());
}
}) {
//This is for Headers If You Needed
@@ -112,26 +95,26 @@ protected Response parseNetworkResponse(NetworkResponse response) {
RequestManager.getInstance(ctx).addToRequestQueue(stringRequest);
}
- public void sendFinEtape(){
+ public void sendFinPause(){
Map send = new HashMap<>();
+ this.dateFin = System.currentTimeMillis();
+ send.put("dateFin",this.dateFin);
+ JSONObject pause = new JSONObject(send);
- send.put("dateFin",System.currentTimeMillis());
- JSONObject etape = new JSONObject(send);
-
- final String requestBody = etape.toString();
- final String URL = BASE_URL+"etapes/"+etapeId;
+ final String requestBody = pause.toString();
+ final String URL = BuildConfig.API_URL +"pauses/"+ this.pauseId;
- Log.d("Etape", requestBody);
+ Log.d("Pause", requestBody);
StringRequest stringRequest = new StringRequest(Request.Method.PATCH, URL, new Response.Listener() {
@Override
public void onResponse(String response) {
- Log.d("Etape", response);
+ Log.d("Pause", response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
- Log.e("Etape", error.toString());
+ Log.e("Pause", error.toString());
}
}) {
//This is for Headers If You Needed
@@ -165,8 +148,4 @@ protected Response parseNetworkResponse(NetworkResponse response) {
};
RequestManager.getInstance(ctx).addToRequestQueue(stringRequest);;
}
-
- public String getEtapeId() {
- return etapeId;
- }
}
diff --git a/android/app/src/main/java/com/smtp/smtp/navigation/RouteGetter.java b/android/app/src/main/java/com/smtp/smtp/navigation/RouteGetter.java
new file mode 100644
index 0000000..f78438b
--- /dev/null
+++ b/android/app/src/main/java/com/smtp/smtp/navigation/RouteGetter.java
@@ -0,0 +1,86 @@
+package com.smtp.smtp.navigation;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.mapbox.api.directions.v5.models.DirectionsResponse;
+import com.mapbox.api.directions.v5.models.DirectionsRoute;
+import com.mapbox.api.matching.v5.MapboxMapMatching;
+import com.mapbox.geojson.Point;
+import com.mapbox.services.android.navigation.v5.navigation.NavigationRoute;
+import com.smtp.smtp.BuildConfig;
+import com.smtp.smtp.R;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
+public class RouteGetter {
+ private String TAG = "RouteGetter";
+ private Context ctx;
+ private List roadPoints;
+
+ public RouteGetter(Context ctx, List roadPoints){
+ this.ctx = ctx;
+ this.roadPoints = roadPoints;
+ }
+
+ public void getRoute(Consumer success, Consumer failure) {
+ NavigationRoute navRoute = getNavigationRoute();
+
+ navRoute.getRoute(
+ new Callback() {
+ @Override
+ public void onResponse(Call call, Response response) {
+ Log.d(TAG, "RouteGetting completed");
+ if (validRouteResponse(response)) {
+ DirectionsRoute route = response.body().routes().get(0);
+ success.accept(route);
+ } else {
+ failure.accept(new Throwable("Route response is invalid!"));
+ }
+ }
+ @Override
+ public void onFailure(Call call, Throwable throwable) {
+ failure.accept(throwable);
+ }
+ });
+ }
+
+ @NotNull
+ private NavigationRoute getNavigationRoute() {
+ Log.d(TAG, "API_URL: " + BuildConfig.API_URL);
+ NavigationRoute.Builder builder = getBuilder();
+ addWaypointToRouteBuilder(builder);
+ return builder.build();
+ }
+
+ @NotNull
+ private NavigationRoute.Builder getBuilder() {
+ return NavigationRoute.builder(ctx)
+ .accessToken("pk." + ctx.getString(R.string.gh_key))
+ .baseUrl(BuildConfig.API_URL)
+ .user("gh")
+ .origin(roadPoints.get(0))
+ .destination(roadPoints.get(roadPoints.size() - 1))
+ .continueStraight(false)
+ .profile("car");
+ }
+
+ private void addWaypointToRouteBuilder(NavigationRoute.Builder builder) {
+ if (roadPoints.size() > 2) {
+ for (int i = 1; i < roadPoints.size() - 1; i++) {
+ builder.addWaypoint(roadPoints.get(i));
+ }
+ }
+ }
+
+ private boolean validRouteResponse(Response response) {
+ return response.body() != null && !response.body().routes().isEmpty();
+ }
+}
diff --git a/android/app/src/main/java/com/smtp/smtp/navigation/User.java b/android/app/src/main/java/com/smtp/smtp/navigation/User.java
new file mode 100644
index 0000000..0e29b60
--- /dev/null
+++ b/android/app/src/main/java/com/smtp/smtp/navigation/User.java
@@ -0,0 +1,47 @@
+package com.smtp.smtp.navigation;
+
+import androidx.annotation.Nullable;
+
+public class User implements Comparable {
+ public String userId;
+ public Double ETA;
+ public String etat;
+
+ public User(String userId, Double ETA, String etat) {
+ this.userId = userId;
+ this.ETA = ETA;
+ this.etat = etat;
+ }
+
+ public Double getETA() {
+ return ETA;
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ public String getEtat() {
+ return etat;
+ }
+
+ @Override
+ public int compareTo(Object o) {
+ User u = (User)o;
+ if (u.getUserId().equals(userId)) return 0;
+ return -1;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ return compareTo(obj) == 0;
+ }
+
+ public void setETA(Double eta) {
+ this.ETA = eta;
+ }
+
+ public void setState(String state) {
+ etat = state;
+ }
+}
diff --git a/android/app/src/main/java/com/smtp/smtp/Waypoint.java b/android/app/src/main/java/com/smtp/smtp/navigation/Waypoint.java
similarity index 83%
rename from android/app/src/main/java/com/smtp/smtp/Waypoint.java
rename to android/app/src/main/java/com/smtp/smtp/navigation/Waypoint.java
index 52ad883..f05a4fe 100644
--- a/android/app/src/main/java/com/smtp/smtp/Waypoint.java
+++ b/android/app/src/main/java/com/smtp/smtp/navigation/Waypoint.java
@@ -1,19 +1,19 @@
-package com.smtp.smtp;
+package com.smtp.smtp.navigation;
import com.mapbox.geojson.Point;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class Waypoint implements Comparable {
- double longitude;
- double latitude;
- int ordre;
- Waypoint(double longitude, double latitude, int ordre){
+ public double longitude;
+ public double latitude;
+ public int ordre;
+ public Waypoint(double longitude, double latitude, int ordre){
this.longitude = longitude;
this.latitude = latitude;
this.ordre = ordre;
}
- Waypoint(double longitude, double latitude){
+ public Waypoint(double longitude, double latitude){
this.longitude = longitude;
this.latitude = latitude;
ordre = -1;
diff --git a/android/app/src/main/java/com/smtp/smtp/WaypointFilter.java b/android/app/src/main/java/com/smtp/smtp/navigation/WaypointFilter.java
similarity index 99%
rename from android/app/src/main/java/com/smtp/smtp/WaypointFilter.java
rename to android/app/src/main/java/com/smtp/smtp/navigation/WaypointFilter.java
index de3221a..f008efa 100644
--- a/android/app/src/main/java/com/smtp/smtp/WaypointFilter.java
+++ b/android/app/src/main/java/com/smtp/smtp/navigation/WaypointFilter.java
@@ -1,4 +1,4 @@
-package com.smtp.smtp;
+package com.smtp.smtp.navigation;
import android.location.Location;
import android.util.Log;
diff --git a/android/app/src/main/java/com/smtp/smtp/navigation/test/TestCycle.java b/android/app/src/main/java/com/smtp/smtp/navigation/test/TestCycle.java
new file mode 100644
index 0000000..2e700fe
--- /dev/null
+++ b/android/app/src/main/java/com/smtp/smtp/navigation/test/TestCycle.java
@@ -0,0 +1,119 @@
+package com.smtp.smtp.navigation.test;
+
+import com.smtp.smtp.navigation.Cycle;
+import com.smtp.smtp.navigation.User;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+
+public class TestCycle {
+
+ @Test
+ public void cloneStateIsDifferentAfterModification() throws CloneNotSupportedException {
+ Cycle c1 = new Cycle("1","chargé");
+ Cycle c2 = c1.cloneMe();
+ c2.setMyEtat("déchargé");
+ Assert.assertNotEquals(c1.getMyEtat(), c2.getMyEtat());
+ }
+
+ @Test
+ public void cycleCloneListIsDifferentAfterModification() throws CloneNotSupportedException {
+ Cycle c1 = new Cycle("1","chargé");
+ User u1 = new User("1", 1.0, "chargé");
+ User u2 = new User("2", 2.0, "chargé");
+ c1.addUser(u1);
+ c1.addUser(u2);
+ Cycle c2 = c1.cloneMe();
+ c1.deleteUser(u1.getUserId());
+ Assert.assertTrue( "Cycle clone must keep his element when it is deleted from original",
+ c2.getUsers().contains(u1) && c2.getUsers().contains(u2));
+ Assert.assertNotEquals("Cycle clone size must be different than original after modification",
+ c1.getUsers().size(), c2.getUsers().size());
+ Assert.assertNotEquals("Cycle clone must be different than original after modification",
+ c1.getUsers(), c2.getUsers());
+ }
+
+ @Test
+ public void cycleOrderIsDifferentAfterUpdateWithSmallerETA() {
+ Cycle c1 = new Cycle("1","chargé");
+ User u1 = new User("1", 2.0, "chargé");
+ User u2 = new User("2", 3.0, "chargé");
+ c1.addUser(u1);
+ c1.addUser(u2);
+ u2.setETA(1.0);
+ c1.updateCycle(u2);
+ Assert.assertEquals("User with smaller ETA should be first",
+ c1.getUsers().get(0), u2 );
+ Assert.assertEquals("User with bigger ETA should be second",
+ c1.getUsers().get(1), u1 );
+ }
+
+ @Test
+ public void userIsNotInTheCycleAfterHisStateChanged() {
+ Cycle c1 = new Cycle("1","chargé");
+ User u1 = new User("1", 2.0, "chargé");
+ User u2 = new User("2", 3.0, "chargé");
+ c1.addUser(u1);
+ c1.addUser(u2);
+ u2.setState("déchargé");
+ c1.updateCycle(u2);
+
+ Assert.assertEquals("", c1.getUsers().size(), 1);
+ }
+
+ @Test
+ public void cycleAreNotEqualsAfterOneUserLeft() throws CloneNotSupportedException {
+ Cycle c1 = new Cycle("1","chargé");
+ User u1 = new User("1", 2.0, "chargé");
+ User u2 = new User("2", 3.0, "chargé");
+ c1.addUser(u1);
+ c1.addUser(u2);
+ Cycle c2 = c1.cloneMe();
+ c1.deleteUser("1");
+
+ Assert.assertTrue("Two cycle must not be equals if one user left",
+ !c1.equals(c2));
+ }
+
+ @Test
+ public void cycleAreEqualsAfterClone() throws CloneNotSupportedException {
+ Cycle c1 = new Cycle("1","chargé");
+ User u1 = new User("1", 2.0, "chargé");
+ User u2 = new User("2", 3.0, "chargé");
+ c1.addUser(u1);
+ c1.addUser(u2);
+ Cycle c2 = c1.cloneMe();
+
+ Assert.assertTrue("Two cycle must be equals after clone",
+ c1.equals(c2));
+ }
+
+ @Test
+ public void cycleListAreEqualsAfterClone() throws CloneNotSupportedException {
+ Cycle c1 = new Cycle("1","chargé");
+ User u1 = new User("1", 2.0, "chargé");
+ User u2 = new User("2", 3.0, "chargé");
+ c1.addUser(u1);
+ c1.addUser(u2);
+ Cycle c2 = c1.cloneMe();
+
+ Assert.assertTrue("Two cycle list must be equals after clone",
+ c1.getUsers().equals(c2.getUsers()));
+ }
+
+ @Test
+ public void cycleAreEqualsEvenIfUserOrderIsDifferent() throws CloneNotSupportedException {
+ Cycle c1 = new Cycle("1","chargé");
+ User u1 = new User("1", 2.0, "chargé");
+ User u2 = new User("2", 3.0, "chargé");
+ c1.addUser(u1);
+ c1.addUser(u2);
+ Cycle c2 = c1.cloneMe();
+ u2.setETA(1.0);
+ c1.updateCycle(u2);
+
+ Assert.assertTrue("Two cycle must be equals even if order is different",
+ c1.equals(c2));
+ }
+}
diff --git a/android/app/src/main/java/com/smtp/smtp/navigation/test/TestCycleManager.java b/android/app/src/main/java/com/smtp/smtp/navigation/test/TestCycleManager.java
new file mode 100644
index 0000000..91898c7
--- /dev/null
+++ b/android/app/src/main/java/com/smtp/smtp/navigation/test/TestCycleManager.java
@@ -0,0 +1,32 @@
+package com.smtp.smtp.navigation.test;
+
+import com.smtp.smtp.navigation.Cycle;
+import com.smtp.smtp.navigation.CycleManager;
+import com.smtp.smtp.navigation.User;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestCycleManager {
+ @Test
+ public void newRouteIsFetchedWhenCycleChange() {
+ Cycle c = new Cycle("1", "chargé");
+ User u1 = new User("1", 2.0, "chargé");
+ User u2 = new User("2", 3.0, "chargé");
+ c.addUser(u1);
+ c.addUser(u2);
+ CycleManager cycleManager = new CycleManager(() -> {}, c);
+ u2.setState("déchargé");
+ c.updateCycle(u2);
+
+ cycleManager.start();
+ try {
+ Thread.sleep(1000);
+ Assert.assertTrue(cycleManager.newRouteHasBeenFetched());
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+
+ }
+}
diff --git a/android/app/src/main/java/com/smtp/smtp/navigation/test/TestUser.java b/android/app/src/main/java/com/smtp/smtp/navigation/test/TestUser.java
new file mode 100644
index 0000000..d8ef068
--- /dev/null
+++ b/android/app/src/main/java/com/smtp/smtp/navigation/test/TestUser.java
@@ -0,0 +1,22 @@
+package com.smtp.smtp.navigation.test;
+
+import com.smtp.smtp.navigation.User;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestUser {
+ @Test
+ public void userWithSameIdAreEquals(){
+ User u1 = new User("1", 1.0, "chargé");
+ User u2 = new User("1", 2.0, "déchargé");
+ Assert.assertTrue(u1.equals(u2));
+ }
+
+ @Test
+ public void userWithDifferentIdAreNotEquals(){
+ User u1 = new User("1", 1.0, "chargé");
+ User u2 = new User("2", 2.0, "déchargé");
+ Assert.assertFalse(u1.equals(u2));
+ }
+}
diff --git a/android/app/src/main/java/com/smtp/smtp/road/MapboxRing.java b/android/app/src/main/java/com/smtp/smtp/road/MapboxRing.java
new file mode 100644
index 0000000..6cd7182
--- /dev/null
+++ b/android/app/src/main/java/com/smtp/smtp/road/MapboxRing.java
@@ -0,0 +1,65 @@
+package com.smtp.smtp.road;
+
+import android.graphics.Color;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.mapbox.geojson.LineString;
+import com.mapbox.geojson.Point;
+import com.mapbox.geojson.Polygon;
+import com.mapbox.mapboxsdk.maps.Style;
+import com.mapbox.mapboxsdk.style.layers.FillLayer;
+import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
+import com.mapbox.turf.TurfMeta;
+import com.mapbox.turf.TurfTransformation;
+
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillColor;
+import static com.mapbox.turf.TurfConstants.UNIT_METERS;
+
+public class MapboxRing {
+ private Point center;
+ private Integer radius;
+ private String sourceId;
+ private String layerId;
+ private GeoJsonSource source;
+ private FillLayer layer;
+ private int color;
+ private int meterDifferenceBetweenCircles;
+
+ MapboxRing(Point center, Integer radius, String sourceId, String layerId, Integer meterDifferenceBetweenCircles) {
+ this.center = center;
+ this.radius = radius;
+ this.sourceId = sourceId;
+ this.layerId = layerId;
+ this.color = Color.argb(125, 255, 0, 0);
+ this.source = new GeoJsonSource(sourceId);
+ this.layer = new FillLayer(layerId, this.sourceId).withProperties(fillColor(color));
+ this.meterDifferenceBetweenCircles = meterDifferenceBetweenCircles;
+
+ computeSource();
+ }
+
+ private void computeSource(){
+ Polygon outerCirclePolygon = getTurfPolygonCircle(radius + this.meterDifferenceBetweenCircles, center);
+ Polygon innerCirclePolygon = getTurfPolygonCircle(
+ radius, center);
+ if (source != null) {
+ source.setGeoJson(Polygon.fromOuterInner(
+ LineString.fromLngLats(TurfMeta.coordAll(outerCirclePolygon, false)),
+ LineString.fromLngLats(TurfMeta.coordAll(innerCirclePolygon, false))
+ ));
+ }
+ }
+
+ public void addToStyle(Style style){
+ style.addSource(this.source);
+ style.addLayer(this.layer);
+ }
+
+ static Polygon getTurfPolygonCircle(@NonNull double radius, @NonNull Point centerPoint) {
+ return TurfTransformation.circle(centerPoint, radius, 360, UNIT_METERS);
+ }
+
+
+}
diff --git a/android/app/src/main/java/com/smtp/smtp/NavigationLauncherActivity.java b/android/app/src/main/java/com/smtp/smtp/road/RouteEditor.java
similarity index 65%
rename from android/app/src/main/java/com/smtp/smtp/NavigationLauncherActivity.java
rename to android/app/src/main/java/com/smtp/smtp/road/RouteEditor.java
index 205a487..d1b8be9 100644
--- a/android/app/src/main/java/com/smtp/smtp/NavigationLauncherActivity.java
+++ b/android/app/src/main/java/com/smtp/smtp/road/RouteEditor.java
@@ -1,4 +1,4 @@
-package com.smtp.smtp;
+package com.smtp.smtp.road;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
@@ -6,6 +6,7 @@
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
+import android.graphics.Color;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
@@ -30,11 +31,16 @@
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.android.material.snackbar.Snackbar;
+import com.mapbox.api.directions.v5.DirectionsCriteria;
+import com.mapbox.api.directions.v5.DirectionsService;
import com.mapbox.api.directions.v5.models.DirectionsResponse;
import com.mapbox.api.directions.v5.models.DirectionsRoute;
+import com.mapbox.api.matching.v5.MapboxMapMatching;
+import com.mapbox.api.matching.v5.models.MapMatchingResponse;
import com.mapbox.core.constants.Constants;
import com.mapbox.geojson.LineString;
import com.mapbox.geojson.Point;
+import com.mapbox.geojson.utils.PolylineUtils;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.annotations.Icon;
import com.mapbox.mapboxsdk.annotations.IconFactory;
@@ -48,65 +54,67 @@
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-
import com.mapbox.mapboxsdk.maps.Style;
-import com.mapbox.mapboxsdk.style.light.Position;
import com.mapbox.services.android.navigation.ui.v5.route.NavigationMapRoute;
import com.mapbox.services.android.navigation.v5.navigation.NavigationRoute;
-
-
-
+import com.smtp.smtp.BuildConfig;
+import com.smtp.smtp.R;
+import com.smtp.smtp.http.RequestManager;
+import com.smtp.smtp.navigation.MapMatcher;
+import com.smtp.smtp.navigation.RouteGetter;
+import com.smtp.smtp.navigation.Waypoint;
+
+import org.jetbrains.annotations.NotNull;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
+import org.unimodules.core.interfaces.Consumer;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import retrofit2.Call;
import retrofit2.Callback;
-public class NavigationLauncherActivity extends AppCompatActivity implements OnMapReadyCallback,
+public class RouteEditor extends AppCompatActivity implements OnMapReadyCallback,
MapboxMap.OnMapLongClickListener, MapboxMap.OnMarkerClickListener {
-
private static final int ONE_HUNDRED_MILLISECONDS = 100;
-
- private Point ORIGIN;
- private Point DESTINATION;
- private static final String TAG = "Navigation";
+ private Point CHARGEMENT;
+ private Point DECHARGEMENT;
+ private static final String TAG = "EditRoad";
private String nameChantier;
private String typeRoute;
private String chantierId;
private int rayonChargement;
+ private int distanceSecuriteMarkerRayon = 25;
private int rayonDéchargement;
- private String token;
+ private String token;
private static final int CAMERA_ANIMATION_DURATION = 1000;
- private static final int DEFAULT_CAMERA_ZOOM = 16;
- private static final String BASE_URL = "http://smtp-dev-env.eba-5jqrxjhz.eu-west-3.elasticbeanstalk.com/";
+ private static final String BASE_URL = BuildConfig.API_URL;
private NavigationMapRoute mapRoute;
private MapboxMap mapboxMap;
- private final int[] padding = new int[]{50, 50, 50, 50};
-
MapView mapView;
ProgressBar loading;
private TextView routeInfo;
private DirectionsRoute route;
+ private boolean firstFetch;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Mapbox.getInstance(this.getApplicationContext(), getString(R.string.mapbox_access_token));
setContentView(R.layout.activity_navigation_launcher);
-
+
Intent i = getIntent();
chantierId = i.getStringExtra("chantierId");
typeRoute = i.getStringExtra("typeRoute");
@@ -116,29 +124,102 @@ protected void onCreate(Bundle savedInstanceState) {
double[] origin = i.getDoubleArrayExtra("origin");
double[] destination = i.getDoubleArrayExtra("destination");
- ORIGIN = Point.fromLngLat(origin[0], origin[1]);
- DESTINATION = Point.fromLngLat(destination[0], destination[1]);
+ CHARGEMENT = Point.fromLngLat(origin[0], origin[1]);
+ DECHARGEMENT = Point.fromLngLat(destination[0], destination[1]);
routeInfo = findViewById(R.id.route_info);
- routeInfo.setText(nameChantier+ "\n" + "Route : " + typeRoute.substring(0, 1).toUpperCase() + typeRoute.substring(1));
+ routeInfo.setText(nameChantier + "\n" + "Route : " + typeRoute.substring(0, 1).toUpperCase() + typeRoute.substring(1));
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
+ firstFetch = true;
loading = findViewById(R.id.loading);
}
- public JSONObject prepareRouteForSending(){
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ public void initWaypoints() {
+ final String URL = BASE_URL + "chantiers/" + chantierId + "/route/" + typeRoute;
+ RequestQueue requestQueue = Volley.newRequestQueue(this);
+ JsonArrayRequest getRequest = new JsonArrayRequest(Request.Method.GET, URL, null,
+ response -> {
+ try {
+ initRoute(response);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ },
+ new Response.ErrorListener() {
+ @Override
+ public void onErrorResponse(VolleyError error) {
+ Log.d(TAG, error.toString());
+ }
+ }
+ ) {
+ @Override
+ public Map getHeaders() throws AuthFailureError {
+ Map params = new HashMap();
+ params.put("Content-Type", "application/json; charset=UTF-8");
+ params.put("Authorization", "Bearer " + token);
+ return params;
+ }
+ };
+
+ requestQueue.add(getRequest);
+ }
+
+ public JSONObject prepareRouteForSending() {
JSONArray res = new JSONArray();
int order = 0;
for (Marker marker : mapboxMap.getMarkers()) {
JSONObject json = new JSONObject();
try {
- if(!isOriginOrDestination(marker)){
- json.put("latitude",marker.getPosition().getLatitude());
- json.put("longitude",marker.getPosition().getLongitude());
+ if (!isOriginOrDestination(marker)) {
+ json.put("latitude", marker.getPosition().getLatitude());
+ json.put("longitude", marker.getPosition().getLongitude());
json.put("ordre", order);
res.put(json);
}
@@ -148,7 +229,7 @@ public JSONObject prepareRouteForSending(){
order++;
}
try {
- return new JSONObject().put("waypoints",res);
+ return new JSONObject().put("waypoints", res);
} catch (JSONException e) {
e.printStackTrace();
}
@@ -158,7 +239,7 @@ public JSONObject prepareRouteForSending(){
public void initRoute(JSONArray array) throws JSONException {
// Ajoute chaque donnée à la liste de waypoint triable
List waypoints = new ArrayList<>();
- for (int i=0; i< array.length(); i++){
+ for (int i = 0; i < array.length(); i++) {
JSONObject waypoint = array.getJSONObject(i);
waypoints.add(
new Waypoint(
@@ -170,103 +251,66 @@ public void initRoute(JSONArray array) throws JSONException {
}
Collections.sort(waypoints);
- // Ajoute les marker à la map
int i = 0;
- for (Waypoint w: waypoints ) {
- i+=1;
+ for (Waypoint w : waypoints) {
+ i += 1;
LatLng point = new LatLng(w.latitude, w.longitude);
MarkerOptions markerOptions = new MarkerOptions()
.position(point)
.icon(getMyIcon(i));
mapboxMap.addMarker(markerOptions);
- Snackbar.make(mapView, "Marqueur : "+mapboxMap.getMarkers().size()+"/"+25, Snackbar.LENGTH_LONG).show();
+ showMessage(mapView, "Marqueur : " + mapboxMap.getMarkers().size() + "/" + 25);
}
fetchRoute();
}
- public Icon getMyIcon(int i){
+ public Icon getMyIcon(int i) {
IconFactory iconFactory = IconFactory.getInstance(getApplicationContext());
- switch (i){
- case 1 :
+ switch (i) {
+ case 1:
return iconFactory.fromResource(R.drawable.marker1);
- case 2 :
+ case 2:
return iconFactory.fromResource(R.drawable.marker2);
- case 3 :
+ case 3:
return iconFactory.fromResource(R.drawable.marker3);
- case 4 :
+ case 4:
return iconFactory.fromResource(R.drawable.marker4);
- case 5 :
+ case 5:
return iconFactory.fromResource(R.drawable.marker5);
- case 6 :
+ case 6:
return iconFactory.fromResource(R.drawable.marker6);
- case 7 :
+ case 7:
return iconFactory.fromResource(R.drawable.marker7);
- case 8 :
+ case 8:
return iconFactory.fromResource(R.drawable.marker8);
- case 9 :
+ case 9:
return iconFactory.fromResource(R.drawable.marker9);
}
return iconFactory.fromResource(R.drawable.marker9);
}
- public void initWaypoints(){
- final String URL = BASE_URL + "chantiers/"+chantierId+"/route/"+typeRoute;
- RequestQueue requestQueue = Volley.newRequestQueue(this);
- // prepare the Request
- JsonArrayRequest getRequest = new JsonArrayRequest(Request.Method.GET, URL, null,
- response -> {
- // display response
- try {
- initRoute(response);
- } catch (JSONException e) {
- e.printStackTrace();
- }
- Log.d("Response", response.toString());
- },
- new Response.ErrorListener()
- {
- @Override
- public void onErrorResponse(VolleyError error) {
- Log.d("Error.Response", error.toString());
- }
- }
- ) {
- @Override
- public Map getHeaders() throws AuthFailureError {
- Map params = new HashMap();
- params.put("Content-Type", "application/json; charset=UTF-8");
- params.put("Authorization", "Bearer " + token);
- return params;
- }
- } ;
-
- // add it to the RequestQueue
- requestQueue.add(getRequest);
- }
-
public void sendRouteToServer(View view) {
- if(mapboxMap.getMarkers().size() < 4){
- Snackbar.make(mapView, R.string.error_not_enough_waypoints, Snackbar.LENGTH_LONG ).show();
+ if (mapboxMap.getMarkers().size() < 4) {
+ showMessage(view, "Il faut au moins deux points pour faire une route");
return;
}
JSONObject route = prepareRouteForSending();
RequestQueue requestQueue = Volley.newRequestQueue(this);
final String requestBody = route.toString();
- String URL = BASE_URL + "chantiers/"+chantierId+"/route/"+typeRoute;
+ String URL = BASE_URL + "chantiers/" + chantierId + "/route/" + typeRoute;
StringRequest stringRequest = new StringRequest(Request.Method.PUT, URL, new Response.Listener() {
@Override
public void onResponse(String response) {
- Snackbar.make(mapView, "La route a été enregistrée avec succès", Snackbar.LENGTH_LONG ).show();
+ showMessage(mapView, "La route a été enregistrée avec succès");
Log.i("VOLLEY", response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
- Snackbar.make(mapView, "Erreur de l'enregistrement de route, veuillez contacter un administrateur", Snackbar.LENGTH_LONG ).show();
+ showMessage(mapView, "Erreur de l'enregistrement de route, veuillez contacter un administrateur");
Log.e("VOLLEY", error.toString());
}
}) {
- //This is for Headers If You Needed
@Override
public Map getHeaders() throws AuthFailureError {
Map params = new HashMap();
@@ -274,10 +318,6 @@ public Map getHeaders() throws AuthFailureError {
params.put("Authorization", "Bearer " + token);
return params;
}
- //@Override
- //public String getBodyContentType() {
- // return "application/json; charset=utf-8";
- //}
@Override
public byte[] getBody() throws AuthFailureError {
@@ -303,71 +343,60 @@ protected Response parseNetworkResponse(NetworkResponse response) {
requestQueue.add(stringRequest);
}
- @Override
- protected void onStart() {
- super.onStart();
- mapView.onStart();
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mapView.onPause();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mapView.onLowMemory();
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- mapView.onStop();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mapView.onDestroy();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mapView.onSaveInstanceState(outState);
- }
public void clearRoute(View view) {
- if(mapboxMap.getMarkers().size() == 0){
- mapboxMap.clear();
+ for (Marker m : mapboxMap.getMarkers()) {
+ if (!isOriginOrDestination(m)) {
+ mapboxMap.removeMarker(m);
+ }
}
mapRoute.removeRoute();
route = null;
}
+
@Override
public void onMapReady(MapboxMap mapboxMap) {
this.mapboxMap = mapboxMap;
- this.mapboxMap.setStyle(Style.SATELLITE_STREETS, style -> {
- this.mapboxMap.setOnMarkerClickListener(this);
- this.mapboxMap.addOnMapLongClickListener(this);
- initMapRoute();
- initWaypoints();
- initLieux();
- fetchRayon();
- boundCameraToRoute();
- });
+ this.mapboxMap.setStyle(new Style.Builder()
+ .fromUri(Style.SATELLITE_STREETS), new Style.OnStyleLoaded() {
+ @Override
+ public void onStyleLoaded(@NonNull Style style) {
+ RouteEditor.this.mapboxMap.setOnMarkerClickListener(RouteEditor.this);
+ RouteEditor.this.mapboxMap.addOnMapLongClickListener(RouteEditor.this);
+ initMapRoute();
+ initWaypoints();
+ initLieux();
+ fetchRayon(() -> {
+ drawRings(style);
+ });
+ }
+ }
+ );
}
- private float getDistance(MarkerOptions marker, Point lieu){
+ private void drawRings(Style style) {
+ MapboxRing ringChargement = new MapboxRing(
+ CHARGEMENT,
+ rayonChargement,
+ "SOURCE_RING_CHARGEMENT",
+ "LAYER_RING_CHARGEMENT",
+ distanceSecuriteMarkerRayon
+ );
+ ringChargement.addToStyle(style);
+
+ MapboxRing ringDechargement = new MapboxRing(
+ DECHARGEMENT,
+ rayonDéchargement,
+ "SOURCE_RING_DECHARGEMENT",
+ "LAYER_RING_DECHARGEMENT",
+ distanceSecuriteMarkerRayon
+ );
+ ringDechargement.addToStyle(style);
+
+ }
+
+ private float getDistance(MarkerOptions marker, Point lieu) {
float[] distanceFromDestination = new float[3];
Location.distanceBetween(
marker.getPosition().getLatitude(),
@@ -379,17 +408,13 @@ private float getDistance(MarkerOptions marker, Point lieu){
return distanceFromDestination[0];
}
- private void initLieux(){
- //IconFactory iconFactory = IconFactory.getInstance(getApplicationContext());
- //Icon icon = iconFactory.fromResource(R.drawable.icon_chargement);
- //Icon icon2 = iconFactory.fromResource(R.drawable.icon_dechargement);
-
+ private void initLieux() {
this.mapboxMap.addMarker(new MarkerOptions().title("Chargement")
- .position(new LatLng(ORIGIN.latitude(), ORIGIN.longitude()))
+ .position(new LatLng(CHARGEMENT.latitude(), CHARGEMENT.longitude()))
);
this.mapboxMap.addMarker(new MarkerOptions().title("Déchargement")
- .position(new LatLng(DESTINATION.latitude(), DESTINATION.longitude()))
+ .position(new LatLng(DECHARGEMENT.latitude(), DECHARGEMENT.longitude()))
);
}
@@ -397,67 +422,50 @@ private void initMapRoute() {
mapRoute = new NavigationMapRoute(null, mapView, mapboxMap);
}
- private boolean isOriginOrDestination(Marker m){
- boolean isOrigin = m.getPosition().getLongitude() == ORIGIN.longitude() && m.getPosition().getLatitude() == ORIGIN.latitude();
- boolean isDestination = m.getPosition().getLongitude() == DESTINATION.longitude() && m.getPosition().getLatitude() == DESTINATION.latitude();
+ private boolean isOriginOrDestination(Marker m) {
+ boolean isOrigin = m.getPosition().getLongitude() == CHARGEMENT.longitude() && m.getPosition().getLatitude() == CHARGEMENT.latitude();
+ boolean isDestination = m.getPosition().getLongitude() == DECHARGEMENT.longitude() && m.getPosition().getLatitude() == DECHARGEMENT.latitude();
return (isOrigin || isDestination);
}
private void fetchRoute() {
- NavigationRoute.Builder builder = NavigationRoute.builder(this)
- .accessToken("pk." + getString(R.string.gh_key))
- .baseUrl(getString(R.string.base_url))
- .user("gh")
- .profile("car");
-
if (mapboxMap.getMarkers().size() < 4) {
- Snackbar.make(mapView, R.string.error_not_enough_waypoints, Snackbar.LENGTH_LONG).show();
+ showMessage(mapView, "Il faut au moins deux points pour faire une route");
return;
}
- List wp = new ArrayList<>();
- for(Marker m : mapboxMap.getMarkers()) {
- if(!isOriginOrDestination(m)){
- Point p = Point.fromLngLat(m.getPosition().getLongitude(), m.getPosition().getLatitude());
- wp.add(p);
- }
- }
+ List waypointsWithoutOriginAndDestination = getWaypointsWithoutOriginAndDestination();
- for (int i = 0; i < wp.size(); i++) {
- Point p = wp.get(i);
- if (i == 0) {
- builder.origin(p);
- } else if (i < wp.size() - 1) {
- builder.addWaypoint(p);
- } else {
- builder.destination(p);
- }
- }
showLoading();
- builder.build().getRoute(new Callback() {
- @Override
- public void onResponse(Call call, retrofit2.Response response) {
- if (validRouteResponse(response)) {
- route = response.body().routes().get(0);
- mapRoute.addRoutes(response.body().routes());
- //boundCameraToRoute();
- } else {
- Snackbar.make(mapView, R.string.error_calculating_route, Snackbar.LENGTH_LONG).show();
- }
+ RouteGetter routeGetter = new RouteGetter(getApplicationContext(), waypointsWithoutOriginAndDestination);
+ routeGetter.getRoute((route) -> {
+ MapMatcher mapMatcher = new MapMatcher(getApplicationContext(), route);
+ mapMatcher.getMatch((trafficRoute) -> {
+ this.route = trafficRoute;
+ this.mapRoute.addRoute(this.route);
hideLoading();
- }
-
- @Override
- public void onFailure(Call call, Throwable t) {
- Snackbar.make(mapView, R.string.error_calculating_route, Snackbar.LENGTH_LONG).show();
- hideLoading();
- }
+ boundCameraToRoute();
+ }, (t) -> {
+ Log.e(TAG, t.getLocalizedMessage());
+ showMessage(mapView, "Erreur au calcul de la route, veuillez contacter un administrateur");
+ });
+ }, (t) -> {
+ Log.e(TAG, t.getLocalizedMessage());
+ showMessage(mapView, "Erreur au calcul de la route, veuillez contacter un administrateur");
});
}
- private boolean validRouteResponse(retrofit2.Response response) {
- return response.body() != null && !response.body().routes().isEmpty();
+ @NotNull
+ private List getWaypointsWithoutOriginAndDestination() {
+ List wp = new ArrayList<>();
+ for (Marker m : mapboxMap.getMarkers()) {
+ if (!isOriginOrDestination(m)) {
+ Point p = Point.fromLngLat(m.getPosition().getLongitude(), m.getPosition().getLatitude());
+ wp.add(p);
+ }
+ }
+ return wp;
}
private void hideLoading() {
@@ -473,7 +481,9 @@ private void showLoading() {
}
private void boundCameraToRoute() {
+ if (!firstFetch) return;
if (route != null) {
+ firstFetch = false;
List routeCoords = LineString.fromPolyline(route.geometry(),
Constants.PRECISION_6).coordinates();
List bboxPoints = new ArrayList<>();
@@ -483,19 +493,13 @@ private void boundCameraToRoute() {
if (bboxPoints.size() > 1) {
try {
LatLngBounds bounds = new LatLngBounds.Builder().includes(bboxPoints).build();
- // left, top, right, bottom
+ int[] padding = new int[]{75, 75, 75, 75};
animateCameraBbox(bounds, CAMERA_ANIMATION_DURATION, padding);
} catch (InvalidLatLngBoundsException exception) {
Toast.makeText(this, R.string.error_valid_route_not_found, Toast.LENGTH_SHORT).show();
}
}
}
- CameraPosition position = new CameraPosition.Builder()
- .target(new LatLng((ORIGIN.latitude()+DESTINATION.latitude())/2, (ORIGIN.longitude()+DESTINATION.longitude())/2 ))
- .zoom(12)
- .tilt(20)
- .build();
- mapboxMap.setCameraPosition(position);
}
private void animateCameraBbox(LatLngBounds bounds, int animationTime, int[] padding) {
@@ -505,40 +509,48 @@ private void animateCameraBbox(LatLngBounds bounds, int animationTime, int[] pad
@Override
public boolean onMarkerClick(@NonNull Marker marker) {
- for(Marker m : mapboxMap.getMarkers()) {
- if(m.getId() == marker.getId()){
- if(!isOriginOrDestination(m)){
+ for (Marker m : mapboxMap.getMarkers()) {
+ if (m.getId() == marker.getId()) {
+ if (!isOriginOrDestination(m)) {
mapboxMap.removeMarker(m);
}
}
}
- if(mapboxMap.getMarkers().size() > 3) {
+ if (mapboxMap.getMarkers().size() > 3) {
fetchRoute();
} else {
clearRoute(null);
}
- Snackbar.make(mapView, "Marqueur : "+(mapboxMap.getMarkers().size()-2)+"/"+25, Snackbar.LENGTH_LONG).show();
- Log.d("MARKER", Long.toString(marker.getId()));
+ showMessage(mapView, "Marqueur : " + (mapboxMap.getMarkers().size() - 2) + "/" + 25);
+ Log.d(TAG,"Clicked marker id: " + marker.getId());
return false;
}
+ public void showMessage(View mapView, String message) {
+ Snackbar snackbar;
+ snackbar = Snackbar.make(mapView, message, Snackbar.LENGTH_LONG);
+ View snackBarView = snackbar.getView();
+ snackBarView.setBackgroundColor(Color.WHITE);
+ snackbar.show();
+ }
+
@Override
public boolean onMapLongClick(@NonNull LatLng point) {
vibrate();
MarkerOptions markerOptions = new MarkerOptions()
.position(point)
- .icon(getMyIcon(mapboxMap.getMarkers().size()-1));
- if(getDistance(markerOptions,ORIGIN)< rayonChargement ){
- Snackbar.make(mapView, "Le marqueur ne peut pas être dans le rayon de chargement"+getDistance(markerOptions,ORIGIN)+"<"+rayonChargement, Snackbar.LENGTH_LONG).show();
- }else if (getDistance(markerOptions,DESTINATION)< rayonDéchargement) {
- Snackbar.make(mapView, "Le marqueur ne peut pas être dans le rayon de déchargement"+getDistance(markerOptions,DESTINATION)+"<"+rayonDéchargement, Snackbar.LENGTH_LONG).show();
- }else{
+ .icon(getMyIcon(mapboxMap.getMarkers().size() - 1));
+ if (getDistance(markerOptions, CHARGEMENT) < rayonChargement + distanceSecuriteMarkerRayon) {
+ showMessage(mapView, "Le marqueur ne peut pas être dans le rayon de chargement " + (getDistance(markerOptions, CHARGEMENT)) + " < " + (rayonChargement + distanceSecuriteMarkerRayon));
+ } else if (getDistance(markerOptions, DECHARGEMENT) < rayonDéchargement + distanceSecuriteMarkerRayon) {
+ showMessage(mapView, "Le marqueur ne peut pas être dans le rayon de déchargement " + (getDistance(markerOptions, DECHARGEMENT)) + " < " + (rayonDéchargement + distanceSecuriteMarkerRayon));
+ } else {
mapboxMap.addMarker(markerOptions);
- Snackbar.make(mapView, "Marqueur : "+(mapboxMap.getMarkers().size()-2)+"/"+23, Snackbar.LENGTH_LONG).show();
+ showMessage(mapView, "Marqueur : " + (mapboxMap.getMarkers().size() - 2) + "/" + 23);
+ }
+ if (mapboxMap.getMarkers().size() > 3) {
+ fetchRoute();
}
- //addPointToRoute(point.getLatitude(), point.getLongitude());
- //updateRouteAfterWaypointChange();
- fetchRoute();
return true;
}
@@ -555,17 +567,19 @@ private void vibrate() {
}
}
- private void fetchRayon() {
+ private void fetchRayon(Runnable lambda) {
final String URL = BASE_URL + "chantiers/" + chantierId;
JsonObjectRequest getRequest = new JsonObjectRequest(Request.Method.GET, URL, null,
response -> {
try {
rayonDéchargement = response.getJSONObject("lieuDéchargement").getInt("rayon");
rayonChargement = response.getJSONObject("lieuChargement").getInt("rayon");
+ if (lambda != null) {
+ lambda.run();
+ }
} catch (JSONException e) {
- e.printStackTrace();
+ Log.e(TAG, e.getLocalizedMessage());
}
- Log.d(TAG, response.toString());
},
new com.android.volley.Response.ErrorListener() {
@Override
diff --git a/android/app/src/main/res/layout/activity_navigation_launcher.xml b/android/app/src/main/res/layout/activity_navigation_launcher.xml
index 7898ba1..3078d08 100644
--- a/android/app/src/main/res/layout/activity_navigation_launcher.xml
+++ b/android/app/src/main/res/layout/activity_navigation_launcher.xml
@@ -20,7 +20,13 @@
android:layout_gravity="top"
android:layout_marginLeft="20dp"
android:layout_marginTop="40dp"
+ android:paddingTop="7dp"
+ android:paddingBottom="7dp"
+ android:paddingRight="10dp"
+ android:paddingLeft="10dp"
android:textStyle="bold"
+ android:background="#B3ffffff"
+ android:textColor="#1f2212"
/>
- {item.prenom +" "+ item.nom}
+ {item.prenom +" "+ item.nom}
)}
/>
diff --git a/components/ButtonAdminSelected.js b/components/ButtonAdminSelected.js
index a725191..eaeca5c 100644
--- a/components/ButtonAdminSelected.js
+++ b/components/ButtonAdminSelected.js
@@ -1,6 +1,7 @@
import React from 'react'
import AddWorkSiteForm from "./Worksite/AddWorkSiteForm";
import ListPlace from "./Place/ListPlace";
+import ListMateriaux from "./Materiau/ListMateriaux";
export default class ButtonAdminSelected extends React.Component {
@@ -14,7 +15,7 @@ export default class ButtonAdminSelected extends React.Component {
}else if(this.props.index == 1){
return
}else if(this.props.index == 2){
- return null;
+ return ;
}else
return null;
}
diff --git a/components/ButtonGroupAdmin.js b/components/ButtonGroupAdmin.js
index 83ad764..48fd439 100644
--- a/components/ButtonGroupAdmin.js
+++ b/components/ButtonGroupAdmin.js
@@ -35,7 +35,7 @@ export default class ButtonGroupAdmin extends React.Component {
}
render () {
- const buttons = ['Ajouter Chantier', 'Afficher Lieux', 'Afficher Entreprises'];
+ const buttons = ['Ajouter Chantier', 'Afficher Lieux', 'Afficher Matériaux'];
const { selectedIndex } = this.state;
if(this.state.typeUser !== "admin"){
diff --git a/components/Carriere/CarriereTruck.js b/components/Carriere/CarriereTruck.js
new file mode 100644
index 0000000..3159e5e
--- /dev/null
+++ b/components/Carriere/CarriereTruck.js
@@ -0,0 +1,149 @@
+import React from "react";
+import style from "../../Style";
+import axios from 'axios'
+import {
+ ActivityIndicator,
+ View,
+ ScrollView,
+ AsyncStorage,
+ TextInput
+} from "react-native";
+
+import Config from "react-native-config";
+import AutoCompletePlaces from "../Place/AutoCompletePlaces";
+import ValidateButton from "../ValidateButton";
+import AutoCompleteMateriaux from "../Materiau/AutoCompleteMateriaux";
+
+
+export default class CarriereTruck extends React.Component {
+ constructor(props) {
+ super(props);
+ this.getLieux = this.getLieux.bind(this);
+ this.getMateriaux = this.getMateriaux.bind(this);
+ this.state = {
+ report: null,
+ idPlace1 : null,
+ idPlace2 : null,
+ qte : null,
+ materiaux : [],
+ };
+ }
+
+ async componentDidMount() {
+ await this.getLieux();
+ await this.getMateriaux();
+ }
+
+ async getLieux() {
+ const token = await AsyncStorage.getItem('token');
+ await axios({
+ method : 'get',
+ url : Config.API_URL + 'lieux',
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status !== 200){
+ console.log(response.status);
+ alert(response.status);
+ return response.status;
+ }
+ console.log(response.status);
+ this.setState({report : response.data});
+ return response.status;
+ })
+ .catch((error) => {
+ console.log(error);
+ })
+ }
+
+ async getMateriaux() {
+ const token = await AsyncStorage.getItem('token');
+ await axios({
+ method : 'get',
+ url : Config.API_URL + 'materiaux',
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status !== 200){
+ console.log(response.status);
+ alert(response.status);
+ return response.status;
+ }
+ console.log(response.status);
+ this.setState({materiaux : response.data});
+ return response.status;
+ })
+ .catch((error) => {
+ console.log(error);
+ })
+ }
+
+
+ async postPrelevement(){
+ const token = await AsyncStorage.getItem('token');
+ const userId = await AsyncStorage.getItem('userId');
+ const data = {
+ "lieuChargementId": this.state.idPlace1,
+ "lieuDechargementId": this.state.idPlace2,
+ "quantite": parseFloat(this.state.qte),
+ "camionneur": userId,
+ "materiau" : this.state.materiau,
+ };
+ axios({
+ method: 'post',
+ url: Config.API_URL + 'prelevements',
+ data : data,
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status !== 201){
+ console.log(response.status);
+ alert(response.status);
+ return response.status;
+ }
+ alert("le prélevement a bien été enregistré");
+
+ console.log(response.status);
+ return response.status;
+ })
+ .catch((error) => {
+ console.log(error);
+ })
+ }
+
+ render() {
+ if (this.state.report === null) {
+ return (
+
+
+
+ )
+ } else {
+ return (
+
+
+
+
+ this.setState({idPlace1})} name={"chargement"} places={this.state.report}/>
+
+
+ this.setState({idPlace2})} name={"déchargement"} places={this.state.report}/>
+
+
+
+ this.setState({materiau})} materiaux ={this.state.materiaux}/>
+
+
+
+ this.setState({qte})}
+ value={this.state.qte} placeholder={"Quantité en tonne"}/>
+
+
+ this.postPrelevement()}/>
+
+
+
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/components/Crane/CraneView.js b/components/Crane/CraneView.js
index c1ee993..1406960 100644
--- a/components/Crane/CraneView.js
+++ b/components/Crane/CraneView.js
@@ -1,10 +1,12 @@
import * as React from 'react';
-import {Text, View, ScrollView, Dimensions, StyleSheet } from 'react-native';
+import {Text, View, ScrollView, Dimensions, StyleSheet, TouchableOpacity } from 'react-native';
import ValidateButton from "../ValidateButton";
import { Ionicons } from '@expo/vector-icons';
import Icon from 'react-native-vector-icons/FontAwesome';
import StopButtons from "../StopButtons";
import TruckArrivalTime from "./TruckArrivalTime";
+import {heightPercentageToDP as hp, widthPercentageToDP as wp} from "react-native-responsive-screen";
+
export default class CraneView extends React.Component {
constructor(props) {
@@ -100,9 +102,13 @@ export default class CraneView extends React.Component {
const { width, height } = Dimensions.get('window');
const styles = StyleSheet.create({
progressBar: {
- flexDirection:'row',
- justifyContent:'center',
- alignItems: 'center' ,
- backgroundColor : '#FFF',
- },
+ flexDirection : "row",
+ position: "absolute",
+ bottom: 80,
+ alignItems:'center',
+ justifyContent:'center',
+ width: wp('100%'),
+ backgroundColor : '#FFF',
+ height: hp('10%')
+ }
});
diff --git a/components/Crane/TruckArrivalTime.js b/components/Crane/TruckArrivalTime.js
index 3c51956..9c8b8b1 100644
--- a/components/Crane/TruckArrivalTime.js
+++ b/components/Crane/TruckArrivalTime.js
@@ -54,11 +54,13 @@ export default class TruckArrivalTime extends React.Component{
let seconds = time - minutes * 60;
return(
-
-
- {minutes}mn{seconds}
+
+
+
+ {minutes}mn{seconds}
+ {this.state.prenom}
+
- {this.state.prenom}
);
}
diff --git a/components/FuelForm.js b/components/FuelForm.js
new file mode 100644
index 0000000..2e58df3
--- /dev/null
+++ b/components/FuelForm.js
@@ -0,0 +1,268 @@
+import Icon from "react-native-vector-icons/FontAwesome5";
+import {Text, View, AsyncStorage, ActivityIndicator, TextInput, Button, TouchableOpacity} from "react-native";
+import * as React from "react";
+import axios from 'axios';
+import Config from "react-native-config";
+import Style from "../Style";
+import TimePicker from 'react-native-simple-time-picker';
+
+
+export default class FuelForm extends React.Component{
+ constructor(props){
+ super(props);
+ this.changeVolumeDebutFuel = this.changeVolumeDebutFuel.bind(this)
+ this.changeVolumeFinFuel = this.changeVolumeFinFuel.bind(this)
+ this.changeVolumeAjoutFuel = this.changeVolumeAjoutFuel.bind(this)
+ this.getVolumes = this.getVolumes.bind(this)
+ this.getHoraires =this.getHoraires.bind(this)
+ this.addHoraire = this.addHoraire.bind(this)
+ this.rearangeVolumes = this.rearangeVolumes.bind(this)
+ this.state = {
+ volumeDebutFuel: "",
+ volumeDebutStored : false,
+ volumeFinFuel : "",
+ volumeFinStored : false,
+ volumeAjoutFuel : "",
+ volumeAjoutStored : false,
+ horaireStored : false,
+ volumes : [],
+ ready : false,
+ horaires : undefined,
+ }
+ }
+
+ async componentDidMount() {
+ await this.getVolumes();
+ await this.rearangeVolumes();
+ await this.getHoraires();
+ }
+
+ changeVolumeDebutFuel(e){
+ e = parseInt(e)
+ this.setState({volumeDebutFuel : e})
+ this.setState({volumeDebutStored : false})
+ }
+
+ changeVolumeFinFuel(e){
+ this.setState({volumeFinFuel : e })
+ this.setState({volumeFinStored : false})
+ }
+
+ changeVolumeAjoutFuel(e){
+ this.setState({volumeAjoutFuel : e})
+ this.setState({volumeAjoutStored : false})
+ }
+
+ async rearangeVolumes(){
+ console.log(this.state.volumes.length)
+ for (let i = 0; i < this.state.volumes.length; i++){
+ console.log("this.state.volumes[i].volume = " + this.state.volumes[i].volume)
+ if (this.state.volumes[i].type === "début"){
+ this.changeVolumeDebutFuel(this.state.volumes[i].volume)
+ this.setState({volumeDebutStored : true})
+ }
+ if(this.state.volumes[i].type === "fin") {
+ this.changeVolumeFinFuel(this.state.volumes[i].volume)
+ this.setState({volumeFinStored : true})
+ }
+ if(this.state.volumes[i].type === "ajout"){
+ this.changeVolumeAjoutFuel(this.state.volumes[i].volume)
+ this.setState({volumeAjoutStored : true})
+ }
+ }
+ this.setState({ready : true})
+ }
+
+ async getVolumes(){
+ const token = await AsyncStorage.getItem('token');
+ const userId = await AsyncStorage.getItem('userId');
+ await axios({
+ method: 'get',
+ url: Config.API_URL + 'grutiers/'+ userId +'/carburant/'+Date.now(),
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status !== 200){
+ console.log(response.status);
+ alert(response.status);
+ return response.status;
+ }
+ this.setState({volumes : response.data})
+ console.log("axios get volumes "+ JSON.stringify(response.data));
+ return response.status;
+ })
+ .catch((error) => {
+ console.log(error + " getVolume");
+ })
+ }
+
+ async getHoraires(){
+ const token = await AsyncStorage.getItem('token');
+ const userId = await AsyncStorage.getItem('userId');
+ await axios({
+ method: 'get',
+ url: Config.API_URL + 'grutiers/'+ userId +'/work-time',
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status !== 200){
+ console.log(response.status);
+ alert(response.status);
+ return response.status;
+ }
+ this.setState({horaires : response.data[new Date().toISOString().split("T")[0]]})
+ console.log("axios get horaires "+ JSON.stringify(response.data[new Date().toISOString().split("T")[0]]));
+ this.state.horaires ? ( console.log("success get") , this.setState({ horaireStored : true }) ): this.setState({horaires : {"hour":0,"minute":0}}), console.log("init horaires {0,0}")
+ return response.status;
+ })
+ .catch((error) => {
+ console.log(error + "getHoraires");
+ })
+ }
+
+ async addHoraire(){
+ const token = await AsyncStorage.getItem('token');
+ const userId = await AsyncStorage.getItem('userId');
+ let data;
+ if(this.state.horaires.idWorkTime !== undefined){
+ data = {
+ "idWorkTime" : this.state.horaires.idWorkTime,
+ "hour": this.state.horaires.hour,
+ "minute" : this.state.horaires.minute,
+ };
+ }else{
+ data = {
+ "hour": this.state.horaires.hour,
+ "minute" : this.state.horaires.minute,
+ };
+ }
+ axios({
+ method: 'put',
+ url: Config.API_URL + 'grutiers/'+userId+'/work-time',
+ data : data,
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status !== 201){
+ console.log(response.status);
+ alert(response.status);
+ return response.status;
+ }
+ this.setState({ horaireStored : true })
+ let item = this.state.horaires
+ item.idWorkTime = response.data[0].id
+ this.setState({ horaires : item })
+ console.log(response.status);
+ return response.status;
+ })
+ .catch((error) => {
+ console.log(error + " addHoraire");
+ })
+ }
+
+ async addVolume(type,volume){
+ const token = await AsyncStorage.getItem('token');
+ const userId = await AsyncStorage.getItem('userId');
+ const data = {
+ "type": type,
+ "volume" : volume,
+ };
+ axios({
+ method: 'put',
+ url: Config.API_URL + 'grutiers/'+userId+'/carburant',
+ data : data,
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status !== 200){
+ console.log(response.status);
+ alert(response.status);
+ return response.status;
+ }
+ if(type === "début"){
+ this.setState({volumeDebutStored : true})
+ }
+ if(type === "fin"){
+ this.setState({volumeFinStored : true})
+ }
+ if(type === "ajout"){
+ this.setState({volumeAjoutStored : true})
+ }
+ console.log(response.status);
+ return response.status;
+ })
+ .catch((error) => {
+ console.log(error + "addVolume");
+ })
+ }
+
+ render() {
+ console.log(Date.now())
+ console.log(this.state.volumes)
+ let selectedHours = this.state.horaires ? this.state.horaires.hour : 0
+ let selectedMinutes = this.state.horaires ? this.state.horaires.minute : 0
+ if(this.state.ready && this.state.horaires){
+ console.log("horaires : " + JSON.stringify(this.state.horaires))
+ return(
+
+
+ { "Formulaire pour comptabiliser l'essence :" }
+ { "Volume d'essence au début de la journée" }
+
+ this.changeVolumeDebutFuel(volumeDebutFuel)}
+ value={this.state.volumeDebutFuel.toString()} placeholder={"Volume début de journée (L)"}/>
+ this.addVolume("début",this.state.volumeDebutFuel)}>
+ { this.state.volumeDebutStored ? : }
+
+
+ { "Volume d'essence à la fin de la journée" }
+
+ this.changeVolumeFinFuel(volumeFinFuel)}
+ value={this.state.volumeFinFuel.toString()} placeholder={"Volume en fin de journée (L)"}/>
+ this.addVolume("fin",this.state.volumeFinFuel)}>
+ { this.state.volumeFinStored ? : }
+
+
+ { "Volume d'essence ajouté cette journée" }
+
+ this.changeVolumeAjoutFuel(volumeAjoutFuel)}
+ value={this.state.volumeAjoutFuel.toString()} placeholder={"Volume d'essence ajouté (L)"}/>
+ this.addVolume("ajout",this.state.volumeAjoutFuel)}>
+ { this.state.volumeAjoutStored ? : }
+
+
+
+ Nombre d'heure de travail effectuée
+
+
+
+ {
+ let time = this.state.horaires ? this.state.horaires : {};
+ time.hour = hours;
+ time.minute = minutes;
+ this.setState({ horaires : time, horaireStored : false })}
+ }
+ />
+
+
+ this.addHoraire()}>
+ { this.state.horaireStored ? : }
+
+
+
+
+
+
+ );
+ }else{
+ return null
+ }
+ }
+}
diff --git a/components/Login.js b/components/Login.js
index ab21fba..fae2be8 100644
--- a/components/Login.js
+++ b/components/Login.js
@@ -3,19 +3,14 @@ import InputText from './InputText';
import ValidateButton from './ValidateButton';
import CustomPicker from './CustomPicker';
import { ButtonGroup } from 'react-native-elements';
-import * as Permissions from 'expo-permissions';
-import * as Location from 'expo-location';
-import RNAndroidLocationEnabler from 'react-native-android-location-enabler';
-import NetInfo from "@react-native-community/netinfo";
import axios from 'axios';
import style from "../Style";
-import {View, ActivityIndicator, AsyncStorage, ScrollView, Text} from 'react-native';
-import AutoCompletePlaces from "./Place/AutoCompletePlaces";
+import {View, AsyncStorage, ScrollView, Text} from 'react-native';
+import { AnimatedCircularProgress } from 'react-native-circular-progress';
import AutoCompleteUsers from "./AutoCompleteUsers";
import Style from "../Style";
var jwtDecode = require('jwt-decode');
import Config from "react-native-config";
-import VersionCheck from 'react-native-version-check';
import Setup from './Services/setup'
import { Image } from 'react-native-elements';
@@ -28,9 +23,6 @@ export default class Login extends React.Component{
this.handlePickerChange = this.handlePickerChange.bind(this);
this.handleChangeFirstField = this.handleChangeFirstField.bind(this);
this.handleChangeSecondField = this.handleChangeSecondField.bind(this);
- this.requestLocationPermission = this.requestLocationPermission.bind(this);
- this.internetCheck = this.internetCheck.bind(this);
- this.accesLocation = this.accesLocation.bind(this);
this.handleValidate = this.handleValidate.bind(this);
this.updateIndex = this.updateIndex.bind(this);
this.formSubmit = this.formSubmit.bind(this);
@@ -42,16 +34,16 @@ export default class Login extends React.Component{
secondField : "",
selectedIndex: 0,
user : null,
+ fill :100
};
}
async componentDidMount(){
+ console.log("Login | begin componentDidMount");
await this.setup.initSetup();
- await this.requestLocationPermission();
- await this.internetCheck();
await axios.get(Config.API_URL + 'entreprises')
.then( response => {
- if(response.status != 200){
+ if(response.status !== 200){
console.log(response.status);
alert(response.status);
return response.status;
@@ -66,56 +58,6 @@ export default class Login extends React.Component{
});
}
- // handle connection error
- async internetCheck(){
- NetInfo.fetch().then(state => {
- if (state.type === 'cellular' || state.type === 'wifi') {
- axios.get(Config.API_URL + 'entreprises')
- .then( response => {
- console.log("internet check passed !");
- }
- ).catch(function (error) {
- alert("Erreur réseau ! Vérifier que les données mobiles et la localisation sont activées");
- });
- }else{
- alert("Erreur réseau ! Vérifier que les données mobiles et la localisation sont activées");
- }
- }).catch(function (error){
- alert("error")
- });
- }
-
- accesLocation(){
- return RNAndroidLocationEnabler.promptForEnableLocationIfNeeded({interval: 10000, fastInterval: 5000})
- .then(data => {
- console.log("data" + data)
- return true
- }).catch(err => {
- return false
- });
- }
-
- // ask location to GPS and get current position if granted
- async requestLocationPermission() {
- let permission = false;
- let acces = false;
- while (!permission || !acces){
- try {
- let {granted} = await Permissions.askAsync(Permissions.LOCATION);
- if (granted) {
- console.log("access to position granted");
- permission = true;
- acces = this.accesLocation();
- console.log(acces);
- } else {
- console.log("Location permission denied");
- }
- } catch (err) {
- console.log("error "+err)
- }
- }
- }
-
async storeDataSession(item, selectedValue){
try {
await AsyncStorage.setItem(item, selectedValue);
@@ -137,17 +79,17 @@ export default class Login extends React.Component{
// to do : change view in fonction of User type
async formSubmit(){
- if(this.state.firstField == "" || this.state.secondField == ""){
+ if(this.state.firstField === "" || this.state.secondField === ""){
alert('Veuillez saisir tous les champs')
}else{
- var data = {
+ let data = {
"nom": this.state.firstField,
"prenom": this.state.secondField,
"entreprise" : this.state.pickerSelected
};
- var url = Config.API_URL;
- var typeUser;
+ let url = Config.API_URL;
+ let typeUser;
switch (this.state.selectedIndex) {
case 0:
@@ -174,7 +116,7 @@ export default class Login extends React.Component{
data : data
})
.then((response) => {
- if(response.status != 200){
+ if(response.status !== 200){
console.log(response);
}else{
console.log(response.status);
@@ -194,6 +136,7 @@ export default class Login extends React.Component{
updateIndex (selectedIndex) {
this.setState({selectedIndex})
+ this.setState({firstField : "", secondField : ""})
}
handleSwitchChange(){
@@ -218,28 +161,40 @@ export default class Login extends React.Component{
render(){
if (this.state.companies == null){
- return ();
+ return (
+
+
+ {
+ (fill) => (
+
+ {Math.trunc(fill)} %
+
+ )
+ }
+
+
+ );
}else{
- let firstPC = this.state.selectedIndex == 2 ? "Mail" : "Nom";
- let secondPC = this.state.selectedIndex == 2 ? "Mot de passe" : "Prenom";
-
- const component1 = () =>
- const component2 = () =>
- const component3 = () =>
+ let firstPC = this.state.selectedIndex === 2 ? "Mail" : "Nom";
+ let secondPC = this.state.selectedIndex === 2 ? "Mot de passe" : "Prenom";
- const buttons = [{ element: component1 }, { element: component2 }, { element: component3 }];
+ const buttons = [
+ ,
+ ,
+
+ ];
// set Data for picker
let pickerData = this.state.companies.map(item => item.nom);
// set selectedValue for picker
- let resIndex = this.state.companies.findIndex(s => s.id == this.state.pickerSelected);
- let selectedIndex = resIndex == -1 ? 0 : resIndex
+ let resIndex = this.state.companies.findIndex(s => s.id === this.state.pickerSelected);
+ let selectedIndex = resIndex === -1 ? 0 : resIndex
let selected = this.state.companies[selectedIndex].nom;
return (
@@ -254,20 +209,20 @@ export default class Login extends React.Component{
buttons={buttons}
containerStyle={{height: 50}}
/>
- {this.state.selectedIndex != 2 &&
+ {this.state.selectedIndex !== 2 &&
this.setState({user})}
currentIndex={this.state.selectedIndex} user={this.state.user}
changeFirstField={txt => this.handleChangeFirstField(txt)}
changeSecondField={txt => this.handleChangeSecondField(txt)}/>
}
- {this.state.selectedIndex == 2 &&
+ {this.state.selectedIndex === 2 &&
}
- {this.state.selectedIndex == 2 &&
-
+ {this.state.selectedIndex === 2 &&
+
}
-
+
{Config.VERSION} version
diff --git a/components/Map/DetournementCard.js b/components/Map/DetournementCard.js
new file mode 100644
index 0000000..ff310d3
--- /dev/null
+++ b/components/Map/DetournementCard.js
@@ -0,0 +1,143 @@
+import React from "react";
+import {Text, View, Button, AsyncStorage } from "react-native";
+import Style from "../../Style";
+import Config from "react-native-config";
+import axios from "axios";
+import CustomPicker from "../CustomPicker";
+
+export default class DetournementCard extends React.Component {
+ constructor(props) {
+ super(props);
+ this.handlePickerChange = this.handlePickerChange.bind(this);
+ this.sendDetournement = this.sendDetournement.bind(this);
+ this.state = {
+ chantier : null,
+ nom : "",
+ prenom : "",
+ origin : null,
+ destination : null,
+ chantiers : [],
+ pickerSelected : null,
+ }
+ };
+
+ async componentDidMount() {
+ this.setState({ chantier : await this.getChantier(this.props.user.chantierId)})
+ await this.getCamionneurInfo();
+ await this.getChantiersExceptCurrent();
+ }
+
+ async getChantier(chantierId){
+ const token = await AsyncStorage.getItem('token');
+ let url = Config.API_URL+ "chantiers/"+ chantierId;
+ return await axios({
+ method : 'get',
+ url : url,
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status != 200){
+ alert(response.status);
+ return response.status;
+ }
+ console.log(response.status);
+ return response.data;
+ })
+ .catch(function (error) {
+ alert(error)
+ console.log(error);
+ });
+ }
+
+ handlePickerChange(value){
+ console.log("value picker : "+value)
+ this.setState({pickerSelected : this.state.chantiers[value]})
+ console.log(" picker : "+ JSON.stringify(this.state.pickerSelected))
+ }
+
+ async getChantiersExceptCurrent(){
+ let res = []
+ let index = 0
+ console.log("CHANTIERS2 : "+ JSON.stringify(this.props.chantiers))
+ for (let i = 0; i < this.props.chantiers.length ; i++){
+ if(this.props.chantiers[i].id !== this.props.user.chantierId){
+ res[index] = this.props.chantiers[i]
+ index++
+ }
+ }
+ console.log("RES : "+ res)
+ await this.setState({pickerSelected : res[0]});
+ await this.setState({chantiers : res})
+
+ }
+
+ sendDetournement(){
+ let chargementLong = this.state.pickerSelected.chargement.longitude;
+ let chargementLat = this.state.pickerSelected.chargement.latitude;
+ let dechargementLong = this.state.pickerSelected.dechargement.longitude;
+ let dechargementLat = this.state.pickerSelected.dechargement.latitude;
+ let chantierId = this.state.pickerSelected.id;
+ let userId = this.props.user.userId;
+ let previousChantierId = this.props.user.chantierId
+ let obj = {
+ "chantierId" : chantierId,
+ "userId" : userId,
+ "originLong" :chargementLong,
+ "originLat" : chargementLat,
+ "destinationLong" : dechargementLong,
+ "destinationLat" : dechargementLat,
+ "previousChantierId": previousChantierId,
+ }
+ console.log("sendDetournement "+JSON.stringify(obj))
+ this.props.socket.emit("chantier/detournement",obj)
+ //this.props.toggleShow();
+ this.props.validate();
+ }
+
+
+ async getCamionneurInfo(){
+ const token = await AsyncStorage.getItem('token');
+ await axios({
+ method: 'get',
+ url: Config.API_URL + "camionneurs/" +this.props.user.userId,
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status != 200){
+ console.log(response.status);
+ }
+ console.log(response.status)
+ this.setState({
+ nom: response.data.nom,
+ prenom : response.data.prenom
+ });
+ })
+ .catch(function (error) {
+ console.log(error);
+ })
+ }
+
+ render() {
+ if(this.props.showDetournementCard && this.state.chantiers.length > 0){
+ let selected = this.state.pickerSelected.nom
+ let pickerData = this.state.chantiers.map(item => item.nom)
+ return(
+
+
+ { this.state.prenom + " " + this.state.nom +" ("+ this.props.user.etat +") "}
+ { this.state.chantier ? this.state.chantier.nom : "null" }
+
+
+
+
+
+
+
+
+ )
+ }else{
+ return null
+ }
+ }
+}
\ No newline at end of file
diff --git a/components/Map/MapAdmin.js b/components/Map/MapAdmin.js
index aba387f..c8c5376 100644
--- a/components/Map/MapAdmin.js
+++ b/components/Map/MapAdmin.js
@@ -1,20 +1,28 @@
import React from "react";
import MapView from 'react-native-maps'
import { UrlTile} from 'react-native-maps'
-import {Text, View, FlatList, Dimensions, StyleSheet,PermissionsAndroid,AsyncStorage, AppState} from "react-native";
+import {
+ Text,
+ View,
+ FlatList,
+ Dimensions,
+ StyleSheet,
+ PermissionsAndroid,
+ AsyncStorage,
+ AppState,
+ TouchableOpacity, Button, TextInput
+} from "react-native";
import TruckMarker from './TruckMarker';
import {Marker, Circle} from "react-native-maps";
-import * as Location from 'expo-location';
-import * as Permissions from 'expo-permissions';
import axios from 'axios';
import CraneView from "../Crane/CraneView";
import io from "socket.io-client";
import KeepAwake from 'react-native-keep-awake';
import Config from "react-native-config";
-import * as RootNavigation from '../../navigation/RootNavigation.js';
-import {widthPercentageToDP as wp, heightPercentageToDP as hp} from 'react-native-responsive-screen';
-
+import Icon from "react-native-vector-icons/FontAwesome5";
+import FuelForm from "../FuelForm";
+const { width, height } = Dimensions.get("window");
export default class MapAdmin extends React.Component {
@@ -29,9 +37,11 @@ export default class MapAdmin extends React.Component {
this.succesConnection = this.succesConnection.bind(this);
this.enableConnection = this.enableConnection.bind(this);
this.onRegionChangeComplete = this.onRegionChangeComplete.bind(this)
+ this.changeShowFuelForm = this.changeShowFuelForm.bind(this)
this.socket = io(Config.API_URL);
this.state = {
socket : null,
+ showFuelForm : false,
currentRegion : {
latitude: this.props.chargement.latitude,
longitude: this.props.chargement.longitude,
@@ -79,7 +89,8 @@ export default class MapAdmin extends React.Component {
// update map when an user connect or disconnect
shouldComponentUpdate(nextProps, nextState) {
- return nextState.users.length != this.state.users.length;
+ return nextState.users.length !== this.state.users.length
+ || nextState.showFuelForm !== this.state.showFuelForm
}
// handle when app is in foreground/background
@@ -167,6 +178,11 @@ export default class MapAdmin extends React.Component {
})
}
+ changeShowFuelForm(){
+ this.setState({showFuelForm: !this.state.showFuelForm})
+ console.log("showFuelForm : " + this.state.showFuelForm)
+ }
+
onRegionChangeComplete(region){
this.setState({currentRegion : region})
}
@@ -192,28 +208,49 @@ export default class MapAdmin extends React.Component {
console.log("users:" + JSON.stringify(this.state.users));
const chargement = {latitude : this.props.chargement.latitude, longitude : this.props.chargement.longitude};
const dechargement = {latitude : this.props.dechargement.latitude, longitude : this.props.dechargement.longitude};
+ console.log("showFuelForm " + this.state.showFuelForm)
return(
-
-
-
-
-
-
-
-
- {this.state.users.map(marker => {
- return ()
- }
- )}
-
-
-
- {this.props.typeOfUser === "crane" ? : null}
-
+
+
+
+
+
+
+
+ {this.state.users.map(marker => {
+ return ()
+ }
+ )}
+
+
+ {(this.state.showFuelForm ) &&
+
+ }
+ {this.props.typeOfUser === "crane" ?
+
+
+ : null}
+
+ {this.props.typeOfUser === "crane" ? : null}
)
}
@@ -221,14 +258,11 @@ export default class MapAdmin extends React.Component {
const styles = StyleSheet.create({
map: {
- width : wp('100%'),
- height: hp('100%'),
+ width : width,
+ height: height,
},
mapCrane: {
- width : wp('100%'),
- height: hp('77%'),
+ width : width,
+ height: height,
},
- progressBar: {
- height: hp('23%')
- }
});
diff --git a/components/Map/MapTest.js b/components/Map/MapTest.js
index 88e1ae2..8f887a8 100644
--- a/components/Map/MapTest.js
+++ b/components/Map/MapTest.js
@@ -2,30 +2,20 @@ import React from "react";
import MapView from 'react-native-maps'
import { UrlTile} from 'react-native-maps'
import {
- Text,
View,
- FlatList,
- Dimensions,
StyleSheet,
- PermissionsAndroid,
AsyncStorage,
AppState,
ActivityIndicator
} from "react-native";
import TruckMarker from './TruckMarker';
import {Marker, Circle} from "react-native-maps";
-import ConnectionToServer from '../Connection/ConnectionToServer';
-import * as Location from 'expo-location';
-import * as Permissions from 'expo-permissions';
import axios from 'axios';
-import CraneView from "../Crane/CraneView";
import io from "socket.io-client";
import KeepAwake from 'react-native-keep-awake';
import Config from "react-native-config";
-import * as RootNavigation from '../../navigation/RootNavigation.js';
import {widthPercentageToDP as wp, heightPercentageToDP as hp} from 'react-native-responsive-screen';
-import {getChantiers} from "../globalHelper/axios";
-import {get} from "react-native/Libraries/TurboModule/TurboModuleRegistry";
+import DetournementCard from "./DetournementCard";
let func = require('../globalHelper/axios');
@@ -57,16 +47,15 @@ export default class MapTest extends React.Component {
etat : null,
appState: AppState.currentState,
chantiers : [],
- ready : false
+ ready : false,
+ showDetournementCard : false,
+ userDetournementCard : null,
};
}
async componentDidMount(){
this.setState({chantiers : await this.getChantiers()});
- console.log("this.state.chantiers before = "+JSON.stringify(this.state.chantiers))
- console.log("size "+ this.state.chantiers.length)
await this.enableConnection();
- console.log("this.state.chantiers edit = "+JSON.stringify(this.state.chantiers))
AppState.addEventListener('change', this.handleAppStateChange);
}
@@ -83,10 +72,7 @@ export default class MapTest extends React.Component {
alert(response.status);
return response.status;
}
- console.log(response.status);
- //console.log(response.data)
return response.data;
-
})
.catch(function (error) {
alert(error)
@@ -96,15 +82,14 @@ export default class MapTest extends React.Component {
// enable socket connection
async enableConnection(){
- console.log("launch enable !");
const userId = await AsyncStorage.getItem('userId');
- for (let i = 0; i < this.state.chantiers.length ; i++){
+ for (let i = 0; i < this.state.chantiers.length ; i++){
let chantiers = [...this.state.chantiers]
let chantier = {...chantiers[i]}
- chantier.chargement = func(chantier.lieuChargementId)
- chantier.dechargement = func(chantier.lieuDéchargementId)
+ console.log("chantier : " + chantier + " n° " + i)
+ chantier.chargement = await func(chantier.lieuChargementId)
+ chantier.dechargement = await func(chantier.lieuDéchargementId)
chantiers[i] = chantier
- console.log("MODIF CHANTIER ----- "+ JSON.stringify(chantier))
this.setState({chantiers : chantiers})
await this.socket.emit("chantier/connect", {
"userId" : userId,
@@ -116,7 +101,6 @@ export default class MapTest extends React.Component {
await this.socket.on("chantier/user/sentCoordinates", this.handleCoordinates);
}
this.setState({ready : true})
- console.log("this.state.chantiers = "+JSON.stringify(this.state.chantiers))
}
// close connection to socket
@@ -131,9 +115,12 @@ export default class MapTest extends React.Component {
AppState.removeEventListener('change', this.handleAppStateChange);
}
- // update map when an user connect or disconnect
+ //update map when an user connect or disconnect
shouldComponentUpdate(nextProps, nextState) {
- return (nextState.users.length != this.state.users.length) || (nextState.chantiers.length != this.state.chantiers.length);
+ return (nextState.users.length !== this.state.users.length)
+ || (nextState.ready !== this.state.ready)
+ || (nextState.chantiers.length !== this.state.chantiers.length)
+ || (nextState.showDetournementCard !== this.state.showDetournementCard);
}
// handle when app is in foreground/background
@@ -170,9 +157,9 @@ export default class MapTest extends React.Component {
console.log("Admin: ACK connection");
}
- async handleConnection(data){
- console.log("Admin: " + data.userId +" is connected")
+ handleConnection(data){
// check if the user connecting is an admin
+ console.log("data : "+ JSON.stringify(data))
let isAdmin = Object.keys(data.coordinates).length === 0 && data.coordinates.constructor === Object;
if(!isAdmin){
let copy = this.state.users.slice();
@@ -205,7 +192,7 @@ export default class MapTest extends React.Component {
async getUserInfo(typeUser,userId){
const token = await AsyncStorage.getItem('token');
- return axios({
+ return await axios({
method: 'get',
url: Config.API_URL + typeUser + '/' + userId,
headers: {'Authorization': 'Bearer ' + token},
@@ -244,46 +231,75 @@ export default class MapTest extends React.Component {
}
}
- render() {
+ render() {
if (!this.state.ready){
return ();
}else {
- console.log("chantiers : "+ JSON.stringify(this.state.chantiers))
- console.log("chantiers[0] : "+ this.state.chantiers[0])
return (
-
-
-
-
- {
- this.state.chantiers.map((chantier, index) => {
- console.log("chantier ? : "+JSON.stringify(chantier))
- return (
- ,
- ,
- ,
-
- )
- }
- )}
-
- {this.state.users.map(marker => {
- return (
-
- )
- }
- )}
-
-
+
+
+ {
+ if(this.state.showDetournementCard) this.setState({showDetournementCard : false})
+ }}
+ style={styles.map}
+ region={this.state.currentRegion}
+ onRegionChangeComplete={this.onRegionChangeComplete}
+ >
+ {this.state.chantiers.map((chantier, index) => {
+ let chargement = {latitude : chantier.chargement.latitude, longitude : chantier.chargement.longitude};
+ return
+ })
+ }
+ {this.state.chantiers.map((chantier, index) => {
+ let dechargement = {latitude : chantier.dechargement.latitude, longitude : chantier.dechargement.longitude};
+ return
+ })
+ }
+ {this.state.chantiers.map((chantier, index) => {
+ let chargement = {latitude : chantier.chargement.latitude, longitude : chantier.chargement.longitude};
+ return
+ })
+ }
+ {this.state.chantiers.map((chantier, index) => {
+ let dechargement = {latitude : chantier.dechargement.latitude, longitude : chantier.dechargement.longitude};
+ return
+ })
+ }
+ {this.state.users.length > 0 && this.state.users.map(marker => {
+ return (
+ this.setState({userDetournementCard: marker})}
+ toggleShow = { () => {
+ this.setState(prevState => ({showDetournementCard : !prevState.showDetournementCard}));
+ } }
+ show = { () => {
+ this.setState(prevState => ({showDetournementCard : false}));
+ this.setState(prevState => ({showDetournementCard : true}));
+ } }
+ />
+ )
+ })
+ }
+
+ {(this.state.showDetournementCard && this.state.userDetournementCard !== null) &&
+ {
+ this.setState(prevState => ({showDetournementCard: !prevState.showDetournementCard}))
+ }}
+ validate = {() => {
+ this.setState({users: []})
+ }}
+ />
+ }
)
}
@@ -294,6 +310,7 @@ const styles = StyleSheet.create({
map: {
width : wp('100%'),
height: hp('100%'),
+ flex : 1,
},
mapCrane: {
width : wp('100%'),
diff --git a/components/Map/Test.js b/components/Map/Test.js
deleted file mode 100644
index 79fe8f3..0000000
--- a/components/Map/Test.js
+++ /dev/null
@@ -1,113 +0,0 @@
-watchLocation(){
- console.log("enter location")
- this.watchID = Geolocation.watchPosition(
- position => {
- const { latitude, longitude } = position.coords;
- console.log("latitude: " +latitude);
-
- this.setState({
- latitude : latitude,
- longitude : longitude
- });
- },
-
- error => console.log(error),
-
- // option
- {
- enableHighAccuracy: true,
- timeout: 10000,
- maximumAge: 1000,
- }
-
- )
-
-}
-
-{
- accuracy: Location.Accuracy.Highest,
- timeInterval: 5000,
- distanceInterval: 10
-},
-
-// Connection to server: socket
-// passer la socket(fonction lister) dans les props du marker dans le marker
-//
-
-import React from "react";
-import MapView from 'react-native-maps'
-import { UrlTile} from 'react-native-maps'
-import {Text, View, FlatList, ListView, StyleSheet,PermissionsAndroid} from "react-native";
-import TruckMarker from './TruckMarker';
-import ConnectionToServer from '../Connection/ConnectionToServer';
-
-
-export default class MapTest extends React.Component {
- constructor(props) {
- super(props);
- this.handleConnection = this.handleConnection.bind(this);
- this.state = {
- socket : null,
- users: [],
- };
- }
-
- async componentDidMount(){
- let s = await new ConnectionToServer();
- await s.listenConnection(this.handleConnection);
- await s.initConnection(56,1);
- s.listenConnection(this.handleConnection);
- this.setState({socket : s});
- }
-
- getChantier(){
-
- }
-
- handleConnection(data){
- console.log(data.userId +" is connected")
- var copy = this.state.users.slice();
- copy.push(data.userId);
- console.log(copy);
- this.setState({
- users : copy
- });
- }
-
- render() {
- return(
-
-
-
-
-
-
-
-
-
- )
- }
-}
-
-
-const styles = StyleSheet.create({
- map: {
- position: 'absolute',
- top: 0,
- left: 0,
- right: 0,
- bottom: 0,
- },
-});
diff --git a/components/Map/TruckMarker.js b/components/Map/TruckMarker.js
index 9e13e2f..6c352e1 100644
--- a/components/Map/TruckMarker.js
+++ b/components/Map/TruckMarker.js
@@ -1,9 +1,9 @@
import React from "react";
import {Callout, Marker} from 'react-native-maps'
-import {Text, View, StyleSheet,AsyncStorage} from "react-native";
+import {Text, View, StyleSheet, AsyncStorage, Button} from "react-native";
import axios from 'axios';
import Config from "react-native-config";
-
+import Style from "../../Style";
export default class TruckMarker extends React.Component {
constructor(props) {
@@ -11,6 +11,7 @@ export default class TruckMarker extends React.Component {
this.handleCoordinates = this.handleCoordinates.bind(this);
this.getCamionneurInfo = this.getCamionneurInfo.bind(this);
this.colorForThisEtat = this.colorForThisEtat.bind(this);
+ this.detournement = this.detournement.bind(this);
this.state = {
socket : this.props.socket,
latitude : this.props.user.coordinates.latitude,
@@ -18,12 +19,13 @@ export default class TruckMarker extends React.Component {
nom: "",
prenom : "",
etat : this.props.user.etat,
+ chantier : "",
}
}
async componentDidMount(){
- //const socket = this.props.socket;
- this.getCamionneurInfo();
+ await this.getCamionneurInfo();
+ this.setState({chantier : await this.getChantier(this.props.user.chantierId)})
await this.state.socket.on("chantier/user/sentCoordinates", this.handleCoordinates);
}
@@ -33,7 +35,7 @@ export default class TruckMarker extends React.Component {
async getCamionneurInfo(){
const token = await AsyncStorage.getItem('token');
- axios({
+ await axios({
method: 'get',
url: Config.API_URL + "camionneurs/" +this.props.user.userId,
headers: {'Authorization': 'Bearer ' + token},
@@ -53,6 +55,29 @@ export default class TruckMarker extends React.Component {
})
}
+ async getChantier(chantierId){
+ const token = await AsyncStorage.getItem('token');
+ let url = Config.API_URL+ "chantiers/"+ chantierId;
+ return await axios({
+ method : 'get',
+ url : url,
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status != 200){
+ alert(response.status);
+ return response.status;
+ }
+ console.log(response.status);
+ console.log("rdata:" + JSON.stringify(response.data));
+ return response.data;
+ })
+ .catch(function (error) {
+ alert(error)
+ console.log(error);
+ });
+ }
+
async handleCoordinates(data){
console.log("Marker: coordinates receive: " + JSON.stringify(data));
if(data.userId == this.props.user.userId){
@@ -85,18 +110,38 @@ export default class TruckMarker extends React.Component {
}
}
+ async detournement() {
+ await this.props.editUser();
+ this.props.show()
+ }
render() {
- return(
-
- )
+ if(this.props.singleChantier){
+ return(
+
+ )
+ }else{
+ return(
+
+ )
+ }
+
}
}
diff --git a/components/Materiau/AutoCompleteMateriaux.js b/components/Materiau/AutoCompleteMateriaux.js
new file mode 100644
index 0000000..0406d0f
--- /dev/null
+++ b/components/Materiau/AutoCompleteMateriaux.js
@@ -0,0 +1,69 @@
+import React from 'react';
+import { StyleSheet, TouchableOpacity , Text, ScrollView , View} from 'react-native';
+import Autocomplete from "react-native-autocomplete-input";
+import PlacePreview from "../Place/PlacePreview";
+export default class AutoCompleteMateriaux extends React.Component {
+
+ constructor (props) {
+ super(props)
+ this.state = {
+ query: '',
+ showPreview :false,
+ }
+ }
+
+ findPlace(query) {
+ if (query === '') {
+ return [];
+ }
+ const { places } = this.props.materiaux;
+ const regex = new RegExp(`${query.trim()}`, 'i');
+ return this.props.materiaux.filter(place => place.nom.search(regex) >= 0);
+ }
+
+ render() {
+ const { query } = this.state;
+ const places = this.findPlace(query);
+ const comp = (a, b) => a.toLowerCase().trim() === b.toLowerCase().trim();
+ const placeHolderName = " type du materiau";
+ if(!this.state.showPreview){
+ return (
+
+ this.setState({ query: text })}
+ placeholder={placeHolderName}
+ containerStyle={styles.autocompleteContainer}
+ renderItem={({ item }) => (
+
+ {
+ this.setState({ query: item.nom });
+ this.props.changeMateriau(item.id);
+ this.setState({showPreview : true});
+ }
+ }>
+ { item.nom }
+
+ )}
+ />
+
+ );
+ }else{
+ return (
+ this.setState({showPreview:false})}
+ changePlace={(idPlace) => this.props.changeMateriau({idPlace})}
+ changeQuery={(query => this.setState({query}))}
+ />
+ );
+ }
+ }
+}
+const styles = StyleSheet.create({
+ autocompleteContainer: {
+ borderWidth: 0,
+ },
+});
\ No newline at end of file
diff --git a/components/Materiau/ListMateriaux.js b/components/Materiau/ListMateriaux.js
new file mode 100644
index 0000000..15df976
--- /dev/null
+++ b/components/Materiau/ListMateriaux.js
@@ -0,0 +1,154 @@
+import React from "react";
+import style from "../../Style";
+import axios from 'axios'
+import {Text, ActivityIndicator, View, FlatList, ScrollView, AsyncStorage, Alert, TextInput} from "react-native";
+import Config from "react-native-config";
+import MateriauRow from "./MateriauRow";
+import ValidateButton from "../ValidateButton";
+
+export default class ListMateriaux extends React.Component {
+ constructor(props) {
+ super(props);
+ this.deleteMateriau = this.deleteMateriau.bind(this);
+ this.reloadData = this.reloadData.bind(this);
+ this.postMateriau = this.postMateriau.bind(this);
+ this.state = {
+ report: null,
+ nom : null
+ };
+ }
+
+ async componentDidMount() {
+ await this.reloadData();
+ }
+
+ async deleteMateriau(id) {
+ const token = await AsyncStorage.getItem('token');
+ let data = { "id" : id};
+ await axios({
+ method : 'delete',
+ url : Config.API_URL + 'materiaux/'+id,
+ headers: {'Authorization': 'Bearer ' + token},
+ data: data
+ })
+ .then( response => {
+ if(response.status !== 204){
+ console.log(response.status);
+ console.log(response.data);
+ }
+ let copy = this.state.report.slice();
+ let index = copy.findIndex(place => place.id === id);
+ if (index > -1) {
+ copy.splice(index, 1);
+ this.setState({
+ report : copy
+ })
+ }
+ console.log(response.data);
+ console.log(response.status);
+ })
+ .catch((error) => {
+ console.log(error);
+ })
+ }
+
+ async postMateriau(){
+ const token = await AsyncStorage.getItem('token');
+ const nom = this.state.nom
+ const data = {
+ "nom" : nom
+ };
+ axios({
+ method: 'post',
+ url: Config.API_URL + 'materiaux',
+ data : data,
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status !== 201){
+ console.log(response.status);
+ alert(response.status);
+ return response.status;
+ }
+ let copy = this.state.report.slice();
+ copy.push(response.data);
+ this.setState({report : copy})
+ alert("le matériau "+ nom +" a bien été créé");
+ console.log(response.status);
+ return response.status;
+ })
+ .catch((error) => {
+ console.log(error);
+ })
+ }
+
+ onPressDeleteMateriau(id){
+ Alert.alert(
+ 'Supprimer un matériau',
+ 'Etes-vous sûr de vouloir supprimer ce matériau ?',
+ [
+ {
+ text: 'OUI',
+ onPress: () => this.deleteMateriau(id)
+ },
+ {
+ text: 'Non',
+ style: 'cancel'
+ },
+ ],
+ { cancelable: false }
+ );
+ }
+
+ async reloadData() {
+ const token = await AsyncStorage.getItem('token');
+ await axios({
+ method : 'get',
+ url : Config.API_URL + 'materiaux',
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status !== 200){
+ console.log(response.status);
+ alert(response.status);
+ return response.status;
+ }
+ console.log(response.status);
+ this.setState({report:response.data})
+ return response.status;
+ })
+ .catch((error) => {
+ console.log(error);
+ })
+ }
+
+ render() {
+ if (this.state.report === null) {
+ return (
+
+
+
+ )
+ } else {
+ return (
+
+
+ Ajouter un matériau :
+
+ this.setState({nom})}
+ value={this.state.nom} placeholder={"Nom du matériau"}/>
+
+
+ this.postMateriau()}/>
+
+ Liste des matériaux :
+ this.onPressDeleteMateriau(id)}/>}
+ />
+
+
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/components/Materiau/MateriauRow.js b/components/Materiau/MateriauRow.js
new file mode 100644
index 0000000..4ec6462
--- /dev/null
+++ b/components/Materiau/MateriauRow.js
@@ -0,0 +1,37 @@
+import React from 'react'
+import {Text, View, AsyncStorage} from 'react-native'
+import {Button} from "react-native-elements";
+import style from "../../Style";
+import {Icon} from "react-native-elements";
+
+export default class MateriauRow extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ typeUser : ""
+ }
+ }
+
+ render() {
+ return (
+
+
+ {this.props.materiau.nom}
+
+
+
+
+ }
+ onPress={() => { this.props.onDelete(this.props.materiau.id) }}
+ title=""
+ type="clear"
+ accessibilityLabel="suppression du lieu"
+ />
+
+
+
+
+ )
+ }
+}
\ No newline at end of file
diff --git a/components/Place/SetGPSLocation.js b/components/Place/AddGPSLocation.js
similarity index 89%
rename from components/Place/SetGPSLocation.js
rename to components/Place/AddGPSLocation.js
index 2b708d2..e5013f6 100644
--- a/components/Place/SetGPSLocation.js
+++ b/components/Place/AddGPSLocation.js
@@ -7,9 +7,10 @@ import axios from 'axios';
import Config from "react-native-config";
import * as RootNavigation from '../../navigation/RootNavigation.js';
import {widthPercentageToDP as wp, heightPercentageToDP as hp} from 'react-native-responsive-screen';
-import {Button} from 'react-native-elements'
+import {Button} from 'react-native-elements';
+import InputText from '../InputText';
-export default class SetGPSLocation extends React.Component {
+export default class AddGPSLocation extends React.Component {
constructor(props) {
super(props);
this.componentDidMount =this.componentDidMount.bind(this);
@@ -54,8 +55,8 @@ export default class SetGPSLocation extends React.Component {
}
confirm(){
- this.props.navigation.goBack();
- RootNavigation.navigate(this.props.route.params.origin, {marker : this.state.marker, type : this.props.route.params.type}, )
+ //this.props.navigation.goBack();
+ RootNavigation.navigate("AddPlace", {marker : this.state.marker} )
//this.props.route.params.setLocation(this.state.marker);
//RootNavigation.goBack();
}
diff --git a/components/Place/AddPlaceForm.js b/components/Place/AddPlaceForm.js
index 3996304..cb20511 100644
--- a/components/Place/AddPlaceForm.js
+++ b/components/Place/AddPlaceForm.js
@@ -1,12 +1,12 @@
import React from 'react'
-import {StyleSheet, TextInput, Modal, Text, TouchableOpacity, AsyncStorage, View} from 'react-native'
+import {TextInput, Text, AsyncStorage, View} from 'react-native'
import ValidateButton from "../ValidateButton";
import axios from 'axios'
import style from './../../Style'
-import {MaterialIcons} from "@expo/vector-icons";
import Config from "react-native-config";
-import {Button} from 'react-native-elements'
+import {Button} from 'react-native-elements';
import * as RootNavigation from '../../navigation/RootNavigation.js';
+import { RadioButton } from 'react-native-paper';
export default class AddWorkSiteForm extends React.Component {
@@ -21,7 +21,7 @@ export default class AddWorkSiteForm extends React.Component {
lon: 3.87671,
lat: 43.610769,
rayon: '',
-
+ checked : 'first'
}
}
@@ -55,13 +55,19 @@ export default class AddWorkSiteForm extends React.Component {
async postPlace(){
const token = await AsyncStorage.getItem('token');
+ if(this.state.adress == '' || this.state.rayon == ''){
+ alert("Veuillez entrer une adresse et/ou un rayon");
+ return;
+ }
const data = {
- "adresse": this.state.adress,
- "longitude": parseFloat(this.state.lon),
- "latitude": parseFloat(this.state.lat),
- "rayon" : parseInt(this.state.rayon),
- };
- console.log(this.state.lon+" => "+parseFloat(this.state.lon))
+ "adresse": this.state.adress,
+ "longitude": parseFloat(this.state.lon),
+ "latitude": parseFloat(this.state.lat),
+ "rayon": parseInt(this.state.rayon),
+ "type": this.state.checked === 'second' ? "carriere" : null,
+ }
+ ;
+ console.log(this.state.lon+" => "+ parseFloat(this.state.lon))
axios({
method: 'post',
url: Config.API_URL + 'lieux',
@@ -86,7 +92,7 @@ export default class AddWorkSiteForm extends React.Component {
}
setGPSLocationPage(){
- RootNavigation.navigate("setGPSLocation", {longitude:this.state.lon, latitude: this.state.lat, origin:"AddPlace", type: "add" });
+ RootNavigation.navigate("AddGPSLocation", {longitude:this.state.lon, latitude: this.state.lat});
}
setLocation(marker){
@@ -100,18 +106,30 @@ export default class AddWorkSiteForm extends React.Component {
render() {
return(
+ Création d'un lieu :
+
+ Chantier
+ this.setState({checked : 'first'})}
+ />
+ this.setState({checked : 'second'})}
+ />
+ Carrière
+
- Création d'un lieu manuel en fonction des points GPS :
this.setState({adress})}
value={this.state.adress} placeholder={" libellé adresse"}/>
- this.setState({rayon})}
+ this.setState({rayon})}
value={this.state.rayon} placeholder={" Rayon du lieu en mètre : exemple 50"}/>
-
this.setGPSLocationPage()}
title={"Placer le lieu"}
/>
-
this.postPlace()}/>
{/* CODE LIEU AUTOMATIQUE
Création d'un lieu automatique en fonction d'une adresse :
@@ -124,7 +142,6 @@ export default class AddWorkSiteForm extends React.Component {
this.getLieu()}/>
*/
}
-
);
}
diff --git a/components/Place/AutoCompletePlaces.js b/components/Place/AutoCompletePlaces.js
index 3d489d2..3caef7a 100644
--- a/components/Place/AutoCompletePlaces.js
+++ b/components/Place/AutoCompletePlaces.js
@@ -15,7 +15,6 @@ export default class AutoCompletePlaces extends React.Component {
}
}
-
findPlace(query) {
if (query === '') {
return [];
@@ -49,7 +48,7 @@ export default class AutoCompletePlaces extends React.Component {
this.setState({showPreview : true});
}
}>
- {item.adresse}
+ {item.adresse +" ("+ (item.type ? item.type : "chantier") +")"}
)}
/>
@@ -68,8 +67,6 @@ export default class AutoCompletePlaces extends React.Component {
}
const styles = StyleSheet.create({
autocompleteContainer: {
- backgroundColor: '#ffffff',
borderWidth: 0,
- marginTop : 30,
},
});
\ No newline at end of file
diff --git a/components/Place/ModifyGPSLocation.js b/components/Place/ModifyGPSLocation.js
new file mode 100644
index 0000000..a627d26
--- /dev/null
+++ b/components/Place/ModifyGPSLocation.js
@@ -0,0 +1,132 @@
+import React from "react";
+import MapView from 'react-native-maps'
+import { UrlTile} from 'react-native-maps'
+import {Text, View, FlatList, Dimensions, StyleSheet,PermissionsAndroid,AsyncStorage } from "react-native";
+import {Marker, Circle} from "react-native-maps";
+import axios from 'axios';
+import Config from "react-native-config";
+import * as RootNavigation from '../../navigation/RootNavigation.js';
+import {widthPercentageToDP as wp, heightPercentageToDP as hp} from 'react-native-responsive-screen';
+import {Button} from 'react-native-elements';
+import InputText from '../InputText';
+
+export default class ModifyGPSLocation extends React.Component {
+ constructor(props) {
+ super(props);
+ this.componentDidMount =this.componentDidMount.bind(this);
+ this.confirm = this.confirm.bind(this);
+ this.updateLieu = this.updateLieu.bind(this);
+ this.state = {
+ currentRegion : {
+ latitude: this.props.route.params.lieu.latitude,
+ longitude: this.props.route.params.lieu.longitude,
+ latitudeDelta: 0.15,
+ longitudeDelta: 0.0421,
+ },
+ marker: {
+ coordinate: {
+ latitude: this.props.route.params.lieu.latitude,
+ longitude: this.props.route.params.lieu.longitude,
+ }
+ }
+ };
+ }
+
+ //initialise location
+ async componentDidMount(){
+
+ }
+
+ async updateLieu(){
+ let token = await AsyncStorage.getItem('token');
+ let adresse = this.props.route.params.lieu.adresse;
+ let rayon = this.props.route.params.lieu.rayon;
+ let id = this.props.route.params.lieu.id;
+ let data = {
+ "adresse": adresse,
+ "longitude": parseFloat(this.state.marker.coordinate.longitude),
+ "latitude": parseFloat(this.state.marker.coordinate.latitude),
+ "rayon" : rayon,
+ };
+ console.log(data)
+ axios({
+ method: 'put',
+ url: Config.API_URL + 'lieux/'+ id,
+ data : data,
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status != 204){
+ console.log(response.status);
+ alert(response.status);
+ return response.status;
+ }
+ console.log(response.status);
+ alert("Le lieu a bien été modifié");
+ return response.status;
+ })
+ .catch((error) => {
+ console.log(error.toString());
+ })
+ }
+
+ onMapPress(e) {
+ this.setState({
+ marker:
+ {
+ coordinate: e.nativeEvent.coordinate,
+ },
+ });
+ }
+
+ onUserPinDragEnd(e){
+ this.setState({
+ marker:
+ {
+ coordinate: e.nativeEvent.coordinate,
+ }
+ });
+ }
+
+ confirm(){
+ this.updateLieu()
+ RootNavigation.navigate("Settings", {marker : this.state.marker, type : this.props.route.params.type}, )
+ //this.props.route.params.setLocation(this.state.marker);
+ //RootNavigation.goBack();
+ }
+
+ render() {
+ console.log("Root navigation:" + JSON.stringify(this.props));
+ console.log("Root navigation:" + typeof this.state.marker.coordinate.longitude);
+ return(
+
+ this.onMapPress(e)}
+ >
+ this.onUserPinDragEnd(e)}
+ >
+
+
+
+ this.confirm()}
+ title={"Valider"}
+ />
+
+
+ )
+ }
+}
+
+const styles = StyleSheet.create({
+ map: {
+ width : wp('100%'),
+ height: hp('70%'),
+ }
+});
diff --git a/components/Place/PlaceRow.js b/components/Place/PlaceRow.js
index 64b92ec..00ac8bb 100644
--- a/components/Place/PlaceRow.js
+++ b/components/Place/PlaceRow.js
@@ -1,12 +1,10 @@
import React from 'react'
-import {Text, TextInput, View, Alert, AsyncStorage} from 'react-native'
+import {Text, View, AsyncStorage} from 'react-native'
import {Button} from "react-native-elements";
import style from "../../Style";
-import axios from 'axios'
import {Icon} from "react-native-elements";
-import * as RootNavigation from "../../navigation/RootNavigation";
-export default class WorkSiteRow extends React.Component {
+export default class PlaceRow extends React.Component {
constructor(props) {
super(props);
this.state = {
diff --git a/components/Road/CoefForm.js b/components/Road/CoefForm.js
new file mode 100644
index 0000000..6568731
--- /dev/null
+++ b/components/Road/CoefForm.js
@@ -0,0 +1,138 @@
+import React from "react";
+import style from "../../Style";
+import {Text, View,AsyncStorage, ActivityIndicator, TextInput, StyleSheet, TouchableOpacity} from "react-native";
+import InputCoef from './InputCoef';
+import axios from 'axios';
+import Config from "react-native-config";
+
+export default class CoefForm extends React.Component {
+ constructor(props) {
+ super(props);
+ this.handleLundi = this.handleLundi.bind(this);
+ this.handleMardi = this.handleMardi.bind(this);
+ this.handleMercredi = this.handleMercredi.bind(this);
+ this.handleJeudi = this.handleJeudi.bind(this);
+ this.handleVendredi = this.handleVendredi.bind(this);
+ this.save = this.save.bind(this);
+ this.getCoefByType = this.getCoefByType.bind(this);
+ this.view = this.view.bind(this);
+ this.state = {
+ lundi :null,
+ mardi : null,
+ mercredi : null,
+ jeudi : null,
+ vendredi : null,
+ loading : true
+ }
+ }
+
+ async componentDidMount(){
+ this.getCoefByType();
+ }
+
+ async getCoefByType(){
+ const token = await AsyncStorage.getItem('token');
+ const type = this.props.type;
+ console.log
+ let url = Config.API_URL + "chantiers/" + this.props.chantier + "/route/" + this.props.type + "/coefs";
+ console.log(url)
+ await axios({
+ method: 'get',
+ url: url,
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then((response) => {
+ console.log(response.status);
+ // set state of all coefficient
+ let tabDataSemaine = response.data[type].JourSemaines;
+ let result = {}
+ tabDataSemaine.map( e => {
+ let semaine = e.nom;
+ result[semaine] = e.Coef.value
+ })
+ this.setState(result);
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ //this.setState({ loading : false})
+ }
+
+ handleLundi(value){
+ this.setState({lundi : value})
+ }
+
+ handleMardi(value){
+ this.setState({mardi : value})
+ }
+
+ handleMercredi(value){
+ this.setState({mercredi : value})
+ }
+
+ handleJeudi(value){
+ this.setState({jeudi : value})
+ }
+
+ handleVendredi(value){
+ this.setState({vendredi : value})
+ }
+
+ async save(day){
+ if(this.state[day] == ""){
+ alert('Entrez un coefficient pour ' + day);
+ }else{
+ const token = await AsyncStorage.getItem('token');
+ const data = {
+ "day" : day,
+ "value" : this.state[day]
+ }
+
+ await axios({
+ method: 'patch',
+ url: Config.API_URL + "chantiers/" + this.props.chantier + "/route/" + this.props.type + "/coefs" ,
+ headers: {'Authorization': 'Bearer ' + token},
+ data : data
+ })
+ .then((response) => {
+ alert("le coefficient de " + day +" pour la route " + this.props.type + " a bien été modifié");
+ console.log(response);
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ }
+ }
+
+ view(){
+ console.log("state" + JSON.stringify(this.state));
+ return(
+
+ this.save("lundi")}/>
+ this.save("mardi")}/>
+ this.save("mercredi")}/>
+ this.save("jeudi")}/>
+ this.save("vendredi")}/>
+
+ )
+ }
+
+ render(){
+ let coefAvailable = this.state.lundi == null && this.state.mardi == null;
+ return (coefAvailable ?
+
+ Pas de coefficient encore défini pour cette route. Contacter un administrateur.
+
+ : this.view());
+ }
+}
+
+const styles = StyleSheet.create({
+ week:{
+ flex : 1,
+ flexDirection : 'column',
+ borderWidth: 1,
+ alignItems: 'center',
+ marginHorizontal : 5,
+ },
+});
diff --git a/components/Road/InputCoef.js b/components/Road/InputCoef.js
new file mode 100644
index 0000000..b3b786a
--- /dev/null
+++ b/components/Road/InputCoef.js
@@ -0,0 +1,50 @@
+import React from 'react'
+import {
+ StyleSheet,
+ TextInput,
+ View,
+ Text,
+ TouchableOpacity
+} from 'react-native';
+import { Input } from 'react-native-elements';
+import Icon from "react-native-vector-icons/FontAwesome5";
+
+export default function InputCoef (props){
+ return(
+
+ {props.placeholder}
+ props.onChangeText(text)}
+ />
+ props.save()}>
+
+
+
+ )
+}
+
+const styles = StyleSheet.create({
+ view:{
+ width:"50%",
+ backgroundColor:"#FFFFFF",
+ height:50,
+ margin:10,
+ justifyContent:"space-between",
+ flexDirection: 'row',
+ alignItems: 'center',
+ padding:10,
+ borderColor : '#abb0b0',
+ },
+ text:{
+ width:"50%",
+ height:40,
+ borderWidth : 1,
+ color:"black"
+ }
+});
diff --git a/components/Road/MapHistory.js b/components/Road/MapHistory.js
new file mode 100644
index 0000000..fe98c3d
--- /dev/null
+++ b/components/Road/MapHistory.js
@@ -0,0 +1,108 @@
+import React from "react";
+import MapView, {Marker} from 'react-native-maps'
+import {
+ View,
+ Dimensions,
+ StyleSheet,
+ AppState, AsyncStorage,
+} from "react-native";
+import KeepAwake from 'react-native-keep-awake';
+import Config from "react-native-config";
+import axios from "axios";
+import TabBarIcon from "../TabBarIcon";
+
+const { width, height } = Dimensions.get("window");
+
+
+export default class MapHistory extends React.Component {
+ constructor(props) {
+ super(props);
+ this.getPoints = this.getPoints.bind(this)
+ this.componentDidMount =this.componentDidMount.bind(this);
+ this.sortie = this.props.route.params.sortie;
+ this.chantier = this.props.route.params.chantier;
+ this.camionneur = this.props.route.params.camionneur;
+ this.state = {
+ points : [],
+ showFuelForm : false,
+ connected : false,
+ users: [],
+ etat : null,
+ appState: AppState.currentState,
+ };
+ }
+
+ async getPoints(){
+ const token = await AsyncStorage.getItem('token');
+ let url = Config.API_URL+ "sorties/"+ this.sortie.id +"/points";
+ await axios({
+ method : 'get',
+ url : url,
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status !== 200){
+ alert(response.status);
+ return response.status;
+ }
+ console.log(response.status);
+ this.setState({points : response.data}) ;
+ })
+ .catch(function (error) {
+ alert(error)
+ console.log(error);
+ });
+ }
+
+ async componentDidMount(){
+ await this.getPoints()
+ }
+
+ render() {
+ console.log("points : "+ JSON.stringify(this.state.points))
+ console.log("points[0] : "+ this.state.points[0])
+ if(this.state.points.length < 1){
+ return null
+ }else{
+ return(
+
+
+
+ {this.state.points.map((waypoint) => {
+ return
+
+ })
+ }
+ {/*
+
+
+ */}
+
+
+ )
+ }
+ }
+}
+
+const styles = StyleSheet.create({
+ map: {
+ width : width,
+ height: height,
+ },
+ mapCrane: {
+ width : width,
+ height: height,
+ },
+});
diff --git a/components/Road/OffRouteHistory.js b/components/Road/OffRouteHistory.js
new file mode 100644
index 0000000..fdd7ad4
--- /dev/null
+++ b/components/Road/OffRouteHistory.js
@@ -0,0 +1,116 @@
+import React from "react";
+import axios from 'axios'
+import {Text, ActivityIndicator, View, ScrollView, AsyncStorage, Alert, FlatList} from "react-native";
+import Config from "react-native-config";
+import style from "../../Style";
+import OffRouteRow from "./OffRouteRow";
+
+
+export default class OffRouteHistory extends React.Component {
+ constructor(props) {
+ super(props);
+ this.deleteWorkSite = this.deleteWorkSite.bind(this);
+ this.reloadData = this.reloadData.bind(this);
+ this.handleDelete = this.handleDelete.bind(this);
+ this.state = {
+ report: null
+ };
+ }
+
+ async componentDidMount() {
+ await this.reloadData();
+ }
+
+ async handleDelete(id){
+ Alert.alert(
+ 'Suppresion de chantier',
+ 'Etes-vous sûr de vouloir supprimer ce chantier ?',
+ [
+ {
+ text: 'OUI',
+ onPress: () => this.deleteWorkSite(id)
+ },
+ {
+ text: 'NON',
+ style: 'cancel'
+ },
+ ],
+ { cancelable: false }
+ );
+ }
+
+ async deleteWorkSite(id) {
+ console.log(id);
+ const token = await AsyncStorage.getItem('token');
+ let data = { "id" : id};
+ await axios({
+ method : 'delete',
+ url : Config.API_URL +'chantiers',
+ headers: {'Authorization': 'Bearer ' + token},
+ data: data
+ })
+ .then( response => {
+ if(response.status !== 204){
+ console.log(response.status);
+ console.log(response.data);
+ }
+ let copy = this.state.report.slice();
+ let index = copy.findIndex(worksite => worksite.id === id);
+ if (index > -1) {
+ copy.splice(index, 1);
+ this.setState({
+ report : copy
+ })
+ }
+ console.log(response.data);
+ console.log(response.status);
+ })
+ .catch((error) => {
+ console.log(error);
+ })
+ }
+
+ async reloadData() {
+ const token = await AsyncStorage.getItem('token');
+ await axios({
+ method : 'get',
+ url : Config.API_URL + 'sorties',
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status !== 200){
+ console.log(response.status);
+ alert(response.status);
+ return response.status;
+ }
+ console.log(response.status);
+ this.setState({report : response.data});
+ return response.status;
+ })
+ .catch((error) => {
+ console.log(error);
+ })
+ }
+
+ render() {
+ if (this.state.report === null) {
+ return (
+
+
+
+ )
+ } else {
+ return (
+
+
+ Liste des sorties de route :
+ this.handleDelete(id)}/>}
+ />
+
+
+ )
+ }
+ }
+}
diff --git a/components/Road/OffRouteRow.js b/components/Road/OffRouteRow.js
new file mode 100644
index 0000000..dbede7d
--- /dev/null
+++ b/components/Road/OffRouteRow.js
@@ -0,0 +1,109 @@
+import React from 'react'
+import {AsyncStorage, Text, View} from 'react-native'
+import style from "../../Style";
+import {Button, Icon} from "react-native-elements";
+import Config from "react-native-config";
+import axios from "axios";
+import * as RootNavigation from "../../navigation/RootNavigation";
+
+export default class OffRouteRow extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ chantier : null,
+ camionneur : null,
+ }
+ }
+
+ async componentDidMount() {
+ await this.getChantier(this.props.item.ChantierId);
+ console.log("this.props.item " + JSON.stringify(this.props.item.ChantierId));
+ await this.setState({camionneur : await this.getCamionneur(this.props.item.CamionneurId)});
+ }
+
+ async getChantier(chantierId){
+ const token = await AsyncStorage.getItem('token');
+ let url = Config.API_URL+ "chantiers/"+ chantierId;
+ await axios({
+ method : 'get',
+ url : url,
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status != 200){
+ alert(response.status);
+ return response.status;
+ }
+ console.log(response.status);
+ this.setState({chantier : response.data});
+ })
+ .catch(function (error) {
+ alert(error)
+ console.log(error);
+ });
+ }
+
+ async getCamionneur(camionneurId){
+ const token = await AsyncStorage.getItem('token');
+ let url = Config.API_URL+ "camionneurs/"+ camionneurId;
+ await axios({
+ method : 'get',
+ url : url,
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status !== 200){
+ alert(response.status);
+ return response.status;
+ }
+ console.log(response.status);
+ this.setState({camionneur : response.data}) ;
+ })
+ .catch(function (error) {
+ alert(error)
+ console.log(error);
+ });
+ }
+
+ render() {
+ console.log("this.props.item " + JSON.stringify(this.props.item));
+ if(this.state.chantier === null){
+ return null
+ }else{
+ return (
+
+
+ {this.state.chantier.nom}
+
+
+
+
+ }
+ onPress={() => { RootNavigation.navigate('mapHistory', {
+ sortie : this.props.item ,
+ chantier : this.state.chantier,
+ camionneur : this.state.camionneur
+ })}}
+ title=""
+ type="clear"
+ accessibilityLabel="visualisation de la sortie de route"
+ />
+
+
+ }
+ onPress={() => { this.props.onDelete(this.props.item.id) }}
+ title=""
+ type="clear"
+ accessibilityLabel="suppression du lieu"
+ />
+
+
+
+
+ )
+ }
+ }
+}
+
diff --git a/components/Road/Road.js b/components/Road/Road.js
index f153b67..c51a958 100644
--- a/components/Road/Road.js
+++ b/components/Road/Road.js
@@ -1,9 +1,10 @@
import React from "react";
import style from "../../Style";
-import {Text, View, ScrollView, AsyncStorage, ActivityIndicator} from "react-native";
+import {Text, View, ScrollView, AsyncStorage, ActivityIndicator, TextInput, StyleSheet} from "react-native";
import {Badge, Button, Icon} from "react-native-elements";
import ActivityStarter from "../../ActivityStarter";
let func = require('../globalHelper/axios');
+import CoefForm from './CoefForm';
export default class Road extends React.Component {
constructor(props) {
@@ -58,15 +59,7 @@ export default class Road extends React.Component {
-
- coefficient :
- Lundi : 1.25
- Mardi : 1.25
- Mercredi : 1.25
- Jeudi : 1.25
- Vendredi : 1.25
- VALIDER
-
+
Déchargement -> Chargement
@@ -95,17 +88,19 @@ export default class Road extends React.Component {
-
- coefficient :
- Lundi : 1.25
- Mardi : 1.25
- Mercredi : 1.25
- Jeudi : 1.25
- Vendredi : 1.25
- VALIDER
-
+
)
}
}
}
+
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ coef : {
+ flex: 1,
+ }
+});
diff --git a/components/Services/setup.js b/components/Services/setup.js
index 93f2843..47e5c58 100644
--- a/components/Services/setup.js
+++ b/components/Services/setup.js
@@ -1,12 +1,16 @@
/*
-Class to check if the app is updated and have all permissions
+Class to check if the app is updated and have all permissions (location an internet enabled)
*/
import axios from 'axios';
import VersionCheck from 'react-native-version-check';
import Config from "react-native-config";
import {AsyncStorage,Alert,BackHandler,Linking} from 'react-native';
-
+import NetInfo from "@react-native-community/netinfo";
+import RNAndroidLocationEnabler from 'react-native-android-location-enabler';
+import RNExitApp from 'react-native-exit-app';
+import * as Permissions from 'expo-permissions';
+import * as Location from 'expo-location';
export default class Setup{
constructor() {
@@ -14,7 +18,15 @@ export default class Setup{
async initSetup(){
- await this.checkUpdate()
+ try{
+ console.log("Setup | begin initSetup");
+ await this.internetCheck();
+ await this.checkUpdate();
+ await this.requestLocationPermission();
+ return 1;
+ }catch(error){
+ console.log(" Setup | initSetup : error "+ err)
+ }
}
// request for get the latest version of the app by type
@@ -31,7 +43,7 @@ export default class Setup{
alert(response.status);
return response.status;
}
- console.log(response.status);
+ console.log("Setup | getLatestVersion : " + response.status);
return response.data;
})
.catch(function (error) {
@@ -60,7 +72,7 @@ export default class Setup{
// check if the current version of app is the latest.
async checkUpdate(){
try{
-
+ console.log("Setup | begin checkUpdate");
// get and split request version
let query = await this.getLatestVersion(Config.VERSION);
let serverVersion = query.numero;
@@ -86,9 +98,83 @@ export default class Setup{
{ cancelable: false }
);
}
-
+ return 0;
}catch (error){
console.log(error);
}
}
+
+ // Check if we have acces to internet
+ async internetCheck(){
+ console.log("Setup | begin internetCheck");
+ return NetInfo.fetch().then(state => {
+ if (state.type === 'cellular' || state.type === 'wifi') {
+ axios({
+ method: 'get',
+ url: Config.API_URL + 'entreprises',
+ timeout: 10000,
+ })
+ .then( response => {
+ console.log("Setup | internetCheck : internet check passed !");
+ }
+ ).catch(function (error) {
+ alert("Erreur réseau ! Vérifier que les données mobiles sont activées");
+ });
+ return 0;
+ }else{
+ alert("Erreur réseau ! Vérifier que les données mobiles sont activées");
+ }
+ }).catch(function (error){
+ alert("error")
+ });
+ }
+
+ async accesLocation(){
+ console.log("Setup | begin accesLocation");
+ let acces = false;
+ while (!acces){
+ await RNAndroidLocationEnabler.promptForEnableLocationIfNeeded({interval: 10000, fastInterval: 5000})
+ .then(data => {
+ console.log("Setup | accesLocation : " + data);
+ acces = true;
+ return 0;
+ }).catch(err => {
+ console.log("Setup | accesLocation : error " + err)
+ });
+ }
+ }
+
+ // ask location to GPS and get current position if granted
+ async requestLocationPermission() {
+ let permission = false;
+ try {
+ console.log("Setup | begin requestLocationPermission");
+ let {granted} = await Permissions.askAsync(Permissions.LOCATION);
+ if (granted) {
+ console.log("Setup | requestLocationPermission : permission to location granted");
+ permission = true;
+ acces = await this.accesLocation();
+ return 0;
+ } else {
+ console.log(" Setup | requestLocationPermission : Location permission denied");
+ // print alert not cancelable
+ Alert.alert(
+ 'Autorisation',
+ "Veuillez modifier les paramètres pour autoriser l'application à accéder à la position ou relancer l'application",
+ [
+ {
+ text: 'Quitter',
+ onPress: () => {
+ RNExitApp.exitApp();
+ },
+ },
+ ],
+ { cancelable: false },
+ );
+ return 1;
+ }
+ } catch (err) {
+ console.log(" Setup | requestLocationPermission : error "+err)
+ }
+ }
}
diff --git a/components/UserPreview.js b/components/UserPreview.js
index 320deca..c613f91 100644
--- a/components/UserPreview.js
+++ b/components/UserPreview.js
@@ -7,7 +7,7 @@ export default class UserPreview extends React.Component {
render() {
return (
- {" Utilisateur sélectionné : "+this.props.user.prenom+" "+this.props.user.nom}
+ {" "+this.props.user.prenom+" "+this.props.user.nom}
}
diff --git a/components/Worksite/AddWorkSiteForm.js b/components/Worksite/AddWorkSiteForm.js
index 7913b66..8e1710c 100644
--- a/components/Worksite/AddWorkSiteForm.js
+++ b/components/Worksite/AddWorkSiteForm.js
@@ -1,14 +1,11 @@
import React from 'react'
-import {StyleSheet, TextInput, ScrollView, Text, TouchableOpacity, AsyncStorage, View } from 'react-native'
+import {StyleSheet, TextInput, Text, AsyncStorage, View } from 'react-native'
import axios from 'axios'
import {Button} from 'react-native-elements'
import AutoCompletePlaces from "../Place/AutoCompletePlaces";
-import AddPlaceForm from "../Place/AddPlaceForm";
-import style from "../../Style";
import {MaterialIcons, Ionicons} from "@expo/vector-icons";
import Config from "react-native-config";
-import InputText from "../InputText";
-import ValidateButton from "../ValidateButton";
+import RadioForm, {RadioButton, RadioButtonInput, RadioButtonLabel} from 'react-native-simple-radio-button';
import * as RootNavigation from '../../navigation/RootNavigation.js';
export default class AddWorkSiteForm extends React.Component {
@@ -36,7 +33,7 @@ export default class AddWorkSiteForm extends React.Component {
async getPlaces(){
const token = await AsyncStorage.getItem('token');
- axios({
+ await axios({
method: 'get',
url: Config.API_URL + 'lieux',
headers: {'Authorization': 'Bearer ' + token}
@@ -107,16 +104,14 @@ export default class AddWorkSiteForm extends React.Component {
recharger
-
this.setState({name})}
value={this.state.name} placeholder={"Nom du chantier"}/>
-
- {/* this.setState({showNewPlaceForm:false})} />*/}
-
- this.setState({idPlace1})} name={"chargement"} places={this.state.places}/>
-
- this.setState({idPlace2})} name={"déchargement"} places={this.state.places}/>
-
+
+ this.setState({idPlace1})} name={"chargement"} places={this.state.places}/>
+
+
+ this.setState({idPlace2})} name={"déchargement"} places={this.state.places}/>
+
this.formSubmit().then(this.props.onReload)}
diff --git a/components/Worksite/ListWorkSite.js b/components/Worksite/ListWorkSite.js
index 344bb0f..1c31cb9 100644
--- a/components/Worksite/ListWorkSite.js
+++ b/components/Worksite/ListWorkSite.js
@@ -1,10 +1,9 @@
import React from "react";
import style from "../../Style";
import axios from 'axios'
-import {Text, ActivityIndicator, View, FlatList, ScrollView, AsyncStorage, Dimensions, Alert} from "react-native";
+import {Text, ActivityIndicator, View, FlatList, ScrollView, AsyncStorage, Alert} from "react-native";
import WorkSiteRow from "./WorkSiteRow";
import ButtonGroupAdmin from "../ButtonGroupAdmin";
-import Search from "../Search";
import Config from "react-native-config";
@@ -45,19 +44,19 @@ export default class ListWorkSite extends React.Component {
console.log(id);
const token = await AsyncStorage.getItem('token');
var data = { "id" : id};
- axios({
+ await axios({
method : 'delete',
url : Config.API_URL +'chantiers',
headers: {'Authorization': 'Bearer ' + token},
data: data
})
.then( response => {
- if(response.status != 204){
+ if(response.status !== 204){
console.log(response.status);
console.log(response.data);
}
- var copy = this.state.report.slice();
- var index = copy.findIndex(worksite => worksite.id === id);
+ let copy = this.state.report.slice();
+ let index = copy.findIndex(worksite => worksite.id === id);
if (index > -1) {
copy.splice(index, 1);
this.setState({
@@ -74,13 +73,13 @@ export default class ListWorkSite extends React.Component {
async reloadData() {
const token = await AsyncStorage.getItem('token');
- axios({
+ await axios({
method : 'get',
url : Config.API_URL + 'chantiers',
headers: {'Authorization': 'Bearer ' + token},
})
.then( response => {
- if(response.status != 200){
+ if(response.status !== 200){
console.log(response.status);
alert(response.status);
return response.status;
@@ -106,8 +105,7 @@ export default class ListWorkSite extends React.Component {
- Liste des chantiers:
-
+ Liste des chantiers :
this.handleDelete(id)}/>}
diff --git a/components/Worksite/WorkSiteSettings.js b/components/Worksite/WorkSiteSettings.js
index 6da64d2..34bf1e2 100644
--- a/components/Worksite/WorkSiteSettings.js
+++ b/components/Worksite/WorkSiteSettings.js
@@ -69,18 +69,24 @@ export default class WorkSiteSettings extends React.Component {
})
}
}else{
- let copy = Object.assign({}, this.state.dechargement);
- copy.latitude = this.props.route.params?.marker.coordinate.latitude;
- copy.longitude = this.props.route.params?.marker.coordinate.longitude;
- this.setState({
- dechargement :copy
- })
+ if(this.state.dechargement.latitude !== this.props.route.params?.marker.coordinate.latitude){
+ let copy = Object.assign({}, this.state.dechargement);
+ copy.latitude = this.props.route.params?.marker.coordinate.latitude;
+ copy.longitude = this.props.route.params?.marker.coordinate.longitude;
+ this.setState({
+ dechargement :copy
+ })
+ }
}
}
}
async updateLieu(lieu){
let token = await AsyncStorage.getItem('token');
+ if(lieu.rayon == '' || lieu.adresse == ''){
+ alert("Veuillez renseigner un rayon ou/et une adresse");
+ return;
+ }
let data = {
"adresse": lieu.adresse,
"longitude": parseFloat(lieu.longitude),
@@ -109,9 +115,8 @@ export default class WorkSiteSettings extends React.Component {
}
setGPSLocationPage(type){
- let lat = type === "chargement" ? this.state.chargement.latitude : this.state.dechargement.latitude;
- let lon = type === "chargement" ? this.state.chargement.longitude : this.state.dechargement.longitude;
- RootNavigation.navigate("setGPSLocation", {longitude:lon, latitude: lat, origin : "Settings", type: type });
+ let lieu = type === "chargement" ? this.state.chargement : this.state.dechargement;
+ RootNavigation.navigate("ModifyGPSLocation", {lieu: lieu, type: type });
}
render(){
@@ -122,6 +127,7 @@ export default class WorkSiteSettings extends React.Component {
)
}else{
+ console.log(" render :" + JSON.stringify(this.state.chargement))
return(
@@ -132,7 +138,7 @@ export default class WorkSiteSettings extends React.Component {
adresse: adresse,
}})} value={this.state.chargement.adresse.toString()} placeholder={" adresse "}/>
Rayon :
- this.setState({ chargement:{
+ this.setState({ chargement:{
...this.state.chargement,
rayon: rayon,
}})} value={this.state.chargement.rayon.toString()} placeholder={" rayon de chargement"}/>
@@ -152,7 +158,7 @@ export default class WorkSiteSettings extends React.Component {
}})} value={this.state.dechargement.adresse.toString()} placeholder={" adresse "}/>
Rayon :
- this.setState({ dechargement:{
+ this.setState({ dechargement:{
...this.state.dechargement,
rayon: rayon,
}})} value={this.state.dechargement.rayon.toString()} placeholder={" rayon de déchargement"}/>
diff --git a/components/globalHelper/axios.js b/components/globalHelper/axios.js
index d0106ba..17578ae 100644
--- a/components/globalHelper/axios.js
+++ b/components/globalHelper/axios.js
@@ -16,9 +16,7 @@ module.exports = async function(lieuID){
return response.status;
}
console.log(response.status);
- //console.log(response.data)
return response.data;
-
})
.catch(function (error) {
alert(error)
@@ -40,9 +38,51 @@ export async function getChantiers() {
return response.status;
}
console.log(response.status);
- console.log(response.data)
return response.data;
+ })
+ .catch(function (error) {
+ alert(error)
+ console.log(error);
+ });
+}
+
+export async function getChantier(chantierId){
+ const token = await AsyncStorage.getItem('token');
+ let url = Config.API_URL+ "chantiers/"+ chantierId;
+ await axios({
+ method : 'get',
+ url : url,
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status !== 200){
+ alert(response.status);
+ return response.status;
+ }
+ console.log(response.status);
+ return response.data;
+ })
+ .catch(function (error) {
+ alert(error)
+ console.log(error);
+ });
+}
+export async function getCamionneur(camionneurId){
+ const token = await AsyncStorage.getItem('token');
+ let url = Config.API_URL+ "camionneurs/"+ camionneurId;
+ await axios({
+ method : 'get',
+ url : url,
+ headers: {'Authorization': 'Bearer ' + token},
+ })
+ .then( response => {
+ if(response.status !== 200){
+ alert(response.status);
+ return response.status;
+ }
+ console.log(response.status);
+ return response.data;
})
.catch(function (error) {
alert(error)
diff --git a/navigation/BottomTabNavigator.js b/navigation/BottomTabNavigator.js
index 60828df..6d4b60e 100644
--- a/navigation/BottomTabNavigator.js
+++ b/navigation/BottomTabNavigator.js
@@ -1,15 +1,13 @@
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
-import { createStackNavigator} from "@react-navigation/stack";
import * as React from 'react';
import TabBarIcon from '../components/TabBarIcon';
import HomeScreen from '../screens/Admin/HomeScreen';
-import LinksScreen from '../screens/Admin/MapScreen';
import UsersScreen from "../screens/Admin/UsersScreen";
import MapScreen from "../screens/Admin/MapScreen";
+import OffRouteScreen from "../screens/Admin/OffRouteScreen";
const BottomTab = createBottomTabNavigator();
-const INITIAL_ROUTE_NAME = 'Home';
export default function BottomTabNavigator({ navigation, route }) {
// Set the header title on the parent stack navigator depending on the
@@ -35,6 +33,14 @@ export default function BottomTabNavigator({ navigation, route }) {
tabBarIcon: ({ focused }) => ,
}}
/>
+ ,
+ }}
+ />
,
}}
/>
,
- }}
- />
- ,
+ title: 'Carriere',
+ tabBarIcon: ({ focused }) => ,
}}
/>
diff --git a/package-lock.json b/package-lock.json
index 94ed0a9..9baeafb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1402,6 +1402,15 @@
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
"dev": true
},
+ "@callstack/react-theme-provider": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@callstack/react-theme-provider/-/react-theme-provider-3.0.5.tgz",
+ "integrity": "sha512-Iec+ybWN0FvNj87sD3oWo/49edGUP0UOSdMnzCJEFJIDYr992ECIuOV89burAAh2/ibPCxgLiK6dmgv2mO/8Tg==",
+ "requires": {
+ "deepmerge": "^3.2.0",
+ "hoist-non-react-statics": "^3.3.0"
+ }
+ },
"@cnakazawa/watch": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz",
@@ -3456,13 +3465,6 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
- "fsevents": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
- "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
- "dev": true,
- "optional": true
- },
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -3920,13 +3922,6 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
- "fsevents": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
- "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
- "dev": true,
- "optional": true
- },
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -4226,13 +4221,6 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
- "fsevents": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
- "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
- "dev": true,
- "optional": true
- },
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -4424,13 +4412,6 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
- "fsevents": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
- "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
- "dev": true,
- "optional": true
- },
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -8363,12 +8344,6 @@
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
}
- },
- "fsevents": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
- "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
- "optional": true
}
}
},
@@ -11957,14 +11932,10 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"fsevents": {
- "version": "1.2.13",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
- "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
- "optional": true,
- "requires": {
- "bindings": "^1.5.0",
- "nan": "^2.12.1"
- }
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
+ "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
+ "optional": true
},
"function-bind": {
"version": "1.1.1",
@@ -17361,6 +17332,16 @@
}
}
},
+ "fsevents": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+ "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+ "optional": true,
+ "requires": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1"
+ }
+ },
"is-number": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
@@ -18214,13 +18195,6 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
- "fsevents": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
- "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
- "dev": true,
- "optional": true
- },
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -18497,13 +18471,6 @@
"path-exists": "^4.0.0"
}
},
- "fsevents": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
- "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
- "dev": true,
- "optional": true
- },
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
@@ -24393,6 +24360,14 @@
"resolved": "https://registry.npmjs.org/react-native-autocomplete-input/-/react-native-autocomplete-input-4.2.0.tgz",
"integrity": "sha512-bLZ9FO3NwcqYY3r6hefEEC4VW45L97kXuCyAqKXW1SJkkG/pGcen6zLq3SMFgoQuG3ryrO/ohz7gme7hFwzjoQ=="
},
+ "react-native-circular-progress": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/react-native-circular-progress/-/react-native-circular-progress-1.3.6.tgz",
+ "integrity": "sha512-0P+RIZ1SdufLNI9oXhZCx1QBwvdkgJeyLHv+243jSvqrRVcfp6E31ktrdZr8QOpI2sG3g3n4NRrtjMxHKL7ryw==",
+ "requires": {
+ "prop-types": "^15.7.2"
+ }
+ },
"react-native-config": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/react-native-config/-/react-native-config-1.3.1.tgz",
@@ -24421,6 +24396,11 @@
}
}
},
+ "react-native-exit-app": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/react-native-exit-app/-/react-native-exit-app-1.1.0.tgz",
+ "integrity": "sha512-Spne19zfMfJvnUTX909EHUqWMk69rATtLJq9XMBGpNSHhx0M7v5yetx2Z87egBhLOqQm+CWfD/oxWzDG8rbIQA=="
+ },
"react-native-flash-message": {
"version": "0.1.15",
"resolved": "https://registry.npmjs.org/react-native-flash-message/-/react-native-flash-message-0.1.15.tgz",
@@ -24471,6 +24451,24 @@
"resolved": "https://registry.npmjs.org/react-native-maps/-/react-native-maps-0.26.1.tgz",
"integrity": "sha512-p4VTB8YB5ZmOmDRCUpoHZkm05amZwhIo04AJMBbB9+JAR2PNNfpo0vceoWX0Mag4wnePkdzPomeWMplr/wimTg=="
},
+ "react-native-paper": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-4.0.1.tgz",
+ "integrity": "sha512-C1kHZ5sS3QU2XdmdHnLAzp88T+FWtkOa+43wYjBClevsDvi72aRf6H9PTs8GS69E8tlNHym3kbVcENgnDPMqhQ==",
+ "requires": {
+ "@callstack/react-theme-provider": "^3.0.5",
+ "color": "^3.1.2",
+ "react-native-safe-area-view": "^0.14.9"
+ }
+ },
+ "react-native-progress": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/react-native-progress/-/react-native-progress-3.6.0.tgz",
+ "integrity": "sha512-zzTe595xaaskyfR5OzaGrU4O0R+YkgdEw+EspgGD7wh8Hu0fs6ue3xLW+HEbTjOCn62pCRivwi3NxbpWNBCC7Q==",
+ "requires": {
+ "prop-types": "^15.7.2"
+ }
+ },
"react-native-ratings": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/react-native-ratings/-/react-native-ratings-6.5.0.tgz",
@@ -24526,11 +24524,79 @@
"resolved": "https://registry.npmjs.org/react-native-simple-radio-button/-/react-native-simple-radio-button-2.7.4.tgz",
"integrity": "sha512-QOZNmJUn0ViBGU+at7wAG/uGzd5PfXi0kMHr9lfTCLXknW/f9f2fOVjxjdHvOCdf/zA/eMJBjGjtusSDzQf1+w=="
},
+ "react-native-simple-time-picker": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/react-native-simple-time-picker/-/react-native-simple-time-picker-0.2.0.tgz",
+ "integrity": "sha1-saEqeICsL1oSALC8PTwAZRlgl9w=",
+ "requires": {
+ "prop-types": "^15.5.10"
+ }
+ },
"react-native-status-bar-height": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/react-native-status-bar-height/-/react-native-status-bar-height-2.5.0.tgz",
"integrity": "sha512-sYBCPYA/NapBSHkdm/IVL4ID3LLlIuLqINi2FBDyMkc2BU9pfSGOtkz9yfxoK39mYJuTrlTOQ7mManARUsYDSA=="
},
+ "react-native-svg": {
+ "version": "12.1.0",
+ "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-12.1.0.tgz",
+ "integrity": "sha512-1g9qBRci7man8QsHoXn6tP3DhCDiypGgc6+AOWq+Sy+PmP6yiyf8VmvKuoqrPam/tf5x+ZaBT2KI0gl7bptZ7w==",
+ "requires": {
+ "css-select": "^2.1.0",
+ "css-tree": "^1.0.0-alpha.39"
+ },
+ "dependencies": {
+ "css-select": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz",
+ "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==",
+ "requires": {
+ "boolbase": "^1.0.0",
+ "css-what": "^3.2.1",
+ "domutils": "^1.7.0",
+ "nth-check": "^1.0.2"
+ }
+ },
+ "css-tree": {
+ "version": "1.0.0-alpha.39",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.39.tgz",
+ "integrity": "sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==",
+ "requires": {
+ "mdn-data": "2.0.6",
+ "source-map": "^0.6.1"
+ }
+ },
+ "css-what": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.3.0.tgz",
+ "integrity": "sha512-pv9JPyatiPaQ6pf4OvD/dbfm0o5LviWmwxNWzblYf/1u9QZd0ihV+PMwy5jdQWQ3349kZmKEx9WXuSka2dM4cg=="
+ },
+ "domelementtype": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
+ },
+ "domutils": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
+ "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
+ "requires": {
+ "dom-serializer": "0",
+ "domelementtype": "1"
+ }
+ },
+ "mdn-data": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz",
+ "integrity": "sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA=="
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
+ }
+ },
"react-native-tab-view": {
"version": "2.15.0",
"resolved": "https://registry.npmjs.org/react-native-tab-view/-/react-native-tab-view-2.15.0.tgz",
@@ -27901,6 +27967,16 @@
"to-regex-range": "^2.1.0"
}
},
+ "fsevents": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+ "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+ "optional": true,
+ "requires": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1"
+ }
+ },
"glob-parent": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
@@ -28536,6 +28612,16 @@
"locate-path": "^3.0.0"
}
},
+ "fsevents": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+ "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+ "optional": true,
+ "requires": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1"
+ }
+ },
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
diff --git a/package.json b/package.json
index f0421e2..d9402ea 100644
--- a/package.json
+++ b/package.json
@@ -44,17 +44,23 @@
"react-native": "~0.63.1",
"react-native-android-location-enabler": "^1.2.1",
"react-native-autocomplete-input": "^4.2.0",
+ "react-native-circular-progress": "^1.3.6",
"react-native-elements": "^1.2.7",
+ "react-native-exit-app": "^1.1.0",
"react-native-flash-message": "^0.1.15",
"react-native-geolocation-service": "^4.0.2",
"react-native-gesture-handler": "^1.6.1",
"react-native-keep-awake": "^4.0.0",
"react-native-maps": "0.26.1",
+ "react-native-paper": "^4.0.1",
+ "react-native-progress": "^3.6.0",
"react-native-reanimated": "~1.7.0",
"react-native-responsive-screen": "^1.4.1",
"react-native-safe-area-context": "^0.7.3",
"react-native-screens": "~2.2.0",
"react-native-simple-radio-button": "^2.7.4",
+ "react-native-simple-time-picker": "^0.2.0",
+ "react-native-svg": "^12.1.0",
"react-native-tab-view": "^2.15.0",
"react-native-unimodules": "~0.9.0",
"react-native-vector-icons": "^6.7.0",
diff --git a/screens/Admin/HomeScreen.js b/screens/Admin/HomeScreen.js
index 61eb4f3..60bd09c 100644
--- a/screens/Admin/HomeScreen.js
+++ b/screens/Admin/HomeScreen.js
@@ -2,7 +2,8 @@ import * as React from 'react';
import {StyleSheet} from 'react-native';
import ListWorkSite from "../../components/Worksite/ListWorkSite";
import WorkSiteSettings from "../../components/Worksite/WorkSiteSettings";
-import setGPSLocation from "../../components/Place/SetGPSLocation";
+import AddGPSLocation from "../../components/Place/AddGPSLocation";
+import ModifyGPSLocation from "../../components/Place/ModifyGPSLocation";
import AddPlaceForm from "../../components/Place/AddPlaceForm";
import WorkSiteScreen from "./WorkSiteScreen";
import {createStackNavigator} from "@react-navigation/stack";
@@ -30,8 +31,13 @@ export default function HomeScreen({navigation}) {
options={({ route }) => ({headerTitle: route.params.worksite.nom})}
/>
({headerTitle: "coordonnées GPS d'un lieu"})}
+ />
+ ({headerTitle: "coordonnées GPS d'un lieu"})}
/>
+ ()}}>
()}}>
+ ({headerTitle: "Sorties de route",})}
+ />
+ ({headerTitle: "Carte sortie de route",})}
+ />
+
+ );
+}
+
diff --git a/screens/Admin/UsersScreen.js b/screens/Admin/UsersScreen.js
index 65d204c..e9af3de 100644
--- a/screens/Admin/UsersScreen.js
+++ b/screens/Admin/UsersScreen.js
@@ -6,13 +6,14 @@ import AddUser from "../../components/User/AddUser";
import Login from "../../components/Login";
import style from "../../Style";
import { createStackNavigator} from "@react-navigation/stack";
+import LogoutButton from "../../components/LogoutButton";
const UserStack = createStackNavigator();
export default function UsersScreen() {
return (
-
+ ()}}>
({headerTitle: route.params.worksite.nom})}
/>
diff --git a/screens/Truck/TruckScreenCarriere.js b/screens/Truck/TruckScreenCarriere.js
new file mode 100644
index 0000000..a5a8dbb
--- /dev/null
+++ b/screens/Truck/TruckScreenCarriere.js
@@ -0,0 +1,24 @@
+import * as React from 'react';
+import {createStackNavigator} from "@react-navigation/stack";
+import TruckView from "../../components/Truck/TruckView";
+import LogoutButton from "../../components/LogoutButton";
+import CarriereTruck from "../../components/Carriere/CarriereTruck";
+
+const HomeStack = createStackNavigator();
+export default function TruckScreenCarriere({navigation,route}) {
+ return (
+ ()}}>
+ ({headerTitle: 'Gestion des carrieres',})}
+ />
+ ({headerTitle: route.params.worksite.nom})}
+ />
+
+ );
+}
\ No newline at end of file