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.
 
 
 
 

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