You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

314 lines
12KB

  1. import 'package:farm_tpf/presentation/custom_widgets/button/ghost_button_widget.dart';
  2. import 'package:farm_tpf/presentation/screens/forgot_password/sc_forgot_password.dart';
  3. import 'package:farm_tpf/themes/app_dimension.dart';
  4. import 'package:flutter/foundation.dart';
  5. import 'package:flutter/material.dart';
  6. import 'package:flutter_bloc/flutter_bloc.dart';
  7. import 'package:flutter_svg/svg.dart';
  8. import 'package:flutter_switch/flutter_switch.dart';
  9. import 'package:get/get.dart';
  10. import 'package:keyboard_dismisser/keyboard_dismisser.dart';
  11. import '../../../authentication/bloc/authentication_bloc.dart';
  12. import '../../../themes/app_colors.dart';
  13. import '../../../themes/styles_text.dart';
  14. import '../../../utils/app_images.dart';
  15. import '../../../utils/const_enum.dart';
  16. import '../../../utils/helpers.dart';
  17. import '../../../utils/utils.dart';
  18. import '../../../utils/validators.dart';
  19. import '../../custom_widgets/button/primary_button_widget.dart';
  20. import '../../custom_widgets/textfield/text_field_normal.dart';
  21. import 'cubit/login_cubit.dart';
  22. class LoginPage extends StatefulWidget {
  23. const LoginPage({Key? key}) : super(key: key);
  24. @override
  25. State<LoginPage> createState() => _LoginPageState();
  26. }
  27. class _LoginPageState extends State<LoginPage> {
  28. var loginBloc = LoginCubit();
  29. var loginErrorMessage = ValueNotifier('');
  30. @override
  31. void initState() {
  32. super.initState();
  33. if (kDebugMode) {
  34. loginBloc.usernameCtl.text = 'gd_doannong';
  35. loginBloc.passwordCtl.text = 'abcd1234';
  36. }
  37. }
  38. @override
  39. void dispose() {
  40. super.dispose();
  41. loginBloc.dispose();
  42. }
  43. @override
  44. Widget build(BuildContext context) {
  45. return BlocListener<LoginCubit, LoginState>(
  46. bloc: loginBloc,
  47. listener: (context, state) {
  48. if (state is LoginLoading) {
  49. Helpers.hideKeyboard(context);
  50. UtilWidget.showLoading();
  51. } else if (state is LoginFailure) {
  52. UtilWidget.hideLoading();
  53. loginErrorMessage.value = state.errorMessage;
  54. loginErrorMessage.notifyListeners();
  55. } else if (state is LoginSuccess) {
  56. UtilWidget.hideLoading();
  57. BlocProvider.of<AuthenticationBloc>(context).add(
  58. const AuthenticationStatusChanged(
  59. AuthenticationStatus.authenticated,
  60. ),
  61. );
  62. } else {
  63. UtilWidget.hideLoading();
  64. }
  65. },
  66. child: _widgetMainBody(),
  67. );
  68. }
  69. Widget _widgetMainBody() {
  70. return Scaffold(
  71. body: KeyboardDismisser(
  72. child: Container(
  73. decoration: BoxDecoration(
  74. //color: AppColors.primary1.withOpacity(0.2),
  75. color: AppColors.primary1,
  76. gradient: LinearGradient(
  77. colors: [
  78. AppColors.primary1,
  79. AppColors.primary1.withOpacity(0),
  80. ],
  81. begin: Alignment.bottomCenter,
  82. end: Alignment.topCenter,
  83. ),
  84. ),
  85. child: Stack(
  86. children: <Widget>[
  87. // Positioned(
  88. // top: 0,
  89. // right: 0,
  90. // left: 0,
  91. // child: Container(
  92. // height: 370.h,
  93. // decoration: BoxDecoration(
  94. // color: AppColors.background1,
  95. // image: const DecorationImage(
  96. // image: AssetImage(AssetPNG.backgroundLogin),
  97. // fit: BoxFit.cover,
  98. // ),
  99. // ),
  100. // ),
  101. // ),
  102. // Positioned(
  103. // top: 0,
  104. // right: 0,
  105. // left: 0,
  106. // child: Container(
  107. // height: 371.h,
  108. // decoration: BoxDecoration(
  109. // color: AppColors.primary1,
  110. // gradient: LinearGradient(
  111. // colors: [
  112. // AppColors.primary1,
  113. // AppColors.primary1.withOpacity(0),
  114. // ],
  115. // begin: Alignment.bottomCenter,
  116. // end: Alignment.topCenter,
  117. // ),
  118. // ),
  119. // ),
  120. // ),
  121. Positioned(
  122. top: 100.h,
  123. right: 40.w,
  124. left: 40.w,
  125. child: Image.asset(
  126. AssetPNG.logo,
  127. height: 150,
  128. ),
  129. ),
  130. Positioned(
  131. bottom: 8,
  132. right: 8,
  133. left: 8,
  134. child: SafeArea(
  135. child: Container(
  136. width: double.infinity,
  137. padding: EdgeInsets.all(32.r),
  138. decoration: BoxDecoration(
  139. color: Colors.white,
  140. borderRadius: BorderRadius.circular(16.r),
  141. ),
  142. child: Form(
  143. key: loginBloc.formKey,
  144. child: Column(
  145. crossAxisAlignment: CrossAxisAlignment.start,
  146. mainAxisSize: MainAxisSize.min,
  147. children: [
  148. Text(
  149. 'Đăng Nhập',
  150. style: StylesText.header1,
  151. ),
  152. const SizedBox(
  153. height: 9,
  154. ),
  155. Text(
  156. 'Nhập tài khoản và mật khẩu để đăng nhập',
  157. style: StylesText.body6.copyWith(
  158. color: AppColors.neutral2,
  159. ),
  160. ),
  161. SizedBox(
  162. height: 24.h,
  163. ),
  164. Text(
  165. 'Tài Khoản',
  166. style: StylesText.body6,
  167. ),
  168. const SizedBox(
  169. height: 4,
  170. ),
  171. TextFieldNormal(
  172. controller: loginBloc.usernameCtl,
  173. hint: 'Nhập tài khoản',
  174. validator: (val) {
  175. return Validators.validateNotNullOrEmpty(
  176. val,
  177. 'Nhập tài khoản',
  178. );
  179. },
  180. ),
  181. const SizedBox(
  182. height: 16,
  183. ),
  184. Text(
  185. 'Mật Khẩu',
  186. style: StylesText.body6,
  187. ),
  188. const SizedBox(
  189. height: 4,
  190. ),
  191. TextFieldNormal(
  192. controller: loginBloc.passwordCtl,
  193. hint: 'Nhập Mật Khẩu',
  194. isPasswordField: true,
  195. validator: (val) {
  196. return Validators.validateNotNullOrEmpty(
  197. val,
  198. 'Nhập Mật Khẩu',
  199. );
  200. },
  201. ),
  202. ValueListenableBuilder<String>(
  203. valueListenable: loginErrorMessage,
  204. builder: (context, errorMessage, _) {
  205. if (Validators.stringNotNullOrEmpty(errorMessage)) {
  206. return Container(
  207. decoration: BoxDecoration(
  208. color: AppColors.semantic7,
  209. borderRadius: BorderRadius.circular(8),
  210. ),
  211. margin: const EdgeInsets.only(
  212. top: 16,
  213. ),
  214. padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
  215. child: Row(
  216. children: [
  217. SvgPicture.asset(AssetSVG.icWarning),
  218. const SizedBox(
  219. width: 4,
  220. ),
  221. Text(
  222. errorMessage,
  223. style: StylesText.caption3.copyWith(
  224. color: AppColors.semantic6,
  225. ),
  226. ),
  227. ],
  228. ),
  229. );
  230. } else {
  231. return const SizedBox.shrink();
  232. }
  233. },
  234. ),
  235. SizedBox(
  236. height: 24.h,
  237. ),
  238. Row(
  239. children: [
  240. ValueListenableBuilder<bool>(
  241. valueListenable: loginBloc.isRemember,
  242. builder: (context, isRemember, _) {
  243. return FlutterSwitch(
  244. width: 36.w,
  245. height: 19.h,
  246. toggleSize: 14.r,
  247. value: isRemember,
  248. borderRadius: 18.r,
  249. padding: 3.r,
  250. showOnOff: false,
  251. activeColor: AppColors.primary1,
  252. onToggle: (val) {
  253. onPressedRememberLogin(val);
  254. },
  255. );
  256. },
  257. ),
  258. const SizedBox(
  259. width: 10,
  260. ),
  261. Expanded(
  262. child: Text(
  263. 'Ghi nhớ đăng nhập',
  264. style: StylesText.caption3,
  265. ),
  266. ),
  267. GhostButtonWidget(
  268. title: 'Quên Mật Khẩu',
  269. onPressed: () {
  270. Get.to(
  271. () => ForgotPasswordScreen(),
  272. );
  273. },
  274. ),
  275. ],
  276. ),
  277. SizedBox(
  278. height: 24.h,
  279. ),
  280. PrimaryButtonWidget(
  281. title: 'Đăng Nhập',
  282. onPressed: () => onPressedLogin(),
  283. ),
  284. ],
  285. ),
  286. ),
  287. ),
  288. ),
  289. ),
  290. ],
  291. ),
  292. ),
  293. ),
  294. );
  295. }
  296. void onPressedRememberLogin(bool isRemember) {
  297. loginBloc.rememberMe(isRemember);
  298. }
  299. void onPressedForgotPassword() {}
  300. void onPressedLogin() {
  301. loginBloc.loginWithCredential();
  302. }
  303. }