Merge branch 'ZohaibIqbalKambrani' of https://gitlab.com/Cloud_Solution/driver-app into development

 Conflicts:
	pubspec.yaml
development
Elham Rababh 4 years ago
commit 7b20f789f6

@ -43,6 +43,8 @@ android {
targetSdkVersion 30 targetSdkVersion 30
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
multiDexEnabled true
} }
buildTypes { buildTypes {

@ -24,8 +24,7 @@
to determine the Window background behind the Flutter UI. --> to determine the Window background behind the Flutter UI. -->
<meta-data <meta-data
android:name="io.flutter.embedding.android.NormalTheme" android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" android:resource="@style/NormalTheme" />
/>
<!-- Displays an Android View that continues showing the launch screen <!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual screen fades out. A splash screen is useful to avoid any visual

@ -0,0 +1 @@
include ':app'

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 919 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

@ -2,26 +2,27 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
/// End points /// End points
const BASE_URL = 'https://hmgwebservices.com/Services'; const isUAT = true;
const GET_PROJECT = '/Lists.svc/REST/GetProject'; const BASE_URL = 'https://${isUAT ? "uat." : ""}hmgwebservices.com/';
const LOGIN = "/Authentication.svc/REST/CheckDriverAuthentication";
const GET_OPT = const PING_SERVICE = '/Services/Weather.svc/REST/CheckConnectivity';
"/Patients.svc/REST/PatientER_Delivery_SendSMSForForgetPassword"; const GET_PROJECT = '/Services/Lists.svc/REST/GetProject';
const CHECK_ACTIVATION_CODE = const LOGIN = "/Services/Authentication.svc/REST/CheckDriverAuthentication";
"/Patients.svc/REST/PatientER_Delivery_CheckActivationCodeForForgetPassword"; const GET_OPT = "/Services/Patients.svc/REST/PatientER_Delivery_SendSMSForForgetPassword";
const CHANGE_FORGOT_PASSWORD = const CHECK_ACTIVATION_CODE = "/Services/Patients.svc/REST/PatientER_Delivery_CheckActivationCodeForForgetPassword";
"/Patients.svc/REST/PatientER_Delivery_ChangeForgetedPasswordForDriver"; const CHANGE_FORGOT_PASSWORD = "/Services/Patients.svc/REST/PatientER_Delivery_ChangeForgetedPasswordForDriver";
const GET_ALL_ORDERS = '/Patients.svc/REST/PatientER_Delivery_GetAllOrder'; const GET_ALL_ORDERS = '/Services/Patients.svc/REST/PatientER_Delivery_GetAllOrder';
const SCAN_QR = '/Patients.svc/REST/PatientER_Delivery_OrderInsert'; const SCAN_QR = '/Services/Patients.svc/REST/PatientER_Delivery_OrderInsert';
const UPDATE_ORDER_STATUS = const UPDATE_ORDER_STATUS = '/Services/Patients.svc/REST/PatientER_Delivery_UpdateOrderStatus';
'/Patients.svc/REST/PatientER_Delivery_UpdateOrderStatus'; const NEXT_ORDER = "/Services/Patients.svc/REST/PatientER_Delivery_NextOrder";
const NEXT_ORDER = "/Patients.svc/REST/PatientER_Delivery_NextOrder"; const UPDATE_DRIVER_LOCATION = "/Services/Patients.svc/REST/PatientER_DriverLocation_Insert";
const INITIATE_DELIVERY = "/epharmacy/api/sendsmstocustomerfordriver";
const GET_ALL_DELIVERD_ORDER = const VERIFY_DELIVERY = "/Services/Patients.svc/REST/PatientER_ValidateSentOutForDeliveryOTPCode";
'/Patients.svc/REST/PatientER_Delivery_GetAllDeliverdOrder';
const GET_ALL_ORDERS_STATUS = const GET_ALL_DELIVERD_ORDER = '/Services/Patients.svc/REST/PatientER_Delivery_GetAllDeliverdOrder';
'/Patients.svc/REST/PatientER_Delivery_GetAllOrderstatus'; const GET_ALL_ORDERS_STATUS = '/Services/Patients.svc/REST/PatientER_Delivery_GetAllOrderstatus';
/// Body Constant /// Body Constant
const CHANNEL = 9; const CHANNEL = 9;
@ -41,3 +42,11 @@ const LINEAR_GRADIENT = LinearGradient(
], ],
// stops: [0.0, 1.0], // stops: [0.0, 1.0],
); );
abstract class DeliveryStatus{
static final int pending = 1;
static final int delivered = 2;
static final int rejected = 3;
static final int cancel = 4;
}

@ -82,4 +82,45 @@ const Map<String, Map<String, String>> localizedValues = {
'en': 'Please Enter your OPT code sent to your phone', 'en': 'Please Enter your OPT code sent to your phone',
'ar': 'الرجاء إدخال رمز OPT الخاص بك المرسل إلى هاتفك' 'ar': 'الرجاء إدخال رمز OPT الخاص بك المرسل إلى هاتفك'
}, },
'enterCustomerVerificationCodeMsg': {
'en': 'Please enter OTP sent to customer phone',
'ar': 'Please enter OTP sent to customer phone'
},
'startDelivery': {
'en': 'Start Delivery',
'ar': 'Start Delivery'
},
'deliveryOption': {
'en': 'Delivery Option',
'ar': 'Delivery Option'
},
'selectReason': {
'en': 'Select Reason',
'ar': 'Select Reason'
},
'accident': {
'en': 'Got accident',
'ar': 'Got accident'
},
'notReachableOnPhoneCall': {
'en': 'Not reachable on phone call',
'ar': 'Not reachable on phone call'
},
'notAvailableAtlocation': {
'en': 'Not available at location',
'ar': 'Not available at location'
},
'deliverLater': {
'en': 'Deliver later',
'ar': 'Deliver later'
},
'other': {
'en': 'Other...',
'ar': 'Other...'
},
}; };

@ -1,5 +1,6 @@
const TOKEN = 'token'; const TOKEN = 'token';
const APP_LANGUAGE = 'language'; const APP_LANGUAGE = 'language';
const USER_PROFILE = 'user-profile'; const USER_PROFILE = 'user-profile';
const ACTIVE_DELIVERIES = 'active-order-deliveries';

@ -0,0 +1,11 @@
class ResponseModel<T>{
bool isSuccessful = false;
String message;
T data;
isSuccessfull(Function(bool) callback){
callback(isSuccessful);
}
ResponseModel({this.message, this.isSuccessful, this.data});
}

@ -0,0 +1,12 @@
class RequestInitiateOrderDelivery{
int orderNo = 0;
String mobileNumber = "";
RequestInitiateOrderDelivery({this.orderNo, this.mobileNumber});
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['OrderNo'] = this.orderNo;
data['MobileNumber'] = this.mobileNumber;
return data;
}
}

@ -0,0 +1,12 @@
class RequestValidateDelivery{
String pinCode;
int orderNo;
RequestValidateDelivery({this.orderNo,this.pinCode});
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['Password'] = this.pinCode;
data['OrderNo'] = this.orderNo;
return data;
}
}

@ -0,0 +1,3 @@
class ResponseInitiateOrderDelivery{
}

@ -27,6 +27,11 @@ class PendingOrdersRes {
dynamic distanceInKilometers; dynamic distanceInKilometers;
List<ItemsQuantitiesList> itemsQuantitiesList; List<ItemsQuantitiesList> itemsQuantitiesList;
String receiverFullName(){
var fullName = "${firstName ?? ''} ${middleName ?? ''} ${lastName ?? ''}";
return fullName;
}
PendingOrdersRes( PendingOrdersRes(
{this.rowID, {this.rowID,
this.orderID, this.orderID,

@ -0,0 +1,23 @@
import 'package:driverapp/config/shared_pref_kay.dart';
import 'package:driverapp/core/model/authentication/authenticated_user.dart';
import 'package:driverapp/uitl/app_shared_preferences.dart';
import 'package:location/location.dart';
class RequestUpdateDriverLocation{
int orderID = 0;
LocationData location;
RequestUpdateDriverLocation({this.orderID,this.location});
Future<Map<String, dynamic>> toJson() async{
final Map<String, dynamic> data = new Map<String, dynamic>();
data['OrderID'] = this.orderID;
data['Latitude'] = "${this.location.latitude}";
data['Longitude'] = "${this.location.longitude}";
Map profile = await AppSharedPreferences().getObject(USER_PROFILE);
AuthenticatedUser doctorProfile = AuthenticatedUser.fromJson(profile);
data['DriverID'] = doctorProfile?.iD;
data['UserID'] = '${doctorProfile?.iD}';
return data;
}
}

@ -16,21 +16,23 @@ AppSharedPreferences sharedPref = new AppSharedPreferences();
/// body: null); /// body: null);
class BaseAppClient { class BaseAppClient {
post( String _Statictoken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
String endPoint, { post(
Map<String, dynamic> body, String endPoint, {
Function(dynamic response, int statusCode) onSuccess, Map<String, dynamic> body,
Function(String error, int statusCode) onFailure, Function(dynamic response, int statusCode) onSuccess,
}) async { Function(String error, int statusCode) onFailure}) async {
String url = BASE_URL + endPoint; String url = BASE_URL + endPoint;
try { try {
Map profile = await sharedPref.getObject(USER_PROFILE); Map profile = await sharedPref.getObject(USER_PROFILE);
String token = await sharedPref.getString(TOKEN); String token = await sharedPref.getString(TOKEN);
if (profile != null) { if (profile != null) {
AuthenticatedUser doctorProfile = AuthenticatedUser.fromJson(profile); AuthenticatedUser doctorProfile = AuthenticatedUser.fromJson(profile);
body['DriverID'] = doctorProfile?.userID; if(!body.keys.contains('DriverID') || body['DriverID'] == null)
body['DriverID'] = doctorProfile?.userID;
if(!body.keys.contains('UserID') || body['UserID'] == null)
body['UserID'] = '${doctorProfile?.userID}';
body['CreatedBy'] = doctorProfile?.userID; body['CreatedBy'] = doctorProfile?.userID;
body['UserID'] = '${doctorProfile?.userID}';
body['TokenID'] = token; body['TokenID'] = token;
body['MobileNo'] = doctorProfile?.mobileNumber; body['MobileNo'] = doctorProfile?.mobileNumber;
} }
@ -45,7 +47,8 @@ class BaseAppClient {
body: json.encode(body), body: json.encode(body),
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Accept': 'application/json' 'Accept': 'application/json',
'Statictoken': _Statictoken
}); });
final int statusCode = response.statusCode; final int statusCode = response.statusCode;
if (statusCode < 200 || statusCode >= 400 || json == null) { if (statusCode < 200 || statusCode >= 400 || json == null) {
@ -56,11 +59,11 @@ class BaseAppClient {
// await helpers.logout(); // await helpers.logout();
//helpers.showErrorToast('Your session expired Please login agian'); //helpers.showErrorToast('Your session expired Please login agian');
// TODO create logout fun // TODO create logout fun
onFailure("Unauthorized", 401);
} else if (parsed['MessageStatus'] == 1) { } else if (parsed['MessageStatus'] == 1) {
onSuccess(parsed, statusCode); onSuccess(parsed, statusCode);
} else { } else {
onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
statusCode);
} }
} }
} else { } else {
@ -71,4 +74,66 @@ class BaseAppClient {
onFailure(e.toString(), -1); onFailure(e.toString(), -1);
} }
} }
get(
String endPoint, {
Map<String, dynamic> body,
Function(dynamic response, int statusCode) onSuccess,
Function(String error, int statusCode) onFailure}) async {
String url = BASE_URL + endPoint;
try {
if (await Utils.checkConnection()) {
final response = await http.get(url,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Statictoken': _Statictoken
});
final int statusCode = response.statusCode;
if (statusCode < 200 || statusCode >= 400 || json == null) {
onFailure('Error While Fetching data', statusCode);
} else {
var parsed = json.decode(response.body.toString());
if (parsed['MessageStatus'] == 1) {
onSuccess(parsed, statusCode);
} else {
onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
}
}
} else {
onFailure('Please Check The Internet Connection', -1);
}
} catch (e) {
print(e);
onFailure(e.toString(), -1);
}
}
simpleGet(
String url,
{ Function(dynamic response, int statusCode) onSuccess,
Function(String error, int statusCode) onFailure}) async {
try {
if (await Utils.checkConnection()) {
final response = await http.get(url,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Statictoken': _Statictoken
});
final int statusCode = response.statusCode;
if (statusCode < 200 || statusCode >= 400) {
onFailure('Error While Fetching data', statusCode);
} else {
onSuccess(response.body, statusCode);
}
} else {
onFailure('Please Check The Internet Connection', -1);
}
} catch (e) {
print(e);
onFailure(e.toString(), -1);
}
}
} }

