Initial commit

This commit is contained in:
jahongireshonqulov
2025-10-18 09:40:06 +05:00
commit 1bf3e41abe
352 changed files with 16315 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
class AuthConfirmArgument {
final String? fullName;
final String? mail;
final String? phoneNumber;
final bool fromLoginPage;
final String? password;
AuthConfirmArgument({
this.fullName,
required this.mail,
required this.phoneNumber,
required this.fromLoginPage,
this.password,
});
}

View File

@@ -0,0 +1,233 @@
import 'package:cargocalculaterapp/core/extension/build_context_extension.dart';
import 'package:cargocalculaterapp/core/utils/app_utils.dart';
import 'package:cargocalculaterapp/core/widgets/loading/custom_loading.dart';
import 'package:cargocalculaterapp/features/auth/presentation/pages/auth_confirm/timer_widget.dart';
import 'package:cargocalculaterapp/generated/l10n.dart';
import 'package:cargocalculaterapp/router/name_routes.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:pin_code_fields/pin_code_fields.dart';
import '../../../../../core/theme/app_text_styles.dart';
import '../../../../../core/theme/colors/app_colors.dart';
import '../../bloc/auth_confirm/auth_confirm_bloc.dart';
import '../mixin/auth_confirm_mixin.dart';
import 'argument/auth_confirm_argument.dart';
class AuthConfirmPage extends StatefulWidget {
const AuthConfirmPage({super.key, required this.argument});
final AuthConfirmArgument? argument;
@override
State<AuthConfirmPage> createState() => _AuthConfirmPageState();
}
class _AuthConfirmPageState extends State<AuthConfirmPage>
with AuthConfirmMixin {
@override
void initState() {
initControllers();
super.initState();
}
@override
Widget build(BuildContext context) {
return BlocConsumer<AuthConfirmBloc, AuthConfirmState>(
listener: (context, state) {
if (state is SuccessSate) {
Navigator.pushNamedAndRemoveUntil(
context,
Routes.main,
(route) => route.isFirst,
);
}
},
builder: (context, state) {
return Scaffold(
appBar: AppBar(),
body: Padding(
padding: AppUtils.kPaddingAll16,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: 64,
height: 64,
decoration: BoxDecoration(
borderRadius: AppUtils.kBorderRadius16,
color: context.color.iconBackground,
),
padding: AppUtils.kPaddingAll16,
child: SvgPicture.asset(
"assets/svg/ic_mail.svg",
width: 32,
height: 32,
),
),
AppUtils.kBoxHeight16,
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Text(
(widget.argument?.mail?.isNotEmpty ?? false)
? AppLocalization.current.confirm_email
: AppLocalization.current.confirm_phone_text,
style: context.text.authTitle,
textAlign: TextAlign.center,
),
),
AppUtils.kBoxHeight16,
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Text(
(widget.argument?.mail?.isNotEmpty ?? false)
? AppLocalization.current.enter_code_mail(
widget.argument?.mail ?? "",
)
: AppLocalization.current.enter_code_phone(
widget.argument?.phoneNumber ?? "",
),
style: context.text.authDesc,
textAlign: TextAlign.center,
),
),
AppUtils.kBoxHeight48,
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 296,
child: PinCodeTextField(
controller: confirmController,
appContext: context,
autoDisposeControllers: false,
length: 4,
animationType: AnimationType.scale,
enabled: true,
enablePinAutofill: true,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
onChanged: (code) {
context.read<AuthConfirmBloc>().add(
SmsCodeEnterEvent(code),
);
},
autoFocus: true,
keyboardType: const TextInputType.numberWithOptions(),
showCursor: true,
textStyle: context.text.bigTitle,
cursorColor: context.color.accentColor,
cursorHeight: 20,
enableActiveFill: true,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
pinTheme: PinTheme(
activeColor:
state is ErrorState
? ThemeColors.timerRed
: state is SuccessSate
? ThemeColors.successInputSMS
: context.color.borderColor,
selectedFillColor:
context.color.scaffoldBackgroundColor,
activeFillColor:
context.color.scaffoldBackgroundColor,
shape: PinCodeFieldShape.box,
inactiveFillColor:
context.color.scaffoldBackgroundColor,
borderRadius: const BorderRadius.all(
Radius.circular(12),
),
borderWidth: 1,
inactiveColor:
state is ErrorState
? ThemeColors.timerRed
: state is SuccessSate
? ThemeColors.successInputSMS
: context.color.borderColor,
fieldWidth: 56,
fieldHeight: 64,
selectedColor:
state is ErrorState
? ThemeColors.timerRed
: state is SuccessSate
? ThemeColors.successInputSMS
: context.color.primaryColor,
),
),
),
],
),
if (state is ErrorState) AppUtils.kBoxHeight16,
if (state is ErrorState)
Center(
child: Text(
AppLocalization.current.incorrect_code,
style: AppTextStyles.timerBlue,
),
),
AppUtils.kBoxHeight24,
if (state.isTimerVisible)
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
AppLocalization.current.send_sms,
style: AppTextStyles.timerBlue,
),
const TimerWidget(),
],
),
if (!state.isTimerVisible)
Center(
child: GestureDetector(
onTap: () {
if (widget.argument != null) {
context.read<AuthConfirmBloc>().add(
ResendCodeEvent(argument: widget.argument!),
);
}
},
child: Text(
AppLocalization.current.send_sms,
style: AppTextStyles.timerBlue,
),
),
),
AppUtils.kBoxHeight48,
Padding(
padding: AppUtils.kPaddingHor34,
child: ElevatedButton(
onPressed:
(confirmController.text.length == 4 &&
state is! LoadingState)
? () {
context.read<AuthConfirmBloc>().add(
OnSubmitEvent(
code: confirmController.text,
argument: widget.argument,
),
);
}
: null,
child:
state is LoadingState
? const CustomLoadingWidget()
: Text(AppLocalization.current.confirm),
),
),
],
),
),
);
},
);
}
@override
void dispose() {
disposeController();
super.dispose();
}
}

View File

@@ -0,0 +1,49 @@
import 'dart:async';
import 'package:cargocalculaterapp/core/theme/app_text_styles.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../bloc/auth_confirm/auth_confirm_bloc.dart';
class TimerWidget extends StatefulWidget {
const TimerWidget({super.key});
@override
State<TimerWidget> createState() => _TimerWidgetState();
}
class _TimerWidgetState extends State<TimerWidget> {
Timer? timer;
int time = 60;
String timeText = "60";
@override
void initState() {
if (timer?.isActive ?? false) {
timer?.cancel();
}
timer = Timer.periodic(const Duration(seconds: 1), (Timer timer) async {
time--;
if (time == 0) {
timer.cancel();
context.read<AuthConfirmBloc>().add(
const TimerChangedEvent(isVisible: false),
);
}
setState(() {
timeText = time.toString().padLeft(2, "0");
});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Text(" 00:$timeText", style: AppTextStyles.timerStyle);
}
@override
void dispose() {
timer?.cancel();
super.dispose();
}
}