Skip to content

Commit 9536167

Browse files
committed
feat(authentication): replace TextFormField with Pinput for email code verification
- Add pinput package for improved pin input experience - Implement Pinput with custom PinTheme - Update form validation and submission logic - Adjust UI to match new input style
1 parent 9c41e59 commit 9536167

File tree

1 file changed

+38
-26
lines changed

1 file changed

+38
-26
lines changed

lib/authentication/view/email_code_verification_page.dart

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:flutter_news_app_web_dashboard_full_source_code/app/bloc/app_blo
55
import 'package:flutter_news_app_web_dashboard_full_source_code/app/config/config.dart';
66
import 'package:flutter_news_app_web_dashboard_full_source_code/authentication/bloc/authentication_bloc.dart';
77
import 'package:flutter_news_app_web_dashboard_full_source_code/l10n/l10n.dart';
8+
import 'package:pinput/pinput.dart';
89
import 'package:ui_kit/ui_kit.dart';
910

1011
/// {@template email_code_verification_page}
@@ -131,10 +132,12 @@ class _EmailCodeVerificationFormState
131132
extends State<_EmailCodeVerificationForm> {
132133
final _formKey = GlobalKey<FormState>();
133134
final _codeController = TextEditingController();
135+
final _focusNode = FocusNode();
134136

135137
@override
136138
void dispose() {
137139
_codeController.dispose();
140+
_focusNode.dispose();
138141
super.dispose();
139142
}
140143

@@ -153,39 +156,48 @@ class _EmailCodeVerificationFormState
153156
Widget build(BuildContext context) {
154157
final l10n = AppLocalizationsX(context).l10n;
155158
final textTheme = Theme.of(context).textTheme;
159+
final colorScheme = Theme.of(context).colorScheme;
160+
161+
final defaultPinTheme = PinTheme(
162+
width: 56,
163+
height: 60,
164+
textStyle: textTheme.headlineSmall,
165+
decoration: BoxDecoration(
166+
color: colorScheme.surface,
167+
borderRadius: BorderRadius.circular(8),
168+
border: Border.all(color: colorScheme.onSurface.withOpacity(0.12)),
169+
),
170+
);
156171

157172
return Form(
158173
key: _formKey,
159174
child: Column(
160175
mainAxisSize: MainAxisSize.min,
161176
children: [
162-
Padding(
163-
// No horizontal padding needed if column is stretched
164-
// padding: const EdgeInsets.symmetric(horizontal: AppSpacing.md),
165-
padding: EdgeInsets.zero,
166-
child: TextFormField(
167-
controller: _codeController,
168-
decoration: InputDecoration(
169-
labelText: l10n.emailCodeVerificationHint,
170-
// border: const OutlineInputBorder(),
171-
counterText: '',
177+
Pinput(
178+
length: 6,
179+
controller: _codeController,
180+
focusNode: _focusNode,
181+
defaultPinTheme: defaultPinTheme,
182+
onCompleted: (pin) => _submitForm(),
183+
validator: (value) {
184+
if (value == null || value.isEmpty) {
185+
return l10n.emailCodeValidationEmptyError;
186+
}
187+
if (value.length != 6) {
188+
return l10n.emailCodeValidationLengthError;
189+
}
190+
return null;
191+
},
192+
focusedPinTheme: defaultPinTheme.copyWith(
193+
decoration: defaultPinTheme.decoration!.copyWith(
194+
border: Border.all(color: colorScheme.primary),
195+
),
196+
),
197+
errorPinTheme: defaultPinTheme.copyWith(
198+
decoration: defaultPinTheme.decoration!.copyWith(
199+
border: Border.all(color: colorScheme.error),
172200
),
173-
keyboardType: TextInputType.number,
174-
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
175-
maxLength: 6,
176-
textAlign: TextAlign.center,
177-
style: textTheme.headlineSmall,
178-
enabled: !widget.isLoading,
179-
validator: (value) {
180-
if (value == null || value.isEmpty) {
181-
return l10n.emailCodeValidationEmptyError;
182-
}
183-
if (value.length != 6) {
184-
return l10n.emailCodeValidationLengthError;
185-
}
186-
return null;
187-
},
188-
onFieldSubmitted: widget.isLoading ? null : (_) => _submitForm(),
189201
),
190202
),
191203
const SizedBox(height: AppSpacing.xxl),

0 commit comments

Comments
 (0)