flutter app untuk unitstock
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

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