Files
bookmywages/lib/view/auth/login_page.dart
T
2025-10-16 11:21:52 +05:30

302 lines
13 KiB
Dart

// ignore_for_file: use_build_context_synchronously
import 'package:bookmywages/consts_widgets/app_assets.dart';
import 'package:bookmywages/consts_widgets/app_colors.dart';
import 'package:bookmywages/consts_widgets/comman_button.dart';
import 'package:bookmywages/consts_widgets/comman_textformfiled.dart';
import 'package:bookmywages/model/login_model.dart';
import 'package:bookmywages/routers/consts_router.dart';
import 'package:bookmywages/viewmodel/api_controller.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
class LoginScreen extends ConsumerStatefulWidget {
const LoginScreen({super.key});
@override
ConsumerState<LoginScreen> createState() => _LoginScreenState();
}
class _LoginScreenState extends ConsumerState<LoginScreen> {
final TextEditingController _usernameController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
bool _obscurePassword = true;
// Add form key and error messages
final _formKey = GlobalKey<FormState>();
String? _emailError;
String? _passwordError;
@override
void dispose() {
_usernameController.dispose();
_passwordController.dispose();
super.dispose();
}
// Validation methods
void _validateEmail(String value) {
if (value.isEmpty) {
setState(() => _emailError = 'Email is required');
} else if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(value)) {
setState(() => _emailError = 'Enter a valid email');
} else {
setState(() => _emailError = null);
}
}
void _validatePassword(String value) {
if (value.isEmpty) {
setState(() => _passwordError = 'Password is required');
} else if (value.length < 4) {
setState(() => _passwordError = 'Password must be at least 4 characters');
} else {
setState(() => _passwordError = null);
}
}
@override
Widget build(BuildContext context) {
final screenSize = MediaQuery.of(context).size;
final double horizontalPadding = screenSize.width * 0.05;
final double imageHeight = screenSize.height * 0.45;
return Scaffold(
backgroundColor: AppColors.secondprimary,
resizeToAvoidBottomInset: true,
body: SingleChildScrollView(
child: Column(
children: [
// Image
Image.asset(
AppAssets.login,
width: screenSize.width,
height: imageHeight,
fit: BoxFit.cover,
),
// Overlapping Login Container using Transform
Transform.translate(
offset: const Offset(0, -100),
child: Padding(
padding: EdgeInsets.symmetric(horizontal: horizontalPadding),
child: Container(
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(32.73),
border: Border.all(
width: 1.09,
color: const Color(0xFFA39898),
),
boxShadow: const [
BoxShadow(
offset: Offset(0, -4),
blurRadius: 12.3,
color: Color(0x66E0E0E0),
),
BoxShadow(
offset: Offset(0, 4),
blurRadius: 4,
color: Color(0x66000000),
),
],
color: Colors.white,
),
child: Padding(
padding: EdgeInsets.all(screenSize.width * 0.05),
child: Form(
key: _formKey,
child: Column(
children: [
const SizedBox(height: 20),
const Text(
"Sign in",
style: TextStyle(
fontSize: 32,
fontFamily: "Gilroy-ExtraBold",
fontWeight: FontWeight.w800,
height: 1.0,
letterSpacing: 0.64,
),
),
SizedBox(height: screenSize.height * 0.03),
CommonTextFormField(
hintText: 'Enter your email',
controller: _usernameController,
prefixIcon: const Icon(
Icons.person,
color: AppColors.hittext,
),
errorText: _emailError,
onChanged: (value) {
_validateEmail(value);
},
),
const SizedBox(height: 42),
CommonTextFormField(
hintText: 'Enter your password',
controller: _passwordController,
obscureText: _obscurePassword,
prefixIcon: const Icon(
Icons.lock,
color: AppColors.hittext,
),
errorText: _passwordError,
onChanged: (value) {
_validatePassword(value);
},
suffixIcon: IconButton(
icon: Icon(
_obscurePassword
? Icons.visibility_off
: Icons.visibility,
color: AppColors.hittext,
),
onPressed: () {
setState(() {
_obscurePassword = !_obscurePassword;
});
},
),
),
Align(
alignment: Alignment.centerRight,
child: TextButton(
onPressed: () {},
child: const Text(
"Forgot Password?",
style: TextStyle(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w400,
fontSize: 14,
height: 1.0,
letterSpacing: 0.1357,
color: Color(0xFFFF0000),
),
),
),
),
const SizedBox(height: 20),
CommanButton(
text: 'Sign in',
textStyle: const TextStyle(
fontFamily: 'Gilroy-Black',
fontWeight: FontWeight.w800,
fontSize: 20,
height: 1.0,
color: AppColors.secondprimary,
),
onPressed: () {
// Validate all fields
_validateEmail(_usernameController.text);
_validatePassword(_passwordController.text);
if (_emailError == null &&
_passwordError == null) {
final loginModel = LoginModel(
email: _usernameController.text.trim(),
password: _passwordController.text.trim(),
);
ref
.read(
loginFutureProvider(loginModel).future,
)
.then((response) async {
Fluttertoast.showToast(
msg:
'Login Successful: ${response['message']}',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
backgroundColor: Colors.green,
textColor: Colors.white,
fontSize: 10.0,
);
final userId = response['data'][0]['id'];
final prefs =
await SharedPreferences.getInstance();
final isVerified = prefs.getString(
'is_verified',
);
if (isVerified == '1') {
Get.toNamed(RouterConts.homescreen);
} else {
Get.toNamed(
RouterConts.otp,
arguments: userId,
); // Replace with your OTP route
}
})
.catchError((error) {
Fluttertoast.showToast(
msg: 'Login Failed: $error',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 10.0,
);
});
} else {
Fluttertoast.showToast(
msg: 'Please fix all errors',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
backgroundColor: Colors.orange,
textColor: Colors.white,
fontSize: 10.0,
);
}
},
isPrimary: true,
backgroundColor: AppColors.primary,
textColor: AppColors.secondprimary,
width: 230,
),
SizedBox(height: 30),
RichText(
text: TextSpan(
text: "Didn't have account? ",
style: TextStyle(
fontFamily: 'Gilroy-ExtraBold',
fontWeight: FontWeight.w700,
fontSize: 17,
height: 1.0,
letterSpacing: 0.01,
color: Color(0xFF9F9F9F),
),
children: [
TextSpan(
text: "Sign up",
style: TextStyle(color: Color(0xFF0066FF)),
recognizer: TapGestureRecognizer()
..onTap = () {
Get.toNamed(RouterConts.siguppage);
},
),
],
),
),
SizedBox(height: 30),
],
),
),
),
),
),
),
],
),
),
);
}
}