@ -0,0 +1,141 @@
import 'dart:collection';
import 'dart:math';
import 'package:driverapp/config/config.dart';
import 'package:driverapp/config/shared_pref_kay.dart';
import 'package:driverapp/core/model/StatusModel.dart';
import 'package:driverapp/core/model/order_delivey/request_initiate_order_delivery.dart';
import 'package:driverapp/core/model/order_delivey/request_validate_delivery.dart';
import 'package:driverapp/core/model/orders/pending_orders_res_model.dart';
import 'package:driverapp/core/model/update_driver_location/request_update_driver_location.dart';
import 'package:driverapp/core/service/base_service.dart';
import 'package:driverapp/uitl/app_shared_preferences.dart';
import 'package:driverapp/uitl/utils.dart';
import 'package:flutter/cupertino.dart';
import 'package:latlong/latlong.dart';
import 'package:location/location.dart';
import 'package:shared_preferences/shared_preferences.dart';
class DeliveryTrackingServices extends BaseService {
var _distanceFilter = 20; // [Meters] (Call update API if distance covered from last location is greater then 'value' )
Future<ResponseModel> initiateOrderDelivery(PendingOrdersRes order) async {
hasError = false;
var testNumber = "";
ResponseModel result;
// var orderRequest = RequestInitiateOrderDelivery(orderNo: order.ePharmacyOrderNo, mobileNumber: testNumber == "" ? order.mobileNumber : testNumber);
var fullUrl = BASE_URL + INITIATE_DELIVERY + "/${order.ePharmacyOrderNo}/${user.iD}";
await baseAppClient.simpleGet(fullUrl,
onSuccess: (dynamic response, int statusCode) {
result = ResponseModel(isSuccessful: true,message: null, data: response);
startLocationUpdate(order.ePharmacyOrderNo);
}, onFailure: (String error, int statusCode) {
result = ResponseModel(isSuccessful: false,message: error,data: null);
});
return result;
}
Future<ResponseModel> validateDelivery(PendingOrdersRes order, String pinCode) async{
hasError = false;
var request = RequestValidateDelivery(orderNo: order.ePharmacyOrderNo, pinCode: pinCode);
ResponseModel result;
await baseAppClient.post(VERIFY_DELIVERY,
onSuccess: (dynamic response, int statusCode) {
result = ResponseModel(isSuccessful: true,message: null, data: response);
}, onFailure: (String error, int statusCode) {
result = ResponseModel(isSuccessful: false,message: error,data: null);
}, body: request.toJson());
return result;
}
_updateDriverLocation(int orderID, LocationData location) async {
if(location != null){
debugPrint("Updating driver location");
var jsonBody = await RequestUpdateDriverLocation(orderID: orderID, location: location).toJson();
await baseAppClient.post(UPDATE_DRIVER_LOCATION,
onSuccess: (dynamic response, int statusCode) {
}, onFailure: (String errorMessage, int statusCode) {
if(statusCode == 200){
// Server responded but check failed (stop updating location)
// stopLocationUpdate(orderID);
// Show error message that you received in response
}
}, body: jsonBody);
}
}
Map _currentRunnings = Map<String,Future>();
Future<Object> startLocationUpdate(int orderID, {int frequencyInSeconds = 3}) async {
if (_currentRunnings[orderID.toString()] == null){
_currentRunnings[orderID.toString()] = Future.doWhile(() async{
await Future.delayed(Duration(seconds: frequencyInSeconds));
var valid = _currentRunnings.containsKey(orderID.toString());
if(valid){
Utils.possibleToGetLocation((value) async{
if(value){
var location = await Utils.getLocation();
if (_haveEnoughLocationUpdate(location))
await _updateDriverLocation(orderID, location);
}
});
}
return valid;
});
}
SharedPreferences.getInstance().then((pref){
pref.setStringList(ACTIVE_DELIVERIES, _currentRunnings.keys.toList());
});
}
bool isActiveDeliveringOrder(int ePharmacyOrderNo){
return _currentRunnings.containsKey(ePharmacyOrderNo.toString());
}
List<String> getActiveDeliveringOrders(){
return _currentRunnings.keys.toList(growable: false);
}
setActiveDeliveringOrders(List<String> orders){
orders.forEach((element) {
if(!_currentRunnings.containsKey(element)){
_currentRunnings[element] = null;
}
});
}
clearActiveDeliveringOrders(){
_currentRunnings.clear();
SharedPreferences.getInstance().then((pref){
pref.setStringList(ACTIVE_DELIVERIES, _currentRunnings.keys.toList());
});
}
stopLocationUpdate(int orderID){
_currentRunnings.remove(orderID.toString());
SharedPreferences.getInstance().then((pref){
pref.setStringList(ACTIVE_DELIVERIES, _currentRunnings.keys.toList());
});
}
LocationData _lastLocation;
bool _haveEnoughLocationUpdate(LocationData location){
_lastLocation = _lastLocation ?? location;
var distanceCovered = Utils.distanceBetween(_lastLocation, location, LengthUnit.Meter);
// debugPrint("distance: $distanceCovered");
return (distanceCovered > _distanceFilter);
}
}

