| var token = await pref.getString(PrefKey.token_key); | var token = await pref.getString(PrefKey.token_key); | ||||
| options.headers["Authorization"] = "Bearer $token"; | options.headers["Authorization"] = "Bearer $token"; | ||||
| options.receiveTimeout = 20000; | options.receiveTimeout = 20000; | ||||
| // log("onRequest: ${options.uri}\n" | |||||
| // "data=${options.data}\n" | |||||
| // "method=${options.method}\n" | |||||
| // "headers=${options.headers}\n" | |||||
| // "queryParameters=${options.queryParameters}"); | |||||
| log("onRequest: ${options.uri}\n" | |||||
| "data=${options.data}\n" | |||||
| "method=${options.method}\n" | |||||
| "headers=${options.headers}\n" | |||||
| "queryParameters=${options.queryParameters}"); | |||||
| return options; | return options; | ||||
| } | } | ||||
| @override | @override | ||||
| Future onResponse(Response response) { | Future onResponse(Response response) { | ||||
| // log("onResponse: $response"); | |||||
| log("onResponse: $response"); | |||||
| return super.onResponse(response); | return super.onResponse(response); | ||||
| } | } | ||||
| @override | @override | ||||
| Future onError(DioError err) { | Future onError(DioError err) { | ||||
| // log("onError: $err\n" | |||||
| // "Response: ${err.response}"); | |||||
| log("onError: $err\n" | |||||
| "Response: ${err.response}"); | |||||
| return super.onError(err); | return super.onError(err); | ||||
| } | } | ||||
| } | } |
| import 'package:farm_tpf/data/repository/user_repository.dart'; | |||||
| import 'package:rxdart/rxdart.dart'; | |||||
| class GetAccountBloc { | |||||
| final _repository = UserRepository(); | |||||
| final _getAccountFetcher = PublishSubject<dynamic>(); | |||||
| Stream<dynamic> get actions => _getAccountFetcher.stream; | |||||
| void getAccount(Function(dynamic) onSuccess, Function(String) onError) async { | |||||
| _repository.getUser().then((value) { | |||||
| onSuccess(value); | |||||
| _getAccountFetcher.sink.add(value); | |||||
| }).catchError((onError) { | |||||
| onError(onError); | |||||
| _getAccountFetcher.addError(onError); | |||||
| }); | |||||
| } | |||||
| void dispose() async { | |||||
| await _getAccountFetcher.drain(); | |||||
| _getAccountFetcher.close(); | |||||
| } | |||||
| } | |||||
| final getAccountBloc = GetAccountBloc(); |
| import 'package:farm_tpf/data/repository/user_repository.dart'; | |||||
| import 'package:farm_tpf/models/password.dart'; | |||||
| import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart'; | |||||
| import 'package:farm_tpf/presentation/custom_widgets/widget_toast.dart'; | |||||
| import 'package:farm_tpf/utils/const_color.dart'; | |||||
| import 'package:farm_tpf/utils/validators.dart'; | |||||
| import 'package:flutter/material.dart'; | |||||
| import 'package:fluttertoast/fluttertoast.dart'; | |||||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||||
| class ChangePasswordScreen extends StatefulWidget { | |||||
| @override | |||||
| _ChangePasswordScreenState createState() => _ChangePasswordScreenState(); | |||||
| } | |||||
| class _ChangePasswordScreenState extends State<ChangePasswordScreen> { | |||||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||||
| final _repository = UserRepository(); | |||||
| GlobalKey<FormState> _formKey = GlobalKey(); | |||||
| bool _autoValidate = false; | |||||
| FlutterToast flutterToast; | |||||
| Password _password = Password(); | |||||
| TextEditingController _currentPasswordController = TextEditingController(); | |||||
| TextEditingController _newPasswordController = TextEditingController(); | |||||
| TextEditingController _confirmPasswordController = TextEditingController(); | |||||
| @override | |||||
| void initState() { | |||||
| super.initState(); | |||||
| flutterToast = FlutterToast(context); | |||||
| } | |||||
| _validateInputs() async { | |||||
| if (_formKey.currentState.validate()) { | |||||
| _formKey.currentState.save(); | |||||
| LoadingDialog.showLoadingDialog(context); | |||||
| _repository.changePassword(_password).then((value) { | |||||
| LoadingDialog.hideLoadingDialog(context); | |||||
| flutterToast.showToast( | |||||
| child: WidgetToast(message: "Cập nhật thành công")); | |||||
| Navigator.pop(context); | |||||
| }).catchError((onError) { | |||||
| _scaffoldKey.currentState.showSnackBar(SnackBar( | |||||
| content: Row( | |||||
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||||
| children: <Widget>[ | |||||
| Text('Cập nhật không thành công.'), | |||||
| Icon(Icons.error), | |||||
| ], | |||||
| ), | |||||
| backgroundColor: Colors.red, | |||||
| duration: Duration(seconds: 3), | |||||
| )); | |||||
| LoadingDialog.hideLoadingDialog(context); | |||||
| }); | |||||
| } else { | |||||
| _autoValidate = true; | |||||
| } | |||||
| } | |||||
| Widget _currentPasswordField() { | |||||
| return TextFormField( | |||||
| keyboardType: TextInputType.text, | |||||
| obscureText: true, | |||||
| decoration: InputDecoration(labelText: "Mật khẩu hiện tại"), | |||||
| controller: _currentPasswordController, | |||||
| validator: (String value) { | |||||
| return Validators.validateNotNullOrEmpty(value, "Mật khẩu hiện tại"); | |||||
| }, | |||||
| onSaved: (newValue) { | |||||
| _password.currentPassword = newValue; | |||||
| }, | |||||
| ); | |||||
| } | |||||
| Widget _newPasswordField() { | |||||
| return TextFormField( | |||||
| keyboardType: TextInputType.text, | |||||
| obscureText: true, | |||||
| decoration: InputDecoration(labelText: "Mật khẩu mới"), | |||||
| controller: _newPasswordController, | |||||
| validator: validators.validateNewPassword, | |||||
| onSaved: (newValue) { | |||||
| _password.newPassword = newValue; | |||||
| }, | |||||
| ); | |||||
| } | |||||
| Widget _confirmPasswordField() { | |||||
| return TextFormField( | |||||
| keyboardType: TextInputType.text, | |||||
| obscureText: true, | |||||
| decoration: InputDecoration(labelText: "Nhập lại mật khẩu mới"), | |||||
| controller: _confirmPasswordController, | |||||
| validator: (String value) { | |||||
| return validators.validateConfirmPassword( | |||||
| _newPasswordController.text, value); | |||||
| }, | |||||
| onSaved: (newValue) {}, | |||||
| ); | |||||
| } | |||||
| Widget _btnSubmit() { | |||||
| return SizedBox( | |||||
| width: double.infinity, | |||||
| height: 55, | |||||
| child: FlatButton( | |||||
| onPressed: () { | |||||
| FocusScopeNode currentFocus = FocusScope.of(context); | |||||
| if (!currentFocus.hasPrimaryFocus) { | |||||
| currentFocus.unfocus(); | |||||
| } | |||||
| _validateInputs(); | |||||
| }, | |||||
| color: COLOR_CONST.DEFAULT, | |||||
| shape: RoundedRectangleBorder( | |||||
| borderRadius: new BorderRadius.circular(7.0), | |||||
| ), | |||||
| child: Text( | |||||
| 'Cập nhật'.toUpperCase(), | |||||
| style: | |||||
| TextStyle(fontWeight: FontWeight.bold, color: COLOR_CONST.WHITE), | |||||
| ), | |||||
| ), | |||||
| ); | |||||
| } | |||||
| @override | |||||
| Widget build(BuildContext context) => KeyboardDismisser( | |||||
| child: Scaffold( | |||||
| key: _scaffoldKey, | |||||
| appBar: AppBar(centerTitle: true, title: Text("Cập nhật mật khẩu")), | |||||
| body: KeyboardDismisser( | |||||
| child: Form( | |||||
| key: _formKey, | |||||
| autovalidate: _autoValidate, | |||||
| child: SingleChildScrollView( | |||||
| padding: EdgeInsets.all(8.0), | |||||
| child: Column( | |||||
| children: <Widget>[ | |||||
| _currentPasswordField(), | |||||
| SizedBox( | |||||
| height: 8.0, | |||||
| ), | |||||
| _newPasswordField(), | |||||
| SizedBox( | |||||
| height: 8.0, | |||||
| ), | |||||
| _confirmPasswordField(), | |||||
| SizedBox( | |||||
| height: 8.0, | |||||
| ), | |||||
| _btnSubmit() | |||||
| ], | |||||
| ), | |||||
| ))))); | |||||
| } |
| import 'package:farm_tpf/data/repository/user_repository.dart'; | |||||
| import 'package:farm_tpf/models/account.dart'; | |||||
| import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart'; | |||||
| import 'package:farm_tpf/presentation/custom_widgets/widget_toast.dart'; | |||||
| import 'package:farm_tpf/presentation/screens/profile/sc_change_password.dart'; | |||||
| import 'package:farm_tpf/utils/validators.dart'; | |||||
| import 'package:flutter/material.dart'; | |||||
| import 'package:fluttertoast/fluttertoast.dart'; | |||||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||||
| import 'bloc_get_account.dart'; | |||||
| class UpdateProfileScreen extends StatefulWidget { | |||||
| static Route route() { | |||||
| return MaterialPageRoute<void>(builder: (_) => UpdateProfileScreen()); | |||||
| } | |||||
| @override | |||||
| _UpdateProfileScreenState createState() => _UpdateProfileScreenState(); | |||||
| } | |||||
| class _UpdateProfileScreenState extends State<UpdateProfileScreen> { | |||||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | |||||
| final _repository = UserRepository(); | |||||
| GlobalKey<FormState> _formKey = GlobalKey(); | |||||
| bool _autoValidate = false; | |||||
| FlutterToast flutterToast; | |||||
| Account _account = Account(); | |||||
| TextEditingController _userNameController = TextEditingController(); | |||||
| TextEditingController _fullNameController = TextEditingController(); | |||||
| TextEditingController _emailController = TextEditingController(); | |||||
| TextEditingController _addressController = TextEditingController(); | |||||
| @override | |||||
| void initState() { | |||||
| super.initState(); | |||||
| flutterToast = FlutterToast(context); | |||||
| getAccountBloc.getAccount((data) { | |||||
| _account = data; | |||||
| _userNameController.text = _account.login; | |||||
| _fullNameController.text = _account.fullName.toString(); | |||||
| _emailController.text = _account.email.toString(); | |||||
| _addressController.text = _account.address; | |||||
| }, (err) { | |||||
| flutterToast.showToast(child: WidgetToast(message: "Lỗi tải dữ liệu")); | |||||
| }); | |||||
| } | |||||
| _validateInputs() async { | |||||
| if (_formKey.currentState.validate()) { | |||||
| _formKey.currentState.save(); | |||||
| LoadingDialog.showLoadingDialog(_scaffoldKey.currentContext); | |||||
| _repository.updateProfile(_account).then((value) { | |||||
| LoadingDialog.hideLoadingDialog(_scaffoldKey.currentContext); | |||||
| _scaffoldKey.currentState.showSnackBar(SnackBar( | |||||
| content: Row( | |||||
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||||
| children: <Widget>[ | |||||
| Text('Cập nhật thành công.'), | |||||
| Icon(Icons.done), | |||||
| ], | |||||
| ), | |||||
| backgroundColor: Colors.green, | |||||
| duration: Duration(seconds: 3), | |||||
| )); | |||||
| }).catchError((onError) { | |||||
| _scaffoldKey.currentState.showSnackBar(SnackBar( | |||||
| content: Row( | |||||
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||||
| children: <Widget>[ | |||||
| Text('Cập nhật không thành công.'), | |||||
| Icon(Icons.error), | |||||
| ], | |||||
| ), | |||||
| backgroundColor: Colors.red, | |||||
| duration: Duration(seconds: 3), | |||||
| )); | |||||
| LoadingDialog.hideLoadingDialog(_scaffoldKey.currentContext); | |||||
| print("error"); | |||||
| }); | |||||
| } else { | |||||
| _autoValidate = true; | |||||
| } | |||||
| } | |||||
| Widget _userNameField() { | |||||
| return TextFormField( | |||||
| keyboardType: TextInputType.text, | |||||
| enabled: false, | |||||
| decoration: InputDecoration(labelText: "Tài khoản"), | |||||
| controller: _userNameController, | |||||
| validator: (String value) { | |||||
| return Validators.validateNotNullOrEmpty(value, "Tài khoản"); | |||||
| }, | |||||
| onSaved: (newValue) {}, | |||||
| ); | |||||
| } | |||||
| Widget _fullNameField() { | |||||
| return TextFormField( | |||||
| keyboardType: TextInputType.text, | |||||
| decoration: InputDecoration(labelText: "Họ và tên"), | |||||
| controller: _fullNameController, | |||||
| validator: (String value) { | |||||
| return Validators.validateNotNullOrEmpty(value, "Họ và tên"); | |||||
| }, | |||||
| onSaved: (newValue) { | |||||
| _account.fullName = newValue; | |||||
| }, | |||||
| ); | |||||
| } | |||||
| Widget _emailField() { | |||||
| return TextFormField( | |||||
| keyboardType: TextInputType.emailAddress, | |||||
| decoration: InputDecoration(labelText: "Email"), | |||||
| controller: _emailController, | |||||
| validator: (String value) { | |||||
| return Validators.validateEmail(value); | |||||
| }, | |||||
| onSaved: (newValue) { | |||||
| _account.email = newValue; | |||||
| }, | |||||
| ); | |||||
| } | |||||
| Widget _addressField() { | |||||
| return TextFormField( | |||||
| keyboardType: TextInputType.text, | |||||
| decoration: InputDecoration(labelText: "Địa chỉ"), | |||||
| controller: _addressController, | |||||
| onSaved: (newValue) { | |||||
| _account.address = newValue; | |||||
| }, | |||||
| ); | |||||
| } | |||||
| Widget _btnChangePassword() { | |||||
| return FlatButton( | |||||
| padding: EdgeInsets.only(top: 0.0, right: 0.0, bottom: 0.0, left: 0.0), | |||||
| onPressed: () { | |||||
| Navigator.push( | |||||
| context, | |||||
| MaterialPageRoute(builder: (context) => ChangePasswordScreen()), | |||||
| ); | |||||
| }, | |||||
| child: Container( | |||||
| padding: | |||||
| EdgeInsets.only(top: 15.0, right: 0.0, bottom: 10.5, left: 0.0), | |||||
| decoration: BoxDecoration( | |||||
| border: | |||||
| Border(bottom: BorderSide(width: 0.5, color: Colors.grey)), | |||||
| ), | |||||
| child: Row( | |||||
| children: [ | |||||
| Expanded( | |||||
| child: Text( | |||||
| "Cập nhật mật khẩu".toUpperCase(), | |||||
| style: TextStyle( | |||||
| fontSize: 14.0, | |||||
| color: Colors.black, | |||||
| fontWeight: FontWeight.bold), | |||||
| )), | |||||
| Icon(Icons.arrow_forward_ios), | |||||
| ], | |||||
| ))); | |||||
| } | |||||
| @override | |||||
| Widget build(BuildContext context) => KeyboardDismisser( | |||||
| child: Scaffold( | |||||
| appBar: AppBar( | |||||
| centerTitle: true, | |||||
| title: Text( | |||||
| "Thông tin cá nhân", | |||||
| textAlign: TextAlign.center, | |||||
| ), | |||||
| actions: <Widget>[ | |||||
| IconButton( | |||||
| icon: Icon(Icons.done), | |||||
| onPressed: () { | |||||
| FocusScopeNode currentFocus = FocusScope.of(context); | |||||
| if (!currentFocus.hasPrimaryFocus) { | |||||
| currentFocus.unfocus(); | |||||
| } | |||||
| _validateInputs(); | |||||
| }) | |||||
| ], | |||||
| ), | |||||
| key: _scaffoldKey, | |||||
| body: _buildContent())); | |||||
| Widget _buildContent() { | |||||
| return StreamBuilder( | |||||
| stream: getAccountBloc.actions, | |||||
| builder: (context, AsyncSnapshot<dynamic> snapshot) { | |||||
| if (snapshot.hasData) { | |||||
| return Form( | |||||
| key: _formKey, | |||||
| autovalidate: _autoValidate, | |||||
| child: SingleChildScrollView( | |||||
| padding: EdgeInsets.all(8.0), | |||||
| child: Column( | |||||
| children: <Widget>[ | |||||
| _userNameField(), | |||||
| SizedBox( | |||||
| height: 8.0, | |||||
| ), | |||||
| _fullNameField(), | |||||
| SizedBox( | |||||
| height: 8.0, | |||||
| ), | |||||
| _emailField(), | |||||
| SizedBox( | |||||
| height: 16.0, | |||||
| ), | |||||
| _btnChangePassword() | |||||
| ], | |||||
| ), | |||||
| )); | |||||
| } else { | |||||
| return Center( | |||||
| child: CircularProgressIndicator(), | |||||
| ); | |||||
| } | |||||
| }); | |||||
| } | |||||
| } |
| import 'package:farm_tpf/presentation/screens/home/home.dart'; | import 'package:farm_tpf/presentation/screens/home/home.dart'; | ||||
| import 'package:farm_tpf/presentation/screens/profile/sc_update_profile.dart'; | |||||
| import 'package:farm_tpf/utils/const_color.dart'; | import 'package:farm_tpf/utils/const_color.dart'; | ||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||
| }); | }); | ||||
| } else if (drawerIndex == DrawerIndex.Setting) { | } else if (drawerIndex == DrawerIndex.Setting) { | ||||
| setState(() { | setState(() { | ||||
| screenView = HomePage(); | |||||
| screenView = UpdateProfileScreen(); | |||||
| }); | }); | ||||
| } else { | } else { | ||||
| //do in your way...... | //do in your way...... |
| url: "https://pub.dartlang.org" | url: "https://pub.dartlang.org" | ||||
| source: hosted | source: hosted | ||||
| version: "1.3.7+5" | version: "1.3.7+5" | ||||
| rxdart: | |||||
| dependency: "direct main" | |||||
| description: | |||||
| name: rxdart | |||||
| url: "https://pub.dartlang.org" | |||||
| source: hosted | |||||
| version: "0.23.1" | |||||
| shared_preferences: | shared_preferences: | ||||
| dependency: "direct main" | dependency: "direct main" | ||||
| description: | description: |
| keyboard_dismisser: ^1.0.2 | keyboard_dismisser: ^1.0.2 | ||||
| fluttertoast: ^6.0.1 | fluttertoast: ^6.0.1 | ||||
| pattern_formatter: ^1.0.2 | pattern_formatter: ^1.0.2 | ||||
| rxdart: ^0.23.0 | |||||
| dev_dependencies: | dev_dependencies: | ||||
| flutter_test: | flutter_test: |