Add information order detail

This commit is contained in:
Nezumi
2023-04-05 20:55:04 +07:00
parent 809e92074d
commit 378ffde31f
31 changed files with 1609 additions and 292 deletions
+13 -4
View File
@@ -1,16 +1,17 @@
plugins { plugins {
id 'com.android.application' id 'com.android.application'
id 'com.google.gms.google-services' id 'com.google.gms.google-services'
id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
} }
android { android {
namespace 'com.capstone.foodify.shipper' namespace 'com.capstone.foodify.shipper'
compileSdk 33 compileSdk 31
defaultConfig { defaultConfig {
applicationId "com.capstone.foodify.shipper" applicationId "com.capstone.foodify.shipper"
minSdk 26 minSdk 26
targetSdk 32 targetSdk 30
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
@@ -27,16 +28,22 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
buildFeatures {
viewBinding true
}
} }
dependencies { dependencies {
implementation 'androidx.core:core-splashscreen:1.0.0' implementation 'androidx.core:core-splashscreen:1.0.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0-beta01' implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.6.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.google.firebase:firebase-auth:21.0.3' implementation 'com.google.firebase:firebase-auth:21.0.3'
implementation 'com.google.firebase:firebase-storage:20.0.1' implementation 'com.google.firebase:firebase-storage:20.0.1'
implementation 'com.google.android.gms:play-services-maps:18.1.0'
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
@@ -48,4 +55,6 @@ dependencies {
implementation 'com.github.gabriel-TheCode:AestheticDialogs:1.3.6' implementation 'com.github.gabriel-TheCode:AestheticDialogs:1.3.6'
implementation 'com.saadahmedev.popup-dialog:popup-dialog:1.0.2' implementation 'com.saadahmedev.popup-dialog:popup-dialog:1.0.2'
implementation 'com.squareup.picasso:picasso:2.71828' implementation 'com.squareup.picasso:picasso:2.71828'
implementation 'com.google.android.gms:play-services-location:21.0.1'
} }
+11 -3
View File
@@ -3,6 +3,10 @@
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application <application
android:allowBackup="true" android:allowBackup="true"
@@ -13,8 +17,12 @@
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.FoodifyShipper" android:theme="@style/Theme.FoodifyShipper"
android:usesCleartextTraffic="true" android:usesCleartextTraffic="true">
tools:targetApi="31"> <receiver
android:name=".GoogleMap.GeofenceBroadcastReceiver"
android:enabled="true"
android:exported="true"></receiver>
<activity <activity
android:name=".Activity.AccountAndProfileActivity" android:name=".Activity.AccountAndProfileActivity"
android:exported="false" /> android:exported="false" />
@@ -23,7 +31,7 @@
android:exported="false" /> android:exported="false" />
<activity <activity
android:name=".Activity.OrderDetailActivity" android:name=".Activity.OrderDetailActivity"
android:exported="false" /> android:exported="true" />
<activity <activity
android:name=".Activity.SignInActivity" android:name=".Activity.SignInActivity"
android:exported="true" android:exported="true"
@@ -1,10 +1,14 @@
package com.capstone.foodify.shipper.API; package com.capstone.foodify.shipper.API;
import com.capstone.foodify.shipper.Model.Shipper;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import retrofit2.Call;
import retrofit2.Retrofit; import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory; import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
import retrofit2.http.Path;
public interface FoodApi { public interface FoodApi {
@@ -15,64 +19,6 @@ public interface FoodApi {
.build() .build()
.create(FoodApi.class); .create(FoodApi.class);
// @GET("products/random?pageSize=10") @GET("shippers/user/{id}")
// Call<Foods> recommendFood(); Call<Shipper> getShipper(@Path("id") int userId);
//
// @GET("products/enable?pageNo=0&pageSize=10&sortBy=createdTime&sortDir=desc")
// Call<Foods> recentFood();
//
// @GET("shops/enable?pageNo=0&pageSize=10&sortBy=id&sortDir=asc")
// Call<Shops> allShops();
//
// @GET("products/search/{name}")
// Call<Foods> searchFoodByName(@Path("name") String name, @Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
//
// @GET("products")
// Call<Foods> listFood(@Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
//
// @GET("categories/randoms?pageNo=0&pageSize=7")
// Call<Categories> listCategory();
//
// @GET("products/categories")
// Call<Foods> listFoodByCategory(@Query("id") List<Integer> id, @Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
//
// @GET("products/categoriesAndName")
// Call<Foods> listFoodByCategoriesAndName(@Query("id") List<Integer> id, @Query("name") String name, @Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
//
// @GET("products/{id}")
// Call<Food> detailFood(@Path("id") String id);
//
// @GET("shops/{id}")
// Call<Shop> detailShop(@Path("id") int id);
//
// @GET("products/shops/{id}")
// Call<Foods> listFoodByShopId(@Path("id") int id, @Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
//
// @GET("districts/{districtId}/wards")
// Call<List<DistrictWardResponse>> wardResponse(@Path("districtId") int district_id);
//
// @GET("districts")
// Call<List<DistrictWardResponse>> districtResponse();
//
// @GET("sliders")
// Call<List<Slider>> listSlider();
//
// @Headers({"accept: */*", "Content-Type: application/json"})
// @POST("auth/signup")
// Call<User> register(@Body User user);
//
// @POST("auth/check")
// Call<CustomResponse> checkEmailOrPhoneExist (@Body User user);
//
// @GET("products/{productId}/comments")
// Call<Comments> getCommentByProductId(@Path("productId") int productId, @Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
//
// @GET("products/{productId}/users/{userId}")
// Call<Comment> getUserComment(@Path("productId") int productId, @Path("userId") int userId);
//
// @GET("shops/{id}")
// Call<Shop> getShopById(@Path("id") int id);
//
// @GET("products/{productId}/user")
// Call<CustomResponse> checkUserBuyProduct(@Path("productId") int productId, @Query("userId") int userId);
} }
@@ -3,6 +3,7 @@ package com.capstone.foodify.shipper.API;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.capstone.foodify.shipper.Common; import com.capstone.foodify.shipper.Common;
import com.capstone.foodify.shipper.Model.Response.Orders;
import com.capstone.foodify.shipper.Model.User; import com.capstone.foodify.shipper.Model.User;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
@@ -20,6 +21,7 @@ import retrofit2.http.Body;
import retrofit2.http.GET; import retrofit2.http.GET;
import retrofit2.http.PUT; import retrofit2.http.PUT;
import retrofit2.http.Path; import retrofit2.http.Path;
import retrofit2.http.Query;
public interface FoodApiToken { public interface FoodApiToken {
Gson gson = new GsonBuilder().setDateFormat("HH:mm:ss dd-MM-yyyy").setLenient().create(); Gson gson = new GsonBuilder().setDateFormat("HH:mm:ss dd-MM-yyyy").setLenient().create();
@@ -41,51 +43,12 @@ public interface FoodApiToken {
.create(FoodApiToken.class); .create(FoodApiToken.class);
// @POST("users/{userId}/loves/{productId}")
// Call<Food> addFoodToFavorite(@Path("userId") int userId, @Path("productId") int productId);
//
// @DELETE("users/{userId}/loves/{productId}")
// Call<Food> removeFoodFromFavorite(@Path("userId") int userId, @Path("productId") int productId);
@GET("users/email/{userEmail}") @GET("users/email/{userEmail}")
Call<User> getUserFromEmail(@Path("userEmail") String userEmail); Call<User> getUserFromEmail(@Path("userEmail") String userEmail);
// @GET("users/{userId}/loves")
// Call<Foods> getListFavoriteFood(@Path("userId") int userId, @Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
//
@PUT("users/{userId}") @PUT("users/{userId}")
Call<User> updateUser(@Path("userId") int userId, @Body User user); Call<User> updateUser(@Path("userId") int userId, @Body User user);
//
// @GET("users/{userId}/loves/{productId}") @GET("shippers/{shipperId}/orders")
// Call<CustomResponse> checkFoodIsFavorite(@Path("userId") int userId, @Path("productId") int productId); Call<Orders> getListOrder(@Path("shipperId") int shipperId, @Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
//
// @POST("users/{userId}/addresses")
// Call<CustomResponse> createAddressUser(@Path("userId") int userId, @Body Address address);
//
// @PUT("users/{userId}/addresses/{addressId}")
// Call<CustomResponse> editAddressUser(@Path("userId") int userId, @Path("addressId") int addressId, @Body Address address);
//
// @DELETE("users/{userId}/addresses/{addressId}")
// Call<CustomResponse> deleteAddressUser(@Path("userId") int userId, @Path("addressId") int addressId);
//
// @POST("users/{userId}/orders")
// Call<Order> createOrder(@Path("userId") int userId, @Body Order order);
//
// @POST("products/{productId}/comments")
// Call<Comment> createComment(@Path("productId") int productId, @Body Comment comment);
//
// @DELETE("products/{productId}/comments/{commentId}")
// Call<CustomResponse> deleteComment(@Path("productId") int productId, @Path("commentId") int commentId);
//
// @PUT("products/{productId}/comments/{commentId}")
// Call<CustomResponse> updateComment(@Path("productId") int productId, @Path("commentId") int commentId, @Body Comment comment);
//
// @GET("users/{userId}/orders/status/{status}")
// Call<Orders> getOrderUser(@Path("userId") int userId, @Path("status") String status, @Query("pageNo") int pageNo, @Query("pageSize") int pageSize, @Query("sortBy") String sortBy, @Query("sortDir") String sortDir);
//
// @DELETE("users/{userId}/orders/{orderId}")
// Call<CustomResponse> deleteOrder(@Path("userId") int userId, @Path("orderId") int orderId);
//
// @PUT("users/{userId}/orders/{orderId}/status")
// Call<CustomResponse> updateOrderStatus(@Path("userId") int userId, @Path("orderId") int orderId, @Query("status") String status);
} }
@@ -1,19 +1,48 @@
package com.capstone.foodify.shipper.Activity; package com.capstone.foodify.shipper.Activity;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate; import androidx.appcompat.app.AppCompatDelegate;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.splashscreen.SplashScreen; import androidx.core.splashscreen.SplashScreen;
import androidx.viewpager2.widget.ViewPager2; import androidx.viewpager2.widget.ViewPager2;
import android.Manifest;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.util.Log;
import android.view.MenuItem; import android.view.MenuItem;
import android.widget.Toast;
import com.capstone.foodify.shipper.BuildConfig;
import com.capstone.foodify.shipper.Common; import com.capstone.foodify.shipper.Common;
import com.capstone.foodify.shipper.R; import com.capstone.foodify.shipper.R;
import com.capstone.foodify.shipper.ViewPagerAdapter; import com.capstone.foodify.shipper.ViewPagerAdapter;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.ResolvableApiException;
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 com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResponse;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.location.Priority;
import com.google.android.gms.location.SettingsClient;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.material.bottomnavigation.BottomNavigationView; import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.navigation.NavigationBarView; import com.google.android.material.navigation.NavigationBarView;
@@ -23,6 +52,22 @@ public class MainActivity extends AppCompatActivity {
ViewPagerAdapter viewPagerAdapter; ViewPagerAdapter viewPagerAdapter;
BottomNavigationView bottomNavigationView; BottomNavigationView bottomNavigationView;
//Location
private static final int REQUEST_CHECK_SETTINGS = 100;
private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 1000;
private static final long FASTEST_UPDATE_IN_MILLISECONDS = 3000;
private static final long MAX_WAIT_TIME_IN_MILLISECONDS = 1000;
private static final int LOCATION_REQUEST_CODE = 100;
private static final String TAG = MainActivity.class.getSimpleName();
private FusedLocationProviderClient mFusedLocationClient;
private SettingsClient mSettingsClient;
private LocationRequest mLocationRequest;
private LocationSettingsRequest mLocationSettingsRequest;
private LocationCallback mLocationCallBack;
private Location mCurrentLocation;
private boolean mRequestingLocationUpdates = false;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@@ -34,6 +79,46 @@ public class MainActivity extends AppCompatActivity {
viewPager2 = findViewById(R.id.viewPager); viewPager2 = findViewById(R.id.viewPager);
bottomNavigation(); bottomNavigation();
if (Common.CURRENT_LOCATION == null) {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mSettingsClient = LocationServices.getSettingsClient(this);
mLocationCallBack = new LocationCallback() {
@Override
public void onLocationResult(@NonNull LocationResult locationResult) {
super.onLocationResult(locationResult);
mCurrentLocation = locationResult.getLastLocation();
Common.CURRENT_LOCATION = mCurrentLocation;
}
};
mLocationRequest = new LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, UPDATE_INTERVAL_IN_MILLISECONDS)
.setWaitForAccurateLocation(false)
.setMinUpdateDistanceMeters(FASTEST_UPDATE_IN_MILLISECONDS)
.setMaxUpdateDelayMillis(MAX_WAIT_TIME_IN_MILLISECONDS)
.build();
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
mLocationSettingsRequest = builder.build();
checkLocationPermission();
}
//Init location user
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
if(mCurrentLocation != null){
Common.CURRENT_LOCATION = mCurrentLocation;
stopLocationUpdates();
}
}
}, 3000);
} }
private void bottomNavigation() { private void bottomNavigation() {
@@ -73,4 +158,131 @@ public class MainActivity extends AppCompatActivity {
} }
}); });
} }
//Location
private void checkLocationPermission(){
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
requestForPermission();
}else {
//Get location
mRequestingLocationUpdates = true;
startLocationUpdates();
}
}
private void requestForPermission() {
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == LOCATION_REQUEST_CODE){
if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
Toast.makeText(this, "Đã cấp quyền thành công!", Toast.LENGTH_SHORT).show();
} else {
showDialogPermission();
}
}
}
private void showDialogPermission() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Hãy cho ứng dụng truy cập vào vị trí của bạn để trải nghiệm tốt hơn!")
.setCancelable(false)
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
openSettings();
dialog.cancel();
}
})
.setNegativeButton("Để sau", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.setTitle("Thông báo!");
alertDialog.show();
}
private void openSettings() {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", BuildConfig.APPLICATION_ID, null);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
private void startLocationUpdates() {
mSettingsClient.checkLocationSettings(mLocationSettingsRequest).addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
@SuppressLint("MissingPermission")
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallBack, Looper.myLooper());
}
}).addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
int statusCode = ((ApiException) e).getStatusCode();
switch (statusCode) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
Log.i(TAG, "Location settings are not satisfied. Attempting to upgrade location settings");
try {
ResolvableApiException rae = (ResolvableApiException) e;
rae.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sie) {
Log.i(TAG, "PendingIntent unable to execute request");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
String errorMessage = "Location settings are inadequate, and cannot be fixed here. Fix in Settings";
Log.e(TAG, errorMessage);
Toast.makeText(MainActivity.this, errorMessage, Toast.LENGTH_SHORT).show();
}
}
});
}
private void stopLocationUpdates() {
mFusedLocationClient.removeLocationUpdates(mLocationCallBack).addOnCompleteListener(this, task -> Log.d(TAG, "Location updates stopped!"));
}
private boolean checkPermission() {
int permissionState = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
return permissionState == PackageManager.PERMISSION_GRANTED;
}
@Override
protected void onResume() {
super.onResume();
if (mRequestingLocationUpdates && checkPermission() && Common.CURRENT_LOCATION == null) {
startLocationUpdates();
}
}
@Override
protected void onPause() {
super.onPause();
if (mRequestingLocationUpdates) {
stopLocationUpdates();
if(Common.CURRENT_LOCATION == null){
if(mCurrentLocation != null)
Common.CURRENT_LOCATION = mCurrentLocation;
}
}
}
} }
@@ -1,36 +1,255 @@
package com.capstone.foodify.shipper.Activity; package com.capstone.foodify.shipper.Activity;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.capstone.foodify.shipper.API.GoogleMapApi;
import com.capstone.foodify.shipper.Adapter.OrderDetailAdapter;
import com.capstone.foodify.shipper.Common;
import com.capstone.foodify.shipper.GoogleMap.GeofenceHelper;
import com.capstone.foodify.shipper.Model.GoogleMap.GoogleMapResponse;
import com.capstone.foodify.shipper.Model.Order;
import com.capstone.foodify.shipper.R; import com.capstone.foodify.shipper.R;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.GeofencingClient;
import com.google.android.gms.location.GeofencingRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.thecode.aestheticdialogs.AestheticDialog;
import com.thecode.aestheticdialogs.DialogAnimation;
import com.thecode.aestheticdialogs.DialogStyle;
import com.thecode.aestheticdialogs.DialogType;
import java.text.DecimalFormat;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class OrderDetailActivity extends AppCompatActivity { public class OrderDetailActivity extends AppCompatActivity {
Button btn_shipping; private static final String TAG = "OrderDetailActivity";
private static final int REQUEST_PHONE_CALL = 1;
Order order;
Button btn_shipping, btn_call, btn_confirm_ship_completed;
TextView order_tracking_number, txt_user_name, txt_phone, txt_address, txt_distance, txt_status, txt_total,
txt_order_time;
String status = "";
ConstraintLayout progressLayout;
RecyclerView rcv_list_order;
OrderDetailAdapter adapter;
LinearLayout layoutConfirmOrder;
private GeofencingClient geofencingClient;
private GeofenceHelper geofenceHelper;
private float GEOFENCE_RADIUS = 100;
private String GEOFENCE_ID = "SOME_GEOFENCE_ID";
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_order_detail); setContentView(R.layout.activity_order_detail);
btn_shipping = findViewById(R.id.btn_shipping); //Get information order
if(getIntent() != null){
order = (Order) getIntent().getSerializableExtra("order");
status = getIntent().getStringExtra("status");
}
initComponent();
initData();
//Check status shipping
if(status != null){
btn_shipping.setVisibility(View.GONE);
layoutConfirmOrder.setVisibility(View.VISIBLE);
}
getDistanceAndCalculateShipCost(order.getAddress());
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, RecyclerView.VERTICAL, false);
rcv_list_order.setLayoutManager(linearLayoutManager);
adapter.setData(order.getOrderDetails());
rcv_list_order.setAdapter(adapter);
btn_shipping.setOnClickListener(new View.OnClickListener() { btn_shipping.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW, if(Common.CURRENT_ORDER == null){
Uri.parse("google.navigation:q=16.0230,108.2498&mode=l")); LatLng latLng = new LatLng(order.getLat(), order.getLng());
intent.setPackage("com.google.android.apps.maps"); addGeofence(latLng, GEOFENCE_RADIUS);
startActivity(intent);
Common.CURRENT_ORDER = order;
Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse("google.navigation:q="+ order.getLat() + "," + order.getLng() + "&mode=l"));
intent.setPackage("com.google.android.apps.maps");
startActivity(intent);
}
} }
}); });
btn_call.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + order.getUser().getPhoneNumber()));
startActivity(intent);
}
});
//Register geofence
geofencingClient = LocationServices.getGeofencingClient(this);
geofenceHelper = new GeofenceHelper(this);
}
private void initComponent(){
adapter = new OrderDetailAdapter();
btn_shipping = findViewById(R.id.btn_shipping);
btn_call = findViewById(R.id.btn_call);
btn_confirm_ship_completed = findViewById(R.id.btn_confirm_ship_complete);
txt_address = findViewById(R.id.txt_address);
order_tracking_number = findViewById(R.id.order_tracking_number);
txt_user_name = findViewById(R.id.txt_userName);
txt_phone = findViewById(R.id.txt_phone);
txt_distance = findViewById(R.id.txt_distance);
txt_status = findViewById(R.id.txt_status);
txt_total = findViewById(R.id.txt_total);
txt_order_time = findViewById(R.id.txt_order_time);
rcv_list_order = findViewById(R.id.list_order);
layoutConfirmOrder = findViewById(R.id.layout1);
progressLayout = findViewById(R.id.progress_layout);
}
private void initData(){
txt_user_name.setText(order.getUser().getFullName());
txt_phone.setText(order.getUser().getPhoneNumber());
txt_address.setText(order.getAddress());
txt_status.setText(translateStatus(order.getStatus()));
txt_total.setText(Common.changeCurrencyUnit(order.getTotal()));
txt_order_time.setText(order.getOrderTime());
}
private String translateStatus(String status){
String statusHasTranslate = null;
if(status.equals("AWAITING")){
statusHasTranslate = "Chờ xác nhận";
}
if(status.equals("CONFIRMED")){
statusHasTranslate = "Đã xác nhận";
}
if(status.equals("SHIPPING")){
statusHasTranslate = "Đang giao";
}
if(status.equals("COMPLETED")){
statusHasTranslate = "Đã giao";
}
if(status.equals("CANCELED")){
statusHasTranslate = "Đã huỷ";
}
return statusHasTranslate;
}
@SuppressLint("MissingPermission")
private void addGeofence(LatLng latLng, float radius) {
Geofence geofence = geofenceHelper.getGeofence(GEOFENCE_ID, latLng, radius, Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_DWELL | Geofence.GEOFENCE_TRANSITION_EXIT);
GeofencingRequest geofencingRequest = geofenceHelper.getGeofencingRequest(geofence);
PendingIntent pendingIntent = geofenceHelper.getPendingIntent();
geofencingClient.addGeofences(geofencingRequest, pendingIntent)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "onSuccess: Geofence Added...");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
String errorMessage = geofenceHelper.getErrorString(e);
Log.d(TAG, "onFailure: " + errorMessage);
}
});
}
private void getDistanceAndCalculateShipCost(String address) {
//Get location from address
GoogleMapApi.apiService.getGeoCode(address, Common.MAP_API).enqueue(new Callback<GoogleMapResponse>() {
@Override
public void onResponse(Call<GoogleMapResponse> call, Response<GoogleMapResponse> response) {
GoogleMapResponse jsonResponse = response.body();
Double lat = jsonResponse.getResults().get(0).getGeometry().getLocation().getLat();
Double lng = jsonResponse.getResults().get(0).getGeometry().getLocation().getLng();
LatLng addressFrom = new LatLng(Common.CURRENT_LOCATION.getLatitude(), Common.CURRENT_LOCATION.getLongitude());
LatLng addressTo = new LatLng(lat, lng);
int distance = CalculationByDistance(addressFrom, addressTo);
txt_distance.setText(distance + " km");
progressLayout.setVisibility(View.GONE);
}
@Override
public void onFailure(Call<GoogleMapResponse> call, Throwable t) {
Toast.makeText(OrderDetailActivity.this, Common.ERROR_CONNECT_SERVER, Toast.LENGTH_SHORT).show();
}
});
} }
public int CalculationByDistance(LatLng from, LatLng to) {
int Radius = 6371;// radius of earth in Km
double lat1 = from.latitude;
double lat2 = to.latitude;
double lon1 = from.longitude;
double lon2 = to.longitude;
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(Math.toRadians(lat1))
* Math.cos(Math.toRadians(lat2)) * Math.sin(dLon / 2)
* Math.sin(dLon / 2);
double c = 2 * Math.asin(Math.sqrt(a));
double valueResult = Radius * c;
double km = valueResult / 1;
DecimalFormat newFormat = new DecimalFormat("####");
return Integer.valueOf(newFormat.format(km));
}
} }
@@ -14,8 +14,10 @@ import androidx.appcompat.app.AppCompatDelegate;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.splashscreen.SplashScreen; import androidx.core.splashscreen.SplashScreen;
import com.capstone.foodify.shipper.API.FoodApi;
import com.capstone.foodify.shipper.API.FoodApiToken; import com.capstone.foodify.shipper.API.FoodApiToken;
import com.capstone.foodify.shipper.Common; import com.capstone.foodify.shipper.Common;
import com.capstone.foodify.shipper.Model.Shipper;
import com.capstone.foodify.shipper.Model.User; import com.capstone.foodify.shipper.Model.User;
import com.capstone.foodify.shipper.R; import com.capstone.foodify.shipper.R;
import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.OnCompleteListener;
@@ -59,35 +61,8 @@ public class SignInActivity extends AppCompatActivity {
if (user != null && Common.CURRENT_USER == null) { if (user != null && Common.CURRENT_USER == null) {
progressLayout.setVisibility(View.VISIBLE); progressLayout.setVisibility(View.VISIBLE);
user.getIdToken(true)
.addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
@Override
public void onComplete(@NonNull Task<GetTokenResult> task) {
if (task.isSuccessful()) {
Common.TOKEN = task.getResult().getToken();
//Get user from database getInformationAndSignInUser(user);
FoodApiToken.apiService.getUserFromEmail(user.getEmail()).enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
User userData = response.body();
if (userData != null) {
Common.CURRENT_USER = userData;
startActivity(new Intent(SignInActivity.this, MainActivity.class));
progressLayout.setVisibility(View.GONE);
}
}
@Override
public void onFailure(Call<User> call, Throwable t) {
}
});
} else {
Toast.makeText(SignInActivity.this, "Error when taking token!", Toast.LENGTH_SHORT).show();
}
}
});
} }
} }
@@ -107,10 +82,6 @@ public class SignInActivity extends AppCompatActivity {
//Init Component //Init Component
initComponent(); initComponent();
setFontUI(); setFontUI();
if(Common.CURRENT_USER != null)
startActivity(new Intent(this, MainActivity.class));
btn_sign_in.setOnClickListener(new View.OnClickListener() { btn_sign_in.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
@@ -173,66 +144,7 @@ public class SignInActivity extends AppCompatActivity {
// Sign in success, update UI with the signed-in user's information // Sign in success, update UI with the signed-in user's information
FirebaseUser user = mAuth.getCurrentUser(); FirebaseUser user = mAuth.getCurrentUser();
//Save user getInformationAndSignInUser(user);
// Paper.book().write("user", user);
user.getIdToken(true)
.addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
@Override
public void onComplete(@NonNull Task<GetTokenResult> task) {
if(task.isSuccessful()){
Common.TOKEN = task.getResult().getToken();
//Get user from database
FoodApiToken.apiService.getUserFromEmail(user.getEmail()).enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
if(response.code() == 200){
User userData = response.body();
if(userData != null){
//Check user is lock or not
if(!userData.isLocked()){
//Check role account
if(userData.getRole().getRoleName().equals("ROLE_USER")){
Common.CURRENT_USER = userData;
//Dismiss progress bar
progressLayout.setVisibility(View.GONE);
startActivity(new Intent(SignInActivity.this, MainActivity.class));
finish();
} else {
Toast.makeText(SignInActivity.this, "Tài khoản không hợp lệ! Vui lòng kiểm tra lại!", Toast.LENGTH_SHORT).show();
FirebaseAuth.getInstance().signOut();
//Dismiss progress bar
progressLayout.setVisibility(View.GONE);
}
} else {
Toast.makeText(SignInActivity.this, "Tài khoản của bạn đã bị khoá!", Toast.LENGTH_SHORT).show();
FirebaseAuth.getInstance().signOut();
//Dismiss progress bar
progressLayout.setVisibility(View.GONE);
}
}
}
}
@Override
public void onFailure(Call<User> call, Throwable t) {
System.out.println("ERROR: " + t);
Common.showErrorServerNotification(SignInActivity.this, "Không thể đăng nhập tài khoản! Vui lòng thử lại sau!");
}
});
} else {
Toast.makeText(SignInActivity.this, "Error when taking token!", Toast.LENGTH_SHORT).show();
}
}
});
} else { } else {
// If sign in fails, display a message to the user. // If sign in fails, display a message to the user.
Toast.makeText(SignInActivity.this, "Thông tin đăng nhập không đúng! Vui lòng kiểm tra và thử lại!", Toast.makeText(SignInActivity.this, "Thông tin đăng nhập không đúng! Vui lòng kiểm tra và thử lại!",
@@ -245,6 +157,66 @@ public class SignInActivity extends AppCompatActivity {
}); });
} }
private void getInformationAndSignInUser(FirebaseUser user) {
user.getIdToken(true)
.addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
@Override
public void onComplete(@NonNull Task<GetTokenResult> task) {
if(task.isSuccessful()){
Common.TOKEN = task.getResult().getToken();
//Get user from database
FoodApiToken.apiService.getUserFromEmail(user.getEmail()).enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
if(response.code() == 200){
User userData = response.body();
if(userData != null){
//Check user is lock or not
if(!userData.isLocked()){
//Check role account
if(userData.getRole().getRoleName().equals("ROLE_SHIPPER")){
Common.CURRENT_USER = userData;
//Get shipper id
getShipperId(userData.getId());
startActivity(new Intent(SignInActivity.this, MainActivity.class));
finish();
} else {
Toast.makeText(SignInActivity.this, "Tài khoản không hợp lệ! Vui lòng kiểm tra lại!", Toast.LENGTH_SHORT).show();
FirebaseAuth.getInstance().signOut();
//Dismiss progress bar
progressLayout.setVisibility(View.GONE);
}
} else {
Toast.makeText(SignInActivity.this, "Tài khoản của bạn đã bị khoá!", Toast.LENGTH_SHORT).show();
FirebaseAuth.getInstance().signOut();
//Dismiss progress bar
progressLayout.setVisibility(View.GONE);
}
}
}
}
@Override
public void onFailure(Call<User> call, Throwable t) {
System.out.println("ERROR: " + t);
Common.showErrorServerNotification(SignInActivity.this, "Không thể đăng nhập tài khoản! Vui lòng thử lại sau!");
}
});
} else {
Toast.makeText(SignInActivity.this, "Error when taking token!", Toast.LENGTH_SHORT).show();
}
}
});
}
private void initData(){ private void initData(){
email = edt_email.getText().toString(); email = edt_email.getText().toString();
password = edt_password.getText().toString(); password = edt_password.getText().toString();
@@ -300,4 +272,22 @@ public class SignInActivity extends AppCompatActivity {
return dataHasValidate; return dataHasValidate;
} }
private void getShipperId(int userId){
FoodApi.apiService.getShipper(userId).enqueue(new Callback<Shipper>() {
@Override
public void onResponse(Call<Shipper> call, Response<Shipper> response) {
if(response.code() == 200){
Common.CURRENT_SHIPPER = response.body();
//Dismiss progress bar
progressLayout.setVisibility(View.GONE);
}
}
@Override
public void onFailure(Call<Shipper> call, Throwable t) {
Toast.makeText(SignInActivity.this, Common.ERROR_CONNECT_SERVER, Toast.LENGTH_SHORT).show();
}
});
}
} }
@@ -1,5 +1,6 @@
package com.capstone.foodify.shipper.Adapter; package com.capstone.foodify.shipper.Adapter;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@@ -11,6 +12,7 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.capstone.foodify.shipper.Activity.OrderDetailActivity; import com.capstone.foodify.shipper.Activity.OrderDetailActivity;
import com.capstone.foodify.shipper.Common;
import com.capstone.foodify.shipper.Model.Order; import com.capstone.foodify.shipper.Model.Order;
import com.capstone.foodify.shipper.R; import com.capstone.foodify.shipper.R;
@@ -21,12 +23,14 @@ import java.util.List;
public class OrderAdapter extends RecyclerView.Adapter<OrderAdapter.OrderViewHolder>{ public class OrderAdapter extends RecyclerView.Adapter<OrderAdapter.OrderViewHolder>{
public List<Order> listOrders; public List<Order> listOrders;
private Activity activity;
public OrderAdapter() { public OrderAdapter(Activity activity) {
this.activity = activity;
} }
public void setData(List<Order> listOrders){ public void setData(List<Order> listOrders){
this.listOrders = listOrders; this.listOrders = listOrders;
notifyDataSetChanged();
} }
@NonNull @NonNull
@@ -40,18 +44,24 @@ public class OrderAdapter extends RecyclerView.Adapter<OrderAdapter.OrderViewHol
public void onBindViewHolder(@NonNull OrderViewHolder holder, int position) { public void onBindViewHolder(@NonNull OrderViewHolder holder, int position) {
Order order = listOrders.get(position); Order order = listOrders.get(position);
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm:ss dd/MM/yyyy");
LocalDateTime now = LocalDateTime.now();
if(order == null) if(order == null)
return; return;
holder.order_tracking_number.setText("Order Id: #" + order.getOrderTrackingNumber()); holder.order_tracking_number.setText("Order Id: #" + order.getOrderTrackingNumber());
holder.user_name.setText("Tên: Nguyễn Văn A"); holder.user_name.setText("Tên: " + order.getUser().getFullName());
holder.phone.setText("0987654321"); holder.phone.setText("Số điện thoại: " + order.getUser().getPhoneNumber());
holder.address.setText("Phạm Như Xương, Hoà Khánh Nam, Liên Chiểu"); holder.address.setText("Địa chỉ: " + order.getAddress());
holder.orderTime.setText(dtf.format(now)); holder.orderTime.setText("Thời gian đặt: " + order.getOrderTime());
holder.total.setText("Tổng: 1.200.000đ"); holder.total.setText("Tổng: " + Common.changeCurrencyUnit(order.getTotal()));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(activity, OrderDetailActivity.class);
intent.putExtra("order", order);
activity.startActivity(intent);
}
});
} }
@Override @Override
@@ -76,13 +86,6 @@ public class OrderAdapter extends RecyclerView.Adapter<OrderAdapter.OrderViewHol
address = itemView.findViewById(R.id.address); address = itemView.findViewById(R.id.address);
orderTime = itemView.findViewById(R.id.order_time); orderTime = itemView.findViewById(R.id.order_time);
total = itemView.findViewById(R.id.total); total = itemView.findViewById(R.id.total);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
context.startActivity(new Intent(context, OrderDetailActivity.class));
}
});
} }
} }
} }
@@ -0,0 +1,97 @@
package com.capstone.foodify.shipper.Adapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.capstone.foodify.shipper.Common;
import com.capstone.foodify.shipper.Model.OrderDetail;
import com.capstone.foodify.shipper.R;
import com.squareup.picasso.Picasso;
import java.util.List;
public class OrderDetailAdapter extends RecyclerView.Adapter<OrderDetailAdapter.OrderDetailViewHolder>{
public List<OrderDetail> listOrder;
public OrderDetailAdapter(){}
public void setData(List<OrderDetail> listOrder){
this.listOrder = listOrder;
}
@NonNull
@Override
public OrderDetailViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_order_detail, parent, false);
return new OrderDetailViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull OrderDetailViewHolder holder, int position) {
OrderDetail order = listOrder.get(position);
if(order == null)
return;
if(order.getFood().getImages().size() == 0){
Picasso.get().load(R.drawable.default_image_food).into(holder.image_view);
} else {
Picasso.get().load(order.getFood().getImages().get(0).getImageUrl()).into(holder.image_view);
}
holder.shop_name.setText(order.getFood().getShop().getName());
holder.quantity.setText("Số lượng: " + order.getQuantity());
holder.food_name.setText(order.getFood().getName());
holder.shop_name.setText(order.getFood().getShop().getName());
//Check value discountPercent
float cost = 0;
if(order.getFood().getDiscountPercent() > 0){
//Calculate final cost when apply discountPercent
cost = order.getFood().getCost() - (order.getFood().getCost() * order.getFood().getDiscountPercent()/100);
//Show discountPercent value on screen
holder.discount.setVisibility(View.VISIBLE);
holder.discount.setText("-" + order.getFood().getDiscountPercent()+ "%");
} else {
cost = order.getFood().getCost();
}
holder.price.setText(Common.changeCurrencyUnit(cost));
}
@Override
public int getItemCount() {
if(listOrder != null)
return listOrder.size();
return 0;
}
public class OrderDetailViewHolder extends RecyclerView.ViewHolder{
ImageView image_view;
TextView food_name, shop_name, price, quantity, discount;
public OrderDetailViewHolder(@NonNull View itemView) {
super(itemView);
//Init Component
image_view = itemView.findViewById(R.id.image_view);
food_name = itemView.findViewById(R.id.food_name_text_view);
shop_name = itemView.findViewById(R.id.shop_name_text_view);
price = itemView.findViewById(R.id.price_text_view);
quantity = itemView.findViewById(R.id.quantity_text_view);
discount = itemView.findViewById(R.id.discount);
}
}
}
@@ -7,23 +7,34 @@ import android.location.Location;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.capstone.foodify.shipper.Model.Order;
import com.capstone.foodify.shipper.Model.Shipper;
import com.capstone.foodify.shipper.Model.User; import com.capstone.foodify.shipper.Model.User;
import com.thecode.aestheticdialogs.AestheticDialog; import com.thecode.aestheticdialogs.AestheticDialog;
import com.thecode.aestheticdialogs.DialogStyle; import com.thecode.aestheticdialogs.DialogStyle;
import com.thecode.aestheticdialogs.DialogType; import com.thecode.aestheticdialogs.DialogType;
import com.thecode.aestheticdialogs.OnDialogClickListener; import com.thecode.aestheticdialogs.OnDialogClickListener;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class Common { public class Common {
public static User CURRENT_USER = null; public static User CURRENT_USER = null;
public static Shipper CURRENT_SHIPPER = null;
public static Order CURRENT_ORDER = null;
public static String TOKEN = null; public static String TOKEN = null;
public static Location CURRENT_LOCATION = null; public static Location CURRENT_LOCATION = null;
public static final String MAP_API = "AIzaSyAY14Ic32UP26Hg6GILznOfbBihiY5BUxw"; public static final String MAP_API = "AIzaSyAY14Ic32UP26Hg6GILznOfbBihiY5BUxw";
public static final String IS_FORGOT_PASSWORD = "isForgotPassword";
public static final String FORMAT_DATE="dd-MM-yyyy"; public static final String FORMAT_DATE="dd-MM-yyyy";
public static final String VALID_EMAIL_ADDRESS_REGEX = "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$"; public static final String VALID_EMAIL_ADDRESS_REGEX = "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$";
public static final String PHONE_CODE = "+84"; public static final String PHONE_CODE = "+84";
public static final String PASSWORD_PATTERN = "^(?=.*[0-9])(?=.*[A-Z])(?=.*[@#$%^&+=!_])(?=\\S+$).{4,}$"; public static final String PASSWORD_PATTERN = "^(?=.*[0-9])(?=.*[A-Z])(?=.*[@#$%^&+=!_])(?=\\S+$).{4,}$";
public static final String PHONE_PATTERN = "^0[98753]{1}\\d{8}$"; public static final String PHONE_PATTERN = "^0[98753]{1}\\d{8}$";
public static final String ERROR_CONNECT_SERVER = "Đã có lỗi kết nối đến hệ thống!";
public static final List<Order> LIST_ORDER = new ArrayList<>();
public static final String SHIPPING_COMPLETED = "1";
public static Typeface setFontBebas(AssetManager assetManager){ public static Typeface setFontBebas(AssetManager assetManager){
return Typeface.createFromAsset(assetManager, "font/bebas.ttf"); return Typeface.createFromAsset(assetManager, "font/bebas.ttf");
@@ -48,4 +59,10 @@ public class Common {
}).show(); }).show();
} }
public static String changeCurrencyUnit(float price){
Locale locale = new Locale("vi", "VN");
NumberFormat fmt = NumberFormat.getCurrencyInstance(locale);
return fmt.format(price);
}
} }
@@ -2,6 +2,8 @@ package com.capstone.foodify.shipper.Fragment;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.core.widget.NestedScrollView;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@@ -9,23 +11,38 @@ import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import com.capstone.foodify.shipper.API.FoodApiToken;
import com.capstone.foodify.shipper.Adapter.OrderAdapter; import com.capstone.foodify.shipper.Adapter.OrderAdapter;
import com.capstone.foodify.shipper.Common; import com.capstone.foodify.shipper.Common;
import com.capstone.foodify.shipper.Model.Order; import com.capstone.foodify.shipper.Model.Order;
import com.capstone.foodify.shipper.Model.Response.Orders;
import com.capstone.foodify.shipper.R; import com.capstone.foodify.shipper.R;
import com.squareup.picasso.Picasso; import com.squareup.picasso.Picasso;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class OrderFragment extends Fragment { public class OrderFragment extends Fragment {
private static int CURRENT_PAGE = 0;
private static int PAGE_SIZE = 8;
private static String SORT_BY = "id";
private static String SORT_DIR = "asc";
private static boolean LAST_PAGE = false;
private List<Order> listOrders = new ArrayList<>(); private List<Order> listOrders = new ArrayList<>();
RecyclerView recyclerView; RecyclerView recyclerView;
OrderAdapter orderAdapter; OrderAdapter orderAdapter;
TextView welcome_text; TextView welcome_text, end_of_list_text_view;
NestedScrollView list_order_layout;
ProgressBar progressBar;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -36,27 +53,77 @@ public class OrderFragment extends Fragment {
//Init Component //Init Component
recyclerView = view.findViewById(R.id.rcv_list_order); recyclerView = view.findViewById(R.id.rcv_list_order);
welcome_text = view.findViewById(R.id.welcome_text); welcome_text = view.findViewById(R.id.welcome_text);
list_order_layout = view.findViewById(R.id.list_order_layout);
progressBar = view.findViewById(R.id.progress_bar);
end_of_list_text_view = view.findViewById(R.id.end_of_list_text);
if(Common.CURRENT_USER != null){ if(Common.CURRENT_USER != null){
welcome_text.setText("Xin chào, " + Common.CURRENT_USER.getFullName() + "!"); welcome_text.setText("Xin chào, " + Common.CURRENT_USER.getFullName() + "!");
} }
orderAdapter = new OrderAdapter(); orderAdapter = new OrderAdapter(getActivity());
getListOrder();
for(int i = 0; i < 5; i++){
int b = (int)(Math.random()*(999999-100000+1)+100000);
listOrders.add(new Order(String.valueOf(b)));
}
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false); LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false);
recyclerView.setLayoutManager(linearLayoutManager); recyclerView.setLayoutManager(linearLayoutManager);
orderAdapter.setData(listOrders);
recyclerView.setAdapter(orderAdapter); recyclerView.setAdapter(orderAdapter);
if (list_order_layout != null) {
list_order_layout.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
@Override
public void onScrollChange(@NonNull NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
if (scrollY == (v.getChildAt(0).getMeasuredHeight() - v.getMeasuredHeight())) {
//When user scroll to bottom, load more data
dataLoadMore();
}
}
});
}
return view; return view;
} }
private void getListOrder(){
if(Common.CURRENT_SHIPPER != null){
FoodApiToken.apiService.getListOrder(Common.CURRENT_SHIPPER.getId(), CURRENT_PAGE++, PAGE_SIZE, SORT_BY, SORT_DIR).enqueue(new Callback<Orders>() {
@Override
public void onResponse(Call<Orders> call, Response<Orders> response) {
if(response.code() == 200){
listOrders.addAll(response.body().getOrders());
orderAdapter.setData(listOrders);
LAST_PAGE = response.body().getPage().isLast();
if(LAST_PAGE)
hideProgressBarAndShowEndOfListText();
} else {
Toast.makeText(getContext(), "Đã có lỗi hệ thống! Mã lỗi: " + response.code(), Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call<Orders> call, Throwable t) {
Toast.makeText(getContext(), Common.ERROR_CONNECT_SERVER, Toast.LENGTH_SHORT).show();
}
});
}
}
private void hideProgressBarAndShowEndOfListText(){
progressBar.setVisibility(View.GONE);
end_of_list_text_view.setVisibility(View.VISIBLE);
}
private void dataLoadMore() {
if(!LAST_PAGE){
getListOrder();
} else {
hideProgressBarAndShowEndOfListText();
}
}
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
@@ -64,4 +131,5 @@ public class OrderFragment extends Fragment {
//Update user name on textview //Update user name on textview
welcome_text.setText("Xin chào, " + Common.CURRENT_USER.getFullName() + "!"); welcome_text.setText("Xin chào, " + Common.CURRENT_USER.getFullName() + "!");
} }
} }
@@ -0,0 +1,48 @@
package com.capstone.foodify.shipper.GoogleMap;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
import com.capstone.foodify.shipper.Activity.OrderDetailActivity;
import com.capstone.foodify.shipper.Common;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.GeofencingEvent;
import java.util.List;
public class GeofenceBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "GeofenceBroadcastReceive";
@Override
public void onReceive(Context context, Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
Log.d(TAG, "onReceive: Error receiving geofence event...");
return;
}
List<Geofence> geofenceList = geofencingEvent.getTriggeringGeofences();
for (Geofence geofence: geofenceList) {
Log.d(TAG, "onReceive: " + geofence.getRequestId());
}
int transitionType = geofencingEvent.getGeofenceTransition();
switch (transitionType) {
case Geofence.GEOFENCE_TRANSITION_ENTER:
Intent newIntent = new Intent(context.getApplicationContext(), OrderDetailActivity.class);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
newIntent.putExtra("order", Common.CURRENT_ORDER);
newIntent.putExtra("status", Common.SHIPPING_COMPLETED);
context.startActivity(newIntent);
break;
}
}
}
@@ -0,0 +1,64 @@
package com.capstone.foodify.shipper.GoogleMap;
import android.app.PendingIntent;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.GeofenceStatusCodes;
import com.google.android.gms.location.GeofencingRequest;
import com.google.android.gms.maps.model.LatLng;
public class GeofenceHelper extends ContextWrapper {
PendingIntent pendingIntent;
public GeofenceHelper(Context base) {
super(base);
}
public GeofencingRequest getGeofencingRequest(Geofence geofence) {
return new GeofencingRequest.Builder()
.addGeofence(geofence)
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
.build();
}
public Geofence getGeofence(String ID, LatLng latLng, float radius, int transitionTypes) {
return new Geofence.Builder()
.setCircularRegion(latLng.latitude, latLng.longitude, radius)
.setRequestId(ID)
.setTransitionTypes(transitionTypes)
.setLoiteringDelay(5000)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.build();
}
public PendingIntent getPendingIntent() {
if (pendingIntent != null) {
return pendingIntent;
}
Intent intent = new Intent(this, GeofenceBroadcastReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
public String getErrorString(Exception e) {
if (e instanceof ApiException) {
ApiException apiException = (ApiException) e;
switch (apiException.getStatusCode()) {
case GeofenceStatusCodes
.GEOFENCE_NOT_AVAILABLE:
return "GEOFENCE_NOT_AVAILABLE";
case GeofenceStatusCodes
.GEOFENCE_TOO_MANY_GEOFENCES:
return "GEOFENCE_TOO_MANY_GEOFENCES";
case GeofenceStatusCodes
.GEOFENCE_TOO_MANY_PENDING_INTENTS:
return "GEOFENCE_TOO_MANY_PENDING_INTENTS";
}
}
return e.getLocalizedMessage();
}
}
@@ -0,0 +1,47 @@
package com.capstone.foodify.shipper.GoogleMap;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import com.capstone.foodify.shipper.R;
import java.util.Random;
public class NotificationHelper extends ContextWrapper {
public NotificationHelper(Context base) {
super(base);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createChannels();
}
}
private String CHANNEL_NAME = "High priority channel";
private String CHANNEL_ID = "com.example.notifications" + CHANNEL_NAME;
@RequiresApi(api = Build.VERSION_CODES.O)
private void createChannels() {
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
notificationChannel.enableLights(true);
notificationChannel.enableVibration(true);
notificationChannel.setDescription("this is the description of the channel.");
notificationChannel.setLightColor(Color.RED);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.createNotificationChannel(notificationChannel);
}
}
@@ -0,0 +1,116 @@
package com.capstone.foodify.shipper.Model;
import java.io.Serializable;
import java.util.List;
public class Food implements Comparable<Food>, Serializable {
private String id;
private String name;
private String description;
private boolean isEnabled;
private float discountPercent;
private float cost;
private float averageRating;
private String reviewCount;
private Shop shop;
private int sold;
private List<Image> images;
public Food() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isEnabled() {
return isEnabled;
}
public void setEnabled(boolean enabled) {
isEnabled = enabled;
}
public float getDiscountPercent() {
return discountPercent;
}
public void setDiscountPercent(float discountPercent) {
this.discountPercent = discountPercent;
}
public float getCost() {
return cost;
}
public void setCost(float cost) {
this.cost = cost;
}
public float getAverageRating() {
return averageRating;
}
public void setAverageRating(float averageRating) {
this.averageRating = averageRating;
}
public String getReviewCount() {
return reviewCount;
}
public void setReviewCount(String reviewCount) {
this.reviewCount = reviewCount;
}
public Shop getShop() {
return shop;
}
public void setShop(Shop shop) {
this.shop = shop;
}
public int getSold() {
return sold;
}
public void setSold(int sold) {
this.sold = sold;
}
public List<Image> getImages() {
return images;
}
public void setImages(List<Image> images) {
this.images = images;
}
@Override
public int compareTo(Food food) {
if(getName().isEmpty() || food.getName().isEmpty()){
return 0;
}
return getName().compareTo(food.getName());
}
}
@@ -0,0 +1,33 @@
package com.capstone.foodify.shipper.Model;
import java.io.Serializable;
public class Image implements Serializable {
private int id;
private String imageUrl;
private int productId;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
}
@@ -1,27 +1,23 @@
package com.capstone.foodify.shipper.Model; package com.capstone.foodify.shipper.Model;
import java.io.Serializable;
import java.util.List; import java.util.List;
public class Order { public class Order implements Serializable {
private int id; private int id;
private String orderTrackingNumber; private String orderTrackingNumber;
private int shipperId;
private String paymentMethod; private String paymentMethod;
private float shippingCost; private float shippingCost;
private float productCost;
private String status; private String status;
private String address; private String address;
private User user;
private Shipper shipper;
private List<OrderDetail> orderDetails; private List<OrderDetail> orderDetails;
private String orderTime;
public Order(String orderTrackingNumber, int shipperId, String paymentMethod, float shippingCost, String status, String address, List<OrderDetail> orderDetails) { private float total;
this.orderTrackingNumber = orderTrackingNumber; private double lat;
this.shipperId = shipperId; private double lng;
this.paymentMethod = paymentMethod;
this.shippingCost = shippingCost;
this.status = status;
this.address = address;
this.orderDetails = orderDetails;
}
public int getId() { public int getId() {
return id; return id;
} }
@@ -41,14 +37,6 @@ public class Order {
this.orderTrackingNumber = orderTrackingNumber; this.orderTrackingNumber = orderTrackingNumber;
} }
public int getShipperId() {
return shipperId;
}
public void setShipperId(int shipperId) {
this.shipperId = shipperId;
}
public String getPaymentMethod() { public String getPaymentMethod() {
return paymentMethod; return paymentMethod;
} }
@@ -96,4 +84,60 @@ public class Order {
public void setListOrderDetail(List<OrderDetail> listOrderDetail) { public void setListOrderDetail(List<OrderDetail> listOrderDetail) {
this.orderDetails = listOrderDetail; this.orderDetails = listOrderDetail;
} }
public float getProductCost() {
return productCost;
}
public void setProductCost(float productCost) {
this.productCost = productCost;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Shipper getShipper() {
return shipper;
}
public void setShipper(Shipper shipper) {
this.shipper = shipper;
}
public String getOrderTime() {
return orderTime;
}
public void setOrderTime(String orderTime) {
this.orderTime = orderTime;
}
public float getTotal() {
return total;
}
public void setTotal(float total) {
this.total = total;
}
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public double getLng() {
return lng;
}
public void setLng(double lng) {
this.lng = lng;
}
} }
@@ -1,11 +1,15 @@
package com.capstone.foodify.shipper.Model; package com.capstone.foodify.shipper.Model;
public class OrderDetail { import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
public class OrderDetail implements Serializable {
private int id; private int id;
private int orderId; @SerializedName("product")
private int productId; private Food food;
private String quantity; private String quantity;
private float subTotal; private float subtotal;
public int getId() { public int getId() {
return id; return id;
@@ -15,22 +19,6 @@ public class OrderDetail {
this.id = id; this.id = id;
} }
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
public String getQuantity() { public String getQuantity() {
return quantity; return quantity;
} }
@@ -39,11 +27,19 @@ public class OrderDetail {
this.quantity = quantity; this.quantity = quantity;
} }
public float getSubTotal() { public float getSubtotal() {
return subTotal; return subtotal;
} }
public void setSubTotal(float subTotal) { public void setSubtotal(float subtotal) {
this.subTotal = subTotal; this.subtotal = subtotal;
}
public Food getFood() {
return food;
}
public void setFood(Food food) {
this.food = food;
} }
} }
@@ -0,0 +1,49 @@
package com.capstone.foodify.shipper.Model;
public class Page {
private int pageNo;
private int pageSize;
private int totalElements;
private int totalPages;
private boolean last;
public int getPageNo() {
return pageNo;
}
public void setPageNo(int pageNo) {
this.pageNo = pageNo;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getTotalElements() {
return totalElements;
}
public void setTotalElements(int totalElements) {
this.totalElements = totalElements;
}
public int getTotalPages() {
return totalPages;
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
public boolean isLast() {
return last;
}
public void setLast(boolean last) {
this.last = last;
}
}
@@ -0,0 +1,27 @@
package com.capstone.foodify.shipper.Model.Response;
import com.capstone.foodify.shipper.Model.Order;
import com.capstone.foodify.shipper.Model.Page;
import java.util.List;
public class Orders {
private List<Order> orders;
private Page page;
public List<Order> getOrders() {
return orders;
}
public void setOrders(List<Order> orders) {
this.orders = orders;
}
public Page getPage() {
return page;
}
public void setPage(Page page) {
this.page = page;
}
}
@@ -0,0 +1,44 @@
package com.capstone.foodify.shipper.Model;
import java.io.Serializable;
import java.util.List;
public class Shipper implements Serializable {
private int id;
private User user;
private Shop shop;
private List<Order> orders;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Shop getShop() {
return shop;
}
public void setShop(Shop shop) {
this.shop = shop;
}
public List<Order> getOrders() {
return orders;
}
public void setOrders(List<Order> orders) {
this.orders = orders;
}
}
@@ -0,0 +1,87 @@
package com.capstone.foodify.shipper.Model;
import java.io.Serializable;
public class Shop implements Serializable {
private int id;
private String name;
private String description;
private String imageUrl;
private boolean isEnabled;
private boolean isStudent;
private int userId;
private double lat;
private double lng;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public boolean isEnabled() {
return isEnabled;
}
public void setEnabled(boolean enabled) {
isEnabled = enabled;
}
public boolean isStudent() {
return isStudent;
}
public void setStudent(boolean student) {
isStudent = student;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public double getLng() {
return lng;
}
public void setLng(double lng) {
this.lng = lng;
}
}
@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M20,8h-3L17,4L3,4c-1.1,0 -2,0.9 -2,2v11h2c0,1.66 1.34,3 3,3s3,-1.34 3,-3h6c0,1.66 1.34,3 3,3s3,-1.34 3,-3h2v-5l-3,-4zM6,18.5c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5zM19.5,9.5l1.96,2.5L17,12L17,9.5h2.5zM18,18.5c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5z"/>
</vector>
@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M23,12l-2.44,-2.79l0.34,-3.69l-3.61,-0.82L15.4,1.5L12,2.96L8.6,1.5L6.71,4.69L3.1,5.5L3.44,9.2L1,12l2.44,2.79l-0.34,3.7l3.61,0.82L8.6,22.5l3.4,-1.47l3.4,1.46l1.89,-3.19l3.61,-0.82l-0.34,-3.69L23,12zM10.09,16.72l-3.8,-3.81l1.48,-1.48l2.32,2.33l5.85,-5.87l1.48,1.48L10.09,16.72z"/>
</vector>
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

@@ -28,7 +28,7 @@
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<TextView <TextView
android:id="@+id/textView" android:id="@+id/txt_order_tracking_number"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
@@ -49,7 +49,7 @@
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textView" app:layout_constraintTop_toBottomOf="@id/txt_order_tracking_number"
android:visibility="visible" android:visibility="visible"
/> />
@@ -64,7 +64,7 @@
<TextView <TextView
android:id="@+id/textView2" android:id="@+id/textView2"
android:text="Thông tin giao hàng" android:text="Thông tin người giao"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:fontFamily="@font/bebas" android:fontFamily="@font/bebas"
@@ -192,13 +192,55 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/distance_layout" android:id="@+id/order_time_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
app:layout_constraintTop_toBottomOf="@id/address_layout" app:layout_constraintTop_toBottomOf="@id/address_layout"
android:orientation="horizontal" android:orientation="horizontal"
> >
<TextView
android:id="@+id/textView5"
android:text="Thời gian đặt:"
android:fontFamily="@font/opensans"
android:textStyle="bold"
android:layout_marginTop="5dp"
android:layout_marginStart="10dp"
android:textColor="@color/black"
android:textSize="15sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/phone_layout"
app:layout_constraintStart_toStartOf="parent"
/>
<TextView
android:id="@+id/txt_order_time"
android:text="2023-05-23"
android:fontFamily="@font/opensans"
android:textStyle="bold"
android:layout_marginTop="5dp"
android:layout_marginStart="10dp"
android:textColor="@color/black"
android:textSize="15sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="@id/textView3"
app:layout_constraintTop_toBottomOf="@id/phone_layout"
app:layout_constraintEnd_toEndOf="parent"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/distance_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toBottomOf="@id/order_time_layout"
android:orientation="horizontal"
>
<TextView <TextView
android:id="@+id/textView4" android:id="@+id/textView4"
android:text="Khoảng cách (tính từ vị trí của bạn):" android:text="Khoảng cách (tính từ vị trí của bạn):"
@@ -260,6 +302,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:id="@+id/txt_status"
/> />
@@ -301,8 +344,28 @@
</LinearLayout> </LinearLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_shipping"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:backgroundTint="@color/green"
android:fontFamily="@font/opensans"
android:text="Giao đến địa chỉ này!"
android:textAllCaps="false"
android:textColor="@color/white"
android:layout_marginTop="30dp"
android:layout_marginStart="60dp"
android:layout_marginEnd="60dp"
app:layout_constraintTop_toBottomOf="@id/total_cost_layout"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:drawableLeft="@drawable/baseline_local_shipping_24"
android:drawableTint="@color/white"
/>
<LinearLayout <LinearLayout
android:id="@+id/btnPaymentMethod" android:id="@+id/layout1"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -310,24 +373,27 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="20dp" android:layout_marginTop="20dp"
android:visibility="gone"
> >
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/btn_shipping" android:id="@+id/btn_call"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:backgroundTint="@color/green" android:backgroundTint="@color/colorGrey"
android:layout_gravity="center" android:layout_gravity="center"
android:fontFamily="@font/opensans" android:fontFamily="@font/opensans"
android:gravity="center" android:gravity="center"
android:text="Giao đến địa chỉ này!" android:text="Gọi điện thoại"
android:textAllCaps="false" android:textAllCaps="false"
android:textStyle="bold"
android:textColor="@color/white" android:textColor="@color/white"
app:iconGravity="textStart" app:iconGravity="textStart"
app:iconPadding="10dp" android:drawableLeft="@drawable/baseline_phone_24"
app:iconTint="@null"/> android:drawableTint="@color/white"
/>
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/btn_confirm_ship_complete" android:id="@+id/btn_confirm_ship_complete"
@@ -338,12 +404,13 @@
android:layout_gravity="center" android:layout_gravity="center"
android:fontFamily="@font/opensans" android:fontFamily="@font/opensans"
android:gravity="center" android:gravity="center"
android:text="Đã giao xong!" android:textStyle="bold"
android:text="Đã giao"
android:textAllCaps="false" android:textAllCaps="false"
android:textColor="@color/white" android:textColor="@color/white"
app:iconGravity="textStart" app:iconGravity="textStart"
app:iconPadding="10dp" android:drawableLeft="@drawable/baseline_verified_24"
app:iconTint="@null"/> android:drawableTint="@color/white"/>
</LinearLayout> </LinearLayout>
@@ -357,7 +424,7 @@
android:background="#80000000" android:background="#80000000"
android:id="@+id/progress_layout" android:id="@+id/progress_layout"
android:clickable="true" android:clickable="true"
android:visibility="gone" android:visibility="visible"
> >
<ProgressBar <ProgressBar
+27 -1
View File
@@ -8,7 +8,9 @@
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:id="@+id/list_order_layout"
>
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -64,6 +66,30 @@
app:layout_constraintTop_toBottomOf="@id/line" app:layout_constraintTop_toBottomOf="@id/line"
/> />
<ProgressBar
android:id="@+id/progress_bar"
android:indeterminateTint="@color/primaryColor"
app:layout_constraintTop_toBottomOf="@id/rcv_list_order"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/end_of_list_text"
android:text="Đã hết"
android:fontFamily="@font/opensans"
android:textColor="@color/grayLight"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/progress_bar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:id="@+id/layout_foreground"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:background="@color/white"
android:padding="5dp"
>
<ImageView
android:id="@+id/image_view"
android:layout_width="95dp"
android:layout_height="95dp"
android:scaleType="centerCrop"
app:riv_corner_radius="10dip"
tools:ignore="ContentDescription" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
android:id="@+id/food_name_text_view"
android:text="Food Name"
android:textSize="15sp"
android:textColor="@color/black"
android:fontFamily="@font/opensans"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="5dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="10dp"
android:layout_weight="0.4"
app:layout_constraintStart_toEndOf="@id/image_view"
app:layout_constraintTop_toTopOf="parent"
android:maxLines="2"
android:ellipsize="end"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="horizontal"
android:layout_weight="0.5"
>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="0.6"
android:layout_marginStart="5dp"
>
<TextView
android:id="@+id/shop_name_text_view"
android:text="Shop Name"
android:textSize="13sp"
android:textColor="@color/secondary"
android:fontFamily="@font/opensans"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
app:layout_constraintStart_toEndOf="@id/image_view"
android:maxLines="1"
android:ellipsize="end"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
>
<TextView
android:id="@+id/price_text_view"
android:text="$5.00"
android:textSize="20sp"
android:textColor="@color/primaryColor"
android:fontFamily="@font/bebas"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/discount"
android:text="-59%"
android:textSize="8sp"
android:textColor="@color/red"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:visibility="gone"
/>
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/quantity_text_view"
android:text="Số lượng: 10"
android:fontFamily="@font/opensans"
android:textColor="@color/black"
android:textSize="13sp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="0.3"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
+1
View File
@@ -2,4 +2,5 @@
<string name="app_name">Foodify Shipper</string> <string name="app_name">Foodify Shipper</string>
<!-- TODO: Remove or change this placeholder text --> <!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string> <string name="hello_blank_fragment">Hello blank fragment</string>
<string name="title_activity_maps">MapsActivity</string>
</resources> </resources>
+1
View File
@@ -6,4 +6,5 @@ buildscript {
plugins { plugins {
id 'com.android.application' version '7.4.2' apply false id 'com.android.application' version '7.4.2' apply false
id 'com.android.library' version '7.4.2' apply false id 'com.android.library' version '7.4.2' apply false
id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin' version '2.0.1' apply false
} }
+1
View File
@@ -15,6 +15,7 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# Android operating system, and which are packaged with your app's APK # Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn # https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true
# Enables namespacing of each library's R class so that its R class includes only the # Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies, # resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library # thereby reducing the size of the R class for that library