// ignore_for_file: use_build_context_synchronously import 'dart:convert'; import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import '../../../../product/constant/app/api_path_constant.dart'; import '../../../../product/constant/enums/app_route_enums.dart'; import '../model/login_model.dart'; import '../../../../product/cache/local_manager.dart'; import '../../../../product/constant/enums/local_keys_enums.dart'; import '../../../../product/services/api_services.dart'; import '../../../../product/shared/shared_snack_bar.dart'; import '../../../../product/constant/icon/icon_constants.dart'; import '../../../../product/extention/context_extention.dart'; import '../../../../product/constant/image/image_constants.dart'; import '../../../../product/services/language_services.dart'; import '../bloc/login_bloc.dart'; import '../../../../product/base/bloc/base_bloc.dart'; import '../../../../product/shared/shared_background.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); @override State createState() => _LoginScreenState(); } class _LoginScreenState extends State { late LoginBloc loginBloc; Map loginRequest = {"username": "", "password": ""}; final _formKey = GlobalKey(); bool isShowPassword = true; APIServices apiServices = APIServices(); @override void initState() { super.initState(); loginBloc = BlocProvider.of(context); checkLogin(context); } @override Widget build(BuildContext context) { return Scaffold( body: SharedBackground( child: SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Row( children: [ const Spacer(), Expanded( flex: 4, child: Image.asset( ImageConstants.instance.getImage("logo"), height: context.dynamicHeight(0.2), ), ), const Spacer(), ], ), SizedBox( height: context.mediumValue, ), StreamBuilder>( stream: loginBloc.streamLoginRequest, builder: (context, loginResquestSnapshot) { return Padding( padding: context.paddingLow, child: Form( key: _formKey, child: Column( children: [ TextFormField( textInputAction: TextInputAction.next, validator: (value) { if (value == "null" || value!.isEmpty) { return appLocalization(context) .login_account_not_empty; } return null; }, onSaved: (username) { loginRequest["username"] = username!; loginBloc.sinkLoginRequest.add(loginRequest); }, decoration: InputDecoration( hintText: appLocalization(context).login_account_hint, prefixIcon: Padding( padding: context.dynamicPadding(16), child: IconConstants.instance .getMaterialIcon(Icons.person), ), ), ), SizedBox(height: context.lowValue), StreamBuilder( stream: loginBloc.streamIsShowPassword, builder: (context, isShowPassSnapshot) { return TextFormField( textInputAction: TextInputAction.done, obscureText: isShowPassSnapshot.data ?? isShowPassword, validator: (value) { if (value == null || value.isEmpty) { return appLocalization(context) .login_password_not_empty; } return null; }, onSaved: (password) { loginRequest["password"] = password!; loginBloc.sinkLoginRequest.add(loginRequest); }, decoration: InputDecoration( hintText: appLocalization(context) .login_password_hint, prefixIcon: Padding( padding: context.dynamicPadding(16), child: IconConstants.instance .getMaterialIcon(Icons.lock), ), suffixIcon: IconButton( onPressed: () { isShowPassword = !isShowPassword; loginBloc.sinkIsShowPassword .add(isShowPassword); }, icon: isShowPassword ? IconConstants.instance .getMaterialIcon( Icons.visibility, ) : IconConstants.instance .getMaterialIcon( Icons.visibility_off, ), ), ), ); }, ), SizedBox( height: context.lowValue, ), ElevatedButton( style: const ButtonStyle( backgroundColor: MaterialStatePropertyAll(Colors.blue), foregroundColor: MaterialStatePropertyAll(Colors.white), ), onPressed: () { validate(); }, child: Text( appLocalization(context).login_button_content), ), ], ), ), ); }, ) ], ), ), ), ); } void validate() async { if (_formKey.currentState!.validate()) { _formKey.currentState!.save(); var data = await apiServices.login(APIPathConstants.LOGIN_PATH, loginRequest); if (data != "") { Map tokenData = jsonDecode(data); String token = tokenData['token']; LocaleManager.instance.setString(PreferencesKeys.TOKEN, token); String userToken = getBaseToken(token); var decode = decodeBase64Token(userToken); LoginModel loginModel = LoginModel.fromJson(jsonDecode(decode) as Map); LocaleManager.instance.setString(PreferencesKeys.UID, loginModel.id!); LocaleManager.instance.setInt(PreferencesKeys.EXP, loginModel.exp!); LocaleManager.instance .setString(PreferencesKeys.ROLE, loginModel.role!); context.goNamed(AppRoutes.HOME.name); } else { showErrorTopSnackBarCustom( context, appLocalization(context).login_incorrect_usernameOrPass); } } } void checkLogin(BuildContext context) async { // ThemeNotifier themeNotifier = context.watch(); await LocaleManager.prefrencesInit(); // String theme = LocaleManager.instance.getStringValue(PreferencesKeys.THEME); String token = LocaleManager.instance.getStringValue(PreferencesKeys.TOKEN); int exp = LocaleManager.instance.getIntValue(PreferencesKeys.EXP); log("Token cu: ${LocaleManager.instance.getStringValue(PreferencesKeys.TOKEN)}"); log("UID: ${LocaleManager.instance.getStringValue(PreferencesKeys.UID)}"); log("EXP: ${LocaleManager.instance.getIntValue(PreferencesKeys.EXP)}"); log("Role: ${LocaleManager.instance.getStringValue(PreferencesKeys.ROLE)}"); log("Theme: ${LocaleManager.instance.getStringValue(PreferencesKeys.THEME)}"); log("Lang: ${LocaleManager.instance.getStringValue(PreferencesKeys.LANGUAGE_CODE)}"); // log("Theme: $theme"); // if (theme == AppThemes.DARK.name) { // themeNotifier.changeValue(AppThemes.DARK); // } else { // themeNotifier.changeValue(AppThemes.LIGHT); // } int timeNow = DateTime.now().millisecondsSinceEpoch ~/ 1000; if (token != "" && (exp - timeNow) > 7200) { context.goNamed(AppRoutes.HOME.name); } } getBaseToken(String token) { List parts = token.split('.'); String userToken = parts[1]; return userToken; } decodeBase64Token(String value) { List res = base64.decode(base64.normalize(value)); return utf8.decode(res); } }