import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:geolocator/geolocator.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:employee_selfservice_mobile/Screens/Menu/Absensi/RequestHttp/checkIn_post.dart'; import 'package:employee_selfservice_mobile/Screens/Menu/Absensi/RequestHttp/checkStatus_post.dart'; import 'package:employee_selfservice_mobile/Screens/Menu/Absensi/absensi_history_screen.dart'; import 'package:intl/intl.dart'; import 'package:latlong2/latlong.dart' as latlong; import 'package:location/location.dart' as loc; import 'dart:developer' as logDev; import 'package:progress_dialog_null_safe/progress_dialog_null_safe.dart'; import 'package:sliding_up_panel/sliding_up_panel.dart'; import 'RequestHttp/checkOut_post.dart'; import 'RequestHttp/historyAbsensi_post.dart'; class AbsensiScreen extends StatefulWidget { const AbsensiScreen({Key? key}) : super(key: key); @override State createState() => _AbsensiScreenState(); } class _AbsensiScreenState extends State { //Visibility Button Check In & Check Out bool visibleCheckIn = false; bool visibleCheckOut = false; latlong.LatLng point = latlong.LatLng(-6.183580253674716, 106.93103973792664); late Position position; late String showCheckIn_List; late String showCheckOut_List; MapController _mapController = MapController(); @override void initState() { showCheckIn_List = ""; showCheckOut_List = ""; WidgetsBinding.instance.addPostFrameCallback((_) { determinePosition(); }); super.initState(); } determinePosition() async { StreamSubscription serviceStatusStream = Geolocator.getServiceStatusStream().listen( (ServiceStatus status) { print(status); }); ProgressDialog loading = ProgressDialog(context); loading = ProgressDialog(context, type: ProgressDialogType.normal, isDismissible: false, showLogs: true); loading.style( message: 'Please Wait .....', borderRadius: 3, backgroundColor: Colors.white, progressWidget: CircularProgressIndicator(), elevation: 10.0, padding: EdgeInsets.all(10), insetAnimCurve: Curves.easeInOut, progress: 0.0, maxProgress: 100.0, progressTextStyle: TextStyle( color: Colors.black, fontSize: 10.0, fontWeight: FontWeight.w400), messageTextStyle: TextStyle( color: Colors.black, fontSize: 15.0, fontWeight: FontWeight.w600)); await loading.show(); bool serviceEnabled = await Geolocator.isLocationServiceEnabled(); logDev.log(serviceEnabled.toString(), name: "ON/OFF LOCATION SERVICE"); if (!serviceEnabled) { //return Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => AbsensiScreen())); //await loading.hide(); //alertDialogEnableLocaionServices(context); return Future.error('Location services are disabled.'); } LocationPermission permission = await Geolocator.checkPermission(); if (permission == LocationPermission.deniedForever) { await loading.hide(); //return Future.error('Location permissions are permanently denied, we cannot request permissions.'); return alertDialogPermissionDeniedForever(context); } else if (permission == LocationPermission.denied) { permission = await Geolocator.requestPermission(); if (permission != LocationPermission.whileInUse && permission != LocationPermission.always) { await loading.hide(); //return Future.error('Location permissions are denied (actual value: $permission).'); return alertDialogPermissionDenied(context); } } position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high); logDev.log(position.toString(), name: "Position GEOLOCATOR"); if (position.isMocked) { await loading.hide(); setState(() { alertDialogFakeGPSDetected(context); }); } else { point = latlong.LatLng(position.latitude, position.longitude); logDev.log(point.toString(), name: "POINT GEOLOCATOR"); _mapController.move(point, 18); //Check Status CheckStatus_Post.connectToAPI().then((valueResult) async { Map object = json.decode(valueResult); if (object.containsKey("result").toString() == "true") { String result = object['result'].toString(); logDev.log(result, name: "Status Absensi Result"); if (result.contains("not_checked_in")) { setState(() { visibleCheckIn = !visibleCheckIn; visibleCheckOut = visibleCheckOut; }); await loading.hide(); } else if (result.contains("checked_in")) { setState(() { visibleCheckIn = visibleCheckIn; visibleCheckOut = !visibleCheckOut; }); await loading.hide(); } else { setState(() { alertDialogFailedResponse(context); }); await loading.hide(); } } else { setState(() { alertDialogFailedResponse(context); }); await loading.hide(); } await loading.hide(); }); //History HistoryAbsensi_Post.connectToAPI().then((valueResult) async { Map object = jsonDecode(valueResult); if (object.containsKey("result").toString() == "true") { String result = object['result'].toString(); if (result.contains("failed")) { await loading.hide(); alertDialogFailedRetrievedData(context); } else { List historyAbsensi = object['result']; await loading.hide(); setState(() { String check_in = historyAbsensi[0]['check_in'].toString(); String check_out = historyAbsensi[0]['check_out'].toString(); logDev.log(historyAbsensi[0]['check_in'].toString(), name: "CHECK IN TIME"); if (check_in != "false") { //Convert UTC to Local Time - Check In Time DateTime checkInTime = DateFormat("yyyy-MM-dd HH:mm:ss").parse( check_in, true); String checkInTimeLocal = checkInTime.toLocal().toString(); String showCheckInTime = checkInTimeLocal.substring(11, 19); //logDev.log(showCheckInTime.substring(0,5), name: "SHOW CHECK IN TIME"); showCheckIn_List = showCheckInTime.substring(0, 5); } else if (check_in == "false") { String show_check_in = "-"; showCheckIn_List = show_check_in; } if (check_out != "false") { //Convert UTC to Local Time - Check Out Time DateTime checkOutTime = DateFormat("yyyy-MM-dd HH:mm:ss").parse( check_out, true); String checkOutTimeLocal = checkOutTime.toLocal().toString(); String showCheckOutTime = checkOutTimeLocal.substring(11, 19); //logDev.log(showCheckOutTime, name: "SHOW CHECK OUT TIME"); showCheckOut_List = showCheckOutTime.substring(0, 5); } else if (check_out == "false") { String show_check_out = "-"; showCheckOut_List = show_check_out; } }); } } else { alertDialogFailedRetrievedData(context); } }); } } updatePosition() async { ProgressDialog loading = ProgressDialog(context); loading = ProgressDialog(context, type: ProgressDialogType.normal, isDismissible: false, showLogs: true); loading.style( message: 'Please Wait .....', borderRadius: 3, backgroundColor: Colors.white, progressWidget: CircularProgressIndicator(), elevation: 10.0, padding: EdgeInsets.all(10), insetAnimCurve: Curves.easeInOut, progress: 0.0, maxProgress: 100.0, progressTextStyle: TextStyle( color: Colors.black, fontSize: 10.0, fontWeight: FontWeight.w400), messageTextStyle: TextStyle( color: Colors.black, fontSize: 15.0, fontWeight: FontWeight.w600)); bool serviceEnabled; LocationPermission permission; serviceEnabled = await Geolocator.isLocationServiceEnabled(); if (!serviceEnabled) { await loading.hide(); return Future.error('Location services are disabled.'); } permission = await Geolocator.checkPermission(); if (permission == LocationPermission.deniedForever) { await loading.hide(); return alertDialogPermissionDeniedForever(context); } else if (permission == LocationPermission.denied) { permission = await Geolocator.requestPermission(); if (permission != LocationPermission.whileInUse && permission != LocationPermission.always) { await loading.hide(); return alertDialogPermissionDenied(context); } } position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high); if (position.isMocked) { await loading.hide(); setState(() { alertDialogFakeGPSDetected(context); }); } else { await loading.hide(); setState((){ point = latlong.LatLng(position.latitude, position.longitude); logDev.log(point.toString(), name: "UPDATE POINT GEOLOCATOR"); _mapController.move(point, 18); }); } } goCheckIn() async { ProgressDialog loading = ProgressDialog(context); loading = ProgressDialog(context, type: ProgressDialogType.normal, isDismissible: false, showLogs: true); loading.style( message: 'Please Wait .....', borderRadius: 3, backgroundColor: Colors.white, progressWidget: CircularProgressIndicator(), elevation: 10.0, padding: EdgeInsets.all(10), insetAnimCurve: Curves.easeInOut, progress: 0.0, maxProgress: 100.0, progressTextStyle: TextStyle( color: Colors.black, fontSize: 10.0, fontWeight: FontWeight.w400), messageTextStyle: TextStyle( color: Colors.black, fontSize: 15.0, fontWeight: FontWeight.w600)); await loading.show(); position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high); if (position.isMocked) { await loading.hide(); setState(() { alertDialogFakeGPSDetected(context); }); } else { await loading.hide(); setState((){ point = latlong.LatLng(position.latitude, position.longitude); _mapController.move(point, 18); }); } String coordinate = point.latitude.toString()+", "+ point.longitude.toString(); CheckIn_Post.connectToAPI(coordinate).then((valueResult) async { Map object = json.decode(valueResult); if (object.containsKey("result").toString() == "true") { String result = object['result'].toString(); logDev.log(result, name: "Check In Result"); if (result.contains("failed")) { await loading.hide(); setState(() { alertDialogFailedRetrievedData(context); }); } else if (result.contains("Anda sudah check in")) { await loading.hide(); setState(() { alertDialogFailedCheckIn(context); }); } else { await loading.hide(); setState(() { alertDialogSuccessCheckIn(context); }); } } else { setState(() { alertDialogFailedResponse(context); }); await loading.hide(); } }); } goCheckOut() async { ProgressDialog loading = ProgressDialog(context); loading = ProgressDialog(context, type: ProgressDialogType.normal, isDismissible: false, showLogs: true); loading.style( message: 'Please Wait .....', borderRadius: 3, backgroundColor: Colors.white, progressWidget: CircularProgressIndicator(), elevation: 10.0, padding: EdgeInsets.all(10), insetAnimCurve: Curves.easeInOut, progress: 0.0, maxProgress: 100.0, progressTextStyle: TextStyle( color: Colors.black, fontSize: 10.0, fontWeight: FontWeight.w400), messageTextStyle: TextStyle( color: Colors.black, fontSize: 15.0, fontWeight: FontWeight.w600)); await loading.show(); position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high); if (position.isMocked) { await loading.hide(); setState(() { alertDialogFakeGPSDetected(context); }); } else { await loading.hide(); setState((){ point = latlong.LatLng(position.latitude, position.longitude); _mapController.move(point, 18); }); } String coordinate = point.latitude.toString()+", "+ point.longitude.toString(); CheckOut_Post.connectToAPI(coordinate).then((valueResult) async { Map object = json.decode(valueResult); if (object.containsKey("result").toString() == "true") { String result = object['result'].toString(); logDev.log(result, name: "Check Out Result"); if (result.contains("failed")) { await loading.hide(); setState(() { alertDialogFailedRetrievedData(context); }); } else if (result.contains("Anda belum check in")) { await loading.hide(); setState(() { alertDialogFailedCheckOut(context); }); } else { await loading.hide(); setState(() { alertDialogSuccessCheckOut(context); }); } } else { setState(() { alertDialogFailedResponse(context); }); await loading.hide(); } }); } PanelController _panelController = PanelController(); void togglePanel() => _panelController.isPanelOpen ? _panelController.close() : _panelController.open(); @override Widget build(BuildContext context) { var size = MediaQuery.of(context).size; return Scaffold( body: SlidingUpPanel( controller: _panelController, parallaxEnabled: true, maxHeight: size.height * 0.5, minHeight: size.height * 0.3, body: Container ( child: Stack( children: [ FlutterMap( mapController: _mapController, options: new MapOptions( onTap: (p, point) async {}, center: point, zoom: 15), children: [ TileLayer( minZoom: 1, maxZoom: 22, maxNativeZoom: 18, minNativeZoom: 1, backgroundColor: Colors.black54, urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', subdomains: ['a', 'b', 'c'], ), /*MarkerLayer(markers: [ Marker(child: Container( child: Icon( Icons.location_on ), ), width: 135, height: 135, point: point, child: Container( child: Icon( Icons.location_on, color: Colors.red, ), )) ])*/ MarkerLayer( markers: [ Marker( width: 135, height: 135, point: point, // Ganti latitude dan longitude dengan nilai yang sesuai child: Container( child: Icon( Icons.location_on, color: Colors.red, ), ), ), ], ) ], ), Container( alignment: AlignmentDirectional.bottomEnd, child: Container( margin: EdgeInsets.fromLTRB(10, 15, 0, (size.height*0.3) + 15), child: RawMaterialButton( onPressed: () { setState(() { updatePosition(); }); }, elevation: 5.0, fillColor: Colors.white, child: Image.asset('assets/images/location1.png', height: 40, width: 40), padding: EdgeInsets.all(5.0), shape: CircleBorder(), ), ), ), ], ), ), panel: Center( child: Column( children: [ GestureDetector( onTap: togglePanel, child: Center( child: Container( margin: EdgeInsets.only(top: 15), height: 5, width: size.width * 0.1, decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), color: Colors.grey ), ), ), ), Container( margin: EdgeInsets.only(top: 15), child: Center( child: Text( 'ATTENDANCE', maxLines: 1, style: GoogleFonts.luckiestGuy( fontSize: 28, color: Color(0xFF4858A7), fontStyle: FontStyle.italic, ), ), ), ), Container( width: double.infinity, margin: EdgeInsets.fromLTRB(10, 15, 10, 10), decoration: BoxDecoration(border: Border.all(color: Colors.black), borderRadius: BorderRadius.all(Radius.circular(15))), child: Column( children: [ Container( child: Text( "Last Attendance", style: GoogleFonts.patrickHand( fontSize: 21, color: Colors.white), ), width: double.infinity, alignment: Alignment.center, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topRight, end: Alignment.bottomRight, colors: [ /*Color(0xFFD21404), Color(0xFFFD7267),*/ Color(0xFF4858A7), Color(0xFF6474C6), ]), border: Border.all(color: Colors.black), borderRadius: BorderRadius.only(topLeft: Radius.circular(15), topRight: Radius.circular(15))), ), Container( width: double.infinity, padding: EdgeInsets.all(15), decoration: BoxDecoration(border: Border.all(color: Colors.black), borderRadius: BorderRadius.only(bottomLeft: Radius.circular(15), bottomRight: Radius.circular(15))), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Expanded( flex: 5, child: Column( children: [ Text('Check In', style: GoogleFonts.fredoka( fontSize: 19)), Text(showCheckIn_List, style: GoogleFonts.barlowSemiCondensed( fontSize: 19)), ], )), Expanded( flex: 5, child: Column( children: [ Text('Check Out', style: GoogleFonts.fredoka( fontSize: 19)), Text(showCheckOut_List, style: GoogleFonts.barlowSemiCondensed( fontSize: 19)), ], )), ], ), Row( children: [ Visibility( visible: visibleCheckIn, child: Container( margin: EdgeInsets.fromLTRB(0, 10, 0, 0), width: size.width - 54, child: ElevatedButton( onPressed: () { goCheckIn(); }, child: Text('Check In'), style: ButtonStyle( backgroundColor: MaterialStateProperty.all( Color(0xFF6474C6))), ), ), ), Visibility( visible: visibleCheckOut, child: Container( margin: EdgeInsets.fromLTRB(0, 10, 0, 0), width: size.width - 54, child: ElevatedButton( onPressed: () { goCheckOut(); }, child: Text('Check Out'), style: ButtonStyle( backgroundColor: MaterialStateProperty.all( Color(0xFF6474C6))), ), ), ), ], ) ], ), ) ], ), ), Container( margin: EdgeInsets.fromLTRB(10, 15, 10, 15), child: InkWell( child: Container( padding: EdgeInsets.fromLTRB(10, 10, 10, 10), width: double.infinity, decoration: BoxDecoration( borderRadius: BorderRadius.circular(5), gradient: LinearGradient(colors: [ Color(0xFF2D4059), Color(0xFF2D4059), /*Color(0xFFEAFFD0), Color(0xFF95E1D3),*/ ])), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(' See Attendance History \t\t', textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 17, fontWeight: FontWeight.w500)), Image.asset( 'assets/images/ic_arrow_white.png', width: 30, height: 30, ) ], )), onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => HistoryAbsensi())); }, ), ) ], ), ), borderRadius: BorderRadius.only(topLeft: Radius.circular(15), topRight: Radius.circular(15)), ), ); } } alertDialogFailedRetrievedData(BuildContext context) { Widget okButton = TextButton( child: Text("Refresh"), onPressed: () { Navigator.of(context, rootNavigator: true).pop(); Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => AbsensiScreen())); }, ); Widget noButton = TextButton( child: Text("Back"), onPressed: () { Navigator.of(context, rootNavigator: true).pop(); Navigator.pop(context); }, ); // set up the AlertDialog AlertDialog alert = AlertDialog( title: Text("Employee Self Service"), content: Text("Failed to Retrieve Data"), actions: [ noButton, okButton, ], ); // show the dialog showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return alert; }, ); } alertDialogFailedResponse(BuildContext context) { Widget okButton = TextButton( child: Text("Refresh"), onPressed: () { Navigator.of(context, rootNavigator: true).pop(); Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => AbsensiScreen())); }, ); Widget noButton = TextButton( child: Text("Back"), onPressed: () { Navigator.of(context, rootNavigator: true).pop(); Navigator.pop(context); }, ); // set up the AlertDialog AlertDialog alert = AlertDialog( title: Text("Employee Self Service"), content: Text("Server Response Error"), actions: [ noButton, okButton, ], ); // show the dialog showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return alert; }, ); } alertDialogSuccessCheckIn(BuildContext context) { Widget okButton = TextButton( child: Text("Ok"), onPressed: () { Navigator.of(context, rootNavigator: true).pop(); Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => AbsensiScreen())); }, ); // set up the AlertDialog AlertDialog alert = AlertDialog( title: Text("Employee Self Service"), content: Text("Successfully Checked In"), actions: [ okButton, ], ); // show the dialog showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return alert; }, ); } alertDialogSuccessCheckOut(BuildContext context) { Widget okButton = TextButton( child: Text("Ok"), onPressed: () { Navigator.of(context, rootNavigator: true).pop(); Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => AbsensiScreen())); }, ); // set up the AlertDialog AlertDialog alert = AlertDialog( title: Text("Employee Self Service"), content: Text("Successfully Checked Out"), actions: [ okButton, ], ); // show the dialog showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return alert; }, ); } alertDialogFailedCheckIn(BuildContext context) { Widget okButton = TextButton( child: Text("Ok"), onPressed: () { Navigator.of(context, rootNavigator: true).pop(); Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => AbsensiScreen())); }, ); // set up the AlertDialog AlertDialog alert = AlertDialog( title: Text("Employee Self Service"), content: Text("You've already checked in"), actions: [ okButton, ], ); // show the dialog showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return alert; }, ); } alertDialogFailedCheckOut(BuildContext context) { Widget okButton = TextButton( child: Text("Ok"), onPressed: () { Navigator.of(context, rootNavigator: true).pop(); Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => AbsensiScreen())); }, ); // set up the AlertDialog AlertDialog alert = AlertDialog( title: Text("Employee Self Service"), content: Text("You haven't checked in"), actions: [ okButton, ], ); // show the dialog showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return alert; }, ); } alertDialogFakeGPSDetected(BuildContext context) { Widget okButton = TextButton( child: Text("Refresh"), onPressed: () { Navigator.of(context, rootNavigator: true).pop(); Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => AbsensiScreen())); }, ); // set up the AlertDialog AlertDialog alert = AlertDialog( title: Text("Employee Self Service"), content: Text("Fake GPS Detected, Please Use Default GPS!"), actions: [ okButton, ], ); // show the dialog showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return alert; }, ); } alertDialogPermissionDenied(BuildContext context) { Widget okButton = TextButton( child: Text("Refresh"), onPressed: () { Navigator.of(context, rootNavigator: true).pop(); Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => AbsensiScreen())); }, ); Widget noButton = TextButton( child: Text("Back"), onPressed: () { Navigator.of(context, rootNavigator: true).pop(); Navigator.pop(context); }, ); // set up the AlertDialog AlertDialog alert = AlertDialog( title: Text("Employee Self Service"), content: Text("Location permissions are denied, we cannot request permissions"), actions: [ noButton, okButton, ], ); // show the dialog showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return alert; }, ); } alertDialogPermissionDeniedForever(BuildContext context) { Widget noButton = TextButton( child: Text("Back"), onPressed: () { Navigator.of(context, rootNavigator: true).pop(); Navigator.pop(context); }, ); // set up the AlertDialog AlertDialog alert = AlertDialog( title: Text("Employee Self Service"), content: Text( "Location permissions are permanently denied, we cannot request permissions. Please configure it in your device settings."), actions: [noButton], ); // show the dialog showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return alert; }, ); } alertDialogEnableLocaionServices(BuildContext context) { ProgressDialog loading = ProgressDialog(context); loading = ProgressDialog(context, type: ProgressDialogType.normal, isDismissible: false, showLogs: true); loading.style( message: 'Please Wait .....', borderRadius: 3, backgroundColor: Colors.white, progressWidget: CircularProgressIndicator(), elevation: 10.0, padding: EdgeInsets.all(10), insetAnimCurve: Curves.easeInOut, progress: 0.0, maxProgress: 100.0, progressTextStyle: TextStyle( color: Colors.black, fontSize: 10.0, fontWeight: FontWeight.w400), messageTextStyle: TextStyle( color: Colors.black, fontSize: 15.0, fontWeight: FontWeight.w600)); Widget okButton = TextButton( child: Text("Open Settings"), onPressed: () { //AppSettings.openLocationSettings(); Navigator.of(context, rootNavigator: true).pop(); loading.hide(); /* Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => AbsensiScreen()));*/ }, ); Widget noButton = TextButton( child: Text("No, thanks"), onPressed: () { Navigator.of(context, rootNavigator: true).pop(); Navigator.pop(context); loading.hide(); }, ); // set up the AlertDialog AlertDialog alert = AlertDialog( title: Text("Employee Self Service"), content: Text("For a better experience, please turn on your device location"), actions: [ noButton, okButton, ], ); // show the dialog showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return alert; }, ); }