Complete refactoring SFM App Source Code

This commit is contained in:
anhtunz
2024-12-15 00:59:02 +07:00
parent caa73ca43c
commit 2e27d59278
247 changed files with 18390 additions and 0 deletions

View File

@@ -0,0 +1,234 @@
// 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:
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<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)}");
// 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<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);
}
}