history_rating.dart 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import 'package:easy_localization/easy_localization.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:telnow_mobile_new/src/api/api_auth_provider.dart';
  4. import 'package:telnow_mobile_new/src/layouts/components/template.dart';
  5. import 'package:telnow_mobile_new/src/utils/U.dart';
  6. class MobHistoryRatingPage extends StatefulWidget {
  7. final Map<String, dynamic> data;
  8. const MobHistoryRatingPage(this.data, {super.key});
  9. @override
  10. State<MobHistoryRatingPage> createState() => _MobHistoryRatingPageState();
  11. }
  12. class _MobHistoryRatingPageState extends State<MobHistoryRatingPage> {
  13. int tempRating = 0;
  14. String description = '';
  15. String ratingAspect = '';
  16. List aspectList = [];
  17. TextEditingController controllerOptOther = new TextEditingController();
  18. var rating = [
  19. {'key': 1, 'image': "assets/image/icon/very_dissatisfied.png", 'label': 'disatisfied'.tr()},
  20. {'key': 2, 'image': "assets/image/icon/dissatisfied.png", 'label': 'lessSatisfied'.tr()},
  21. {'key': 3, 'image': "assets/image/icon/neutral.png", 'label': 'satisfied'.tr()},
  22. {'key': 4, 'image': "assets/image/icon/satisfied.png", 'label': 'verySatisfied'.tr()},
  23. {'key': 5, 'image': "assets/image/icon/very_satisfied.png", 'label': 'reallyPleased'.tr()},
  24. ];
  25. getAspectList(){
  26. String locale = context.locale.toString();
  27. List optionList = widget.data['_ratingAspect'+locale[0].toUpperCase()+locale[1]] != null && widget.data['_ratingAspect'+locale[0].toUpperCase()+locale[1]].trim() != '' ? widget.data['_ratingAspect'+locale[0].toUpperCase()+locale[1]].split(';') : [];
  28. if(optionList.isNotEmpty){
  29. optionList.add('OTHER_OPTION');
  30. }
  31. else{
  32. ratingAspect = 'OTHER_OPTION';
  33. }
  34. setState(() {
  35. aspectList = optionList;
  36. });
  37. }
  38. @override
  39. Widget build(BuildContext context) {
  40. getAspectList();
  41. return Scaffold(
  42. backgroundColor: backgroundColor,
  43. appBar: PreferredSize(preferredSize: Size.fromHeight(0), child: AppBar(elevation: 0, backgroundColor: secondaryColor)),
  44. body: Column(
  45. children: [
  46. Container(
  47. width: double.infinity,
  48. padding: EdgeInsets.all(20),
  49. color: secondaryColor,
  50. child: Column(
  51. crossAxisAlignment: CrossAxisAlignment.start,
  52. children: [
  53. Text(widget.data[U.langColumn(context, 'requestSubject')], style: TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.w600)),
  54. SizedBox(height: 4),
  55. Text(convertDate(widget.data['datetimeRequest'], context.locale.toString()), style: TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w300)),
  56. ],
  57. ),
  58. ),
  59. Expanded(
  60. child: Container(
  61. alignment: Alignment.topCenter,
  62. width: U.bodyWidth(context),
  63. child: SingleChildScrollView(
  64. child: Column(
  65. crossAxisAlignment: CrossAxisAlignment.center,
  66. children: [
  67. Container(
  68. padding: EdgeInsets.all(20),
  69. child: Column(
  70. children: [
  71. Text('satisfactionAsk'.tr(), style: TextStyle(fontSize: 16)),
  72. SizedBox(height: 12),
  73. Row(
  74. mainAxisAlignment: MainAxisAlignment.center,
  75. children: List.generate(rating.length, (i) {
  76. return Expanded(
  77. child: GestureDetector(
  78. child: Image(
  79. image: AssetImage(rating[i]['image'].toString()),
  80. color: Colors.white.withValues(alpha: tempRating == rating[i]['key'] ? 1 : 0.3),
  81. colorBlendMode: BlendMode.modulate,
  82. ),
  83. onTap: () {
  84. setState(() {
  85. tempRating = rating[i]['key'] as int;
  86. description = rating[i]['label'] as String;
  87. });
  88. },
  89. ),
  90. );
  91. }),
  92. ),
  93. SizedBox(height: 6),
  94. Text(description, style: TextStyle(color: textColor, fontSize: 14, fontWeight: FontWeight.w300), textAlign: TextAlign.center),
  95. ],
  96. ),
  97. ),
  98. tempRating != 0 ? separator() : Container(),
  99. tempRating != 0 ? Container(
  100. padding: EdgeInsets.all(20),
  101. child: Column(
  102. crossAxisAlignment: CrossAxisAlignment.start,
  103. children: [
  104. Text('whatMakesYou'.tr()+' '+description+'?', style: TextStyle(fontSize: 16)),
  105. SizedBox(height: 12),
  106. Wrap(
  107. runSpacing: 10, spacing: 10,
  108. children: List.generate(aspectList.length, (i){
  109. return GestureDetector(
  110. child: Container(
  111. padding: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
  112. child: Text(aspectList[i]=='OTHER_OPTION'?'letMeWrite'.tr():aspectList[i], style: TextStyle(color: textColor)),
  113. decoration: BoxDecoration(
  114. color: aspectList[i] == ratingAspect ? primaryColor.withValues(alpha: 0.3) : Colors.white,
  115. border: Border.all(color: aspectList[i] == ratingAspect ? primaryColor : textColor),
  116. borderRadius: BorderRadius.all(Radius.circular(50))
  117. ),
  118. ),
  119. onTap: (){
  120. setState(() {
  121. ratingAspect = ratingAspect == aspectList[i]?'':aspectList[i];
  122. });
  123. },
  124. );
  125. }),
  126. ),
  127. aspectList.isNotEmpty ? SizedBox(height: 10) : Container(),
  128. ratingAspect == 'OTHER_OPTION' ? otherOptTextField() : Container(),
  129. ],
  130. ),
  131. ) : Container(),
  132. SizedBox(height: 10),
  133. tempRating != 0 ? Row(
  134. mainAxisAlignment: MainAxisAlignment.center,
  135. children: [
  136. SizedBox(width: 20),
  137. Expanded(child: buttonTemplate(text: 'textCancel'.tr(), backgroundColor: Colors.black12, borderColor: Colors.black12, textColor: textColor, height: 40, action: (){
  138. Navigator.of(context).pop();
  139. })),
  140. SizedBox(width: 20),
  141. Expanded(child: buttonTemplate(text: 'save_rating'.tr(), backgroundColor: primaryColor, borderColor: primaryColor, height: 40, action: ()async{
  142. showLoading(context);
  143. var data = {"ticketNo": widget.data['ticketNo'], "rateSatisfy": tempRating};
  144. if(ratingAspect != 'OTHER_OPTION'){
  145. data['aspect'] = ratingAspect;
  146. }
  147. else if(ratingAspect == 'OTHER_OPTION' && controllerOptOther.text.isNotEmpty){
  148. data['aspect'] = controllerOptOther.text;
  149. }
  150. var res = await ApiAuthProvider() .postData('/api/requestHistories/rateSatisfy', null, data, context);
  151. closeLoading(context);
  152. if (res != null) {
  153. Navigator.of(context).pop(tempRating);
  154. }
  155. })),
  156. SizedBox(width: 20),
  157. ],
  158. ) : Container()
  159. ],
  160. ),
  161. ),
  162. ),
  163. )
  164. ],
  165. ),
  166. );
  167. }
  168. otherOptTextField(){
  169. return TextFormField(
  170. maxLines: 1, maxLength: 50,
  171. controller: controllerOptOther,
  172. style: TextStyle(fontSize: 14, color: Colors.black),
  173. decoration: InputDecoration(
  174. counterText: '',
  175. counterStyle: TextStyle(fontSize: 0),
  176. hintText: 'writeHere'.tr(),
  177. hintStyle: TextStyle(color: textColor.withValues(alpha: 0.5), fontSize: 14),
  178. filled: true, fillColor: Colors.white,
  179. isDense: true,
  180. contentPadding: EdgeInsets.all(13),
  181. prefixIcon: Padding(padding: EdgeInsets.only(left: 13, right: 13), child: U.iconsax('edit-2', color: textColor, size: 22)),
  182. enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Color(0xff262626).withValues(alpha: 0.5))),
  183. focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: primaryColor)),
  184. ),
  185. );
  186. }
  187. }