Flutter app for Asset Management
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 

585 rindas
25 KiB

  1. import 'dart:io';
  2. import 'util/photo_viewer.dart';
  3. import 'package:assetstock/util/dbHandler.dart';
  4. import 'package:flutter/material.dart';
  5. import 'package:image_picker/image_picker.dart';
  6. import 'main.dart';
  7. import 'util/Models.dart';
  8. import 'package:http/http.dart' as http;
  9. import 'util/prefsKey.dart';
  10. class AssetDetails extends StatefulWidget {
  11. // AssetDetails({Key key}) : super(key: key);
  12. int no;
  13. List<String>lokasi;
  14. AssetDetails({this.no,this.lokasi});
  15. @override
  16. _AssetDetailsState createState() => _AssetDetailsState();
  17. }
  18. class _AssetDetailsState extends State<AssetDetails> with TickerProviderStateMixin {
  19. final barCode = new TextEditingController();
  20. final prefixCode = new TextEditingController();
  21. final qty = new TextEditingController();
  22. final ket = new TextEditingController();
  23. TabController _controller;
  24. int _currentIndex;
  25. Asset _asset = new Asset();
  26. final focusNode = new FocusNode();
  27. bool isAppend = false;
  28. loadAsset()async{
  29. var blob = await DBHelper.database.getBlobbyNo(widget.no);
  30. if(blob!=null){
  31. var result = await DBHelper.database.searchbyTagNumber(blob.tag_number.toUpperCase());
  32. if(result['DATA']!=null) {
  33. result['DATA'].blob = blob.blob;
  34. result['DATA'].no = widget.no;
  35. result['DATA'].keterangan = blob.keterangan;
  36. }
  37. else util.showToast('Alert', 'Asset data not found');
  38. String tag_number = result['DATA'].tag_number;
  39. int separator = tag_number.lastIndexOf('/')+1;
  40. setState(() {
  41. _asset = result['DATA'];
  42. prefixCode.text = tag_number.substring(0,separator);
  43. barCode.text = tag_number.substring(separator);
  44. ket.text = result['DATA'].keterangan;
  45. });
  46. }
  47. else{
  48. util.showToast('Alert', 'Asset data not found');
  49. }
  50. }
  51. @override
  52. void initState() {
  53. // TODO: implement initState
  54. super.initState();
  55. qty.text='1';
  56. _controller = new TabController(length: 1, vsync: this);
  57. _controller.addListener(() {
  58. setState(() {
  59. _currentIndex = _controller.index;
  60. });
  61. });
  62. if(widget.no!=null){
  63. loadAsset();
  64. }
  65. }
  66. findAsset(query,{silent=false})async{
  67. var result = await DBHelper.database.searchbyTagNumber(query.toUpperCase());
  68. if(result['DATA']!=null){
  69. if(result['EXIST']){
  70. if(widget.no==null){
  71. setState(() {
  72. isAppend=false;
  73. barCode.text = '';
  74. ket.text = '';
  75. _asset = new Asset();
  76. });
  77. FocusScope.of(context).requestFocus(focusNode);
  78. }
  79. else{
  80. String tag_number = _asset.tag_number;
  81. int separator = tag_number.lastIndexOf('/')+1;
  82. setState(() {
  83. prefixCode.text = tag_number.substring(0,separator);
  84. barCode.text = tag_number.substring(separator);
  85. });
  86. }
  87. if(!silent)util.showToast('Alert', 'Asset data already inserted');
  88. }
  89. else{
  90. var image;
  91. if(_asset.blob!=null)image=_asset.blob;
  92. setState(() {
  93. isAppend=false;
  94. _asset = result['DATA'];
  95. if(image!=null)_asset.blob = image;
  96. _asset.no = widget.no;
  97. });
  98. }
  99. }
  100. else{
  101. var image;
  102. if(_asset.blob!=null)image=_asset.blob;
  103. setState(() {
  104. // barCode.text = '';
  105. isAppend=true;
  106. // ket.text = '';
  107. _asset = new Asset();
  108. if(image!=null)_asset.blob = image;
  109. _asset.tag_number = query.toUpperCase();
  110. _asset.no = widget.no;
  111. });
  112. // FocusScope.of(context).requestFocus(focusNode);
  113. if(!silent)util.showToast('Alert', 'Asset data not found');
  114. }
  115. }
  116. @override
  117. Widget build(BuildContext context) {
  118. return Scaffold(
  119. resizeToAvoidBottomInset: true,
  120. body: Container(
  121. padding: EdgeInsets.only(top: 20,bottom: 50),
  122. color: Colors.grey.withOpacity(0.3),
  123. child: Column(
  124. children: <Widget>[
  125. Expanded(
  126. flex: 5,
  127. child: Column(
  128. children: <Widget>[
  129. Expanded(
  130. flex:18,
  131. child: TabBarView(
  132. controller: _controller,
  133. children: <Widget>[
  134. Padding(
  135. padding: EdgeInsets.only(top:20,left: 20,right: 20),
  136. child: Stack(
  137. children: <Widget>[
  138. Container(color: Colors.grey,),
  139. Positioned.fill(child: InkWell(onTap: ()async{
  140. var image = await picker.getImage(source: ImageSource.camera,imageQuality: 60,maxWidth: 600);
  141. if(image!=null){
  142. _asset.blob = await image.readAsBytes();
  143. setState(() {
  144. });
  145. print(File(image.path).lengthSync()/1024);
  146. File(image.path).deleteSync();
  147. }
  148. },child: Container(
  149. decoration: BoxDecoration(
  150. image: (_asset!=null&&_asset.blob!=null)?DecorationImage(
  151. image: MemoryImage(_asset.blob),
  152. fit: BoxFit.fitWidth
  153. ):null
  154. ),
  155. child: (_asset!=null&&_asset.blob!=null)?null:Icon(Icons.camera_alt,size: 200,color: Colors.white,))))
  156. ],
  157. ),
  158. ),
  159. // Padding(
  160. // padding: EdgeInsets.only(top:20,left: 20,right: 20),
  161. // child: Stack(
  162. // children: <Widget>[
  163. // Container(color: Colors.grey,),
  164. // Positioned.fill(child: InkWell(onTap: ()async{
  165. // await picker.getImage(source: ImageSource.camera);
  166. // },child: Container(child: Icon(Icons.camera_alt,size: 200,color: Colors.white,))))
  167. // ],
  168. // ),
  169. // ),
  170. ],
  171. ),
  172. ),
  173. Expanded(
  174. flex:1,
  175. child:
  176. Container(
  177. // color: Colors.grey,
  178. // child: TabBar(
  179. // indicatorColor: Colors.blueGrey,
  180. // controller: _controller,
  181. // labelColor: Colors.blueGrey,
  182. // labelStyle: TextStyle(
  183. // fontSize: 17,
  184. // fontWeight: FontWeight.bold
  185. // ),
  186. // unselectedLabelStyle: TextStyle(
  187. // fontSize: 16
  188. // ),
  189. // indicatorSize: TabBarIndicatorSize.label,
  190. // tabs: <Widget>[
  191. // Tab(
  192. // text: 'Asset',
  193. // ),
  194. // Tab(
  195. // text: 'Barcode',
  196. // ),
  197. // ],
  198. // ),
  199. )
  200. ),
  201. ],
  202. ),
  203. ),
  204. Expanded(
  205. flex: 5,
  206. child: Container(
  207. color: Colors.white,
  208. padding: EdgeInsets.all(20),
  209. child: SingleChildScrollView(
  210. scrollDirection: Axis.vertical,
  211. child: Column(
  212. mainAxisAlignment: MainAxisAlignment.start,
  213. children: <Widget>[
  214. (_asset.tag_number!=null)?Container(
  215. alignment: Alignment.centerRight,
  216. child: InkWell(
  217. onTap: ()async {
  218. try{
  219. var dbName = await DBHelper.database.getDbName();
  220. var bUnit = await DBHelper.database.getBUnit();
  221. util.showLoading(context);
  222. http.Response result = await http.get(
  223. '${prefs.getString(keyClass.hostAddress)??"https://asset.thamringroup.web.id"}/api/images?q=${_asset.tag_number}&s=${dbName}&b=${bUnit}',
  224. ).timeout(Duration(seconds: 3));
  225. Navigator.pop(context);
  226. if(result!=null){
  227. Navigator.push(context, MaterialPageRoute(builder: (context) => PhotoViewer(result.bodyBytes)));
  228. }
  229. else util.showToast('ALERT', "No Archived Images yet");
  230. }
  231. catch(e){
  232. Navigator.pop(context);
  233. print(e);
  234. util.showToast('ALERT', "No Archived Images yet");
  235. }
  236. //showPhoto
  237. },
  238. child: Padding(
  239. padding: const EdgeInsets.all(4.0),
  240. child: Text('Archived images',style: TextStyle(color: Colors.indigo, decoration: TextDecoration.underline,),),
  241. ),
  242. ),
  243. ):Container(),
  244. (_asset.tag_number!=null)?SizedBox(height: 5,):Container(),
  245. Row(
  246. children: <Widget>[
  247. Expanded(
  248. flex:3,
  249. child: Container(
  250. child: TextField(
  251. controller: prefixCode,
  252. autofocus: (widget.no==null),
  253. onSubmitted: (value)async{
  254. String query = value.replaceAll('*', '');
  255. query = query.substring(0,query.lastIndexOf('/')+1);
  256. setState(() {
  257. prefixCode.text = query;
  258. });
  259. if(prefixCode.text!=''&&barCode.text!='')await findAsset(prefixCode.text+barCode.text);
  260. else FocusScope.of(context).requestFocus(focusNode);
  261. },
  262. decoration: InputDecoration(
  263. hintText: "Prefix code",
  264. alignLabelWithHint: true,
  265. ),
  266. ),
  267. ),
  268. ),
  269. SizedBox(width: 10,),
  270. Expanded(
  271. flex:3,
  272. child: Container(
  273. child: TextField(
  274. controller: barCode,
  275. focusNode: focusNode,
  276. autofocus: (widget.no==null),
  277. onSubmitted: (value)async{
  278. String query = value.replaceAll('*', '');
  279. if(prefixCode.text!=''){
  280. query = query.replaceAll(prefixCode.text.toUpperCase(), '');
  281. }
  282. else{
  283. if(query.contains('/'))query = query.substring(query.lastIndexOf('/'));
  284. util.showToast('ALERT', 'Please fill the prefix first');
  285. }
  286. setState(() {
  287. barCode.text = query;
  288. });
  289. if(prefixCode.text!=''&&barCode.text!='')await findAsset(prefixCode.text+barCode.text);
  290. },
  291. decoration: InputDecoration(
  292. hintText: "Suffix / Barcode",
  293. alignLabelWithHint: true,
  294. suffixIcon: InkWell(onTap: ()async{
  295. if(prefixCode.text!=''){
  296. var scan = await util.scan();
  297. if(scan['STATUS']==1){
  298. String query = scan['DATA'];
  299. // print("$query != ${prefixCode.text.toUpperCase()}");
  300. setState(() {
  301. query = query.trim().replaceAll(prefixCode.text.toUpperCase(), '');
  302. barCode.text = query;
  303. });
  304. if(prefixCode.text!=''&&barCode.text!='')await findAsset(prefixCode.text+barCode.text);
  305. }
  306. }
  307. else util.showToast('ALERT', 'Please fill the prefix first');
  308. },child: Icon(Icons.center_focus_strong))
  309. ),
  310. ),
  311. ),
  312. ),
  313. Expanded(flex: 1,
  314. child: Container(
  315. alignment: Alignment.centerRight,
  316. child: Text('Qty :'),
  317. ),),
  318. Expanded(
  319. flex:2,
  320. child: Container(
  321. child: TextField(
  322. enabled: false,
  323. keyboardType: TextInputType.number,
  324. decoration: InputDecoration(
  325. contentPadding: EdgeInsets.all(8)
  326. ),
  327. controller: qty,
  328. ),
  329. ),
  330. ),
  331. ],
  332. ),
  333. SizedBox(height: 5,),
  334. Container(
  335. alignment: Alignment.centerLeft,
  336. height: 50,
  337. child: Row(
  338. children: <Widget>[
  339. Expanded(
  340. flex : 3,
  341. child: Text('Note ',style: TextStyle(fontSize: 16),),
  342. ),
  343. Expanded(
  344. flex : 1,
  345. child: Text(':',style: TextStyle(fontSize: 16),),
  346. ),
  347. Expanded(
  348. flex : 7,
  349. child: TextField(
  350. controller: ket,
  351. decoration: InputDecoration(
  352. hintText: "Insert Note here",
  353. ),
  354. ),
  355. ),
  356. ],
  357. ),
  358. ),
  359. SizedBox(height: 5,),
  360. Container(
  361. alignment: Alignment.centerLeft,
  362. height: 50,
  363. child: Row(
  364. children: <Widget>[
  365. Expanded(
  366. flex : 3,
  367. child: Text('Asset No ',style: TextStyle(fontSize: 16),),
  368. ),
  369. Expanded(
  370. flex : 1,
  371. child: Text(':',style: TextStyle(fontSize: 16),),
  372. ),
  373. Expanded(
  374. flex : 7,
  375. child: Text((_asset.asset_no??'-')=='null'?'-':_asset.asset_no??'-',style: TextStyle(fontSize: 16),),
  376. ),
  377. ],
  378. ),
  379. ),
  380. SizedBox(height: 5,),
  381. Container(
  382. alignment: Alignment.centerLeft,
  383. height: 50,
  384. child: Row(
  385. children: <Widget>[
  386. Expanded(
  387. flex : 3,
  388. child: Text('Asset Desc ',style: TextStyle(fontSize: 16),),
  389. ),
  390. Expanded(
  391. flex : 1,
  392. child: Text(':',style: TextStyle(fontSize: 16),),
  393. ),
  394. Expanded(
  395. flex : 7,
  396. child: Text(_asset.asset_desc??'-',style: TextStyle(fontSize: 16),),
  397. ),
  398. ],
  399. ),
  400. ),
  401. SizedBox(height: 5,),
  402. Container(
  403. alignment: Alignment.centerLeft,
  404. height: 50,
  405. child: Row(
  406. children: <Widget>[
  407. Expanded(
  408. flex : 3,
  409. child: Text('PIC ',style: TextStyle(fontSize: 16),),
  410. ),
  411. Expanded(
  412. flex : 1,
  413. child: Text(':',style: TextStyle(fontSize: 16),),
  414. ),
  415. Expanded(
  416. flex : 7,
  417. child: Text(_asset.pic??'-',style: TextStyle(fontSize: 16),),
  418. ),
  419. ],
  420. ),
  421. ),
  422. SizedBox(height: 5,),
  423. Container(
  424. alignment: Alignment.centerLeft,
  425. height: 50,
  426. child: Row(
  427. children: <Widget>[
  428. Expanded(
  429. flex : 3,
  430. child: Text('Lantai ',style: TextStyle(fontSize: 16),),
  431. ),
  432. Expanded(
  433. flex : 1,
  434. child: Text(':',style: TextStyle(fontSize: 16),),
  435. ),
  436. Expanded(
  437. flex : 7,
  438. child: Text(_asset.lantai??'-',style: TextStyle(fontSize: 16),),
  439. ),
  440. ],
  441. ),
  442. ),
  443. SizedBox(height: 5,),
  444. Container(
  445. alignment: Alignment.centerLeft,
  446. height: 50,
  447. child: Row(
  448. children: <Widget>[
  449. Expanded(
  450. flex : 3,
  451. child: Text('Ruang ',style: TextStyle(fontSize: 16),),
  452. ),
  453. Expanded(
  454. flex : 1,
  455. child: Text(':',style: TextStyle(fontSize: 16),),
  456. ),
  457. Expanded(
  458. flex : 7,
  459. child: Text(_asset.ruangan??'-',style: TextStyle(fontSize: 16),),
  460. ),
  461. ],
  462. ),
  463. ),
  464. // SizedBox(height: 5,),
  465. // Container(
  466. // alignment: Alignment.centerLeft,
  467. // height: 50,
  468. // child: Row(
  469. // children: <Widget>[
  470. // Expanded(
  471. // flex : 3,
  472. // child: Text('Gedung ',style: TextStyle(fontSize: 16),),
  473. // ),
  474. // Expanded(
  475. // flex : 1,
  476. // child: Text(':',style: TextStyle(fontSize: 16),),
  477. // ),
  478. // Expanded(
  479. // flex : 7,
  480. // child: Text(_asset.gedung??'-',style: TextStyle(fontSize: 16),),
  481. // ),
  482. // ],
  483. // ),
  484. // ),
  485. ],
  486. ),
  487. ),
  488. ),
  489. ),
  490. ],
  491. ),
  492. ),
  493. bottomSheet: Container(
  494. height: 50,
  495. // color: Colors.grey.withOpacity(0.3),
  496. child: Row(
  497. children: <Widget>[
  498. Expanded(
  499. flex: 5,
  500. child: FlatButton(
  501. onPressed: ()async{
  502. if(barCode.text!=''&&prefixCode.text!='')await findAsset(prefixCode.text+barCode.text,silent: true);
  503. else _asset.tag_number = null;
  504. if(_asset.tag_number!=null&&_asset.blob!=null){
  505. _asset.keterangan = ket.text;
  506. bool upsertReady = !isAppend;
  507. if(isAppend){
  508. upsertReady = await showDialog(context: context,builder: (context)=>WillPopScope(
  509. onWillPop: ()async{
  510. Navigator.pop(context,false);
  511. return false;
  512. },
  513. child: AlertDialog(
  514. title: Text('Append New Asset'),
  515. content: Text('${(widget.no==null)?'Insert':'Update'} brand new asset?'),
  516. actions: <Widget>[
  517. FlatButton(
  518. onPressed: ()async{
  519. Navigator.pop(context,true);
  520. },
  521. child: Text('Save'),
  522. ),
  523. FlatButton(
  524. onPressed: ()async{
  525. Navigator.pop(context,false);
  526. },
  527. child: Text('Cancel'),
  528. )
  529. ],
  530. ),
  531. ));
  532. }
  533. if(upsertReady){
  534. if(widget.no==null){
  535. var insert = await DBHelper.database.insertAsset(_asset);
  536. if(insert!=null){
  537. util.showToast("SUCCESS", 'Asset Inserted');
  538. await DBHelper.database.closeDb();
  539. setState(() {
  540. barCode.text = '';
  541. ket.text = '';
  542. _asset = new Asset();
  543. });
  544. FocusScope.of(context).requestFocus(focusNode);
  545. }
  546. }
  547. else{
  548. var update = await DBHelper.database.updateAsset(_asset);
  549. if(update!=null){
  550. util.showToast("SUCCESS", 'Asset Updated');
  551. await DBHelper.database.closeDb();
  552. Navigator.pop(context);
  553. }
  554. }
  555. }
  556. }
  557. else{
  558. util.showToast('ERROR', 'Please complete the asset data');
  559. }
  560. },
  561. color: Colors.green,
  562. child: Container(alignment: Alignment.center,height: 50,
  563. child: Text('Save')),
  564. ),
  565. ),
  566. Expanded(
  567. flex: 5,
  568. child: FlatButton(
  569. onPressed: (){
  570. Navigator.pop(context);
  571. },
  572. color: Colors.red,
  573. child: Container(alignment: Alignment.center,height:50,child: Text('Cancel')),
  574. ),
  575. ),
  576. ],
  577. ),
  578. ),
  579. );
  580. }
  581. }