refactor(legacy-customer-service): move contact form state to provider (no setState)

This commit is contained in:
2026-04-22 00:34:53 +02:00
parent a547f7a786
commit 4cd4be24e6
3 changed files with 117 additions and 14 deletions

View File

@@ -1,5 +1,6 @@
import 'package:customer_service/src/domain/email_validator.dart';
import 'package:customer_service/src/presentation/providers/contact_controller.dart';
import 'package:customer_service/src/presentation/providers/contact_form_state_provider.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -24,9 +25,6 @@ class _ContactScreenState extends ConsumerState<ContactScreen> {
late final TextEditingController _emailController;
late final TextEditingController _subjectController;
late final TextEditingController _bodyController;
String _country = '';
String _channel = '';
String? _localError;
@override
void initState() {
@@ -47,16 +45,16 @@ class _ContactScreenState extends ConsumerState<ContactScreen> {
}
void _onSend() {
final formNotifier = ref.read(contactFormProvider.notifier);
final formState = ref.read(contactFormProvider);
final emailError = EmailValidator.validate(_emailController.text);
if (emailError != null) {
setState(() => _localError = emailError);
return;
}
setState(() => _localError = null);
formNotifier.setLocalError(emailError);
if (emailError != null) return;
ref.read(contactControllerProvider.notifier).sendEmail(
country: _country,
channel: _channel,
country: formState.country,
channel: formState.channel,
name: _nameController.text,
email: _emailController.text.trim(),
subject: _subjectController.text,
@@ -73,6 +71,7 @@ class _ContactScreenState extends ConsumerState<ContactScreen> {
final isLoading = ref.watch(
contactControllerProvider.select((s) => s.isLoading),
);
final formState = ref.watch(contactFormProvider);
return LegacyPageLayout(
title: context.translate(I18n.contactTitle),
@@ -84,11 +83,11 @@ class _ContactScreenState extends ConsumerState<ContactScreen> {
child: Column(
children: [
_CountrySection(
onChanged: (value) => setState(() => _country = value),
onChanged: ref.read(contactFormProvider.notifier).setCountry,
),
SizedBox(height: SizeUtils.getByScreen(small: 18, big: 17)),
_ChannelSection(
onChanged: (value) => setState(() => _channel = value),
onChanged: ref.read(contactFormProvider.notifier).setChannel,
),
SizedBox(height: SizeUtils.getByScreen(small: 18, big: 17)),
CustomTextField(
@@ -114,11 +113,11 @@ class _ContactScreenState extends ConsumerState<ContactScreen> {
lines: 8,
onSubmitted: (_) => _onSend(),
),
if (_localError != null)
if (formState.localError != null)
Padding(
padding: const EdgeInsets.only(top: 4),
child: Text(
context.translate(_localError!),
context.translate(formState.localError!),
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context).colorScheme.error,

View File

@@ -0,0 +1,41 @@
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'contact_form_state_provider.g.dart';
class ContactFormState {
const ContactFormState({
this.country = '',
this.channel = '',
this.localError,
});
final String country;
final String channel;
final String? localError;
ContactFormState copyWith({
String? country,
String? channel,
String? localError,
}) {
return ContactFormState(
country: country ?? this.country,
channel: channel ?? this.channel,
localError: localError,
);
}
}
@riverpod
class ContactForm extends _$ContactForm {
@override
ContactFormState build() => const ContactFormState();
void setCountry(String value) =>
state = state.copyWith(country: value, localError: state.localError);
void setChannel(String value) =>
state = state.copyWith(channel: value, localError: state.localError);
void setLocalError(String? error) => state = state.copyWith(localError: error);
}

View File

@@ -0,0 +1,63 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'contact_form_state_provider.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint, type=warning
@ProviderFor(ContactForm)
const contactFormProvider = ContactFormProvider._();
final class ContactFormProvider
extends $NotifierProvider<ContactForm, ContactFormState> {
const ContactFormProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'contactFormProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$contactFormHash();
@$internal
@override
ContactForm create() => ContactForm();
/// {@macro riverpod.override_with_value}
Override overrideWithValue(ContactFormState value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<ContactFormState>(value),
);
}
}
String _$contactFormHash() => r'995f52ca7d57da81833f6290f6c2bf2eaa043e47';
abstract class _$ContactForm extends $Notifier<ContactFormState> {
ContactFormState build();
@$mustCallSuper
@override
void runBuild() {
final created = build();
final ref = this.ref as $Ref<ContactFormState, ContactFormState>;
final element =
ref.element
as $ClassProviderElement<
AnyNotifier<ContactFormState, ContactFormState>,
ContactFormState,
Object?,
Object?
>;
element.handleValue(ref, created);
}
}