diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 8d53eaf..7be27d5 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -2,6 +2,9 @@
package="com.mohem_flutter_app">
+
+
+
diff --git a/assets/icons/create_req.svg b/assets/icons/create_req.svg
new file mode 100644
index 0000000..a87e809
--- /dev/null
+++ b/assets/icons/create_req.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/icons/home.svg b/assets/icons/home.svg
new file mode 100644
index 0000000..fb67997
--- /dev/null
+++ b/assets/icons/home.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/icons/item_for_sale.svg b/assets/icons/item_for_sale.svg
new file mode 100644
index 0000000..0a87567
--- /dev/null
+++ b/assets/icons/item_for_sale.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/nfc/ic_done.png b/assets/icons/nfc/ic_done.png
new file mode 100644
index 0000000..5b80285
Binary files /dev/null and b/assets/icons/nfc/ic_done.png differ
diff --git a/assets/icons/nfc/ic_nfc.png b/assets/icons/nfc/ic_nfc.png
new file mode 100644
index 0000000..274e1b8
Binary files /dev/null and b/assets/icons/nfc/ic_nfc.png differ
diff --git a/assets/icons/work_list.svg b/assets/icons/work_list.svg
new file mode 100644
index 0000000..a802c53
--- /dev/null
+++ b/assets/icons/work_list.svg
@@ -0,0 +1,15 @@
+
diff --git a/lib/api/dashboard_api_client.dart b/lib/api/dashboard_api_client.dart
index 76e2453..f4c583d 100644
--- a/lib/api/dashboard_api_client.dart
+++ b/lib/api/dashboard_api_client.dart
@@ -8,6 +8,7 @@ import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_
import 'package:mohem_flutter_app/models/dashboard/itg_forms_model.dart';
import 'package:mohem_flutter_app/models/generic_response_model.dart';
import 'package:mohem_flutter_app/models/member_login_list_model.dart';
+import 'package:uuid/uuid.dart';
import 'api_client.dart';
@@ -89,4 +90,27 @@ class DashboardApiClient {
return responseData;
}, url, postParams);
}
+
+ //Mark Attendance
+ Future markAttendance({String lat = "0", String? long = "0", required int pointType, String nfcValue = "", bool isGpsRequired = false}) async {
+ String url = "${ApiConsts.swpRest}AuthenticateAndSwipeUserSupportNFC";
+ var uuid = Uuid();
+ // Generate a v4 (random) id
+
+ Map postParams = {
+ "UID": uuid.v4(), //Mobile Id
+ "Latitude": lat,
+ "Longitude": long,
+ "QRValue": "",
+ "PointType": pointType, // NFC=2, Wifi = 3, QR= 1,
+ "NFCValue": nfcValue,
+ "WifiValue": "",
+ "IsGpsRequired": isGpsRequired
+ };
+ postParams.addAll(AppState().postParamsJson);
+ return await ApiClient().postJsonForObject((json) {
+ GenericResponseModel responseData = GenericResponseModel.fromJson(json);
+ return responseData;
+ }, url, postParams);
+ }
}
diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart
index 89493ee..51337ff 100644
--- a/lib/app_state/app_state.dart
+++ b/lib/app_state/app_state.dart
@@ -37,6 +37,7 @@ class AppState {
bool isArabic(context) => EasyLocalization.of(context)?.locale.languageCode == "ar";
String? _username;
+
// todo ''sikander' added password for now, later will remove & improve
String? password;
diff --git a/lib/classes/app_permissions.dart b/lib/classes/app_permissions.dart
new file mode 100644
index 0000000..a70342c
--- /dev/null
+++ b/lib/classes/app_permissions.dart
@@ -0,0 +1,30 @@
+import 'package:permission_handler/permission_handler.dart';
+
+class AppPermissions{
+ static location(Function(bool) completion) {
+ Permission.location.isGranted.then((isGranted){
+ if(!isGranted){
+ Permission.location.request().then((granted){
+ completion(granted == PermissionStatus.granted);
+ });
+ }
+ completion(isGranted);
+ });
+
+ }
+
+ static checkAll(Function(bool) completion){
+ [
+ Permission.location
+ ].request().then((value){
+
+ bool allGranted = false;
+ value.values.forEach((element) {
+ allGranted = allGranted && element == PermissionStatus.granted;
+ });
+
+ completion(allGranted);
+
+ });
+ }
+}
\ No newline at end of file
diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart
index a11edec..a95e5b4 100644
--- a/lib/classes/consts.dart
+++ b/lib/classes/consts.dart
@@ -1,10 +1,12 @@
class ApiConsts {
//static String baseUrl = "http://10.200.204.20:2801/"; // Local server
static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server
- static String baseUrlServices = baseUrl + "/services/"; // server
+ // static String baseUrl = "https://hmgwebservices.com"; // Live server
+ static String baseUrlServices = baseUrl + "/Services/"; // server
// static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server
static String utilitiesRest = baseUrlServices + "Utilities.svc/REST/";
static String erpRest = baseUrlServices + "ERP.svc/REST/";
+ static String swpRest = baseUrlServices + "SWP.svc/REST/";
static String user = baseUrlServices + "api/User/";
static String cocRest = baseUrlServices + "COCWS.svc/REST/";
}
diff --git a/lib/classes/utils.dart b/lib/classes/utils.dart
index 3b200f5..d3081d4 100644
--- a/lib/classes/utils.dart
+++ b/lib/classes/utils.dart
@@ -47,6 +47,10 @@ class Utils {
});
}
+ static Future delay(int millis) async {
+ return await Future.delayed(Duration(milliseconds: millis));
+ }
+
static void hideLoading(BuildContext context) {
if (_isLoadingVisible) {
_isLoadingVisible = false;
diff --git a/lib/main.dart b/lib/main.dart
index 6a0516e..9952762 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,4 +1,5 @@
import 'dart:io';
+import 'dart:typed_data';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
@@ -9,6 +10,9 @@ import 'package:mohem_flutter_app/models/post_params_model.dart';
import 'package:mohem_flutter_app/provider/dashboard_provider_model.dart';
import 'package:mohem_flutter_app/provider/eit_provider_model.dart';
import 'package:mohem_flutter_app/theme/app_theme.dart';
+import 'package:mohem_flutter_app/widgets/nfc/nfc_reader_sheet.dart';
+import 'package:nfc_manager/nfc_manager.dart';
+import 'package:nfc_manager/platform_tags.dart';
import 'package:provider/provider.dart';
import 'package:sizer/sizer.dart';
import 'package:firebase_core/firebase_core.dart';
@@ -26,7 +30,7 @@ Future main() async {
await EasyLocalization.ensureInitialized();
await Firebase.initializeApp();
AppState().setPostParamsModel(
- PostParamsModel(channel: 31, versionID: 3.2, mobileType: Platform.isAndroid ? "android" : "ios"),
+ PostParamsModel(channel: 31, versionID: 3.4, mobileType: Platform.isAndroid ? "android" : "ios"),
);
runApp(
EasyLocalization(
@@ -79,3 +83,140 @@ class MyApp extends StatelessWidget {
);
}
}
+
+// class MyApp extends StatefulWidget {
+// @override
+// State createState() => MyAppState();
+// }
+//
+// class MyAppState extends State {
+// ValueNotifier result = ValueNotifier(null);
+//
+// @override
+// Widget build(BuildContext context) {
+// return MaterialApp(
+// home: Scaffold(
+// appBar: AppBar(title: Text('NfcManager Plugin Example')),
+// body: SafeArea(
+// child: FutureBuilder(
+// future: NfcManager.instance.isAvailable(),
+// builder: (context, ss) => ss.data != true
+// ? Center(child: Text('NfcManager.isAvailable(): ${ss.data}'))
+// : Flex(
+// mainAxisAlignment: MainAxisAlignment.spaceBetween,
+// direction: Axis.vertical,
+// children: [
+// Flexible(
+// flex: 2,
+// child: Container(
+// margin: EdgeInsets.all(4),
+// constraints: BoxConstraints.expand(),
+// decoration: BoxDecoration(border: Border.all()),
+// child: SingleChildScrollView(
+// child: ValueListenableBuilder(
+// valueListenable: result,
+// builder: (context, value, _) => Text('${value ?? ''}'),
+// ),
+// ),
+// ),
+// ),
+// Flexible(
+// flex: 3,
+// child: GridView.count(
+// padding: EdgeInsets.all(4),
+// crossAxisCount: 2,
+// childAspectRatio: 4,
+// crossAxisSpacing: 4,
+// mainAxisSpacing: 4,
+// children: [
+// ElevatedButton(child: Text('Tag Read'), onPressed: _tagRead),
+// ElevatedButton(child: Text('Ndef Write'), onPressed: _ndefWrite),
+// ElevatedButton(child: Text('Ndef Write Lock'), onPressed: _ndefWriteLock),
+// ],
+// ),
+// ),
+// ],
+// ),
+// ),
+// ),
+// ),
+// );
+// }
+//
+// void _tagRead() {
+// showNfcReader(
+// context,
+// onNcfScan: (String? nfcId) {},
+// );
+// // NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
+// // result.value = tag.data;
+// // print(tag.data);
+// // var ndef = Ndef.from(tag);
+// //
+// // var f = MifareUltralight(tag: tag, identifier: tag.data["nfca"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22);
+// // final String identifier = f.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
+// // print(identifier); // => 0428fcf2255e81
+// // print(ndef!.additionalData);
+// //
+// // // onDiscovered callback
+// // // final mifare = MiFare.from(tag);
+// // // if (mifare == null) {
+// // // print('Tag is not compatible with MiFare.');
+// // // return;
+// // // }
+// // // print(mifare.identifier);
+// // // final String identifier = mifare.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
+// // // print(identifier); // => 0428fcf2255e81
+// // NfcManager.instance.stopSession();
+// // });
+// }
+//
+// void _ndefWrite() {
+// NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
+// var ndef = Ndef.from(tag);
+// if (ndef == null || !ndef.isWritable) {
+// result.value = 'Tag is not ndef writable';
+// NfcManager.instance.stopSession(errorMessage: result.value);
+// return;
+// }
+//
+// NdefMessage message = NdefMessage([
+// NdefRecord.createText('Hello World!'),
+// NdefRecord.createUri(Uri.parse('https://flutter.dev')),
+// NdefRecord.createMime('text/plain', Uint8List.fromList('Hello'.codeUnits)),
+// NdefRecord.createExternal('com.example', 'mytype', Uint8List.fromList('mydata'.codeUnits)),
+// ]);
+//
+// try {
+// await ndef.write(message);
+// result.value = 'Success to "Ndef Write"';
+// NfcManager.instance.stopSession();
+// } catch (e) {
+// result.value = e;
+// NfcManager.instance.stopSession(errorMessage: result.value.toString());
+// return;
+// }
+// });
+// }
+//
+// void _ndefWriteLock() {
+// NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
+// var ndef = Ndef.from(tag);
+// if (ndef == null) {
+// result.value = 'Tag is not ndef';
+// NfcManager.instance.stopSession(errorMessage: result.value.toString());
+// return;
+// }
+//
+// try {
+// await ndef.writeLock();
+// result.value = 'Success to "Ndef Write Lock"';
+// NfcManager.instance.stopSession();
+// } catch (e) {
+// result.value = e;
+// NfcManager.instance.stopSession(errorMessage: result.value.toString());
+// return;
+// }
+// });
+// }
+// }
diff --git a/lib/provider/dashboard_provider_model.dart b/lib/provider/dashboard_provider_model.dart
index 9fab4b9..9316182 100644
--- a/lib/provider/dashboard_provider_model.dart
+++ b/lib/provider/dashboard_provider_model.dart
@@ -19,6 +19,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
//Attendance Tracking
bool isAttendanceTrackingLoading = true;
int endTime = 0, isTimeRemainingInSeconds = 0;
+ double progress = 0.0;
GetAttendanceTracking? attendanceTracking;
//Work List
@@ -40,19 +41,27 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
List? getMenuEntriesList;
//Attendance Tracking API's & Methods
- void fetchAttendanceTracking(context) async {
+ Future fetchAttendanceTracking(context) async {
try {
attendanceTracking = await DashboardApiClient().getAttendanceTracking();
+ print("attendanceTracking:" + (attendanceTracking!.pRemainingHours).toString());
isAttendanceTrackingLoading = false;
- isTimeRemainingInSeconds = calculateSeconds("00:00:00");
- endTime = DateTime.now().millisecondsSinceEpoch + Duration(seconds: isTimeRemainingInSeconds).inMilliseconds;
- print("isTimeRemainingInSeconds " + isTimeRemainingInSeconds.toString());
- print("endTime " + endTime.toString());
+ // isTimeRemainingInSeconds = calculateSeconds( "00:00:00");
+ if (attendanceTracking?.pSwipeIn != null) {
+ isTimeRemainingInSeconds = calculateSeconds(attendanceTracking!.pRemainingHours ?? "00:00:00");
+ int totalShiftTimeInSeconds = calculateSeconds(attendanceTracking!.pScheduledHours ?? "00:00:00");
+ print("totalShiftTimeInSeconds: " + totalShiftTimeInSeconds.toString());
+ print("isTimeRemainingInSeconds: " + isTimeRemainingInSeconds.toString());
+ progress = (isTimeRemainingInSeconds / totalShiftTimeInSeconds);
+ endTime = DateTime.now().millisecondsSinceEpoch + Duration(seconds: isTimeRemainingInSeconds).inMilliseconds;
+ print("endTime " + endTime.toString());
+ }
- // notifyListeners();
+ notifyListeners();
} catch (ex) {
Utils.handleException(ex, context, null);
}
+ return true;
}
int calculateSeconds(String time) {
@@ -62,17 +71,19 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
return ((hour * 60 * 60) + (mints * 60) + seconds);
}
- update() {
- isAttendanceTrackingLoading = !isAttendanceTrackingLoading;
- isWorkListLoading = !isWorkListLoading;
- attendanceTracking?.pSwipeIn = "a";
- isTimeRemainingInSeconds = calculateSeconds("00:10:30");
- endTime = DateTime.now().millisecondsSinceEpoch + Duration(seconds: isTimeRemainingInSeconds).inMilliseconds;
- notifyListeners();
+ update(context) {
+ fetchAttendanceTracking(context);
+ // isAttendanceTrackingLoading = !isAttendanceTrackingLoading;
+ // isWorkListLoading = !isWorkListLoading;
+ // attendanceTracking?.pSwipeIn = "a";
+ // isTimeRemainingInSeconds = calculateSeconds("00:10:30");
+ // endTime = DateTime.now().millisecondsSinceEpoch + Duration(seconds: isTimeRemainingInSeconds).inMilliseconds;
+ // notifyListeners();
}
ItgFormsModel? itgFormsModel;
List? getOpenNotificationsList;
+
//Work List API's & Methods
Future fetchWorkListCounter(context, {bool showLoading = false}) async {
try {
@@ -167,7 +178,7 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
}
}
- //Verify Menus by printing in log
+ // Verify Menus by printing in log
// for(int i=0;i {
data.fetchWorkListCounter(context);
data.fetchMissingSwipe(context);
data.fetchLeaveTicketBalance(context);
- data.fetchMenuEntries();
+ // data.fetchMenuEntries();
}
@override
@@ -96,7 +96,7 @@ class _DashboardScreenState extends State {
],
),
).onPress(() {
- data.update();
+ data.update(context);
})
],
).paddingOnly(left: 21, right: 21, top: 48, bottom: 7),
diff --git a/lib/ui/landing/today_attendance_screen.dart b/lib/ui/landing/today_attendance_screen.dart
index b2ab7aa..2008484 100644
--- a/lib/ui/landing/today_attendance_screen.dart
+++ b/lib/ui/landing/today_attendance_screen.dart
@@ -1,12 +1,25 @@
import 'package:easy_localization/src/public_ext.dart';
import 'package:flutter/material.dart';
+import 'package:flutter_countdown_timer/flutter_countdown_timer.dart';
import 'package:flutter_svg/flutter_svg.dart';
+import 'package:google_maps_flutter/google_maps_flutter.dart';
+import 'package:mohem_flutter_app/api/dashboard_api_client.dart';
+import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
+import 'package:mohem_flutter_app/classes/date_uitl.dart';
+import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/extensions/string_extensions.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
+import 'package:mohem_flutter_app/models/generic_response_model.dart';
import 'package:mohem_flutter_app/widgets/circular_step_progress_bar.dart';
+import 'package:mohem_flutter_app/widgets/nfc/nfc_reader_sheet.dart';
+import 'package:nfc_manager/nfc_manager.dart';
+import 'package:provider/provider.dart';
+
+import '../../provider/dashboard_provider_model.dart';
+import '../../widgets/location/Location.dart';
class TodayAttendanceScreen extends StatefulWidget {
TodayAttendanceScreen({Key? key}) : super(key: key);
@@ -18,14 +31,45 @@ class TodayAttendanceScreen extends StatefulWidget {
}
class _TodayAttendanceScreenState extends State {
+ ValueNotifier result = ValueNotifier(null);
+ late DashboardProviderModel data;
+ bool isNfcEnabled = false, isNfcLocationEnabled = false, isQrEnabled = false, isQrLocationEnabled = false, isWifiEnabled = false, isWifiLocationEnabled = false;
+
@override
void initState() {
super.initState();
+ checkAttendanceAvailablity();
+ data = Provider.of(context, listen: false);
+ }
+
+ checkAttendanceAvailablity() async {
+ bool isAvailable = await NfcManager.instance.isAvailable();
+ setState(() {
+ AppState().privilegeListModel!.forEach((element) {
+ // Check availability
+ if (isAvailable) if (element.serviceName == "enableNFC") {
+ // if (element.previlege ?? false)
+ isNfcEnabled = true;
+ } else if (element.serviceName == "enableQR") {
+ if (element.previlege ?? false) isQrEnabled = true;
+ } else if (element.serviceName == "enableWIFI") {
+ if (element.previlege ?? false) isWifiEnabled = true;
+ } else if (element.serviceName == "enableLocatoinNFC") {
+ if (element.previlege ?? false) isNfcLocationEnabled = true;
+ } else if (element.serviceName == "enableLocationQR") {
+ if (element.previlege ?? false) isQrLocationEnabled = true;
+ } else if (element.serviceName == "enableLocationWIFI") {
+ if (element.previlege ?? false) isWifiLocationEnabled = true;
+ }
+ });
+ });
}
@override
void dispose() {
super.dispose();
+ // Stop Session
+ NfcManager.instance.stopSession();
}
@override
@@ -37,123 +81,170 @@ class _TodayAttendanceScreenState extends State {
icon: const Icon(Icons.arrow_back_ios, color: Colors.white),
onPressed: () => Navigator.pop(context),
),
- ),
- backgroundColor: Colors.white,
- body: ListView(
- children: [
- Container(
- color: MyColors.backgroundBlackColor,
- padding: EdgeInsets.only(top: 4,left: 21, right: 21, bottom: 21),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- "June 13, 2021".toText24(isBold: true, color: Colors.white),
- LocaleKeys.timeLeftToday.tr().toText16(color: Color(0xffACACAC)),
- 21.height,
- Center(
- child: CircularStepProgressBar(
- totalSteps: 16 * 4,
- currentStep: 16,
- width: 216,
- height: 216,
- selectedColor: MyColors.gradiantEndColor,
- unselectedColor: MyColors.grey70Color,
- child: Center(
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- "08:58:15".toText32(color: Colors.white, isBold: true),
- 19.height,
- "Shift Time".tr().toText12(color: MyColors.greyACColor),
- "08:00 - 17:00".toText22(color: Colors.white, isBold: true),
- ],
- ),
- ),
- ),
- ),
- ],
- ),
- ),
- Container(
- color: MyColors.backgroundBlackColor,
- child: Stack(
- children: [
- Container(
- height: 187,
- padding: EdgeInsets.only(left: 31, right: 31, top: 31, bottom: 16),
- decoration: BoxDecoration(
- borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)),
- gradient: const LinearGradient(transform: GradientRotation(.64), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [
- MyColors.gradiantEndColor,
- MyColors.gradiantStartColor,
- ]),
- ),
- child: Column(
- children: [
- Row(
- children: [commonStatusView("Check In", "09:27"), commonStatusView("Check Out", "- - : - -")],
- ),
- 21.height,
- Row(
- children: [commonStatusView("Late In", "00:27"), commonStatusView("Regular", "08:00")],
- ),
- ],
- ),
- ),
- Container(
- width: double.infinity,
- decoration: BoxDecoration(borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), color: Colors.white),
- margin: EdgeInsets.only(top: 187 - 31),
- padding: EdgeInsets.only(left: 21, right: 21, top: 24, bottom: 24),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- mainAxisSize: MainAxisSize.min,
- children: [
- "Mark".tr().toText12(),
- "Attendance".tr().toText24(),
- "Select the method to mark the attendance".tr().toText12(color: Color(0xff535353)),
- 24.height,
- GridView(
- physics: const NeverScrollableScrollPhysics(),
- shrinkWrap: true,
- padding: EdgeInsets.zero,
- gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1 / 1, crossAxisSpacing: 8, mainAxisSpacing: 8),
- children: [
- attendanceMethod("NFC", "assets/images/nfc.svg", () {}),
- attendanceMethod("Wifi", "assets/images/wufu.svg", () {}),
- ],
- )
- ],
- ),
- ),
- // Positioned(
- // top: 187 - 21,
- // child: Container(
- // padding: EdgeInsets.only(left: 31, right: 31, top: 31, bottom: 16),
- // decoration: BoxDecoration(borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), color: Colors.white),
- // child: Column(
- // children: [
- // Row(
- // children: [commonStatusView("Check In", "09:27"), commonStatusView("Check Out", "- - : - -")],
- // ),
- // 21.height,
- // Row(
- // children: [commonStatusView("Late In", "00:27"), commonStatusView("Regular", "08:00")],
- // ),
- // ],
- // ),
- // ),
- // ),
- ],
+ actions: [
+ IconButton(
+ onPressed: () {
+ data.fetchAttendanceTracking();
+ },
+ icon: Icon(
+ Icons.ac_unit,
+ color: Colors.white,
),
)
],
),
+ backgroundColor: MyColors.backgroundBlackColor,
+ body: Consumer(
+ builder: (context, model, child) {
+ return (model.isAttendanceTrackingLoading
+ ? Center(child: CircularProgressIndicator())
+ : ListView(
+ children: [
+ Container(
+ color: MyColors.backgroundBlackColor,
+ padding: EdgeInsets.only(top: 4, left: 21, right: 21, bottom: 21),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ DateUtil.getWeekDayMonthDayYearDateFormatted(DateTime.now(), "en").toText24(isBold: true, color: Colors.white),
+ LocaleKeys.timeLeftToday.tr().toText16(color: Color(0xffACACAC)),
+ 21.height,
+ Center(
+ child: CircularStepProgressBar(
+ totalSteps: 16 * 4,
+ currentStep: (model.progress * 100).toInt(),
+ width: 216,
+ height: 216,
+ selectedColor: MyColors.gradiantEndColor,
+ unselectedColor: MyColors.grey70Color,
+ child: Center(
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ CountdownTimer(
+ endTime: model.endTime,
+ onEnd: null,
+ endWidget: "00:00:00".toText32(color: Colors.white, isBold: true),
+ textStyle: TextStyle(color: Colors.white, fontSize: 32, letterSpacing: -1.92, fontWeight: FontWeight.bold, height: 1),
+ ),
+ 19.height,
+ "Shift Time".tr().toText12(color: MyColors.greyACColor),
+ (model.attendanceTracking!.pShtName ?? "00:00:00").toString().toText22(color: Colors.white, isBold: true),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ Container(
+ color: MyColors.backgroundBlackColor,
+ child: Stack(
+ children: [
+ Container(
+ height: 187,
+ padding: EdgeInsets.only(left: 31, right: 31, top: 31, bottom: 16),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)),
+ gradient: const LinearGradient(transform: GradientRotation(.64), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [
+ MyColors.gradiantEndColor,
+ MyColors.gradiantStartColor,
+ ]),
+ ),
+ child: Column(
+ children: [
+ Row(
+ children: [
+ commonStatusView("Check In", (model.attendanceTracking!.pSwipeIn) ?? "- - : - -"),
+ commonStatusView("Check Out", (model.attendanceTracking!.pSwipeOut) ?? "- - : - -")
+ ],
+ ),
+ 21.height,
+ Row(
+ children: [
+ commonStatusView("Late In", (model.attendanceTracking!.pLateInHours) ?? "- - : - -"),
+ commonStatusView("Regular", (model.attendanceTracking!.pScheduledHours) ?? "- - : - -")
+ ],
+ ),
+ ],
+ ),
+ ),
+ Container(
+ width: double.infinity,
+ decoration: BoxDecoration(borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), color: Colors.white),
+ margin: EdgeInsets.only(top: 187 - 31),
+ padding: EdgeInsets.only(left: 21, right: 21, top: 24, bottom: 24),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ "Mark".tr().toText12(),
+ "Attendance".tr().toText24(),
+ "Select the method to mark the attendance".tr().toText12(color: Color(0xff535353)),
+ 24.height,
+ GridView(
+ physics: const NeverScrollableScrollPhysics(),
+ shrinkWrap: true,
+ padding: EdgeInsets.zero,
+ gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1 / 1, crossAxisSpacing: 8, mainAxisSpacing: 8),
+ children: [
+ attendanceMethod("NFC", "assets/images/nfc.svg", isNfcEnabled, () {
+ showNfcReader(context, onNcfScan: (String? nfcId) async {
+ print(nfcId);
+ Utils.showLoading(context);
+ try {
+ GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 2, nfcValue: nfcId ?? "");
+ bool status = await model.fetchAttendanceTracking();
+ Utils.hideLoading(context);
+ } catch (ex) {
+ print(ex);
+ Utils.hideLoading(context);
+ Utils.handleException(ex, (msg) {
+ Utils.confirmDialog(context, msg);
+ });
+ }
+ });
+ // Location.getCurrentLocation((LatLng? latlng) {
+ // print(latlng!.longitude.toString());
+ // });
+ }),
+ attendanceMethod("Wifi", "assets/images/wufu.svg", isWifiEnabled, () {}),
+ ],
+ )
+ ],
+ ),
+ ),
+ // Positioned(
+ // top: 187 - 21,
+ // child: Container(
+ // padding: EdgeInsets.only(left: 31, right: 31, top: 31, bottom: 16),
+ // decoration: BoxDecoration(borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), color: Colors.white),
+ // child: Column(
+ // children: [
+ // Row(
+ // children: [commonStatusView("Check In", "09:27"), commonStatusView("Check Out", "- - : - -")],
+ // ),
+ // 21.height,
+ // Row(
+ // children: [commonStatusView("Late In", "00:27"), commonStatusView("Regular", "08:00")],
+ // ),
+ // ],
+ // ),
+ // ),
+ // ),
+ ],
+ ),
+ )
+ ],
+ ))
+ .animatedSwither();
+ },
+ ),
);
}
- Widget attendanceMethod(String title, String image, VoidCallback onPress) => Container(
- padding: const EdgeInsets.only(left: 10, right: 10, top: 14, bottom: 14),
+ Widget attendanceMethod(String title, String image, bool isEnabled, VoidCallback onPress) => Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
gradient: const LinearGradient(transform: GradientRotation(.64), begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [
@@ -161,9 +252,26 @@ class _TodayAttendanceScreenState extends State {
MyColors.gradiantStartColor,
]),
),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [Expanded(child: SvgPicture.asset(image)), title.toText17(isBold: true, color: Colors.white)],
+ clipBehavior: Clip.antiAlias,
+ child: Stack(
+ children: [
+ Container(
+ padding: const EdgeInsets.only(left: 10, right: 10, top: 14, bottom: 14),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Expanded(child: SvgPicture.asset(image)),
+ title.toText17(isBold: true, color: Colors.white),
+ ],
+ ),
+ ),
+ if (!isEnabled)
+ Container(
+ width: double.infinity,
+ height: double.infinity,
+ color: Colors.grey.withOpacity(0.7),
+ )
+ ],
),
).onPress(onPress);
diff --git a/lib/ui/landing/widget/services_widget.dart b/lib/ui/landing/widget/services_widget.dart
index 955915c..ee77693 100644
--- a/lib/ui/landing/widget/services_widget.dart
+++ b/lib/ui/landing/widget/services_widget.dart
@@ -144,18 +144,19 @@ class ServicesWidget extends StatelessWidget {
SizedBox(
height: 105 + 26,
child: ListView.separated(
- shrinkWrap: true,
- physics: const BouncingScrollPhysics(),
- padding: const EdgeInsets.only(left: 21, right: 21, top: 13, bottom: 13),
- scrollDirection: Axis.horizontal,
- itemBuilder: (cxt, index) {
- return AspectRatio(
- aspectRatio: 105 / 105,
- child: ServicesMenuShimmer(),
- );
- },
- separatorBuilder: (cxt, index) => 9.width,
- itemCount: 4),
+ shrinkWrap: true,
+ physics: const BouncingScrollPhysics(),
+ padding: const EdgeInsets.only(left: 21, right: 21, top: 13, bottom: 13),
+ scrollDirection: Axis.horizontal,
+ itemBuilder: (cxt, index) {
+ return AspectRatio(
+ aspectRatio: 105 / 105,
+ child: ServicesMenuShimmer(),
+ );
+ },
+ separatorBuilder: (cxt, index) => 9.width,
+ itemCount: 4,
+ ),
),
],
);
diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart
index cdcdb94..6e2cbb8 100644
--- a/lib/ui/login/login_screen.dart
+++ b/lib/ui/login/login_screen.dart
@@ -69,13 +69,12 @@ class _LoginScreenState extends State {
}
String? firebaseToken;
- GetMobileLoginInfoListModel? loginInfo;
+
Future checkFirebaseToken() async {
try {
Utils.showLoading(context);
firebaseToken = await _firebaseMessaging.getToken();
- loginInfo = await LoginApiClient().getMobileLoginInfoNEW(firebaseToken ?? "", Platform.isAndroid ? "android" : "ios");
- loginInfo!.deviceToken = firebaseToken;
+ GetMobileLoginInfoListModel? loginInfo = await LoginApiClient().getMobileLoginInfoNEW(firebaseToken ?? "", Platform.isAndroid ? "android" : "ios");
if (loginInfo == null) {
Utils.hideLoading(context);
print("Device token not found");
@@ -113,7 +112,7 @@ class _LoginScreenState extends State {
}
Utils.hideLoading(context);
if (_autoLogin) {
- Navigator.pushNamed(context, AppRoutes.verifyLastLogin, arguments: loginInfo);
+ Navigator.pushNamed(context, AppRoutes.verifyLastLogin);
} else {
Navigator.pushNamed(context, AppRoutes.verifyLogin, arguments: "$firebaseToken");
}
@@ -129,7 +128,7 @@ class _LoginScreenState extends State {
@override
Widget build(BuildContext context) {
username.text = "15153";
- password.text = "Xy12345@";
+ password.text = "Abcd@1234";
return Scaffold(
body: Column(
children: [
diff --git a/lib/widgets/location/Location.dart b/lib/widgets/location/Location.dart
new file mode 100644
index 0000000..bd39e2e
--- /dev/null
+++ b/lib/widgets/location/Location.dart
@@ -0,0 +1,249 @@
+import 'dart:async';
+import 'dart:math';
+import 'dart:ui';
+import 'package:flutter/material.dart';
+import 'package:flutter/rendering.dart';
+import 'package:geolocator/geolocator.dart';
+import 'package:google_directions_api/google_directions_api.dart';
+import 'package:google_maps_flutter/google_maps_flutter.dart';
+import 'package:mohem_flutter_app/classes/utils.dart';
+// import 'package:geodesy/geodesy.dart' as geodesy;
+
+import '../../classes/app_permissions.dart';
+import '../../theme/colors.dart';
+
+
+//Created By Mr.Zohaib
+class Location {
+ static _Map map = _Map();
+
+ static havePermission(Function(bool) callback) {
+ Geolocator.checkPermission().then((value) async {
+ if (value == LocationPermission.denied) {
+ value = await Geolocator.requestPermission();
+ callback(![LocationPermission.denied, LocationPermission.deniedForever].contains(value));
+ } else {
+ callback(true);
+ }
+ });
+ }
+
+ static isEnabled(Function(bool) callback) {
+ Geolocator.isLocationServiceEnabled().then((value) => callback(value));
+ }
+
+ static bool _listeningSettingChange = true;
+
+ static listenGPS({bool change = true, Function(bool)? onChange}) async {
+ _listeningSettingChange = change;
+ if (change == false) return;
+
+ Future.doWhile(() async {
+ await Utils.delay(1000);
+ var enable = await Geolocator.isLocationServiceEnabled();
+ onChange!(enable);
+ return _listeningSettingChange;
+ });
+ }
+
+ static getCurrentLocation(Function(LatLng?) callback) {
+ done(Position position) {
+ //AppStorage.sp.saveLocation(position);
+
+ LatLng? myCurrentLocation = LatLng(position.latitude, position.longitude);
+ callback(myCurrentLocation);
+ }
+
+ AppPermissions.location((granted) {
+
+ if (granted)
+ Geolocator.getLastKnownPosition(forceAndroidLocationManager: true).then((value) {
+ if (value == null) {
+ Geolocator.getCurrentPosition().then((value) {
+ done(value);
+ });
+ } else {
+ done(value);
+ }
+ });
+ });
+ }
+
+ // static LatLng locationAwayFrom(
+ // {required LatLng loc1, num distanceMeters = 200.0, num bearing = 270.0}) {
+ // geodesy.LatLng l1 = geodesy.LatLng(loc1.latitude, loc1.longitude);
+ // geodesy.LatLng destinationPoint = geodesy.Geodesy()
+ // .destinationPointByDistanceAndBearing(l1, distanceMeters, bearing);
+ // return LatLng(destinationPoint.latitude, destinationPoint.longitude);
+ // }
+
+ static Future distanceTo(LatLng destination) async {
+ var myLoc = await Geolocator.getLastKnownPosition();
+ var distance = 0.0;
+ if (myLoc != null) {
+ distance = Geolocator.distanceBetween(destination.latitude, destination.longitude, myLoc.latitude, myLoc.longitude);
+ }
+ return distance;
+ }
+}
+
+class _Map {
+ Marker createMarker(
+ String id, {
+ required LatLng coordinates,
+ BitmapDescriptor? icon,
+ VoidCallback? onTap,
+ }) {
+ final MarkerId markerId = MarkerId(id);
+ return Marker(
+ icon: icon ?? BitmapDescriptor.defaultMarker,
+ markerId: markerId,
+ position: coordinates,
+ flat: false,
+ // infoWindow: InfoWindow(title: id, snippet: '*'),
+ onTap: onTap,
+ );
+ }
+
+ CameraPosition initialCamera({required Completer mapController, LatLng? position, double zoom = 12}) {
+ position = position ?? LatLng(24.7249303, 46.5416656);
+ CameraPosition riyadhEye = CameraPosition(
+ target: position,
+ zoom: zoom,
+ );
+ mapController.future.then((controller) {
+ controller.animateCamera(CameraUpdate.newCameraPosition(riyadhEye));
+ });
+ return riyadhEye;
+ }
+
+ CameraPosition moveTo(LatLng location, {double zoom = 12, double direction = 0.0, required Completer mapController, bool? animation}) {
+ var camera = CameraPosition(target: location, zoom: zoom, bearing: direction);
+ mapController.future.then((controller) {
+ animation ?? false ? controller.animateCamera(CameraUpdate.newCameraPosition(camera)) : controller.moveCamera(CameraUpdate.newCameraPosition(camera));
+ });
+ return camera;
+ }
+
+ moveCamera(CameraPosition camera, @required Completer mapController, bool animation) {
+ mapController.future.then((controller) {
+ animation ? controller.animateCamera(CameraUpdate.newCameraPosition(camera)) : controller.moveCamera(CameraUpdate.newCameraPosition(camera));
+ });
+ }
+
+ scrollBy({double x = 0, double y = 0, required Completer mapController, bool animation = true}) {
+ var camera = CameraUpdate.scrollBy(x, y);
+ mapController.future.then((controller) {
+ animation ? controller.animateCamera(camera) : controller.moveCamera(camera);
+ });
+ }
+
+ goToCurrentLocation({Completer? mapController, double? direction = 0.0, bool? animation}) {
+ Location.getCurrentLocation((location) {
+ moveTo(location!, zoom: 17, mapController: mapController!, animation: animation, direction: direction!);
+ });
+ }
+
+ var routes = Map();
+
+ setRoutePolylines(LatLng? source, LatLng? destination, Set polylines, Completer mapController, Function(DirectionsRoute?) completion) {
+ if (source == null || destination == null) {
+ completion(null);
+ return;
+ }
+
+ var origin = '${source.latitude},${source.longitude}';
+ var destin = '${destination.latitude},${destination.longitude}';
+ var routeId = '$origin->$destination';
+
+ createPolyline(DirectionsRoute results) {
+ List polylineCoordinates = results.overviewPath!.map((e) => LatLng(e.latitude, e.longitude)).toList();
+ PolylineId id = PolylineId("route");
+ Polyline polyline = Polyline(
+ polylineId: id,
+ color: accentColor,
+ width: 5,
+ jointType: JointType.round,
+ startCap: Cap.roundCap,
+ endCap: Cap.roundCap,
+ points: polylineCoordinates,
+ );
+
+ polylines.removeWhere((element) => true);
+ polylines.add(polyline);
+
+ LatLngBounds bound = getBounds(coordinates: polylineCoordinates);
+ focusCameraToLatLngBounds(bound: bound, mapController: mapController, padding: 100);
+ completion(routes[routeId]);
+ }
+
+ var availableRoute = routes[routeId];
+ if (availableRoute == null) {
+ var request = DirectionsRequest(origin: origin, destination: destin);
+ DirectionsService().route(request, (response, status) {
+ if (status == DirectionsStatus.ok && response.routes!.isNotEmpty) {
+ routes[routeId] = response.routes!.first;
+ createPolyline(response.routes!.first);
+ }
+ });
+ } else {
+ createPolyline(availableRoute);
+ }
+ }
+
+ LatLngBounds getBounds({required List coordinates}) {
+ var lngs = coordinates.map((c) => c.longitude).toList();
+ var lats = coordinates.map((c) => c.latitude).toList();
+
+ double bottomMost = lngs.reduce(min);
+ double topMost = lngs.reduce(max);
+ double leftMost = lats.reduce(min);
+ double rightMost = lats.reduce(max);
+
+ LatLngBounds bounds = LatLngBounds(
+ northeast: LatLng(rightMost, topMost),
+ southwest: LatLng(leftMost, bottomMost),
+ );
+ return bounds;
+
+ double? x0, x1, y0, y1;
+ for (LatLng latLng in coordinates) {
+ if (x0 == null) {
+ x0 = x1 = latLng.latitude;
+ y0 = y1 = latLng.longitude;
+ } else {
+ if (latLng.latitude > x1!) x1 = latLng.latitude;
+ if (latLng.latitude < x0) x0 = latLng.latitude;
+ if (latLng.longitude > y1!) y1 = latLng.longitude;
+ if (latLng.longitude < y0!) y0 = latLng.longitude;
+ }
+ }
+ return LatLngBounds(northeast: LatLng(x1!, y1!), southwest: LatLng(x0!, y0!));
+ }
+
+ focusCameraToLatLngBounds({LatLngBounds? bound, Completer? mapController, double? padding}) async {
+ if (bound == null) return;
+
+ CameraUpdate camera = CameraUpdate.newLatLngBounds(bound, padding!);
+ final GoogleMapController controller = await mapController!.future;
+ controller.animateCamera(camera);
+ }
+
+ focusCameraTo2Points({LatLng? point1, LatLng? point2, Completer? mapController, double? padding}) async {
+ var source = point1;
+ var destination = point2;
+ if (source != null && destination != null) {
+ // 'package:google_maps_flutter_platform_interface/src/types/location.dart': Failed assertion: line 72 pos 16: 'southwest.latitude <= northeast.latitude': is not true.
+ LatLngBounds bound;
+ if (source.latitude <= destination.latitude) {
+ bound = LatLngBounds(southwest: source, northeast: destination);
+ } else {
+ bound = LatLngBounds(southwest: destination, northeast: source);
+ }
+
+ if (bound == null) return;
+
+ focusCameraToLatLngBounds(bound: bound, mapController: mapController, padding: padding);
+ }
+ }
+}
diff --git a/lib/widgets/nfc/nfc_reader_sheet.dart b/lib/widgets/nfc/nfc_reader_sheet.dart
new file mode 100644
index 0000000..84397ba
--- /dev/null
+++ b/lib/widgets/nfc/nfc_reader_sheet.dart
@@ -0,0 +1,187 @@
+import 'dart:async';
+
+import 'package:flutter/material.dart';
+import 'package:nfc_manager/nfc_manager.dart';
+import 'package:nfc_manager/platform_tags.dart';
+
+void showNfcReader(BuildContext context, {required Function(String? nfcId) onNcfScan}) {
+ showModalBottomSheet(
+ context: context,
+ enableDrag: false,
+ isDismissible: false,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12)),
+ ),
+ backgroundColor: Colors.white,
+ builder: (context) {
+ return NfcLayout(
+ onNcfScan: onNcfScan,
+ );
+ },
+ );
+}
+
+class NfcLayout extends StatefulWidget {
+ Function(String? nfcId) onNcfScan;
+
+ NfcLayout({required this.onNcfScan});
+
+ @override
+ _NfcLayoutState createState() => _NfcLayoutState();
+}
+
+class _NfcLayoutState extends State {
+ bool _reading = false;
+ Widget? mainWidget;
+ String? nfcId;
+
+ @override
+ void initState() {
+ super.initState();
+
+ NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
+ print(tag.data);
+ var f = MifareUltralight(tag: tag, identifier: tag.data["nfca"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22);
+ final String identifier = f.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
+ // print(identifier); // => 0428fcf2255e81
+ nfcId = identifier;
+
+ setState(() {
+ _reading = true;
+ mainWidget = doneNfc();
+ });
+
+ Future.delayed(const Duration(seconds: 1), () {
+ NfcManager.instance.stopSession();
+ Navigator.pop(context);
+ widget.onNcfScan(nfcId);
+ });
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ (mainWidget == null && !_reading) ? mainWidget = scanNfc() : mainWidget = doneNfc();
+ return AnimatedSwitcher(duration: Duration(milliseconds: 500), child: mainWidget);
+ }
+
+ Widget scanNfc() {
+ return Container(
+ key: ValueKey(1),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ SizedBox(
+ height: 30,
+ ),
+ Text(
+ "Ready To Scan",
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 24,
+ ),
+ ),
+ SizedBox(
+ height: 30,
+ ),
+ Image.asset(
+ "assets/icons/nfc/ic_nfc.png",
+ height: MediaQuery.of(context).size.width / 3,
+ ),
+ SizedBox(
+ height: 30,
+ ),
+ Text(
+ "Approach an NFC Tag",
+ style: TextStyle(
+ fontSize: 18,
+ ),
+ ),
+ SizedBox(
+ height: 30,
+ ),
+ ButtonTheme(
+ minWidth: MediaQuery.of(context).size.width / 1.2,
+ height: 45.0,
+ buttonColor: Colors.grey[300],
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(6),
+ ),
+ child: RaisedButton(
+ onPressed: () {
+ NfcManager.instance.stopSession();
+ Navigator.pop(context);
+ },
+ elevation: 0,
+ child: Text("CANCEL"),
+ ),
+ ),
+ SizedBox(
+ height: 30,
+ ),
+ ],
+ ),
+ );
+ }
+
+ Widget doneNfc() {
+ return Container(
+ key: ValueKey(2),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ SizedBox(
+ height: 30,
+ ),
+ Text(
+ "Successfully Scanned",
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 24,
+ ),
+ ),
+ SizedBox(
+ height: 30,
+ ),
+ Image.asset(
+ "assets/icons/nfc/ic_done.png",
+ height: MediaQuery.of(context).size.width / 3,
+ ),
+ SizedBox(
+ height: 30,
+ ),
+ Text(
+ "Approach an NFC Tag",
+ style: TextStyle(
+ fontSize: 18,
+ ),
+ ),
+ SizedBox(
+ height: 30,
+ ),
+ ButtonTheme(
+ minWidth: MediaQuery.of(context).size.width / 1.2,
+ height: 45.0,
+ buttonColor: Colors.grey[300],
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(6),
+ ),
+ child: RaisedButton(
+ // onPressed: () {
+ // _stream?.cancel();
+ // widget.onNcfScan(nfcId);
+ // Navigator.pop(context);
+ // },
+ onPressed: null,
+ elevation: 0,
+ child: Text("DONE"),
+ ),
+ ),
+ SizedBox(
+ height: 30,
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/widgets/swipe/nfc_reader_sheet.dart b/lib/widgets/swipe/nfc_reader_sheet.dart
new file mode 100644
index 0000000..3dc357d
--- /dev/null
+++ b/lib/widgets/swipe/nfc_reader_sheet.dart
@@ -0,0 +1,194 @@
+// import 'dart:async';
+//
+// import 'package:flutter/material.dart';
+//
+//
+// void showNfcReader(BuildContext context, {Function onNcfScan}) {
+// showModalBottomSheet(
+// context: context,
+// enableDrag: false,
+// isDismissible: false,
+// shape: RoundedRectangleBorder(
+// borderRadius: BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12)),
+// ),
+// backgroundColor: Colors.white,
+// builder: (context) {
+// return NfcLayout(
+// onNcfScan: onNcfScan,
+// );
+// });
+// }
+//
+// class NfcLayout extends StatefulWidget {
+// Function onNcfScan;
+//
+// NfcLayout({this.onNcfScan});
+//
+// @override
+// _NfcLayoutState createState() => _NfcLayoutState();
+// }
+//
+// class _NfcLayoutState extends State {
+// StreamSubscription _stream;
+// bool _reading = false;
+// Widget mainWidget;
+// String nfcId;
+//
+// @override
+// void initState() {
+// super.initState();
+//
+// setState(() {
+// // _reading = true;
+// // Start reading using NFC.readNDEF()
+// _stream = NFC.readNDEF(once: false, throwOnUserCancel: false, readerMode: NFCDispatchReaderMode()).listen((NDEFMessage message) {
+// setState(() {
+// _reading = true;
+// mainWidget = doneNfc();
+// });
+// Future.delayed(const Duration(milliseconds: 500), () {
+// _stream?.cancel();
+// widget.onNcfScan(nfcId);
+// Navigator.pop(context);
+// });
+// print("read NDEF id: ${message.id}");
+// print("NFC Record " + message.payload);
+// print("NFC Record Lenght " + message.records.length.toString());
+// print("NFC Record " + message.records.first.id);
+// print("NFC Record " + message.records.first.payload);
+// print("NFC Record " + message.records.first.data);
+// print("NFC Record " + message.records.first.type);
+// // widget.onNcfScan(message.id);
+// nfcId = message.id;
+// }, onError: (e) {
+// // Check error handling guide below
+// });
+// });
+// }
+//
+// @override
+// Widget build(BuildContext context) {
+// (mainWidget == null && !_reading) ? mainWidget = scanNfc() : mainWidget = doneNfc();
+// return AnimatedSwitcher(duration: Duration(milliseconds: 500), child: mainWidget);
+// }
+//
+// Widget scanNfc() {
+// return Container(
+// key: ValueKey(1),
+// child: Column(
+// mainAxisSize: MainAxisSize.min,
+// children: [
+// SizedBox(
+// height: 30,
+// ),
+// Text(
+// "Ready To Scan",
+// style: TextStyle(
+// fontWeight: FontWeight.bold,
+// fontSize: 24,
+// ),
+// ),
+// SizedBox(
+// height: 30,
+// ),
+// Image.asset(
+// "assets/images/nfc/ic_nfc.png",
+// height: MediaQuery.of(context).size.width / 3,
+// ),
+// SizedBox(
+// height: 30,
+// ),
+// Text(
+// "Approach an NFC Tag",
+// style: TextStyle(
+// fontSize: 18,
+// ),
+// ),
+// SizedBox(
+// height: 30,
+// ),
+// ButtonTheme(
+// minWidth: MediaQuery.of(context).size.width / 1.2,
+// height: 45.0,
+// buttonColor: Colors.grey[300],
+// shape: RoundedRectangleBorder(
+// borderRadius: BorderRadius.circular(6),
+// ),
+// child: RaisedButton(
+// onPressed: () {
+// _stream?.cancel();
+// Navigator.pop(context);
+// },
+// elevation: 0,
+// child: Text("CANCEL"),
+// ),
+// ),
+// SizedBox(
+// height: 30,
+// ),
+// ],
+// ),
+// );
+// }
+//
+// Widget doneNfc() {
+// return Container(
+// key: ValueKey(2),
+// child: Column(
+// mainAxisSize: MainAxisSize.min,
+// children: [
+// SizedBox(
+// height: 30,
+// ),
+// Text(
+// "Successfully Scanned",
+// style: TextStyle(
+// fontWeight: FontWeight.bold,
+// fontSize: 24,
+// ),
+// ),
+// SizedBox(
+// height: 30,
+// ),
+// Image.asset(
+// "assets/images/nfc/ic_done.png",
+// height: MediaQuery.of(context).size.width / 3,
+// ),
+// SizedBox(
+// height: 30,
+// ),
+// Text(
+// "Approach an NFC Tag",
+// style: TextStyle(
+// fontSize: 18,
+// ),
+// ),
+// SizedBox(
+// height: 30,
+// ),
+// ButtonTheme(
+// minWidth: MediaQuery.of(context).size.width / 1.2,
+// height: 45.0,
+// buttonColor: Colors.grey[300],
+// shape: RoundedRectangleBorder(
+// borderRadius: BorderRadius.circular(6),
+// ),
+// child: RaisedButton(
+// // onPressed: () {
+// // _stream?.cancel();
+// // widget.onNcfScan(nfcId);
+// // Navigator.pop(context);
+// // },
+// onPressed: null,
+// elevation: 0,
+// child: Text("DONE"),
+// ),
+// ),
+// SizedBox(
+// height: 30,
+// ),
+// ],
+// ),
+// );
+// }
+// }
diff --git a/pubspec.lock b/pubspec.lock
deleted file mode 100644
index 58ce64a..0000000
--- a/pubspec.lock
+++ /dev/null
@@ -1,514 +0,0 @@
-# Generated by pub
-# See https://dart.dev/tools/pub/glossary#lockfile
-packages:
- args:
- dependency: transitive
- description:
- name: args
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.3.0"
- async:
- dependency: transitive
- description:
- name: async
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.8.2"
- boolean_selector:
- dependency: transitive
- description:
- name: boolean_selector
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.1.0"
- characters:
- dependency: transitive
- description:
- name: characters
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.2.0"
- charcode:
- dependency: transitive
- description:
- name: charcode
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.3.1"
- clock:
- dependency: transitive
- description:
- name: clock
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.1.0"
- collection:
- dependency: transitive
- description:
- name: collection
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.15.0"
- crypto:
- dependency: transitive
- description:
- name: crypto
- url: "https://pub.dartlang.org"
- source: hosted
- version: "3.0.1"
- cupertino_icons:
- dependency: "direct main"
- description:
- name: cupertino_icons
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.4"
- easy_localization:
- dependency: "direct main"
- description:
- name: easy_localization
- url: "https://pub.dartlang.org"
- source: hosted
- version: "3.0.0"
- easy_logger:
- dependency: transitive
- description:
- name: easy_logger
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.0.2"
- fake_async:
- dependency: transitive
- description:
- name: fake_async
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.2.0"
- ffi:
- dependency: transitive
- description:
- name: ffi
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.1.2"
- file:
- dependency: transitive
- description:
- name: file
- url: "https://pub.dartlang.org"
- source: hosted
- version: "6.1.2"
- flutter:
- dependency: "direct main"
- description: flutter
- source: sdk
- version: "0.0.0"
- flutter_countdown_timer:
- dependency: "direct main"
- description:
- name: flutter_countdown_timer
- url: "https://pub.dartlang.org"
- source: hosted
- version: "4.1.0"
- flutter_lints:
- dependency: "direct dev"
- description:
- name: flutter_lints
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.4"
- flutter_localizations:
- dependency: transitive
- description: flutter
- source: sdk
- version: "0.0.0"
- flutter_plugin_android_lifecycle:
- dependency: transitive
- description:
- name: flutter_plugin_android_lifecycle
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.5"
- flutter_svg:
- dependency: "direct main"
- description:
- name: flutter_svg
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.0"
- flutter_test:
- dependency: "direct dev"
- description: flutter
- source: sdk
- version: "0.0.0"
- flutter_web_plugins:
- dependency: transitive
- description: flutter
- source: sdk
- version: "0.0.0"
- fluttertoast:
- dependency: "direct main"
- description:
- name: fluttertoast
- url: "https://pub.dartlang.org"
- source: hosted
- version: "8.0.8"
- http:
- dependency: "direct main"
- description:
- name: http
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.13.4"
- http_parser:
- dependency: transitive
- description:
- name: http_parser
- url: "https://pub.dartlang.org"
- source: hosted
- version: "4.0.0"
- injector:
- dependency: "direct main"
- description:
- name: injector
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.0"
- intl:
- dependency: transitive
- description:
- name: intl
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.17.0"
- js:
- dependency: transitive
- description:
- name: js
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.6.3"
- lints:
- dependency: transitive
- description:
- name: lints
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.1"
- local_auth:
- dependency: "direct main"
- description:
- name: local_auth
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.1.9"
- logger:
- dependency: "direct main"
- description:
- name: logger
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.1.0"
- matcher:
- dependency: transitive
- description:
- name: matcher
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.12.11"
- meta:
- dependency: transitive
- description:
- name: meta
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.7.0"
- nested:
- dependency: transitive
- description:
- name: nested
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.0"
- path:
- dependency: transitive
- description:
- name: path
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.8.0"
- path_drawing:
- dependency: transitive
- description:
- name: path_drawing
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.0"
- path_parsing:
- dependency: transitive
- description:
- name: path_parsing
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.0"
- path_provider:
- dependency: "direct main"
- description:
- name: path_provider
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.8"
- path_provider_android:
- dependency: transitive
- description:
- name: path_provider_android
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.9"
- path_provider_ios:
- dependency: transitive
- description:
- name: path_provider_ios
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.7"
- path_provider_linux:
- dependency: transitive
- description:
- name: path_provider_linux
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.1.4"
- path_provider_macos:
- dependency: transitive
- description:
- name: path_provider_macos
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.4"
- path_provider_platform_interface:
- dependency: transitive
- description:
- name: path_provider_platform_interface
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.1"
- path_provider_windows:
- dependency: transitive
- description:
- name: path_provider_windows
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.4"
- permission_handler:
- dependency: "direct main"
- description:
- name: permission_handler
- url: "https://pub.dartlang.org"
- source: hosted
- version: "8.3.0"
- permission_handler_platform_interface:
- dependency: transitive
- description:
- name: permission_handler_platform_interface
- url: "https://pub.dartlang.org"
- source: hosted
- version: "3.7.0"
- petitparser:
- dependency: transitive
- description:
- name: petitparser
- url: "https://pub.dartlang.org"
- source: hosted
- version: "4.4.0"
- platform:
- dependency: transitive
- description:
- name: platform
- url: "https://pub.dartlang.org"
- source: hosted
- version: "3.1.0"
- plugin_platform_interface:
- dependency: transitive
- description:
- name: plugin_platform_interface
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.2"
- process:
- dependency: transitive
- description:
- name: process
- url: "https://pub.dartlang.org"
- source: hosted
- version: "4.2.4"
- provider:
- dependency: "direct main"
- description:
- name: provider
- url: "https://pub.dartlang.org"
- source: hosted
- version: "6.0.1"
- shared_preferences:
- dependency: transitive
- description:
- name: shared_preferences
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.11"
- shared_preferences_android:
- dependency: transitive
- description:
- name: shared_preferences_android
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.9"
- shared_preferences_ios:
- dependency: transitive
- description:
- name: shared_preferences_ios
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.8"
- shared_preferences_linux:
- dependency: transitive
- description:
- name: shared_preferences_linux
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.3"
- shared_preferences_macos:
- dependency: transitive
- description:
- name: shared_preferences_macos
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.2"
- shared_preferences_platform_interface:
- dependency: transitive
- description:
- name: shared_preferences_platform_interface
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.0"
- shared_preferences_web:
- dependency: transitive
- description:
- name: shared_preferences_web
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.2"
- shared_preferences_windows:
- dependency: transitive
- description:
- name: shared_preferences_windows
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.3"
- shimmer:
- dependency: "direct main"
- description:
- name: shimmer
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.0"
- sizer:
- dependency: "direct main"
- description:
- name: sizer
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.15"
- sky_engine:
- dependency: transitive
- description: flutter
- source: sdk
- version: "0.0.99"
- source_span:
- dependency: transitive
- description:
- name: source_span
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.8.1"
- stack_trace:
- dependency: transitive
- description:
- name: stack_trace
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.10.0"
- stream_channel:
- dependency: transitive
- description:
- name: stream_channel
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.1.0"
- string_scanner:
- dependency: transitive
- description:
- name: string_scanner
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.1.0"
- term_glyph:
- dependency: transitive
- description:
- name: term_glyph
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.2.0"
- test_api:
- dependency: transitive
- description:
- name: test_api
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.4.3"
- typed_data:
- dependency: transitive
- description:
- name: typed_data
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.3.0"
- universal_io:
- dependency: transitive
- description:
- name: universal_io
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.4"
- vector_math:
- dependency: transitive
- description:
- name: vector_math
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.1.1"
- win32:
- dependency: transitive
- description:
- name: win32
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.3.1"
- xdg_directories:
- dependency: transitive
- description:
- name: xdg_directories
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.2.0"
- xml:
- dependency: transitive
- description:
- name: xml
- url: "https://pub.dartlang.org"
- source: hosted
- version: "5.3.1"
-sdks:
- dart: ">=2.14.0 <3.0.0"
- flutter: ">=2.5.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index ca8fe9c..d38cc5a 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
- sdk: ">=2.12.0 <3.0.0"
+ sdk: ">=2.16.0 <3.0.0"
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
@@ -39,16 +39,26 @@ dependencies:
provider: ^6.0.1
easy_localization: ^3.0.0
http: ^0.13.4
- permission_handler: ^8.3.0
+ permission_handler: ^9.2.0
flutter_svg: ^1.0.0
sizer: ^2.0.15
local_auth: ^1.1.9
fluttertoast: ^8.0.8
shared_preferences: ^2.0.12
- firebase_messaging: ^11.2.6
+ firebase_messaging: ^11.2.8
shimmer: ^2.0.0
logger: ^1.1.0
flutter_countdown_timer: ^4.1.0
+ nfc_manager: ^3.1.1
+ uuid: ^3.0.6
+
+ # maps
+ google_maps_flutter: ^2.0.2
+ google_maps_utils: ^1.4.0+1
+ google_directions_api: ^0.9.0
+ geolocator: any
+ # flutter_compass: ^0.6.1
+ google_maps_flutter_web: ^0.3.2
dev_dependencies:
@@ -84,6 +94,8 @@ flutter:
- assets/images/
- assets/images/login/
- assets/images/logos/
+ - assets/icons/nfc/ic_nfc.png
+ - assets/icons/nfc/ic_done.png
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.