feat(apps): integrate auth cubits with register and login screens

This commit is contained in:
qzl
2026-02-25 15:21:26 +08:00
parent 0a7e1cd2d4
commit 8c1dfa9987
4 changed files with 301 additions and 126 deletions
@@ -1,29 +1,74 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:formz/formz.dart';
import '../../../../core/theme/design_tokens.dart';
import '../../../../shared/widgets/app_button.dart';
import '../../../../shared/widgets/warning_banner.dart';
import '../../presentation/cubits/register_cubit.dart';
import '../../presentation/bloc/auth_bloc.dart';
import '../../presentation/bloc/auth_event.dart';
class RegisterStep2Screen extends StatefulWidget {
const RegisterStep2Screen({super.key});
class RegisterStep2Screen extends StatelessWidget {
final RegisterCubit? cubit;
const RegisterStep2Screen({super.key, this.cubit});
@override
State<RegisterStep2Screen> createState() => _RegisterStep2ScreenState();
Widget build(BuildContext context) {
final registerCubit =
cubit ?? (GoRouterState.of(context).extra as RegisterCubit?);
if (registerCubit == null) {
return Scaffold(
body: Center(child: Text('Error: RegisterCubit not found')),
);
}
return BlocProvider.value(
value: registerCubit,
child: const RegisterStep2View(),
);
}
}
class _RegisterStep2ScreenState extends State<RegisterStep2Screen> {
final _passwordController = TextEditingController();
class RegisterStep2View extends StatefulWidget {
const RegisterStep2View({super.key});
@override
State<RegisterStep2View> createState() => _RegisterStep2ViewState();
}
class _RegisterStep2ViewState extends State<RegisterStep2View> {
final _codeController = TextEditingController();
final _inviteController = TextEditingController();
bool _obscureText = true;
@override
void dispose() {
_passwordController.dispose();
_codeController.dispose();
_inviteController.dispose();
super.dispose();
}
Future<void> _handleComplete() async {
final cubit = context.read<RegisterCubit>();
cubit.verificationCodeChanged(_codeController.text);
if (!cubit.state.isStep2Valid) {
return;
}
final response = await cubit.submitStep2();
if (response != null && mounted) {
context.read<AuthBloc>().add(AuthLoggedIn(user: response.user));
context.go('/home');
}
}
Future<void> _handleResendCode() async {
await context.read<RegisterCubit>().resendCode();
}
@override
Widget build(BuildContext context) {
return Scaffold(
@@ -96,62 +141,41 @@ class _RegisterStep2ScreenState extends State<RegisterStep2Screen> {
}
Widget _buildFormContainer() {
return SizedBox(
width: 327,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_buildPasswordInput(),
const SizedBox(height: 12),
_buildCodeInput(),
const SizedBox(height: 12),
_buildInviteInput(),
const SizedBox(height: 12),
_buildStepIndicator(),
const SizedBox(height: 12),
AppButton(text: '完成注册', onPressed: () {}),
],
),
);
}
Widget _buildPasswordInput() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'密码',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w500,
color: Color(0xFF475569),
),
),
const SizedBox(height: 6),
TextField(
controller: _passwordController,
obscureText: _obscureText,
decoration: InputDecoration(
hintText: '请输入至少 8 位密码',
suffixIcon: IconButton(
icon: Icon(
_obscureText ? Icons.visibility_off : Icons.visibility,
size: 20,
color: AppColors.slate400,
return BlocBuilder<RegisterCubit, RegisterState>(
builder: (context, state) {
return SizedBox(
width: 327,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_buildCodeInput(state),
const SizedBox(height: 12),
_buildInviteInput(),
const SizedBox(height: 12),
_buildStepIndicator(),
if (state.errorMessage != null)
Padding(
padding: const EdgeInsets.only(top: 8),
child: WarningBanner(
message: state.errorMessage!,
visible: true,
),
),
const SizedBox(height: 12),
AppButton(
text: '完成注册',
onPressed: state.status == FormzSubmissionStatus.inProgress
? null
: _handleComplete,
),
onPressed: () {
setState(() {
_obscureText = !_obscureText;
});
},
),
],
),
),
],
);
},
);
}
Widget _buildCodeInput() {
Widget _buildCodeInput(RegisterState state) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -187,7 +211,9 @@ class _RegisterStep2ScreenState extends State<RegisterStep2Screen> {
width: 112,
height: 40,
child: OutlinedButton(
onPressed: () {},
onPressed: state.status == FormzSubmissionStatus.inProgress
? null
: _handleResendCode,
style: OutlinedButton.styleFrom(
backgroundColor: AppColors.background,
side: const BorderSide(color: AppColors.input),