301 lines
12 KiB
Dart
301 lines
12 KiB
Dart
import 'package:easy_localization/easy_localization.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
|
|
import '../../application/user_bloc/user_bloc.dart';
|
|
import '../../configs/configs.dart';
|
|
import '../../core/core.dart';
|
|
import '../../domain/domain.dart';
|
|
import '../widgets/widgets.dart';
|
|
import 'dart:io' show Platform;
|
|
|
|
class LoginScreen extends StatefulWidget {
|
|
const LoginScreen({super.key});
|
|
|
|
@override
|
|
State<LoginScreen> createState() => _LoginScreenState();
|
|
}
|
|
|
|
class _LoginScreenState extends State<LoginScreen> {
|
|
final TextEditingController _userNameController = TextEditingController();
|
|
final TextEditingController _passwordController = TextEditingController();
|
|
final _formKey = GlobalKey<FormState>();
|
|
bool _obscureText = true;
|
|
|
|
void _nextScreen() {
|
|
Navigator.of(context).pushNamedAndRemoveUntil(
|
|
AppRouter.root,
|
|
(route) => false,
|
|
);
|
|
}
|
|
|
|
void _onEyeTapped() {
|
|
setState(() {
|
|
_obscureText = !_obscureText;
|
|
});
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_userNameController.dispose();
|
|
_passwordController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
App.init(context);
|
|
return Scaffold(
|
|
body: SingleChildScrollView(
|
|
child: Column(
|
|
children: [
|
|
/// image part
|
|
Container(
|
|
height: AppDimensions.normalize(155),
|
|
color: AppColors.primary,
|
|
child: SingleChildScrollView(
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
Container(
|
|
padding: const EdgeInsets.only(top: 20, bottom: 20),
|
|
child: Column(
|
|
children: [
|
|
// SvgPicture.asset(
|
|
// AppAssets.logo,
|
|
// height: AppDimensions.normalize(30),
|
|
// ),
|
|
Space.yf(4),
|
|
|
|
Image.asset(
|
|
AppAssets.logoLogin,
|
|
),
|
|
Space.yf(0.50),
|
|
Text(
|
|
appTitle,
|
|
style: AppText.h1b?.copyWith(
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
Space.yf(0.30),
|
|
Text(
|
|
'deliver_all'.tr(),
|
|
style: AppText.b1?.copyWith(
|
|
color: AppColors.yellow,
|
|
),
|
|
),
|
|
Image.asset(
|
|
AppAssets.trucksPng,
|
|
height: AppDimensions.normalize(52),
|
|
width: double.infinity,
|
|
fit: BoxFit.fill,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
|
|
/// form part
|
|
SizedBox(
|
|
height: AppDimensions.normalize(190),
|
|
child: Stack(
|
|
clipBehavior: Clip.none,
|
|
children: [
|
|
Positioned(
|
|
top: -20,
|
|
left: 0,
|
|
right: 0,
|
|
bottom: 0,
|
|
child: Container(
|
|
decoration: const BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.only(
|
|
topLeft: Radius.circular(16),
|
|
topRight: Radius.circular(16),
|
|
),
|
|
),
|
|
child: Padding(
|
|
padding: Space.hf().copyWith(top: 30),
|
|
child: Form(
|
|
key: _formKey,
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'login_header'.tr(),
|
|
style: const TextStyle(
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
|
|
Space.yf(0.5),
|
|
|
|
Text(
|
|
'login_desc'.tr(),
|
|
style: const TextStyle(
|
|
color: Colors.grey,
|
|
),
|
|
),
|
|
|
|
/// gap
|
|
Space.yf(),
|
|
|
|
/// username field
|
|
Text('login'.tr()),
|
|
Space.y!,
|
|
TextFormField(
|
|
controller: _userNameController,
|
|
decoration: InputDecoration(
|
|
hintText: 'login_hint'.tr(),
|
|
prefixIcon: const Icon(Icons.person_outline),
|
|
border: const OutlineInputBorder(),
|
|
),
|
|
validator: (val) => FormValidator.validateField(val),
|
|
),
|
|
|
|
/// gap
|
|
Space.yf(),
|
|
|
|
/// password field
|
|
Text('password'.tr()),
|
|
Space.y!,
|
|
TextFormField(
|
|
controller: _passwordController,
|
|
obscureText: _obscureText,
|
|
decoration: InputDecoration(
|
|
hintText: 'password_hint'.tr(),
|
|
prefixIcon: const Icon(Icons.lock_outline),
|
|
suffixIcon: GestureDetector(
|
|
onTap: _onEyeTapped,
|
|
child: _obscureText
|
|
? const Icon(Icons.visibility_off)
|
|
: const Icon(
|
|
Icons.visibility,
|
|
),
|
|
),
|
|
border: const OutlineInputBorder(),
|
|
),
|
|
validator: (val) => FormValidator.validateField(val),
|
|
),
|
|
|
|
/// gap
|
|
Space.yf(),
|
|
|
|
BlocConsumer<UserBloc, UserState>(
|
|
listener: (context, state) {
|
|
if (state is UserLogged) {
|
|
_nextScreen();
|
|
} else if (state is UserLoggedFail) {
|
|
if (state.failure is CredentialFailure) {
|
|
showErrorDialog(
|
|
context: context,
|
|
header: 'credentials_validation_header'.tr(),
|
|
body: 'credentials_validation_body'.tr(),
|
|
);
|
|
} else {
|
|
showAuthErrorDialog(context);
|
|
}
|
|
}
|
|
},
|
|
builder: (context, state) {
|
|
if (state is UserLoading) {
|
|
return const Center(
|
|
child: CircularProgressIndicator(),
|
|
);
|
|
}
|
|
return SizedBox(
|
|
width: double.infinity,
|
|
child: AppButton(
|
|
textColor: Colors.white,
|
|
btnColor: AppColors.primary,
|
|
onPressed: () {
|
|
if (_formKey.currentState!.validate()) {
|
|
Keyboard.hide(context);
|
|
|
|
/// sign in
|
|
context.read<UserBloc>().add(
|
|
SignInUser(
|
|
SignInParams(
|
|
username: _userNameController.text,
|
|
password: _passwordController.text,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
},
|
|
text: 'start_tracking'.tr(),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
|
|
if (Platform.isIOS)
|
|
Align(
|
|
alignment: Alignment.center,
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
/// spacer
|
|
Space.yf(),
|
|
Text(
|
|
'or'.tr(),
|
|
style: AppText.h3,
|
|
),
|
|
Space.yf(),
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 22),
|
|
height: 40,
|
|
decoration: BoxDecoration(
|
|
border: Border.all(
|
|
color: AppColors.primary, // Border color
|
|
width: 1.0, // Border width
|
|
),
|
|
borderRadius: BorderRadius.circular(8.0),
|
|
),
|
|
child: TextButton(
|
|
style: TextButton.styleFrom(
|
|
foregroundColor: AppColors.primary,
|
|
padding: EdgeInsets.zero,
|
|
textStyle: const TextStyle(
|
|
color: Colors.black,
|
|
),
|
|
),
|
|
onPressed: () {
|
|
debugPrint('register');
|
|
Navigator.of(context).pushNamedAndRemoveUntil(
|
|
AppRouter.register,
|
|
(route) => false,
|
|
);
|
|
},
|
|
child: Text(
|
|
'register'.tr(),
|
|
style: AppText.b1b,
|
|
),
|
|
),
|
|
),
|
|
Space.yf(0.30),
|
|
],
|
|
),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|