@ -79,11 +79,11 @@ class OrdersService extends BaseService {
try { try {
await baseAppClient.post(GET_ALL_ORDERS_STATUS, await baseAppClient.post(GET_ALL_ORDERS_STATUS,
onSuccess: (dynamic response, int statusCode) { onSuccess: (dynamic response, int statusCode) {
listCountDelivered = listCountDelivered =
response["PatientER_CountOrderList"][0]["NumberOfDeliveredOrder"]; response["PatientER_CountOrderList"][0]["NumberOfDeliveredOrder"];
listCountUnDelivered = listCountUnDelivered =
response["PatientER_CountOrderList"][0]["NumberOfUnDeliveredOrder"]; response["PatientER_CountOrderList"][0]["NumberOfUnDeliveredOrder"];
}, onFailure: (String error, int statusCode) { }, onFailure: (String error, int statusCode) {
hasError = true; hasError = true;
super.error = error; super.error = error;
}, body: {}); }, body: {});
@ -100,10 +100,9 @@ class OrdersService extends BaseService {
try { try {
await baseAppClient.post(UPDATE_ORDER_STATUS, await baseAppClient.post(UPDATE_ORDER_STATUS,
onSuccess: (dynamic response, int statusCode) { onSuccess: (dynamic response, int statusCode) {
isOrderStatusUpdated = isOrderStatusUpdated = response["PatientER_Delivery_IsOrderUpdated"];
response["PatientER_Delivery_IsOrderUpdated"]; listCountUnDelivered--;
listCountUnDelivered --; listCountDelivered++;
listCountDelivered ++;
}, onFailure: (String error, int statusCode) { }, onFailure: (String error, int statusCode) {
hasError = true; hasError = true;
super.error = error; super.error = error;
@ -137,13 +136,12 @@ class OrdersService extends BaseService {
Future getDeliveredList() async { Future getDeliveredList() async {
LocationData loc = await Utils.getLocation(); LocationData loc = await Utils.getLocation();
PendingOrders _requestGetPendingOrders = PendingOrders( PendingOrders _requestGetPendingOrders = PendingOrders(
searchKey: "", searchKey: "",
pageSize: 0, pageSize: 0,
pageIndex: 0, pageIndex: 0,
latitude: loc.latitude.toString(), latitude: loc.latitude.toString(),
longitude: loc.longitude.toString(), longitude: loc.longitude.toString(),
driverAppPageID: 0 driverAppPageID: 0);
);
if (loc != null) { if (loc != null) {
hasError = false; hasError = false;
try { try {

@ -1,16 +1,20 @@
import 'package:driverapp/core/enum/viewstate.dart'; import 'package:driverapp/core/enum/viewstate.dart';
import 'package:driverapp/core/model/StatusModel.dart';
import 'package:driverapp/core/model/orders/deliverd_order_res_model.dart'; import 'package:driverapp/core/model/orders/deliverd_order_res_model.dart';
import 'package:driverapp/core/model/orders/next_order_request_model.dart'; import 'package:driverapp/core/model/orders/next_order_request_model.dart';
import 'package:driverapp/core/model/orders/pending_orders_res_model.dart'; import 'package:driverapp/core/model/orders/pending_orders_res_model.dart';
import 'package:driverapp/core/model/orders/update_order_status_request_model.dart'; import 'package:driverapp/core/model/orders/update_order_status_request_model.dart';
import 'package:driverapp/core/model/scan_qr/scan_qr_request_model.dart'; import 'package:driverapp/core/model/scan_qr/scan_qr_request_model.dart';
import 'package:driverapp/core/service/delivery_tracking_services.dart';
import 'package:driverapp/core/service/orders_service.dart'; import 'package:driverapp/core/service/orders_service.dart';
import 'package:flutter/cupertino.dart';
import '../../locator.dart'; import '../../locator.dart';
import 'base_view_model.dart'; import 'base_view_model.dart';
class OrdersViewModel extends BaseViewModel { class OrdersViewModel extends BaseViewModel {
OrdersService _ordersService = locator<OrdersService>(); OrdersService _ordersService = locator<OrdersService>();
DeliveryTrackingServices deliveryService = locator<DeliveryTrackingServices>();
List<PendingOrdersRes> get orders => _ordersService.orders; List<PendingOrdersRes> get orders => _ordersService.orders;
@ -64,15 +68,37 @@ class OrdersViewModel extends BaseViewModel {
setState(ViewState.Idle); setState(ViewState.Idle);
} }
Future updateOrderStatus( Future<ResponseModel> updateOrderStatus({@required int orderNo, @required int status, String rejectionReason}) async {
UpdateOrderStatusRequestModel updateOrderStatusRequestModel) async { var updateOrderStatusRequestModel
= UpdateOrderStatusRequestModel(
deliveryOrderID: orderNo,
deliveryOrderStatus: status,
rejectionReason: rejectionReason,
cancleReason: rejectionReason);
setState(ViewState.BusyLocal); setState(ViewState.BusyLocal);
await _ordersService.updateOrderStatus(updateOrderStatusRequestModel); await _ordersService.updateOrderStatus(updateOrderStatusRequestModel);
if (_ordersService.hasError) { if (_ordersService.hasError) {
error = _ordersService.error; error = _ordersService.error;
setState(ViewState.ErrorLocal); setState(ViewState.ErrorLocal);
} else return ResponseModel(isSuccessful: false, message: error);
} else {
setState(ViewState.Idle); setState(ViewState.Idle);
if(status == 2)
moveOrderFromPendingToDelivered(orderNo);
return ResponseModel(isSuccessful: true, message: "Successful");
}
}
moveOrderFromPendingToDelivered(int orderNo) async{
var idx = orders.indexWhere((element) => element.ePharmacyOrderNo == orderNo);
var order = orders[idx];
orders.removeAt(idx);
var order_delivered = DeliverdOrderResModel.fromJson(order.toJson());
order_delivered.description = "Delivered";
order_delivered.descriptionN = "Delivered";
deliverdOrders.add(order_delivered);
} }
Future nextOrder(NextOrderRequestModel nextOrderRequestModel) async { Future nextOrder(NextOrderRequestModel nextOrderRequestModel) async {
@ -85,6 +111,31 @@ class OrdersViewModel extends BaseViewModel {
setState(ViewState.Idle); setState(ViewState.Idle);
} }
Future initDelivery(PendingOrdersRes order, {Function(@required ResponseModel response) completion}) async{
var response = await deliveryService.initiateOrderDelivery(order);
completion(response ?? ResponseModel(isSuccessful: false,message: "Something went wrong, Please try again later."));
return response;
// (true, response['ErrorEndUserMessage'] ?? response['ErrorMessage'] ?? "Successfully, Please start navigation.")
}
Future<ResponseModel> validateDelivery(PendingOrdersRes order, String pinCode) async{
return await deliveryService.validateDelivery(order, pinCode);
}
Future<ResponseModel> resendOtpToReceiver(PendingOrdersRes order) async{
// return await _deliveryService.validateDelivery(order, pinCode);
}
bool isActiveDeliveringOrder(int index){
return deliveryService.isActiveDeliveringOrder(orders[index].ePharmacyOrderNo);
}
Future<List<String>> getActiveDeliveringOrders() async{
return deliveryService.getActiveDeliveringOrders();
}
showBottomSheet() { showBottomSheet() {
isBottomSheetAppear = true; isBottomSheetAppear = true;
setState(ViewState.Idle); setState(ViewState.Idle);

@ -1,3 +1,4 @@
import 'package:driverapp/core/service/delivery_tracking_services.dart';
import 'package:get_it/get_it.dart'; import 'package:get_it/get_it.dart';
import 'core/service/authentication_service.dart'; import 'core/service/authentication_service.dart';
@ -15,6 +16,7 @@ void setupLocator() {
locator.registerLazySingleton(() => HospitalService()); locator.registerLazySingleton(() => HospitalService());
locator.registerLazySingleton(() => AuthenticationService()); locator.registerLazySingleton(() => AuthenticationService());
locator.registerLazySingleton(() => OrdersService()); locator.registerLazySingleton(() => OrdersService());
locator.registerLazySingleton(() => DeliveryTrackingServices());
/// View Model /// View Model
locator.registerFactory(() => HospitalViewModel()); locator.registerFactory(() => HospitalViewModel());

@ -1,9 +1,14 @@
import 'package:driverapp/core/service/delivery_tracking_services.dart';
import 'package:driverapp/core/viewModels/orders_view_model.dart';
import 'package:driverapp/pages/splash_screen_page.dart'; import 'package:driverapp/pages/splash_screen_page.dart';
import 'package:driverapp/uitl/app_shared_preferences.dart';
import 'package:driverapp/uitl/translations_delegate_base.dart'; import 'package:driverapp/uitl/translations_delegate_base.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'config/shared_pref_kay.dart';
import 'config/size_config.dart'; import 'config/size_config.dart';
import 'core/viewModels/authentication_view_model.dart'; import 'core/viewModels/authentication_view_model.dart';
import 'core/viewModels/project_view_model.dart'; import 'core/viewModels/project_view_model.dart';
@ -14,9 +19,30 @@ void main() {
runApp(MyApp()); runApp(MyApp());
} }
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget with WidgetsBindingObserver{
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if(state == AppLifecycleState.paused){
debugPrint("....App paused....");
}else if(state == AppLifecycleState.resumed){
debugPrint("....App resumed....");
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
WidgetsBinding.instance.addObserver(this);
SharedPreferences.getInstance().then((value){
var activeOrders = value.getStringList(ACTIVE_DELIVERIES) ?? [];
locator<DeliveryTrackingServices>().setActiveDeliveringOrders(activeOrders);
});
return LayoutBuilder( return LayoutBuilder(
builder: (context, constraints) { builder: (context, constraints) {
return OrientationBuilder( return OrientationBuilder(
@ -30,6 +56,9 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider<AuthenticationViewModel>( ChangeNotifierProvider<AuthenticationViewModel>(
create: (context) => AuthenticationViewModel(), create: (context) => AuthenticationViewModel(),
), ),
ChangeNotifierProvider<OrdersViewModel>(
create: (context) => OrdersViewModel(),
),
], ],
child: Consumer<ProjectViewModel>( child: Consumer<ProjectViewModel>(
builder: (context, projectProvider, child) => MaterialApp( builder: (context, projectProvider, child) => MaterialApp(

@ -0,0 +1,453 @@
import 'package:driverapp/app-icons/driver_app_icons.dart';
import 'package:driverapp/config/config.dart';
import 'package:driverapp/config/size_config.dart';
import 'package:driverapp/core/model/authentication/login_request.dart';
import 'package:driverapp/core/model/orders/pending_orders_res_model.dart';
import 'package:driverapp/core/service/delivery_tracking_services.dart';
import 'package:driverapp/core/viewModels/authentication_view_model.dart';
import 'package:driverapp/core/viewModels/orders_view_model.dart';
import 'package:driverapp/core/viewModels/project_view_model.dart';
import 'package:driverapp/locator.dart';
import 'package:driverapp/pages/authentication/reset_password_page.dart';
import 'package:driverapp/pages/delivery/delivery_confirmed_page.dart';
import 'package:driverapp/uitl/app_toast.dart';
import 'package:driverapp/uitl/translations_delegate_base.dart';
import 'package:driverapp/uitl/utils.dart';
import 'package:driverapp/widgets/buttons/secondary_button.dart';
import 'package:driverapp/widgets/others/app_scaffold_widget.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:provider/provider.dart';
import 'package:sweetalert/sweetalert.dart';
import 'forget_password_page.dart';
// ignore: must_be_immutable
class DeliveryVerificationPage extends StatelessWidget {
final PendingOrdersRes order;
DeliveryVerificationPage({this.order});
ProjectViewModel _projectViewModel;
OrdersViewModel _ordersViewModel;
final formKey = GlobalKey<FormState>();
Map formValues = {
'digit1': null,
'digit2': null,
'digit3': null,
'digit4': null,
};
FocusNode focusD1 = FocusNode();
FocusNode focusD2 = FocusNode();
FocusNode focusD3 = FocusNode();
FocusNode focusD4 = FocusNode();
var model;
TextEditingController digit1 = TextEditingController(text: "");
TextEditingController digit2 = TextEditingController(text: "");
TextEditingController digit3 = TextEditingController(text: "");
TextEditingController digit4 = TextEditingController(text: "");
bool _isLoading = false;
SizedBox buildSizedBox([double height = 20]) {
return SizedBox(
height: height,
);
}
BuildContext _context;
@override
Widget build(BuildContext context) {
_context = context;
_projectViewModel = Provider.of(context);
_ordersViewModel = Provider.of(context);
String validateCodeDigit(value) {
if (value.isEmpty) {
return 'Please enter your Password';
}
return null;
}
return AnimatedSwitcher(
duration: Duration(milliseconds: 2000),
child: AppScaffold(
isShowAppBar: false,
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FractionallySizedBox(
widthFactor: 0.80,
child: Column(
children: <Widget>[
SizedBox(
height: 30,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
child: Icon(
DriverApp.deliverd_icon,
size: 150,
color: Theme.of(context).primaryColor,
),
margin: EdgeInsets.only(
top: 20,
),
),
],
),
SizedBox(
height: 20,
),
Column(
children: <Widget>[
Center(
child: Text(
"Verification",
style: TextStyle(
fontSize: 25,
letterSpacing: 1,
fontWeight: FontWeight.w600),
),
),
],
),
SizedBox(
height: 30,
),
SizedBox(
height: 10,
),
Form(
key: formKey,
child: Container(
width: SizeConfig.realScreenWidth * 0.90,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20),
child: Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: <Widget>[
Expanded(
child: Text(
TranslationBase.of(context)
.enterCustomerVerificationCodeMsg,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 13,
color: Colors.grey),
),
),
SizedBox(
height: 10,
)
],
),
),
buildSizedBox(30),
Center(
child: FractionallySizedBox(
widthFactor: 0.80,
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
children: <Widget>[
Container(
width: 55,
height: 55,
color: Colors.transparent,
child: Center(
child: TextFormField(
textInputAction:
TextInputAction.next,
style: TextStyle(
fontSize: SizeConfig
.textMultiplier *
3,
),
focusNode: focusD1,
controller: digit1,
enableInteractiveSelection: false,
showCursor: false,
maxLength: 1,
textAlign: TextAlign.center,
keyboardType:
TextInputType.number,
decoration:
buildInputDecoration(
context),
onSaved: (val) {
formValues[
'digit1'] = val;
},
validator: validateCodeDigit,
onFieldSubmitted: (_) {
FocusScope.of(context)
.requestFocus(focusD2);
},
onChanged: (val) => val.isNotEmpty
? FocusScope.of(context).requestFocus(focusD2)
: FocusScope.of(context).requestFocus(focusD1)
),
),
),
Container(
width: 55,
height: 55,
color: Colors.transparent,
child: Center(
child: TextFormField(
focusNode: focusD2,
controller: digit2,
enableInteractiveSelection: false,
showCursor: false,
maxLength: 1,
textInputAction:
TextInputAction.next,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: SizeConfig
.textMultiplier *
3,
),
keyboardType:
TextInputType.number,
decoration:
buildInputDecoration(
context),
validator: validateCodeDigit,
onSaved: (val) {
formValues[
'digit2'] = val;
},
onFieldSubmitted: (_) {
FocusScope.of(context)
.requestFocus(focusD3);
},
onChanged: (val) => val.isNotEmpty
? FocusScope.of(context).requestFocus(focusD3)
: FocusScope.of(context).requestFocus(focusD1)
),
),
),
Container(
width: 55,
height: 55,
color: Colors.transparent,
child: Center(
child: TextFormField(
focusNode: focusD3,
controller: digit3,
enableInteractiveSelection: false,
showCursor: false,
maxLength: 1,
textInputAction: TextInputAction.next,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: SizeConfig
.textMultiplier * 3,
),
keyboardType:
TextInputType.number,
decoration:
buildInputDecoration(
context),
validator: validateCodeDigit,
onSaved: (val) {
formValues[
'digit3'] = val;
},
onFieldSubmitted: (_) {
FocusScope.of(context)
.requestFocus(focusD4);
},
onChanged: (val) => val.isNotEmpty
? FocusScope.of(context).requestFocus(focusD4)
: FocusScope.of(context).requestFocus(focusD2),
),
)),
Container(
width: 55,
height: 55,
color: Colors.transparent,
child: Center(
child: TextFormField(
focusNode: focusD4,
controller: digit4,
enableInteractiveSelection: false,
showCursor: false,
maxLength: 1,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: SizeConfig
.textMultiplier *
3,
),
keyboardType:
TextInputType.number,
decoration:
buildInputDecoration(
context),
validator: validateCodeDigit,
onSaved: (val) {
formValues[
'digit4'] = val;
},
onFieldSubmitted: (_) {
FocusScope.of(context)
.requestFocus(focusD4);
},
onChanged: (val) => val.isNotEmpty
? FocusScope.of(context).requestFocus(focusD4)
: FocusScope.of(context).requestFocus(focusD3)
),
),
)
],
),
),
),
buildSizedBox(20),
// ShowTimerText(model: model),
])))
],
),
),
SizedBox(
height: 20,
),
SizedBox(
height: 10,
),
Container(
margin: EdgeInsets.all(10),
height: MediaQuery.of(context).size.height * 0.22,
child: Column(
children: <Widget>[
SecondaryButton(
label: "Verify Receiver",
onTap: () {
_verifyCustomer();
},
disabled: _isLoading,
loading: _isLoading,
),
SizedBox(
height: 10,
),
// Row(
// mainAxisAlignment: MainAxisAlignment.end,
// children: <Widget>[
// InkWell(
// onTap: () {
// Navigator.pushReplacement(
// context,
// MaterialPageRoute(
// builder: (context) =>
// ForgetPasswordPage()),
// );
// },
// child: InkWell(
// onTap: () async {
// await _ordersViewModel.resendOtpToReceiver(order);
// },
// child: Text(
// "Resend OPT?",
// style: TextStyle(
// fontSize: 14,
// color: Theme.of(context).primaryColor),
// ),
// ),
// ),
// ],
// ),
],
))
],
),
),
),
);
}
TextStyle buildTextStyle() {
return TextStyle(
fontSize: SizeConfig.textMultiplier * 3,
);
}
InputDecoration buildInputDecoration(BuildContext context) {
return InputDecoration(
filled: true,
fillColor: Colors.white,
// ts/images/password_icon.png
contentPadding: EdgeInsets.only(top: 30, bottom: 30),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
borderSide: BorderSide(color: Colors.grey),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
borderSide: BorderSide(color: Theme.of(context).primaryColor, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
borderSide: BorderSide(color: Theme.of(context).errorColor, width: 2),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
borderSide: BorderSide(color: Theme.of(context).errorColor, width: 2),
),
counterText: "",
errorStyle: TextStyle(height: 0.0)
);
}
_verifyCustomer() async {
if (formKey.currentState.validate()) {
final pinCode = digit1.text + digit2.text + digit3.text + digit4.text;
formKey.currentState.save();
SweetAlert.show(_context, subtitle: "Please wait...", style: SweetAlertStyle.loading);
var results = await _ordersViewModel.validateDelivery(order, pinCode);
if (results != null && results.isSuccessful) {
results = await _ordersViewModel.updateOrderStatus(orderNo: order.orderID, status: DeliveryStatus.delivered);
popWithDelay(context: _context, seconds: 0.2, callback: (){
if(results.isSuccessful){
_goToDeliveryDoneConfirmation();
}else{
Utils.showErrorToast(results.message);
}
});
}else{
Navigator.of(_context).pop();
Utils.showErrorToast(results.message);
}
}
}
_goToDeliveryDoneConfirmation(){
locator<DeliveryTrackingServices>().stopLocationUpdate(order.ePharmacyOrderNo); // Stop Driver Location update for Order
Navigator.pushReplacement(
_context,
MaterialPageRoute(
builder: (context) => DeliveryConfirmedPage(order),
),
);
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,242 @@
import 'package:driverapp/config/config.dart';
import 'package:driverapp/core/enum/viewstate.dart';
import 'package:driverapp/core/model/orders/next_order_request_model.dart';
import 'package:driverapp/core/model/orders/pending_orders_res_model.dart';
import 'package:driverapp/core/service/orders_service.dart';
import 'package:driverapp/core/viewModels/orders_view_model.dart';
import 'package:driverapp/locator.dart';
import 'package:driverapp/pages/base/base_view.dart';
import 'package:driverapp/root_page.dart';
import 'package:driverapp/uitl/utils.dart';
import 'package:driverapp/widgets/buttons/secondary_button.dart';
import 'package:driverapp/widgets/delivery/customer_brief_card.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:location/location.dart';
import '../../uitl/translations_delegate_base.dart';
import '../../widgets/others/app_scaffold_widget.dart';
import 'information_page.dart';
class DeliveryCancelRejectedPage extends StatelessWidget {
final PendingOrdersRes item;
DeliveryCancelRejectedPage(this.item);
@override
Widget build(BuildContext context) {
return BaseView<OrdersViewModel>(
builder: (_, model, w) => AppScaffold(
isAppBarGradient: true,
isShowAppBar: true,
appBarColor: Theme.of(context).primaryColor,
arrowColor: Colors.white,
titleColor: Colors.white,
body: SafeArea(
child: Container(
//
child: ListView(
children: <Widget>[
Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(gradient: LINEAR_GRADIENT),
height: MediaQuery.of(context).orientation ==
Orientation.portrait
? MediaQuery.of(context).size.width * 1
: MediaQuery.of(context).size.width * 1,
child: Stack(
children: [
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).orientation ==
Orientation.portrait
? MediaQuery.of(context).size.width * 0.7
: MediaQuery.of(context).size.width * 0.5,
padding: EdgeInsets.only(
top: MediaQuery.of(context).size.width * 0.14,
),
decoration: BoxDecoration(
color: Colors.white10, shape: BoxShape.circle),
child: Column(
children: <Widget>[
Icon(
Icons.check_circle,
color: Colors.white,
size: 75,
),
SizedBox(
height:
MediaQuery.of(context).size.width * 0.03,
),
Text(
'Delivery Confirmed',
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
),
SizedBox(
height:
MediaQuery.of(context).size.width * 0.01,
),
Text(
TranslationBase.of(context).confirmationSent,
style: TextStyle(
color: Colors.white,
fontSize: 13,
),
),
],
),
),
],
),
),
// Container(
// width: MediaQuery.of(context).size.width,
// height: MediaQuery.of(context).size.width,
// ),
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).orientation ==
Orientation.landscape
? MediaQuery.of(context).size.width * 0.6
: MediaQuery.of(context).size.width * 1.0,
margin: EdgeInsets.only(
top: MediaQuery.of(context).orientation ==
Orientation.portrait
? MediaQuery.of(context).size.width * 0.70
: MediaQuery.of(context).size.width * 0.60,
),
decoration: BoxDecoration(
color: Theme
.of(context)
.scaffoldBackgroundColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(80),
topRight: Radius.circular(80)),
),
child: Column(
mainAxisAlignment: MediaQuery.of(context).orientation ==
Orientation.landscape
? MainAxisAlignment.center
: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.only(
bottom: MediaQuery.of(context).size.width * 0.00,
),
child: Padding(
padding: MediaQuery.of(context).orientation ==
Orientation.landscape
? EdgeInsets.only(top: 60.0)
: EdgeInsets.only(top: 30.0),
child: Column(
children: <Widget>[
// TODO return add note when its needed
// FlatButton.icon(
// padding: EdgeInsets.all(14.0),
// color: Colors.orangeAccent,
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(10.0),
// ),
// label: Text(
// TranslationBase.of(context).addNoteBtn,
// style: TextStyle(
// color: Colors.white, fontSize: 20.0),
// ),
// icon: Icon(
// Icons.mode_edit,
// color: Colors.white,
// ),
// onPressed: () {},
// ),
// SizedBox(
// height: MediaQuery.of(context).size.width *
// 0.00, //20,
// ),
Padding(
padding: const EdgeInsets.only(top: 30.0),
child: Container(
margin: EdgeInsets.all(10),
child: SecondaryButton(
label: TranslationBase.of(context)
.nextDelivery,
loading:
model.state == ViewState.BusyLocal,
onTap: () {
getNextOrder(context, model);
},
),
),
),
],
),
),
),
],
),
),
Container(
margin: EdgeInsets.only(
top: MediaQuery.of(context).orientation ==
Orientation.portrait
? MediaQuery.of(context).size.width * 0.6
: MediaQuery.of(context).size.width * 0.4,
),
child: CustomerBriefCard(
customerOrderId: item.orderID,
pharmacyOrderId: item.ePharmacyOrderNo,
customerFirstName: item.firstName,
customerLastName: item.lastName,
mobileNo: item.mobileNumber,
totalPayment: item.amount,
distanceInKilometers: item.distanceInKilometers,
showDistance: false,
deliveryTime: item.orderCreatedOn),
),
],
),
],
),
),
),
),
);
}
getNextOrder(BuildContext context, OrdersViewModel model) async {
model.setState(ViewState.BusyLocal);
LocationData loc = await Utils.getLocation();
NextOrderRequestModel nextOrderRequestModel = NextOrderRequestModel(
pageIndex: 0,
pageSize: 0,
latitude: loc.latitude.toString(), // "46.621730",
longitude: loc.longitude.toString(), // "24.797682",
searchKey: "");
await model.nextOrder(nextOrderRequestModel);
if (model.state == ViewState.ErrorLocal) {
Utils.showErrorToast(model.error);
} else {
if (model.nextOrdersList != null && model.nextOrdersList.length == 0) {
Utils.showErrorToast("No Items in the list");
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => RootPage(),
),
);
} else {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) =>
InformationPage(item: model.nextOrdersList[0]),
),
);
}
}
}
}

@ -2,7 +2,9 @@ import 'package:driverapp/config/config.dart';
import 'package:driverapp/core/enum/viewstate.dart'; import 'package:driverapp/core/enum/viewstate.dart';
import 'package:driverapp/core/model/orders/next_order_request_model.dart'; import 'package:driverapp/core/model/orders/next_order_request_model.dart';
import 'package:driverapp/core/model/orders/pending_orders_res_model.dart'; import 'package:driverapp/core/model/orders/pending_orders_res_model.dart';
import 'package:driverapp/core/service/orders_service.dart';
import 'package:driverapp/core/viewModels/orders_view_model.dart'; import 'package:driverapp/core/viewModels/orders_view_model.dart';
import 'package:driverapp/locator.dart';
import 'package:driverapp/pages/base/base_view.dart'; import 'package:driverapp/pages/base/base_view.dart';
import 'package:driverapp/root_page.dart'; import 'package:driverapp/root_page.dart';
import 'package:driverapp/uitl/utils.dart'; import 'package:driverapp/uitl/utils.dart';
@ -211,10 +213,8 @@ class DeliveryConfirmedPage extends StatelessWidget {
NextOrderRequestModel nextOrderRequestModel = NextOrderRequestModel( NextOrderRequestModel nextOrderRequestModel = NextOrderRequestModel(
pageIndex: 0, pageIndex: 0,
pageSize: 0, pageSize: 0,
latitude: loc.latitude.toString(), latitude: loc.latitude.toString(), // "46.621730",
//"46.621730", longitude: loc.longitude.toString(), // "24.797682",
longitude: loc.longitude.toString(),
//"24.797682",
searchKey: ""); searchKey: "");
await model.nextOrder(nextOrderRequestModel); await model.nextOrder(nextOrderRequestModel);
if (model.state == ViewState.ErrorLocal) { if (model.state == ViewState.ErrorLocal) {

@ -1,10 +1,22 @@
import 'dart:convert';
import 'dart:io';
import 'package:android_intent/android_intent.dart';
import 'package:driverapp/app-icons/driver_app_icons.dart'; import 'package:driverapp/app-icons/driver_app_icons.dart';
import 'package:driverapp/config/config.dart'; import 'package:driverapp/config/config.dart';
import 'package:driverapp/core/enum/viewstate.dart'; import 'package:driverapp/core/enum/viewstate.dart';
import 'package:driverapp/core/model/StatusModel.dart';
import 'package:driverapp/core/model/orders/pending_orders_req_model.dart';
import 'package:driverapp/core/model/orders/pending_orders_res_model.dart'; import 'package:driverapp/core/model/orders/pending_orders_res_model.dart';
import 'package:driverapp/core/model/orders/update_order_status_request_model.dart'; import 'package:driverapp/core/model/orders/update_order_status_request_model.dart';
import 'package:driverapp/core/service/delivery_tracking_services.dart';
import 'package:driverapp/core/viewModels/orders_view_model.dart'; import 'package:driverapp/core/viewModels/orders_view_model.dart';
import 'package:driverapp/locator.dart';
import 'package:driverapp/pages/authentication/delivery_verification_page.dart';
import 'package:driverapp/pages/authentication/verification_page.dart';
import 'package:driverapp/pages/base/base_view.dart'; import 'package:driverapp/pages/base/base_view.dart';
import 'package:driverapp/uitl/app_shared_preferences.dart';
import 'package:driverapp/uitl/app_toast.dart';
import 'package:driverapp/uitl/translations_delegate_base.dart'; import 'package:driverapp/uitl/translations_delegate_base.dart';
import 'package:driverapp/uitl/utils.dart'; import 'package:driverapp/uitl/utils.dart';
import 'package:driverapp/widgets/bottom_sheet/action_sheet_button.dart'; import 'package:driverapp/widgets/bottom_sheet/action_sheet_button.dart';
@ -17,140 +29,44 @@ import 'package:driverapp/widgets/delivery/package_content.dart';
import 'package:driverapp/widgets/others/app_scaffold_widget.dart'; import 'package:driverapp/widgets/others/app_scaffold_widget.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_material_pickers/flutter_material_pickers.dart';
import 'package:hexcolor/hexcolor.dart'; import 'package:hexcolor/hexcolor.dart';
import 'package:maps_launcher/maps_launcher.dart'; import 'package:map_launcher/map_launcher.dart';
import 'package:sweetalert/sweetalert.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'delivery_cancel_page.dart';
import 'delivery_confirmed_page.dart'; import 'delivery_confirmed_page.dart';
// ignore: must_be_immutable
class InformationPage extends StatelessWidget {
final PendingOrdersRes item;
int _orderStatus;
class InformationPage extends StatefulWidget {
final PendingOrdersRes item;
InformationPage({this.item}); InformationPage({this.item});
@override
State<StatefulWidget> createState() => _InformationPageState();
}
// ignore: must_be_immutable
class _InformationPageState extends State<InformationPage> {
var _deliveryService = locator<DeliveryTrackingServices>();
PendingOrdersRes _item;
bool _isDeliveryStarted;
OrdersViewModel _viewModel;
@override
void initState() {
super.initState();
_item = widget.item;
_isDeliveryStarted = _deliveryService.getActiveDeliveringOrders().contains(_item.ePharmacyOrderNo.toString());
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
showDeliveryOptions(OrdersViewModel model) {
showModalBottomSheet(
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(50.0),
topRight: Radius.circular(50.0),
),
),
isScrollControlled: true,
context: context,
builder: (BuildContext bc) {
return FractionallySizedBox(
heightFactor: 0.35,
child: ListView(
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(50.0),
topRight: Radius.circular(50.0),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(
height: 10,
),
Center(
child: Texts(
TranslationBase.of(context).selectAction,
color: Colors.black,
fontSize: 22,
),
),
SizedBox(
height: 10,
),
FractionallySizedBox(
widthFactor: MediaQuery.of(context).orientation ==
Orientation.portrait
? 0.9
: 0.98,
child: Container(
height: MediaQuery.of(context).size.height * 0.45,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(50.0),
topRight: Radius.circular(50.0),
),
),
width: double.infinity,
child: ListView(
children: <Widget>[
Column(
children: <Widget>[
SizedBox(
height: 3,
child: Container(
color: Hexcolor("#D5D5D5"),
),
),
SizedBox(
height: 15,
),
ActionSheetButton(
label:
TranslationBase.of(context).delivered,
icon: DriverApp.deliverd_icon,
onTap: () {
selectAction(context, 2, model);
},
),
SizedBox(height: 15),
// ActionSheetButton(
// label: TranslationBase.of(context)
// .deliveredAccepted,
// icon: DriverApp.not_available,
// onTap: () {
// selectAction(context, 4, model);
// },
// ),
// SizedBox(height: 15),
ActionSheetButton(
label: TranslationBase.of(context)
.deliveredRejected,
icon: DriverApp.rejected_icon,
onTap: () {
selectAction(context, 3, model);
},
),
SizedBox(height: 15),
// ActionSheetButton(
// label: TranslationBase.of(context).canceled,
// icon: DriverApp.not_reachable_icon,
// onTap: () {
// selectAction(context, 6, model);
// },
// ),
// SizedBox(height: 15),
],
),
],
),
),
)
],
),
),
],
),
);
});
}
return BaseView<OrdersViewModel>( return BaseView<OrdersViewModel>(
onModelReady: (model) => _viewModel = model,
builder: (_, model, w) => AppScaffold( builder: (_, model, w) => AppScaffold(
isShowAppBar: true, isShowAppBar: true,
isShowHomeIcon: true, isShowHomeIcon: true,
@ -175,12 +91,12 @@ class InformationPage extends StatelessWidget {
child: Container( child: Container(
width: MediaQuery.of(context).size.width * 1.0, width: MediaQuery.of(context).size.width * 1.0,
height: MediaQuery.of(context).orientation == height: MediaQuery.of(context).orientation ==
Orientation.portrait Orientation.portrait
? MediaQuery.of(context).size.height * 0.70 ? MediaQuery.of(context).size.height * 0.70
: MediaQuery.of(context).size.height * 1.7, : MediaQuery.of(context).size.height * 1.7,
margin: EdgeInsets.only( margin: EdgeInsets.only(
top: MediaQuery.of(context).orientation == top: MediaQuery.of(context).orientation ==
Orientation.portrait Orientation.portrait
? MediaQuery.of(context).size.width * 0.23 ? MediaQuery.of(context).size.width * 0.23
: MediaQuery.of(context).size.width * 0.13), : MediaQuery.of(context).size.width * 0.13),
decoration: BoxDecoration( decoration: BoxDecoration(
@ -192,88 +108,53 @@ class InformationPage extends StatelessWidget {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[ children: <Widget>[
SizedBox( Visibility(
height: MediaQuery.of(context).orientation == visible: _isDeliveryStarted,
Orientation.portrait child: Padding(
? MediaQuery.of(context).size.height * 0.10 padding: MediaQuery.of(context).orientation ==
: MediaQuery.of(context).size.height * 0.29, Orientation.portrait
//MediaQuery.of(context).size.width * 0.005, ? EdgeInsets.only(top: 60.0)
), : EdgeInsets.only(top: 15.0),
Padding( child: Row(
padding: MediaQuery.of(context).orientation == mainAxisAlignment: MainAxisAlignment.center,
Orientation.portrait children: <Widget>[
? EdgeInsets.only(top: 60.0) DeliveryInfoButton(
: EdgeInsets.only(top: 15.0), btnColor: Colors.white, //Color(0xffED1C24),
child: Row( btnIcon: Icon(DriverApp.location_1,
mainAxisAlignment: MainAxisAlignment.center, size: MediaQuery.of(context)
children: <Widget>[ .orientation ==
DeliveryInfoButton( Orientation.portrait
btnColor: Colors.white, //Color(0xffED1C24),
btnIcon: Icon(DriverApp.location_1,
size: MediaQuery.of(context)
.orientation ==
Orientation.portrait
? 50
: 90,
color: Color(0xffED1C24)),
btnName:
TranslationBase.of(context).location,
btnFunction: () {
MapsLauncher.launchCoordinates(
item.latitude, item.longitude);
},
),
//TODO: return it back when it needed
// DeliveryInfoButton(
// btnColor: Colors.white, //Color(0xFF61B260),
// btnIcon: Icon(
// DriverApp.whatsapp,
// size:
// MediaQuery.of(context).orientation ==
// Orientation.portrait
// ? 50
// : 90,
// color: Color(0xFF5EA34A),
// ),
// btnName: 'Whatsapp',
// btnFunction: () {},
// ),
// DeliveryInfoButton(
// btnColor: Colors.white, //Color(0xFFFCB657),
// btnIcon: Icon(
// DriverApp.message,
// size:
// MediaQuery.of(context).orientation ==
// Orientation.portrait
// ? 50
// : 90,
// color: Color(0xffFFA540),
// ),
// btnName: TranslationBase.of(context).sms,
// btnFunction: () {},
// ),
DeliveryInfoButton(
btnColor: Colors.white,
//Theme.of(context).primaryColor,
btnIcon: Icon(
DriverApp.call,
size:
MediaQuery.of(context).orientation ==
Orientation.portrait
? 50 ? 50
: 90, : 90,
color: Theme.of(context).primaryColor, color: Color(0xffED1C24)),
btnName:
TranslationBase.of(context).location,
btnFunction: () {
_openMapDirection(_item);
// MapsLauncher.launchCoordinates(
// _item.latitude, _item.longitude);
},
), ),
btnName: TranslationBase.of(context).call, DeliveryInfoButton(
btnFunction: () => btnColor: Colors.white,
launch("tel://" + item.mobileNumber), //Theme.of(context).primaryColor,
), btnIcon: Icon(
], DriverApp.call,
size:
MediaQuery.of(context).orientation ==
Orientation.portrait
? 50
: 90,
color: Theme.of(context).primaryColor,
),
btnName: TranslationBase.of(context).call,
btnFunction: () =>
launch("tel://" + _item.mobileNumber),
),
],
),
), ),
), ),
SizedBox(
height: MediaQuery.of(context).size.width * 0.08,
),
Container( Container(
margin: EdgeInsets.only( margin: EdgeInsets.only(
left: MediaQuery.of(context).size.width * 0.05, left: MediaQuery.of(context).size.width * 0.05,
@ -300,15 +181,15 @@ class InformationPage extends StatelessWidget {
padding: const EdgeInsets.only(left: 10), padding: const EdgeInsets.only(left: 10),
child: Column( child: Column(
children: List.generate( children: List.generate(
item.itemsQuantitiesList != null _item.itemsQuantitiesList != null
? item.itemsQuantitiesList.length ? _item.itemsQuantitiesList.length
: 0, (index) { : 0, (index) {
return packageContent( return packageContent(
packageName: item packageName: _item
.itemsQuantitiesList[index] .itemsQuantitiesList[index]
.itemName .itemName
.toString(), .toString(),
packageCount: item packageCount: _item
.itemsQuantitiesList[index] .itemsQuantitiesList[index]
.quantity .quantity
.toString(), .toString(),
@ -324,14 +205,15 @@ class InformationPage extends StatelessWidget {
), ),
Container( Container(
margin: MediaQuery.of(context).orientation == margin: MediaQuery.of(context).orientation ==
Orientation.portrait Orientation.portrait
? EdgeInsets.all(8.0) ? EdgeInsets.all(8.0)
: EdgeInsets.symmetric(horizontal: 12.0), : EdgeInsets.symmetric(horizontal: 12.0),
child: SecondaryButton( child: SecondaryButton(
label: label: _isDeliveryStarted
TranslationBase.of(context).clientReached, ? TranslationBase.of(context).deliveryOption
: TranslationBase.of(context).startDelivery,
onTap: () { onTap: () {
showDeliveryOptions(model); takeAction();
}, },
), ),
), ),
@ -340,16 +222,16 @@ class InformationPage extends StatelessWidget {
), ),
), ),
CustomerBriefCard( CustomerBriefCard(
customerOrderId: item.orderID, customerOrderId: _item.orderID,
pharmacyOrderId: item.ePharmacyOrderNo, pharmacyOrderId: _item.ePharmacyOrderNo,
customerFirstName: item.firstName, customerFirstName: _item.firstName,
customerLastName: item.lastName, customerLastName: _item.lastName,
mobileNo: item.mobileNumber, mobileNo: _item.mobileNumber,
totalPayment: item.amount, totalPayment: _item.amount,
deliveryTime: item.orderCreatedOn, deliveryTime: _item.orderCreatedOn,
longitude: item.longitude, longitude: _item.longitude,
latitude: item.latitude, latitude: _item.latitude,
distanceInKilometers: item.distanceInKilometers, distanceInKilometers: _item.distanceInKilometers,
), ),
], ],
), ),
@ -361,68 +243,236 @@ class InformationPage extends StatelessWidget {
); );
} }
selectAction(BuildContext context, orderStatus, OrdersViewModel model) { void takeAction(){
String orderStatusText; if(_isDeliveryStarted) {
this._orderStatus = orderStatus; showDeliveryOptions(_viewModel);
switch (orderStatus) { }else{
case 2: if(_deliveryService.getActiveDeliveringOrders().isEmpty){
orderStatusText = TranslationBase SweetAlert.show(context,subtitle: "Initializing delivery...", style: SweetAlertStyle.loading);
.of(context) _viewModel.initDelivery(_item, completion: (response) {
.delivered; if (response.isSuccessful) {
break; setState(() => _isDeliveryStarted = true);
// case 4: Navigator.pop(context);
// orderStatusText = TranslationBase.of(context).deliveredAccepted; AppToast.showSuccessToast(message: "Start navigation by clicking icon [${response.data}]");
// break;
case 3: }else{
orderStatusText = TranslationBase SweetAlert.show(context,subtitle: response.message, style: SweetAlertStyle.error);
.of(context) }
.deliveredRejected; });
break; }else{
// case 6: SweetAlert.show(context,subtitle: "Complete the last delivery first.",style: SweetAlertStyle.error);
// orderStatusText = TranslationBase.of(context).canceled; }
// break; }
} }
showDialog(
cancelDelivery() {
List<String> speedOptions = <String>[
TranslationBase.of(context).notReachableOnPhoneCall,
TranslationBase.of(context).notAvailableAtlocation,
TranslationBase.of(context).accident,
TranslationBase.of(context).deliverLater,
// TranslationBase.of(context).other,
];
List<Icon> speedIcons = <Icon>[
Icon(IconData(0xe901, fontFamily: 'HMGIcon1')),
Icon(IconData(0xe900, fontFamily: 'HMGIcon1')),
Icon(IconData(0xe902, fontFamily: 'HMGIcon1')),
Icon(IconData(0xe903, fontFamily: 'HMGIcon1')),
];
showMaterialSelectionPicker(
context: context,
title: TranslationBase.of(context).selectReason,
items: speedOptions,
selectedItem: speedOptions.first,
icons: speedIcons,
onChanged: (value) async {
SweetAlert.show(context,subtitle: "Canceling delivery...", style: SweetAlertStyle.loading);
var result = await _viewModel.updateOrderStatus(orderNo: _item.orderID, status: DeliveryStatus.cancel);
Navigator.pop(context);
if(result.isSuccessful){
_viewModel.deliveryService.stopLocationUpdate(_item.ePharmacyOrderNo);
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => DeliveryCancelRejectedPage(_item), // Replace with Delivery Cancel Screen
),
);
}else{
SweetAlert.show(context,subtitle: result.message,style: SweetAlertStyle.error);
}
},
);
}
showDeliveryOptions(OrdersViewModel model) {
showModalBottomSheet(
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(50.0),
topRight: Radius.circular(50.0),
),
),
isScrollControlled: true,
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext bc) {
return CustomDialog( return FractionallySizedBox(
orderStatusText: orderStatusText, heightFactor: 0.40,
callService: () { child: ListView(
updateOrderStatus(context, model); children: <Widget>[
}, Container(
model: model, decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(50.0),
topRight: Radius.circular(50.0),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(
height: 10,
),
Center(
child: Texts(
TranslationBase.of(context).selectAction,
color: Colors.black,
fontSize: 22,
),
),
SizedBox(
height: 10,
),
FractionallySizedBox(
widthFactor: MediaQuery.of(context).orientation == Orientation.portrait
? 0.9
: 0.98,
child: Container(
height: MediaQuery.of(context).size.height * 0.45,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(50.0),
topRight: Radius.circular(50.0),
),
),
width: double.infinity,
child: ListView(
children: <Widget>[
Column(
children: <Widget>[
SizedBox(
height: 3,
child: Container(
color: HexColor("#D5D5D5"),
),
),
SizedBox(
height: 15,
),
ActionSheetButton(
label:
TranslationBase.of(context).delivered,
icon: DriverApp.deliverd_icon,
onTap: () {
Navigator.of(context).pop(); // Pop Bottom Action Sheet
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => DeliveryVerificationPage(order: _item)),
);
},
),
SizedBox(height: 15),
// ActionSheetButton(
// label: TranslationBase.of(context)
// .deliveredAccepted,
// icon: DriverApp.not_available,
// onTap: () {
// selectAction(context, 4, model);
// },
// ),
// SizedBox(height: 15),
ActionSheetButton(
label: TranslationBase.of(context)
.deliveredRejected,
icon: DriverApp.rejected_icon,
onTap: () {
Navigator.of(context).pop(); // Pop Bottom Action Sheet
rejectDelivery();
}
),
SizedBox(height: 15),
ActionSheetButton(
label: TranslationBase.of(context).cancel,
icon: DriverApp.not_reachable_icon,
onTap: () {
cancelDelivery();
},
),
SizedBox(height: 15),
],
),
],
),
),
)
],
),
),
],
),
); );
}); });
} }
updateOrderStatus(BuildContext context, OrdersViewModel model) async { rejectDelivery(){
UpdateOrderStatusRequestModel updateOrderStatusRequestModel = SweetAlert.show(context,title: "Are you sure?",style: SweetAlertStyle.confirm, showCancelButton: true,onPress: (bool isConfirm) {
UpdateOrderStatusRequestModel( if (isConfirm) {
deliveryOrderID: item.orderID, _viewModel.updateOrderStatus(orderNo: _item.orderID, status: DeliveryStatus.rejected).then((results){
deliveryOrderStatus: _orderStatus,
rejectionReason: "NO Reason",
cancleReason: "");
await model.updateOrderStatus(updateOrderStatusRequestModel);
if (model.state == ViewState.ErrorLocal) {
Utils.showErrorToast(model.error);
Navigator.of(context).pop();
model.hideBottomSheet();
} else {
/// to hide the dialog
Navigator.of(context).pop();
model.hideBottomSheet();
/// to remove this page from the stack please no one remove this line. });
Navigator.of(context).pop(); }
return true;
});
}
_openMapDirection(PendingOrdersRes order) async{
Utils.getLocation().then((locationData){
if(locationData != null){
// MapLauncher.isMapAvailable(MapType.google).then((value){
// if (value) {
// MapLauncher.showDirections(
// mapType: MapType.google,
// destination: Coords(order.latitude, order.longitude),
// directionsMode: DirectionsMode.driving,
// destinationTitle: order.receiverFullName())
// .then((value) {
//
// });
// }else{
// // Google Map Not installed show error
// }
// });
Navigator.pushReplacement( /* Directly start navigation */
context, MapLauncher.isMapAvailable(MapType.google).then((value){
MaterialPageRoute( var url = "https://www.google.com/maps/dir/?api=1&destination=${order.latitude},${order.longitude}&travelmode=driving&dir_action=navigate";
builder: (context) => if (Platform.isAndroid) {
DeliveryConfirmedPage(item), var intent = AndroidIntent(action: 'action_view',data: url,package: 'com.google.android.apps.maps');
), intent.launch();
); }else if (Platform.isIOS) {
} launch(url);
}
});
// Start updating server wit your current location
_deliveryService.startLocationUpdate(order.ePharmacyOrderNo);
}
});
} }
} }

@ -0,0 +1,14 @@
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
class Logs{
static save(String log){
SharedPreferences.getInstance().then((_prefs) async{
var jsonString = _prefs.getString("LOG") ?? "[]";
var list = json.decode(jsonString) as List;
list.add("Running... ${DateTime.now()}");
_prefs.setString("LOG", json.encode(list));
});
}
}

@ -62,6 +62,9 @@ class TranslationBase {
String get enterVerificationMsg => String get enterVerificationMsg =>
localizedValues['enterVerificationMsg'][locale.languageCode]; localizedValues['enterVerificationMsg'][locale.languageCode];
String get enterCustomerVerificationCodeMsg =>
localizedValues['enterCustomerVerificationCodeMsg'][locale.languageCode];
String get forgotPassword => String get forgotPassword =>
localizedValues['forgotPassword'][locale.languageCode]; localizedValues['forgotPassword'][locale.languageCode];
@ -108,6 +111,13 @@ class TranslationBase {
String get clientReached => String get clientReached =>
localizedValues['clientReached'][locale.languageCode]; localizedValues['clientReached'][locale.languageCode];
String get startDelivery =>
localizedValues['startDelivery'][locale.languageCode];
String get deliveryOption =>
localizedValues['deliveryOption'][locale.languageCode];
String get addNoteBtn => localizedValues['addNoteBtn'][locale.languageCode]; String get addNoteBtn => localizedValues['addNoteBtn'][locale.languageCode];
String get nextDelivery => String get nextDelivery =>
@ -133,6 +143,24 @@ class TranslationBase {
String get selectAction => String get selectAction =>
localizedValues['selectAction'][locale.languageCode]; localizedValues['selectAction'][locale.languageCode];
String get selectReason =>
localizedValues['selectReason'][locale.languageCode];
String get other =>
localizedValues['other'][locale.languageCode];
String get notReachableOnPhoneCall =>
localizedValues['notReachableOnPhoneCall'][locale.languageCode];
String get deliverLater =>
localizedValues['deliverLater'][locale.languageCode];
String get notAvailableAtlocation =>
localizedValues['notAvailableAtlocation'][locale.languageCode];
String get accident =>
localizedValues['accident'][locale.languageCode];
String get youHaveSelected => String get youHaveSelected =>
localizedValues['youHaveSelected'][locale.languageCode]; localizedValues['youHaveSelected'][locale.languageCode];

@ -5,6 +5,7 @@ import 'package:driverapp/pages/setting/request_permission_page.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:latlong/latlong.dart';
import 'package:location/location.dart'; import 'package:location/location.dart';
import 'app_shared_preferences.dart'; import 'app_shared_preferences.dart';
@ -12,6 +13,22 @@ import 'app_toast.dart';
AppSharedPreferences sharedPref = new AppSharedPreferences(); AppSharedPreferences sharedPref = new AppSharedPreferences();
popWithDelay({@required BuildContext context, @required num seconds, @required VoidCallback callback}){
Navigator.of(context).pop();
Future.delayed(Duration(milliseconds: (seconds*1000).toInt())).then((value){
callback();
});
}
pop(BuildContext context, VoidCallback callBack){
Navigator.of(context).pop();
callBack();
}
delay(int milliseconds, VoidCallback callback){
Future.delayed(Duration(milliseconds: milliseconds)).then((value) => callback());
}
class Utils { class Utils {
///show custom Error Toast ///show custom Error Toast
/// [message] to show for user /// [message] to show for user
@ -48,8 +65,25 @@ class Utils {
static hideKeyboard(BuildContext context) { static hideKeyboard(BuildContext context) {
FocusScope.of(context).unfocus(); FocusScope.of(context).unfocus();
} }
static double distanceBetween(LocationData point1, LocationData point2, LengthUnit unit){
var distance = Distance();
num dist = distance.as(
unit,
LatLng(point1.latitude,point1.longitude),
LatLng(point2.latitude,point2.longitude)
);
return dist;
}
static getLocation() async { static possibleToGetLocation(Function(bool) completion) async{
Location location = new Location();
var serviceEnabled = await location.serviceEnabled();
var hasPermission = await location.hasPermission() == PermissionStatus.granted;
completion(serviceEnabled && hasPermission);
}
static Future<LocationData> getLocation() async {
Location location = new Location(); Location location = new Location();
LocationData currentLocation; LocationData currentLocation;
bool _serviceEnabled; bool _serviceEnabled;
@ -104,8 +138,8 @@ class Utils {
// open setting page // open setting page
} else { } else {
currentLocation = await location.getLocation(); currentLocation = await location.getLocation();
return currentLocation;
} }
return currentLocation;
} }
static formatStringToPascalCase(String name) { static formatStringToPascalCase(String name) {
@ -120,3 +154,4 @@ class Utils {
return formattedNamesList.join(' '); return formattedNamesList.join(' ');
} }
} }

@ -19,7 +19,7 @@ class ActionSheetButton extends StatelessWidget {
: MediaQuery.of(context).size.height * 0.14, : MediaQuery.of(context).size.height * 0.14,
decoration: BoxDecoration(boxShadow: [ decoration: BoxDecoration(boxShadow: [
BoxShadow( BoxShadow(
color: Hexcolor("#DBE5E6"), color: HexColor("#DBE5E6"),
spreadRadius: 15, spreadRadius: 15,
blurRadius: 15, blurRadius: 15,
offset: Offset(0, 7), offset: Offset(0, 7),
@ -66,7 +66,7 @@ class ActionSheetButton extends StatelessWidget {
style: TextStyle( style: TextStyle(
fontSize: 22.0, fontSize: 22.0,
fontFamily: "Metropolis-Bold", fontFamily: "Metropolis-Bold",
color: Hexcolor("##1A1818")), color: HexColor("##1A1818")),
), ),
) )
], ],

@ -25,7 +25,7 @@ class CustomBottomSheet extends StatelessWidget {
children: <Widget>[ children: <Widget>[
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Hexcolor("#D5D5D5"), color: HexColor("#D5D5D5"),
borderRadius: BorderRadius.circular(3.0)), borderRadius: BorderRadius.circular(3.0)),
width: 200, width: 200,
height: 7.0, height: 7.0,

@ -103,7 +103,7 @@ class _ButtonState extends State<Button> with TickerProviderStateMixin {
: 19), : 19),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10.0)), borderRadius: BorderRadius.all(Radius.circular(10.0)),
color: Hexcolor('#515b5d'), color: HexColor('#515b5d'),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Color.fromRGBO( color: Color.fromRGBO(

@ -194,7 +194,7 @@ class _SecondaryButtonState extends State<SecondaryButton>
widget.color != null ? null : LINEAR_GRADIENT, widget.color != null ? null : LINEAR_GRADIENT,
color: widget.color != null color: widget.color != null
? widget.color ? widget.color
: Hexcolor("#000000"), : HexColor("#000000"),
), ),
), ),
), ),

@ -25,7 +25,7 @@ class CircleContainer extends StatelessWidget {
shape: BoxShape.circle, shape: BoxShape.circle,
color: color, color: color,
border: Border.all( border: Border.all(
color: borderColor ?? Hexcolor("#707070"), width: borderWidth)), color: borderColor ?? HexColor("#707070"), width: borderWidth)),
height: 80, height: 80,
width: 80, width: 80,
), ),

@ -61,7 +61,7 @@ class CustomerBriefCard extends StatelessWidget {
], ],
), ),
child: Container( child: Container(
padding: EdgeInsets.only(left: 30, top: 20, right: 30), padding: EdgeInsets.only(left: 20, top: 20, right: 20),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,

@ -6,140 +6,157 @@ import 'package:hexcolor/hexcolor.dart';
class OrderInfoCard extends StatelessWidget { class OrderInfoCard extends StatelessWidget {
const OrderInfoCard( const OrderInfoCard(
{Key key, this.order, this.onTap, this.showStatus = false}) {Key key, this.order, this.onTap, this.showStatus = false, this.isActiveToDeliver = false})
: super(key: key); : super(key: key);
final dynamic order; final dynamic order;
final Function onTap; final Function onTap;
final bool showStatus; final bool showStatus;
final bool isActiveToDeliver;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return InkWell( return InkWell(
child: Container( child:
Container(
child: RoundedContainer( child: RoundedContainer(
showShadow: true, showShadow: true,
raduis: 25.0, raduis: 25.0,
height: MediaQuery.of(context).orientation == Orientation.portrait height: MediaQuery.of(context).orientation == Orientation.portrait
? MediaQuery.of(context).size.height * (showStatus ? 0.22 : 0.160) ? MediaQuery.of(context).size.height * (showStatus ? 0.22 : 0.160)
: MediaQuery.of(context).size.height * : MediaQuery.of(context).size.height *
(showStatus ? 0.359 : 0.269), (showStatus ? 0.359 : 0.269),
child: FractionallySizedBox( child: FractionallySizedBox(
widthFactor: 0.98, widthFactor: 0.98,
child: Column( child: Stack(
// mainAxisAlignment: MainAxisAlignment.start, children:[
if(isActiveToDeliver)
Padding(
padding: const EdgeInsets.all(10.0),
child: Align(
alignment: Alignment.bottomRight,
child:Image.asset(
'assets/images/check.png',
height: 20,
width: 20,
),
),
),
Column(
// mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[ children: <Widget>[
Column( Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
Column( Column(
children: [ children: [
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Padding( Padding(
padding: padding:
EdgeInsets.only(left: 15.0, top: 14.0), EdgeInsets.only(left: 15.0, top: 14.0),
child: Image.asset( child: Image.asset(
'assets/images/location.png', 'assets/images/location.png',
height: MediaQuery.of(context) height: MediaQuery.of(context)
.orientation == .orientation ==
Orientation.portrait Orientation.portrait
? MediaQuery.of(context).size.height * ? MediaQuery.of(context).size.height *
0.06 0.06
: MediaQuery.of(context).size.height * : MediaQuery.of(context).size.height *
0.11, 0.11,
width: MediaQuery.of(context).orientation == width: MediaQuery.of(context).orientation ==
Orientation.portrait Orientation.portrait
? MediaQuery.of(context).size.width * ? MediaQuery.of(context).size.width *
0.05 0.05
: MediaQuery.of(context).size.width * : MediaQuery.of(context).size.width *
0.09, 0.09,
), ),
),
SizedBox(
width: 13,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 20.0),
child: Text(
Utils.formatStringToPascalCase(
order.firstName +
' ' +
order.lastName),
style: TextStyle(
fontSize: 18.0,
color: Hexcolor("#343333"),
fontWeight: FontWeight.bold),
), ),
), SizedBox(
Text( width: 13,
order.mobileNumber,
style: TextStyle(
color: Color(0xff30B7B9),
fontWeight: FontWeight.w600,
fontSize: 15.0,
), ),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 20.0),
child: Text(
Utils.formatStringToPascalCase(
order.firstName +
' ' +
order.lastName),
style: TextStyle(
fontSize: 18.0,
color: HexColor("#343333"),
fontWeight: FontWeight.bold),
),
),
Text(
order.mobileNumber,
style: TextStyle(
color: Color(0xff30B7B9),
fontWeight: FontWeight.w600,
fontSize: 15.0,
),
),
Text(
order.orderID.toString(),
style: TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.w400,
letterSpacing: 8.0),
),
],
),
],
),
],
)
],
),
Padding(
padding: EdgeInsets.all(8.0),
child: DistanceInKilometers(
distanceInKilometers: order.distanceInKilometers,
),
),
],
),
if (showStatus)
Row(
children: [
Container(
margin: EdgeInsets.only(bottom: 12, left: 10),
child: RoundedContainer(
margin: 4,
showShadow: false,
backgroundColor:
order.statusID == 2 ? Colors.green : Colors.red,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 5, horizontal: 15),
child: Text(
order.description,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 15.0,
), ),
Text( ),
order.orderID.toString(),
style: TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.w400,
letterSpacing: 8.0),
),
],
), ),
], ),
), ),
], ],
) )
],
),
Padding(
padding: EdgeInsets.all(8.0),
child: DistanceInKilometers(
distanceInKilometers: order.distanceInKilometers,
),
),
],
),
if (showStatus)
Row(
children: [
Container(
margin: EdgeInsets.only(bottom: 12, left: 10),
child: RoundedContainer(
margin: 4,
showShadow: false,
backgroundColor:
order.statusID == 2 ? Colors.green : Colors.red,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 5, horizontal: 15),
child: Text(
order.description,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 15.0,
),
),
),
),
),
], ],
) ),
], ]),
),
), ),
), ),
), ),

