menu_history.dart 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  1. import 'package:auto_route/auto_route.dart';
  2. import 'package:easy_localization/easy_localization.dart';
  3. import 'package:easy_refresh/easy_refresh.dart';
  4. import 'package:flutter/material.dart';
  5. import 'package:lazy_load_scrollview/lazy_load_scrollview.dart';
  6. import 'package:provider/provider.dart';
  7. import 'package:telnow_mobile_new/src/api/api_auth_provider.dart';
  8. import 'package:telnow_mobile_new/src/layouts/functions/history.dart';
  9. import 'package:telnow_mobile_new/src/layouts/components/template.dart';
  10. import 'package:telnow_mobile_new/src/layouts/web/history_detail.dart';
  11. import 'package:telnow_mobile_new/src/utils/U.dart';
  12. import 'package:telnow_mobile_new/src/utils/provider.dart';
  13. class WebHistoryPage extends StatefulWidget {
  14. const WebHistoryPage({super.key});
  15. @override
  16. State<WebHistoryPage> createState() => _WebHistoryPageState();
  17. }
  18. class _WebHistoryPageState extends State<WebHistoryPage> with TickerProviderStateMixin {
  19. final HistoryFunction hisFunc = HistoryFunction();
  20. late AnimationController _animationController;
  21. var rating = [
  22. {'key': 1, 'image': "assets/image/icon/very_dissatisfied.png", 'label': 'disatisfied'.tr()},
  23. {'key': 2, 'image': "assets/image/icon/dissatisfied.png", 'label': 'lessSatisfied'.tr()},
  24. {'key': 3, 'image': "assets/image/icon/neutral.png", 'label': 'satisfied'.tr()},
  25. {'key': 4, 'image': "assets/image/icon/satisfied.png", 'label': 'verySatisfied'.tr()},
  26. {'key': 5, 'image': "assets/image/icon/very_satisfied.png", 'label': 'reallyPleased'.tr()},
  27. ];
  28. bool _timeLimit = false;
  29. @override
  30. void initState() {
  31. // print(U.newServerVersion(1716279633));
  32. Provider.of<HistoryModule>(context, listen: false).reset();
  33. _animationController = new AnimationController(vsync: this, duration: Duration(seconds: 1));
  34. _animationController.repeat(reverse: true);
  35. WidgetsBinding.instance.addPostFrameCallback((_) {
  36. hisFunc.getActiveForum(context);
  37. });
  38. // TODO: implement initState
  39. super.initState();
  40. }
  41. @override
  42. void dispose() {
  43. _animationController.dispose();
  44. super.dispose();
  45. }
  46. @override
  47. Widget build(BuildContext context) {
  48. return Provider.of<UserModule>(context).resetData() ? RefreshPage(() {
  49. Provider.of<UserModule>(context, listen: false).setResetData(false);
  50. hisFunc.getActiveForum(context);
  51. }) : Scaffold(
  52. backgroundColor: backgroundColor,
  53. appBar: PreferredSize(preferredSize: Size.fromHeight(0), child: AppBar(elevation: 0, backgroundColor: primaryColor)),
  54. body: Column(
  55. children: [
  56. Container(
  57. padding: EdgeInsets.symmetric(vertical: 25, horizontal: 100),
  58. child: Row(
  59. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  60. children: [
  61. Text('history'.tr(), style: TextStyle(color: textColor, fontSize: 17, fontWeight: FontWeight.w500), overflow: TextOverflow.ellipsis),
  62. Provider.of<HistoryModule>(context).multiSelectMode() ? GestureDetector(
  63. child: Container(
  64. padding: EdgeInsets.fromLTRB(16, 9, 16, 9),
  65. child: Row(
  66. children: [
  67. Text('delete'.tr(), style: TextStyle(color: primaryColor, fontSize: 14)),
  68. SizedBox(width: 5),
  69. U.iconsax('trash', color: primaryColor, size: 20)
  70. ],
  71. ),
  72. decoration: BoxDecoration(color: primaryColor.withValues(alpha: 0.1), border: Border.all(color: primaryColor), borderRadius: BorderRadius.all(Radius.circular(50))),
  73. ),
  74. onTap: () => hisFunc.deleteData(context),
  75. ) : GestureDetector(
  76. child: Text('buttonBack'.tr(), style: TextStyle(color: primaryColor, fontSize: 14)),
  77. onTap: (){
  78. var pid = U.getPidFromUrl(context.router.currentUrl);
  79. context.router.removeLast();
  80. context.navigateToPath("/app/$pid/menu");
  81. },
  82. )
  83. ],
  84. ),
  85. ),
  86. divider(),
  87. Container(
  88. padding: EdgeInsets.symmetric(vertical: 25, horizontal: 100),
  89. child: Column(
  90. crossAxisAlignment: CrossAxisAlignment.start,
  91. children: [
  92. Row(
  93. children: [
  94. GestureDetector(
  95. child: Container(
  96. padding: EdgeInsets.symmetric(vertical: 5, horizontal: 16),
  97. child: Text('ongoing'.tr(), style: TextStyle(color: Provider.of<HistoryModule>(context).selectedFilter() == 1 ? textColor : textColor.withValues(alpha: 0.65), fontSize: 16)),
  98. decoration: BoxDecoration(color: Colors.white, border: Border(bottom: BorderSide(color: Provider.of<HistoryModule>(context).selectedFilter() == 1 ? primaryColor : primaryColor.withValues(alpha: 0.3), width: Provider.of<HistoryModule>(context).selectedFilter() == 1 ? 2 : 1))),
  99. ),
  100. onTap: () {
  101. if (!Provider.of<HistoryModule>(context, listen: false).isLoadHistory()) {
  102. Provider.of<HistoryModule>(context, listen: false).setPressAttention(0);
  103. Provider.of<HistoryModule>(context, listen: false).setSelectedFilter(1);
  104. hisFunc.onRefresh(context);
  105. }
  106. },
  107. ),
  108. GestureDetector(
  109. child: Container(
  110. padding: EdgeInsets.symmetric(vertical: 5, horizontal: 16),
  111. child: Text('done'.tr(), style: TextStyle(color: Provider.of<HistoryModule>(context).selectedFilter() == 0 ? textColor : textColor.withValues(alpha: 0.65), fontSize: 16)),
  112. decoration: BoxDecoration(color: Colors.white, border: Border(bottom: BorderSide(color: Provider.of<HistoryModule>(context).selectedFilter() == 0 ? primaryColor : primaryColor.withValues(alpha: 0.3), width: Provider.of<HistoryModule>(context).selectedFilter() == 0 ? 2 : 1))),
  113. ),
  114. onTap: () {
  115. if (!Provider.of<HistoryModule>(context, listen: false).isLoadHistory()) {
  116. Provider.of<HistoryModule>(context, listen: false).setPressAttention(0);
  117. Provider.of<HistoryModule>(context, listen: false).setSelectedFilter(0);
  118. hisFunc.onRefresh(context);
  119. }
  120. },
  121. ),
  122. ],
  123. ),
  124. SizedBox(height: 20),
  125. Provider.of<HistoryModule>(context).selectedFilter() == 0 ? doneFilter() : ongoingFilter(),
  126. ],
  127. ),
  128. ),
  129. Expanded(
  130. child: Provider.of<UserModule>(context).user().isNotEmpty ? Container(
  131. width: double.infinity,
  132. padding: EdgeInsets.symmetric(horizontal: 100),
  133. child: LazyLoadScrollView(
  134. onEndOfPage: () => hisFunc.getMission(context),
  135. scrollOffset: 500,
  136. child: EasyRefresh(
  137. header: MaterialHeader(clamping: true, color: primaryColor),
  138. onRefresh: ()=>hisFunc.onRefresh(context),
  139. child: Provider.of<HistoryModule>(context).selectedFilter() == 0 ? doneContainer() : ongoingContainer(),
  140. ),
  141. ),
  142. ) : Provider.of<UserModule>(context).resetData() ? Container() : _timeLimit ? showButton(context) : loadingTemplate(() {if(mounted) setState(()=>_timeLimit=true);},),
  143. )
  144. ],
  145. ),
  146. );
  147. }
  148. Widget ongoingFilter() {
  149. return SingleChildScrollView(
  150. scrollDirection: Axis.horizontal,
  151. child: Row(
  152. children: List.generate(hisFunc.ongoingList.length, (i) {
  153. return GestureDetector(
  154. child: Container(
  155. margin: EdgeInsets.only(right: 16),
  156. padding: EdgeInsets.symmetric(vertical: 8, horizontal: 16),
  157. child: Text(hisFunc.ongoingList[i]['title'], style: TextStyle(color: Provider.of<HistoryModule>(context).checkPressAttention(hisFunc.ongoingList[i]['value']) ? Colors.white : textColor, fontSize: 16)),
  158. decoration: BoxDecoration(
  159. color: Provider.of<HistoryModule>(context).checkPressAttention(hisFunc.ongoingList[i]['value']) ? primaryColor : Color(0xffF2F8F7),
  160. border: Border.all(color: Provider.of<HistoryModule>(context).checkPressAttention(hisFunc.ongoingList[i]['value']) ? primaryColor : Color(0xffBEC1C1)),
  161. borderRadius: BorderRadius.all(Radius.circular(50))),
  162. ),
  163. onTap: () {
  164. if (!Provider.of<HistoryModule>(context, listen: false).isLoadHistory()) {
  165. if (Provider.of<HistoryModule>(context, listen: false).checkPressAttention(hisFunc.ongoingList[i]['value'])) {
  166. Provider.of<HistoryModule>(context, listen: false).setPressAttention(0);
  167. hisFunc.onRefresh(context);
  168. } else {
  169. Provider.of<HistoryModule>(context, listen: false).setPressAttention(hisFunc.ongoingList[i]['value']);
  170. hisFunc.onRefresh(context);
  171. }
  172. }
  173. },
  174. );
  175. }),
  176. ),
  177. );
  178. }
  179. Widget ongoingContainer() {
  180. return SingleChildScrollView(
  181. child: Column(
  182. children: [
  183. U.newServerVersion(1709864293) && !U.getInternetStatus() ? Column(
  184. children: List.generate(Provider.of<HistoryModule>(context).dataPending().length, (i) {
  185. return GestureDetector(
  186. child: Container(
  187. width: double.infinity,
  188. padding: EdgeInsets.all(15),
  189. margin: EdgeInsets.only(bottom: 15),
  190. decoration: BoxDecoration(color: Colors.white, border: Border.all(color: textColor.withValues(alpha: 0.15)), borderRadius: BorderRadius.all(Radius.circular(12))),
  191. child: Column(
  192. children: [
  193. Row(
  194. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  195. children: [
  196. Text(convertDate(Provider.of<HistoryModule>(context).dataPending()[i]['datetimeRequest'], context.locale.toString()), style: TextStyle(color: primaryColor, fontSize: 14)),
  197. renderStatus('sending'.tr(), Color(0xff02C539).withValues(alpha: 0.2))
  198. ],
  199. ),
  200. SizedBox(height: 10),
  201. divider(),
  202. SizedBox(height: 10),
  203. Row(
  204. children: [
  205. imageTiles(imageUrl: Provider.of<HistoryModule>(context).dataPending()[i]['image'] ?? "null"),
  206. SizedBox(width: 25),
  207. Expanded(
  208. child: Column(
  209. crossAxisAlignment: CrossAxisAlignment.start,
  210. children: [
  211. Text(Provider.of<HistoryModule>(context).dataPending()[i]['title'], style: TextStyle(color: textColor, fontWeight: FontWeight.w500), overflow: TextOverflow.ellipsis),
  212. SizedBox(height: 10),
  213. Text(Provider.of<HistoryModule>(context).dataPending()[i][U.langColumn(context, 'sub')], style: TextStyle(color: textColor), overflow: TextOverflow.ellipsis),
  214. SizedBox(height: 5),
  215. Text(Provider.of<HistoryModule>(context).dataPending()[i][U.langColumn(context, 'desc')], style: TextStyle(color: textColor), overflow: TextOverflow.ellipsis),
  216. dashed(top: 10, bottom: 10),
  217. Row(
  218. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  219. children: [
  220. Text('location'.tr()+': '+Provider.of<HistoryModule>(context).dataPending()[i]['location'], style: TextStyle(color: textColor, fontSize: 14), overflow: TextOverflow.ellipsis),
  221. Row(
  222. children: [
  223. Container(
  224. width: 25, height: 25,
  225. decoration: BoxDecoration(image: DecorationImage(image: AssetImage('assets/image/general/Hourglass.png'), fit: BoxFit.cover)),
  226. ),
  227. SizedBox(width: 8),
  228. Text('pending_info_tiles'.tr(), style: TextStyle(color: textColor, fontSize: 14))
  229. ],
  230. )
  231. ],
  232. )
  233. ],
  234. ),
  235. )
  236. ],
  237. )
  238. ],
  239. ),
  240. ),
  241. onTap: () {
  242. if(!U.getInternetStatus()){
  243. // navigateTo(context, MobHistoryDetailPendingPage(data: Provider.of<HistoryModule>(context, listen: false).dataPending()[i])).then((val) {
  244. // val = val??false;
  245. // if(val) hisFunc.onRefresh(context);
  246. // });
  247. }
  248. else{
  249. hisFunc.onRefresh(context);
  250. }
  251. },
  252. );
  253. }),
  254. ) : Container(),
  255. Column(
  256. children: List.generate(Provider.of<HistoryModule>(context).dataMisi().length, (i) {
  257. return GestureDetector(
  258. child: Container(
  259. width: double.infinity,
  260. padding: EdgeInsets.all(15),
  261. margin: EdgeInsets.only(bottom: 15),
  262. decoration: BoxDecoration(color: Colors.white, border: Border.all(color: textColor.withValues(alpha: 0.15)), borderRadius: BorderRadius.all(Radius.circular(12))),
  263. child: Column(
  264. children: [
  265. Row(
  266. children: [
  267. Text(convertDate(Provider.of<HistoryModule>(context).dataMisi()[i]['datetimeRequest'], context.locale.toString()), style: TextStyle(color: primaryColor, fontSize: 14)),
  268. SizedBox(width: 15),
  269. Expanded(
  270. child: Text('ticketNumber'.tr()+': '+Provider.of<HistoryModule>(context).dataMisi()[i]['ticketNo'], style: TextStyle(color: textColor, fontSize: 14), overflow: TextOverflow.ellipsis),
  271. ),
  272. Provider.of<HistoryModule>(context).dataMisi()[i]['currentState'] == 'DIMULAI' ? Container(
  273. child: Row(
  274. children: [
  275. Container(
  276. width: 25, height: 25,
  277. decoration: BoxDecoration(
  278. border: Border.all(color: primaryColor), borderRadius: BorderRadius.all(Radius.circular(25)),
  279. image: DecorationImage(image: AssetImage('assets/image/general/Avatar.jpg'), fit: BoxFit.cover)
  280. ),
  281. ),
  282. SizedBox(width: 8),
  283. Text(Provider.of<HistoryModule>(context).dataMisi()[i]['servantNameStart'] + 'isWorking'.tr(), style: TextStyle(color: textColor, fontSize: 14), overflow: TextOverflow.ellipsis)
  284. ],
  285. ),
  286. ) : Container(),
  287. Provider.of<HistoryModule>(context).dataMisi()[i]['_activeHoldRequest'] != null?renderStatus('hold'.tr(), Color(0xffD3D3D3)):Provider.of<HistoryModule>(context).dataMisi()[i]['currentState'] == 'DIMULAI'?renderStatus('onProgress'.tr(), Color(0xffCCA600).withValues(alpha: 0.2)):renderStatus('queued'.tr(), Color(0xff02C539).withValues(alpha: 0.2))
  288. ],
  289. ),
  290. SizedBox(height: 10),
  291. divider(),
  292. SizedBox(height: 10),
  293. Row(
  294. children: [
  295. imageTiles(imageUrl: Provider.of<HistoryModule>(context).dataMisi()[i]['_requestImage'] ?? "null", width: 150, height: 120),
  296. SizedBox(width: 25),
  297. Expanded(
  298. child: Column(
  299. crossAxisAlignment: CrossAxisAlignment.start,
  300. children: [
  301. Text(Provider.of<HistoryModule>(context).dataMisi()[i][U.langColumn(context, 'requestGroupDescription')], style: TextStyle(color: textColor, fontSize: 16), overflow: TextOverflow.ellipsis),
  302. SizedBox(height: 10),
  303. Text(Provider.of<HistoryModule>(context).dataMisi()[i][U.langColumn(context, 'requestSubject')], style: TextStyle(color: textColor, fontWeight: FontWeight.w600), overflow: TextOverflow.ellipsis),
  304. SizedBox(height: 5),
  305. Text(Provider.of<HistoryModule>(context).dataMisi()[i][U.langColumn(context, '_subjectDescription')]??'', style: TextStyle(color: textColor), overflow: TextOverflow.ellipsis),
  306. dashed(top: 10, bottom: 10),
  307. renderRequested(Provider.of<HistoryModule>(context).dataMisi()[i]),
  308. Row(
  309. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  310. crossAxisAlignment: CrossAxisAlignment.center ,
  311. children: [
  312. Text('location'.tr()+': '+Provider.of<HistoryModule>(context).dataMisi()[i]['ipphoneExtLocation'], style: TextStyle(color: textColor, fontSize: 14), overflow: TextOverflow.ellipsis),
  313. Provider.of<HistoryModule>(context).dataMisi()[i]['_activeHoldRequest'] != null ? Container(
  314. child: Row(
  315. children: [
  316. Container(
  317. width: 25, height: 25,
  318. decoration: BoxDecoration(image: DecorationImage(image: AssetImage('assets/image/general/Watch.png'), fit: BoxFit.cover)),
  319. ),
  320. SizedBox(width: 8),
  321. Text(Provider.of<HistoryModule>(context).dataMisi()[i]['_activeHoldRequest']['description'], style: TextStyle(color: textColor, fontSize: 14))
  322. ],
  323. ),
  324. ) : Provider.of<HistoryModule>(context).dataMisi()[i]['_hasForum'] && Provider.of<HistoryModule>(context).dataMisi()[i]['_forumMsg'] != null ? ConstrainedBox(
  325. constraints: BoxConstraints(minWidth: 10),
  326. child: Row(
  327. children: [
  328. FadeTransition(opacity: _animationController, child: U.iconsax('messages-3', color: primaryColor)),
  329. SizedBox(width: 8),
  330. Text('“${Provider.of<HistoryModule>(context).dataMisi()[i]['_forumMsg']}”', style: TextStyle(color: textColor.withValues(alpha: 0.75), fontSize: 14, fontStyle: FontStyle.italic))
  331. ],
  332. ),
  333. ) : Container(),
  334. ],
  335. ),
  336. ],
  337. ),
  338. )
  339. ],
  340. ),
  341. ],
  342. ),
  343. ),
  344. onTap: () => navigateTo(context, WebHistoryDetailPage(index: i)).then((val) {
  345. val = val??false;
  346. if(val) Provider.of<HistoryModule>(context, listen: false).cancelMisi(i);
  347. }),
  348. );
  349. }),
  350. ),
  351. !Provider.of<HistoryModule>(context).stopLoadHistory() || (Provider.of<HistoryModule>(context).isLoadHistory() && Provider.of<HistoryModule>(context).page() > 0)
  352. ? Container(margin: EdgeInsets.only(top: Provider.of<HistoryModule>(context).page() > 0 ? 0 : 50), child: loadingTemplate(() {},))
  353. : Provider.of<HistoryModule>(context).dataMisi().isEmpty && Provider.of<HistoryModule>(context).dataPending().isEmpty
  354. ? NoDataPage()
  355. : Container(),
  356. ],
  357. ),
  358. );
  359. }
  360. Widget doneFilter() {
  361. return Row(
  362. children: List.generate(hisFunc.doneList.length, (i) {
  363. return GestureDetector(
  364. child: Container(
  365. margin: EdgeInsets.only(right: 16),
  366. padding: EdgeInsets.symmetric(vertical: 8, horizontal: 16),
  367. decoration: BoxDecoration(
  368. color: Provider.of<HistoryModule>(context).checkPressAttention(hisFunc.doneList[i]['value']) ? primaryColor : Color(0xffF2F8F7),
  369. border: Border.all(color: Provider.of<HistoryModule>(context).checkPressAttention(hisFunc.doneList[i]['value']) ? primaryColor : Color(0xffBEC1C1)),
  370. borderRadius: BorderRadius.all(Radius.circular(50))),
  371. child: Text(hisFunc.doneList[i]['title'], style: TextStyle(color: Provider.of<HistoryModule>(context).checkPressAttention(hisFunc.doneList[i]['value']) ? Colors.white : textColor, fontSize: 16)),
  372. ),
  373. onTap: () {
  374. if (!Provider.of<HistoryModule>(context, listen: false).isLoadHistory()) {
  375. if (Provider.of<HistoryModule>(context, listen: false).checkPressAttention(hisFunc.doneList[i]['value'])) {
  376. Provider.of<HistoryModule>(context, listen: false).setPressAttention(0);
  377. hisFunc.onRefresh(context);
  378. } else {
  379. Provider.of<HistoryModule>(context, listen: false).setPressAttention(hisFunc.doneList[i]['value']);
  380. hisFunc.onRefresh(context);
  381. }
  382. }
  383. },
  384. );
  385. }),
  386. );
  387. }
  388. Widget doneContainer() {
  389. return SingleChildScrollView(
  390. child: Column(
  391. children: [
  392. Column(
  393. children: List.generate(Provider.of<HistoryModule>(context).dataMisi().length, (i) {
  394. return GestureDetector(
  395. child: Container(
  396. width: double.infinity,
  397. padding: EdgeInsets.all(15),
  398. margin: EdgeInsets.only(bottom: 15),
  399. decoration: BoxDecoration(color: Colors.white, border: Border.all(color: textColor.withValues(alpha: 0.15)), borderRadius: BorderRadius.all(Radius.circular(12))),
  400. child: Column(
  401. children: [
  402. Row(
  403. children: [
  404. Text(convertDate(Provider.of<HistoryModule>(context).dataMisi()[i]['datetimeRequest'], context.locale.toString()), style: TextStyle(color: primaryColor, fontSize: 14)),
  405. SizedBox(width: 15),
  406. Expanded(
  407. child: Text('ticketNumber'.tr()+': '+Provider.of<HistoryModule>(context).dataMisi()[i]['ticketNo'], style: TextStyle(color: textColor, fontSize: 14), overflow: TextOverflow.ellipsis),
  408. ),
  409. Provider.of<HistoryModule>(context).dataMisi()[i]['currentState'] == 'DISELESAIKAN' || Provider.of<HistoryModule>(context).dataMisi()[i]['currentState'] == 'TUNTAS' ? renderStatus('stateFinish'.tr(), primaryColor.withValues(alpha: 0.4)) : renderStatus('stateCancel'.tr(), Color(0xffD81010).withValues(alpha: 0.4))
  410. ],
  411. ),
  412. SizedBox(height: 10),
  413. divider(),
  414. SizedBox(height: 10),
  415. Row(
  416. children: [
  417. imageTiles(imageUrl: Provider.of<HistoryModule>(context).dataMisi()[i]['_requestImage'] ?? "null", width: 150, height: 120),
  418. SizedBox(width: 25),
  419. Expanded(
  420. child: Column(
  421. crossAxisAlignment: CrossAxisAlignment.start,
  422. children: [
  423. Text(Provider.of<HistoryModule>(context).dataMisi()[i][U.langColumn(context, 'requestGroupDescription')], style: TextStyle(color: textColor, fontSize: 16), overflow: TextOverflow.ellipsis),
  424. SizedBox(height: 10),
  425. Text(Provider.of<HistoryModule>(context).dataMisi()[i][U.langColumn(context, 'requestSubject')], style: TextStyle(color: textColor, fontWeight: FontWeight.w600), overflow: TextOverflow.ellipsis),
  426. SizedBox(height: 5),
  427. Text(Provider.of<HistoryModule>(context).dataMisi()[i][U.langColumn(context, '_subjectDescription')]??'', style: TextStyle(color: textColor), overflow: TextOverflow.ellipsis),
  428. dashed(top: 10, bottom: 10),
  429. renderRequested(Provider.of<HistoryModule>(context).dataMisi()[i]),
  430. Text('location'.tr()+': '+Provider.of<HistoryModule>(context).dataMisi()[i]['ipphoneExtLocation'], style: TextStyle(color: textColor, fontSize: 14), overflow: TextOverflow.ellipsis),
  431. ],
  432. ),
  433. )
  434. ],
  435. ),
  436. SizedBox(height: 10),
  437. divider(),
  438. SizedBox(height: 10),
  439. Row(
  440. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  441. children: [
  442. !Provider.of<HistoryModule>(context).dataMisi()[i]['autoResponse'] && Provider.of<HistoryModule>(context).dataMisi()[i]['servantIdentityStart'] != '#system' && (Provider.of<HistoryModule>(context).dataMisi()[i]['currentState'] == 'TUNTAS' || Provider.of<HistoryModule>(context).dataMisi()[i]['currentState'] == 'DISELESAIKAN') ? Container(
  443. child: hisFunc.askForRate(Provider.of<HistoryModule>(context, listen: true).dataMisi()[i]) ? GestureDetector(
  444. child: Container(
  445. padding: EdgeInsets.symmetric(vertical: 4, horizontal: 16),
  446. child: Text('rateReq'.tr(), style: TextStyle(color: secondaryColor, fontSize: 14), overflow: TextOverflow.ellipsis),
  447. decoration: BoxDecoration(color: Colors.white, border: Border.all(color: secondaryColor), borderRadius: BorderRadius.all(Radius.circular(50))),
  448. ),
  449. onTap: () {
  450. U.newServerVersion(1716279633) ? rateMissionNew(context, Provider.of<HistoryModule>(context, listen: false).dataMisi()[i], i) : rateMission(context, Provider.of<HistoryModule>(context, listen: false).dataMisi()[i], i);
  451. },
  452. ) : !hisFunc.isAutoResponse(Provider.of<HistoryModule>(context).dataMisi()[i]) ? Row(
  453. children: [
  454. Image(image: AssetImage(rating[Provider.of<HistoryModule>(context).dataMisi()[i]['satisfactionRate'] - 1]['image'].toString()), width: 25),
  455. SizedBox(width: 5),
  456. Text(rating[Provider.of<HistoryModule>(context).dataMisi()[i]['satisfactionRate'] - 1]['label'].toString(), style: TextStyle(color: textColor, fontSize: 14), overflow: TextOverflow.ellipsis),
  457. ],
  458. ) : Container(),
  459. ) : message(Provider.of<HistoryModule>(context).dataMisi()[i]['_hasForum'], Provider.of<HistoryModule>(context).dataMisi()[i]['_forumMsg'] ?? "null"),
  460. GestureDetector(
  461. child: Container(
  462. padding: EdgeInsets.symmetric(vertical: 4, horizontal: 16),
  463. child: Text('reqAgain'.tr(), style: TextStyle(color: primaryColor, fontSize: 14)),
  464. decoration: BoxDecoration(color: Colors.white, border: Border.all(color: primaryColor), borderRadius: BorderRadius.all(Radius.circular(50))),
  465. ),
  466. onTap: () => hisFunc.requestAgainAction(context, i),
  467. )
  468. ],
  469. ),
  470. ],
  471. ),
  472. ),
  473. onTap: () {
  474. if (Provider.of<HistoryModule>(context, listen: false).multiSelectMode()) {
  475. hisFunc.selectedController(context, i);
  476. } else {
  477. navigateTo(context, WebHistoryDetailPage(index: i));
  478. }
  479. },
  480. onLongPress: () => hisFunc.selectedController(context, i),
  481. );
  482. })
  483. ),
  484. !Provider.of<HistoryModule>(context).stopLoadHistory() || (Provider.of<HistoryModule>(context).isLoadHistory() && Provider.of<HistoryModule>(context).page() > 0)
  485. ? Container(margin: EdgeInsets.only(top: Provider.of<HistoryModule>(context).page() > 0 ? 0 : 50), child: loadingTemplate(() {},))
  486. : Provider.of<HistoryModule>(context).dataMisi().length == 0 ? NoDataPage() : Container(),
  487. ],
  488. ),
  489. );
  490. }
  491. Widget renderRequested(list){
  492. if(list['receptionistId'] != null){
  493. var user = Provider.of<UserModule>(context, listen: false).user();
  494. if(user['roomAttendant'] && user['userId'] != list['informantUserId'] && user['userId'] == list['receptionistId']){
  495. return Column(
  496. crossAxisAlignment: CrossAxisAlignment.start,
  497. children: [
  498. Text('${'requestedFor'.tr()}: ${list['informantName']??'-'}' ,style: TextStyle(color: textColor, fontSize: 13), overflow: TextOverflow.ellipsis),
  499. SizedBox(height: 5),
  500. ],
  501. );
  502. }
  503. if(user['userId'] == list['informantUserId'] && user['userId'] != list['receptionistId']){
  504. return Column(
  505. crossAxisAlignment: CrossAxisAlignment.start,
  506. children: [
  507. Text('${'requestedBy'.tr()}: ${list['receptionistName']??''}' ,style: TextStyle(color: textColor, fontSize: 13), overflow: TextOverflow.ellipsis),
  508. SizedBox(height: 5),
  509. ],
  510. );
  511. }
  512. }
  513. return Container();
  514. }
  515. Widget message(bool _hasForum, String _forumMsg, {double top = 0}) {
  516. return _hasForum ? Container(
  517. margin: EdgeInsets.only(top: top),
  518. child: Row(
  519. children: [
  520. FadeTransition(opacity: _animationController, child: U.iconsax('messages-3', color: primaryColor)),
  521. SizedBox(width: 8),
  522. Text('“$_forumMsg”', style: TextStyle(color: textColor.withValues(alpha: 0.75), fontSize: 14, fontStyle: FontStyle.italic), overflow: TextOverflow.ellipsis),
  523. ],
  524. ),
  525. ) : Container();
  526. }
  527. renderStatus(text, color){
  528. return Container(
  529. padding: EdgeInsets.symmetric(vertical: 3, horizontal: 10),
  530. margin: EdgeInsets.only(left: 10),
  531. child: Text(text, style: TextStyle(fontSize: 12, color: textColor)),
  532. decoration: BoxDecoration(
  533. color: color, borderRadius: BorderRadius.all(Radius.circular(3))
  534. ),
  535. );
  536. }
  537. rateMission(BuildContext context, list, index) {
  538. showDialog(
  539. context: context,
  540. builder: (contexts) {
  541. int tempRating = 0;
  542. String description = '';
  543. return AlertDialog(
  544. backgroundColor: Colors.transparent,
  545. contentPadding: EdgeInsets.all(0),
  546. content: StatefulBuilder(
  547. builder: (contextt, setStates) {
  548. return Container(
  549. decoration: BoxDecoration(color: secondaryColor, borderRadius: BorderRadius.all(Radius.circular(25))),
  550. child: Column(
  551. mainAxisSize: MainAxisSize.min,
  552. crossAxisAlignment: CrossAxisAlignment.start,
  553. children: [
  554. Padding(
  555. padding: EdgeInsets.symmetric(vertical: 12, horizontal: 16),
  556. child: Column(
  557. crossAxisAlignment: CrossAxisAlignment.start,
  558. children: [
  559. Text(list[U.langColumn(context, 'requestSubject')], style: TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.w600)),
  560. SizedBox(height: 4),
  561. Row(
  562. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  563. children: [
  564. Text('ticketNumber'.tr()+': '+list['ticketNo'], style: TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w300)),
  565. Text(convertDate(list['datetimeRequest'], context.locale.toString()), style: TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w300)),
  566. ],
  567. ),
  568. ],
  569. ),
  570. ),
  571. Container(
  572. padding: EdgeInsets.fromLTRB(30, 15, 30, 15),
  573. decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(25))),
  574. child: Column(
  575. children: [
  576. Text('satisfactionAsk'.tr(), style: TextStyle(fontSize: 16)),
  577. SizedBox(height: 12),
  578. Row(
  579. mainAxisAlignment: MainAxisAlignment.center,
  580. children: List.generate(rating.length, (i) {
  581. return Expanded(
  582. child: GestureDetector(
  583. child: Image(
  584. image: AssetImage(rating[i]['image'].toString()),
  585. color: Colors.white.withValues(alpha: tempRating == rating[i]['key'] ? 1 : 0.3),
  586. colorBlendMode: BlendMode.modulate,
  587. ),
  588. // child: Icon(rating[i]['icon'] as IconData, color: tempRating == rating[i]['key']?rating[i]['color'] as Color:Colors.grey),
  589. onTap: () {
  590. setStates(() {
  591. tempRating = rating[i]['key'] as int;
  592. description = rating[i]['label'] as String;
  593. });
  594. },
  595. ),
  596. );
  597. }),
  598. ),
  599. SizedBox(height: 6),
  600. Text(description, style: TextStyle(color: textColor, fontSize: 14, fontWeight: FontWeight.w300), textAlign: TextAlign.center),
  601. SizedBox(height: 20),
  602. Opacity(
  603. opacity: tempRating > 0 ? 1 : 0,
  604. child: Row(
  605. mainAxisAlignment: MainAxisAlignment.center,
  606. children: [
  607. Expanded(child: buttonTemplate(text: 'textCancel'.tr(), backgroundColor: Colors.black12, borderColor: Colors.black12, textColor: textColor, height: 40, action: (){
  608. navigateBack(contexts);
  609. })),
  610. SizedBox(width: 20),
  611. Expanded(child: buttonTemplate(text: 'save_rating'.tr(), backgroundColor: primaryColor, borderColor: primaryColor, height: 40, action: ()async{
  612. if (tempRating > 0) {
  613. var data = {"ticketNo": list['ticketNo'], "rateSatisfy": tempRating};
  614. var res = await ApiAuthProvider() .postData('/api/requestHistories/rateSatisfy', null, data, contexts);
  615. if (res != null) {
  616. Provider.of<HistoryModule>(context, listen: false).setSatisfaction(index, tempRating);
  617. navigateBack(contexts);
  618. }
  619. }
  620. }))
  621. ],
  622. ),
  623. )
  624. ],
  625. ),
  626. )
  627. ],
  628. ),
  629. );
  630. },
  631. ),
  632. );
  633. }
  634. );
  635. }
  636. rateMissionNew(BuildContext context, list, index) {
  637. String locale = context.locale.toString();
  638. showDialog(
  639. context: context,
  640. builder: (contexts) {
  641. int tempRating = 0;
  642. String description = '';
  643. String ratingAspect = '';
  644. TextEditingController controllerOptOther = new TextEditingController();
  645. List aspectList = list['_ratingAspect'+locale[0].toUpperCase()+locale[1]] != null && list['_ratingAspect'+locale[0].toUpperCase()+locale[1]].trim() != '' ? list['_ratingAspect'+locale[0].toUpperCase()+locale[1]].split(';') : [];
  646. if(aspectList.isNotEmpty){
  647. aspectList.add('OTHER_OPTION');
  648. }
  649. else{
  650. ratingAspect = 'OTHER_OPTION';
  651. }
  652. return AlertDialog(
  653. backgroundColor: Colors.transparent,
  654. contentPadding: EdgeInsets.all(0),
  655. content: StatefulBuilder(
  656. builder: (contextt, setStates) {
  657. return Container(
  658. decoration: BoxDecoration(color: secondaryColor, borderRadius: BorderRadius.all(Radius.circular(25))),
  659. child: Column(
  660. mainAxisSize: MainAxisSize.min,
  661. crossAxisAlignment: CrossAxisAlignment.start,
  662. children: [
  663. Padding(
  664. padding: EdgeInsets.symmetric(vertical: 12, horizontal: 16),
  665. child: Column(
  666. crossAxisAlignment: CrossAxisAlignment.start,
  667. children: [
  668. Text(list[U.langColumn(context, 'requestSubject')], style: TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.w600)),
  669. SizedBox(height: 4),
  670. Row(
  671. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  672. children: [
  673. Text('ticketNumber'.tr()+': '+list['ticketNo'], style: TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w300)),
  674. Text(convertDate(list['datetimeRequest'], context.locale.toString()), style: TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w300)),
  675. ],
  676. ),
  677. ],
  678. ),
  679. ),
  680. Container(
  681. padding: EdgeInsets.fromLTRB(30, 15, 30, 15),
  682. decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(25))),
  683. child: Column(
  684. children: [
  685. Text('satisfactionAsk'.tr(), style: TextStyle(fontSize: 16)),
  686. SizedBox(height: 12),
  687. Row(
  688. mainAxisAlignment: MainAxisAlignment.center,
  689. children: List.generate(rating.length, (i) {
  690. return Expanded(
  691. child: GestureDetector(
  692. child: Image(
  693. image: AssetImage(rating[i]['image'].toString()),
  694. color: Colors.white.withValues(alpha: tempRating == rating[i]['key'] ? 1 : 0.3),
  695. colorBlendMode: BlendMode.modulate,
  696. ),
  697. onTap: () {
  698. setStates(() {
  699. tempRating = rating[i]['key'] as int;
  700. description = rating[i]['label'] as String;
  701. });
  702. },
  703. ),
  704. );
  705. }),
  706. ),
  707. SizedBox(height: 6),
  708. Text(description, style: TextStyle(color: textColor, fontSize: 14, fontWeight: FontWeight.w300), textAlign: TextAlign.center),
  709. tempRating != 0 ? SizedBox(height: 20) : Container(),
  710. tempRating != 0 ? separator() : Container(),
  711. tempRating != 0 ? SizedBox(height: 20) : Container(),
  712. tempRating != 0 ? Column(
  713. crossAxisAlignment: CrossAxisAlignment.start,
  714. children: [
  715. Text('whatMakesYou'.tr()+' '+description+'?', style: TextStyle(fontSize: 16)),
  716. SizedBox(height: 12),
  717. Wrap(
  718. runSpacing: 10, spacing: 10,
  719. children: List.generate(aspectList.length, (i){
  720. return GestureDetector(
  721. child: Container(
  722. padding: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
  723. child: Text(aspectList[i]=='OTHER_OPTION'?'letMeWrite'.tr():aspectList[i], style: TextStyle(color: textColor)),
  724. decoration: BoxDecoration(
  725. color: aspectList[i] == ratingAspect ? primaryColor.withValues(alpha: 0.3) : Colors.white,
  726. border: Border.all(color: aspectList[i] == ratingAspect ? primaryColor : textColor),
  727. borderRadius: BorderRadius.all(Radius.circular(50))
  728. ),
  729. ),
  730. onTap: (){
  731. setStates(() {
  732. ratingAspect = ratingAspect == aspectList[i]?'':aspectList[i];
  733. });
  734. },
  735. );
  736. }),
  737. ),
  738. aspectList.isNotEmpty ? SizedBox(height: 10) : Container(),
  739. ratingAspect == 'OTHER_OPTION' ? TextFormField(
  740. maxLines: 1, maxLength: 50,
  741. autofocus: true,
  742. controller: controllerOptOther,
  743. style: TextStyle(fontSize: 14, color: Colors.black),
  744. decoration: InputDecoration(
  745. counterText: '',
  746. counterStyle: TextStyle(fontSize: 0),
  747. hintText: 'writeHere'.tr(),
  748. hintStyle: TextStyle(color: textColor.withValues(alpha: 0.5), fontSize: 14),
  749. filled: true, fillColor: Colors.white,
  750. isDense: true,
  751. contentPadding: EdgeInsets.all(13),
  752. prefixIcon: Padding(padding: EdgeInsets.only(left: 13, right: 13), child: U.iconsax('edit-2', color: textColor, size: 22)),
  753. enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Color(0xff262626).withValues(alpha: 0.5))),
  754. focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: primaryColor)),
  755. ),
  756. ) : Container(),
  757. ],
  758. ) : Container(),
  759. tempRating != 0 ? SizedBox(height: 20) : Container(),
  760. Opacity(
  761. opacity: tempRating > 0 ? 1 : 0,
  762. child: Row(
  763. mainAxisAlignment: MainAxisAlignment.center,
  764. children: [
  765. Expanded(child: buttonTemplate(text: 'textCancel'.tr(), backgroundColor: Colors.black12, borderColor: Colors.black12, textColor: textColor, height: 40, action: (){
  766. navigateBack(contexts);
  767. })),
  768. SizedBox(width: 20),
  769. Expanded(child: buttonTemplate(text: 'save_rating'.tr(), backgroundColor: primaryColor, borderColor: primaryColor, height: 40, action: ()async{
  770. if (tempRating > 0) {
  771. var data = {"ticketNo": list['ticketNo'], "rateSatisfy": tempRating};
  772. if(ratingAspect != 'OTHER_OPTION'){
  773. data['aspect'] = ratingAspect;
  774. }
  775. else if(ratingAspect == 'OTHER_OPTION' && controllerOptOther.text.isNotEmpty){
  776. data['aspect'] = controllerOptOther.text;
  777. }
  778. var res = await ApiAuthProvider() .postData('/api/requestHistories/rateSatisfy', null, data, contexts);
  779. if (res != null) {
  780. Provider.of<HistoryModule>(context, listen: false).setSatisfaction(index, tempRating);
  781. navigateBack(contexts);
  782. }
  783. }
  784. }))
  785. ],
  786. ),
  787. )
  788. ],
  789. ),
  790. )
  791. ],
  792. ),
  793. );
  794. },
  795. ),
  796. );
  797. }
  798. );
  799. }
  800. }