| @@ -21,24 +21,24 @@ class HttpLogInterceptor extends InterceptorsWrapper { | |||
| var token = await pref.getString(PrefKey.token_key); | |||
| options.headers["Authorization"] = "Bearer $token"; | |||
| 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; | |||
| } | |||
| @override | |||
| Future onResponse(Response response) { | |||
| // log("onResponse: $response"); | |||
| log("onResponse: $response"); | |||
| return super.onResponse(response); | |||
| } | |||
| @override | |||
| Future onError(DioError err) { | |||
| // log("onError: $err\n" | |||
| // "Response: ${err.response}"); | |||
| log("onError: $err\n" | |||
| "Response: ${err.response}"); | |||
| return super.onError(err); | |||
| } | |||
| } | |||
| @@ -0,0 +1,26 @@ | |||
| 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(); | |||
| @@ -0,0 +1,158 @@ | |||
| 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() | |||
| ], | |||
| ), | |||
| ))))); | |||
| } | |||
| @@ -0,0 +1,229 @@ | |||
| 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(), | |||
| ); | |||
| } | |||
| }); | |||
| } | |||
| } | |||
| @@ -1,4 +1,5 @@ | |||
| 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:flutter/material.dart'; | |||
| @@ -58,7 +59,7 @@ class _NavigationHomeScreenState extends State<NavigationHomeScreen> { | |||
| }); | |||
| } else if (drawerIndex == DrawerIndex.Setting) { | |||
| setState(() { | |||
| screenView = HomePage(); | |||
| screenView = UpdateProfileScreen(); | |||
| }); | |||
| } else { | |||
| //do in your way...... | |||
| @@ -492,6 +492,13 @@ packages: | |||
| url: "https://pub.dartlang.org" | |||
| source: hosted | |||
| 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: | |||
| dependency: "direct main" | |||
| description: | |||
| @@ -20,6 +20,7 @@ dependencies: | |||
| keyboard_dismisser: ^1.0.2 | |||
| fluttertoast: ^6.0.1 | |||
| pattern_formatter: ^1.0.2 | |||
| rxdart: ^0.23.0 | |||
| dev_dependencies: | |||
| flutter_test: | |||