Flutter app for Asset Management
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

553 lignes
26 KiB

  1. import 'dart:async';
  2. import 'dart:convert';
  3. import 'dart:io';
  4. import 'package:assetstock/util/download_Upload_Handler.dart';
  5. import 'package:path/path.dart';
  6. import 'package:flutter/cupertino.dart';
  7. import 'package:flutter/material.dart';
  8. import 'package:path_provider/path_provider.dart';
  9. import 'main.dart';
  10. import 'util/prefsKey.dart';
  11. import 'util/dbHandler.dart';
  12. class Home extends StatefulWidget {
  13. Home({Key key}) : super(key: key);
  14. @override
  15. _HomeState createState() => _HomeState();
  16. }
  17. class _HomeState extends State<Home> {
  18. List<Widget> Menus = [];
  19. final hostAddress = new TextEditingController();
  20. StreamSubscription _dlulStream;
  21. double progress,progressDL;
  22. loadMenu()async{
  23. Menus.add(Padding(
  24. padding: const EdgeInsets.all(8.0),
  25. child: Container(
  26. decoration: BoxDecoration(
  27. color: Colors.white,
  28. borderRadius: BorderRadius.circular(5)
  29. ),
  30. child: Text('Get Data'),
  31. ),
  32. ));
  33. setState(() {
  34. });
  35. }
  36. @override
  37. void initState() {
  38. // TODO: implement initState
  39. super.initState();
  40. WidgetsBinding.instance.addPostFrameCallback((_) async {
  41. // await loadMenu();
  42. });
  43. }
  44. clearData(context)async{
  45. String errMsg;
  46. Directory documentsDirectory = await getApplicationDocumentsDirectory();
  47. String path = join(documentsDirectory.path, "assets.db");
  48. File db = File(path);
  49. if(db.existsSync()){
  50. bool result = await showDialog(context: context,builder: (context)=>WillPopScope(
  51. onWillPop: ()async{
  52. Navigator.pop(context,false);
  53. return false;
  54. },
  55. child: AlertDialog(
  56. title: Text('Clear Data ?'),
  57. content: Text('Proceed to clear any remaining units data on this device?'),
  58. actions: <Widget>[
  59. FlatButton(
  60. child: Text('Proceed'),
  61. onPressed: ()async{
  62. util.showLoading(context);
  63. await Future.sync(()async{
  64. await prefs.remove(keyClass.dbName);
  65. // await prefs.setString(keyClass.lastDownload, null);
  66. // await prefs.setString(keyClass.lastUpload, null);
  67. // await prefs.setString(keyClass.targetProccess, null);
  68. setState(() {
  69. // lastUpload = '';
  70. // lastDownload = '';
  71. // timeString = '';
  72. });
  73. // var result = await DBHelper.database.deleteAll();
  74. // if(result!=null) {
  75. // if(result!=null){
  76. try{
  77. await DBHelper.database.closeDb();
  78. db.deleteSync();
  79. }
  80. catch(e){
  81. print(e);
  82. util.showToast('ERROR','Failed to delete database file');
  83. }
  84. // }
  85. // else{
  86. // errMsg = 'Failed to clear unit data';
  87. // }
  88. // }
  89. // else{
  90. // errMsg = 'Failed to clear unit data';
  91. // }
  92. });
  93. Navigator.pop(context);
  94. Navigator.pop(context,true);
  95. util.showToast(errMsg==null?"SUCCESS":"ERROR",errMsg??'Data Cleared');
  96. },
  97. ),
  98. FlatButton(
  99. child: Text('Cancel'),
  100. onPressed: (){Navigator.pop(context,false);},
  101. )
  102. ],
  103. ),
  104. ));
  105. return result;
  106. }
  107. else return true;
  108. }
  109. @override
  110. Widget build(BuildContext context) {
  111. return Scaffold(
  112. floatingActionButton: Padding(
  113. padding: const EdgeInsets.only(bottom:45.0),
  114. child: FloatingActionButton(
  115. onPressed: ()async{
  116. Directory documentsDirectory = await getApplicationDocumentsDirectory();
  117. String path = join(documentsDirectory.path, "assets.db");
  118. File db = File(path);
  119. if(db.existsSync()){
  120. Navigator.pushNamed(context, '/logs');
  121. }
  122. else{
  123. util.showToast("ALERT", 'Get data Master first');
  124. }
  125. },
  126. child: Icon(Icons.description,size: 30,),
  127. ),
  128. ),
  129. body: Container(
  130. color: Colors.grey.withOpacity(0.3),
  131. child:
  132. // (Menus.length==0)?Container(alignment: Alignment.center,
  133. // child: Text('Empty',
  134. // style: TextStyle(fontSize: 20,color: Colors.black38,fontWeight: FontWeight.bold),),)
  135. // :
  136. Column(
  137. children: <Widget>[
  138. Expanded(
  139. flex: 1,
  140. child: Container(
  141. padding: const EdgeInsets.only(left: 10,top:10,right: 5),
  142. alignment: Alignment.bottomCenter,
  143. child: Row(
  144. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  145. children: <Widget>[
  146. Row(
  147. children: <Widget>[
  148. Icon(Icons.dashboard,color: Colors.blueGrey,size: 20,),
  149. SizedBox(width: 5,),
  150. Text('Menu')
  151. ],
  152. ),
  153. PopupMenuButton(
  154. itemBuilder: (context)=>[
  155. PopupMenuItem(
  156. value: "changeAddress",
  157. child: Row(
  158. children: <Widget>[
  159. Icon(Icons.network_wifi,color: Colors.blueGrey,),
  160. SizedBox(width: 10,),
  161. Text('Change Host Address',style: TextStyle(color: Colors.blueGrey,fontWeight: FontWeight.w500),)
  162. ],
  163. ),
  164. )
  165. ],
  166. onSelected: (value)async{
  167. if(value == "changeAddress"){
  168. hostAddress.text = prefs.getString(keyClass.hostAddress)??'https://asset.thamringroup.web.id';
  169. await showDialog(context: context,builder: (context)=>AlertDialog(
  170. title: Text('Set IP Address'),
  171. content: TextField(
  172. controller: hostAddress,
  173. onSubmitted: (value){
  174. prefs.setString(keyClass.hostAddress,(value=='')?'https://asset.thamringroup.web.id':value);
  175. Navigator.pop(context);
  176. },
  177. ),
  178. actions: <Widget>[
  179. FlatButton(
  180. child: Text('OK'),
  181. onPressed: (){
  182. prefs.setString(keyClass.hostAddress,(hostAddress.text=='')?'https://asset.thamringroup.web.id':hostAddress.text);
  183. Navigator.pop(context);
  184. },
  185. )
  186. ],
  187. ));
  188. setState(() {
  189. });
  190. }
  191. },
  192. child: Padding(
  193. padding: const EdgeInsets.all(8.0),
  194. child: Icon(Icons.clear_all,color: Colors.blueGrey,size: 20,),
  195. ),
  196. ),
  197. ],
  198. ),
  199. ),
  200. ),
  201. Flexible(
  202. flex: 10,
  203. child: Container(
  204. alignment: Alignment.topCenter,
  205. child: GridView.count(
  206. padding: EdgeInsets.all(0),
  207. crossAxisCount: 2,
  208. children: [
  209. InkWell(
  210. onTap: ()async{
  211. String Address = prefs.getString(keyClass.hostAddress);
  212. // await Future.delayed(Duration(milliseconds: 300));
  213. util.showLoading(context,dissmissable: false);
  214. var bUnits = await util.JsonDataPostRaw({}, "${Address??"https://asset.thamringroup.web.id"}/admin/getBisnisList",timeout: true,duration: 5);
  215. Navigator.pop(context);
  216. if(bUnits["STATUS"]==1){
  217. var selectedBisnis= bUnits["DATA"][0]["id"];
  218. var bisnisPicked = await showDialog(context: context,builder: (context)=>StatefulBuilder(
  219. builder: (context,setState)=>AlertDialog(
  220. title: Text('Pick Bisnis Unit'),
  221. content: DropdownButtonFormField(
  222. onChanged: (value)async{
  223. setState(() {
  224. selectedBisnis = value;
  225. });
  226. },
  227. value: selectedBisnis,
  228. items: new List<DropdownMenuItem<dynamic>>.from(bUnits['DATA'].map((value){
  229. String showText = value["name"];
  230. if(showText.length>30) showText = showText.substring(0,30);
  231. return DropdownMenuItem(
  232. child: Text(showText),
  233. value: value["id"],
  234. );
  235. })),
  236. ),
  237. actions: <Widget>[
  238. FlatButton(
  239. onPressed: ()async{
  240. Navigator.pop(context,true);
  241. },
  242. child: Text('Next'),
  243. ),
  244. FlatButton(
  245. onPressed: ()async{
  246. Navigator.pop(context,false);
  247. },
  248. child: Text('Cancel'),
  249. )
  250. ],
  251. ),
  252. ));
  253. if(bisnisPicked??false){
  254. util.showLoading(context,dissmissable: false);
  255. var result = await util.JsonDataPostRaw({"bUnit":selectedBisnis}, "${Address??"https://asset.thamringroup.web.id"}/admin/getrefDbList");
  256. Navigator.pop(context);
  257. if(result['STATUS']==1){
  258. bool isClear = await clearData(context);
  259. if(isClear??false){
  260. String selected = result['DATA'][0]["fullName"];
  261. bool res =await showDialog(context: context,builder: (context)=>StatefulBuilder(
  262. builder: (context,setState)=>AlertDialog(
  263. title: Text('Pick Database'),
  264. content: DropdownButtonFormField(
  265. onChanged: (value){
  266. setState(() {
  267. selected = value;
  268. });
  269. },
  270. value: selected,
  271. items: new List<DropdownMenuItem<dynamic>>.from(result['DATA'].map((value){
  272. String showText = value["name"];
  273. if(showText.length>20) showText = showText.substring(0,20);
  274. return DropdownMenuItem(
  275. child: Text(showText),
  276. value: value["fullName"],
  277. );
  278. })),
  279. ),
  280. actions: <Widget>[
  281. FlatButton(
  282. onPressed: ()async{
  283. Navigator.pop(context,true);
  284. },
  285. child: Text('Get'),
  286. ),
  287. FlatButton(
  288. onPressed: ()async{
  289. Navigator.pop(context,false);
  290. },
  291. child: Text('Cancel'),
  292. )
  293. ],
  294. ),
  295. ));
  296. if(res??false){
  297. // util.showLoading(context,dissmissable: false);
  298. await prefs.setString(keyClass.dbName,selected);
  299. file_Trans_Handler trans = new file_Trans_Handler();
  300. await trans.downloadFile("assets.db", "${Address??"https://asset.thamringroup.web.id"}/admin/downloadDb/$selectedBisnis/$selected");
  301. _dlulStream = trans.progress.listen((value)async {
  302. setState(() {
  303. progressDL = (value!=-1.0)?value:null;
  304. });
  305. if(value!=null&&value >= 1.0) {
  306. _dlulStream.cancel();
  307. progressDL = null;
  308. // setState(() {
  309. // lastDownload = DateTime.now().toIso8601String();
  310. // });
  311. // await prefs.setString(keyClass.lastDownload, lastDownload);
  312. // await DBHelper.database.insertUpdateValue(new valueTab(name: 'TGL_START',value: DateFormat('dd-MM-yyyy HH:mm:ss').format(DateTime.parse(lastDownload))));
  313. // await DBHelper.database.insertUpdateValue(new valueTab(name: 'TGL_STOCK_TAKING',value: DateFormat('dd-MM-yyyy').format(DateTime.parse(lastDownload))));
  314. // await DBHelper.database.closeDb();
  315. // var allUnits = await DBHelper.database.getAllAsset();
  316. // print('${allUnits.length} Units');
  317. util.showToast('ALERT','Data Downloaded');
  318. // await DBHelper.database.setOpenState();
  319. }
  320. if(value==-1.0){
  321. util.showToast('ALERT','Data Error ${trans.error}');
  322. }
  323. });
  324. // Navigator.pop(context);
  325. setState(() {
  326. });
  327. }
  328. }
  329. }
  330. else{
  331. await util.showToast("ERROR",result['ERROR']??"Database tidak ditemukan");
  332. }
  333. }
  334. }
  335. else{
  336. await util.showToast("ERROR",bUnits['DATA']??'not responding');
  337. }
  338. },
  339. child: Padding(
  340. padding: const EdgeInsets.only(left: 10,top:10,right: 5),
  341. child: Container(
  342. decoration: BoxDecoration(
  343. color: Colors.white,
  344. borderRadius: BorderRadius.circular(10)
  345. ),
  346. child: Column(
  347. mainAxisAlignment: MainAxisAlignment.center,
  348. children: <Widget>[
  349. Expanded(
  350. flex: 4,
  351. child: Container(alignment: Alignment.center,child: (progressDL==null)?Icon(Icons.add_to_home_screen,size: 100,color: Colors.blueGrey,):Stack(
  352. children: <Widget>[
  353. Container(width: 100,height: 100,child: CircularProgressIndicator(backgroundColor: Color(0xFFB4B4B4),valueColor:new AlwaysStoppedAnimation<Color>(Colors.blueGrey),value: progressDL,)),
  354. Container(width: 100,height: 100,alignment: Alignment.center,child: Text("${(progressDL*100).floor().toString()}%",style: TextStyle(color: Colors.blueGrey,fontWeight: FontWeight.bold,fontSize: 25),),)
  355. ],
  356. )),
  357. ),
  358. Flexible(
  359. flex: 2,
  360. child: Text('Get Data Master',style: TextStyle(color: Colors.blueGrey,fontSize: 18,fontWeight: FontWeight.bold),),
  361. ),
  362. ],
  363. ),
  364. ),
  365. ),
  366. ),
  367. Padding(
  368. padding: const EdgeInsets.only(left: 5,top:10,right: 10),
  369. child: Material(
  370. color: Colors.white,
  371. child: InkWell(
  372. onTap: ()async{
  373. await Future.delayed(Duration(milliseconds: 300));
  374. Directory documentsDirectory = await getApplicationDocumentsDirectory();
  375. String path = join(documentsDirectory.path, "assets.db");
  376. File db = File(path);
  377. if(db.existsSync())Navigator.pushNamed(context, '/stocking');
  378. else{
  379. util.showToast('Alert', 'Please download data master first');
  380. }
  381. },
  382. child: Container(
  383. decoration: BoxDecoration(
  384. borderRadius: BorderRadius.circular(10)
  385. ),
  386. child: Column(
  387. mainAxisAlignment: MainAxisAlignment.center,
  388. children: <Widget>[
  389. Expanded(
  390. flex: 4,
  391. child: Container(alignment: Alignment.center,child: Icon(Icons.aspect_ratio,size: 100,color: Colors.blueGrey,)),
  392. ),
  393. Flexible(
  394. flex: 2,
  395. child: Text('Start Stocking',style: TextStyle(color: Colors.blueGrey,fontSize: 18,fontWeight: FontWeight.bold),),
  396. ),
  397. ],
  398. ),
  399. ),
  400. ),
  401. ),
  402. ),
  403. InkWell(
  404. onTap: ()async{
  405. final file = File(
  406. "${(await getApplicationDocumentsDirectory()).path}/assets.db");
  407. if(file.existsSync()){
  408. TextEditingController sendingUser = new TextEditingController();
  409. sendingUser.text = prefs.getString(keyClass.user)??'';
  410. bool isUserDefined = await showDialog(context: context,
  411. barrierDismissible: false,
  412. builder: (context)=>AlertDialog(
  413. title: Text('Sender'),
  414. content: TextField(
  415. controller: sendingUser,
  416. ),
  417. actions: [
  418. FlatButton(
  419. child: Text('Send'),
  420. onPressed: ()async{
  421. if(sendingUser.text!='') Navigator.pop(context,true);
  422. else Navigator.pop(context,false);
  423. },
  424. )
  425. ],
  426. ));
  427. if(isUserDefined??false){
  428. prefs.setString(keyClass.user, sendingUser.text);
  429. util.showToast("ALERT",'Preparing Data');
  430. await DBHelper.database.closeDb();
  431. file_Trans_Handler trans = new file_Trans_Handler();
  432. util.showToast("ALERT",'Sending Data');
  433. setState(() {
  434. progress = 0;
  435. });
  436. trans.uploadFile("assets.db", "${prefs.getString(keyClass.hostAddress)??"https://asset.thamringroup.web.id"}/admin/uploadSqliteDb",sendingUser.text,context);
  437. _dlulStream = trans.progress.listen((value) async {
  438. setState(() {
  439. progress = (value!=-1.0)?value:null;
  440. });
  441. if(value!=null&&value >= 1.0) {
  442. if(trans.error==''&&trans.isFinish){
  443. _dlulStream.cancel();
  444. progress = null;
  445. util.showToast("SUCCESS",(trans.success!='')?trans.success:'Data uploaded');
  446. }
  447. }
  448. if(value==-1.0&&trans.isFinish){
  449. _dlulStream.cancel();
  450. progress = null;
  451. util.showToast("ERROR",'Data upload error. ${trans.error}');
  452. }
  453. });
  454. }
  455. else util.showToast("ALERT",'Sending user not filled');
  456. }
  457. else{
  458. util.showToast("ALERT",'No database file found');
  459. }
  460. },
  461. child: Padding(
  462. padding: const EdgeInsets.only(left: 10,top:10,right: 5),
  463. child: Container(
  464. decoration: BoxDecoration(
  465. color: Colors.white,
  466. borderRadius: BorderRadius.circular(10)
  467. ),
  468. child: Column(
  469. mainAxisAlignment: MainAxisAlignment.center,
  470. children: <Widget>[
  471. Expanded(
  472. flex: 4,
  473. child: Container(alignment: Alignment.center,child: (progress==null)?Icon(Icons.send,size: 100,color: Colors.blueGrey,):Stack(
  474. children: <Widget>[
  475. Container(width: 100,height: 100,child: CircularProgressIndicator(backgroundColor: Color(0xFFB4B4B4),valueColor:new AlwaysStoppedAnimation<Color>(Colors.blueGrey),value: progress,)),
  476. Container(width: 100,height: 100,alignment: Alignment.center,child: Text("${(progress*100).floor().toString()}%",style: TextStyle(color: Colors.blueGrey,fontWeight: FontWeight.bold,fontSize: 25),),)
  477. ],
  478. )),
  479. ),
  480. Flexible(
  481. flex: 2,
  482. child: Text('Send Data',style: TextStyle(color: Colors.blueGrey,fontSize: 18,fontWeight: FontWeight.bold),),
  483. ),
  484. ],
  485. ),
  486. ),
  487. ),
  488. ),
  489. InkWell(
  490. onTap: ()async{
  491. Directory documentsDirectory = await getApplicationDocumentsDirectory();
  492. String path = join(documentsDirectory.path, "assets.db");
  493. File db = File(path);
  494. if(db.existsSync()) await clearData(context);
  495. else util.showToast('Alert', 'No database file found');
  496. },
  497. child: Padding(
  498. padding: const EdgeInsets.only(left: 5,top:10,right: 10),
  499. child: Container(
  500. decoration: BoxDecoration(
  501. color: Colors.white,
  502. borderRadius: BorderRadius.circular(10)
  503. ),
  504. child: Column(
  505. mainAxisAlignment: MainAxisAlignment.center,
  506. children: <Widget>[
  507. Expanded(
  508. flex: 4,
  509. child: Container(alignment: Alignment.center,child: Icon(Icons.delete,size: 100,color: Colors.blueGrey,)),
  510. ),
  511. Flexible(
  512. flex: 2,
  513. child: Text('Clear Data',style: TextStyle(color: Colors.blueGrey,fontSize: 18,fontWeight: FontWeight.bold),),
  514. ),
  515. ],
  516. ),
  517. ),
  518. ),
  519. ),
  520. ],
  521. ),
  522. ),
  523. ),
  524. Flexible(
  525. flex: 2,
  526. child: Container(
  527. padding: EdgeInsets.all(8),
  528. alignment: Alignment.bottomRight,
  529. child: Column(
  530. crossAxisAlignment: CrossAxisAlignment.end,
  531. mainAxisAlignment: MainAxisAlignment.end,
  532. children: <Widget>[
  533. Text((prefs.getString(keyClass.dbName)!=null)?"Master Data : ${prefs.getString(keyClass.dbName)}":'',style: TextStyle(color: Colors.blueGrey),),
  534. Text('Connected to ${prefs.getString(keyClass.hostAddress)??'https://asset.thamringroup.web.id'}',style: TextStyle(color: Colors.blueGrey),),
  535. ],
  536. ),
  537. ),
  538. ),
  539. ],
  540. ),
  541. ),
  542. );
  543. }
  544. }