Files
be_happy_public/lib/presentation/screens/pin_login_screen.dart
2026-05-12 12:03:37 +03:00

180 lines
6.1 KiB
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 '../event/map_event.dart';
import '../event/spalsh_event.dart';
import '../viewmodel/map_bloc.dart';
import '../viewmodel/pin_bloc.dart';
import '../event/pin_event.dart';
import '../state/pin_state.dart';
import '../viewmodel/splash_bloc.dart';
class PinLoginScreen extends StatefulWidget {
const PinLoginScreen({super.key});
@override
State<PinLoginScreen> createState() => _PinLoginScreenState();
}
class _PinLoginScreenState extends State<PinLoginScreen> {
final TextEditingController controller = TextEditingController();
final FocusNode focusNode = FocusNode();
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
focusNode.requestFocus();
});
controller.addListener(_onTextChanged);
}
void _onTextChanged() {
final text = controller.text;
context.read<PinBloc>().add(PinDigitChanged(text));
if (text.length == 6) {
context.read<PinBloc>().add(PinSubmitted(text));
}
}
@override
void dispose() {
controller.dispose();
focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocListener<PinBloc, PinState>(
listener: (context, state) {
if (state is PinSuccess) {
context.read<SplashBloc>().add(PinVerificationSuccess());
context.go("/home");
}
if (state.error != null) {
controller.clear();
focusNode.requestFocus();
}
},
child: Scaffold(
body: GestureDetector(
onTap: () => focusNode.requestFocus(),
child: Container(
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),
),
BlocBuilder<PinBloc, PinState>(
builder: (context, state) {
final title = state is PinCreateInProgress
? "Создайте PIN-код"
: "Введите PIN-код";
final subtitle = state is PinCreateInProgress
? "Запомните PIN-код"
: "Введите ваш пароль для входа";
if (state is PinLoading) {
return const Center(child: CircularProgressIndicator());
}
return Column(
children: [
const SizedBox(height: 60),
Text(
title,
style: const TextStyle(
color: AppColors.whiteText,
fontSize: 20,
),
),
const SizedBox(height: 35),
Stack(
alignment: Alignment.center,
children: [
CodeDots(
code: state.pin,
length: 6,
),
SizedBox(
width: 200,
height: 50,
child: TextField(
controller: controller,
focusNode: focusNode,
keyboardType: TextInputType.number,
maxLength: 6,
showCursor: false,
decoration: const InputDecoration(
border: InputBorder.none,
counterText: "",
),
style: const TextStyle(color: Colors.transparent),
),
),
],
),
const SizedBox(height: 12),
// Блок ошибки
if (state.error != null)
Text(
state.error!,
style: const TextStyle(
color: AppColors.pinError,
fontSize: 14,
),
),
const SizedBox(height: 40),
Text(
subtitle,
style: const TextStyle(color: AppColors.white70),
),
const SizedBox(height: 20),
if (state is! PinCreateInProgress)
TextButton(
onPressed: () {
context.read<MapBloc>().add(LogoutPressed());
context.read<SplashBloc>().add(AuthCheckRequested());
},
child: const Text(
"Забыли PIN-код?",
style: TextStyle(
color: AppColors.whiteText,
decoration: TextDecoration.underline,
fontSize: 14,
),
),
),
const SizedBox(height: 40),
],
);
},
),
],
),
),
),
),
),
);
}
}