password.dart 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. import 'package:easy_localization/easy_localization.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter/services.dart';
  4. import 'package:telnow_mobile_new/src/api/api_auth_provider.dart';
  5. import 'package:telnow_mobile_new/src/api/api_auth_repository.dart';
  6. import 'package:telnow_mobile_new/src/injector/injector.dart';
  7. import 'package:telnow_mobile_new/src/layouts/components/template.dart';
  8. import 'package:telnow_mobile_new/src/model/login/login_body.dart';
  9. import 'package:telnow_mobile_new/src/model/token/token.dart';
  10. import 'package:telnow_mobile_new/src/storage/sharedpreferences/shared_preferences_manager.dart';
  11. import 'package:telnow_mobile_new/src/utils/U.dart';
  12. class MobPasswordPage extends StatefulWidget {
  13. Map<String, dynamic> user;
  14. MobPasswordPage({required this.user, super.key});
  15. @override
  16. State<MobPasswordPage> createState() => _MobPasswordPageState();
  17. }
  18. class _MobPasswordPageState extends State<MobPasswordPage> {
  19. final ApiAuthProvider apiAuthProvider = ApiAuthProvider();
  20. final ApiAuthRepository apiAuthRepository = ApiAuthRepository();
  21. final SharedPreferencesManager sharedPreferencesManager = locator<SharedPreferencesManager>();
  22. String controllerOld = '';
  23. String controllerNew = '';
  24. String controllerConfirm = '';
  25. @override
  26. Widget build(BuildContext context) {
  27. return Scaffold(
  28. backgroundColor: backgroundColor,
  29. appBar: appBarTemplate(context: context, title: 'settingPassword'.tr()),
  30. body: Column(
  31. children: [
  32. divider(),
  33. Expanded(
  34. child: Container(
  35. alignment: Alignment.topCenter,
  36. width: U.bodyWidth(context),
  37. child: SingleChildScrollView(
  38. padding: EdgeInsets.all(16),
  39. child: Column(
  40. crossAxisAlignment: CrossAxisAlignment.start,
  41. children: [
  42. Container(
  43. margin: EdgeInsets.only(bottom: 5),
  44. child: Text('titlePassOld'.tr(), style: TextStyle(fontSize: 16, color: textColor)),
  45. ),
  46. passwordFieldTemplate(value: controllerOld, iconColor: textColor.withValues(alpha: 0.5), color: textColor, placeholder: 'oldPassword'.tr(), action: (val)=>controllerOld=val),
  47. Container(
  48. margin: EdgeInsets.only(top: 20, bottom: 5),
  49. child: Column(
  50. crossAxisAlignment: CrossAxisAlignment.start,
  51. children: [
  52. Text('titlePassNew'.tr(), style: TextStyle(fontSize: 16, color: textColor)),
  53. SizedBox(height: 10),
  54. Text('newPassword'.tr(), style: TextStyle(fontSize: 16, color: textColor)),
  55. ],
  56. )
  57. ),
  58. passwordFieldTemplate(value: controllerNew, placeholder: 'newPassword'.tr(), action: (val)=>controllerNew=val),
  59. Container(
  60. margin: EdgeInsets.only(top: 20, bottom: 5),
  61. child: Text('confirmPassword'.tr(), style: TextStyle(fontSize: 16, color: textColor)),
  62. ),
  63. passwordFieldTemplate(value: controllerConfirm, placeholder: 'confirmPassword'.tr(), action: (val)=>controllerConfirm=val)
  64. ],
  65. ),
  66. ),
  67. ),
  68. ),
  69. SafeArea(
  70. child: Container(
  71. padding: EdgeInsets.symmetric(vertical: 10, horizontal: 16),
  72. decoration: BoxDecoration(
  73. color: Colors.white,
  74. border: Border(top: BorderSide(color: textColor.withValues(alpha: 0.15)))
  75. ),
  76. child: buttonTemplate(text: 'buttonSave'.tr(), action: ()async{
  77. if(controllerOld.trim().isNotEmpty && controllerNew.trim().isNotEmpty && controllerConfirm.trim().isNotEmpty){
  78. if(controllerNew == controllerConfirm){
  79. var data = {
  80. 'oldPassword':controllerOld.trim(),
  81. 'password':controllerNew.trim()
  82. };
  83. var res = await apiAuthProvider.patchData('/api/informants/'+widget.user['id'].toString()+'/changePassword', data, context);
  84. if(res != null){
  85. String username = widget.user['_isRelated']?widget.user['relatedTo']:widget.user['userId'];
  86. String? password = widget.user['_isRelated'] && widget.user['tenantCode']!=null && widget.user['tenantCode']!=''?widget.user['tenantCode']+' '+data['password']:data['password'];
  87. LoginBody loginBody = LoginBody(username, password!, 'password');
  88. Token token = await apiAuthRepository.postLoginUser(loginBody);
  89. if (token.error != null) {
  90. showError(context, token.error);
  91. }
  92. else{
  93. await sharedPreferencesManager.putString(SharedPreferencesManager.keyAccessToken, token.accessToken!);
  94. await sharedPreferencesManager.putString(SharedPreferencesManager.keyRefreshToken, token.refreshToken!);
  95. await sharedPreferencesManager.putString(SharedPreferencesManager.keyUsername, widget.user['_isRelated']?widget.user['tenantCode']!=null && widget.user['tenantCode']!=''?widget.user['tenantCode']+' '+data['password']!:data['password']!:widget.user['userId']);
  96. Navigator.of(context).pop(true);
  97. }
  98. }
  99. }
  100. else{
  101. showError(context, 'checkNewPass'.tr());
  102. }
  103. }
  104. else{
  105. showError(context, 'cannotEmpty'.tr());
  106. }
  107. }),
  108. ),
  109. )
  110. ],
  111. ),
  112. );
  113. }
  114. Widget passwordFieldTemplate({required String value, iconColor = primaryColor, Color color = primaryColor, placeholder = '', required action(value)}){
  115. TextEditingController controller = TextEditingController()..text = value;
  116. bool hidePass = true;
  117. return SizedBox(
  118. width: double.infinity,
  119. child: StatefulBuilder(
  120. builder: (context, fieldState) => TextFormField(
  121. controller: controller,
  122. style: TextStyle(fontSize: 16, color: color),
  123. keyboardType: widget.user['_isRelated']?TextInputType.number:null,
  124. inputFormatters: widget.user['_isRelated']?[FilteringTextInputFormatter.digitsOnly]:null,
  125. enableInteractiveSelection: widget.user['_isRelated']?false:true,
  126. obscureText: hidePass,
  127. decoration: InputDecoration(
  128. hintText: placeholder,
  129. hintStyle: TextStyle(fontSize: 16, color: color.withValues(alpha: 0.5)),
  130. filled: true,
  131. fillColor: Colors.white,
  132. hoverColor: textColor.withValues(alpha: 0.1),
  133. contentPadding: EdgeInsets.all(16),
  134. border: InputBorder.none,
  135. prefixIcon: U.iconsax('bold/key', size: 24, color: iconColor),
  136. suffixIconConstraints: BoxConstraints(maxHeight: 40, maxWidth: 40, minHeight: 40, minWidth: 40),
  137. suffixIcon: GestureDetector(child: U.iconsax(hidePass?'eye':'eye-slash', size: 24, color: textColor.withValues(alpha: 0.5)), onTap: ()=>fieldState(()=>hidePass=!hidePass)),
  138. enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: textColor.withValues(alpha: 0.5))),
  139. focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: textColor.withValues(alpha: 0.5))),
  140. isDense: true
  141. ),
  142. onChanged: (val)=>action(val.toString()),
  143. ),
  144. ),
  145. );
  146. }
  147. }