import 'dart:async'; import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:in_app_update/in_app_update.dart'; import 'package:package_info/package_info.dart'; import 'package:path/path.dart' as paths; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:path_provider/path_provider.dart'; // import 'Util/download_Upload_Handler.dart'; import 'package:intl/intl.dart'; import 'package:unitstocks/Blocs/Cabang/cabang_bloc.dart'; import 'package:unitstocks/Blocs/Logout/logout_bloc.dart'; import 'package:unitstocks/Blocs/Stock_Taking/Restore/restore_bloc.dart'; import '../main.dart'; import '../Utils/keys.dart'; // import 'Util/UnitModel.dart'; import 'package:permission_handler/permission_handler.dart' as pHandler; import '../Blocs/Stock_Taking/State/load_state_bloc.dart'; import '../Blocs/Stock_Taking/Unit/get_unit_bloc.dart'; import '../Blocs/Stock_Taking/Clear/clear_data_bloc.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import '../Blocs/Stock_Taking/Backup/backup_bloc.dart'; import '../Blocs/Stock_Taking/Send/upload_bloc.dart'; import '../Blocs/Stock_Taking/Process/process_units_bloc.dart'; import '../Blocs/Stock_Taking/Submit/submit_unit_bloc.dart'; class HomePage extends StatefulWidget { const HomePage({Key? key}) : super(key: key); @override _HomePageState createState() => _HomePageState(); } class _HomePageState extends State with RouteAware { StreamSubscription? progressDLStream, progressULStream; String lastDownload = ''; String lastUpload = ''; double? progressDL, progressUL; String timeString = ''; bool isLoading = false; String? state = ''; late LoadStateBloc _stateBloc; late GetUnitBloc _getDataBloc; late BackupBloc _backupBloc; late RestoreBloc _restoreBloc; late UploadBloc _uploadBloc; late ProcessUnitsBloc _processBloc; late SubmitUnitBloc _submitBloc; final hostAddress = new TextEditingController(); final _refreshController = new RefreshController(initialRefresh: false); String currentVersion = ''; clearData(contextParent)async{ ClearDataBloc _clearBloc = ClearDataBloc(); setState(() { progressDL = null; isLoading = false; }); bool? result; await showDialog( context: contextParent,builder: (context)=>WillPopScope( onWillPop: ()async{ Navigator.pop(context,false); return false; }, child: BlocProvider( create: (context) => _clearBloc, child: BlocListener( listener: (context, state) { setState(() { isLoading =(state is ClearDataLoading); }); if(state is ClearDataFinish){ result = state.cleared; if(result??false) { Navigator.pop(context); setState(() { lastDownload = ""; }); } util.showFlushbar(contextParent, state.msg,color: (result??false)?Colors.grey:Colors.red); } }, child: AlertDialog( title: const Text('Clear Data ?'), content: const Text('Proceed to clear any remaining units data on this device?'), actions: [ TextButton( child: const Text('Proceed'), onPressed: ()async{ _clearBloc.add(ClearDataInit()); }, ), TextButton( child: const Text('Cancel'), onPressed: (){Navigator.pop(context);}, ) ], ), ), ), )); return result??false; } @override void initState() { // TODO: implement initState super.initState(); _stateBloc = LoadStateBloc(); _getDataBloc = GetUnitBloc(); _backupBloc = BackupBloc(); _restoreBloc = RestoreBloc(); _processBloc = ProcessUnitsBloc(); _submitBloc = SubmitUnitBloc(); _uploadBloc = UploadBloc(); lastDownload = prefs.getString(Keys.lastDownload) ?? ''; lastUpload = prefs.getString(Keys.lastUpload) ?? ''; WidgetsBinding.instance!.addPostFrameCallback((_) async { await _check_Update(); await util.permissionCheck(context,pHandler.Permission.storage,()async{print("storage permit granted!");},customMessage: " untuk menyimpan data backup"); if(prefs.getString(Keys.stockId)!= null){ _stateBloc.add(const LoadState()); } }); } _check_Update() async { if (defaultTargetPlatform == TargetPlatform.android) { try { final PackageInfo info = await PackageInfo.fromPlatform(); AppUpdateInfo _updateInfo = await InAppUpdate.checkForUpdate(); currentVersion = info.version.trim(); String latestversion = '0.0.0'; var result = await util.getMinAppVer(); if (result['STATUS'] == 1) { latestversion = result['DATA']; } var current = currentVersion.split('.'); var latest = latestversion.split('.'); if (int.parse(current[0]) == int.parse(latest[0])) { if (int.parse(current[1]) == int.parse(latest[1])) { if (int.parse(current[2]) < int.parse(latest[2])) { await util.updateDialog(context); } else { if (_updateInfo.updateAvailability == 2) { await InAppUpdate.startFlexibleUpdate(); await InAppUpdate.completeFlexibleUpdate(); } } } else if (int.parse(current[1]) < int.parse(latest[1])) { await util.updateDialog(context); // await InAppUpdate.performImmediateUpdate(); } else { if (_updateInfo.updateAvailability == 2) { await InAppUpdate.startFlexibleUpdate(); await InAppUpdate.completeFlexibleUpdate(); } } } else if (int.parse(current[0]) < int.parse(latest[0])) { await util.updateDialog(context); // await InAppUpdate.performImmediateUpdate(); } else { if (_updateInfo.updateAvailability == 2) { await InAppUpdate.startFlexibleUpdate(); await InAppUpdate.completeFlexibleUpdate(); } } } catch (e) { print("error Update $e"); } } } changeCabang(context) async { String selected = prefs.getString(Keys.cabangId) ?? ''; return await showDialog( context: context, builder: (context) => StatefulBuilder( builder: (context, setState) => BlocProvider( create: (_) => CabangBloc(), child: BlocListener( listener: (context, cabangState) async { if (cabangState is CabangFinished) { if (cabangState.cabangChanged) { setState(() { lastUpload = ''; lastDownload = ''; timeString = ''; }); } Navigator.pop(context, cabangState.cabangChanged); } }, child: Material( color: Colors.white.withOpacity(0.9), child: BlocBuilder( builder: (context, cabangState) { if (cabangState is CabangLoading) { return const Center( child: SizedBox( height: 10, width: 10, child: CircularProgressIndicator(), ), ); } else if (cabangState is CabangInitial) { BlocProvider.of(context).add(CabangInit( userId: prefs.getString(Keys.loginId), company: prefs.getString(Keys.company))); } else if (cabangState is CabangDisplay) { selected = (selected == '') ? cabangState.cabangList[0]["RETURN_VALUE"] : selected; return Center( child: Container( decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 2, offset: const Offset( 0, 0), // changes position of shadow ), ], borderRadius: BorderRadius.circular(5)), // height: MediaQuery.of(context).size.height/3.2, height: 220, width: MediaQuery.of(context).size.width * 0.75, child: Column( children: [ Flexible( flex: 3, child: Container( padding: const EdgeInsets.only( top: 10, left: 10, right: 10), alignment: Alignment.center, decoration: const BoxDecoration( borderRadius: BorderRadius.only( topLeft: Radius.circular(5), topRight: Radius.circular(5))), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: const [ Icon( Icons.business, size: 70, color: Colors.indigo, ), SizedBox( height: 5, ), Text( 'Set Cabang', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 16, color: Colors.indigo), ) ], ), ), ), Flexible( flex: 1, child: Container( padding: const EdgeInsets.only( left: 20, right: 20), alignment: Alignment.centerLeft, child: Theme( data: ThemeData( canvasColor: Colors.white, primaryColor: Colors.indigo, accentColor: Colors.indigo, hintColor: Colors.indigo), child: DropdownButtonFormField( style: TextStyle( color: Colors.black.withOpacity(0.6), fontWeight: FontWeight.w500, fontSize: 14, ), decoration: const InputDecoration( contentPadding: EdgeInsets.all(8.0), ), value: selected, onChanged: (value) { setState(() { selected = value.toString(); }); }, items: cabangState.cabangList.map((item) { return DropdownMenuItem( value: item['RETURN_VALUE'], child: Text( (item["DISPLAY_VALUE"].length > 20) ? item["DISPLAY_VALUE"] .substring(0, 20) + "..." : item["DISPLAY_VALUE"]), ); }).toList(), ), ), ), ), Flexible( flex: 1, child: Container( child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( child: const Text( 'OK', style: TextStyle(color: Colors.indigo), ), onPressed: () async { BlocProvider.of(context) .add(CabangPicked( cabangId: selected)); }, ), ], ), ), ) ], ), ), ); } else if (cabangState is CabangError) { return Center( child: Container( decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 2, offset: const Offset( 0, 0), // changes position of shadow ), ], borderRadius: BorderRadius.circular(5)), // height: MediaQuery.of(context).size.height/3.2, height: 220, width: MediaQuery.of(context).size.width * 0.75, child: Column( children: [ Flexible( flex: 3, child: Container( padding: const EdgeInsets.only( top: 10, left: 10, right: 10), alignment: Alignment.center, decoration: const BoxDecoration( borderRadius: BorderRadius.only( topLeft: Radius.circular(5), topRight: Radius.circular(5))), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: const [ Icon( Icons.business, size: 70, color: Colors.indigo, ), SizedBox( height: 5, ), Text( 'Error', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 16, color: Colors.indigo), ) ], ), ), ), Flexible( flex: 1, child: Container( padding: const EdgeInsets.only( left: 20, right: 20), alignment: Alignment.centerLeft, child: Theme( data: ThemeData( canvasColor: Colors.white, primaryColor: Colors.indigo, accentColor: Colors.indigo, hintColor: Colors.indigo), child: const Text( "Error menarik data list cabang!"), ), ), ), Flexible( flex: 1, child: Container( child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( child: const Text( 'Retry', style: TextStyle(color: Colors.indigo), ), onPressed: () async { BlocProvider.of(context) .add(CabangInit( userId: prefs.getString( Keys.loginId), company: prefs.getString( Keys.company))); }, ), ], ), ), ) ], ), ), ); } return Container(); }), ), ), ), )); } @override Widget build(BuildContext context) { return WillPopScope( onWillPop: () async { await showDialog( context: context, builder: (context) => Material( color: Colors.white.withOpacity(0.9), child: Center( child: Container( decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 2, offset: const Offset(0, 0), // changes position of shadow ), ], borderRadius: BorderRadius.circular(5)), // height: MediaQuery.of(context).size.height/4.8, height: 220, width: MediaQuery.of(context).size.width * 0.75, child: Column( children: [ Flexible( flex: 3, child: Container( padding: const EdgeInsets.only(top: 10, left: 10, right: 10), alignment: Alignment.center, decoration: const BoxDecoration( // color: Colors.indigo, borderRadius: BorderRadius.only( topLeft: const Radius.circular(5), topRight: Radius.circular(5))), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ const Icon( Icons.exit_to_app, size: 70, color: Colors.indigo, ), ], ), ), ), Flexible( flex: 1, child: Container( padding: const EdgeInsets.only(left: 20, right: 20), alignment: Alignment.centerLeft, child: Text( 'Keluar dari aplikasi?', style: TextStyle( fontWeight: FontWeight.w500, fontSize: 14, color: Colors.black.withOpacity(0.6)), )), ), Flexible( flex: 1, child: Container( padding: const EdgeInsets.only(bottom: 10), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( child: const Text( 'Exit', style: TextStyle(color: Colors.indigo), ), onPressed: () async { Navigator.pop(context); await locationStream?.cancel(); exit(0); }, ), TextButton( child: const Text( 'Cancel', style: TextStyle(color: Colors.indigo), ), onPressed: () { Navigator.pop(context); }, ) ], ), ), ) ], ), ), ), ), ); return false; }, child: MultiBlocProvider( providers: [ BlocProvider( create: (BuildContext context) => _stateBloc, ), BlocProvider( create: (BuildContext context) => _getDataBloc, ), BlocProvider( create: (BuildContext context) => _backupBloc, ), BlocProvider( create: (BuildContext context) => _restoreBloc, ), BlocProvider( create: (BuildContext context) => _uploadBloc, ), BlocProvider( create: (BuildContext context) => _processBloc, ), BlocProvider( create: (BuildContext context) => _submitBloc, ), ], child: MultiBlocListener( listeners: [ BlocListener( listener: (context,state){ if(state is GetUnitLoading){ setState(() { isLoading = true; progressDL= state.percent; }); } else if(state is GetUnitFinish){ setState(() { isLoading = false; progressDL= null; }); if(state.success){ setState(() { lastDownload = prefs.getString(Keys.lastDownload); }); util.showFlushbar(context, state.respond); _stateBloc.add(const LoadState()); } else util.showFlushbar(context, state.respond,color: Colors.red); } }, ), BlocListener( listener: (context,states){ setState(() { isLoading = (states is StateLoading); }); if(states is LoadFailed){ util.showFlushbar(context, states.err,color: Colors.red); } else if(states is LoadSuccess){ setState(() { state = states.state; }); } }, ), BlocListener( listener: (context,state){ setState(() { isLoading = (state is BackupLoading); }); if(state is BackupFinish){ util.showFlushbar(context, state.msg,color: state.success?Colors.grey:Colors.red); } }, ), BlocListener( listener: (context,state){ setState(() { isLoading = (state is RestoreLoading); }); if(state is RestoreFinish){ util.showFlushbar(context, state.msg,color: state.success?Colors.grey:Colors.red); setState(() { lastDownload = prefs.getString(Keys.lastDownload); }); _stateBloc.add(const LoadState()); } }, ), BlocListener( listener: (context,state){ setState(() { isLoading = (state is UploadLoading); }); if(state is UploadFinish){ util.showFlushbar(context, state.msg,color: state.success?Colors.grey:Colors.red); if(state.success){ setState(() { lastUpload = prefs.getString(Keys.lastUpload); }); } _stateBloc.add(const LoadState()); } }, ), BlocListener( listener: (context,state){ setState(() { isLoading = (state is ProcessLoading); }); if(state is ProcessLoading){ util.showLoading(context); } else if(state is ProcessFinish){ Navigator.pop(context); util.showFlushbar(context, state.msg,color: state.success?Colors.grey:Colors.red); _stateBloc.add(const LoadState()); } }, ), BlocListener( listener: (context,state){ setState(() { isLoading = (state is SubmitLoading); }); if(state is SubmitLoading){ util.showLoading(context); } else if(state is SubmitFinish){ Navigator.pop(context); util.showFlushbar(context, state.msg,color: state.success?Colors.grey:Colors.red); _stateBloc.add(const LoadState()); } }, ) ], child: Scaffold( body: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Container( padding: const EdgeInsets.only(bottom: 0, left: 15, right: 10, top: 10), height: MediaQuery.of(context).size.height / 13, width: MediaQuery.of(context).size.width, alignment: Alignment.bottomLeft, child: Row( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Home', style: TextStyle( color: Colors.indigo.withOpacity(0.8), fontSize: 18, fontWeight: FontWeight.bold), ), PopupMenuButton( enabled: !isLoading, child: Padding( padding: const EdgeInsets.only(right: 2.0), child: Icon( Icons.menu, color: Colors.indigo.withOpacity(0.8), ), ), itemBuilder: (context) { return [ // PopupMenuItem( // value:'hostChange', // child: Row( // children: [ // Icon(Icons.network_wifi,color: Colors.black,), // SizedBox(width: 10,), // Text('Change Ip Address') // ], // ), // ), PopupMenuItem( value: 'cabangChange', child: Row( children: const [ Icon( Icons.business, color: Colors.black, ), SizedBox( width: 10, ), Text('Change Cabang') ], ), ), PopupMenuItem( value:'backup', child: Row( children: [ const Icon(Icons.save,color: Colors.black,), const SizedBox(width: 10,), const Text('Backup Data') ], ), ), PopupMenuItem( value: 'restore', child: Row( children: const [ Icon( Icons.sync, color: Colors.black, ), SizedBox( width: 10, ), Text('Restore Backup') ], ), ), PopupMenuItem( value: 'logout', child: Row( children: const [ Icon( Icons.exit_to_app, color: Colors.black, ), SizedBox( width: 10, ), Text('Logout') ], ), ), ]; }, onSelected: (value) async { // if(value == 'hostChange'){ // hostAddress.text = prefs.getString(Keys.hostAddress); // await showDialog(context: context,builder: (context)=> // Material( // color: Colors.white.withOpacity(0.9), // child: Center( // child: Container( // decoration: BoxDecoration( // color: Colors.white, // boxShadow: [ // BoxShadow( // color: Colors.grey.withOpacity(0.5), // spreadRadius: 2, // blurRadius: 2, // offset: Offset(0, 0), // changes position of shadow // ), // ], // borderRadius: BorderRadius.circular(5) // ), // height:220, // // height: MediaQuery.of(context).size.height/3.2, // width: MediaQuery.of(context).size.width*0.75, // child: Column( // children: [ // Flexible( // flex:3, // child: Container( // padding: EdgeInsets.only(top:10,left: 10,right: 10), // alignment: Alignment.center, // decoration: BoxDecoration( // // color: Colors.indigo, // borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5)) // ), // child: Column( // mainAxisSize: MainAxisSize.min, // crossAxisAlignment: CrossAxisAlignment.center, // children: [ // Icon(Icons.network_wifi,size: 70,color: Colors.indigo,), // SizedBox(height: 5,), // Text('Set Ip Address',style: TextStyle(fontWeight: FontWeight.bold,fontSize: 16,color: Colors.indigo),) // ], // ), // ), // ), // Flexible( // flex: 1, // child: Container( // padding: EdgeInsets.only(left: 20,right: 20), // alignment: Alignment.centerLeft, // child: Theme( // data: ThemeData( // canvasColor: Colors.white, // primaryColor: Colors.indigo, // accentColor: Colors.indigo, // hintColor: Colors.indigo // ), // child: TextField( // controller: hostAddress, // decoration: const InputDecoration( // contentPadding: EdgeInsets.all(8), // ), // onSubmitted: (value){ // prefs.setString(Keys.hostAddress,(value=='')?'https://tbg.thamringroup.web.id/ords/tbs/unit/v1':value); // Navigator.pop(context); // }, // ), // ), // ), // ), // Flexible( // flex: 1, // child: Container( // child: Row( // mainAxisAlignment: MainAxisAlignment.end, // children: [ // TextButton( // child: Text('OK',style: TextStyle(color: Colors.indigo),), // onPressed: (){ // prefs.setString(Keys.hostAddress,(hostAddress.text=='')?'https://tbg.thamringroup.web.id/ords/tbs/unit/v1':hostAddress.text); // Navigator.pop(context); // }, // ) // ], // ), // ), // ) // ], // ), // ), // ), // ) // ); // } if (value == "cabangChange") { var res = await changeCabang(context); if (res ?? false) { setState(() {}); } } if (value == 'logout') { await showDialog( context: context, builder: (context) => Material( color: Colors.white.withOpacity(0.9), child: BlocProvider( create: (_) => LogoutBloc(), child: Center( child: Container( decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Colors.grey .withOpacity(0.5), spreadRadius: 2, blurRadius: 2, offset: const Offset(0, 0), // changes position of shadow ), ], borderRadius: BorderRadius.circular(5)), height: 220, // height: MediaQuery.of(context).size.height/3.2, width: MediaQuery.of(context).size.width * 0.75, child: BlocBuilder( bloc: LogoutBloc(), builder: (context, state) { final blocLogout = BlocProvider.of( context); if (state is LogoutLoading) { return const Center( child: SizedBox( height: 10, width: 10, child: CircularProgressIndicator(), ), ); } return Column( children: [ Flexible( flex: 3, child: Container( padding: const EdgeInsets.only( top: 10, left: 10, right: 10), alignment: Alignment.center, decoration: const BoxDecoration( borderRadius: BorderRadius.only( topLeft: Radius .circular( 5), topRight: Radius .circular( 5))), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment .center, children: const [ Icon( Icons.logout, size: 70, color: Colors.indigo, ), SizedBox( height: 5, ), Text( 'Logout', style: TextStyle( fontWeight: FontWeight .bold, fontSize: 16, color: Colors .indigo), ) ], ), ), ), Flexible( flex: 1, child: Container( padding: const EdgeInsets.only( left: 20, right: 20), alignment: Alignment.centerLeft, child: const Text( "Kembali ke halaman login?"), ), ), Flexible( flex: 1, child: Container( child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( child: const Text( 'Logout', style: TextStyle( color: Colors .indigo), ), onPressed: () { blocLogout.add( LogoutInitiate( context: context)); }, ), TextButton( child: const Text( 'Cancel', style: TextStyle( color: Colors .indigo), ), onPressed: () { Navigator.pop(context); }, ) ], ), ), ) ], ); }, ), ), ), ), )); } if(value == 'backup'){ if(lastDownload != null && lastDownload != '' ){ bool? isBackup = await showDialog(context: context,builder: (context)=>AlertDialog( title: const Text('Backup Data ?'), content: const Text('Backup data akan menghapus dan mengganti data backup unit dan cabang sebelumnya.'), actions: [ TextButton( child: const Text('OK'), onPressed: ()async{ Navigator.pop(context,true); }, ), TextButton( child: const Text('Cancel'), onPressed: ()=>Navigator.pop(context,false), ) ], )); if(isBackup??false){ _backupBloc.add(BackupInit(context: context)); } } else{ util.showFlushbar(context, "Data Unit cabang tidak ditemukan. Silakan get data terlbih dahulu."); } } if(value == 'restore'){ if(prefs.getString(Keys.stockId) == null){ util.showFlushbar(context, "Data Unit cabang tidak ditemukan. Silakan get data terlbih dahulu."); } else{ if(prefs.getString(Keys.stockId) == prefs.getString(Keys.backupStockId)){ // _stateBloc.add(LoadState()); // state di load waktu get data if(['Open','Submitted'].contains(state)){ bool? isRestore = await showDialog(context: context,builder: (context)=>AlertDialog( title: const Text('Restore Data ?'), content: const Text('Restore data akan menghapus dan mengganti data unit dan cabang yang ada dengan data backup.'), actions: [ TextButton( child: const Text('OK'), onPressed: ()async{ Navigator.pop(context,true); }, ), TextButton( child: const Text('Cancel'), onPressed: ()=>Navigator.pop(context,false), ) ], )); if(isRestore??false){ bool? isclear; // check exist Directory? documentsDirectory = await getExternalStorageDirectory(); String path = paths.join(documentsDirectory!.path, "UnitStocking.db"); File db = File(path); if(db.existsSync()){ isclear = await clearData(context); } else{ isclear = true; } if(isclear??false){ _restoreBloc.add(RestoreInit(context: context)); } } } else{ util.showFlushbar(context, "Stocking Unit sudah selesai dan tidak perlu di restore"); } } else { util.showFlushbar(context, "File Backup tidak ditemukan atau sudah selesai"); } } } // if (value == 'restore') { // await showDialog(context: context,builder: (context)=>BlocProvider( // create: (_)=>RestoreBloc(), // child: BlocBuilder( // builder: (context,restoreState) { // if(restoreState is RestoreLoading){ // return const Center( // child: SizedBox( // height: 10, // width: 10, // child: // CircularProgressIndicator(), // ), // ); // } // else if(restoreState is RestoreSuccess){ // Navigator.pop(context); // setState(() { // lastUpload = ''; // lastDownload = ''; // timeString = ''; // }); // } // return AlertDialog( // title: Text((restoreState is RestoreFailed)?"Error":'Restore Data ?'), // content: Text((restoreState is RestoreFailed)?"${restoreState.err}. Ulangi?":'Restore data akan menghapus dan mengganti data unit yang ada dengan data unit backup.'), // actions: [ // TextButton( // child: const Text('OK'), // onPressed: ()async{ // BlocProvider.of(context).add(const RestoreInit()); // }, // ), // TextButton( // child: const Text('Batal'), // onPressed: ()=>Navigator.pop(context), // ) // ], // ); // } // ), // )); // } }, ), ], ), ), (prefs.getString(Keys.stockId) == null) ? Container() : Padding( padding: const EdgeInsets.only(top: 8, right: 8), child: Container( decoration: BoxDecoration( color: Colors.indigo.withOpacity(0.9), borderRadius: BorderRadius.circular(8) // border: Border.all(), ), padding: const EdgeInsets.all(8), child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.center, children: [ const Text( 'Status : ', style: TextStyle(color: Colors.white), ), Text( state ?? '-', style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.white), ), ], ), ), ), Expanded( child: Container( child: SmartRefresher( controller: _refreshController, enablePullDown: !(isLoading), onRefresh: (){ if(prefs.getString(Keys.stockId)!= null){ _stateBloc.add(const LoadState()); } else { util.showFlushbar(context, "Silakan tarik data unit terlebih dulu"); } _refreshController.refreshCompleted(); }, child: GridView.count( padding: const EdgeInsets.all(10), crossAxisSpacing: 10, mainAxisSpacing: 10, crossAxisCount: 2, children: [ AbsorbPointer( absorbing: isLoading, child: InkWell( splashColor: Colors.black, onTap: () async { bool? getData = await showDialog( context: context, builder: (context)=>AlertDialog( title: const Text("Get Data Units?"), content: const Text('Fetch data unit for stocking'), actions: [ TextButton( child: const Text('Proceed'), onPressed: (){ Navigator.pop(context,true); }, ), TextButton( child: const Text('Cancel'), onPressed: (){ Navigator.pop(context,false); }, ) ], ) ); if(getData??false){ setState(() { isLoading = true; }); // var a = Stopwatch(); // a.start(); await Future.delayed(const Duration(milliseconds: 200)); bool? isclear; Directory? documentsDirectory = await getExternalStorageDirectory(); String path = paths.join(documentsDirectory!.path, "UnitStocking.db"); File db = File(path); if(db.existsSync()){ isclear = await clearData(context); } else{ isclear = true; } if(isclear??false){ _getDataBloc.add(GetUnitInit()); } } }, child: Container( padding: const EdgeInsets.all(5), decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 2, offset: const Offset(0, 0), // changes position of shadow ), ], borderRadius: const BorderRadius.all(const Radius.circular(5.0)), color: Colors.green.withAlpha(220).withOpacity(0.7), ), child: Stack( children: [ Container( alignment: (progressDL != null) ? Alignment.bottomCenter : Alignment.bottomLeft, padding: const EdgeInsets.only( left: 10, right: 10, top: 10, bottom: 15), child: (progressDL != null) ? Column( mainAxisSize: MainAxisSize.min, children: [ LinearProgressIndicator( value: progressDL, ), Text( '${(progressDL! * 100).floor()}%', style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold), ) ], ) : (lastDownload == '') ? null : Text( 'Last download : ${DateFormat('dd MMM yyyy HH:mm').format(DateTime.parse(lastDownload))}', style: const TextStyle( color: Colors.white, fontSize: 11, fontWeight: FontWeight.bold)), ), Positioned.fill( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.file_upload, size: MediaQuery.of(context).size.width / 6, color: Colors.white, ), const SizedBox( height: 5, ), const Text( 'Get Data Master', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16), ), ], ), ), ], ), ), ), ), InkWell( splashColor: Colors.black, onTap: () async { await Future.delayed(const Duration(milliseconds: 200)); if (lastDownload != '') { Navigator.pushNamed(context, '/units'); } else { util.showFlushbar(context, 'Data Master tidak ditemukan. Get data master dulu.'); } }, child: Container( padding: const EdgeInsets.all(5), decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 2, offset: const Offset(0, 0), // changes position of shadow ), ], borderRadius: const BorderRadius.all(const Radius.circular(5.0)), color: Colors.blueGrey.withAlpha(230).withOpacity(0.8), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.receipt, size: MediaQuery.of(context).size.width / 6, color: Colors.white, ), const SizedBox( height: 5, ), const Text( 'Stocking', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16), ) ], ), ), ), InkWell( splashColor: Colors.black, onTap: () async { _uploadBloc.add(Upload(context: context)); }, child: Container( padding: const EdgeInsets.all(5), decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 2, offset: const Offset(0, 0), // changes position of shadow ), ], borderRadius: const BorderRadius.all(const Radius.circular(5.0)), color: Colors.indigo.withAlpha(220).withOpacity(0.7), ), child: Stack( children: [ BlocBuilder( bloc: _uploadBloc, builder: (context, state){ if(state is UploadLoading){ return Column( mainAxisSize: MainAxisSize.min, children: [ LinearProgressIndicator( value: progressUL, ), Text( '${(progressUL ?? 0 * 100).floor()}%', style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold), ) ], ); } if(lastUpload != ''){ return Positioned.fill( child: Container( alignment: Alignment.bottomCenter, child: Text( 'Last upload : ${DateFormat('dd MMM yyyy HH:mm').format(DateTime.parse(lastUpload))}\n${(timeString != '') ? 'Duration: $timeString' : ''}', style: const TextStyle( color: Colors.white, fontSize: 11, fontWeight: FontWeight.bold)), ), ); } return Container(); }), Positioned.fill( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.file_upload, size: MediaQuery.of(context).size.width / 6, color: Colors.white, ), const SizedBox( height: 5, ), const Text( 'Send Data Stokan', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16), ), ], ), ), ], ), ), ), (prefs.getString(Keys.targetProccess) == null && prefs.getBool(Keys.submitProccess) == null) ? InkWell( splashColor: Colors.black, onTap: () async { await Future.delayed(const Duration(milliseconds: 200)); await clearData(context); }, child: Container( padding: const EdgeInsets.all(5), decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 2, offset: const Offset( 0, 0), // changes position of shadow ), ], borderRadius: const BorderRadius.all(Radius.circular(5.0)), color: Colors.red.withAlpha(200).withOpacity(0.7), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.restore_from_trash, size: MediaQuery.of(context).size.width / 6, color: Colors.white, ), const SizedBox( height: 5, ), const Text( 'Clear Data', style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16), ) ], ), ), ) : (prefs.getString(Keys.targetProccess) != null) ? InkWell( onTap: () async { bool result = await showDialog( context: context, builder: (context) => WillPopScope( onWillPop: () async { Navigator.pop(context, false); return false; }, child: AlertDialog( title: const Text('Process Data ?'), content: const Text( 'Proceed to unpack the uploaded data.'), actions: [ TextButton( child: const Text('Proceed'), onPressed: () async { Navigator.pop(context, true); }, ), TextButton( child: const Text('Cancel'), onPressed: () { Navigator.pop(context, false); }, ) ], ), )); if (result) { _processBloc.add(ProcessUnit()); } }, child: Container( padding: const EdgeInsets.all(5), decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 2, offset: const Offset( 0, 0), // changes position of shadow ), ], borderRadius: const BorderRadius.all(const Radius.circular(5.0)), color: Colors.orangeAccent .withAlpha(230) .withOpacity(0.7), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.arrow_forward, size: MediaQuery.of(context).size.width / 6, color: Colors.white, ), const SizedBox( height: 5, ), const Text( 'Process Units', style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16), ) ], ), ), ) : InkWell( onTap: () async { bool result = await showDialog(context: context,builder: (context)=>WillPopScope( onWillPop: ()async{ Navigator.pop(context,false); return false; }, child: AlertDialog( title: const Text('Submit Data ?'), content: const Text('Submit the uploaded data.'), actions: [ TextButton( child: const Text('Submit'), onPressed: ()async{ Navigator.pop(context,true); }, ), TextButton( child: const Text('Cancel'), onPressed: (){Navigator.pop(context,false);}, ) ], ), )); if(result){ _submitBloc.add(Submit()); } }, child: Container( padding: const EdgeInsets.all(5), decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 2, offset: const Offset( 0, 0), // changes position of shadow ), ], borderRadius: const BorderRadius.all(const Radius.circular(5.0)), color: Colors.lightGreen.withAlpha(230), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.arrow_forward, size: MediaQuery.of(context).size.width / 6, color: Colors.white, ), const SizedBox( height: 5, ), const Text( 'Submit Process', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16), ) ], ), ), ), (prefs.getString(Keys.targetProccess) != null || (prefs.getBool(Keys.submitProccess) != null && prefs.getBool(Keys.submitProccess))) ? InkWell( splashColor: Colors.black, onTap: () async { await Future.delayed(const Duration(milliseconds: 200)); await clearData(context); }, child: Container( padding: const EdgeInsets.all(5), decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 2, blurRadius: 2, offset: const Offset( 0, 0), // changes position of shadow ), ], borderRadius: const BorderRadius.all(const Radius.circular(5.0)), color: Colors.red.withAlpha(200), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.restore_from_trash, size: MediaQuery.of(context).size.width / 6, color: Colors.white, ), const SizedBox( height: 5, ), const Text( 'Clear Data', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16), ) ], ), ), ) : Container(), ], ), ), ), ), ], ), bottomSheet: Container( padding: const EdgeInsets.only(bottom: 15, right: 10), height: 58, alignment: Alignment.bottomRight, child: Opacity( opacity: 0.5, child: Padding( padding: const EdgeInsets.all(5), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( (lastDownload != '') ? 'Master Data Downloaded' : 'No Master Data Found', style: const TextStyle(fontSize: 12), ), (currentVersion!="")?Text("ver. $currentVersion",style: const TextStyle(fontWeight: FontWeight.bold,fontSize: 12),):Container() ] )))), ), ), ), ); } @override void didPushNext() async { //pushed from home if(prefs.getString(Keys.stockId)!= null){ _stateBloc.add(const LoadState()); } } @override void didPopNext() async { //popped to home if(prefs.getString(Keys.stockId)!= null){ _stateBloc.add(const LoadState()); } } @override void didChangeDependencies() { super.didChangeDependencies(); routeObserver.subscribe(this, ModalRoute.of(context) as PageRoute); } @override void dispose() { _stateBloc.close(); _getDataBloc.close(); _backupBloc.close(); _restoreBloc.close(); _uploadBloc.close(); _processBloc.close(); _submitBloc.close(); routeObserver.unsubscribe(this); super.dispose(); } }