231 lines
9.7 KiB
Dart
231 lines
9.7 KiB
Dart
// 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<LoginScreen> createState() => _LoginScreenState();
|
|
}
|
|
|
|
class _LoginScreenState extends State<LoginScreen> {
|
|
late LoginBloc loginBloc;
|
|
Map<String, dynamic> loginRequest = {"username": "", "password": ""};
|
|
final _formKey = GlobalKey<FormState>();
|
|
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<Map<String, dynamic>>(
|
|
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<bool>(
|
|
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:
|
|
WidgetStatePropertyAll(Colors.blue),
|
|
foregroundColor:
|
|
WidgetStatePropertyAll(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);
|
|
log("Data: $data");
|
|
// log(message)
|
|
if (data != "") {
|
|
Map<String, dynamic> 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<String, dynamic>);
|
|
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<ThemeNotifier>();
|
|
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)}");
|
|
int timeNow = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
|
if (token != "" && (exp - timeNow) > 7200) {
|
|
context.goNamed(AppRoutes.HOME.name);
|
|
}
|
|
}
|
|
|
|
getBaseToken(String token) {
|
|
List<String> parts = token.split('.');
|
|
String userToken = parts[1];
|
|
return userToken;
|
|
}
|
|
|
|
decodeBase64Token(String value) {
|
|
List<int> res = base64.decode(base64.normalize(value));
|
|
return utf8.decode(res);
|
|
}
|
|
}
|