import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter_map/plugin_api.dart'; import 'package:geolocator/geolocator.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:hris_selfservice_mobile/Screens/Menu/Absensi/RequestHttp/checkIn_post.dart'; import 'package:hris_selfservice_mobile/Screens/Menu/Absensi/RequestHttp/checkStatus_post.dart'; import 'package:hris_selfservice_mobile/Screens/Menu/Absensi/absensi_history_screen.dart'; import 'package:intl/intl.dart'; import 'package:latlong2/latlong.dart' as latlong; import 'dart:developer' as logDev; import 'package:progress_dialog_null_safe/progress_dialog_null_safe.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 { 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; loading.show(); serviceEnabled = await Geolocator.isLocationServiceEnabled(); if (!serviceEnabled) { loading.hide(); return Future.error('Location services are disabled.'); } permission = await Geolocator.checkPermission(); if (permission == LocationPermission.deniedForever) { 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) { 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) { 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; }); loading.hide(); } else if (result.contains("checked_in")) { setState(() { visibleCheckIn = visibleCheckIn; visibleCheckOut = !visibleCheckOut; }); loading.hide(); } else { setState(() { alertDialogFailedResponse(context); }); loading.hide(); } } else { setState(() { alertDialogFailedResponse(context); }); 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")) { loading.hide(); alertDialogFailedRetrievedData(context); } else { List historyAbsensi = object['result']; 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); } }); //loading.hide(); } } 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; loading.show(); serviceEnabled = await Geolocator.isLocationServiceEnabled(); if (!serviceEnabled) { loading.hide(); return Future.error('Location services are disabled.'); } permission = await Geolocator.checkPermission(); if (permission == LocationPermission.deniedForever) { loading.hide(); return alertDialogPermissionDeniedForever(context); } else if (permission == LocationPermission.denied) { permission = await Geolocator.requestPermission(); if (permission != LocationPermission.whileInUse && permission != LocationPermission.always) { loading.hide(); return alertDialogPermissionDenied(context); } } position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high); if (position.isMocked) { loading.hide(); setState(() { alertDialogFakeGPSDetected(context); }); } else { 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)); loading.show(); position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high); if (position.isMocked) { loading.hide(); setState(() { alertDialogFakeGPSDetected(context); }); } else { 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")) { loading.hide(); setState(() { alertDialogFailedRetrievedData(context); }); } else if (result.contains("Anda sudah check in")) { loading.hide(); setState(() { alertDialogFailedCheckIn(context); }); } else { loading.hide(); setState(() { alertDialogSuccessCheckIn(context); }); } } else { setState(() { alertDialogFailedResponse(context); }); 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)); loading.show(); position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high); if (position.isMocked) { loading.hide(); setState(() { alertDialogFakeGPSDetected(context); }); } else { 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")) { loading.hide(); setState(() { alertDialogFailedRetrievedData(context); }); } else if (result.contains("Anda belum check in")) { loading.hide(); setState(() { alertDialogFailedCheckOut(context); }); } else { loading.hide(); setState(() { alertDialogSuccessCheckOut(context); }); } } else { setState(() { alertDialogFailedResponse(context); }); loading.hide(); } }); } @override Widget build(BuildContext context) { var size = MediaQuery.of(context).size; return Scaffold( body: SingleChildScrollView( child: Column( children: [ Container( height: size.height * 0.6, 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( width: 135, height: 135, point: point, builder: (ctx) => Container( child: Icon( Icons.location_on, color: Colors.red, ), )) ]) ], ), Align( alignment: AlignmentDirectional.bottomEnd, child: Container( margin: EdgeInsets.fromLTRB(10, 15, 0, 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(), ), ), ) ], ), ), Container( width: double.infinity, margin: EdgeInsets.fromLTRB(10, 15, 10, 10), decoration: BoxDecoration(border: Border.all(color: Colors.black)), 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)), ), Container( width: double.infinity, padding: EdgeInsets.all(15), decoration: BoxDecoration(border: Border.all(color: Colors.black)), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Expanded( flex: 5, child: Column( children: [ Text('Check In', style: GoogleFonts.fredokaOne( fontSize: 19)), Text(showCheckIn_List, style: GoogleFonts.barlowSemiCondensed( fontSize: 19)), ], )), Expanded( flex: 5, child: Column( children: [ Text('Check Out', style: GoogleFonts.fredokaOne( 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( width: double.infinity, margin: EdgeInsets.fromLTRB(10, 10, 10, 0), padding: EdgeInsets.all(15), decoration: BoxDecoration(border: Border.all(color: Colors.black)), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('Rabu, 23 November 2022', maxLines: 1), Column( children: [Text('Check In'), Text('07.00')], ), Column( children: [ Text('Check Out'), Text('16.30'), ], ), ], ), Text('Location : Global Service Indonesia', maxLines: 1), ], )), Container( width: double.infinity, margin: EdgeInsets.fromLTRB(10, 10, 10, 0), padding: EdgeInsets.all(15), decoration: BoxDecoration(border: Border.all(color: Colors.black)), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('Rabu, 23 November 2022', maxLines: 1), Column( children: [Text('Check In'), Text('07.00')], ), Column( children: [ Text('Check Out'), Text('16.30'), ], ), ], ), Text('Location : Global Service Indonesia', maxLines: 1), ], )), Container( width: double.infinity, margin: EdgeInsets.fromLTRB(10, 10, 10, 0), padding: EdgeInsets.all(15), decoration: BoxDecoration(border: Border.all(color: Colors.black)), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('Rabu, 23 November 2022', maxLines: 1), Column( children: [Text('Check In'), Text('07.00')], ), Column( children: [ Text('Check Out'), Text('16.30'), ], ), ], ), Text('Location : Global Service Indonesia', maxLines: 1), ], )), Container( width: double.infinity, margin: EdgeInsets.fromLTRB(10, 10, 10, 0), padding: EdgeInsets.all(15), decoration: BoxDecoration(border: Border.all(color: Colors.black)), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('Rabu, 23 November 2022', maxLines: 1), Column( children: [Text('Check In'), Text('07.00')], ), Column( children: [ Text('Check Out'), Text('16.30'), ], ), ], ), Text('Location : Global Service Indonesia', maxLines: 1), ], )),*/ 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())); }, ), ), ], ), ), ); } } 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; }, ); }