flutter app untuk unitstock
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 

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