474 lines
21 KiB
Dart
474 lines
21 KiB
Dart
import 'dart:ui';
|
||
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter/services.dart';
|
||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||
import 'package:get/get.dart';
|
||
import 'package:glassmorphism/glassmorphism.dart';
|
||
import 'package:traderscircuit/Utils/Common/CustomTextFormField.dart';
|
||
import 'package:traderscircuit/Utils/Common/commonBotton.dart';
|
||
import 'package:traderscircuit/Utils/base_manager.dart';
|
||
import 'package:traderscircuit/Utils/text.dart';
|
||
import 'package:traderscircuit/Utils/utils.dart';
|
||
import 'package:traderscircuit/resources/routes/route_name.dart';
|
||
import 'package:traderscircuit/view/login/VerifyOtp.dart';
|
||
import 'package:traderscircuit/view/onBoarding/splashScreen1.dart';
|
||
import 'package:traderscircuit/view_model/Login/send_otp_api.dart';
|
||
import 'package:traderscircuit/Utils/Dialogs.dart';
|
||
import 'package:traderscircuit/view_model/LoginPage/Loginbloc.dart';
|
||
|
||
import '../../view_model/LoginPage/Loginobserver.dart';
|
||
import '../../view_model/SendOtp/sendOtpObserver.dart';
|
||
import '../../view_model/SendOtp/sendOtpbloc.dart';
|
||
|
||
class LoginScreen extends StatefulWidget {
|
||
const LoginScreen({super.key});
|
||
|
||
@override
|
||
State<LoginScreen> createState() => _LoginScreenState();
|
||
}
|
||
|
||
class _LoginScreenState extends State<LoginScreen> {
|
||
final GlobalKey<FormState> _sendotpform = GlobalKey<FormState>();
|
||
TextEditingController phonecontroller = TextEditingController();
|
||
bool isValidPhoneNumber(String phoneNumber) {
|
||
final RegExp phoneNumberExpression = RegExp(r"^0{10}$");
|
||
|
||
return !phoneNumberExpression.hasMatch(phoneNumber);
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
// final CounterBloc counterbloc = BlocProvider.of<CounterBloc>(context);
|
||
//final sendOtpBloc = context.read<SendOtpBloc>();
|
||
|
||
return WillPopScope(
|
||
onWillPop: () async {
|
||
_onBackButtonPressed(context);
|
||
return true; // Return true to allow the pop action
|
||
},
|
||
child: Scaffold(
|
||
backgroundColor: Colors.black,
|
||
extendBody: true,
|
||
body: BlocProvider<SendOtpBloc>(
|
||
create: (context) => SendOtpBloc(),
|
||
child: Stack(
|
||
children: [
|
||
const CommonBlurLeft(),
|
||
const CommonBlurRight(),
|
||
Stack(
|
||
children: [
|
||
Padding(
|
||
padding: const EdgeInsets.symmetric(
|
||
horizontal: 16, vertical: 16),
|
||
child: Form(
|
||
key: _sendotpform,
|
||
child: ListView(
|
||
physics: const BouncingScrollPhysics(),
|
||
// mainAxisAlignment: MainAxisAlignment.start,
|
||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
SizedBox(
|
||
height: 20.h,
|
||
),
|
||
const Row(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
Text(
|
||
"Traders Circuit",
|
||
style: TextStyle(
|
||
fontFamily: 'hiragino',
|
||
color: Colors.white,
|
||
fontSize: 25,
|
||
fontWeight: FontWeight.w600),
|
||
),
|
||
],
|
||
),
|
||
SizedBox(
|
||
height: 42.h,
|
||
),
|
||
//bloc implementation
|
||
/* GestureDetector(
|
||
onTap: () {
|
||
counterbloc.add(NumberIncreaseEvent());
|
||
},
|
||
child: SizedBox(
|
||
height: 80.h,
|
||
child: Text(
|
||
"click me",
|
||
style: TextStyle(
|
||
fontFamily: 'hiragino',
|
||
color: Colors.white,
|
||
fontSize: 24,
|
||
fontWeight: FontWeight.w700),
|
||
),
|
||
),
|
||
),
|
||
if (state is UpdateState)
|
||
Text(
|
||
"${state.counter}",
|
||
style: TextStyle(
|
||
fontFamily: 'hiragino',
|
||
color: Colors.white,
|
||
fontSize: 24,
|
||
fontWeight: FontWeight.w700),
|
||
),
|
||
*/
|
||
const Text(
|
||
"Lets get started ",
|
||
style: TextStyle(
|
||
fontFamily: 'hiragino',
|
||
color: Colors.white,
|
||
fontSize: 24,
|
||
fontWeight: FontWeight.w700),
|
||
),
|
||
SizedBox(
|
||
height: 10.h,
|
||
),
|
||
text18W800("Enter your mobile number to get otp"),
|
||
SizedBox(
|
||
height: 35.h,
|
||
),
|
||
Row(
|
||
children: [
|
||
Expanded(
|
||
child: GlassmorphicContainer(
|
||
width: 60,
|
||
height: 50,
|
||
borderRadius: 8,
|
||
blur: 10,
|
||
alignment: Alignment.center,
|
||
border: 0.8,
|
||
linearGradient: LinearGradient(
|
||
begin: Alignment.topLeft,
|
||
end: Alignment.bottomRight,
|
||
colors: [
|
||
Colors.white.withOpacity(0.1),
|
||
const Color(0xFFFFFFFF)
|
||
.withOpacity(0.05),
|
||
],
|
||
stops: const [
|
||
0.1,
|
||
1,
|
||
]),
|
||
borderGradient: LinearGradient(
|
||
begin: Alignment.topLeft,
|
||
end: Alignment.bottomRight,
|
||
colors: [
|
||
const Color(0xff9A0000).withOpacity(0.5),
|
||
const Color(0xFFffffff).withOpacity(0.5),
|
||
],
|
||
),
|
||
child: Row(
|
||
crossAxisAlignment:
|
||
CrossAxisAlignment.center,
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
// SvgPicture.asset("assets/images/svg/india.svg"),
|
||
Image.asset(
|
||
"assets/images/png/india.png",
|
||
height: 25.h,
|
||
width: 25.h,
|
||
),
|
||
const SizedBox(
|
||
width: 2,
|
||
),
|
||
const Text(
|
||
"+91",
|
||
style: TextStyle(
|
||
fontFamily: 'hiragino',
|
||
fontSize: 15,
|
||
color: Colors.white,
|
||
),
|
||
)
|
||
],
|
||
),
|
||
),
|
||
),
|
||
const SizedBox(
|
||
width: 10,
|
||
),
|
||
SizedBox(
|
||
width: 285.w,
|
||
child: CustomTextFormField(
|
||
texttype: TextInputType.phone,
|
||
textEditingController: phonecontroller,
|
||
// validator: (value) {
|
||
// if (value.isEmpty) {
|
||
// return 'Enter your phone number';
|
||
// } else if (!RegExp(r'(^(?:[+0]9)?[0-9]{10}$)')
|
||
// .hasMatch(value)) {
|
||
// return 'Enter a valid phone number';
|
||
// } else if (!isValidPhoneNumber(value)) {
|
||
// return 'Phone number cannot contain 10 zeros';
|
||
// }
|
||
// return null;
|
||
// },
|
||
inputFormatters: [
|
||
LengthLimitingTextInputFormatter(10),
|
||
FilteringTextInputFormatter.allow(
|
||
RegExp('[0-9]')),
|
||
],
|
||
),
|
||
)
|
||
],
|
||
),
|
||
const SizedBox(
|
||
height: 10,
|
||
),
|
||
text14W300(
|
||
"We’ll send six digit code to the registered number. Standard data rates may apply"),
|
||
SizedBox(
|
||
height: 65.h,
|
||
),
|
||
|
||
BlocConsumer<SendOtpBloc, SendOtpState>(
|
||
listener: (context, state) {
|
||
if (state == SendOtpState.success) {
|
||
WidgetsBinding.instance
|
||
?.addPostFrameCallback((_) {
|
||
Get.toNamed(RouteName.verifyotp, arguments: {
|
||
"phonenumber": phonecontroller.text,
|
||
});
|
||
});
|
||
} else if (state == SendOtpState.failure) {
|
||
Utils.showToast("Oops something went wrong");
|
||
}
|
||
}, builder: (context, state) {
|
||
print(state);
|
||
if (state == SendOtpState.loading) {
|
||
return Center(
|
||
child: Container(
|
||
height: 40,
|
||
width: 40,
|
||
child: CircularProgressIndicator()));
|
||
}
|
||
return CommonBtn(
|
||
text: "Login/Signup",
|
||
onTap: () async {
|
||
final isValid =
|
||
_sendotpform.currentState?.validate();
|
||
if (isValid!) {
|
||
FocusManager.instance.primaryFocus
|
||
?.unfocus();
|
||
if (isValid != null && isValid) {
|
||
Map<String, String> myLoginData = {
|
||
"mobile_number": phonecontroller.text,
|
||
};
|
||
context
|
||
.read<SendOtpBloc>()
|
||
.add(SendOtp(myLoginData));
|
||
} else {
|
||
ScaffoldMessenger.of(context)
|
||
.showSnackBar(
|
||
SnackBar(
|
||
content: Text(
|
||
'Please enter valid phone number'),
|
||
),
|
||
);
|
||
}
|
||
}
|
||
});
|
||
}),
|
||
|
||
SizedBox(
|
||
height: 10.h,
|
||
),
|
||
text14W300(
|
||
"By continuing, you agree to our Terms & Conditions"),
|
||
SizedBox(
|
||
height: 45.h,
|
||
),
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
Container(
|
||
height: 0.2.h,
|
||
width: 108.w,
|
||
color: Colors.white,
|
||
),
|
||
SizedBox(
|
||
width: 22.w,
|
||
),
|
||
text18W600("OR"),
|
||
SizedBox(
|
||
width: 22.w,
|
||
),
|
||
Container(
|
||
height: 0.2.h,
|
||
width: 108.w,
|
||
color: Colors.white,
|
||
),
|
||
],
|
||
),
|
||
SizedBox(
|
||
height: 40.h,
|
||
),
|
||
GlassmorphicContainer(
|
||
width: double.infinity,
|
||
height: 55.h,
|
||
borderRadius: 8,
|
||
linearGradient: LinearGradient(
|
||
begin: Alignment.topLeft,
|
||
end: Alignment.bottomRight,
|
||
colors: [
|
||
const Color(0xFFffffff).withOpacity(0.1),
|
||
const Color(0xFFFFFFFF).withOpacity(0.05),
|
||
],
|
||
stops: const [
|
||
0.1,
|
||
1,
|
||
]),
|
||
border: 0.3,
|
||
blur: 10,
|
||
borderGradient: LinearGradient(
|
||
begin: Alignment.topLeft,
|
||
end: Alignment.bottomRight,
|
||
colors: [
|
||
const Color(0xFFAF2E89).withOpacity(0.2),
|
||
const Color(0xFFA23E31).withOpacity(0.2),
|
||
const Color(0xFF0000).withOpacity(0.2),
|
||
],
|
||
stops: const [
|
||
0.3,
|
||
0.6,
|
||
1,
|
||
]),
|
||
child: Center(
|
||
child: Row(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
Image.asset(
|
||
"assets/images/png/apple.png",
|
||
height: 30.h,
|
||
width: 30.w,
|
||
),
|
||
SizedBox(
|
||
width: 7.h,
|
||
),
|
||
text16W400("Continue with apple"),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
SizedBox(
|
||
height: 15.h,
|
||
),
|
||
GlassmorphicContainer(
|
||
width: double.infinity,
|
||
height: 55.h,
|
||
borderRadius: 8,
|
||
linearGradient: LinearGradient(
|
||
begin: Alignment.topLeft,
|
||
end: Alignment.bottomRight,
|
||
colors: [
|
||
const Color(0xFFffffff).withOpacity(0.1),
|
||
const Color(0xFFFFFFFF).withOpacity(0.05),
|
||
],
|
||
stops: const [
|
||
0.1,
|
||
1,
|
||
]),
|
||
border: 0.5,
|
||
blur: 10,
|
||
borderGradient: LinearGradient(
|
||
begin: Alignment.topLeft,
|
||
end: Alignment.bottomRight,
|
||
colors: [
|
||
const Color(0xFFAF2E89).withOpacity(0.2),
|
||
const Color(0xFFA23E31).withOpacity(0.2),
|
||
const Color(0xFF0000).withOpacity(0.2),
|
||
],
|
||
stops: const [
|
||
0.3,
|
||
0.6,
|
||
1,
|
||
]),
|
||
child: Center(
|
||
child: Row(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
Image.asset(
|
||
"assets/images/png/google.png",
|
||
height: 30.h,
|
||
width: 30.w,
|
||
),
|
||
SizedBox(
|
||
width: 7.h,
|
||
),
|
||
text16W400(
|
||
"Continue with google",
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
SizedBox(
|
||
height: 45.h,
|
||
),
|
||
Row(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
InkWell(
|
||
onTap: () {
|
||
Get.toNamed(RouteName.mainscreen);
|
||
},
|
||
child: text16W700(
|
||
"Continue as guest",
|
||
),
|
||
),
|
||
],
|
||
)
|
||
],
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Future<bool> _onBackButtonPressed(BuildContext context) async {
|
||
bool? exitApp = await showDialog(
|
||
context: context,
|
||
builder: (context) {
|
||
return AlertDialog(
|
||
backgroundColor: const Color(0xFFFFF3E4),
|
||
title: const Text('Exit App'),
|
||
content: const Text('Do you really want to close the app?'),
|
||
actions: [
|
||
TextButton(
|
||
onPressed: () {
|
||
Navigator.of(context).pop(false);
|
||
},
|
||
child: const Text(
|
||
'No',
|
||
style: TextStyle(
|
||
color: Color(0xff1B243D),
|
||
),
|
||
),
|
||
),
|
||
TextButton(
|
||
onPressed: () {
|
||
SystemNavigator.pop();
|
||
Navigator.pop(context);
|
||
},
|
||
child: const Text(
|
||
'Yes',
|
||
style: TextStyle(
|
||
color: Color(0xff1B243D),
|
||
),
|
||
),
|
||
)
|
||
],
|
||
);
|
||
});
|
||
return exitApp ?? false;
|
||
}
|
||
}
|