From 5925a97b011a627379af411065f72cf1719ddf60 Mon Sep 17 00:00:00 2001 From: JulianAlcala Date: Wed, 22 Apr 2026 00:16:48 +0200 Subject: [PATCH] refactor(legacy-account): move personal_data form state to provider (no setState) --- .../presentation/personal_data_screen.dart | 33 ++++-- .../personal_data_form_state_provider.dart | 38 ++++++ .../personal_data_form_state_provider.g.dart | 111 ++++++++++++++++++ 3 files changed, 171 insertions(+), 11 deletions(-) create mode 100644 modules/legacy/modules/account/lib/src/features/personal_data/presentation/providers/personal_data_form_state_provider.dart create mode 100644 modules/legacy/modules/account/lib/src/features/personal_data/presentation/providers/personal_data_form_state_provider.g.dart diff --git a/modules/legacy/modules/account/lib/src/features/personal_data/presentation/personal_data_screen.dart b/modules/legacy/modules/account/lib/src/features/personal_data/presentation/personal_data_screen.dart index d9fbc3a2..0d120caf 100644 --- a/modules/legacy/modules/account/lib/src/features/personal_data/presentation/personal_data_screen.dart +++ b/modules/legacy/modules/account/lib/src/features/personal_data/presentation/personal_data_screen.dart @@ -1,4 +1,5 @@ import 'package:account/src/features/personal_data/presentation/providers/personal_data_controller.dart'; +import 'package:account/src/features/personal_data/presentation/providers/personal_data_form_state_provider.dart'; import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -42,8 +43,6 @@ class _PersonalDataFormState extends ConsumerState<_PersonalDataForm> { late final TextEditingController _firstNameController; late final TextEditingController _lastNameController; late final TextEditingController _phoneController; - late String _isoCode; - String? _localError; @override void initState() { @@ -54,7 +53,6 @@ class _PersonalDataFormState extends ConsumerState<_PersonalDataForm> { _phoneController = TextEditingController( text: parsed?.nationalNumber ?? widget.user.phone, ); - _isoCode = parsed?.isoCode ?? SfPhoneNumber.defaultIsoCode; } @override @@ -77,20 +75,24 @@ class _PersonalDataFormState extends ConsumerState<_PersonalDataForm> { void _onSubmit() { if (!_hasChanges) return; + final formProvider = personalDataFormProvider(widget.user.phone); + final formNotifier = ref.read(formProvider.notifier); + final isoCode = ref.read(formProvider).isoCode; + final phoneText = _phoneController.text.trim(); String? fullPhone; if (phoneText.isNotEmpty) { final parsed = SfPhoneNumber.tryParse( _phoneController.text, - defaultIsoCode: _isoCode, + defaultIsoCode: isoCode, ); if (parsed == null) { - setState(() => _localError = I18n.errorMessagePhoneIsInvalid); + formNotifier.setLocalError(I18n.errorMessagePhoneIsInvalid); return; } fullPhone = parsed.e164; } - setState(() => _localError = null); + formNotifier.setLocalError(null); final first = _firstNameController.text.trim().isNotEmpty ? _firstNameController.text.trim() @@ -122,6 +124,9 @@ class _PersonalDataFormState extends ConsumerState<_PersonalDataForm> { final isLoading = ref.watch( personalDataControllerProvider.select((s) => s.isLoading), ); + final formState = ref.watch( + personalDataFormProvider(widget.user.phone), + ); return LegacyPageLayout( title: context.translate(I18n.personalData), @@ -155,11 +160,17 @@ class _PersonalDataFormState extends ConsumerState<_PersonalDataForm> { children: [ CountryPrefixPicker( headerText: context.translate(I18n.selectYourCountry), - initialSelection: _isoCode, + initialSelection: formState.isoCode, onChanged: (country) { final code = country.code; - if (code != null && code != _isoCode) { - setState(() => _isoCode = code); + if (code != null) { + ref + .read( + personalDataFormProvider( + widget.user.phone, + ).notifier, + ) + .setIsoCode(code); } }, width: 80, @@ -175,11 +186,11 @@ class _PersonalDataFormState extends ConsumerState<_PersonalDataForm> { ), ], ), - if (_localError != null) + if (formState.localError != null) Padding( padding: const EdgeInsets.only(top: 8), child: Text( - context.translate(_localError!), + context.translate(formState.localError!), textAlign: TextAlign.center, style: TextStyle( color: Theme.of(context).colorScheme.error, diff --git a/modules/legacy/modules/account/lib/src/features/personal_data/presentation/providers/personal_data_form_state_provider.dart b/modules/legacy/modules/account/lib/src/features/personal_data/presentation/providers/personal_data_form_state_provider.dart new file mode 100644 index 00000000..385cddd4 --- /dev/null +++ b/modules/legacy/modules/account/lib/src/features/personal_data/presentation/providers/personal_data_form_state_provider.dart @@ -0,0 +1,38 @@ +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:sf_shared/sf_shared.dart'; + +part 'personal_data_form_state_provider.g.dart'; + +class PersonalDataFormState { + const PersonalDataFormState({required this.isoCode, this.localError}); + + final String isoCode; + final String? localError; + + PersonalDataFormState copyWith({String? isoCode, String? localError}) { + return PersonalDataFormState( + isoCode: isoCode ?? this.isoCode, + localError: localError, + ); + } +} + +@riverpod +class PersonalDataFormNotifier extends _$PersonalDataFormNotifier { + @override + PersonalDataFormState build(String initialPhone) { + final parsed = SfPhoneNumber.tryParse(initialPhone); + return PersonalDataFormState( + isoCode: parsed?.isoCode ?? SfPhoneNumber.defaultIsoCode, + ); + } + + void setIsoCode(String code) { + if (code == state.isoCode) return; + state = state.copyWith(isoCode: code); + } + + void setLocalError(String? error) { + state = state.copyWith(localError: error); + } +} diff --git a/modules/legacy/modules/account/lib/src/features/personal_data/presentation/providers/personal_data_form_state_provider.g.dart b/modules/legacy/modules/account/lib/src/features/personal_data/presentation/providers/personal_data_form_state_provider.g.dart new file mode 100644 index 00000000..2064b97f --- /dev/null +++ b/modules/legacy/modules/account/lib/src/features/personal_data/presentation/providers/personal_data_form_state_provider.g.dart @@ -0,0 +1,111 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'personal_data_form_state_provider.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(PersonalDataFormNotifier) +const personalDataFormProvider = PersonalDataFormNotifierFamily._(); + +final class PersonalDataFormNotifierProvider + extends $NotifierProvider { + const PersonalDataFormNotifierProvider._({ + required PersonalDataFormNotifierFamily super.from, + required String super.argument, + }) : super( + retry: null, + name: r'personalDataFormProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$personalDataFormNotifierHash(); + + @override + String toString() { + return r'personalDataFormProvider' + '' + '($argument)'; + } + + @$internal + @override + PersonalDataFormNotifier create() => PersonalDataFormNotifier(); + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(PersonalDataFormState value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider(value), + ); + } + + @override + bool operator ==(Object other) { + return other is PersonalDataFormNotifierProvider && + other.argument == argument; + } + + @override + int get hashCode { + return argument.hashCode; + } +} + +String _$personalDataFormNotifierHash() => + r'566d8314bb56d0eff43c6998195bd72820ef11e8'; + +final class PersonalDataFormNotifierFamily extends $Family + with + $ClassFamilyOverride< + PersonalDataFormNotifier, + PersonalDataFormState, + PersonalDataFormState, + PersonalDataFormState, + String + > { + const PersonalDataFormNotifierFamily._() + : super( + retry: null, + name: r'personalDataFormProvider', + dependencies: null, + $allTransitiveDependencies: null, + isAutoDispose: true, + ); + + PersonalDataFormNotifierProvider call(String initialPhone) => + PersonalDataFormNotifierProvider._(argument: initialPhone, from: this); + + @override + String toString() => r'personalDataFormProvider'; +} + +abstract class _$PersonalDataFormNotifier + extends $Notifier { + late final _$args = ref.$arg as String; + String get initialPhone => _$args; + + PersonalDataFormState build(String initialPhone); + @$mustCallSuper + @override + void runBuild() { + final created = build(_$args); + final ref = this.ref as $Ref; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier, + PersonalDataFormState, + Object?, + Object? + >; + element.handleValue(ref, created); + } +}