register user detail

This commit is contained in:
jayesh
2024-05-31 17:01:48 +05:30
parent 264f53373f
commit bc1dcf6c3b
44 changed files with 815 additions and 62 deletions

View File

@@ -34,7 +34,7 @@ class CountrySelectionList extends StatelessWidget {
height: 24,
),
const Gap(10),
TextWidget().tex14W500(countryName[index],
TextWidget().text14W500(countryName[index],
clr: AppColor.charcoalColor),
],
),

View File

@@ -31,7 +31,7 @@ class BottomSection extends StatelessWidget {
function: () {
goRouter.goNamed(RouteName.loginScreen);
},
text: TextWidget().tex15W400(AppText.forgorPassword,
text: TextWidget().text15W400(AppText.forgorPassword,
clr: AppColor.forgotPassButtonColor,
textDecoration: TextDecoration.underline)),
),
@@ -103,7 +103,7 @@ class BottomSection extends StatelessWidget {
"fromScreentype": "login",
});
},
text: TextWidget().tex14W700(AppText.signUpText,
text: TextWidget().text14W700(AppText.signUpText,
clr: AppColor.textLabelColor,
textDecoration: TextDecoration.underline)),
],

View File

@@ -4,6 +4,7 @@ import 'package:gap/gap.dart';
import 'package:tanami_app/core/styles/app_text.dart';
import 'package:tanami_app/core/utils/constant/country_flag_data.dart';
import '../../../../shared/components/bloc/password_field/password_visibility_bloc.dart';
import '../../../../shared/components/form_label_textfield.dart';
import '../../../countrySelection/presentation/bloc/choose_country_bloc.dart';
import '../../../countrySelection/presentation/bloc/choose_country_state.dart';
@@ -70,11 +71,14 @@ class LoginForm extends StatelessWidget {
textEditingController: loginBloc.phoneNumberTextField,
),
const Gap(20),
FormLabelTextField(
hintText: AppText.enterPassword,
title: AppText.password,
type: "password",
textEditingController: loginBloc.passwordTextField,
BlocProvider(
create: (_) => PasswordVisibilityBloc(),
child: FormLabelTextField(
hintText: AppText.enterPassword,
title: AppText.password,
type: "password",
textEditingController: loginBloc.passwordTextField,
),
),
],
),

View File

@@ -21,14 +21,14 @@ class TopSection extends StatelessWidget {
),
),
const Gap(60),
TextWidget().tex20W700(
TextWidget().text20W700(
AppText.welcomeText,
clr: AppColor.charcoalColor,
),
const Gap(10),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 75),
child: TextWidget().tex14W500(
child: TextWidget().text14W500(
AppText.pleaseEnterLoginDetails,
clr: AppColor.smokeGrayColor,
),

View File

@@ -0,0 +1,46 @@
// timer_bloc.dart
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'timer_event.dart';
import 'timer_state.dart';
class TimerBloc extends Bloc<TimerEvent, TimerState> {
Timer? _timer;
TimerBloc() : super(const TimerInitial()) {
on<StartTimer>(_onStartTimer);
on<Tick>(_onTick);
}
void _onStartTimer(StartTimer event, Emitter<TimerState> emit) {
const int duration = 300; // 5 minutes in seconds
emit(const TimerRunInProgress(duration));
_startTicker(duration);
}
void _onTick(Tick event, Emitter<TimerState> emit) {
if (event.duration > 0) {
emit(TimerRunInProgress(event.duration));
} else {
emit(const TimerRunComplete());
}
}
void _startTicker(int duration) {
_timer?.cancel();
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
if (duration - timer.tick > 0) {
add(Tick(duration - timer.tick));
} else {
timer.cancel();
add(const Tick(0));
}
});
}
@override
Future<void> close() {
_timer?.cancel();
return super.close();
}
}

View File

@@ -0,0 +1,20 @@
// timer_event.dart
import 'package:equatable/equatable.dart';
abstract class TimerEvent extends Equatable {
const TimerEvent();
@override
List<Object> get props => [];
}
class StartTimer extends TimerEvent {}
class Tick extends TimerEvent {
final int duration;
const Tick(this.duration);
@override
List<Object> get props => [duration];
}

View File

