added country_code_picker package to link phone feature
This commit is contained in:
@@ -168,6 +168,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "3.1.2"
|
||||||
|
country_code_picker:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: country_code_picker
|
||||||
|
sha256: f0411f4833b6f98e8b7215f4fa3813bcc88e50f13925f70a170dbd36e3e447f5
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.4.1"
|
||||||
coverage:
|
coverage:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -214,6 +222,14 @@ packages:
|
|||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "0.0.1"
|
version: "0.0.1"
|
||||||
|
diacritic:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: diacritic
|
||||||
|
sha256: "12981945ec38931748836cd76f2b38773118d0baef3c68404bdfde9566147876"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.6"
|
||||||
dio:
|
dio:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -432,6 +448,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.20.2"
|
version: "0.20.2"
|
||||||
|
intl_phone_field_v2:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: intl_phone_field_v2
|
||||||
|
sha256: b1e5077e31cc8705639a69b2e0410a8ecc858c3e518726d99b378b6c35adfefb
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.0.5"
|
||||||
io:
|
io:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:auth/src/features/link_phone/presentation/link_phone_view_model.dart';
|
import 'package:auth/src/features/link_phone/presentation/link_phone_view_model.dart';
|
||||||
|
import 'package:design_system/src/dropdowns/country_prefix_picker.dart';
|
||||||
import 'package:design_system/design_system.dart';
|
import 'package:design_system/design_system.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
@@ -10,13 +11,11 @@ class LinkPhoneScreen extends ConsumerWidget {
|
|||||||
|
|
||||||
const LinkPhoneScreen({super.key, required this.navigationContract});
|
const LinkPhoneScreen({super.key, required this.navigationContract});
|
||||||
|
|
||||||
void _onCountryChanged(int? value) {}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final theme = ref.watch(themePortProvider);
|
final theme = ref.watch(themePortProvider);
|
||||||
|
|
||||||
final viewModel = ref.watch(linkPhoneViewModelProvider.notifier);
|
final viewModel = ref.read(linkPhoneViewModelProvider.notifier);
|
||||||
final viewState = ref.watch(linkPhoneViewModelProvider);
|
final viewState = ref.watch(linkPhoneViewModelProvider);
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@@ -56,19 +55,17 @@ class LinkPhoneScreen extends ConsumerWidget {
|
|||||||
Row(
|
Row(
|
||||||
spacing: 10,
|
spacing: 10,
|
||||||
children: [
|
children: [
|
||||||
CustomDropdown(
|
CountryPrefixPicker(
|
||||||
value: 0,
|
initialCountryCode: viewState.dialCode,
|
||||||
items: const [
|
onChanged: (country) {
|
||||||
Icon(Icons.outlined_flag),
|
viewModel.updateDialCode(
|
||||||
Icon(Icons.outlined_flag),
|
country.dialCode ?? viewState.dialCode,
|
||||||
Icon(Icons.outlined_flag),
|
);
|
||||||
],
|
},
|
||||||
onChanged: _onCountryChanged,
|
|
||||||
width: 80,
|
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: CustomTextField(
|
child: CustomTextField(
|
||||||
// controller: viewModel.phoneNumberController,
|
controller: viewModel.phoneNumberController,
|
||||||
hint: context.translate(I18n.phoneNumber),
|
hint: context.translate(I18n.phoneNumber),
|
||||||
numeric: true,
|
numeric: true,
|
||||||
),
|
),
|
||||||
@@ -80,11 +77,10 @@ class LinkPhoneScreen extends ConsumerWidget {
|
|||||||
|
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
if (viewState.errorMessage?.isNotEmpty ?? false) ...[
|
if (viewState.errorMessage.isNotEmpty) ...[
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
Text(
|
||||||
// context.translate(viewState.errorMessage
|
viewState.errorMessage,
|
||||||
'',
|
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Color.fromRGBO(239, 17, 17, 1),
|
color: Color.fromRGBO(239, 17, 17, 1),
|
||||||
@@ -99,7 +95,7 @@ class LinkPhoneScreen extends ConsumerWidget {
|
|||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await viewModel.requestCode();
|
await viewModel.requestCode();
|
||||||
final updatedState = ref.read(linkPhoneViewModelProvider);
|
final updatedState = ref.read(linkPhoneViewModelProvider);
|
||||||
if (updatedState.errorMessage!.isEmpty) {
|
if (updatedState.errorMessage.isEmpty) {
|
||||||
navigationContract.pushTo(AppRoutes.phoneCode);
|
navigationContract.pushTo(AppRoutes.phoneCode);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -17,30 +17,42 @@ class LinkPhoneViewModel extends Notifier<LinkPhoneViewState> {
|
|||||||
@override
|
@override
|
||||||
LinkPhoneViewState build() {
|
LinkPhoneViewState build() {
|
||||||
_linkPhoneUseCase = ref.read(linkPhoneUseCaseProvider);
|
_linkPhoneUseCase = ref.read(linkPhoneUseCaseProvider);
|
||||||
|
|
||||||
phoneNumberController = TextEditingController();
|
phoneNumberController = TextEditingController();
|
||||||
phoneNumberController.addListener(_onPhoneNumberChanged);
|
phoneNumberController.addListener(_onPhoneNumberChanged);
|
||||||
|
|
||||||
ref.onDispose(disposeControllers);
|
ref.onDispose(disposeControllers);
|
||||||
|
|
||||||
return const LinkPhoneViewState();
|
return const LinkPhoneViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onPhoneNumberChanged() {
|
void _onPhoneNumberChanged() {
|
||||||
final raw = phoneNumberController.text;
|
final raw = phoneNumberController.text;
|
||||||
|
|
||||||
state = state.copyWith(phoneNumber: raw, errorMessage: '');
|
state = state.copyWith(phoneNumber: raw, errorMessage: '');
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> requestCode() async {
|
void updateDialCode(String dialCode) {
|
||||||
final phone = phoneNumberController.text.trim();
|
state = state.copyWith(dialCode: dialCode, errorMessage: '');
|
||||||
|
}
|
||||||
|
|
||||||
if (phone.isEmpty) {
|
Future<void> requestCode() async {
|
||||||
|
final trimmedNumber = state.phoneNumber.trim();
|
||||||
|
|
||||||
|
if (trimmedNumber.isEmpty) {
|
||||||
state = state.copyWith(errorMessage: 'El teléfono no puede estar vacío');
|
state = state.copyWith(errorMessage: 'El teléfono no puede estar vacío');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
state = state.copyWith(isLoading: true, errorMessage: '');
|
final fullPhone = '${state.dialCode}$trimmedNumber';
|
||||||
|
|
||||||
|
state = state.copyWith(
|
||||||
|
isLoading: true,
|
||||||
|
errorMessage: '',
|
||||||
|
codeRequested: false,
|
||||||
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await _linkPhoneUseCase.requestCode(phone: phone);
|
await _linkPhoneUseCase.requestCode(phone: fullPhone);
|
||||||
if (!ref.mounted) return;
|
if (!ref.mounted) return;
|
||||||
|
|
||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
@@ -50,7 +62,12 @@ class LinkPhoneViewModel extends Notifier<LinkPhoneViewState> {
|
|||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (!ref.mounted) return;
|
if (!ref.mounted) return;
|
||||||
state = state.copyWith(isLoading: false, errorMessage: e.toString());
|
|
||||||
|
state = state.copyWith(
|
||||||
|
isLoading: false,
|
||||||
|
errorMessage: e.toString(),
|
||||||
|
codeRequested: false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ part 'link_phone_view_state.freezed.dart';
|
|||||||
abstract class LinkPhoneViewState with _$LinkPhoneViewState {
|
abstract class LinkPhoneViewState with _$LinkPhoneViewState {
|
||||||
const factory LinkPhoneViewState({
|
const factory LinkPhoneViewState({
|
||||||
@Default('') String phoneNumber,
|
@Default('') String phoneNumber,
|
||||||
String? errorMessage,
|
@Default('+34') String dialCode,
|
||||||
|
@Default('') String errorMessage,
|
||||||
@Default(false) bool isLoading,
|
@Default(false) bool isLoading,
|
||||||
@Default(false) bool codeRequested,
|
@Default(false) bool codeRequested,
|
||||||
}) = _LinkPhoneViewState;
|
}) = _LinkPhoneViewState;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$LinkPhoneViewState {
|
mixin _$LinkPhoneViewState {
|
||||||
|
|
||||||
String get phoneNumber; String? get errorMessage; bool get isLoading; bool get codeRequested;
|
String get phoneNumber; String get dialCode; String get errorMessage; bool get isLoading; bool get codeRequested;
|
||||||
/// Create a copy of LinkPhoneViewState
|
/// Create a copy of LinkPhoneViewState
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -25,16 +25,16 @@ $LinkPhoneViewStateCopyWith<LinkPhoneViewState> get copyWith => _$LinkPhoneViewS
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is LinkPhoneViewState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.codeRequested, codeRequested) || other.codeRequested == codeRequested));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is LinkPhoneViewState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.codeRequested, codeRequested) || other.codeRequested == codeRequested));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,phoneNumber,errorMessage,isLoading,codeRequested);
|
int get hashCode => Object.hash(runtimeType,phoneNumber,dialCode,errorMessage,isLoading,codeRequested);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'LinkPhoneViewState(phoneNumber: $phoneNumber, errorMessage: $errorMessage, isLoading: $isLoading, codeRequested: $codeRequested)';
|
return 'LinkPhoneViewState(phoneNumber: $phoneNumber, dialCode: $dialCode, errorMessage: $errorMessage, isLoading: $isLoading, codeRequested: $codeRequested)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ abstract mixin class $LinkPhoneViewStateCopyWith<$Res> {
|
|||||||
factory $LinkPhoneViewStateCopyWith(LinkPhoneViewState value, $Res Function(LinkPhoneViewState) _then) = _$LinkPhoneViewStateCopyWithImpl;
|
factory $LinkPhoneViewStateCopyWith(LinkPhoneViewState value, $Res Function(LinkPhoneViewState) _then) = _$LinkPhoneViewStateCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String phoneNumber, String? errorMessage, bool isLoading, bool codeRequested
|
String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -62,11 +62,12 @@ class _$LinkPhoneViewStateCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of LinkPhoneViewState
|
/// Create a copy of LinkPhoneViewState
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? phoneNumber = null,Object? errorMessage = freezed,Object? isLoading = null,Object? codeRequested = null,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? phoneNumber = null,Object? dialCode = null,Object? errorMessage = null,Object? isLoading = null,Object? codeRequested = null,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable
|
phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable
|
||||||
as String,errorMessage: freezed == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
as String,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,codeRequested: null == codeRequested ? _self.codeRequested : codeRequested // ignore: cast_nullable_to_non_nullable
|
as bool,codeRequested: null == codeRequested ? _self.codeRequested : codeRequested // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,
|
||||||
));
|
));
|
||||||
@@ -153,10 +154,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String phoneNumber, String? errorMessage, bool isLoading, bool codeRequested)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _LinkPhoneViewState() when $default != null:
|
case _LinkPhoneViewState() when $default != null:
|
||||||
return $default(_that.phoneNumber,_that.errorMessage,_that.isLoading,_that.codeRequested);case _:
|
return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -174,10 +175,10 @@ return $default(_that.phoneNumber,_that.errorMessage,_that.isLoading,_that.codeR
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String phoneNumber, String? errorMessage, bool isLoading, bool codeRequested) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _LinkPhoneViewState():
|
case _LinkPhoneViewState():
|
||||||
return $default(_that.phoneNumber,_that.errorMessage,_that.isLoading,_that.codeRequested);case _:
|
return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested);case _:
|
||||||
throw StateError('Unexpected subclass');
|
throw StateError('Unexpected subclass');
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -194,10 +195,10 @@ return $default(_that.phoneNumber,_that.errorMessage,_that.isLoading,_that.codeR
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String phoneNumber, String? errorMessage, bool isLoading, bool codeRequested)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _LinkPhoneViewState() when $default != null:
|
case _LinkPhoneViewState() when $default != null:
|
||||||
return $default(_that.phoneNumber,_that.errorMessage,_that.isLoading,_that.codeRequested);case _:
|
return $default(_that.phoneNumber,_that.dialCode,_that.errorMessage,_that.isLoading,_that.codeRequested);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -209,11 +210,12 @@ return $default(_that.phoneNumber,_that.errorMessage,_that.isLoading,_that.codeR
|
|||||||
|
|
||||||
|
|
||||||
class _LinkPhoneViewState implements LinkPhoneViewState {
|
class _LinkPhoneViewState implements LinkPhoneViewState {
|
||||||
const _LinkPhoneViewState({this.phoneNumber = '', this.errorMessage, this.isLoading = false, this.codeRequested = false});
|
const _LinkPhoneViewState({this.phoneNumber = '', this.dialCode = '+34', this.errorMessage = '', this.isLoading = false, this.codeRequested = false});
|
||||||
|
|
||||||
|
|
||||||
@override@JsonKey() final String phoneNumber;
|
@override@JsonKey() final String phoneNumber;
|
||||||
@override final String? errorMessage;
|
@override@JsonKey() final String dialCode;
|
||||||
|
@override@JsonKey() final String errorMessage;
|
||||||
@override@JsonKey() final bool isLoading;
|
@override@JsonKey() final bool isLoading;
|
||||||
@override@JsonKey() final bool codeRequested;
|
@override@JsonKey() final bool codeRequested;
|
||||||
|
|
||||||
@@ -227,16 +229,16 @@ _$LinkPhoneViewStateCopyWith<_LinkPhoneViewState> get copyWith => __$LinkPhoneVi
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _LinkPhoneViewState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.codeRequested, codeRequested) || other.codeRequested == codeRequested));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _LinkPhoneViewState&&(identical(other.phoneNumber, phoneNumber) || other.phoneNumber == phoneNumber)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.codeRequested, codeRequested) || other.codeRequested == codeRequested));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,phoneNumber,errorMessage,isLoading,codeRequested);
|
int get hashCode => Object.hash(runtimeType,phoneNumber,dialCode,errorMessage,isLoading,codeRequested);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'LinkPhoneViewState(phoneNumber: $phoneNumber, errorMessage: $errorMessage, isLoading: $isLoading, codeRequested: $codeRequested)';
|
return 'LinkPhoneViewState(phoneNumber: $phoneNumber, dialCode: $dialCode, errorMessage: $errorMessage, isLoading: $isLoading, codeRequested: $codeRequested)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -247,7 +249,7 @@ abstract mixin class _$LinkPhoneViewStateCopyWith<$Res> implements $LinkPhoneVie
|
|||||||
factory _$LinkPhoneViewStateCopyWith(_LinkPhoneViewState value, $Res Function(_LinkPhoneViewState) _then) = __$LinkPhoneViewStateCopyWithImpl;
|
factory _$LinkPhoneViewStateCopyWith(_LinkPhoneViewState value, $Res Function(_LinkPhoneViewState) _then) = __$LinkPhoneViewStateCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String phoneNumber, String? errorMessage, bool isLoading, bool codeRequested
|
String phoneNumber, String dialCode, String errorMessage, bool isLoading, bool codeRequested
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -264,11 +266,12 @@ class __$LinkPhoneViewStateCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of LinkPhoneViewState
|
/// Create a copy of LinkPhoneViewState
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? phoneNumber = null,Object? errorMessage = freezed,Object? isLoading = null,Object? codeRequested = null,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? phoneNumber = null,Object? dialCode = null,Object? errorMessage = null,Object? isLoading = null,Object? codeRequested = null,}) {
|
||||||
return _then(_LinkPhoneViewState(
|
return _then(_LinkPhoneViewState(
|
||||||
phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable
|
phoneNumber: null == phoneNumber ? _self.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable
|
||||||
as String,errorMessage: freezed == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
as String,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,codeRequested: null == codeRequested ? _self.codeRequested : codeRequested // ignore: cast_nullable_to_non_nullable
|
as bool,codeRequested: null == codeRequested ? _self.codeRequested : codeRequested // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ dependencies:
|
|||||||
freezed_annotation: ^3.1.0
|
freezed_annotation: ^3.1.0
|
||||||
freezed: ^3.2.3
|
freezed: ^3.2.3
|
||||||
dio: ^5.9.0
|
dio: ^5.9.0
|
||||||
|
country_code_picker: ^3.4.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
@@ -9,4 +9,5 @@ export 'src/snackbars/snackbar.dart';
|
|||||||
export 'src/buttons/primary_button.dart';
|
export 'src/buttons/primary_button.dart';
|
||||||
export 'src/buttons/secondary_button.dart';
|
export 'src/buttons/secondary_button.dart';
|
||||||
export 'src/buttons/custom_text_button.dart';
|
export 'src/buttons/custom_text_button.dart';
|
||||||
export 'src/dropdowns/dropdown.dart';
|
export 'src/dropdowns/dropdown.dart';
|
||||||
|
export 'src/dropdowns/country_prefix_picker.dart';
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import 'package:country_code_picker/country_code_picker.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class CountryPrefixPicker extends StatelessWidget {
|
||||||
|
const CountryPrefixPicker({
|
||||||
|
super.key,
|
||||||
|
required this.onChanged,
|
||||||
|
this.initialCountryCode = '+34',
|
||||||
|
this.radius = 12,
|
||||||
|
this.width = 90,
|
||||||
|
this.height = 55,
|
||||||
|
this.borderColor = const Color(0xFF4B4B4B),
|
||||||
|
this.backgroundColor = Colors.white,
|
||||||
|
});
|
||||||
|
|
||||||
|
final ValueChanged<CountryCode> onChanged;
|
||||||
|
final String initialCountryCode;
|
||||||
|
|
||||||
|
final double radius;
|
||||||
|
final double width;
|
||||||
|
final double height;
|
||||||
|
final Color borderColor;
|
||||||
|
final Color backgroundColor;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SizedBox(
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
child: CountryCodePicker(
|
||||||
|
onChanged: onChanged,
|
||||||
|
initialSelection: initialCountryCode,
|
||||||
|
showFlag: false,
|
||||||
|
showDropDownButton: false,
|
||||||
|
hideMainText: true,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
builder: (CountryCode? country) {
|
||||||
|
if (country == null) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
|
return InputDecorator(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
isDense: false,
|
||||||
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 12,
|
||||||
|
vertical: 16,
|
||||||
|
),
|
||||||
|
filled: true,
|
||||||
|
fillColor: backgroundColor,
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(radius)),
|
||||||
|
borderSide: BorderSide(color: borderColor),
|
||||||
|
),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(radius)),
|
||||||
|
borderSide: BorderSide(color: borderColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
if (country.flagUri != null)
|
||||||
|
Image.asset(
|
||||||
|
country.flagUri!,
|
||||||
|
package: 'country_code_picker',
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
const Icon(Icons.arrow_drop_down, size: 24),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +1,17 @@
|
|||||||
import 'package:design_system/design_system.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
||||||
|
|
||||||
class CustomTextField extends StatefulWidget{
|
class CustomTextField extends StatefulWidget {
|
||||||
bool? showPassword;
|
final bool? showPassword;
|
||||||
final bool numeric;
|
final bool numeric;
|
||||||
final String hint;
|
final String hint;
|
||||||
final String label;
|
final String label;
|
||||||
final int? lines;
|
final int? lines;
|
||||||
final ValueChanged<String>? onChanged;
|
final ValueChanged<String>? onChanged;
|
||||||
final int? length;
|
final int? length;
|
||||||
|
final TextEditingController? controller;
|
||||||
|
|
||||||
CustomTextField({
|
const CustomTextField({
|
||||||
super.key,
|
super.key,
|
||||||
this.showPassword,
|
this.showPassword,
|
||||||
this.numeric = false,
|
this.numeric = false,
|
||||||
@@ -21,63 +20,74 @@ class CustomTextField extends StatefulWidget{
|
|||||||
this.lines,
|
this.lines,
|
||||||
this.length,
|
this.length,
|
||||||
this.onChanged,
|
this.onChanged,
|
||||||
|
this.controller,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<CustomTextField> createState() => CustomTextFieldState();
|
State<CustomTextField> createState() => CustomTextFieldState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class CustomTextFieldState extends State<CustomTextField>{
|
class CustomTextFieldState extends State<CustomTextField> {
|
||||||
|
late bool _showPassword;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_showPassword = widget.showPassword ?? true;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
?widget.label == '' ? null : Align(
|
if (widget.label.isNotEmpty)
|
||||||
alignment: Alignment.bottomLeft,
|
Align(
|
||||||
child: Text(
|
alignment: Alignment.bottomLeft,
|
||||||
widget.label,
|
child: Text(
|
||||||
style: TextStyle(fontSize: 14, letterSpacing: 0),
|
widget.label,
|
||||||
)
|
style: const TextStyle(fontSize: 14, letterSpacing: 0),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
TextFormField(
|
TextFormField(
|
||||||
keyboardType: widget.numeric? TextInputType.number : TextInputType.text,
|
controller: widget.controller,
|
||||||
obscureText: !(widget.showPassword ?? true),
|
keyboardType: widget.numeric
|
||||||
enableSuggestions: widget.showPassword ?? true,
|
? TextInputType.number
|
||||||
autocorrect: !(widget.showPassword ?? false),
|
: TextInputType.text,
|
||||||
style: TextStyle(color: Color(0xFF4B4B4B)),
|
obscureText: !_showPassword,
|
||||||
inputFormatters: widget.numeric? [
|
enableSuggestions: _showPassword,
|
||||||
FilteringTextInputFormatter.digitsOnly
|
autocorrect: !_showPassword,
|
||||||
] : [],
|
style: const TextStyle(color: Color(0xFF4B4B4B)),
|
||||||
|
inputFormatters: widget.numeric
|
||||||
|
? <TextInputFormatter>[FilteringTextInputFormatter.digitsOnly]
|
||||||
|
: const <TextInputFormatter>[],
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
counterText: "",
|
counterText: "",
|
||||||
hintText: widget.hint,
|
hintText: widget.hint,
|
||||||
//labelText: widget.label,
|
border: const OutlineInputBorder(
|
||||||
//floatingLabelBehavior: FloatingLabelBehavior.always,
|
|
||||||
border: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(12)),
|
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||||
borderSide: BorderSide(color: Color(0xFF4B4B4B)),
|
borderSide: BorderSide(color: Color(0xFF4B4B4B)),
|
||||||
gapPadding: 16
|
gapPadding: 16,
|
||||||
),
|
),
|
||||||
suffixIcon: widget.showPassword!=null ? IconButton(
|
suffixIcon: widget.showPassword != null
|
||||||
icon: Icon(widget.showPassword!
|
? IconButton(
|
||||||
? Icons.visibility_off
|
icon: Icon(
|
||||||
: Icons.visibility),
|
_showPassword ? Icons.visibility_off : Icons.visibility,
|
||||||
onPressed: () {
|
),
|
||||||
setState(() {
|
onPressed: () {
|
||||||
widget.showPassword = !widget.showPassword!;
|
setState(() {
|
||||||
});
|
_showPassword = !_showPassword;
|
||||||
},
|
});
|
||||||
) : null,
|
},
|
||||||
|
)
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
minLines: widget.lines ?? 1,
|
minLines: widget.lines ?? 1,
|
||||||
maxLines: widget.lines ?? 1,
|
maxLines: widget.lines ?? 1,
|
||||||
maxLength: widget.length,
|
maxLength: widget.length,
|
||||||
onChanged: widget.onChanged ?? (_)=>{},
|
onChanged: widget.onChanged,
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ dependencies:
|
|||||||
path: ../utils
|
path: ../utils
|
||||||
flutter_riverpod: ^3.0.3
|
flutter_riverpod: ^3.0.3
|
||||||
get_it: ^9.0.5
|
get_it: ^9.0.5
|
||||||
|
country_code_picker: ^3.4.1
|
||||||
fonts:
|
fonts:
|
||||||
path: ../../packages/fonts
|
path: ../../packages/fonts
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user