flutter app untuk unitstock
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 

1202 行
61 KiB

  1. import 'dart:async';
  2. import 'dart:io';
  3. import 'package:flutter/foundation.dart';
  4. import 'package:flutter/rendering.dart';
  5. import 'package:flutter/widgets.dart';
  6. import 'package:in_app_update/in_app_update.dart';
  7. import 'package:package_info/package_info.dart';
  8. import 'package:path/path.dart';
  9. import 'package:flutter/cupertino.dart';
  10. import 'package:flutter/material.dart';
  11. import 'package:path_provider/path_provider.dart';
  12. import 'Util/DBHelper.dart';
  13. import 'Util/Util.dart';
  14. import 'Util/download_Upload_Handler.dart';
  15. import 'package:intl/intl.dart';
  16. import 'main.dart';
  17. import 'Util/Prefs.dart';
  18. import 'Util/UnitModel.dart';
  19. import 'package:permission_handler/permission_handler.dart' as pHandler;
  20. import 'package:device_info_plus/device_info_plus.dart';
  21. class HomePage extends StatefulWidget {
  22. // HomePage({Key key}) : super(key: key);
  23. final String title;
  24. HomePage({this.title});
  25. @override
  26. _HomePageState createState() => _HomePageState();
  27. }
  28. class _HomePageState extends State<HomePage> {
  29. Util util = new Util();
  30. StreamSubscription progressDLStream,progressULStream;
  31. String lastDownload = '';
  32. String lastUpload = '';
  33. double progressDL,progressUL;
  34. String timeString = '';
  35. bool isLoading = false;
  36. String state = '';
  37. final hostAddress = new TextEditingController();
  38. clearData(context)async{
  39. setState(() {
  40. progressDL = null;
  41. isLoading = false;
  42. });
  43. String errMsg;
  44. bool result = await showDialog(context: context,builder: (context)=>WillPopScope(
  45. onWillPop: ()async{
  46. Navigator.pop(context,false);
  47. return false;
  48. },
  49. child: AlertDialog(
  50. title: Text('Clear Data ?'),
  51. content: Text('Proceed to clear any remaining units data on this device?'),
  52. actions: <Widget>[
  53. TextButton(
  54. child: Text('OK'),
  55. onPressed: ()async{
  56. util.showLoading(context);
  57. await Future.sync(()async{
  58. try{
  59. Directory documentsDirectory = await getApplicationDocumentsDirectory();
  60. String path = join(documentsDirectory.path, "UnitStocking.db");
  61. File db = File(path);
  62. if(db.existsSync()){
  63. await DBHelper.database.closeDb();
  64. db.deleteSync();
  65. await prefs.remove(keyClass.lastDownload);
  66. await prefs.remove(keyClass.lastUpload);
  67. await prefs.remove(keyClass.targetProccess);
  68. await prefs.remove(keyClass.submitProccess);
  69. await prefs.remove(keyClass.stock_id);
  70. setState(() {
  71. lastUpload = '';
  72. lastDownload = '';
  73. timeString = '';
  74. });
  75. }
  76. }
  77. catch(e){
  78. print(e);
  79. util.showFlushbar(context, 'Failed to delete database file',color: Colors.red);
  80. }
  81. });
  82. Navigator.pop(context);
  83. Navigator.pop(context,true);
  84. util.showFlushbar(context,errMsg??'Data Cleared');
  85. },
  86. ),
  87. TextButton(
  88. child: Text('Cancel'),
  89. onPressed: (){Navigator.pop(context,false);},
  90. )
  91. ],
  92. ),
  93. ));
  94. return result;
  95. }
  96. loadState()async{
  97. String company = prefs.getString(keyClass.company);
  98. if(prefs.getString(keyClass.stock_id) == null)
  99. {
  100. valueTab value = await DBHelper.database.getValue(keyClass.stock_id);
  101. if(value != null)await prefs.setString(keyClass.stock_id, value.value);
  102. }
  103. String stock_taking_id = prefs.getString(keyClass.stock_id);
  104. if(prefs.getString(keyClass.backup_stock_id) == null && stock_taking_id!= null) prefs.setString(keyClass.backup_stock_id,stock_taking_id);
  105. if(company!=null&&stock_taking_id!=null){
  106. var result = await util.JsonDataPostRaw({"company":company,"stockTakingId":stock_taking_id}, '${prefs.getString(keyClass.hostAddress)}/stock_taking/state/');
  107. if(result['STATUS']==1){
  108. setState(() {
  109. state = result['DATA'];
  110. });
  111. }
  112. }
  113. }
  114. @override
  115. void initState() {
  116. // TODO: implement initState
  117. super.initState();
  118. loadState();
  119. lastDownload = prefs.getString(keyClass.lastDownload)??'';
  120. lastUpload = prefs.getString(keyClass.lastUpload)??'';
  121. WidgetsBinding.instance.addPostFrameCallback((_) async {
  122. await _check_Update();
  123. // dak jadi pakek external karena butuh Full acces File yang ribet ngorosnyo di appstore dan playstore
  124. // final androidVersion = await DeviceInfoPlugin().androidInfo;
  125. // if ((androidVersion.version.sdkInt ?? 0) >= 30) {
  126. // print(1);
  127. // await util.permissionCheck(this.context,pHandler.Permission.manageExternalStorage,()async{print("storage permit granted!");},customMessage: " untuk menyimpan data backup ke external storage!!");
  128. // } else {
  129. // print(3);
  130. await util.permissionCheck(this.context,pHandler.Permission.storage,()async{print("storage permit granted!");},customMessage: " untuk menyimpan data backup");
  131. // }
  132. });
  133. }
  134. _check_Update()async{
  135. if(defaultTargetPlatform == TargetPlatform.android){
  136. try{
  137. final PackageInfo info = await PackageInfo.fromPlatform();
  138. AppUpdateInfo _updateInfo = await InAppUpdate.checkForUpdate();
  139. String currentVersion = info.version.trim();
  140. String latestversion = '0.0.0';
  141. var result = await util.getMinAppVer();
  142. if(result['STATUS']==1){
  143. latestversion = result['DATA'];
  144. }
  145. var current = currentVersion.split('.');
  146. var latest = latestversion.split('.');
  147. if(int.parse(current[0])==int.parse(latest[0])){
  148. if(int.parse(current[1])==int.parse(latest[1])){
  149. if(int.parse(current[2])<int.parse(latest[2])) {
  150. await util.updateDialog(context);
  151. }
  152. else{
  153. if(_updateInfo?.updateAvailability == 2) {
  154. await InAppUpdate.startFlexibleUpdate();
  155. await InAppUpdate.completeFlexibleUpdate();
  156. }
  157. }
  158. }
  159. else if(int.parse(current[1])<int.parse(latest[1])) {
  160. await util.updateDialog(context);
  161. // await InAppUpdate.performImmediateUpdate();
  162. }
  163. else{
  164. if(_updateInfo?.updateAvailability == 2) {
  165. await InAppUpdate.startFlexibleUpdate();
  166. await InAppUpdate.completeFlexibleUpdate();
  167. }
  168. }
  169. }
  170. else if(int.parse(current[0])<int.parse(latest[0])) {
  171. await util.updateDialog(context);
  172. // await InAppUpdate.performImmediateUpdate();
  173. }
  174. else{
  175. if(_updateInfo?.updateAvailability == 2 ) {
  176. await InAppUpdate.startFlexibleUpdate();
  177. await InAppUpdate.completeFlexibleUpdate();
  178. }
  179. }
  180. }
  181. catch(e){
  182. print("error Update $e");
  183. }
  184. }
  185. }
  186. changeCabang(context)async{
  187. util.showLoading(context);
  188. var result = await util.JsonDataPostRaw({"company":prefs.getString(keyClass.company),"User":prefs.getString(keyClass.loginId)}, '${prefs.getString(keyClass.hostAddress)}/user/cabangs/');
  189. Navigator.pop(context);
  190. if(result['STATUS']==1){
  191. var selected = prefs.getString(keyClass.cabang_id)??result['DATA'][0]["RETURN_VALUE"];
  192. return await showDialog(context: context,builder: (context)=>StatefulBuilder(
  193. builder:(context,setState)=>
  194. Material(
  195. color: Colors.white.withOpacity(0.9),
  196. child: Center(
  197. child: Container(
  198. decoration: BoxDecoration(
  199. color: Colors.white,
  200. boxShadow: [
  201. BoxShadow(
  202. color: Colors.grey.withOpacity(0.5),
  203. spreadRadius: 2,
  204. blurRadius: 2,
  205. offset: Offset(0, 0), // changes position of shadow
  206. ),
  207. ],
  208. borderRadius: BorderRadius.circular(5)
  209. ),
  210. // height: MediaQuery.of(context).size.height/3.2,
  211. height:220,
  212. width: MediaQuery.of(context).size.width*0.75,
  213. child: Column(
  214. children: <Widget>[
  215. Flexible(
  216. flex:3,
  217. child: Container(
  218. padding: EdgeInsets.only(top:10,left: 10,right: 10),
  219. alignment: Alignment.center,
  220. decoration: BoxDecoration(
  221. // color: Colors.indigo,
  222. borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5))
  223. ),
  224. child: Column(
  225. mainAxisSize: MainAxisSize.min,
  226. crossAxisAlignment: CrossAxisAlignment.center,
  227. children: <Widget>[
  228. Icon(Icons.business,size: 70,color: Colors.indigo,),
  229. SizedBox(height: 5,),
  230. Text('Set Cabang',style: TextStyle(fontWeight: FontWeight.bold,fontSize: 16,color: Colors.indigo),)
  231. ],
  232. ),
  233. ),
  234. ),
  235. Flexible(
  236. flex: 1,
  237. child: Container(
  238. padding: EdgeInsets.only(left: 20,right: 20),
  239. alignment: Alignment.centerLeft,
  240. child: Theme(
  241. data: ThemeData(
  242. canvasColor: Colors.white,
  243. primaryColor: Colors.indigo,
  244. accentColor: Colors.indigo,
  245. hintColor: Colors.indigo
  246. ),
  247. child: DropdownButtonFormField(
  248. style: TextStyle(color: Colors.black.withOpacity(0.6),fontWeight: FontWeight.w500,fontSize: 14,),
  249. decoration: InputDecoration(
  250. contentPadding: EdgeInsets.all(8.0),
  251. ),
  252. value: selected,
  253. onChanged: (value){
  254. setState(() {
  255. selected = value;
  256. });
  257. },
  258. items: result['DATA'].map<DropdownMenuItem<dynamic>>((item){
  259. return DropdownMenuItem(
  260. value: item['RETURN_VALUE'],
  261. child: Container(width: MediaQuery.of(context).size.width*0.55,child: Text(item["DISPLAY_VALUE"])),
  262. );
  263. }).toList(),
  264. ),
  265. ),
  266. ),
  267. ),
  268. Flexible(
  269. flex: 1,
  270. child: Container(
  271. child: Row(
  272. mainAxisAlignment: MainAxisAlignment.end,
  273. children: <Widget>[
  274. TextButton(
  275. child: Text('OK',style: TextStyle(color: Colors.indigo),),
  276. onPressed: ()async{
  277. if(selected!=prefs.getString(keyClass.cabang_id)){
  278. prefs.setString(keyClass.cabang_id,selected);
  279. await Future.sync(()async{
  280. await prefs.remove(keyClass.lastDownload);
  281. await prefs.remove(keyClass.lastUpload);
  282. await prefs.remove(keyClass.targetProccess);
  283. await prefs.remove(keyClass.submitProccess);
  284. await prefs.remove(keyClass.stock_id);
  285. lastUpload = '';
  286. lastDownload = '';
  287. timeString = '';
  288. try{
  289. Directory documentsDirectory = await getApplicationDocumentsDirectory();
  290. String path = join(documentsDirectory.path, "UnitStocking.db");
  291. File db = File(path);
  292. if(db.existsSync()){
  293. db.deleteSync();
  294. }
  295. }
  296. catch(e){
  297. print(e);
  298. util.showFlushbar(context, 'Failed to delete database file',color: Colors.red);
  299. }
  300. });
  301. Navigator.pop(context,true);
  302. }
  303. else{
  304. Navigator.pop(context,false);
  305. }
  306. },
  307. ),
  308. ],
  309. ),
  310. ),
  311. )
  312. ],
  313. ),
  314. ),
  315. ),
  316. ),
  317. ));
  318. }
  319. else{
  320. util.showFlushbar(context, result['DATA'],color: Colors.red);
  321. return false;
  322. }
  323. }
  324. @override
  325. Widget build(BuildContext context) {
  326. return WillPopScope(
  327. onWillPop: ()async{
  328. await showDialog(context: context,builder: (context)=>
  329. Material(
  330. color: Colors.white.withOpacity(0.9),
  331. child: Center(
  332. child: Container(
  333. decoration: BoxDecoration(
  334. color: Colors.white,
  335. boxShadow: [
  336. BoxShadow(
  337. color: Colors.grey.withOpacity(0.5),
  338. spreadRadius: 2,
  339. blurRadius: 2,
  340. offset: Offset(0, 0), // changes position of shadow
  341. ),
  342. ],
  343. borderRadius: BorderRadius.circular(5)
  344. ),
  345. // height: MediaQuery.of(context).size.height/4.8,
  346. height:220,
  347. width: MediaQuery.of(context).size.width*0.75,
  348. child: Column(
  349. children: <Widget>[
  350. Flexible(
  351. flex:3,
  352. child: Container(
  353. padding: EdgeInsets.only(top:10,left: 10,right: 10),
  354. alignment: Alignment.center,
  355. decoration: BoxDecoration(
  356. // color: Colors.indigo,
  357. borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5))
  358. ),
  359. child: Column(
  360. mainAxisSize: MainAxisSize.min,
  361. crossAxisAlignment: CrossAxisAlignment.center,
  362. children: <Widget>[
  363. Icon(Icons.exit_to_app,size: 70,color: Colors.indigo,),
  364. ],
  365. ),
  366. ),
  367. ),
  368. Flexible(
  369. flex: 1,
  370. child: Container(
  371. padding: EdgeInsets.only(left: 20,right: 20),
  372. alignment: Alignment.centerLeft,
  373. child: Text('Keluar dari aplikasi?',style: TextStyle(fontWeight: FontWeight.w500,fontSize: 14,color: Colors.black.withOpacity(0.6)),)
  374. ),
  375. ),
  376. Flexible(
  377. flex: 1,
  378. child: Container(
  379. padding: EdgeInsets.only(bottom:10),
  380. child: Row(
  381. mainAxisAlignment: MainAxisAlignment.end,
  382. children: <Widget>[
  383. TextButton(
  384. child: Text('Exit',style: TextStyle(color: Colors.indigo),),
  385. onPressed: ()async{
  386. Navigator.pop(context);
  387. await locationStream?.cancel();
  388. exit(0);
  389. },
  390. ),
  391. TextButton(
  392. child: Text('Cancel',style: TextStyle(color: Colors.indigo),),
  393. onPressed: (){
  394. Navigator.pop(context);
  395. },
  396. )
  397. ],
  398. ),
  399. ),
  400. )
  401. ],
  402. ),
  403. ),
  404. ),
  405. ),
  406. );
  407. return false;
  408. },
  409. child: Scaffold(
  410. body: Column(
  411. crossAxisAlignment: CrossAxisAlignment.end,
  412. children: <Widget>[
  413. Container(
  414. padding: EdgeInsets.only(bottom: 0,left: 15,right: 10,top: 10),
  415. height: MediaQuery.of(context).size.height/13,
  416. width: MediaQuery.of(context).size.width,
  417. alignment: Alignment.bottomLeft,
  418. child: Row(
  419. crossAxisAlignment: CrossAxisAlignment.end,
  420. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  421. children: <Widget>[
  422. Text('Home',style: TextStyle(color: Colors.indigo.withOpacity(0.8),fontSize: 18,fontWeight: FontWeight.bold),),
  423. PopupMenuButton(
  424. child: Padding(
  425. padding: const EdgeInsets.only(right:2.0),
  426. child: Icon(Icons.menu,color: Colors.indigo.withOpacity(0.8),),
  427. ),
  428. itemBuilder: (context){
  429. return [
  430. PopupMenuItem(
  431. value:'hostChange',
  432. child: Row(
  433. children: <Widget>[
  434. Icon(Icons.network_wifi,color: Colors.black,),
  435. SizedBox(width: 10,),
  436. Text('Change Ip Address')
  437. ],
  438. ),
  439. ),
  440. PopupMenuItem(
  441. value:'cabangChange',
  442. child: Row(
  443. children: <Widget>[
  444. Icon(Icons.business,color: Colors.black,),
  445. SizedBox(width: 10,),
  446. Text('Change Cabang')
  447. ],
  448. ),
  449. ),
  450. PopupMenuItem(
  451. value:'backup',
  452. child: Row(
  453. children: <Widget>[
  454. Icon(Icons.save,color: Colors.black,),
  455. SizedBox(width: 10,),
  456. Text('Backup Data')
  457. ],
  458. ),
  459. ),
  460. PopupMenuItem(
  461. value:'restore',
  462. child: Row(
  463. children: <Widget>[
  464. Icon(Icons.sync,color: Colors.black,),
  465. SizedBox(width: 10,),
  466. Text('Restore Data')
  467. ],
  468. ),
  469. ),
  470. PopupMenuItem(
  471. value:'logout',
  472. child: Row(
  473. children: <Widget>[
  474. Icon(Icons.exit_to_app,color: Colors.black,),
  475. SizedBox(width: 10,),
  476. Text('Logout')
  477. ],
  478. ),
  479. ),
  480. ];
  481. },
  482. onSelected: (value)async{
  483. if(value == 'hostChange'){
  484. hostAddress.text = prefs.getString(keyClass.hostAddress);
  485. await showDialog(context: context,builder: (context)=>
  486. Material(
  487. color: Colors.white.withOpacity(0.9),
  488. child: Center(
  489. child: Container(
  490. decoration: BoxDecoration(
  491. color: Colors.white,
  492. boxShadow: [
  493. BoxShadow(
  494. color: Colors.grey.withOpacity(0.5),
  495. spreadRadius: 2,
  496. blurRadius: 2,
  497. offset: Offset(0, 0), // changes position of shadow
  498. ),
  499. ],
  500. borderRadius: BorderRadius.circular(5)
  501. ),
  502. height:220,
  503. // height: MediaQuery.of(context).size.height/3.2,
  504. width: MediaQuery.of(context).size.width*0.75,
  505. child: Column(
  506. children: <Widget>[
  507. Flexible(
  508. flex:3,
  509. child: Container(
  510. padding: EdgeInsets.only(top:10,left: 10,right: 10),
  511. alignment: Alignment.center,
  512. decoration: BoxDecoration(
  513. // color: Colors.indigo,
  514. borderRadius: BorderRadius.only(topLeft: Radius.circular(5),topRight: Radius.circular(5))
  515. ),
  516. child: Column(
  517. mainAxisSize: MainAxisSize.min,
  518. crossAxisAlignment: CrossAxisAlignment.center,
  519. children: <Widget>[
  520. Icon(Icons.network_wifi,size: 70,color: Colors.indigo,),
  521. SizedBox(height: 5,),
  522. Text('Set Ip Address',style: TextStyle(fontWeight: FontWeight.bold,fontSize: 16,color: Colors.indigo),)
  523. ],
  524. ),
  525. ),
  526. ),
  527. Flexible(
  528. flex: 1,
  529. child: Container(
  530. padding: EdgeInsets.only(left: 20,right: 20),
  531. alignment: Alignment.centerLeft,
  532. child: Theme(
  533. data: ThemeData(
  534. canvasColor: Colors.white,
  535. primaryColor: Colors.indigo,
  536. accentColor: Colors.indigo,
  537. hintColor: Colors.indigo
  538. ),
  539. child: TextField(
  540. controller: hostAddress,
  541. decoration: InputDecoration(
  542. contentPadding: EdgeInsets.all(8),
  543. ),
  544. onSubmitted: (value){
  545. prefs.setString(keyClass.hostAddress,(value=='')?'https://tbg.thamringroup.web.id/ords/tbs/unit/v1':value);
  546. Navigator.pop(context);
  547. },
  548. ),
  549. ),
  550. ),
  551. ),
  552. Flexible(
  553. flex: 1,
  554. child: Container(
  555. child: Row(
  556. mainAxisAlignment: MainAxisAlignment.end,
  557. children: <Widget>[
  558. TextButton(
  559. child: Text('OK',style: TextStyle(color: Colors.indigo),),
  560. onPressed: (){
  561. prefs.setString(keyClass.hostAddress,(hostAddress.text=='')?'https://tbg.thamringroup.web.id/ords/tbs/unit/v1':hostAddress.text);
  562. Navigator.pop(context);
  563. },
  564. )
  565. ],
  566. ),
  567. ),
  568. )
  569. ],
  570. ),
  571. ),
  572. ),
  573. )
  574. // AlertDialog(
  575. // title: Text('Set IP Address'),
  576. // content: TextField(
  577. // controller: hostAddress,
  578. // onSubmitted: (value){
  579. // prefs.setString(keyClass.hostAddress,(value=='')?'https://unitstocksbackend.thamringroup.web.id':value);
  580. // Navigator.pop(context);
  581. // },
  582. // ),
  583. // actions: <Widget>[
  584. // TextButton(
  585. // child: Text('OK'),
  586. // onPressed: (){
  587. // prefs.setString(keyClass.hostAddress,(hostAddress.text=='')?'https://unitstocksbackend.thamringroup.web.id':hostAddress.text);
  588. // Navigator.pop(context);
  589. // },
  590. // )
  591. // ],
  592. // )
  593. );
  594. }
  595. if(value=="cabangChange") {
  596. var res = await changeCabang(context);
  597. if(res??false){
  598. setState(() {
  599. });
  600. }
  601. }
  602. if(value == 'logout'){
  603. // prefs.remove(keyClass.cabang_id);
  604. prefs.remove(keyClass.company);
  605. prefs.remove(keyClass.loginId);
  606. prefs.setBool(keyClass.logged_in, false);
  607. Navigator.pushNamed(context, '/login');
  608. }
  609. if(value == 'backup'){
  610. if(lastDownload != null && lastDownload != '' ){
  611. bool isBackup = await showDialog(context: context,builder: (context)=>AlertDialog(
  612. title: Text('Backup Data ?'),
  613. content: Text('Backup data akan menghapus dan mengganti data backup unit dan cabang sebelumnya.'),
  614. actions: <Widget>[
  615. TextButton(
  616. child: Text('OK'),
  617. onPressed: ()async{
  618. Navigator.pop(context,true);
  619. },
  620. ),
  621. TextButton(
  622. child: Text('Cancel'),
  623. onPressed: ()=>Navigator.pop(context,false),
  624. )
  625. ],
  626. ));
  627. if(isBackup??false){
  628. var result = await DBHelper.database.backupDb(context);
  629. util.showFlushbar(context, result['MSG'],color: result["STATUS"]==1?Colors.grey:Colors.red);
  630. }
  631. }
  632. else{
  633. util.showFlushbar(context, "Data Unit cabang tidak ditemukan. Silakan get data terlbih dahulu.");
  634. }
  635. }
  636. if(value == 'restore'){
  637. if(prefs.getString(keyClass.stock_id) == null){
  638. util.showFlushbar(context, "Data Unit cabang tidak ditemukan. Silakan get data terlbih dahulu.");
  639. }
  640. else{
  641. if(prefs.getString(keyClass.stock_id) == prefs.getString(keyClass.backup_stock_id)){
  642. String company = prefs.getString(keyClass.company);
  643. String stock_taking_id = prefs.getString(keyClass.stock_id);
  644. String stockState = '';
  645. if(company!=null&&stock_taking_id!=null){
  646. var result = await util.JsonDataPostRaw({"company":company,"stockTakingId":stock_taking_id}, '${prefs.getString(keyClass.hostAddress)}/stock_taking/state/');
  647. if(result['STATUS']==1){
  648. stockState = result['DATA'];
  649. }
  650. }
  651. if(['Open','Submitted'].contains(stockState)){
  652. bool isRestore = await showDialog(context: context,builder: (context)=>AlertDialog(
  653. title: Text('Restore Data ?'),
  654. content: Text('Restore data akan menghapus dan mengganti data unit dan cabang yang ada dengan data backup.'),
  655. actions: <Widget>[
  656. TextButton(
  657. child: Text('OK'),
  658. onPressed: ()async{
  659. Navigator.pop(context,true);
  660. },
  661. ),
  662. TextButton(
  663. child: Text('Cancel'),
  664. onPressed: ()=>Navigator.pop(context,false),
  665. )
  666. ],
  667. ));
  668. if(isRestore??false){
  669. var response;
  670. bool isclear;
  671. Directory documentsDirectory = await getApplicationDocumentsDirectory();
  672. String path = join(documentsDirectory.path, "UnitStocking.db");
  673. File db = File(path);
  674. if(db.existsSync()){
  675. isclear = await clearData(context);
  676. }
  677. else{
  678. isclear = true;
  679. }
  680. if(isclear??false){
  681. var result = await DBHelper.database.restoreDb(context);
  682. if(result["STATUS"]==1){
  683. await prefs.remove(keyClass.lastDownload);
  684. await prefs.remove(keyClass.lastUpload);
  685. await prefs.remove(keyClass.targetProccess);
  686. await prefs.remove(keyClass.submitProccess);
  687. setState(() {
  688. lastUpload = '';
  689. lastDownload = '';
  690. timeString = '';
  691. });
  692. valueTab value = await DBHelper.database.getValue(keyClass.tgl_start);
  693. if(value != null)await prefs.setString(keyClass.lastDownload, DateFormat('dd-MM-yyyy HH:mm:ss').parse(value.value).toIso8601String());
  694. else {
  695. await prefs.setString(keyClass.lastDownload, DateTime.now().toIso8601String());
  696. }
  697. value = await DBHelper.database.getValue(keyClass.stock_id);
  698. if(value != null) await prefs.setString(keyClass.stock_id,value.value);
  699. else {
  700. await prefs.setString(keyClass.stock_id,prefs.getString(keyClass.backup_stock_id));
  701. }
  702. loadState();
  703. setState(() {
  704. lastDownload = prefs.getString(keyClass.lastDownload);
  705. });
  706. }
  707. response = result["MSG"];
  708. }
  709. if(response != null)util.showFlushbar(context, response);
  710. }
  711. }
  712. else{
  713. util.showFlushbar(context, "Stocking Unit sudah selesai dan tidak perlu di restore");
  714. }
  715. }
  716. else {
  717. util.showFlushbar(context, "File Backup tidak ditemukan atau sudah selesai");
  718. }
  719. }
  720. }
  721. },
  722. ),
  723. ],
  724. ),
  725. ),
  726. (prefs.getString(keyClass.stock_id)==null)?Container():Padding(
  727. padding: const EdgeInsets.only(top: 8,right: 8),
  728. child: Container(
  729. decoration: BoxDecoration(
  730. color: Colors.indigo.withOpacity(0.9),
  731. borderRadius: BorderRadius.circular(8)
  732. // border: Border.all(),
  733. ),
  734. padding: EdgeInsets.all(8),
  735. child: Row(
  736. mainAxisSize: MainAxisSize.min,
  737. mainAxisAlignment: MainAxisAlignment.end,
  738. crossAxisAlignment: CrossAxisAlignment.center,
  739. children: <Widget>[
  740. Text('Status : ',style: TextStyle(color: Colors.white),),
  741. Text(state??'-',style: TextStyle(fontWeight: FontWeight.bold,color: Colors.white),),
  742. ],
  743. ),
  744. ),
  745. ),
  746. Expanded(
  747. child: Container(
  748. child:
  749. GridView.count(
  750. padding: EdgeInsets.all(10),
  751. crossAxisSpacing: 10,
  752. mainAxisSpacing: 10,
  753. crossAxisCount: 2,
  754. children: <Widget>[
  755. AbsorbPointer(
  756. absorbing: isLoading,
  757. child: InkWell(
  758. splashColor: Colors.black,
  759. onTap: ()async{
  760. bool getData = await showDialog(
  761. context: context,
  762. builder: (context)=>AlertDialog(
  763. title: Text("Get Data Units?"),
  764. content: Text('Fetch data unit for stocking'),
  765. actions: <Widget>[
  766. TextButton(
  767. child: Text('OK'),
  768. onPressed: (){
  769. Navigator.pop(context,true);
  770. },
  771. ),
  772. TextButton(
  773. child: Text('Cancel'),
  774. onPressed: (){
  775. Navigator.pop(context,false);
  776. },
  777. )
  778. ],
  779. )
  780. );
  781. if(getData??false){
  782. setState(() {
  783. isLoading = true;
  784. });
  785. var a = Stopwatch();
  786. a.start();
  787. await Future.delayed(Duration(milliseconds: 200));
  788. bool isclear;
  789. Directory documentsDirectory = await getApplicationDocumentsDirectory();
  790. String path = join(documentsDirectory.path, "UnitStocking.db");
  791. File db = File(path);
  792. if(db.existsSync()){
  793. isclear = await clearData(context);
  794. }
  795. else{
  796. isclear = true;
  797. }
  798. if(isclear??false){
  799. print('fetching');
  800. util.showLoading(context);
  801. file_Trans_Handler trans = new file_Trans_Handler();
  802. // trans.downloadFile('UnitStocking.db',"http://172.16.1.8:14002/getSqliteDbtest/TBS/02");
  803. trans.downloadFile('UnitStocking.db',"${prefs.getString(keyClass.hostAddress)}/stock_taking/get_units/${prefs.getString(keyClass.company)}/${prefs.getString(keyClass.cabang_id)}");
  804. progressDLStream = trans.progress.listen((value)async {
  805. if(progressDL==null) {
  806. // print(['test',value]);
  807. if(value!=null) Navigator.pop(context);
  808. }
  809. setState(() {
  810. progressDL = (value!=-1.0)?value:null;
  811. });
  812. if(value!=null&&value >= 1.0) {
  813. progressDLStream.cancel();
  814. progressDL = null;
  815. setState(() {
  816. lastDownload = DateTime.now().toIso8601String();
  817. });
  818. await prefs.setString(keyClass.lastDownload, lastDownload);
  819. await DBHelper.database.closeDb();
  820. await DBHelper.database.insertUpdateValue(new valueTab(name: keyClass.tgl_start,value: DateFormat('dd-MM-yyyy HH:mm:ss').format(DateTime.parse(lastDownload))));
  821. await DBHelper.database.insertUpdateValue(new valueTab(name: 'TGL_STOCK_TAKING',value: DateFormat('dd-MM-yyyy').format(DateTime.parse(lastDownload))));
  822. util.showFlushbar(context,'Data downloaded');
  823. loadState();
  824. a.stop();
  825. if(a.elapsed.inSeconds<3){
  826. await Future.delayed(Duration(seconds: 3-a.elapsed.inSeconds));
  827. }
  828. setState(() {
  829. isLoading = false;
  830. });
  831. }
  832. if(value==-1.0){
  833. setState(() {
  834. isLoading = false;
  835. });
  836. util.showFlushbar(context,trans.error??'Data download error',color: Colors.red);
  837. }
  838. });
  839. // Navigator.popUntil(context, ModalRoute.withName('/home'));
  840. }
  841. }
  842. },
  843. child: Container(
  844. padding: EdgeInsets.all(5),
  845. decoration: BoxDecoration(
  846. boxShadow: [
  847. BoxShadow(
  848. color: Colors.grey.withOpacity(0.5),
  849. spreadRadius: 2,
  850. blurRadius: 2,
  851. offset: Offset(0, 0), // changes position of shadow
  852. ),
  853. ],
  854. borderRadius: BorderRadius.all(Radius.circular(5.0)),
  855. color: Colors.green.withAlpha(220).withOpacity(0.7),
  856. ),
  857. child: Stack(
  858. children: <Widget>[
  859. Container(
  860. alignment: (progressDL!=null)?Alignment.bottomCenter:Alignment.bottomLeft,
  861. padding: EdgeInsets.only(left: 10,right: 10,top: 10,bottom: 15),
  862. child: (progressDL!=null)?Column(
  863. mainAxisSize: MainAxisSize.min,
  864. children: <Widget>[
  865. LinearProgressIndicator(
  866. value: progressDL,
  867. ),
  868. Text('${(progressDL*100).floor()}%',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold),)
  869. ],
  870. ):(lastDownload=='')?null:Text('Last download : ${DateFormat('dd MMM yyyy HH:mm').format(DateTime.parse(lastDownload))}',style: TextStyle(color: Colors.white,fontSize: 11,fontWeight: FontWeight.bold)),
  871. ),
  872. Positioned.fill(
  873. child: Column(
  874. mainAxisAlignment: MainAxisAlignment.center,
  875. children: <Widget>[
  876. Icon(Icons.file_upload,size: MediaQuery.of(context).size.width/6,color: Colors.white,),
  877. SizedBox(height: 5,),
  878. Text('Get Data Master',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 16),),
  879. ],
  880. ),
  881. ),
  882. ],
  883. ),
  884. ),
  885. ),
  886. ),
  887. InkWell(
  888. splashColor: Colors.black,
  889. onTap: ()async{
  890. await Future.delayed(Duration(milliseconds: 200));
  891. if(lastDownload!=''){
  892. Navigator.pushNamed(context, '/stocking');
  893. }
  894. else{
  895. util.showFlushbar(context, 'Data Master tidak ditemukan. Get data master dulu.');
  896. }
  897. },
  898. child: Container(
  899. padding: EdgeInsets.all(5),
  900. decoration: BoxDecoration(
  901. boxShadow: [
  902. BoxShadow(
  903. color: Colors.grey.withOpacity(0.5),
  904. spreadRadius: 2,
  905. blurRadius: 2,
  906. offset: Offset(0, 0), // changes position of shadow
  907. ),
  908. ],
  909. borderRadius: BorderRadius.all(Radius.circular(5.0)),
  910. color: Colors.blueGrey.withAlpha(230).withOpacity(0.8),
  911. ),
  912. child: Column(
  913. mainAxisAlignment: MainAxisAlignment.center,
  914. children: <Widget>[
  915. Icon(Icons.receipt,size: MediaQuery.of(context).size.width/6,color: Colors.white,),
  916. SizedBox(height: 5,),
  917. Text('Stocking',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 16),)
  918. ],
  919. ),
  920. ),
  921. ),
  922. InkWell(
  923. splashColor: Colors.black,
  924. onTap: ()async{
  925. if(lastDownload!=''){
  926. await DBHelper.database.insertUpdateValue(new valueTab(name: 'TGL_SELESAI',value: DateFormat('dd-MM-yyyy HH:mm:ss').format(new DateTime.now())));
  927. await DBHelper.database.closeDb();
  928. file_Trans_Handler trans = new file_Trans_Handler();
  929. bool popped = false;
  930. util.showLoading(context,onwillpop:()async{
  931. await trans.cancel();
  932. popped = true;
  933. return true;
  934. });
  935. var upload = await trans.uploadFile('UnitStocking.db',"${prefs.getString(keyClass.hostAddress)}/stock_taking/upload/",prefs.getString(keyClass.company),prefs.getString(keyClass.cabang_id));
  936. if(!popped){
  937. Navigator.pop(context);
  938. util.showFlushbar(context, upload['DATA'],color:(upload['STATUS']!=1)?Colors.red:Colors.grey);
  939. if(upload['STATUS']==1){
  940. setState(() {
  941. lastUpload = new DateTime.now().toIso8601String();
  942. });
  943. prefs.setString(keyClass.lastUpload, lastUpload);
  944. prefs.setString(keyClass.targetProccess, upload[keyClass.targetProccess]);
  945. }
  946. }
  947. }
  948. else{
  949. util.showFlushbar(context, "Belum ada data yang disimpan.",color: Colors.red);
  950. }
  951. },
  952. child: Container(
  953. padding: EdgeInsets.all(5),
  954. decoration: BoxDecoration(
  955. boxShadow: [
  956. BoxShadow(
  957. color: Colors.grey.withOpacity(0.5),
  958. spreadRadius: 2,
  959. blurRadius: 2,
  960. offset: Offset(0, 0), // changes position of shadow
  961. ),
  962. ],
  963. borderRadius: BorderRadius.all(Radius.circular(5.0)),
  964. color: Colors.indigo.withAlpha(220).withOpacity(0.7),
  965. ),
  966. child: Stack(
  967. children: <Widget>[
  968. Container(
  969. alignment: (progressUL!=null)?Alignment.bottomCenter:Alignment.bottomLeft,
  970. padding: EdgeInsets.only(left: 10,right: 10,top: 10,bottom: 0),
  971. child: (progressUL!=null)?Column(
  972. mainAxisSize: MainAxisSize.min,
  973. children: <Widget>[
  974. LinearProgressIndicator(
  975. value: progressUL,
  976. ),
  977. Text('${(progressUL*100).floor()}%',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold),)
  978. ],
  979. ):(lastUpload=='')?null:Text('Last upload : ${DateFormat('dd MMM yyyy HH:mm').format(DateTime.parse(lastUpload))}\n${(timeString!='')?'Duration: $timeString':''}',style: TextStyle(color: Colors.white,fontSize: 11,fontWeight: FontWeight.bold)),
  980. ),
  981. Positioned.fill(
  982. child: Column(
  983. mainAxisAlignment: MainAxisAlignment.center,
  984. children: <Widget>[
  985. Icon(Icons.file_upload,size: MediaQuery.of(context).size.width/6,color: Colors.white,),
  986. SizedBox(height: 5,),
  987. Text('Send Data Stokan',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 16),),
  988. ],
  989. ),
  990. ),
  991. ],
  992. ),
  993. ),
  994. ),
  995. (prefs.getString(keyClass.targetProccess)==null&&prefs.getBool(keyClass.submitProccess)==null)?InkWell(
  996. splashColor: Colors.black,
  997. onTap: ()async{
  998. await Future.delayed(Duration(milliseconds: 200));
  999. await clearData(context);
  1000. },
  1001. child: Container(
  1002. padding: EdgeInsets.all(5),
  1003. decoration: BoxDecoration(
  1004. boxShadow: [
  1005. BoxShadow(
  1006. color: Colors.grey.withOpacity(0.5),
  1007. spreadRadius: 2,
  1008. blurRadius: 2,
  1009. offset: Offset(0, 0), // changes position of shadow
  1010. ),
  1011. ],
  1012. borderRadius: BorderRadius.all(Radius.circular(5.0)),
  1013. color: Colors.red.withAlpha(200).withOpacity(0.7),
  1014. ),
  1015. child: Column(
  1016. mainAxisAlignment: MainAxisAlignment.center,
  1017. children: <Widget>[
  1018. Icon(Icons.restore_from_trash,size: MediaQuery.of(context).size.width/6,color: Colors.white,),
  1019. SizedBox(height: 5,),
  1020. Text('Clear Data',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 16),)
  1021. ],
  1022. ),
  1023. ),
  1024. ):
  1025. (prefs.getString(keyClass.targetProccess)!=null)?InkWell(
  1026. onTap: ()async{
  1027. bool result = await showDialog(context: context,builder: (context)=>WillPopScope(
  1028. onWillPop: ()async{
  1029. Navigator.pop(context,false);
  1030. return false;
  1031. },
  1032. child: AlertDialog(
  1033. title: Text('Process Data ?'),
  1034. content: Text('Proceed to unpack the uploaded data.'),
  1035. actions: <Widget>[
  1036. TextButton(
  1037. child: Text('OK'),
  1038. onPressed: ()async{
  1039. Navigator.pop(context,true);
  1040. },
  1041. ),
  1042. TextButton(
  1043. child: Text('Cancel'),
  1044. onPressed: (){Navigator.pop(context,false);},
  1045. )
  1046. ],
  1047. ),
  1048. ));
  1049. if(result){
  1050. util.showLoading(context);
  1051. var unpack = await util.JsonDataPutRaw({"userId":prefs.getString(keyClass.loginId),"cabangId":prefs.getString(keyClass.cabang_id),"company":prefs.getString(keyClass.company),"dbPath":prefs.getString(keyClass.targetProccess)}, '${prefs.getString(keyClass.hostAddress)}/stock_taking/add_collection/');
  1052. Navigator.pop(context);
  1053. util.showFlushbar(context, unpack['DATA'],color:(unpack['STATUS']!=1)?Colors.red:Colors.grey);
  1054. if(unpack['STATUS']==1){
  1055. prefs.remove(keyClass.targetProccess);
  1056. prefs.setBool(keyClass.submitProccess,true);
  1057. }
  1058. setState(() {
  1059. });
  1060. }
  1061. },
  1062. child: Container(
  1063. padding: EdgeInsets.all(5),
  1064. decoration: BoxDecoration(
  1065. boxShadow: [
  1066. BoxShadow(
  1067. color: Colors.grey.withOpacity(0.5),
  1068. spreadRadius: 2,
  1069. blurRadius: 2,
  1070. offset: Offset(0, 0), // changes position of shadow
  1071. ),
  1072. ],
  1073. borderRadius: BorderRadius.all(Radius.circular(5.0)),
  1074. color: Colors.orangeAccent.withAlpha(230).withOpacity(0.7),
  1075. ),
  1076. child: Column(
  1077. mainAxisAlignment: MainAxisAlignment.center,
  1078. children: <Widget>[
  1079. Icon(Icons.arrow_forward,size: MediaQuery.of(context).size.width/6,color: Colors.white,),
  1080. SizedBox(height: 5,),
  1081. Text('Process Units',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 16),)
  1082. ],
  1083. ),
  1084. ),
  1085. ):
  1086. InkWell(
  1087. onTap: ()async{
  1088. bool result = await showDialog(context: context,builder: (context)=>WillPopScope(
  1089. onWillPop: ()async{
  1090. Navigator.pop(context,false);
  1091. return false;
  1092. },
  1093. child: AlertDialog(
  1094. title: Text('Submit Data ?'),
  1095. content: Text('Submit the uploaded data.'),
  1096. actions: <Widget>[
  1097. TextButton(
  1098. child: Text('Submit'),
  1099. onPressed: ()async{
  1100. Navigator.pop(context,true);
  1101. },
  1102. ),
  1103. TextButton(
  1104. child: Text('Cancel'),
  1105. onPressed: (){Navigator.pop(context,false);},
  1106. )
  1107. ],
  1108. ),
  1109. ));
  1110. if(result){
  1111. util.showLoading(context);
  1112. if(prefs.getString(keyClass.stock_id) == null)
  1113. {
  1114. valueTab value = await DBHelper.database.getValue(keyClass.stock_id);
  1115. await prefs.setString(keyClass.stock_id, value.value);
  1116. }
  1117. var submits = await util.JsonDataPostRaw({"stockTakingId":prefs.getString(keyClass.stock_id),"company":prefs.getString(keyClass.company),"user_id":prefs.getString(keyClass.loginId)}, '${prefs.getString(keyClass.hostAddress)}/stock_taking/submit/');
  1118. Navigator.pop(context);
  1119. util.showFlushbar(context, submits['DATA'],color:(submits['STATUS']!=1)?Colors.red:Colors.grey);
  1120. if(submits['STATUS']==1){
  1121. loadState();
  1122. prefs.remove(keyClass.submitProccess);
  1123. }
  1124. setState(() {
  1125. });
  1126. }
  1127. },
  1128. child: Container(
  1129. padding: EdgeInsets.all(5),
  1130. decoration: BoxDecoration(
  1131. boxShadow: [
  1132. BoxShadow(
  1133. color: Colors.grey.withOpacity(0.5),
  1134. spreadRadius: 2,
  1135. blurRadius: 2,
  1136. offset: Offset(0, 0), // changes position of shadow
  1137. ),
  1138. ],
  1139. borderRadius: BorderRadius.all(Radius.circular(5.0)),
  1140. color: Colors.lightGreen.withAlpha(230),
  1141. ),
  1142. child: Column(
  1143. mainAxisAlignment: MainAxisAlignment.center,
  1144. children: <Widget>[
  1145. Icon(Icons.arrow_forward,size: MediaQuery.of(context).size.width/6,color: Colors.white,),
  1146. SizedBox(height: 5,),
  1147. Text('Submit Process',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 16),)
  1148. ],
  1149. ),
  1150. ),
  1151. ),
  1152. (prefs.getString(keyClass.targetProccess)!=null||(prefs.getBool(keyClass.submitProccess)!=null&&prefs.getBool(keyClass.submitProccess)))?InkWell(
  1153. splashColor: Colors.black,
  1154. onTap: ()async{
  1155. await Future.delayed(Duration(milliseconds: 200));
  1156. await clearData(context);
  1157. },
  1158. child: Container(
  1159. padding: EdgeInsets.all(5),
  1160. decoration: BoxDecoration(
  1161. boxShadow: [
  1162. BoxShadow(
  1163. color: Colors.grey.withOpacity(0.5),
  1164. spreadRadius: 2,
  1165. blurRadius: 2,
  1166. offset: Offset(0, 0), // changes position of shadow
  1167. ),
  1168. ],
  1169. borderRadius: BorderRadius.all(Radius.circular(5.0)),
  1170. color: Colors.red.withAlpha(200),
  1171. ),
  1172. child: Column(
  1173. mainAxisAlignment: MainAxisAlignment.center,
  1174. children: <Widget>[
  1175. Icon(Icons.restore_from_trash,size: MediaQuery.of(context).size.width/6,color: Colors.white,),
  1176. SizedBox(height: 5,),
  1177. Text('Clear Data',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 16),)
  1178. ],
  1179. ),
  1180. ),
  1181. ):Container(),
  1182. ],
  1183. )),
  1184. ),
  1185. ],
  1186. ),
  1187. bottomSheet: Container(height: 22,alignment: Alignment.bottomRight,child: Opacity(opacity: 0.5,child: Padding(padding: EdgeInsets.all(5),child: Text((lastDownload!='')?'Master Data Downloaded':'No Master Data Found',style: TextStyle(fontSize: 12),)))),
  1188. ),
  1189. );
  1190. }
  1191. }