@@ -0,0 +1,28 @@
// timer_state.dart
import 'package:equatable/equatable.dart';
class TimerState extends Equatable {
final int duration;
const TimerState(this.duration);
String get formattedDuration {
final minutes = (duration ~/ 60).toString().padLeft(2, '0');
final seconds = (duration % 60).toString().padLeft(2, '0');
return '$minutes:$seconds';
}
@override
List<Object> get props => [duration];
}
class TimerInitial extends TimerState {
const TimerInitial() : super(300); // Initial state with 5 minutes
}
class TimerRunInProgress extends TimerState {
const TimerRunInProgress(int duration) : super(duration);
}
class TimerRunComplete extends TimerState {
const TimerRunComplete() : super(0);
}

View File

@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:tanami_app/features/otpVerification/presentation/widgets/otp_fill_section.dart';
import '../widgets/otp_top_section.dart';
import '../widgets/resend_otp_section.dart';
class OtpLayout extends StatelessWidget {
const OtpLayout({super.key});
@@ -13,6 +14,7 @@ class OtpLayout extends StatelessWidget {
children: const [
OtpTopSection(),
OtpFillSection(),
ResendOtpSection(),
],
));
}

View File

@@ -4,6 +4,8 @@ import 'package:tanami_app/features/otpVerification/presentation/bloc/otp_bloc.d
import 'package:tanami_app/features/otpVerification/presentation/pages/otp_layout.dart';
import '../bloc/otp_event.dart';
import '../bloc/timer/timer_bloc.dart';
import '../bloc/timer/timer_event.dart';
class OtpScreen extends StatelessWidget {
const OtpScreen({super.key});
@@ -18,6 +20,10 @@ class OtpScreen extends StatelessWidget {
// Create an instance of the OnboardingBloc
create: (context) => OtpBloc()..add(StartListeningForOtp()),
),
BlocProvider(
create: (context) =>
TimerBloc()..add(StartTimer()), // Start the timer here
),
],
child: const OtpLayout(),
),

View File

@@ -2,8 +2,10 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:sms_autofill/sms_autofill.dart';
import 'package:tanami_app/core/routes/route_name.dart';
import 'package:tanami_app/core/routes/routes.dart';
import 'package:tanami_app/core/styles/app_color.dart';
import 'package:tanami_app/core/styles/app_text.dart';
import 'package:tanami_app/shared/components/loader.dart';
import 'package:tanami_app/shared/components/toast_message.dart';
@@ -22,10 +24,15 @@ class OtpFillSection extends StatelessWidget {
Loader.loader(context);
} else if (state is OtpSubmissionSuccess) {
goRouter.pop();
successToastMessage(context, 'OTP Verified Successfully!');
successToastMessage(
context,
AppText.otpVerifiedSucessfully,
);
goRouter.pushNamed(RouteName.registerUserDetailsScreen);
} else if (state is OtpSubmissionFailure) {
goRouter.pop();
errorToastMessage(context, 'OTP Verification Failed: ${state.error}');
errorToastMessage(
context, '${AppText.otpVerifiedFailed} ${state.error}');
}
},
builder: (context, state) {

View File

@@ -22,14 +22,14 @@ class OtpTopSection extends StatelessWidget {
),
),
const Gap(125),
TextWidget().tex20W700(
TextWidget().text20W700(
AppText.checkYourMessages,
clr: AppColor.charcoalColor,
),
const Gap(25),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 35),
child: TextWidget().tex14W500(
child: TextWidget().text14W500(
AppText.referToSameOtpMessage,
clr: AppColor.smokeGrayColor,
),

View File

@@ -0,0 +1,43 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:tanami_app/core/styles/app_color.dart';
import 'package:tanami_app/core/styles/app_text.dart';
import 'package:tanami_app/shared/components/text_widget.dart';
import 'package:tanami_app/shared/components/toast_message.dart';
import '../bloc/timer/timer_bloc.dart';
import '../bloc/timer/timer_state.dart';
class ResendOtpSection extends StatelessWidget {
const ResendOtpSection({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<TimerBloc, TimerState>(
builder: (context, state) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
TextWidget().text14W500(
state.formattedDuration,
clr: AppColor.plainBlack,
),
InkWell(
onTap: () {
successToastMessage(context, "OTP Resend Sucessfully !");
},
child: TextWidget().text14W500(
AppText.resendSms,
clr: AppColor.plainBlack,
textDecoration: TextDecoration.underline,
),
)
],
),
);
},
);
}
}

