Files
be_happy_public/lib/presentation/screens/phone_login_screen.dart
2026-05-12 12:02:40 +03:00

184 lines
6.0 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:be_happy/presentation/event/spalsh_event.dart';
import 'package:be_happy/presentation/viewmodel/splash_bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import '../../../core/app_colors.dart';
import '../components/code_dots.dart';
import '../components/gradient_button.dart';
import '../event/verify_code_event.dart';
import '../state/verify_code_state.dart';
import '../viewmodel/verify_code_bloc.dart';
import 'pin_login_screen.dart';
class PhoneLoginScreen extends StatefulWidget {
final String phoneNumber;
final String tempToken;
const PhoneLoginScreen({
Key? key,
required this.phoneNumber,
required this.tempToken,
}) : super(key: key);
@override
State<PhoneLoginScreen> createState() => _PhoneLoginScreenState();
}
class _PhoneLoginScreenState extends State<PhoneLoginScreen> {
final TextEditingController codeController = TextEditingController();
final FocusNode codeFocusNode = FocusNode();
bool _isFirstTry = true;
@override
void initState() {
super.initState();
context.read<VerifyCodeBloc>().add(
VerifyCodeStarted(
phoneNumber: widget.phoneNumber,
tempToken: widget.tempToken,
),
);
codeController.addListener(() {
context.read<VerifyCodeBloc>().add(CodeChanged(codeController.text));
if (codeController.text.length == 6) {
Future.delayed(const Duration(milliseconds: 150), () {
context.read<VerifyCodeBloc>().add(VerifyCodeSubmitted());
});
}
});
WidgetsBinding.instance.addPostFrameCallback((_) {
FocusScope.of(context).requestFocus(codeFocusNode);
});
}
void openKeyboard() {
if (codeFocusNode.hasFocus) {
codeFocusNode.unfocus();
}
Future.delayed(const Duration(milliseconds: 50), () {
FocusScope.of(context).requestFocus(codeFocusNode);
});
}
@override
void dispose() {
codeController.dispose();
codeFocusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocConsumer<VerifyCodeBloc, VerifyCodeState>(
listener: (context, state) {
if (state.isSuccess) {
context.go("/pin");
} else if (state.error != null) {
setState(() {
_isFirstTry = false;
});
codeController.clear();
FocusScope.of(context).requestFocus(codeFocusNode);
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text(state.error!)));
} else if (state.isBlocked) {
context.go("/block");
}
},
builder: (context, state) {
return Scaffold(
resizeToAvoidBottomInset: true,
body: Container(
width: double.infinity,
decoration: const BoxDecoration(gradient: AppColors.phoneScreenBg),
child: SafeArea(
child: Stack(
children: [
Positioned(
top: 310,
left: 0,
right: 0,
child: Image.asset("assets/wave.png", fit: BoxFit.cover),
),
Column(
children: [
const SizedBox(height: 60),
const Text(
"Код отправлен на номер",
style: TextStyle(
fontSize: 18,
color: AppColors.whiteText,
),
),
const SizedBox(height: 6),
Text(
widget.phoneNumber,
style: const TextStyle(
fontSize: 20,
color: AppColors.whiteText,
),
),
const SizedBox(height: 35),
GestureDetector(
onTap: openKeyboard,
child: CodeDots(code: state.code, length: 6),
),
const SizedBox(height: 8),
if (!_isFirstTry)
Text(
"Осталось ${state.attemptsLeft} попытк${state.attemptsLeft == 1 ? 'а' : 'и'}",
style: const TextStyle(
color: AppColors.pinError,
fontSize: 14,
),
),
const SizedBox(height: 40),
GradientButton(
text: state.secondsLeft == 0
? "Отправить код повторно"
: "Отправить код повторно\nчерез 00:${state.secondsLeft.toString().padLeft(2, '0')} сек.",
onTap: state.secondsLeft == 0
? () {
context.read<VerifyCodeBloc>().add(
ResendCodePressed(),
);
}
: () {},
enabled: state.secondsLeft == 0,
width: 250,
),
const Spacer(),
SizedBox(
height: 50,
width: double.infinity,
child: Opacity(
opacity: 0.0,
child: TextField(
controller: codeController,
focusNode: codeFocusNode,
keyboardType: TextInputType.number,
maxLength: 6,
autofocus: true,
),
),
),
],
),
],
),
),
),
);
},
);
}
}