@ -67,7 +67,7 @@ class _RoundedContainerState extends State<RoundedContainer> {
boxShadow: widget.showShadow ? [ boxShadow: widget.showShadow ? [
BoxShadow( BoxShadow(
color: Hexcolor("#DBE5E6"), color: HexColor("#DBE5E6"),
spreadRadius: 15, spreadRadius: 15,
blurRadius: 15, blurRadius: 15,
offset: Offset(0, 7), // changes position of shadow offset: Offset(0, 7), // changes position of shadow

@ -56,7 +56,7 @@ dependencies:
# UI Reqs # UI Reqs
dotted_border: 1.0.5 dotted_border: 1.0.5
expandable: ^4.1.4 expandable: ^4.1.4
hexcolor: 1.0.1 hexcolor: ^1.0.6
# Notification Banner # Notification Banner
dropdown_banner: ^1.4.0 dropdown_banner: ^1.4.0
@ -72,6 +72,10 @@ dependencies:
# location # location
location: ^3.0.2 location: ^3.0.2
# latlong tools
latlong: any
#gradient #gradient
gradient_app_bar: ^0.1.3 gradient_app_bar: ^0.1.3
@ -79,11 +83,14 @@ dependencies:
#Barcode Scanner #Barcode Scanner
flutter_barcode_scanner: ^1.0.1 flutter_barcode_scanner: ^1.0.1
#android_intent
android_intent: any
# Alerts Dailogs
sweetalert: any
# flutter_material_pickers
flutter_material_pickers: 1.7.4
@ -119,3 +126,7 @@ flutter:
- asset: assets/fonts/Metropolis/Metropolis-Regular.otf - asset: assets/fonts/Metropolis/Metropolis-Regular.otf
- asset: assets/fonts/Metropolis/Metropolis-Bold.otf - asset: assets/fonts/Metropolis/Metropolis-Bold.otf
- asset: assets/fonts/Metropolis/Metropolis-Light.otf - asset: assets/fonts/Metropolis/Metropolis-Light.otf
- family: HMGIcon1
fonts:
- asset: assets/fonts/icomoon.ttf

Loading…
Cancel
Save