View File

@@ -8,7 +8,6 @@ class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
final TextEditingController countrySelectionTextField =
TextEditingController();
final TextEditingController phoneNumberTextField = TextEditingController();
final TextEditingController passwordTextField = TextEditingController();
GlobalKey<FormState> getFormKey() {
return formKey;
@@ -16,7 +15,7 @@ class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
RegisterBloc() : super(RegisterInitial()) {
phoneNumberTextField.addListener(_onFormFieldChanged);
passwordTextField.addListener(_onFormFieldChanged);
countrySelectionTextField.addListener(_onFormFieldChanged);
on<RegisterFormChanged>(_onLoginFormChanged);
on<RegisterSubmitted>((event, emit) async {
@@ -28,8 +27,8 @@ class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
// Simulate API call
await Future.delayed(const Duration(seconds: 2));
// Replace the next line with actual API call
final isSuccess = await _mockLoginApi(
event.phoneNumber, event.password, event.countryResidence);
final isSuccess =
await _mockLoginApi(event.phoneNumber, event.countryResidence);
if (isSuccess) {
emit(RegisterSuccess());
} else {
@@ -58,7 +57,6 @@ class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
// Mock API function, replace with actual API call
Future<bool> _mockLoginApi(
String phoneNumber,
String password,
String countryResidence,
) async {
return true;
@@ -67,7 +65,7 @@ class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
@override
Future<void> close() {
phoneNumberTextField.dispose();
passwordTextField.dispose();
countrySelectionTextField.dispose();
return super.close();
}

View File

@@ -9,17 +9,16 @@ abstract class RegisterEvent extends Equatable {
class RegisterSubmitted extends RegisterEvent {
final String phoneNumber;
final String password;
final String countryResidence;
const RegisterSubmitted(
this.phoneNumber,
this.password,
this.countryResidence,
);
@override
List<Object> get props => [phoneNumber, password, countryResidence];
List<Object> get props => [phoneNumber, countryResidence];
}
class RegisterFormChanged extends RegisterEvent {

View File

@@ -0,0 +1,94 @@
import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'register_user_event.dart';
import 'register_user_state.dart';
class RegisterUserBloc extends Bloc<RegisterUserEvent, RegisterUserState> {
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
final TextEditingController firstNameTextField = TextEditingController();
final TextEditingController lastNameTextField = TextEditingController();
final TextEditingController emailTextField = TextEditingController();
final TextEditingController passwordTextField = TextEditingController();
final TextEditingController repeatPasswordTextField = TextEditingController();
GlobalKey<FormState> getFormKey() {
return formKey;
}
RegisterUserBloc() : super(RegisterUserInitial()) {
firstNameTextField.addListener(_onFormFieldChanged);
passwordTextField.addListener(_onFormFieldChanged);
lastNameTextField.addListener(_onFormFieldChanged);
emailTextField.addListener(_onFormFieldChanged);
repeatPasswordTextField.addListener(_onFormFieldChanged);
on<RegisterFormChanged>(_onLoginFormChanged);
on<RegisterUserSubmitted>((event, emit) async {
if (!formKey.currentState!.validate()) {
return;
}
emit(RegisterUserLoading());
try {
// Simulate API call
await Future.delayed(const Duration(seconds: 2));
// Replace the next line with actual API call
final isSuccess = await _mockLoginApi(
event.firstName,
event.password,
event.lastName,
event.confirmPassword,
event.email,
);
if (isSuccess) {
emit(RegisterUserSuccess());
} else {
emit(const RegisterUserFailure(
"Register failed. Please check your credentials."));
}
} catch (e) {
emit(RegisterUserFailure(e.toString()));
}
});
}
void _onFormFieldChanged() {
add(RegisterFormChanged(
firstNameTextField.text,
lastNameTextField.text,
emailTextField.text,
passwordTextField.text,
repeatPasswordTextField.text,
));
}
void _onLoginFormChanged(
RegisterFormChanged event, Emitter<RegisterUserState> emit) {
final areFieldsFilled = event.firstName.isNotEmpty &&
event.lastName.isNotEmpty &&
event.email.isNotEmpty &&
event.password.isNotEmpty &&
event.confirmPassword.isNotEmpty;
emit(RegisterUserFieldsState(areFieldsFilled));
}
// Mock API function, replace with actual API call
Future<bool> _mockLoginApi(
String firstName,
String password,
String confirmPassword,
String email,
String lastName,
) async {
return true;
}
@override
Future<void> close() {
firstNameTextField.dispose();
passwordTextField.dispose();
lastNameTextField.dispose();
emailTextField.dispose();
repeatPasswordTextField.dispose();
return super.close();
}
}

View File

@@ -0,0 +1,48 @@
import 'package:equatable/equatable.dart';
abstract class RegisterUserEvent extends Equatable {
const RegisterUserEvent();
@override
List<Object> get props => [];
}
class RegisterUserSubmitted extends RegisterUserEvent {
final String firstName;
final String lastName;
final String email;
final String password;
final String confirmPassword;
const RegisterUserSubmitted(
this.firstName,
this.password,
this.lastName,
this.confirmPassword,
this.email,
);
@override
List<Object> get props =>
[firstName, lastName, email, confirmPassword, password];
}
class RegisterFormChanged extends RegisterUserEvent {
final String firstName;
final String lastName;
final String email;
final String password;
final String confirmPassword;
const RegisterFormChanged(
this.firstName,
this.password,
this.lastName,
this.confirmPassword,
this.email,
);
@override
List<Object> get props =>
[firstName, lastName, email, confirmPassword, password];
}

View File

@@ -0,0 +1,32 @@
import 'package:equatable/equatable.dart';
abstract class RegisterUserState extends Equatable {
const RegisterUserState();
@override
List<Object> get props => [];
}
class RegisterUserInitial extends RegisterUserState {}
class RegisterUserLoading extends RegisterUserState {}
class RegisterUserSuccess extends RegisterUserState {}
class RegisterUserFailure extends RegisterUserState {
final String error;
const RegisterUserFailure(this.error);
@override
List<Object> get props => [error];
}
class RegisterUserFieldsState extends RegisterUserState {
final bool areFieldsFilled;
const RegisterUserFieldsState(this.areFieldsFilled);
@override
List<Object> get props => [areFieldsFilled];
}

View File

@@ -0,0 +1,26 @@
import 'package:flutter/material.dart';
import 'package:tanami_app/features/register/presentation/widgets/register_user_bottom_section.dart';
import '../../../../shared/components/appbar_widget.dart';
import '../widgets/register_user_form.dart';
import '../widgets/register_user_top_section.dart';
class RegisterUserDetailsLayout extends StatelessWidget {
const RegisterUserDetailsLayout({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const AppBarWidget(
height: 75,
titleTxt: "",
),
body: ListView(
children: const [
RegisterUserTopSection(),
RegisterUserForm(),
RegisterUserBottomSection(),
],
));
}
}

View File

@@ -0,0 +1,32 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:tanami_app/features/register/presentation/pages/register_user_details_layout.dart';
import 'package:tanami_app/shared/components/bloc/checkbox/checkbox_bloc.dart';
import '../bloc/register_user_bloc.dart';
class RegisterUserDetailsScreen extends StatelessWidget {
const RegisterUserDetailsScreen({
super.key,
});
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: true,
body: MultiBlocProvider(
providers: [
BlocProvider(
// Create an instance of the OnboardingBloc
create: (context) => RegisterUserBloc(),
),
BlocProvider(
// Create an instance of the OnboardingBloc
create: (context) => CheckboxBloc(),
),
],
child: const RegisterUserDetailsLayout(),
),
);
}
}

View File

@@ -75,10 +75,6 @@ class RegisterBottomSection extends StatelessWidget {
.read<RegisterBloc>()
.phoneNumberTextField
.text,
context
.read<RegisterBloc>()
.passwordTextField
.text,
""),
)
: null;
@@ -97,7 +93,7 @@ class RegisterBottomSection extends StatelessWidget {
radioBloc.resetSelection();
goRouter.pop();
},
text: TextWidget().tex14W700(AppText.backText,
text: TextWidget().text14W700(AppText.backText,
clr: AppColor.textLabelColor,
textDecoration: TextDecoration.underline)),
],

View File

@@ -42,7 +42,7 @@ class RegisterStepBottomSection extends StatelessWidget {
"fromScreen": "registerStep",
});
},
text: TextWidget().tex14W700(
text: TextWidget().text14W700(
AppText.loginText,
clr: AppColor.darkGreyColor,
textDecoration: TextDecoration.underline,

View File

@@ -21,12 +21,12 @@ class RegisterStepCount extends StatelessWidget {
child: ListTile(
isThreeLine: true,
leading: SvgPicture.asset(stepImage[index]),
title: TextWidget().tex14W700(
title: TextWidget().text14W700(
title[index],
clr: AppColor.textLabelColor,
txtAlign: TextAlign.start,
),
subtitle: TextWidget().tex14W500(
subtitle: TextWidget().text14W500(
description[index],
clr: AppColor.textLabelColor,
txtAlign: TextAlign.start,

View File

@@ -21,14 +21,14 @@ class RegisterStepTopSection extends StatelessWidget {
),
),
const Gap(30),
TextWidget().tex20W700(
TextWidget().text20W700(
AppText.getStarted,
clr: AppColor.charcoalColor,
),
const Gap(10),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 75),
child: TextWidget().tex14W500(
child: TextWidget().text14W500(
AppText.setupYourTanamiAccountToBegin,
clr: AppColor.smokeGrayColor,
),

View File

@@ -21,14 +21,14 @@ class RegisterTopSection extends StatelessWidget {
),
),
const Gap(60),
TextWidget().tex20W700(
TextWidget().text20W700(
AppText.welcome,
clr: AppColor.charcoalColor,
),
const Gap(10),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 75),
child: TextWidget().tex14W500(
child: TextWidget().text14W500(
AppText.selectYourCountryOfResidence,
clr: AppColor.smokeGrayColor,
),

View File

@@ -0,0 +1,156 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:gap/gap.dart';
import 'package:tanami_app/core/styles/app_images.dart';
import 'package:tanami_app/shared/components/checkbox_widget.dart';
import 'package:tanami_app/shared/components/loader.dart';
import 'package:tanami_app/shared/components/toast_message.dart';
import '../../../../core/routes/route_name.dart';
import '../../../../core/routes/routes.dart';
import '../../../../core/styles/app_color.dart';
import '../../../../core/styles/app_text.dart';
import '../../../../shared/components/button_widget.dart';
import '../../../../shared/components/text_widget.dart';
import '../bloc/register_user_bloc.dart';
import '../bloc/register_user_event.dart';
import '../bloc/register_user_state.dart';
class RegisterUserBottomSection extends StatelessWidget {
const RegisterUserBottomSection({super.key});
@override
Widget build(BuildContext context) {
return Column(
children: [
const Gap(40),
Row(
children: [
const CheckBoxWidget(),
Container(
width: 0.8.sw,
child: Row(
children: [
const Text("I agree to the "),
InkWell(
onTap: () {
// Handle Terms & Conditions tap
},
child: const Text(
"Terms & Conditions",
style: TextStyle(
color: Colors.blue,
decoration: TextDecoration.underline,
),
),
),
const Text(" and the "),
InkWell(
onTap: () {
// Handle Privacy Policy tap
},
child: const Text(
"Privacy Policy",
style: TextStyle(
color: Colors.blue,
decoration: TextDecoration.underline,
),
),
),
],
),
)
],
),
const Gap(10),
Image.asset(
AppImages.stage2Image,
width: 75,
height: 12,
),
const Gap(36),
BlocConsumer<RegisterUserBloc, RegisterUserState>(
listener: (context, state) {
if (state is RegisterUserLoading) {
Loader.loader(context);
} else if (state is RegisterUserSuccess) {
successToastMessage(context, "successful !");
goRouter.pop();
goRouter.pushNamed(RouteName.otpScreen);
} else if (state is RegisterUserFailure) {
goRouter.pop();
errorToastMessage(
context,
state.error,
);
}
},
builder: (context, state) {
bool isButtonEnabled = false;
if (state is RegisterUserFieldsState) {
isButtonEnabled = state.areFieldsFilled;
} else if (state is RegisterUserSuccess ||
state is RegisterUserFailure) {
isButtonEnabled = true;
}
return Container(
margin: const EdgeInsets.symmetric(
horizontal: 16,
),
width: 1.sw,
height: 56.h,
child: ButtonWidget().elevatedBtn(
txtClr: isButtonEnabled
? AppColor.plainWhite
: AppColor.inactiveBtnTxtColor,
function: () {
isButtonEnabled
? context.read<RegisterUserBloc>().add(
RegisterUserSubmitted(
context
.read<RegisterUserBloc>()
.firstNameTextField
.text,
context
.read<RegisterUserBloc>()
.passwordTextField
.text,
context
.read<RegisterUserBloc>()
.lastNameTextField
.text,
context
.read<RegisterUserBloc>()
.repeatPasswordTextField
.text,
context
.read<RegisterUserBloc>()
.emailTextField
.text,
),
)
: null;
},
text: AppText.nextText,
clr: isButtonEnabled
? AppColor.primaryColor2
: AppColor.inactiveBtnColor,
),
);
},
),
const Gap(5),
ButtonWidget().textBtn(
function: () {
goRouter.pop();
},
text: TextWidget().text14W700(AppText.backText,
clr: AppColor.textLabelColor,
textDecoration: TextDecoration.underline)),
],
);
}
}

View File

@@ -0,0 +1,76 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:gap/gap.dart';
import 'package:tanami_app/core/styles/app_text.dart';
import '../../../../shared/components/bloc/password_field/password_visibility_bloc.dart';
import '../../../../shared/components/form_label_textfield.dart';
import '../bloc/register_user_bloc.dart';
class RegisterUserForm extends StatelessWidget {
const RegisterUserForm({super.key});
@override
Widget build(BuildContext context) {
final registerUserBloc = context.read<RegisterUserBloc>();
return Form(
key: registerUserBloc.formKey,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 14,
),
child: Align(
alignment: Alignment.topLeft,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Gap(50),
FormLabelTextField(
hintText: AppText.enterFirstName,
title: AppText.firstNameText,
type: AppText.firstNameText,
textEditingController: registerUserBloc.firstNameTextField,
),
const Gap(12),
FormLabelTextField(
hintText: AppText.enterLastName,
title: AppText.lastNameText,
type: AppText.lastNameText,
textEditingController: registerUserBloc.lastNameTextField,
),
const Gap(12),
FormLabelTextField(
hintText: AppText.enterEmail,
title: AppText.emailText,
type: AppText.emailText,
textEditingController: registerUserBloc.emailTextField,
),
const Gap(12),
BlocProvider(
create: (_) => PasswordVisibilityBloc(),
child: FormLabelTextField(
hintText: AppText.enterPassword,
title: AppText.password,
type: AppText.password.toLowerCase(),
textEditingController: registerUserBloc.passwordTextField,
),
),
const Gap(12),
BlocProvider(
create: (_) => PasswordVisibilityBloc(),
child: FormLabelTextField(
hintText: AppText.repeatPasswordText,
title: AppText.repeatPasswordText,
type: AppText.password.toLowerCase(),
textEditingController:
registerUserBloc.repeatPasswordTextField,
),
),
],
),
),
),
);
}
}

View File

@@ -0,0 +1,34 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:gap/gap.dart';
import 'package:tanami_app/core/styles/app_color.dart';
import 'package:tanami_app/core/styles/app_images.dart';
import 'package:tanami_app/core/styles/app_text.dart';
import 'package:tanami_app/shared/components/text_widget.dart';
class RegisterUserTopSection extends StatelessWidget {
const RegisterUserTopSection({super.key});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Gap(22),
Center(
child: SvgPicture.asset(
AppImages.weclomeLogo,
),
),
const Gap(25),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 75),
child: TextWidget().text14W500(
AppText.enterNameEmailUniquePassword,
clr: AppColor.smokeGrayColor,
),
),
],
);
}
}

View File

@@ -32,7 +32,7 @@ Widget buildOnboardingPage(
fit: BoxFit.cover,
),
const Gap(15),
TextWidget().tex22W700(
TextWidget().text22W700(
title,
clr: AppColor.primaryColor,
),
@@ -41,7 +41,7 @@ Widget buildOnboardingPage(
padding: const EdgeInsets.symmetric(
horizontal: 50,
),
child: TextWidget().tex15W500(
child: TextWidget().text15W500(
description,
clr: AppColor.darkGreyColor,
),

View File

@@ -42,7 +42,7 @@ class LoginSignUpButton extends StatelessWidget {
"fromScreen": "welcome",
});
},
text: TextWidget().tex14W700(
text: TextWidget().text14W700(
AppText.loginText,
clr: AppColor.darkGreyColor,
textDecoration: TextDecoration.underline,