template.dart 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. import 'dart:async';
  2. import 'dart:convert';
  3. import 'dart:io';
  4. import 'dart:ui';
  5. import 'package:another_flushbar/flushbar.dart';
  6. import 'package:auto_route/auto_route.dart';
  7. import 'package:cached_network_image/cached_network_image.dart';
  8. import 'package:dotted_line/dotted_line.dart';
  9. import 'package:easy_localization/easy_localization.dart';
  10. import 'package:flutter/foundation.dart';
  11. import 'package:flutter/material.dart';
  12. import 'package:flutter/services.dart';
  13. import 'package:flutter_cache_manager/flutter_cache_manager.dart';
  14. import 'package:fluttertoast/fluttertoast.dart';
  15. import 'package:loading_indicator/loading_indicator.dart';
  16. import 'package:lottie/lottie.dart';
  17. import 'package:page_transition/page_transition.dart';
  18. import 'package:photo_view/photo_view.dart';
  19. import 'package:photo_view/photo_view_gallery.dart';
  20. import 'package:telnow_mobile_new/src/api/api_auth_provider.dart';
  21. import 'package:telnow_mobile_new/src/api/jwt_token.dart';
  22. import 'package:telnow_mobile_new/src/injector/injector.dart';
  23. import 'package:telnow_mobile_new/src/layouts/auth/qr.dart';
  24. import 'package:telnow_mobile_new/src/storage/sharedpreferences/shared_preferences_manager.dart';
  25. import 'package:telnow_mobile_new/src/utils/U.dart';
  26. import 'package:telnow_mobile_new/src/utils/cache_manager.dart';
  27. import 'package:uuid/uuid.dart';
  28. PreferredSizeWidget appBarTemplate({required BuildContext context, required String title, String icon = 'arrow-left', List<Widget>? action, exc = false}){
  29. return AppBar(
  30. elevation: 0,
  31. bottomOpacity: 0,
  32. backgroundColor: backgroundColor,
  33. leading: GestureDetector(
  34. child: U.iconsax(icon, color: textColor),
  35. onTap: ()=>Navigator.of(context).pop(exc),
  36. ),
  37. titleSpacing: 0,
  38. title: Text(title, style: TextStyle(color: textColor, fontSize: 17, fontWeight: FontWeight.w500), overflow: TextOverflow.ellipsis),
  39. actions: action,
  40. );
  41. }
  42. Widget buttonTemplate({double width = double.infinity, double height = 51, required String text, required action(), backgroundColor = primaryColor, textColor = Colors.white, borderColor = primaryColor}){
  43. return SizedBox(
  44. width: width,
  45. height: height,
  46. child: ElevatedButton(
  47. style: ButtonStyle(
  48. elevation: MaterialStateProperty.all<double>(0),
  49. backgroundColor: MaterialStateProperty.all<Color>(backgroundColor),
  50. shape: MaterialStateProperty.all<RoundedRectangleBorder>(RoundedRectangleBorder(borderRadius: BorderRadius.circular(12))),
  51. side: MaterialStateProperty.all<BorderSide>(BorderSide(color: borderColor))
  52. ),
  53. onPressed: ()=>action(),
  54. child: Text(text, style: TextStyle(fontSize: 16, color: textColor, fontWeight: FontWeight.w500)),
  55. ),
  56. );
  57. }
  58. Widget textVertical(String title, String subtitle){
  59. return Column(
  60. crossAxisAlignment: CrossAxisAlignment.start,
  61. children: [
  62. Text(title, style: TextStyle(color: textColor)),
  63. SizedBox(height: 5),
  64. Text(subtitle, style: TextStyle(color: textColor, fontSize: 12, fontWeight: FontWeight.w300)),
  65. ],
  66. );
  67. }
  68. Widget textHorizontal(String title, String subtitle, {double size = 14, double opacity = 1, bool copy = false}){
  69. return Row(
  70. crossAxisAlignment: CrossAxisAlignment.start,
  71. children: [
  72. Text(title, style: TextStyle(color: textColor.withValues(alpha: opacity), fontSize: size)),
  73. Expanded(
  74. child: copy?Row(
  75. mainAxisAlignment: MainAxisAlignment.end,
  76. children: [
  77. Expanded(child: Text(subtitle, style: TextStyle(color: textColor, fontSize: size), maxLines: 3, overflow: TextOverflow.ellipsis, textAlign: TextAlign.right)),
  78. SizedBox(width: 5),
  79. InkWell(
  80. child: Icon(Icons.copy, color: textColor, size: size+2),
  81. onTap: ()async{
  82. await Clipboard.setData(ClipboardData(text: subtitle));
  83. Fluttertoast.showToast(msg: 'Copied to Clipboard!'.tr());
  84. },
  85. ),
  86. ],
  87. ):Text(subtitle, style: TextStyle(color: textColor, fontSize: size), maxLines: 3, overflow: TextOverflow.ellipsis, textAlign: TextAlign.right),
  88. ),
  89. ],
  90. );
  91. }
  92. Widget divider({opacity = 0.15}){
  93. return Divider(height: 1, thickness: 1, color: textColor.withValues(alpha: opacity));
  94. }
  95. Widget dashed({double top = 8, double bottom = 8, double left = 0, double right = 0, Color color = textColor, double width = double.infinity}){
  96. return Padding(padding: EdgeInsets.only(top: top, bottom: bottom, left: left, right: right), child: DottedLine(dashColor: color, lineLength: width, dashLength: 5, dashGapLength: 5, lineThickness: 0.15, dashRadius: 1));
  97. }
  98. Widget separator(){
  99. return Container(
  100. color: Color(0xffF3F3F3),
  101. width: double.infinity, height: 8,
  102. );
  103. }
  104. //------------------------------------------------------------------------------
  105. Widget categoryContainer({required BuildContext context, required String iconUrl}){
  106. double size = U.bodyWidth(context)/6;
  107. String ext = iconUrl.split(".").last;
  108. return Container(
  109. padding: EdgeInsets.all(5),
  110. child: Image(image: CachedNetworkImageProvider(iconUrl+'?bridge-cache=true', cacheManager: CacheManager(CacheMan.config(iconUrl+'?bridge-cache=true'))), width: size, height: size),
  111. decoration: BoxDecoration(
  112. color: Colors.white,
  113. borderRadius: BorderRadius.all(Radius.circular(20)),
  114. border: Border.all(width: 0.2, color: Colors.black12),
  115. boxShadow: [BoxShadow(color: Colors.grey.withValues(alpha: 0.3), blurRadius: 2, offset: Offset(0, 2))]
  116. ),
  117. );
  118. }
  119. Widget shimmerTopMenu(BuildContext context){
  120. double size = (U.bodyWidth(context)/6)+10;
  121. return Row(
  122. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  123. children: List.generate(4, (index){
  124. return Container(
  125. width: size, height: size,
  126. decoration: BoxDecoration(
  127. color: Colors.black26,
  128. borderRadius: BorderRadius.all(Radius.circular(20)),
  129. ),
  130. );
  131. // return Shimmer.fromColors(
  132. // baseColor: Colors.grey[400]!,
  133. // highlightColor: Colors.white,
  134. // child: Container(
  135. // width: size, height: size,
  136. // decoration: BoxDecoration(
  137. // color: Colors.white,
  138. // borderRadius: BorderRadius.all(Radius.circular(20)),
  139. // ),
  140. // ),
  141. // );
  142. }),
  143. );
  144. }
  145. //------------------------------------------------------------------------------
  146. Widget requestTiles({required String image, required String title, required String subtitle, bool border = false, double vertical = 16}){
  147. return Container(
  148. margin: EdgeInsets.symmetric(vertical: vertical),
  149. padding: EdgeInsets.only(right: border?16:0),
  150. child: Row(
  151. children: [
  152. imageTiles(imageUrl: image),
  153. SizedBox(width: 16),
  154. Expanded(
  155. child: Column(
  156. crossAxisAlignment: CrossAxisAlignment.start,
  157. children: [
  158. Text(title, style: TextStyle(color: textColor, fontWeight: FontWeight.w500), overflow: TextOverflow.ellipsis),
  159. dashed(),
  160. Text(subtitle, style: TextStyle(color: textColor, fontSize: 13, fontWeight: FontWeight.w300), maxLines: 2, overflow: TextOverflow.ellipsis)
  161. ],
  162. ),
  163. )
  164. ],
  165. ),
  166. decoration: BoxDecoration(
  167. color: Colors.white,
  168. border: border?Border.all(color: textColor.withValues(alpha: 0.15)):null,
  169. borderRadius: border?BorderRadius.all(Radius.circular(12)):null
  170. ),
  171. );
  172. }
  173. Widget imageTiles({required String imageUrl, double width = 100, double height = 80, double radius = 12}){
  174. return imageUrl != "null" ? Container(
  175. padding: EdgeInsets.fromLTRB(1, 0, 1, 0),
  176. decoration: BoxDecoration(
  177. color: textColor.withValues(alpha: 0.1),
  178. borderRadius: BorderRadius.all(Radius.circular(radius)),
  179. ),
  180. child: Container(
  181. width: width, height: height,
  182. decoration: BoxDecoration(
  183. color: textColor.withValues(alpha: 0.1),
  184. borderRadius: BorderRadius.all(Radius.circular(radius)),
  185. image: DecorationImage(
  186. image: CachedNetworkImageProvider(imageUrl+'?bridge-cache=true', cacheManager: CacheManager(CacheMan.config(imageUrl+'?bridge-cache=true'))),
  187. fit: BoxFit.cover,
  188. ),
  189. ),
  190. ),
  191. ): Container(
  192. height: height,
  193. width: width,
  194. child: Center(child: Text("noImage".tr(), style: TextStyle(fontStyle: FontStyle.italic, fontSize: width<100?10:14, color: Colors.black38), maxLines: 2, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center,)),
  195. decoration: BoxDecoration(
  196. color: Colors.black12,
  197. borderRadius: BorderRadius.all(Radius.circular(12.0))
  198. ),
  199. );
  200. }
  201. Widget loginFieldTemplate({required String value, placeholder = '', required action(value), required submit(value), isPassword = false}){
  202. TextEditingController controller = TextEditingController()..text = value;
  203. bool hidePass = true;
  204. return SizedBox(
  205. width: double.infinity,
  206. child: StatefulBuilder(
  207. builder: (context, fieldState) => TextFormField(
  208. controller: controller,
  209. style: TextStyle(fontSize: 16, color: Colors.white),
  210. keyboardType: TextInputType.text,
  211. obscureText: isPassword?hidePass:false,
  212. cursorColor: Colors.white,
  213. decoration: InputDecoration(
  214. hintText: placeholder,
  215. hintStyle: TextStyle(fontSize: 16, color: Colors.white.withValues(alpha: 0.6)),
  216. filled: true,
  217. fillColor: Colors.white.withValues(alpha: 0.25),
  218. hoverColor: Colors.white.withValues(alpha: 0.26),
  219. contentPadding: EdgeInsets.all(16),
  220. border: InputBorder.none,
  221. suffixIconConstraints: BoxConstraints(maxHeight: 40, maxWidth: 40, minHeight: 40, minWidth: 40),
  222. suffixIcon: isPassword?GestureDetector(child: U.iconsax(hidePass?'eye':'eye-slash', color: Colors.white.withValues(alpha: 0.6)), onTap: ()=>fieldState(()=>hidePass=!hidePass)):null,
  223. enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.white)),
  224. focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.white)),
  225. isDense: true
  226. ),
  227. onChanged: (val)=>action(val.toString()),
  228. onFieldSubmitted: (val)=>submit(val.toString()),
  229. ),
  230. ),
  231. );
  232. }
  233. Widget loadingTemplate(){
  234. return Center(
  235. child: Container(
  236. height: 36,
  237. child: LoadingIndicator(
  238. indicatorType: Indicator.ballPulseRise,
  239. colors: U.defaultRainbowColors(),
  240. strokeWidth: 2,
  241. backgroundColor: Colors.black.withValues(alpha: 0),
  242. pathBackgroundColor: Colors.black,
  243. ),
  244. ),
  245. );
  246. }
  247. Widget infoContainer(String text){
  248. return Container(
  249. width: double.infinity,
  250. padding: EdgeInsets.all(12),
  251. child: Text(text, style: TextStyle(color: textColor), textAlign: TextAlign.center),
  252. decoration: BoxDecoration(
  253. color: secondaryColor.withValues(alpha: 0.1),
  254. border: Border.all(color: secondaryColor),
  255. borderRadius: BorderRadius.all(Radius.circular(12))
  256. ),
  257. );
  258. }
  259. class PhotoPreview extends StatelessWidget {
  260. final title;
  261. final imageUrl;
  262. final bool isUrl;
  263. final bool isNetwork;
  264. PhotoPreview(this.title, this.imageUrl, this.isUrl, {this.isNetwork = false});
  265. @override
  266. Widget build(BuildContext context) {
  267. return Scaffold(
  268. backgroundColor: Colors.black,
  269. appBar: AppBar(
  270. elevation: 0,
  271. bottomOpacity: 0,
  272. titleSpacing: 0,
  273. title: Text(title, style: TextStyle(color: Colors.white, fontSize: 17, fontWeight: FontWeight.w500), overflow: TextOverflow.ellipsis),
  274. backgroundColor: Colors.black.withValues(alpha: 0.4),
  275. leading: GestureDetector(
  276. child: U.iconsax('arrow-left', color: Colors.white),
  277. onTap: () => Navigator.of(context).pop(),
  278. ),
  279. ),
  280. body: Container(
  281. width: MediaQuery.of(context).size.width,
  282. height: MediaQuery.of(context).size.height,
  283. child: PhotoView(
  284. maxScale: 5.0,
  285. minScale: 0.3,
  286. imageProvider: (isUrl ? NetworkImage(imageUrl) : isNetwork ? MemoryImage(imageUrl) : FileImage(imageUrl)) as ImageProvider<Object>?,
  287. )),
  288. );
  289. }
  290. }
  291. class PhotoPreviewGallery extends StatelessWidget {
  292. final String title;
  293. final List imageList;
  294. final int startIndex;
  295. final bool isUrl;
  296. final String column;
  297. const PhotoPreviewGallery({required this.title, required this.imageList, required this.startIndex, this.isUrl = true, this.column = 'image', super.key});
  298. @override
  299. Widget build(BuildContext context) {
  300. return Scaffold(
  301. backgroundColor: Colors.black,
  302. appBar: AppBar(
  303. title: Text(title, style: TextStyle(fontSize: 18)),
  304. backgroundColor: Colors.black.withValues(alpha: 0.4),
  305. titleSpacing: 0,
  306. leading: new IconButton(
  307. icon: new Icon(Icons.arrow_back_rounded),
  308. onPressed: () => Navigator.of(context).pop(),
  309. ),
  310. ),
  311. body: Container(
  312. width: MediaQuery.of(context).size.width,
  313. height: MediaQuery.of(context).size.height,
  314. child: PhotoViewGallery.builder(
  315. itemCount: imageList.length,
  316. pageController: PageController(initialPage: startIndex),
  317. builder: (context, index) {
  318. var uuid = Uuid().v1().replaceAll('-', '');
  319. return PhotoViewGalleryPageOptions(
  320. imageProvider: (isUrl?NetworkImage(imageList[index][column]+'?uuid='+uuid):imageList[index] is File?FileImage(imageList[index]):MemoryImage(imageList[index])) as ImageProvider<Object>?,
  321. maxScale: 5.0, minScale: 0.3,
  322. );
  323. },
  324. )
  325. ),
  326. );
  327. }
  328. }
  329. //------------------------------------------------------------------------------
  330. class MyClipper extends CustomClipper<Path> {
  331. final isNip;
  332. MyClipper(this.isNip);
  333. @override
  334. Path getClip(Size size) {
  335. var path = Path();
  336. double factor = 6.0;
  337. path.lineTo(0, size.height - factor);
  338. path.quadraticBezierTo(0, size.height, factor, size.height);
  339. if (isNip) {
  340. path.lineTo(size.width - (factor * 2), size.height);
  341. path.quadraticBezierTo(size.width - factor, size.height, size.width - factor, size.height - factor);
  342. path.lineTo(size.width - factor, factor);
  343. } else {
  344. path.lineTo(size.width - factor, size.height);
  345. path.quadraticBezierTo(size.width, size.height, size.width, size.height - factor);
  346. path.lineTo(size.width, factor);
  347. path.quadraticBezierTo(size.width, 0, size.width - factor, 0);
  348. }
  349. path.lineTo(size.width, 0);
  350. path.lineTo(factor, 0);
  351. path.quadraticBezierTo(0, 0, 0, factor);
  352. return path;
  353. }
  354. @override
  355. bool shouldReclip(CustomClipper oldClipper) => true;
  356. }
  357. class YourClipper extends CustomClipper<Path> {
  358. final isNip;
  359. YourClipper(this.isNip);
  360. @override
  361. Path getClip(Size size) {
  362. var path = Path();
  363. double factor = 6.0;
  364. if (isNip) {
  365. path.lineTo(factor, factor);
  366. path.lineTo(factor, size.height - factor);
  367. path.quadraticBezierTo(factor, size.height, factor * 2, size.height);
  368. } else {
  369. path.lineTo(0, size.height - factor);
  370. path.quadraticBezierTo(0, size.height, factor, size.height);
  371. }
  372. path.lineTo(size.width - factor, size.height);
  373. path.quadraticBezierTo(size.width, size.height, size.width, size.height - factor);
  374. path.lineTo(size.width, factor);
  375. path.quadraticBezierTo(size.width, 0, size.width - factor, 0);
  376. if (!isNip) {
  377. path.lineTo(factor, 0);
  378. path.quadraticBezierTo(0, 0, 0, factor);
  379. }
  380. return path;
  381. }
  382. @override
  383. bool shouldReclip(CustomClipper oldClipper) => true;
  384. }
  385. isBase64(value) {
  386. try {
  387. base64Decode(value);
  388. return true;
  389. } catch (e) {
  390. return false;
  391. }
  392. }
  393. //------------------------------------------------------------------------------
  394. class Debouncer {
  395. final int? milliseconds;
  396. VoidCallback? action;
  397. Timer? _timer;
  398. Debouncer({this.milliseconds});
  399. run(VoidCallback action) {
  400. if (null != _timer) {
  401. _timer?.cancel();
  402. }
  403. _timer = Timer(Duration(milliseconds: milliseconds!), action);
  404. }
  405. }
  406. navigateTo(BuildContext context, child){
  407. return Navigator.push(context, PageTransition(type: PageTransitionType.rightToLeft, child: child));
  408. }
  409. navigateToThen(BuildContext context, child, act){
  410. return Navigator.push(context, PageTransition(type: PageTransitionType.rightToLeft, child: child)).then((v) => act());
  411. }
  412. navigateBack(BuildContext context, {exc = false}){
  413. return Navigator.of(context).pop(exc);
  414. }
  415. void showError(BuildContext context, message) {
  416. Flushbar(
  417. message: message,
  418. icon: Icon(
  419. Icons.info_outline,
  420. size: 28.0,
  421. color: Colors.red,
  422. ),
  423. duration: Duration(seconds: 5),
  424. flushbarPosition: FlushbarPosition.BOTTOM,
  425. margin: EdgeInsets.all(8),
  426. borderRadius: BorderRadius.all(Radius.circular(8)),
  427. )..show(context);
  428. }
  429. void showSuccess(context, message) {
  430. Flushbar(
  431. message: message,
  432. icon: Icon(
  433. Icons.info_outline,
  434. size: 28.0,
  435. color: Colors.green,
  436. ),
  437. duration: Duration(seconds: 5),
  438. flushbarPosition: FlushbarPosition.BOTTOM,
  439. margin: EdgeInsets.all(8),
  440. borderRadius: BorderRadius.all(Radius.circular(8)),
  441. )..show(context);
  442. }
  443. String convertDate(date, locale) {
  444. if (date == "-" || date.isEmpty) {
  445. return date;
  446. }
  447. final dateToCheck = DateTime.parse(date);
  448. final now = DateTime.now();
  449. final today = DateTime(now.year, now.month, now.day);
  450. final yesterday = DateTime(now.year, now.month, now.day - 1);
  451. final aDate = DateTime(dateToCheck.year, dateToCheck.month, dateToCheck.day);
  452. if (aDate == today) {
  453. return 'today'.tr()+' '+DateFormat('HH:mm', locale).format(DateTime.parse(date));
  454. } else if (aDate == yesterday) {
  455. return 'yesterday'.tr()+' '+DateFormat('HH:mm', locale).format(DateTime.parse(date));
  456. } else {
  457. return DateFormat('dd MMM HH:mm', locale).format(DateTime.parse(date));
  458. }
  459. }
  460. //------------------------------------------------------------------------------
  461. class RefreshPage extends StatelessWidget {
  462. final VoidCallback onRefresh;
  463. RefreshPage(this.onRefresh);
  464. @override
  465. Widget build(BuildContext context) {
  466. return Container(
  467. padding: EdgeInsets.only(top: MediaQuery.of(context).size.height / 2.5),
  468. height: MediaQuery.of(context).size.height,
  469. child: Center(
  470. child: GestureDetector(
  471. child: Column(
  472. children: [
  473. Icon(Icons.refresh_rounded, size: 50, color: Colors.grey),
  474. Text('refresh'.tr(), style: TextStyle(color: Colors.grey))
  475. ],
  476. ),
  477. onTap: () => onRefresh(),
  478. ),
  479. ),
  480. );
  481. }
  482. }
  483. //------------------------------------------------------------------------------
  484. final JwtToken token = JwtToken();
  485. final SharedPreferencesManager _sharedPreferencesManager = locator<SharedPreferencesManager>();
  486. class NoDataPage extends StatelessWidget {
  487. @override
  488. Widget build(BuildContext context) {
  489. print(ApiAuthProvider().getServiceAsset('TNSendRequest.json'));
  490. return Center(
  491. child: Column(
  492. mainAxisSize: MainAxisSize.min,
  493. children: <Widget>[
  494. kIsWeb && !isCanvasKit ? Container(
  495. width: 150, margin: EdgeInsets.only(top: 20, bottom: 10), padding: EdgeInsets.all(10),
  496. child: Image(image: AssetImage('assets/image/error/EmptyData.png'))
  497. ) : Lottie.asset('assets/image/lottie/Nodata.json', width: 250, height: 250, fit: BoxFit.fill),
  498. Padding(
  499. padding: const EdgeInsets.fromLTRB(15, 0, 15, 10),
  500. child: Text('notFound'.tr(),
  501. style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
  502. textAlign: TextAlign.center),
  503. ),
  504. Padding(
  505. padding: const EdgeInsets.fromLTRB(15, 0, 15, 10),
  506. child: Text('notFound2'.tr(),
  507. style: TextStyle(fontSize: 14), textAlign: TextAlign.center),
  508. )
  509. ],
  510. ),
  511. );
  512. }
  513. }
  514. handlingError(context, type) {
  515. var data = [
  516. {
  517. 'image': 'NoInternet.png',
  518. 'title': 'noInternetTitle'.tr(),
  519. 'description': 'noInternetDesc'.tr()
  520. },
  521. {
  522. 'image': 'ErrorServer.png',
  523. 'title': 'errorServerTitle'.tr(),
  524. 'description': 'errorServerDesc'.tr()
  525. },
  526. {
  527. 'image': 'ErrorConnection.png',
  528. 'title': 'errorConnectTitle'.tr(),
  529. 'description': 'errorConnectDesc'.tr()
  530. },
  531. {
  532. 'image': 'ErrorAuth.png',
  533. 'title': 'invalidAccountTitle'.tr(),
  534. 'description': 'invalidAccountDesc'.tr()
  535. },
  536. {
  537. 'image': 'ErrorAuth.png',
  538. 'title': 'expAccountTitle'.tr(),
  539. 'description': 'expAccountDesc'.tr()
  540. }
  541. ];
  542. showModalBottomSheet<void>(
  543. context: context,
  544. backgroundColor: Colors.white,
  545. isDismissible: false,
  546. enableDrag: false,
  547. builder: (BuildContext context) {
  548. return SingleChildScrollView(
  549. child: Column(
  550. mainAxisSize: MainAxisSize.min,
  551. children: <Widget>[
  552. Container(
  553. padding: const EdgeInsets.fromLTRB(15, 10, 15, 0),
  554. alignment: Alignment.centerRight,
  555. child: GestureDetector(
  556. child: Icon(Icons.clear),
  557. onTap: () => Navigator.of(context).pop(),
  558. ),
  559. ),
  560. Container(
  561. width: 200,
  562. padding: const EdgeInsets.fromLTRB(15, 0, 15, 10),
  563. child: Image(
  564. image: AssetImage('assets/image/error/' + data[type]['image']!))),
  565. Padding(
  566. padding: const EdgeInsets.fromLTRB(15, 0, 15, 10),
  567. child: Text(data[type]['title']!,
  568. style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
  569. textAlign: TextAlign.center),
  570. ),
  571. Padding(
  572. padding: const EdgeInsets.fromLTRB(15, 0, 15, 10),
  573. child: Text(data[type]['description']!,
  574. style: TextStyle(fontSize: 14),
  575. textAlign: TextAlign.center),
  576. ),
  577. type == 3 || type == 4
  578. ? Padding(
  579. padding: const EdgeInsets.fromLTRB(15, 0, 15, 10),
  580. child: SizedBox(
  581. width: double.infinity,
  582. height: 45,
  583. child: TextButton(
  584. style: ButtonStyle(
  585. backgroundColor:
  586. MaterialStateProperty.all<Color>(primaryColor),
  587. shape: MaterialStateProperty.all<
  588. RoundedRectangleBorder>(
  589. RoundedRectangleBorder(
  590. borderRadius: BorderRadius.circular(5),
  591. ))),
  592. child: new Text('logout'.tr().toUpperCase(),
  593. style: TextStyle(color: Colors.white),
  594. textAlign: TextAlign.center),
  595. onPressed: () {
  596. if (type == 4) {
  597. _sharedPreferencesManager.clearKey(
  598. SharedPreferencesManager.keyAccessCode);
  599. _sharedPreferencesManager.clearKey(
  600. SharedPreferencesManager.keySerialCode);
  601. _sharedPreferencesManager.clearKey(
  602. SharedPreferencesManager.keyAccessToken);
  603. _sharedPreferencesManager.clearKey(
  604. SharedPreferencesManager.keyRefreshToken);
  605. _sharedPreferencesManager.clearKey(
  606. SharedPreferencesManager.keyUsername);
  607. _sharedPreferencesManager.clearKey(
  608. SharedPreferencesManager.keyIsLogin);
  609. _sharedPreferencesManager.clearKey(
  610. SharedPreferencesManager.keyScoope);
  611. _sharedPreferencesManager.clearKey(
  612. SharedPreferencesManager.debugString);
  613. _sharedPreferencesManager.clearKey(SharedPreferencesManager.keyHistoryMark);
  614. Navigator.pushAndRemoveUntil(
  615. context,
  616. MaterialPageRoute(
  617. builder: (context) => NewQrPage()),
  618. ModalRoute.withName("/home"));
  619. } else {
  620. var pid = U.getPidFromUrl(context.router.currentUrl);
  621. token.logout();
  622. context.router.removeLast();
  623. context.navigateToPath("/app/$pid/login");
  624. // print(pid);
  625. // context.router.removeLast();
  626. // context.navigateToPath('/app/$pid/login');
  627. }
  628. },
  629. )),
  630. )
  631. : Container(height: 1, width: 1)
  632. ],
  633. ),
  634. );
  635. });
  636. }
  637. // ignore: must_be_immutable
  638. class NoImageFound extends StatelessWidget {
  639. bool show = true;
  640. NoImageFound(this.show);
  641. @override
  642. Widget build(BuildContext context) {
  643. return Container(
  644. width: MediaQuery.of(context).size.width - 150,
  645. height: MediaQuery.of(context).size.height / 4,
  646. child: Stack(
  647. fit: StackFit.expand,
  648. children: [
  649. Image.asset('assets/image/general/QrCode.jpg', fit: BoxFit.cover),
  650. ClipRRect(
  651. // Clip it cleanly.
  652. child: BackdropFilter(
  653. filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
  654. child: Container(
  655. color: Colors.grey.withValues(alpha: 0.5),
  656. alignment: Alignment.center,
  657. child: show
  658. ? Container(
  659. padding: const EdgeInsets.all(10),
  660. child: Text('notFoundImg'.tr(),
  661. style: TextStyle(fontSize: 12)),
  662. decoration: BoxDecoration(
  663. color: Colors.white24,
  664. borderRadius:
  665. BorderRadius.all(Radius.circular(50))),
  666. )
  667. : Center(
  668. child: CircularProgressIndicator(),
  669. ),
  670. ),
  671. ),
  672. ),
  673. ],
  674. ),
  675. );
  676. }
  677. }
  678. dialogConfirm({required BuildContext context, required String title, required String text, required Function actionYes}){
  679. showDialog(
  680. context: context,
  681. builder: (BuildContext context) {
  682. return AlertDialog(
  683. title: Text(title),
  684. content: Text(text),
  685. actions: <Widget>[
  686. TextButton(
  687. child: Text("buttonNo".tr()),
  688. onPressed: () {
  689. Navigator.of(context).pop();
  690. },
  691. ),
  692. TextButton(
  693. onPressed: (){
  694. Navigator.of(context).pop();
  695. actionYes();
  696. },
  697. child: Text("buttonYes".tr())),
  698. ],
  699. );
  700. },
  701. );
  702. }
  703. showLoading(BuildContext context, {String? text, String? lottie}){
  704. showDialog(
  705. context: context,
  706. barrierDismissible: false,
  707. barrierColor: lottie!=null?Colors.white:null,
  708. builder: (BuildContext context) {
  709. return WillPopScope(
  710. onWillPop: ()=>Future.value(false),
  711. child: Center(
  712. child: Column(
  713. mainAxisSize: MainAxisSize.min,
  714. children: [
  715. lottie != null ? Lottie.asset('assets/image/lottie/$lottie', width: 250, height: 250, fit: BoxFit.fill) : CircularProgressIndicator(color: primaryColor),
  716. SizedBox(height: 5),
  717. Text(text??'inProcess'.tr(), style: TextStyle(color: lottie!=null?Colors.black:Colors.white))
  718. ],
  719. ),
  720. ),
  721. );
  722. },
  723. );
  724. }
  725. closeLoading(BuildContext context){
  726. Navigator.of(context, rootNavigator: true).pop();
  727. }