added country_code_picker package to link phone feature #8
@@ -168,6 +168,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
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:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -214,6 +222,14 @@ packages:
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
diacritic:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: diacritic
|
||||
sha256: "12981945ec38931748836cd76f2b38773118d0baef3c68404bdfde9566147876"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.6"
|
||||
dio:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -432,6 +448,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
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:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
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:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
@@ -10,13 +11,11 @@ class LinkPhoneScreen extends ConsumerWidget {
|
||||
|
||||
const LinkPhoneScreen({super.key, required this.navigationContract});
|
||||
|
||||
void _onCountryChanged(int? value) {}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
|
||||
final viewModel = ref.watch(linkPhoneViewModelProvider.notifier);
|
||||
final viewModel = ref.read(linkPhoneViewModelProvider.notifier);
|
||||
final viewState = ref.watch(linkPhoneViewModelProvider);
|
||||
|
||||
return Scaffold(
|
||||
@@ -56,19 +55,17 @@ class LinkPhoneScreen extends ConsumerWidget {
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
CustomDropdown(
|
||||
value: 0,
|
||||
items: const [
|
||||
Icon(Icons.outlined_flag),
|
||||
Icon(Icons.outlined_flag),
|
||||
Icon(Icons.outlined_flag),
|
||||
],
|
||||
onChanged: _onCountryChanged,
|
||||
width: 80,
|
||||
CountryPrefixPicker(
|
||||
initialCountryCode: viewState.dialCode,
|
||||
onChanged: (country) {
|
||||
viewModel.updateDialCode(
|
||||
country.dialCode ?? viewState.dialCode,
|
||||
);
|
||||
},
|
||||
),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
// controller: viewModel.phoneNumberController,
|
||||
controller: viewModel.phoneNumberController,
|
||||
hint: context.translate(I18n.phoneNumber),
|
||||
numeric: true,
|
||||
),
|
||||
@@ -80,11 +77,10 @@ class LinkPhoneScreen extends ConsumerWidget {
|
||||
|
||||
const SizedBox(height: 16),
|
||||
|
||||
if (viewState.errorMessage?.isNotEmpty ?? false) ...[
|
||||
if (viewState.errorMessage.isNotEmpty) ...[
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
// context.translate(viewState.errorMessage
|
||||
'',
|
||||
viewState.errorMessage,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
color: Color.fromRGBO(239, 17, 17, 1),
|
||||
@@ -99,7 +95,7 @@ class LinkPhoneScreen extends ConsumerWidget {
|
||||
onPressed: () async {
|
||||
await viewModel.requestCode();
|
||||
final updatedState = ref.read(linkPhoneViewModelProvider);
|
||||
if (updatedState.errorMessage!.isEmpty) {
|
||||
if (updatedState.errorMessage.isEmpty) {
|
||||
navigationContract.pushTo(AppRoutes.phoneCode);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -17,30 +17,42 @@ class LinkPhoneViewModel extends Notifier<LinkPhoneViewState> {
|
||||
@override
|
||||
LinkPhoneViewState build() {
|
||||
_linkPhoneUseCase = ref.read(linkPhoneUseCaseProvider);
|
||||
|
||||
phoneNumberController = TextEditingController();
|
||||
phoneNumberController.addListener(_onPhoneNumberChanged);
|
||||
|
||||
ref.onDispose(disposeControllers);
|
||||
|
||||
return const LinkPhoneViewState();
|
||||
}
|
||||
|
||||
void _onPhoneNumberChanged() {
|
||||
final raw = phoneNumberController.text;
|
||||
|
||||
state = state.copyWith(phoneNumber: raw, errorMessage: '');
|
||||
}
|
||||
|
||||
Future<void> requestCode() async {
|
||||
final phone = phoneNumberController.text.trim();
|
||||
void updateDialCode(String dialCode) {
|
||||
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');
|
||||
return;
|
||||
}
|
||||
|
||||
state = state.copyWith(isLoading: true, errorMessage: '');
|
||||
final fullPhone = '${state.dialCode}$trimmedNumber';
|
||||
|
||||
state = state.copyWith(
|
||||
isLoading: true,
|
||||
errorMessage: '',
|
||||
codeRequested: false,
|
||||
);
|
||||
|
||||
try {
|
||||
await _linkPhoneUseCase.requestCode(phone: phone);
|
||||
await _linkPhoneUseCase.requestCode(phone: fullPhone);
|
||||
if (!ref.mounted) return;
|
||||
|
||||
state = state.copyWith(
|
||||
@@ -50,7 +62,12 @@ class LinkPhoneViewModel extends Notifier<LinkPhoneViewState> {
|
||||
);
|
||||
} catch (e) {
|
||||
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 {
|
||||
const factory LinkPhoneViewState({
|
||||
@Default('') String phoneNumber,
|
||||
String? errorMessage,
|
||||
@Default('+34') String dialCode,
|
||||
@Default('') String errorMessage,
|
||||
@Default(false) bool isLoading,
|
||||
@Default(false) bool codeRequested,
|
||||
}) = _LinkPhoneViewState;
|
||||
|
||||
@@ -14,7 +14,7 @@ T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
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
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -25,16 +25,16 @@ $LinkPhoneViewStateCopyWith<LinkPhoneViewState> get copyWith => _$LinkPhoneViewS
|
||||
|
||||
@override
|
||||
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
|
||||
int get hashCode => Object.hash(runtimeType,phoneNumber,errorMessage,isLoading,codeRequested);
|
||||
int get hashCode => Object.hash(runtimeType,phoneNumber,dialCode,errorMessage,isLoading,codeRequested);
|
||||
|
||||
@override
|
||||
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;
|
||||
@useResult
|
||||
$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
|
||||
/// 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(
|
||||
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?,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as String,dialCode: null == dialCode ? _self.dialCode : dialCode // 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,
|
||||
));
|
||||
@@ -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) {
|
||||
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();
|
||||
|
||||
}
|
||||
@@ -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) {
|
||||
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');
|
||||
|
||||
}
|
||||
@@ -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) {
|
||||
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;
|
||||
|
||||
}
|
||||
@@ -209,11 +210,12 @@ return $default(_that.phoneNumber,_that.errorMessage,_that.isLoading,_that.codeR
|
||||
|
||||
|
||||
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 final String? errorMessage;
|
||||
@override@JsonKey() final String dialCode;
|
||||
@override@JsonKey() final String errorMessage;
|
||||
@override@JsonKey() final bool isLoading;
|
||||
@override@JsonKey() final bool codeRequested;
|
||||
|
||||
@@ -227,16 +229,16 @@ _$LinkPhoneViewStateCopyWith<_LinkPhoneViewState> get copyWith => __$LinkPhoneVi
|
||||
|
||||
@override
|
||||
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
|
||||
int get hashCode => Object.hash(runtimeType,phoneNumber,errorMessage,isLoading,codeRequested);
|
||||
int get hashCode => Object.hash(runtimeType,phoneNumber,dialCode,errorMessage,isLoading,codeRequested);
|
||||
|
||||
@override
|
||||
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;
|
||||
@override @useResult
|
||||
$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
|
||||
/// 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(
|
||||
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?,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as String,dialCode: null == dialCode ? _self.dialCode : dialCode // 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,
|
||||
));
|
||||
|
||||
@@ -32,6 +32,7 @@ dependencies:
|
||||
freezed_annotation: ^3.1.0
|
||||
freezed: ^3.2.3
|
||||
dio: ^5.9.0
|
||||
country_code_picker: ^3.4.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@@ -9,4 +9,5 @@ export 'src/snackbars/snackbar.dart';
|
||||
export 'src/buttons/primary_button.dart';
|
||||
export 'src/buttons/secondary_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),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ class CustomTextField extends StatefulWidget {
|
||||
final int? lines;
|
||||
final ValueChanged<String>? onChanged;
|
||||
final int? length;
|
||||
final TextEditingController? controller;
|
||||
|
||||
const CustomTextField({
|
||||
super.key,
|
||||
@@ -19,6 +20,7 @@ class CustomTextField extends StatefulWidget {
|
||||
this.lines,
|
||||
this.length,
|
||||
this.onChanged,
|
||||
this.controller,
|
||||
});
|
||||
|
||||
@override
|
||||
|
||||
@@ -16,6 +16,7 @@ dependencies:
|
||||
path: ../utils
|
||||
flutter_riverpod: ^3.0.3
|
||||
get_it: ^9.0.5
|
||||
country_code_picker: ^3.4.1
|
||||
fonts:
|
||||
path: ../../packages/fonts
|
||||
|
||||
|
||||
Reference in New Issue
Block a user