diff --git a/.firebase/hosting.YnVpbGQvd2Vi.cache b/.firebase/hosting.YnVpbGQvd2Vi.cache deleted file mode 100644 index c3398a5..0000000 --- a/.firebase/hosting.YnVpbGQvd2Vi.cache +++ /dev/null @@ -1,23 +0,0 @@ -404.html,1642287121706,05cbc6f94d7a69ce2e29646eab13be2c884e61ba93e3094df5028866876d18b3 -favicon.png,1639011687000,fcc7c4545d5b62ad01682589e6fdc7ea03d0a3b42069963c815c344b632eb5cf -main.dart.js.map,1642207247023,abc955e1017b89dfcf20763db0acbfda343cda73b8084f95bc5cd9630b192201 -manifest.json,1642160045195,1912cc123b4cfb94aaa7f1f2401b8b481627a1c9f72605d9fb0809274bdab1dd -assets/assets/images/logo.png,1642165093192,46d074a42ae1f9059a9a7cd821e0322d3d235cfad11f234ab195ea4888c3d7f5 -assets/assets/images/logo.svg,1642165093192,7cf5f5af876af4468414504b4b4c3409d8db0d22c1d1f9bf288f11d01c33c902 -assets/fonts/MaterialIcons-Regular.otf,1615596762000,5f71a8843e4edc9656c39061c2232458a6fc77e1603305960e4efa9c77f8b7a2 -assets/packages/cupertino_icons/assets/CupertinoIcons.ttf,1639011803000,3064af137aeffc9011ba060601a01177b279963822310a778aeafa74c209732c -canvaskit/canvaskit.js,315439200000,332d67a51b86f5129fc7d929d6bb6bd0416b17fd853899efc1f5044770954ed6 -canvaskit/canvaskit.wasm,315439200000,762e8ec23b044aaf7e2afe995375fa038229c63fddc04b1a3109854d9f78d187 -canvaskit/profiling/canvaskit.js,315439200000,41ae97b4ac8a386f55b22f1962c7b564da96df256fd938d684e73a8061e70b61 -canvaskit/profiling/canvaskit.wasm,315439200000,cb4c2221f1c20811ac3a33666833b4458656193de55b276b3c8fc31856b2f3a0 -icons/Icon-192.png,1639011687000,d2e0131bb7851eb9d98f7885edb5ae4b4d6b7a6c7addf8a25b9b712b39274c0f -icons/Icon-512.png,1639011687000,7a31ce91e554f1941158ca46f31c7f3f2b7c8c129229ea74a8fae1affe335033 -icons/Icon-maskable-192.png,1639011703000,dd96c123fdf6817cdf7e63d9693bcc246bac2e3782a41a6952fa41c0617c5573 -icons/Icon-maskable-512.png,1639011703000,e7983524dc70254adc61764657d7e03d19284de8da586b5818d737bc08c6d14e -index.html,1642289710325,2e855649204f6c1701dc6e1cdaf0fb4cff49651a453b1e9b9f60afac610f0f12 -version.json,1642289710193,987d29d4db73292611b5cd11b219133aad0de1a0e5adf39d1c2301dfbe047053 -assets/AssetManifest.json,1642289710317,27c917a5c112db140de837c0bc7297d486b5689d077f19d60710bce221bd54ae -flutter_service_worker.js,1642289710644,86ceabb8dbec2c85655ea168988825fa5bc93e65fe6e5afe59bbef04df1e0843 -assets/FontManifest.json,1642289710317,9ea504185602e57d97b7c3517d382b8627a13c0181c490c96a9b55a5d5c8810c -assets/NOTICES,1642289710317,f2d7ef4214f50e12face36654f5239e3798c8ede2eaf0c6180e7a16cbb065f0b -main.dart.js,1642289709928,34efdbb00f862de5859badc0378bc648ba08ee1761ce7471c5a770715c1479c1 diff --git a/firebase.json b/firebase.json index 0d25a77..6603732 100644 --- a/firebase.json +++ b/firebase.json @@ -5,6 +5,12 @@ "firebase.json", "**/.*", "**/node_modules/**" + ], + "rewrites": [ + { + "source": "**", + "destination": "/index.html" + } ] } } diff --git a/lib/main.dart b/lib/main.dart index 91f84bd..619bcfd 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:firebase_core/firebase_core.dart'; -import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'ecommerce_website.dart'; import 'firebase_options.dart'; @@ -13,6 +12,5 @@ void main() async { options: DefaultFirebaseOptions.currentPlatform, ); setupLocator(); - await dotenv.load(fileName: ".env"); runApp(const EcommerceWebsite()); } diff --git a/lib/models/user/user_model.dart b/lib/models/user/user_model.dart index dd46ecc..b0b159b 100644 --- a/lib/models/user/user_model.dart +++ b/lib/models/user/user_model.dart @@ -12,9 +12,7 @@ class UserModel with _$UserModel { String? lastName, String? email, String? phoneNumber, - String? address, - String? city, - String? postalCode, + String? streetAddress, String? userOrdersUid, String? userCartUid, }) = _UserModel; diff --git a/lib/models/user/user_model.freezed.dart b/lib/models/user/user_model.freezed.dart index c51e162..01972ab 100644 --- a/lib/models/user/user_model.freezed.dart +++ b/lib/models/user/user_model.freezed.dart @@ -28,9 +28,7 @@ class _$UserModelTearOff { String? lastName, String? email, String? phoneNumber, - String? address, - String? city, - String? postalCode, + String? streetAddress, String? userOrdersUid, String? userCartUid}) { return _UserModel( @@ -39,9 +37,7 @@ class _$UserModelTearOff { lastName: lastName, email: email, phoneNumber: phoneNumber, - address: address, - city: city, - postalCode: postalCode, + streetAddress: streetAddress, userOrdersUid: userOrdersUid, userCartUid: userCartUid, ); @@ -62,9 +58,7 @@ mixin _$UserModel { String? get lastName => throw _privateConstructorUsedError; String? get email => throw _privateConstructorUsedError; String? get phoneNumber => throw _privateConstructorUsedError; - String? get address => throw _privateConstructorUsedError; - String? get city => throw _privateConstructorUsedError; - String? get postalCode => throw _privateConstructorUsedError; + String? get streetAddress => throw _privateConstructorUsedError; String? get userOrdersUid => throw _privateConstructorUsedError; String? get userCartUid => throw _privateConstructorUsedError; @@ -84,9 +78,7 @@ abstract class $UserModelCopyWith<$Res> { String? lastName, String? email, String? phoneNumber, - String? address, - String? city, - String? postalCode, + String? streetAddress, String? userOrdersUid, String? userCartUid}); } @@ -106,9 +98,7 @@ class _$UserModelCopyWithImpl<$Res> implements $UserModelCopyWith<$Res> { Object? lastName = freezed, Object? email = freezed, Object? phoneNumber = freezed, - Object? address = freezed, - Object? city = freezed, - Object? postalCode = freezed, + Object? streetAddress = freezed, Object? userOrdersUid = freezed, Object? userCartUid = freezed, }) { @@ -133,17 +123,9 @@ class _$UserModelCopyWithImpl<$Res> implements $UserModelCopyWith<$Res> { ? _value.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable as String?, - address: address == freezed - ? _value.address - : address // ignore: cast_nullable_to_non_nullable - as String?, - city: city == freezed - ? _value.city - : city // ignore: cast_nullable_to_non_nullable - as String?, - postalCode: postalCode == freezed - ? _value.postalCode - : postalCode // ignore: cast_nullable_to_non_nullable + streetAddress: streetAddress == freezed + ? _value.streetAddress + : streetAddress // ignore: cast_nullable_to_non_nullable as String?, userOrdersUid: userOrdersUid == freezed ? _value.userOrdersUid @@ -169,9 +151,7 @@ abstract class _$UserModelCopyWith<$Res> implements $UserModelCopyWith<$Res> { String? lastName, String? email, String? phoneNumber, - String? address, - String? city, - String? postalCode, + String? streetAddress, String? userOrdersUid, String? userCartUid}); } @@ -192,9 +172,7 @@ class __$UserModelCopyWithImpl<$Res> extends _$UserModelCopyWithImpl<$Res> Object? lastName = freezed, Object? email = freezed, Object? phoneNumber = freezed, - Object? address = freezed, - Object? city = freezed, - Object? postalCode = freezed, + Object? streetAddress = freezed, Object? userOrdersUid = freezed, Object? userCartUid = freezed, }) { @@ -219,17 +197,9 @@ class __$UserModelCopyWithImpl<$Res> extends _$UserModelCopyWithImpl<$Res> ? _value.phoneNumber : phoneNumber // ignore: cast_nullable_to_non_nullable as String?, - address: address == freezed - ? _value.address - : address // ignore: cast_nullable_to_non_nullable - as String?, - city: city == freezed - ? _value.city - : city // ignore: cast_nullable_to_non_nullable - as String?, - postalCode: postalCode == freezed - ? _value.postalCode - : postalCode // ignore: cast_nullable_to_non_nullable + streetAddress: streetAddress == freezed + ? _value.streetAddress + : streetAddress // ignore: cast_nullable_to_non_nullable as String?, userOrdersUid: userOrdersUid == freezed ? _value.userOrdersUid @@ -253,9 +223,7 @@ class _$_UserModel implements _UserModel { this.lastName, this.email, this.phoneNumber, - this.address, - this.city, - this.postalCode, + this.streetAddress, this.userOrdersUid, this.userCartUid}); @@ -273,11 +241,7 @@ class _$_UserModel implements _UserModel { @override final String? phoneNumber; @override - final String? address; - @override - final String? city; - @override - final String? postalCode; + final String? streetAddress; @override final String? userOrdersUid; @override @@ -285,7 +249,7 @@ class _$_UserModel implements _UserModel { @override String toString() { - return 'UserModel(uid: $uid, firstName: $firstName, lastName: $lastName, email: $email, phoneNumber: $phoneNumber, address: $address, city: $city, postalCode: $postalCode, userOrdersUid: $userOrdersUid, userCartUid: $userCartUid)'; + return 'UserModel(uid: $uid, firstName: $firstName, lastName: $lastName, email: $email, phoneNumber: $phoneNumber, streetAddress: $streetAddress, userOrdersUid: $userOrdersUid, userCartUid: $userCartUid)'; } @override @@ -299,10 +263,8 @@ class _$_UserModel implements _UserModel { const DeepCollectionEquality().equals(other.email, email) && const DeepCollectionEquality() .equals(other.phoneNumber, phoneNumber) && - const DeepCollectionEquality().equals(other.address, address) && - const DeepCollectionEquality().equals(other.city, city) && const DeepCollectionEquality() - .equals(other.postalCode, postalCode) && + .equals(other.streetAddress, streetAddress) && const DeepCollectionEquality() .equals(other.userOrdersUid, userOrdersUid) && const DeepCollectionEquality() @@ -317,9 +279,7 @@ class _$_UserModel implements _UserModel { const DeepCollectionEquality().hash(lastName), const DeepCollectionEquality().hash(email), const DeepCollectionEquality().hash(phoneNumber), - const DeepCollectionEquality().hash(address), - const DeepCollectionEquality().hash(city), - const DeepCollectionEquality().hash(postalCode), + const DeepCollectionEquality().hash(streetAddress), const DeepCollectionEquality().hash(userOrdersUid), const DeepCollectionEquality().hash(userCartUid)); @@ -341,9 +301,7 @@ abstract class _UserModel implements UserModel { String? lastName, String? email, String? phoneNumber, - String? address, - String? city, - String? postalCode, + String? streetAddress, String? userOrdersUid, String? userCartUid}) = _$_UserModel; @@ -361,11 +319,7 @@ abstract class _UserModel implements UserModel { @override String? get phoneNumber; @override - String? get address; - @override - String? get city; - @override - String? get postalCode; + String? get streetAddress; @override String? get userOrdersUid; @override diff --git a/lib/models/user/user_model.g.dart b/lib/models/user/user_model.g.dart index 783b1e9..61d15d5 100644 --- a/lib/models/user/user_model.g.dart +++ b/lib/models/user/user_model.g.dart @@ -12,9 +12,7 @@ _$_UserModel _$$_UserModelFromJson(Map json) => _$_UserModel( lastName: json['lastName'] as String?, email: json['email'] as String?, phoneNumber: json['phoneNumber'] as String?, - address: json['address'] as String?, - city: json['city'] as String?, - postalCode: json['postalCode'] as String?, + streetAddress: json['streetAddress'] as String?, userOrdersUid: json['userOrdersUid'] as String?, userCartUid: json['userCartUid'] as String?, ); @@ -26,9 +24,7 @@ Map _$$_UserModelToJson(_$_UserModel instance) => 'lastName': instance.lastName, 'email': instance.email, 'phoneNumber': instance.phoneNumber, - 'address': instance.address, - 'city': instance.city, - 'postalCode': instance.postalCode, + 'streetAddress': instance.streetAddress, 'userOrdersUid': instance.userOrdersUid, 'userCartUid': instance.userCartUid, }; diff --git a/lib/services/authentication_service.dart b/lib/services/authentication_service.dart index 840d7bf..4c27a8b 100644 --- a/lib/services/authentication_service.dart +++ b/lib/services/authentication_service.dart @@ -1,7 +1,6 @@ import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/foundation.dart'; -import '../models/user/user_model.dart'; import 'firestore_service.dart'; class AuthenticationService { @@ -30,14 +29,27 @@ class AuthenticationService { Future signUpWithEmailAndPassword({ required String email, required String password, + required String firstName, + required String lastName, + required String phoneNumber, + required String streetAddress, + required String city, + required String postalCode, }) async { try { var authResult = await _auth.createUserWithEmailAndPassword( email: email, password: password, ); - await FirestoreService(uid: authResult.user!.uid) - .updateUserData(UserModel()); + await FirestoreService().updateUserData( + email: email, + firstName: firstName, + lastName: lastName, + phoneNumber: phoneNumber, + streetAddress: streetAddress, + city: city, + postalCode: postalCode, + ); return authResult.user != null; } catch (e) { return e.toString(); diff --git a/lib/services/firestore_service.dart b/lib/services/firestore_service.dart index 7541bf2..e97c7d6 100644 --- a/lib/services/firestore_service.dart +++ b/lib/services/firestore_service.dart @@ -1,5 +1,4 @@ import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:flutter_ecommerce_website_demo/models/user/user_model.dart'; class FirestoreService { String? uid; @@ -19,8 +18,24 @@ class FirestoreService { FirebaseFirestore.instance.collection('userOrders'); // Future - Update User Data - Future updateUserData(UserModel userModel) { - return userCollection.doc(uid).set(userModel.toJson()); + Future updateUserData({ + required String email, + required String firstName, + required String lastName, + required String phoneNumber, + required String streetAddress, + required String city, + required String postalCode, + }) async { + return userCollection.doc(uid).set({ + email: email, + firstName: firstName, + lastName: lastName, + phoneNumber: phoneNumber, + streetAddress: streetAddress, + city: city, + postalCode: postalCode, + }); } // Stream - Get User Data @@ -29,7 +44,7 @@ class FirestoreService { } // Stream - Get Phone Data - Stream> get phones { + Stream> get phones { return phonesCollection.snapshots(); } } diff --git a/lib/shared/validators.dart b/lib/shared/validators.dart index 41ab3c1..ac663c3 100644 --- a/lib/shared/validators.dart +++ b/lib/shared/validators.dart @@ -37,4 +37,57 @@ class Validators { } return null; } + + String? validateStreetAddress(String? value) { + if (value == null) return 'Address is required'; + if (value.isEmpty) return 'Address is required'; + return null; + } + + String? validatePostalCode(String? value) { + if (value == null) return 'Postcode is required'; + if (value.isEmpty) return 'Postcode is required'; + // check if postal code is 5 numeric characters long + if (!RegExp(r'^[0-9]{5}$').hasMatch(value)) { + return 'Postal code must be 5 digits long'; + } + return null; + } + + String? validateCity(String? value) { + if (value == null) return 'City is required'; + if (value.isEmpty) return 'City is required'; + if (!RegExp(r'^[a-zA-Z ]+$').hasMatch(value)) { + return 'City must be alphabetic'; + } + if (value.length < 2) { + return 'City must be at least 2 characters long'; + } + return null; + } + + String? validatePhoneNumber(String? value) { + if (value == null) return 'Phone number is required'; + if (value.isEmpty) return 'Phone number is required'; + if (!RegExp(r'^[0-9]{10}$').hasMatch(value)) { + return 'Phone number must be 10 digits long'; + } + return null; + } + + String? validateFirstName(String? value) { + if (value == null) return 'First name is required'; + if (value.isEmpty) return 'First name is required'; + if (value.length < 2) { + return 'First name must be at least 2 characters long'; + } + return null; + } + + String? validateLastName(String? value) { + if (value == null) return 'Last name is required'; + if (value.isEmpty) return 'Last name is required'; + if (value.length < 2) return 'Last name must be at least 2 characters long'; + return null; + } } diff --git a/lib/view_models/sign_up/sign_up_view_model.dart b/lib/view_models/sign_up/sign_up_view_model.dart index 4b93da3..44b50ad 100644 --- a/lib/view_models/sign_up/sign_up_view_model.dart +++ b/lib/view_models/sign_up/sign_up_view_model.dart @@ -16,14 +16,24 @@ class SignUpViewModel extends BaseViewModel with Validators { required String email, required String password, required String confirmPassword, + required String firstName, + required String lastName, + required String phoneNumber, + required String streetAddress, + required String postalCode, + required String city, }) async { if (validateEmail(email) != null || validatePassword(password) != null || - validatePassword(confirmPassword) != null) { + validatePassword(confirmPassword) != null || + validateFirstName(firstName) != null || + validateLastName(lastName) != null || + validatePhoneNumber(phoneNumber) != null || + validateStreetAddress(streetAddress) != null) { _dialogService.showDialog( title: 'Invalid Details', description: - '${validateEmail(email) ?? validatePassword(password) ?? validatePassword(confirmPassword)}', + '${validateEmail(email) ?? validatePassword(password) ?? validatePassword(confirmPassword) ?? validateFirstName(firstName) ?? validateLastName(lastName) ?? validatePhoneNumber(phoneNumber) ?? validateStreetAddress(streetAddress) ?? validatePostalCode(postalCode) ?? validateCity(city)}', ); } else if (password != confirmPassword) { _dialogService.showDialog( @@ -35,6 +45,12 @@ class SignUpViewModel extends BaseViewModel with Validators { var result = await _authService.signUpWithEmailAndPassword( email: email, password: password, + firstName: firstName, + lastName: lastName, + phoneNumber: phoneNumber, + streetAddress: streetAddress, + city: city, + postalCode: postalCode, ); setBusy(false); if (result is bool) { @@ -51,7 +67,7 @@ class SignUpViewModel extends BaseViewModel with Validators { title: 'Sign Up Failure', description: result .toString() - .substring(result.toString().indexOf(' ', 1) + 1), + // .substring(result.toString().indexOf(' ', 1) + 1), ); } } diff --git a/lib/views/dialog_manager.dart b/lib/views/dialog_manager.dart index f561cc1..8149464 100644 --- a/lib/views/dialog_manager.dart +++ b/lib/views/dialog_manager.dart @@ -35,8 +35,8 @@ class _DialogManagerState extends State { showDialog( context: context, builder: (context) => AlertDialog( - title: Text(request.title), - content: Text(request.description), + title: SelectableText(request.title), + content: SelectableText(request.description), actions: [ if (isConfirmationDialog) TextButton( diff --git a/lib/views/sign_up/sign_up_view.dart b/lib/views/sign_up/sign_up_view.dart index 2448120..c16962b 100644 --- a/lib/views/sign_up/sign_up_view.dart +++ b/lib/views/sign_up/sign_up_view.dart @@ -19,6 +19,12 @@ class _SignUpViewState extends State { final _emailController = TextEditingController(); final _passwordController = TextEditingController(); final _confirmPasswordController = TextEditingController(); + final _firstNameController = TextEditingController(); + final _lastNameController = TextEditingController(); + final _phoneNumbercontroller = TextEditingController(); + final _streetAddressController = TextEditingController(); + final _cityController = TextEditingController(); + final _postalCodeController = TextEditingController(); @override Widget build(BuildContext context) { @@ -26,56 +32,109 @@ class _SignUpViewState extends State { viewModelBuilder: () => SignUpViewModel(), builder: (context, model, child) => Form( key: locator().signUpFormKey, - child: Column( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - verticalSpaceLarge, - Text( - 'Sign Up', - style: Theme.of(context).textTheme.headline3, - ), - verticalSpaceMedium, - CustomTextFormField( - labelText: 'Email', - controller: _emailController, - keyboardType: TextInputType.emailAddress, - validator: model.validateEmail, - ), - verticalSpaceSmall, - CustomTextFormField( - labelText: 'Password', - controller: _passwordController, - keyboardType: TextInputType.visiblePassword, - validator: model.validatePassword, - isPasswordField: true, - ), - verticalSpaceSmall, - CustomTextFormField( - labelText: 'Confirm Password', - controller: _confirmPasswordController, - keyboardType: TextInputType.visiblePassword, - validator: (value) => model.validateConfirmPassword( - value, - _passwordController.text, + child: SingleChildScrollView( + padding: const EdgeInsets.symmetric(horizontal: 6), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + verticalSpaceLarge, + Text( + 'Sign Up', + style: Theme.of(context).textTheme.headline3, ), - isPasswordField: true, - ), - verticalSpaceMedium, - BusyButton( - title: 'Sign Up', - busy: model.isBusy, - onPressed: () { - model.signUp( - email: _emailController.text, - password: _passwordController.text, - confirmPassword: _confirmPasswordController.text, - ); - }, - ), - verticalSpaceLarge, - ], + verticalSpaceMedium, + CustomTextFormField( + labelText: 'Email', + controller: _emailController, + keyboardType: TextInputType.emailAddress, + validator: model.validateEmail, + ), + verticalSpaceSmall, + CustomTextFormField( + labelText: 'Password', + controller: _passwordController, + keyboardType: TextInputType.visiblePassword, + validator: model.validatePassword, + isPasswordField: true, + ), + verticalSpaceSmall, + CustomTextFormField( + labelText: 'Confirm Password', + controller: _confirmPasswordController, + keyboardType: TextInputType.visiblePassword, + validator: (value) => model.validateConfirmPassword( + value, + _passwordController.text, + ), + isPasswordField: true, + ), + verticalSpaceSmall, + // first name custom text form field + CustomTextFormField( + labelText: 'First Name', + controller: _firstNameController, + validator: model.validateFirstName, + keyboardType: TextInputType.name, + ), + verticalSpaceSmall, + // last name custom text form field + CustomTextFormField( + labelText: 'Last Name', + controller: _lastNameController, + validator: model.validateLastName, + keyboardType: TextInputType.name, + ), + verticalSpaceSmall, + CustomTextFormField( + labelText: 'Phone Number', + controller: _phoneNumbercontroller, + keyboardType: TextInputType.phone, + validator: model.validatePhoneNumber, + ), + verticalSpaceSmall, + CustomTextFormField( + labelText: 'Street address', + controller: _streetAddressController, + keyboardType: TextInputType.streetAddress, + validator: model.validateStreetAddress, + ), + verticalSpaceSmall, + CustomTextFormField( + labelText: 'Postal Code', + controller: _postalCodeController, + keyboardType: TextInputType.phone, + validator: model.validatePostalCode, + ), + verticalSpaceSmall, + CustomTextFormField( + labelText: 'City', + controller: _cityController, + keyboardType: TextInputType.text, + validator: model.validateCity, + ), + verticalSpaceMedium, + BusyButton( + title: 'Sign Up', + busy: model.isBusy, + onPressed: () { + model.signUp( + email: _emailController.text, + password: _passwordController.text, + confirmPassword: _confirmPasswordController.text, + firstName: _firstNameController.text, + lastName: _lastNameController.text, + phoneNumber: _phoneNumbercontroller.text, + streetAddress: _streetAddressController.text, + city: _cityController.text, + postalCode: _postalCodeController.text, + ); + }, + ), + verticalSpaceLarge, + ], + ), ), ), ); diff --git a/lib/views/sign_up/widgets/custom_text_form_field.dart b/lib/views/sign_up/widgets/custom_text_form_field.dart index 92aba5d..0d7faab 100644 --- a/lib/views/sign_up/widgets/custom_text_form_field.dart +++ b/lib/views/sign_up/widgets/custom_text_form_field.dart @@ -7,15 +7,17 @@ class CustomTextFormField extends StatefulWidget { final TextEditingController controller; final TextInputType keyboardType; final String? Function(String?)? validator; + final Function(String?)? onChanged; const CustomTextFormField({ Key? key, + this.isPasswordField = false, + this.obscureText = false, required this.labelText, required this.controller, required this.keyboardType, - this.isPasswordField = false, - this.obscureText = false, required this.validator, + this.onChanged, }) : super(key: key); @override @@ -27,19 +29,45 @@ class _CustomTextFormFieldState extends State { @override Widget build(BuildContext context) { return TextFormField( + onChanged: widget.onChanged, keyboardType: widget.isPasswordField ? TextInputType.visiblePassword : widget.keyboardType, controller: widget.controller, + cursorColor: Colors.orange, decoration: InputDecoration( - border: OutlineInputBorder( + focusedErrorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide( + color: Colors.red, + width: 3, + ), + ), + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide( + color: Colors.red, + width: 3, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide( + color: Colors.orange, + width: 3, + ), + ), + enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), + borderSide: const BorderSide( + color: Colors.grey, + width: 3, + ), ), labelText: widget.labelText, errorMaxLines: 3, suffixIcon: widget.obscureText || widget.isPasswordField ? IconButton( - tooltip: _obscureText ? 'Show Password' : 'Hide Password', icon: Icon( _obscureText ? Icons.visibility : Icons.visibility_off, ), @@ -47,7 +75,8 @@ class _CustomTextFormFieldState extends State { setState(() { _obscureText = !_obscureText; }); - }) + }, + ) : null, ), obscureText: diff --git a/pubspec.lock b/pubspec.lock index eb9b564..af928a9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -211,13 +211,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.1" - eventify: - dependency: "direct main" - description: - name: eventify - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" fake_async: dependency: transitive description: @@ -293,13 +286,6 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_dotenv: - dependency: "direct main" - description: - name: flutter_dotenv - url: "https://pub.dartlang.org" - source: hosted - version: "5.0.2" flutter_lints: dependency: "direct dev" description: @@ -307,18 +293,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.4" - flutter_localizations: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - flutter_styled_toast: - dependency: "direct main" - description: - name: flutter_styled_toast - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" flutter_svg: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 4a2494f..432b207 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -32,13 +32,10 @@ dependencies: colorful_safe_area: ^0.3.0 cupertino_icons: ^1.0.4 email_validator: ^2.0.1 - eventify: ^1.0.0 firebase_auth: ^3.3.5 firebase_core: ^1.11.0 flutter: sdk: flutter - flutter_dotenv: ^5.0.2 - flutter_styled_toast: ^2.0.0 flutter_svg: ^1.0.1 get_it: ^7.2.0 google_fonts: ^2.2.0 @@ -70,7 +67,6 @@ flutter: assets: - assets/images/logo.png - assets/images/logo.svg - - .env # - images/a_dot_ham.jpeg # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware.