Compare commits
3 Commits
89f94cf1ff
...
b21aa04557
Author | SHA1 | Date | |
---|---|---|---|
b21aa04557 | |||
01df7a0dff | |||
8909274543 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -196,3 +196,4 @@ $RECYCLE.BIN/
|
|||||||
|
|
||||||
.idea/
|
.idea/
|
||||||
*.iml
|
*.iml
|
||||||
|
google-services.json
|
||||||
|
@ -31,23 +31,29 @@ class App extends StatelessWidget {
|
|||||||
|
|
||||||
static FormData getNormalFormData() {
|
static FormData getNormalFormData() {
|
||||||
return const FormData([
|
return const FormData([
|
||||||
FormEntry(formFieldName, Name.pure()),
|
FormInput(formFieldName, Name.pure()),
|
||||||
FormEntry(formFieldPhone, Phone.pure()),
|
FormInput(formFieldPhone, Phone.pure()),
|
||||||
FormEntry(formFieldPro, Boolean.pure()),
|
FormInput(formFieldPro, Boolean.pure()),
|
||||||
FormEntry(formFieldConfirmedPassword, ConfirmedPassword.pure(),
|
FormInput(
|
||||||
export: false),
|
formFieldConfirmedPassword,
|
||||||
|
ConfirmedPassword.pure(),
|
||||||
|
metadata: FormInputMetadata(export: false),
|
||||||
|
),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FormData getProFormData() {
|
static FormData getProFormData() {
|
||||||
return const FormData([
|
return const FormData([
|
||||||
FormEntry(formFieldName, Name.pure()),
|
FormInput(formFieldName, Name.pure()),
|
||||||
FormEntry(formFieldPhone, Phone.pure()),
|
FormInput(formFieldPhone, Phone.pure()),
|
||||||
FormEntry(formFieldPro, Boolean.pure()),
|
FormInput(formFieldPro, Boolean.pure()),
|
||||||
FormEntry(formFieldSiren, Siren.pure()),
|
FormInput(formFieldSiren, Siren.pure()),
|
||||||
FormEntry(formFieldIban, Iban.pure()),
|
FormInput(formFieldIban, Iban.pure()),
|
||||||
FormEntry(formFieldConfirmedPassword, ConfirmedPassword.pure(),
|
FormInput(
|
||||||
export: false),
|
formFieldConfirmedPassword,
|
||||||
|
ConfirmedPassword.pure(),
|
||||||
|
metadata: FormInputMetadata(export: false),
|
||||||
|
),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,42 +109,42 @@ class App extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
AuthenticationRepositoryInterface _authenticationRepository =
|
AuthenticationRepositoryInterface authenticationRepository =
|
||||||
AuthenticationRepositoryFirebase();
|
AuthenticationRepositoryFirebase();
|
||||||
|
|
||||||
AuthenticationCubit _authenticationCubit = AuthenticationCubit(
|
AuthenticationCubit authenticationCubit = AuthenticationCubit(
|
||||||
authenticationRepository: _authenticationRepository,
|
authenticationRepository: authenticationRepository,
|
||||||
onAuthSuccess: onAuthSuccess,
|
onAuthSuccess: onAuthSuccess,
|
||||||
);
|
);
|
||||||
|
|
||||||
SignUpCubit _signUpCubit = SignUpCubit(
|
SignUpCubit signUpCubit = SignUpCubit(
|
||||||
authenticationRepository: _authenticationRepository,
|
authenticationRepository: authenticationRepository,
|
||||||
authenticationCubit: _authenticationCubit,
|
authenticationCubit: authenticationCubit,
|
||||||
entries: getNormalFormData(),
|
entries: getNormalFormData(),
|
||||||
onSignUpSuccess: onSignUpSuccess,
|
onSignUpSuccess: onSignUpSuccess,
|
||||||
);
|
);
|
||||||
|
|
||||||
SignInCubit _signInCubit = SignInCubit(
|
SignInCubit signInCubit = SignInCubit(
|
||||||
authenticationRepository: _authenticationRepository,
|
authenticationRepository: authenticationRepository,
|
||||||
authenticationCubit: _authenticationCubit,
|
authenticationCubit: authenticationCubit,
|
||||||
);
|
);
|
||||||
|
|
||||||
return MultiRepositoryProvider(
|
return MultiRepositoryProvider(
|
||||||
providers: [
|
providers: [
|
||||||
RepositoryProvider<AuthenticationRepositoryInterface>(
|
RepositoryProvider<AuthenticationRepositoryInterface>(
|
||||||
create: (context) => _authenticationRepository,
|
create: (context) => authenticationRepository,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: MultiBlocProvider(
|
child: MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider<AuthenticationCubit>(
|
BlocProvider<AuthenticationCubit>(
|
||||||
create: (context) => _authenticationCubit..init(),
|
create: (context) => authenticationCubit..init(),
|
||||||
),
|
),
|
||||||
BlocProvider<SignUpCubit>(
|
BlocProvider<SignUpCubit>(
|
||||||
create: (context) => _signUpCubit,
|
create: (context) => signUpCubit,
|
||||||
),
|
),
|
||||||
BlocProvider<SignInCubit>(
|
BlocProvider<SignInCubit>(
|
||||||
create: (context) => _signInCubit,
|
create: (context) => signInCubit,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: const AppView(),
|
child: const AppView(),
|
||||||
|
@ -37,7 +37,7 @@ class _NameInput extends StatelessWidget {
|
|||||||
labelText: 'name',
|
labelText: 'name',
|
||||||
helperText: '',
|
helperText: '',
|
||||||
errorText:
|
errorText:
|
||||||
state.data.input(formFieldName).invalid ? 'invalid name' : null,
|
state.data.isNotValid(formFieldName) ? 'invalid name' : null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -58,7 +58,7 @@ class _PhoneInput extends StatelessWidget {
|
|||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'phone',
|
labelText: 'phone',
|
||||||
helperText: '',
|
helperText: '',
|
||||||
errorText: state.data.input(formFieldPhone).invalid
|
errorText: state.data.isNotValid(formFieldPhone)
|
||||||
? 'invalid phone'
|
? 'invalid phone'
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
@ -81,7 +81,7 @@ class _SirenInput extends StatelessWidget {
|
|||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'siren',
|
labelText: 'siren',
|
||||||
helperText: '',
|
helperText: '',
|
||||||
errorText: state.data.input(formFieldSiren).invalid
|
errorText: state.data.isNotValid(formFieldSiren)
|
||||||
? 'invalid SIREN'
|
? 'invalid SIREN'
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
@ -105,7 +105,7 @@ class _IbanInput extends StatelessWidget {
|
|||||||
labelText: 'iban',
|
labelText: 'iban',
|
||||||
helperText: '',
|
helperText: '',
|
||||||
errorText:
|
errorText:
|
||||||
state.data.input(formFieldIban).invalid ? 'invalid IBAN' : null,
|
state.data.isNotValid(formFieldIban) ? 'invalid IBAN' : null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -149,8 +149,7 @@ class _PasswordInput extends StatelessWidget {
|
|||||||
.read<SignUpCubit>()
|
.read<SignUpCubit>()
|
||||||
.state
|
.state
|
||||||
.data
|
.data
|
||||||
.input(formFieldConfirmedPassword)
|
.valueOf<String, ValidationError>(formFieldConfirmedPassword),
|
||||||
.value,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -185,7 +184,7 @@ class _ConfirmPasswordInput extends StatelessWidget {
|
|||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'confirm password',
|
labelText: 'confirm password',
|
||||||
helperText: '',
|
helperText: '',
|
||||||
errorText: state.data.input(formFieldConfirmedPassword).invalid
|
errorText: state.data.isNotValid(formFieldConfirmedPassword)
|
||||||
? 'passwords do not match'
|
? 'passwords do not match'
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
@ -203,7 +202,7 @@ class _CheckIsProInput extends StatelessWidget {
|
|||||||
trailing: BlocBuilder<SignUpCubit, SignUpState>(
|
trailing: BlocBuilder<SignUpCubit, SignUpState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return Checkbox(
|
return Checkbox(
|
||||||
value: state.data.input<bool>(formFieldPro).value,
|
value: state.data.valueOf<bool, ValidationError>(formFieldPro),
|
||||||
onChanged: (isPro) {
|
onChanged: (isPro) {
|
||||||
final value =
|
final value =
|
||||||
isPro!; // tristate is false, so value can't be null
|
isPro!; // tristate is false, so value can't be null
|
||||||
@ -297,7 +296,7 @@ class SignUpForm extends StatelessWidget {
|
|||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
BlocBuilder<SignUpCubit, SignUpState>(
|
BlocBuilder<SignUpCubit, SignUpState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
if (state.data.input<bool>(formFieldPro).value) {
|
if (state.data.valueOf<bool, ValidationError>(formFieldPro)) {
|
||||||
return Column(children: [
|
return Column(children: [
|
||||||
_SirenInput(),
|
_SirenInput(),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
|
@ -33,7 +33,7 @@ class PasswordResetCubit extends Cubit<PasswordResetState> {
|
|||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
email: email,
|
email: email,
|
||||||
status: FormData.validate([email]),
|
status: FormStatus.validate([email]),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ class SignInCubit extends Cubit<SignInState> {
|
|||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
email: email,
|
email: email,
|
||||||
status: FormData.validate([email, state.password]),
|
status: FormStatus.validate([email, state.password]),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -49,7 +49,7 @@ class SignInCubit extends Cubit<SignInState> {
|
|||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
password: password,
|
password: password,
|
||||||
status: FormData.validate([state.email, password]),
|
status: FormStatus.validate([state.email, password]),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -44,16 +44,16 @@ class SignUpCubit extends Cubit<SignUpState> {
|
|||||||
void emailChanged(String value) {
|
void emailChanged(String value) {
|
||||||
final Email email = Email.dirty(value);
|
final Email email = Email.dirty(value);
|
||||||
|
|
||||||
final List<FormInput<dynamic, ValidationError>> inputsToValidate = [
|
final List<FormInputValidator<dynamic, ValidationError>> toValidate = [
|
||||||
email,
|
email,
|
||||||
state.password,
|
state.password,
|
||||||
...state.data.inputs<dynamic>(),
|
...state.data.validators<dynamic, ValidationError>(),
|
||||||
];
|
];
|
||||||
|
|
||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
email: email,
|
email: email,
|
||||||
status: FormData.validate(inputsToValidate),
|
status: FormStatus.validate(toValidate),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -61,26 +61,26 @@ class SignUpCubit extends Cubit<SignUpState> {
|
|||||||
void passwordChanged(String value) {
|
void passwordChanged(String value) {
|
||||||
final Password password = Password.dirty(value);
|
final Password password = Password.dirty(value);
|
||||||
|
|
||||||
final List<FormInput<dynamic, ValidationError>> inputsToValidate = [
|
final List<FormInputValidator<dynamic, ValidationError>> toValidate = [
|
||||||
state.email,
|
state.email,
|
||||||
password,
|
password,
|
||||||
...state.data.inputs<dynamic>(),
|
...state.data.validators<dynamic, ValidationError>(),
|
||||||
];
|
];
|
||||||
|
|
||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
password: password,
|
password: password,
|
||||||
status: FormData.validate(inputsToValidate),
|
status: FormStatus.validate(toValidate),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take from wyatt_form_bloc/wyatt_form_bloc.dart
|
// Take from wyatt_form_bloc/wyatt_form_bloc.dart
|
||||||
void dataChanged<T>(String field, FormInput dirtyValue) {
|
void dataChanged<T>(String field, FormInputValidator dirtyValue) {
|
||||||
final _form = state.data.clone();
|
final _form = state.data.clone();
|
||||||
|
|
||||||
if (_form.contains(field)) {
|
if (_form.contains(field)) {
|
||||||
_form.update(field, dirtyValue);
|
_form.updateValidator(field, dirtyValue);
|
||||||
} else {
|
} else {
|
||||||
throw Exception('Form field $field not found');
|
throw Exception('Form field $field not found');
|
||||||
}
|
}
|
||||||
@ -88,8 +88,12 @@ class SignUpCubit extends Cubit<SignUpState> {
|
|||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
data: _form,
|
data: _form,
|
||||||
status: FormData.validate(
|
status: FormStatus.validate(
|
||||||
[state.email, state.password, ..._form.inputs<dynamic>()],
|
[
|
||||||
|
state.email,
|
||||||
|
state.password,
|
||||||
|
...state.data.validators<dynamic, ValidationError>(),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -120,8 +124,12 @@ class SignUpCubit extends Cubit<SignUpState> {
|
|||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
data: _form,
|
data: _form,
|
||||||
status: FormData.validate(
|
status: FormStatus.validate(
|
||||||
[state.email, state.password, ..._form.inputs<dynamic>()],
|
[
|
||||||
|
state.email,
|
||||||
|
state.password,
|
||||||
|
...state.data.validators<dynamic, ValidationError>(),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -68,9 +68,9 @@ void main() {
|
|||||||
SignUpCubit(
|
SignUpCubit(
|
||||||
authenticationRepository: authenticationRepository,
|
authenticationRepository: authenticationRepository,
|
||||||
authenticationCubit: authenticationCubit,
|
authenticationCubit: authenticationCubit,
|
||||||
entries: FormData.empty(),
|
entries: const FormData.empty(),
|
||||||
).state,
|
).state,
|
||||||
SignUpState(data: FormData.empty()),
|
const SignUpState(data: FormData.empty()),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -80,11 +80,11 @@ void main() {
|
|||||||
build: () => SignUpCubit(
|
build: () => SignUpCubit(
|
||||||
authenticationRepository: authenticationRepository,
|
authenticationRepository: authenticationRepository,
|
||||||
authenticationCubit: authenticationCubit,
|
authenticationCubit: authenticationCubit,
|
||||||
entries: FormData.empty(),
|
entries: const FormData.empty(),
|
||||||
),
|
),
|
||||||
act: (SignUpCubit cubit) => cubit.emailChanged(invalidEmailString),
|
act: (SignUpCubit cubit) => cubit.emailChanged(invalidEmailString),
|
||||||
expect: () => <SignUpState>[
|
expect: () => <SignUpState>[
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
email: invalidEmail,
|
email: invalidEmail,
|
||||||
status: FormStatus.invalid,
|
status: FormStatus.invalid,
|
||||||
data: FormData.empty(),
|
data: FormData.empty(),
|
||||||
@ -97,15 +97,15 @@ void main() {
|
|||||||
build: () => SignUpCubit(
|
build: () => SignUpCubit(
|
||||||
authenticationRepository: authenticationRepository,
|
authenticationRepository: authenticationRepository,
|
||||||
authenticationCubit: authenticationCubit,
|
authenticationCubit: authenticationCubit,
|
||||||
entries: FormData.empty(),
|
entries: const FormData.empty(),
|
||||||
),
|
),
|
||||||
seed: () => SignUpState(
|
seed: () => const SignUpState(
|
||||||
password: validPassword,
|
password: validPassword,
|
||||||
data: FormData.empty(),
|
data: FormData.empty(),
|
||||||
),
|
),
|
||||||
act: (SignUpCubit cubit) => cubit.emailChanged(validEmailString),
|
act: (SignUpCubit cubit) => cubit.emailChanged(validEmailString),
|
||||||
expect: () => <SignUpState>[
|
expect: () => <SignUpState>[
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
email: validEmail,
|
email: validEmail,
|
||||||
password: validPassword,
|
password: validPassword,
|
||||||
status: FormStatus.valid,
|
status: FormStatus.valid,
|
||||||
@ -121,12 +121,12 @@ void main() {
|
|||||||
build: () => SignUpCubit(
|
build: () => SignUpCubit(
|
||||||
authenticationRepository: authenticationRepository,
|
authenticationRepository: authenticationRepository,
|
||||||
authenticationCubit: authenticationCubit,
|
authenticationCubit: authenticationCubit,
|
||||||
entries: FormData.empty(),
|
entries: const FormData.empty(),
|
||||||
),
|
),
|
||||||
act: (SignUpCubit cubit) =>
|
act: (SignUpCubit cubit) =>
|
||||||
cubit.passwordChanged(invalidPasswordString),
|
cubit.passwordChanged(invalidPasswordString),
|
||||||
expect: () => <SignUpState>[
|
expect: () => <SignUpState>[
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
password: invalidPassword,
|
password: invalidPassword,
|
||||||
status: FormStatus.invalid,
|
status: FormStatus.invalid,
|
||||||
data: FormData.empty(),
|
data: FormData.empty(),
|
||||||
@ -139,15 +139,15 @@ void main() {
|
|||||||
build: () => SignUpCubit(
|
build: () => SignUpCubit(
|
||||||
authenticationRepository: authenticationRepository,
|
authenticationRepository: authenticationRepository,
|
||||||
authenticationCubit: authenticationCubit,
|
authenticationCubit: authenticationCubit,
|
||||||
entries: FormData.empty(),
|
entries: const FormData.empty(),
|
||||||
),
|
),
|
||||||
seed: () => SignUpState(
|
seed: () => const SignUpState(
|
||||||
email: validEmail,
|
email: validEmail,
|
||||||
data: FormData.empty(),
|
data: FormData.empty(),
|
||||||
),
|
),
|
||||||
act: (SignUpCubit cubit) => cubit.passwordChanged(validPasswordString),
|
act: (SignUpCubit cubit) => cubit.passwordChanged(validPasswordString),
|
||||||
expect: () => <SignUpState>[
|
expect: () => <SignUpState>[
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
email: validEmail,
|
email: validEmail,
|
||||||
password: validPassword,
|
password: validPassword,
|
||||||
status: FormStatus.valid,
|
status: FormStatus.valid,
|
||||||
@ -163,7 +163,7 @@ void main() {
|
|||||||
build: () => SignUpCubit(
|
build: () => SignUpCubit(
|
||||||
authenticationRepository: authenticationRepository,
|
authenticationRepository: authenticationRepository,
|
||||||
authenticationCubit: authenticationCubit,
|
authenticationCubit: authenticationCubit,
|
||||||
entries: FormData.empty(),
|
entries: const FormData.empty(),
|
||||||
),
|
),
|
||||||
act: (SignUpCubit cubit) => cubit.signUpFormSubmitted(),
|
act: (SignUpCubit cubit) => cubit.signUpFormSubmitted(),
|
||||||
expect: () => const <SignUpState>[],
|
expect: () => const <SignUpState>[],
|
||||||
@ -174,9 +174,9 @@ void main() {
|
|||||||
build: () => SignUpCubit(
|
build: () => SignUpCubit(
|
||||||
authenticationRepository: authenticationRepository,
|
authenticationRepository: authenticationRepository,
|
||||||
authenticationCubit: authenticationCubit,
|
authenticationCubit: authenticationCubit,
|
||||||
entries: FormData.empty(),
|
entries: const FormData.empty(),
|
||||||
),
|
),
|
||||||
seed: () => SignUpState(
|
seed: () => const SignUpState(
|
||||||
status: FormStatus.valid,
|
status: FormStatus.valid,
|
||||||
email: validEmail,
|
email: validEmail,
|
||||||
password: validPassword,
|
password: validPassword,
|
||||||
@ -199,9 +199,9 @@ void main() {
|
|||||||
build: () => SignUpCubit(
|
build: () => SignUpCubit(
|
||||||
authenticationRepository: authenticationRepository,
|
authenticationRepository: authenticationRepository,
|
||||||
authenticationCubit: authenticationCubit,
|
authenticationCubit: authenticationCubit,
|
||||||
entries: FormData.empty(),
|
entries: const FormData.empty(),
|
||||||
),
|
),
|
||||||
seed: () => SignUpState(
|
seed: () => const SignUpState(
|
||||||
status: FormStatus.valid,
|
status: FormStatus.valid,
|
||||||
email: validEmail,
|
email: validEmail,
|
||||||
password: validPassword,
|
password: validPassword,
|
||||||
@ -209,13 +209,13 @@ void main() {
|
|||||||
),
|
),
|
||||||
act: (SignUpCubit cubit) => cubit.signUpFormSubmitted(),
|
act: (SignUpCubit cubit) => cubit.signUpFormSubmitted(),
|
||||||
expect: () => <SignUpState>[
|
expect: () => <SignUpState>[
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
status: FormStatus.submissionInProgress,
|
status: FormStatus.submissionInProgress,
|
||||||
email: validEmail,
|
email: validEmail,
|
||||||
password: validPassword,
|
password: validPassword,
|
||||||
data: FormData.empty(),
|
data: FormData.empty(),
|
||||||
),
|
),
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
status: FormStatus.submissionSuccess,
|
status: FormStatus.submissionSuccess,
|
||||||
email: validEmail,
|
email: validEmail,
|
||||||
password: validPassword,
|
password: validPassword,
|
||||||
@ -238,9 +238,9 @@ void main() {
|
|||||||
build: () => SignUpCubit(
|
build: () => SignUpCubit(
|
||||||
authenticationRepository: authenticationRepository,
|
authenticationRepository: authenticationRepository,
|
||||||
authenticationCubit: authenticationCubit,
|
authenticationCubit: authenticationCubit,
|
||||||
entries: FormData.empty(),
|
entries: const FormData.empty(),
|
||||||
),
|
),
|
||||||
seed: () => SignUpState(
|
seed: () => const SignUpState(
|
||||||
status: FormStatus.valid,
|
status: FormStatus.valid,
|
||||||
email: validEmail,
|
email: validEmail,
|
||||||
password: validPassword,
|
password: validPassword,
|
||||||
@ -248,13 +248,13 @@ void main() {
|
|||||||
),
|
),
|
||||||
act: (SignUpCubit cubit) => cubit.signUpFormSubmitted(),
|
act: (SignUpCubit cubit) => cubit.signUpFormSubmitted(),
|
||||||
expect: () => <SignUpState>[
|
expect: () => <SignUpState>[
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
status: FormStatus.submissionInProgress,
|
status: FormStatus.submissionInProgress,
|
||||||
email: validEmail,
|
email: validEmail,
|
||||||
password: validPassword,
|
password: validPassword,
|
||||||
data: FormData.empty(),
|
data: FormData.empty(),
|
||||||
),
|
),
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
status: FormStatus.submissionFailure,
|
status: FormStatus.submissionFailure,
|
||||||
email: validEmail,
|
email: validEmail,
|
||||||
password: validPassword,
|
password: validPassword,
|
||||||
|
@ -26,10 +26,10 @@ void main() {
|
|||||||
group('SignUpState', () {
|
group('SignUpState', () {
|
||||||
test('supports value comparisons', () {
|
test('supports value comparisons', () {
|
||||||
expect(
|
expect(
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
data: FormData.empty(),
|
data: FormData.empty(),
|
||||||
),
|
),
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
data: FormData.empty(),
|
data: FormData.empty(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -37,10 +37,10 @@ void main() {
|
|||||||
|
|
||||||
test('returns same object when no properties are passed', () {
|
test('returns same object when no properties are passed', () {
|
||||||
expect(
|
expect(
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
data: FormData.empty(),
|
data: FormData.empty(),
|
||||||
).copyWith(),
|
).copyWith(),
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
data: FormData.empty(),
|
data: FormData.empty(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -48,10 +48,10 @@ void main() {
|
|||||||
|
|
||||||
test('returns object with updated status when status is passed', () {
|
test('returns object with updated status when status is passed', () {
|
||||||
expect(
|
expect(
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
data: FormData.empty(),
|
data: FormData.empty(),
|
||||||
).copyWith(status: FormStatus.pure),
|
).copyWith(status: FormStatus.pure),
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
data: FormData.empty(),
|
data: FormData.empty(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -59,10 +59,10 @@ void main() {
|
|||||||
|
|
||||||
test('returns object with updated email when email is passed', () {
|
test('returns object with updated email when email is passed', () {
|
||||||
expect(
|
expect(
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
data: FormData.empty(),
|
data: FormData.empty(),
|
||||||
).copyWith(email: email),
|
).copyWith(email: email),
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
email: email,
|
email: email,
|
||||||
data: FormData.empty(),
|
data: FormData.empty(),
|
||||||
),
|
),
|
||||||
@ -71,10 +71,10 @@ void main() {
|
|||||||
|
|
||||||
test('returns object with updated password when password is passed', () {
|
test('returns object with updated password when password is passed', () {
|
||||||
expect(
|
expect(
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
data: FormData.empty(),
|
data: FormData.empty(),
|
||||||
).copyWith(password: password),
|
).copyWith(password: password),
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
password: password,
|
password: password,
|
||||||
data: FormData.empty(),
|
data: FormData.empty(),
|
||||||
),
|
),
|
||||||
@ -85,12 +85,12 @@ void main() {
|
|||||||
'returns object with updated data'
|
'returns object with updated data'
|
||||||
' when data is passed', () {
|
' when data is passed', () {
|
||||||
expect(
|
expect(
|
||||||
SignUpState(
|
const SignUpState(
|
||||||
data: FormData.empty(),
|
data: FormData.empty(),
|
||||||
).copyWith(
|
).copyWith(
|
||||||
data: const FormData(
|
data: const FormData(
|
||||||
[
|
[
|
||||||
FormEntry(
|
FormInput(
|
||||||
'field',
|
'field',
|
||||||
Name.pure(),
|
Name.pure(),
|
||||||
),
|
),
|
||||||
@ -100,7 +100,7 @@ void main() {
|
|||||||
const SignUpState(
|
const SignUpState(
|
||||||
data: FormData(
|
data: FormData(
|
||||||
[
|
[
|
||||||
FormEntry(
|
FormInput(
|
||||||
'field',
|
'field',
|
||||||
Name.pure(),
|
Name.pure(),
|
||||||
),
|
),
|
||||||
|
@ -18,8 +18,13 @@ part of 'form_data_cubit.dart';
|
|||||||
|
|
||||||
@immutable
|
@immutable
|
||||||
class FormDataState extends Equatable {
|
class FormDataState extends Equatable {
|
||||||
|
/// Global status of a form.
|
||||||
final FormStatus status;
|
final FormStatus status;
|
||||||
|
|
||||||
|
/// FormData with all inputs, and associated metadata.
|
||||||
final FormData data;
|
final FormData data;
|
||||||
|
|
||||||
|
/// Optional error message.
|
||||||
final String? errorMessage;
|
final String? errorMessage;
|
||||||
|
|
||||||
const FormDataState({
|
const FormDataState({
|
||||||
|
@ -76,11 +76,21 @@ enum FormStatus {
|
|||||||
/// Indicates whether the form submission has been canceled.
|
/// Indicates whether the form submission has been canceled.
|
||||||
bool get isSubmissionCanceled => this == FormStatus.submissionCanceled;
|
bool get isSubmissionCanceled => this == FormStatus.submissionCanceled;
|
||||||
|
|
||||||
/// Validate a list of inputs
|
/// Validate a list of inputs by processing them in `validate` as validators.
|
||||||
static FormStatus validate(List<FormInput> inputs) {
|
static FormStatus validateInputs(List<FormInput> inputs) {
|
||||||
return inputs.every((FormInput input) => input.validator.pure)
|
return validate(
|
||||||
|
inputs
|
||||||
|
.map<FormInputValidator>((FormInput input) => input.validator)
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Validate a list of validators.
|
||||||
|
static FormStatus validate(List<FormInputValidator> validators) {
|
||||||
|
return validators.every((FormInputValidator validator) => validator.pure)
|
||||||
? FormStatus.pure
|
? FormStatus.pure
|
||||||
: inputs.any((FormInput input) => input.validator.valid == false)
|
: validators
|
||||||
|
.any((FormInputValidator validator) => validator.valid == false)
|
||||||
? FormStatus.invalid
|
? FormStatus.invalid
|
||||||
: FormStatus.valid;
|
: FormStatus.valid;
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,11 @@ class FormData extends Equatable {
|
|||||||
const FormData(this._inputs);
|
const FormData(this._inputs);
|
||||||
const FormData.empty() : this(const <FormInput>[]);
|
const FormData.empty() : this(const <FormInput>[]);
|
||||||
|
|
||||||
|
/// Returns all inputs as a list
|
||||||
|
List<FormInput> inputs() => _inputs;
|
||||||
|
|
||||||
/// Returns the input for the associated key
|
/// Returns the input for the associated key
|
||||||
FormInput inputByKey(String key) {
|
FormInput inputOf(String key) {
|
||||||
if (contains(key)) {
|
if (contains(key)) {
|
||||||
return _inputs.firstWhere((FormInput input) => input.key == key);
|
return _inputs.firstWhere((FormInput input) => input.key == key);
|
||||||
} else {
|
} else {
|
||||||
@ -36,65 +39,83 @@ class FormData extends Equatable {
|
|||||||
void updateInput(String key, FormInput input) {
|
void updateInput(String key, FormInput input) {
|
||||||
if (contains(key)) {
|
if (contains(key)) {
|
||||||
final index = _inputs.indexOf(
|
final index = _inputs.indexOf(
|
||||||
inputByKey(key),
|
inputOf(key),
|
||||||
);
|
);
|
||||||
_inputs[index] = input;
|
_inputs[index] = input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates validator of a given input. (perform copyWith)
|
/// Returns all associated validators as a list
|
||||||
void updateValidator(String key, FormInputValidator dirtyValue) {
|
List<FormInputValidator<V, E>> validators<V, E>() {
|
||||||
if (contains(key)) {
|
return _inputs
|
||||||
final index = _inputs.indexOf(
|
.map<FormInputValidator<V, E>>(
|
||||||
inputByKey(key),
|
(FormInput input) => input.validator as FormInputValidator<V, E>,
|
||||||
);
|
)
|
||||||
_inputs[index] = _inputs[index].copyWith(validator: dirtyValue);
|
.toList();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Updates metadata of a given input. (perform copyWith)
|
|
||||||
void updateMetadata(String key, FormInputMetadata meta) {
|
|
||||||
if (contains(key)) {
|
|
||||||
final index = _inputs.indexOf(
|
|
||||||
inputByKey(key),
|
|
||||||
);
|
|
||||||
_inputs[index] = _inputs[index].copyWith(metadata: meta);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A [FormInputValidator] represents the value of a single form input field.
|
/// A [FormInputValidator] represents the value of a single form input field.
|
||||||
/// It contains information about the [FormInputStatus], value, as well
|
/// It contains information about the [FormInputStatus], value, as well
|
||||||
/// as validation status.
|
/// as validation status.
|
||||||
T validatorOf<T>(String key) {
|
T validatorOf<T>(String key) {
|
||||||
return inputByKey(key).validator as T;
|
return inputOf(key).validator as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates validator of a given input. (perform copyWith)
|
||||||
|
void updateValidator(String key, FormInputValidator dirtyValue) {
|
||||||
|
if (contains(key)) {
|
||||||
|
final index = _inputs.indexOf(
|
||||||
|
inputOf(key),
|
||||||
|
);
|
||||||
|
_inputs[index] = _inputs[index].copyWith(validator: dirtyValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a validation error if the [FormInputValidator] is invalid.
|
/// Returns a validation error if the [FormInputValidator] is invalid.
|
||||||
/// Returns null if the [FormInputValidator] is valid.
|
/// Returns null if the [FormInputValidator] is valid.
|
||||||
E? errorOf<V, E>(String key) {
|
E? errorOf<V, E>(String key) {
|
||||||
return (inputByKey(key).validator as FormInputValidator<V, E>).error;
|
return (inputOf(key).validator as FormInputValidator<V, E>).error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The value of the associated [FormInputValidator]. For example,
|
/// The value of the associated [FormInputValidator]. For example,
|
||||||
/// if you have a FormInputValidator for FirstName, the value could be 'Joe'.
|
/// if you have a FormInputValidator for FirstName, the value could be 'Joe'.
|
||||||
V valueOf<V, E>(String key) {
|
V valueOf<V, E>(String key) {
|
||||||
return (inputByKey(key).validator as FormInputValidator<V, E>).value;
|
return (inputOf(key).validator as FormInputValidator<V, E>).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the [FormInputValidator] is not valid.
|
/// Returns `true` if the [FormInputValidator] is not valid.
|
||||||
/// Same as `E? errorOf<V, E>(String key) != null`
|
/// Same as `E? errorOf<V, E>(String key) != null`
|
||||||
bool isNotValid(String key) {
|
bool isNotValid(String key) {
|
||||||
return !inputByKey(key).validator.valid;
|
return !inputOf(key).validator.valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns all associated metadata as a list
|
||||||
|
List<FormInputMetadata<M>> metadata<M>() {
|
||||||
|
return _inputs
|
||||||
|
.map<FormInputMetadata<M>>(
|
||||||
|
(FormInput input) => input.metadata as FormInputMetadata<M>,
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the metadata associated. With `M` the type of extra data.
|
/// Returns the metadata associated. With `M` the type of extra data.
|
||||||
FormInputMetadata<M> metadataOf<M>(String key) {
|
FormInputMetadata<M> metadataOf<M>(String key) {
|
||||||
return inputByKey(key).metadata as FormInputMetadata<M>;
|
return inputOf(key).metadata as FormInputMetadata<M>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates metadata of a given input. (perform copyWith)
|
||||||
|
void updateMetadata(String key, FormInputMetadata meta) {
|
||||||
|
if (contains(key)) {
|
||||||
|
final index = _inputs.indexOf(
|
||||||
|
inputOf(key),
|
||||||
|
);
|
||||||
|
_inputs[index] = _inputs[index].copyWith(metadata: meta);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validate self inputs.
|
/// Validate self inputs.
|
||||||
FormStatus validate() {
|
FormStatus validate() {
|
||||||
return FormStatus.validate(_inputs);
|
return FormStatus.validateInputs(_inputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if this contains an input with the given key.
|
/// Check if this contains an input with the given key.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user