From 689cf29eabe4d1f6f79dca023c2b452e61ff1eb4 Mon Sep 17 00:00:00 2001 From: jahongireshonqulov Date: Fri, 31 Oct 2025 19:27:21 +0500 Subject: [PATCH] feat: login page ui done --- assets/icons/common/ic_login.svg | 261 ++++++++++++++++++ assets/icons/common/ic_visibility.svg | 8 + assets/icons/common/ic_visibility_off.svg | 17 ++ assets/icons/dark/ic_arrow_left.svg | 6 + assets/icons/light/ic_arrow_left.svg | 4 + assets/translations/app_en.arb | 22 +- assets/translations/app_ru.arb | 22 +- assets/translations/app_uz.arb | 22 +- lib/core/constants/app_locale_keys.dart | 2 + lib/core/l10n/app_localizations.dart | 78 ++++++ lib/core/l10n/app_localizations_en.dart | 41 +++ lib/core/l10n/app_localizations_ru.dart | 41 +++ lib/core/l10n/app_localizations_uz.dart | 41 +++ lib/core/router/app_routes.dart | 6 + lib/core/theme/app_colors.dart | 6 +- lib/core/theme/app_icons.dart | 7 +- lib/core/theme/app_theme_colors.dart | 38 ++- lib/core/theme/app_theme_textstyles.dart | 12 + lib/core/theme/theme_icons.dart | 23 +- lib/core/utils/app_utils.dart | 6 + .../presentation/login_page/login_page.dart | 15 + .../login_page/widgets/login_body.dart | 155 +++++++++++ .../login_page/widgets/welcome_text.dart | 52 ++++ lib/feature/common/common.dart | 2 +- .../presentation/widgets/app_button.dart | 4 +- .../widgets/app_text_form_field.dart | 145 ++++++---- .../presentation/widgets/w_back_button.dart | 31 +++ .../common/presentation/widgets/widgets.dart | 1 + .../onboarding_page/onboarding_page.dart | 5 +- .../pages/splash_page/splash_page.dart | 8 +- lib/main.dart | 4 +- 31 files changed, 992 insertions(+), 93 deletions(-) create mode 100644 assets/icons/common/ic_login.svg create mode 100644 assets/icons/common/ic_visibility.svg create mode 100644 assets/icons/common/ic_visibility_off.svg create mode 100644 assets/icons/dark/ic_arrow_left.svg create mode 100644 assets/icons/light/ic_arrow_left.svg create mode 100644 lib/feature/auth/presentation/login_page/login_page.dart create mode 100644 lib/feature/auth/presentation/login_page/widgets/login_body.dart create mode 100644 lib/feature/auth/presentation/login_page/widgets/welcome_text.dart create mode 100644 lib/feature/common/presentation/widgets/w_back_button.dart diff --git a/assets/icons/common/ic_login.svg b/assets/icons/common/ic_login.svg new file mode 100644 index 0000000..90b1e31 --- /dev/null +++ b/assets/icons/common/ic_login.svg @@ -0,0 +1,261 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/common/ic_visibility.svg b/assets/icons/common/ic_visibility.svg new file mode 100644 index 0000000..392a305 --- /dev/null +++ b/assets/icons/common/ic_visibility.svg @@ -0,0 +1,8 @@ + + + + diff --git a/assets/icons/common/ic_visibility_off.svg b/assets/icons/common/ic_visibility_off.svg new file mode 100644 index 0000000..c2b6a89 --- /dev/null +++ b/assets/icons/common/ic_visibility_off.svg @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/assets/icons/dark/ic_arrow_left.svg b/assets/icons/dark/ic_arrow_left.svg new file mode 100644 index 0000000..e5fd83d --- /dev/null +++ b/assets/icons/dark/ic_arrow_left.svg @@ -0,0 +1,6 @@ + + + + diff --git a/assets/icons/light/ic_arrow_left.svg b/assets/icons/light/ic_arrow_left.svg new file mode 100644 index 0000000..ee6e240 --- /dev/null +++ b/assets/icons/light/ic_arrow_left.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/translations/app_en.arb b/assets/translations/app_en.arb index 9dc6d1f..a61ba64 100644 --- a/assets/translations/app_en.arb +++ b/assets/translations/app_en.arb @@ -10,6 +10,26 @@ "onboarding_button_next": "Next", "onboarding_title_2": "A place for extraordinary people in the world", "onboarding_subtitle_2": "Discover your favorite meals and get them delivered fast wherever you are.", - "onboarding_button_get_started": "Get Started" + "onboarding_button_get_started": "Get Started", + "welcome_to_volt": "Welcome to {name}", + "@welcome_to_volt":{ + "placeholders": { + "name": { + "type": "String" + } + } + }, + "please_login": "Please login to your account", + "email_or_phone": "Phone Number", + "enter_email_or_phone": "Enter your email or phone number", + "password": "Password", + "enter_password": "Enter your password", + "forgot_password": "Forgot Password?", + "login": "Login", + "or_login_with": "Or login with", + "google": "Google", + "facebook": "Facebook", + "dont_have_account": "Don’t have an account?", + "register": "Register" } \ No newline at end of file diff --git a/assets/translations/app_ru.arb b/assets/translations/app_ru.arb index 9e65f15..db87340 100644 --- a/assets/translations/app_ru.arb +++ b/assets/translations/app_ru.arb @@ -10,6 +10,26 @@ "onboarding_button_next": "Далее", "onboarding_title_2": "Место для выдающихся людей по всему миру", "onboarding_subtitle_2": "Находите свои любимые блюда и получайте их быстро, где бы вы ни находились.", - "onboarding_button_get_started": "Начать" + "onboarding_button_get_started": "Начать", + "welcome_to_volt": "Добро пожаловать в {name}", + "@welcome_to_volt":{ + "placeholders": { + "name": { + "type": "String" + } + } + }, + "please_login": "Пожалуйста, войдите в свой аккаунт", + "email_or_phone": "Номер телефона", + "enter_email_or_phone": "Введите свою почту или номер телефона", + "password": "Пароль", + "enter_password": "Введите свой пароль", + "forgot_password": "Забыли пароль?", + "login": "Войти", + "or_login_with": "Или войдите с помощью", + "google": "Google", + "facebook": "Facebook", + "dont_have_account": "У вас нет аккаунта?", + "register": "Зарегистрироваться" } \ No newline at end of file diff --git a/assets/translations/app_uz.arb b/assets/translations/app_uz.arb index 3920426..3f03d6e 100644 --- a/assets/translations/app_uz.arb +++ b/assets/translations/app_uz.arb @@ -10,6 +10,26 @@ "onboarding_button_next": "Keyingi", "onboarding_title_2": "Butun dunyodagi ajoyib insonlar uchun joy", "onboarding_subtitle_2": "Sevimli taomlaringizni toping va ularni tezda yetkazib oling, qaerda bo‘lishingizdan qat’i nazar.", - "onboarding_button_get_started": "Boshlash" + "onboarding_button_get_started": "Boshlash", + "welcome_to_volt": "{name} ilovasiga xush kelibsiz", + "@welcome_to_volt":{ + "placeholders": { + "name": { + "type": "String" + } + } + }, + "please_login": "Iltimos, akkauntingizga kiring", + "email_or_phone": "Telefon raqami", + "enter_email_or_phone": "Email yoki telefon raqamingizni kiriting", + "password": "Parol", + "enter_password": "Parolingizni kiriting", + "forgot_password": "Parolni unutdingizmi?", + "login": "Kirish", + "or_login_with": "Yoki quyidagi orqali kiring", + "google": "Google", + "facebook": "Facebook", + "dont_have_account": "Akkauntingiz yo‘qmi?", + "register": "Ro‘yxatdan o‘tish" } \ No newline at end of file diff --git a/lib/core/constants/app_locale_keys.dart b/lib/core/constants/app_locale_keys.dart index 99acccd..66647e9 100644 --- a/lib/core/constants/app_locale_keys.dart +++ b/lib/core/constants/app_locale_keys.dart @@ -4,6 +4,8 @@ abstract class AppLocaleKeys { static const String browseSearchHistory = 'browse-search-history'; static const String token = 'token'; + static const String appName = "Felix Eats"; + static const String fontBlack = "fontBlack"; static const String fontBold = "fontBold"; static const String fontSemiBold = "fontSemiBold"; diff --git a/lib/core/l10n/app_localizations.dart b/lib/core/l10n/app_localizations.dart index c764e5b..c8a8822 100644 --- a/lib/core/l10n/app_localizations.dart +++ b/lib/core/l10n/app_localizations.dart @@ -171,6 +171,84 @@ abstract class AppLocalizations { /// In en, this message translates to: /// **'Get Started'** String get onboarding_button_get_started; + + /// No description provided for @welcome_to_volt. + /// + /// In en, this message translates to: + /// **'Welcome to {name}'** + String welcome_to_volt(String name); + + /// No description provided for @please_login. + /// + /// In en, this message translates to: + /// **'Please login to your account'** + String get please_login; + + /// No description provided for @email_or_phone. + /// + /// In en, this message translates to: + /// **'Phone Number'** + String get email_or_phone; + + /// No description provided for @enter_email_or_phone. + /// + /// In en, this message translates to: + /// **'Enter your email or phone number'** + String get enter_email_or_phone; + + /// No description provided for @password. + /// + /// In en, this message translates to: + /// **'Password'** + String get password; + + /// No description provided for @enter_password. + /// + /// In en, this message translates to: + /// **'Enter your password'** + String get enter_password; + + /// No description provided for @forgot_password. + /// + /// In en, this message translates to: + /// **'Forgot Password?'** + String get forgot_password; + + /// No description provided for @login. + /// + /// In en, this message translates to: + /// **'Login'** + String get login; + + /// No description provided for @or_login_with. + /// + /// In en, this message translates to: + /// **'Or login with'** + String get or_login_with; + + /// No description provided for @google. + /// + /// In en, this message translates to: + /// **'Google'** + String get google; + + /// No description provided for @facebook. + /// + /// In en, this message translates to: + /// **'Facebook'** + String get facebook; + + /// No description provided for @dont_have_account. + /// + /// In en, this message translates to: + /// **'Don’t have an account?'** + String get dont_have_account; + + /// No description provided for @register. + /// + /// In en, this message translates to: + /// **'Register'** + String get register; } class _AppLocalizationsDelegate diff --git a/lib/core/l10n/app_localizations_en.dart b/lib/core/l10n/app_localizations_en.dart index dc76b68..9ec64b8 100644 --- a/lib/core/l10n/app_localizations_en.dart +++ b/lib/core/l10n/app_localizations_en.dart @@ -49,4 +49,45 @@ class AppLocalizationsEn extends AppLocalizations { @override String get onboarding_button_get_started => 'Get Started'; + + @override + String welcome_to_volt(String name) { + return 'Welcome to $name'; + } + + @override + String get please_login => 'Please login to your account'; + + @override + String get email_or_phone => 'Phone Number'; + + @override + String get enter_email_or_phone => 'Enter your email or phone number'; + + @override + String get password => 'Password'; + + @override + String get enter_password => 'Enter your password'; + + @override + String get forgot_password => 'Forgot Password?'; + + @override + String get login => 'Login'; + + @override + String get or_login_with => 'Or login with'; + + @override + String get google => 'Google'; + + @override + String get facebook => 'Facebook'; + + @override + String get dont_have_account => 'Don’t have an account?'; + + @override + String get register => 'Register'; } diff --git a/lib/core/l10n/app_localizations_ru.dart b/lib/core/l10n/app_localizations_ru.dart index 28df034..3e60d40 100644 --- a/lib/core/l10n/app_localizations_ru.dart +++ b/lib/core/l10n/app_localizations_ru.dart @@ -47,4 +47,45 @@ class AppLocalizationsRu extends AppLocalizations { @override String get onboarding_button_get_started => 'Начать'; + + @override + String welcome_to_volt(String name) { + return 'Добро пожаловать в $name'; + } + + @override + String get please_login => 'Пожалуйста, войдите в свой аккаунт'; + + @override + String get email_or_phone => 'Номер телефона'; + + @override + String get enter_email_or_phone => 'Введите свою почту или номер телефона'; + + @override + String get password => 'Пароль'; + + @override + String get enter_password => 'Введите свой пароль'; + + @override + String get forgot_password => 'Забыли пароль?'; + + @override + String get login => 'Войти'; + + @override + String get or_login_with => 'Или войдите с помощью'; + + @override + String get google => 'Google'; + + @override + String get facebook => 'Facebook'; + + @override + String get dont_have_account => 'У вас нет аккаунта?'; + + @override + String get register => 'Зарегистрироваться'; } diff --git a/lib/core/l10n/app_localizations_uz.dart b/lib/core/l10n/app_localizations_uz.dart index eda4f42..8cbfd9b 100644 --- a/lib/core/l10n/app_localizations_uz.dart +++ b/lib/core/l10n/app_localizations_uz.dart @@ -47,4 +47,45 @@ class AppLocalizationsUz extends AppLocalizations { @override String get onboarding_button_get_started => 'Boshlash'; + + @override + String welcome_to_volt(String name) { + return '$name ilovasiga xush kelibsiz'; + } + + @override + String get please_login => 'Iltimos, akkauntingizga kiring'; + + @override + String get email_or_phone => 'Telefon raqami'; + + @override + String get enter_email_or_phone => 'Email yoki telefon raqamingizni kiriting'; + + @override + String get password => 'Parol'; + + @override + String get enter_password => 'Parolingizni kiriting'; + + @override + String get forgot_password => 'Parolni unutdingizmi?'; + + @override + String get login => 'Kirish'; + + @override + String get or_login_with => 'Yoki quyidagi orqali kiring'; + + @override + String get google => 'Google'; + + @override + String get facebook => 'Facebook'; + + @override + String get dont_have_account => 'Akkauntingiz yo‘qmi?'; + + @override + String get register => 'Ro‘yxatdan o‘tish'; } diff --git a/lib/core/router/app_routes.dart b/lib/core/router/app_routes.dart index 1e415f3..a73006f 100644 --- a/lib/core/router/app_routes.dart +++ b/lib/core/router/app_routes.dart @@ -1,4 +1,5 @@ import 'package:flutter/cupertino.dart'; +import 'package:food_delivery_client/feature/auth/presentation/login_page/login_page.dart'; import 'package:food_delivery_client/feature/onboarding/presentation/pages/onboarding_page/onboarding_page.dart'; import 'package:food_delivery_client/feature/onboarding/presentation/pages/splash_page/splash_page.dart'; @@ -20,6 +21,11 @@ class AppRoutes { path: Routes.onBoarding, pageBuilder: (context, state) => CupertinoPage(child: OnboardingPage()), ), + + GoRoute( + path: Routes.login, + pageBuilder: (context, state) => CupertinoPage(child: LoginPage()), + ), ], ); } diff --git a/lib/core/theme/app_colors.dart b/lib/core/theme/app_colors.dart index b5bb16c..3aa4a5b 100644 --- a/lib/core/theme/app_colors.dart +++ b/lib/core/theme/app_colors.dart @@ -50,7 +50,9 @@ abstract class AppColors { static const Color cFFAB40 = Color(0xFFFFAB40); static const Color cD6D4D4 = Color(0xFFD6D4D4); static const Color c1A202C = Color(0xFF1A202C); - static const Color c524242 = Color(0xFF524242 ); - + static const Color c524242 = Color(0xFF524242); + static const Color cE2E4EA = Color(0xFFE2E4EA); + static const Color cA7AEC1 = Color(0xFFA7AEC1); + static const Color c151B33 = Color(0xFF151B33); } diff --git a/lib/core/theme/app_icons.dart b/lib/core/theme/app_icons.dart index 30bcc16..241b93a 100644 --- a/lib/core/theme/app_icons.dart +++ b/lib/core/theme/app_icons.dart @@ -4,15 +4,20 @@ abstract class AppIcons { static const String icOnBoarding1 = "$baseUrl/ic_onboarding1.svg"; static const String icOnBoarding2 = "$baseUrl/ic_onboarding2.svg"; static const String icOnBoarding3 = "$baseUrl/ic_onboarding3.svg"; + static const String icLogin = "$baseUrl/ic_login.svg"; + static const String icVisibility = "$baseUrl/ic_visibility.svg"; + static const String icVisibilityOff = "$baseUrl/ic_visibility_off.svg"; + } abstract class AppLightSvgs { static const String baseUrl = "assets/icons/light"; - static const String icSplash = "$baseUrl/ic_splash.svg"; + static const String icArrowLeft = "$baseUrl/ic_arrow_left.svg"; } abstract class AppDarkSvgs { static const String baseUrl = "assets/icons/dark"; static const String icSplash = "$baseUrl/ic_splash.svg"; + static const String icArrowLeft = "$baseUrl/ic_arrow_left.svg"; } diff --git a/lib/core/theme/app_theme_colors.dart b/lib/core/theme/app_theme_colors.dart index 86b1a97..a456cb8 100644 --- a/lib/core/theme/app_theme_colors.dart +++ b/lib/core/theme/app_theme_colors.dart @@ -4,35 +4,57 @@ import 'package:food_delivery_client/food_delivery_client.dart'; class AppThemeColors extends ThemeExtension { final Color onBoardingColor; final Color boxShadow; + final Color iconColor; + final Color buttonInactiveColor; + final Color borderColor; - AppThemeColors({required this.onBoardingColor, required this.boxShadow}); + + AppThemeColors({ + required this.onBoardingColor, + required this.boxShadow, + required this.iconColor, + required this.buttonInactiveColor, + required this.borderColor + }); static AppThemeColors light = AppThemeColors( - onBoardingColor: AppColors.cFFFFFF, - boxShadow: AppColors.cD6D4D4, + onBoardingColor: AppColors.cFFFFFF, + boxShadow: AppColors.cD6D4D4, + buttonInactiveColor: AppColors.cE2E4EA, + iconColor: AppColors.cFFFFFF, + borderColor:AppColors.cE2E4EA + ); static AppThemeColors dark = AppThemeColors( - onBoardingColor: AppColors.c131720, - boxShadow: AppColors.c524242, + onBoardingColor: AppColors.c131720, + boxShadow: AppColors.c524242, + buttonInactiveColor: AppColors.c292F3D, + iconColor: AppColors.c131720, + borderColor: AppColors.c292F3D ); @override ThemeExtension copyWith({ Color? onBoardingColor, Color? boxShadow, + Color? iconColor, + Color? buttonInactiveColor, + Color? borderColor }) { return AppThemeColors( onBoardingColor: onBoardingColor ?? this.onBoardingColor, boxShadow: boxShadow ?? this.boxShadow, + iconColor: iconColor ?? this.iconColor, + buttonInactiveColor: buttonInactiveColor ?? this.buttonInactiveColor, + borderColor: borderColor??this.borderColor ); } @override ThemeExtension lerp( - covariant ThemeExtension? other, - double t, - ) { + covariant ThemeExtension? other, + double t,) { if (other is! AppThemeColors) return this; return t < 0.5 ? this : other; } diff --git a/lib/core/theme/app_theme_textstyles.dart b/lib/core/theme/app_theme_textstyles.dart index 0bbfa39..453d790 100644 --- a/lib/core/theme/app_theme_textstyles.dart +++ b/lib/core/theme/app_theme_textstyles.dart @@ -42,13 +42,17 @@ class AppThemeTextStyles extends ThemeExtension { static AppThemeTextStyles light = AppThemeTextStyles( size14Regular: TextStyle( fontSize: 14, + height: 1.6, fontWeight: FontWeight.w400, fontFamily: _fontRegular, + color: AppColors.c151B33, ), size16Medium: TextStyle( fontSize: 16, + height: 1.3, fontWeight: FontWeight.w500, fontFamily: _fontMedium, + color: AppColors.c151B33, ), size16SemiBold: TextStyle( fontSize: 16, @@ -70,8 +74,10 @@ class AppThemeTextStyles extends ThemeExtension { ), size24Bold: TextStyle( fontSize: 24, + height: 1.3, fontWeight: FontWeight.w700, fontFamily: _fontBold, + color: AppColors.c151B33, ), size64Black: TextStyle( fontSize: 64, @@ -84,13 +90,17 @@ class AppThemeTextStyles extends ThemeExtension { static AppThemeTextStyles dark = AppThemeTextStyles( size14Regular: TextStyle( fontSize: 14, + height: 1.6, fontWeight: FontWeight.w400, fontFamily: _fontRegular, + color: AppColors.cFFFFFF, ), size16Medium: TextStyle( fontSize: 16, + height: 1.3, fontWeight: FontWeight.w500, fontFamily: _fontMedium, + color: AppColors.cFFFFFF, ), size16SemiBold: TextStyle( fontSize: 16, @@ -112,8 +122,10 @@ class AppThemeTextStyles extends ThemeExtension { ), size24Bold: TextStyle( fontSize: 24, + height: 1.3, fontWeight: FontWeight.w700, fontFamily: _fontBold, + color: AppColors.cFFFFFF, ), size64Black: TextStyle( fontSize: 64, diff --git a/lib/core/theme/theme_icons.dart b/lib/core/theme/theme_icons.dart index 229f8a0..6f4737e 100644 --- a/lib/core/theme/theme_icons.dart +++ b/lib/core/theme/theme_icons.dart @@ -3,16 +3,29 @@ import 'package:food_delivery_client/core/core.dart'; class AppThemeIcons extends ThemeExtension { final String icSplash; + final String icArrowLeft; - AppThemeIcons({required this.icSplash}); + AppThemeIcons({required this.icSplash, required this.icArrowLeft}); - static AppThemeIcons light = AppThemeIcons(icSplash: AppLightSvgs.icSplash); + static AppThemeIcons light = AppThemeIcons( + icSplash: AppLightSvgs.icSplash, + icArrowLeft: AppLightSvgs.icArrowLeft, + ); - static AppThemeIcons dark = AppThemeIcons(icSplash: AppDarkSvgs.icSplash); + static AppThemeIcons dark = AppThemeIcons( + icSplash: AppDarkSvgs.icSplash, + icArrowLeft: AppDarkSvgs.icArrowLeft, + ); @override - ThemeExtension copyWith({String? icSplash}) { - return AppThemeIcons(icSplash: icSplash ?? this.icSplash); + ThemeExtension copyWith({ + String? icSplash, + String? icArrowLeft, + }) { + return AppThemeIcons( + icSplash: icSplash ?? this.icSplash, + icArrowLeft: icArrowLeft ?? this.icArrowLeft, + ); } @override diff --git a/lib/core/utils/app_utils.dart b/lib/core/utils/app_utils.dart index ce77d16..75391aa 100644 --- a/lib/core/utils/app_utils.dart +++ b/lib/core/utils/app_utils.dart @@ -1,6 +1,12 @@ import '../../food_delivery_client.dart'; abstract class AppUtils { + static const Gradient kGradient = LinearGradient( + begin: AlignmentGeometry.bottomCenter, + end: AlignmentGeometry.topCenter, + colors: [AppColors.cFF6F00, AppColors.cFFAB40], + ); + static const SizedBox kSizedBox = SizedBox.shrink(); static const Radius kRadius = Radius.zero; diff --git a/lib/feature/auth/presentation/login_page/login_page.dart b/lib/feature/auth/presentation/login_page/login_page.dart new file mode 100644 index 0000000..a72ef12 --- /dev/null +++ b/lib/feature/auth/presentation/login_page/login_page.dart @@ -0,0 +1,15 @@ +import 'package:food_delivery_client/feature/auth/presentation/login_page/widgets/login_body.dart'; +import 'package:food_delivery_client/feature/common/presentation/widgets/w_back_button.dart'; + +import '../../../../food_delivery_client.dart'; + +class LoginPage extends StatelessWidget { + const LoginPage({super.key}); + + @override + Widget build(BuildContext context) { + return WLoginBody(); + } +} + + diff --git a/lib/feature/auth/presentation/login_page/widgets/login_body.dart b/lib/feature/auth/presentation/login_page/widgets/login_body.dart new file mode 100644 index 0000000..4230f26 --- /dev/null +++ b/lib/feature/auth/presentation/login_page/widgets/login_body.dart @@ -0,0 +1,155 @@ +import 'package:food_delivery_client/feature/auth/presentation/login_page/widgets/welcome_text.dart'; +import 'package:food_delivery_client/feature/common/presentation/widgets/app_text_form_field.dart'; + +import '../../../../../food_delivery_client.dart'; + +class WLoginBody extends StatefulWidget { + const WLoginBody({super.key}); + + @override + State createState() => _WLoginBodyState(); +} + +class _WLoginBodyState extends State { + late TextEditingController _phoneNumberController; + late TextEditingController _passwordController; + final _formKey = GlobalKey(); + + @override + void initState() { + _phoneNumberController = TextEditingController(); + _passwordController = TextEditingController(); + super.initState(); + } + + @override + void dispose() { + _phoneNumberController.dispose(); + _passwordController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Form( + key: _formKey, + autovalidateMode: AutovalidateMode.onUserInteraction, + child: WLayout( + top: false, + child: Scaffold( + body: Stack( + children: [ + SvgPicture.asset(AppIcons.icLogin), + Positioned( + child: Material( + color: AppColors.cTransparent, + child: + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + 30.verticalSpace, + WBackButton(), + 20.verticalSpace, + WelcomeText( + text: context.loc.welcome_to_volt( + AppLocaleKeys.appName, + ), + ), + 8.verticalSpace, + Text( + context.loc.please_login, + style: AppTextStyles.size14Regular.copyWith( + color: AppColors.cA7AEC1, + height: 1.6, + ), + ), + 54.verticalSpace, + Text( + context.loc.email_or_phone, + style: context.appThemeTextStyles.size16Medium, + ), + 10.verticalSpace, + AppTextFormField( + controller: _phoneNumberController, + hintText: context.loc.enter_email_or_phone, + ), + 20.verticalSpace, + Text( + context.loc.password, + style: context.appThemeTextStyles.size16Medium, + ), + 10.verticalSpace, + AppTextFormField( + obscureText: true, + controller: _passwordController, + hintText: context.loc.enter_password, + ), + 10.verticalSpace, + Align( + alignment: AlignmentGeometry.centerRight, + child: TextButton( + onPressed: () {}, + child: Text( + context.loc.forgot_password, + style: AppTextStyles.size14Regular.copyWith( + color: AppColors.cFF6F00, + ), + ), + ), + ), + 60.verticalSpace, + AppButton( + name: context.loc.login, + onPressed: () { + if (_formKey.currentState?.validate() ?? false) {} + }, + ), + 15.verticalSpace, + Align( + alignment: AlignmentGeometry.center, + child: RichText( + text: TextSpan( + text: context.loc.dont_have_account, + style: context.appThemeTextStyles.size14Regular, + children: [ + WidgetSpan( + baseline: TextBaseline.alphabetic, + alignment: PlaceholderAlignment.baseline, + + child: TextButton( + onPressed: () {}, + style: ButtonStyle( + shadowColor: WidgetStatePropertyAll( + AppColors.cFF6F00.newWithOpacity(.2), + ), + padding: WidgetStatePropertyAll( + EdgeInsets.zero, + ), + ), + child: Text( + context.loc.register, + style: AppTextStyles.size14Bold + .copyWith(color: AppColors.cFF6F00), + ), + ), + ), + ], + ), + ), + ), + ], + ).paddingOnly( + left: 24, + right: 24, + top: context.mq.viewPadding.top, + bottom: context.mq.viewPadding.bottom, + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/feature/auth/presentation/login_page/widgets/welcome_text.dart b/lib/feature/auth/presentation/login_page/widgets/welcome_text.dart new file mode 100644 index 0000000..2789bc4 --- /dev/null +++ b/lib/feature/auth/presentation/login_page/widgets/welcome_text.dart @@ -0,0 +1,52 @@ +import '../../../../../food_delivery_client.dart'; + +class WelcomeText extends StatelessWidget { + final String text; + + const WelcomeText({Key? key, required this.text}) : super(key: key); + + @override + Widget build(BuildContext context) { + final voltIndex = text.toLowerCase().indexOf( + AppLocaleKeys.appName.toLowerCase(), + ); + + if (voltIndex == -1) { + return Text( + text, + style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), + ); + } + + final before = text.substring(0, voltIndex); + final volt = text.substring( + voltIndex, + voltIndex + AppLocaleKeys.appName.length, + ); + final after = text.substring(voltIndex + AppLocaleKeys.appName.length); + + return Text.rich( + TextSpan( + children: [ + TextSpan(text: before, style: context.appThemeTextStyles.size24Bold), + WidgetSpan( + alignment: PlaceholderAlignment.baseline, + baseline: TextBaseline.alphabetic, + child: ShaderMask( + shaderCallback: (bounds) => + AppUtils.kGradient.createShader(bounds), + child: Text( + volt, + style: context.appThemeTextStyles.size24Bold.copyWith( + color: AppColors.cFFFFFF, + ), + ), + ), + ), + // "Volt" dan keyingi text + TextSpan(text: after, style: context.appThemeTextStyles.size24Bold), + ], + ), + ); + } +} diff --git a/lib/feature/common/common.dart b/lib/feature/common/common.dart index f1b8234..7184953 100644 --- a/lib/feature/common/common.dart +++ b/lib/feature/common/common.dart @@ -1,3 +1,3 @@ export 'presentation/widgets/widgets.dart'; export 'presentation/blocs/language_bloc/language_bloc.dart'; -export 'data/models/success_model.dart'; \ No newline at end of file +export 'data/models/success_model.dart'; diff --git a/lib/feature/common/presentation/widgets/app_button.dart b/lib/feature/common/presentation/widgets/app_button.dart index dfbaf56..8fffaf9 100644 --- a/lib/feature/common/presentation/widgets/app_button.dart +++ b/lib/feature/common/presentation/widgets/app_button.dart @@ -57,10 +57,10 @@ class AppButton extends StatelessWidget { mainAxisAlignment: mainAxisAlignment ?? MainAxisAlignment.center, children: [ - leading?? AppUtils.kSizedBox, + leading ?? AppUtils.kSizedBox, Text( name, - style: AppTextStyles.size16Bold.copyWith( + style: AppTextStyles.size14Bold.copyWith( color: AppColors.cFFFFFF, ), ), diff --git a/lib/feature/common/presentation/widgets/app_text_form_field.dart b/lib/feature/common/presentation/widgets/app_text_form_field.dart index e30faf8..c2b4d02 100644 --- a/lib/feature/common/presentation/widgets/app_text_form_field.dart +++ b/lib/feature/common/presentation/widgets/app_text_form_field.dart @@ -55,67 +55,92 @@ class _AppTextFormFieldState extends State { @override Widget build(BuildContext context) { - return TextFormField( - enabled: true, - //autofocus: true, - maxLines: widget.maxLines ?? 1, - minLines: widget.minLines ?? 1, - onChanged: widget.onChanged, - focusNode: widget.focusNode, - inputFormatters: widget.inputFormatters, - keyboardType: widget.keyBoardType, - style: widget.textStyle ?? AppTextStyles.size16Regular, - onTap: widget.onTap, - textAlign: widget.textAlign ?? TextAlign.start, - controller: widget.controller, - validator: widget.validator, - obscureText: widget.obscureText ? visibility : false, - obscuringCharacter: "*", - autovalidateMode: AutovalidateMode.onUserInteraction, - decoration: InputDecoration( + return DecoratedBox( + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + offset: const Offset(0, 4), + color: AppColors.cA7AEC1.newWithOpacity(.15), + blurRadius: 70, + ), + ], + ), + child: TextFormField( enabled: true, - filled: true, - - fillColor: widget.fillColor ?? AppColors.cEEEEEE, - hintText: widget.hintText, - hintStyle: - widget.hintTextStyle ?? - AppTextStyles.size16Regular.copyWith(color: AppColors.c7F7F7F), - suffixIcon: widget.obscureText - ? IconButton( - onPressed: () { - setState(() { - visibility = !visibility; - }); - }, - icon: Icon( - visibility ? Icons.visibility : Icons.visibility_off, - color: AppColors.c000000, - ), - ) - : widget.suffixIcon, - prefixIconConstraints: BoxConstraints(minHeight: 24, minWidth: 0), - prefixIcon: widget.prefixIcon?.paddingOnly(left: 10).paddingAll(3), - contentPadding: EdgeInsets.symmetric(vertical: 12, horizontal: 12), - border: OutlineInputBorder( - borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40, - borderSide: BorderSide.none, - ), - errorBorder: OutlineInputBorder( - borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40, - borderSide: BorderSide.none, - ), - enabledBorder: OutlineInputBorder( - borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40, - borderSide: BorderSide.none, - ), - focusedBorder: OutlineInputBorder( - borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40, - borderSide: BorderSide.none, - ), - disabledBorder: OutlineInputBorder( - borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40, - borderSide: BorderSide.none, + //autofocus: true, + maxLines: widget.maxLines ?? 1, + minLines: widget.minLines ?? 1, + onChanged: widget.onChanged, + focusNode: widget.focusNode, + inputFormatters: widget.inputFormatters, + keyboardType: widget.keyBoardType, + style: widget.textStyle ?? context.appThemeTextStyles.size14Regular, + onTap: widget.onTap, + textAlign: widget.textAlign ?? TextAlign.start, + controller: widget.controller, + validator: widget.validator, + obscureText: widget.obscureText ? visibility : false, + obscuringCharacter: "*", + autovalidateMode: AutovalidateMode.onUserInteraction, + cursorColor: AppColors.cFF6F00, + decoration: InputDecoration( + enabled: true, + filled: true, + fillColor: context.appThemeColors.iconColor ?? AppColors.cEEEEEE, + hintText: widget.hintText, + hintStyle: + widget.hintTextStyle ?? + context.appThemeTextStyles.size14Regular.copyWith( + color: AppColors.cA7AEC1, + ), + suffixIcon: widget.obscureText + ? IconButton( + onPressed: () { + setState(() { + visibility = !visibility; + }); + }, + icon: SvgPicture.asset( + visibility ? AppIcons.icVisibility : AppIcons.icVisibilityOff, + color: AppColors.c000000, + ), + ) + : widget.suffixIcon, + prefixIconConstraints: BoxConstraints(minHeight: 24, minWidth: 0), + prefixIcon: widget.prefixIcon?.paddingOnly(left: 10).paddingAll(3), + contentPadding: EdgeInsets.symmetric(vertical: 16, horizontal: 14), + border: OutlineInputBorder( + borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius16, + borderSide: BorderSide( + color: context.appThemeColors.borderColor, + width: 1, + ), + ), + errorBorder: OutlineInputBorder( + borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius16, + borderSide: BorderSide( + color: context.appThemeColors.borderColor, + width: 1, + ), + ), + enabledBorder: OutlineInputBorder( + borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius16, + borderSide: BorderSide( + color: context.appThemeColors.borderColor, + width: 1, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius16, + borderSide: BorderSide(color: AppColors.cFF6F00, width: 1), + ), + disabledBorder: OutlineInputBorder( + borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40, + borderSide: BorderSide( + color: context.appThemeColors.borderColor, + width: 1, + ), + ), ), ), ); diff --git a/lib/feature/common/presentation/widgets/w_back_button.dart b/lib/feature/common/presentation/widgets/w_back_button.dart new file mode 100644 index 0000000..7d6386a --- /dev/null +++ b/lib/feature/common/presentation/widgets/w_back_button.dart @@ -0,0 +1,31 @@ +import '../../../../food_delivery_client.dart'; + +class WBackButton extends StatelessWidget { + const WBackButton({super.key}); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () {}, + borderRadius: AppUtils.kBorderRadius22, + child: Ink( + height: 44, + width: 44, + decoration: BoxDecoration( + borderRadius: AppUtils.kBorderRadius22, + color: context.appThemeColors.iconColor, + boxShadow: [ + BoxShadow( + color: AppColors.cA7AEC1.newWithOpacity(.3), + offset: const Offset(0, 4), + blurRadius: 80, + ), + ], + ), + child: SvgPicture.asset( + context.appThemeIcons.icArrowLeft, + ).paddingAll(10), + ), + ); + } +} diff --git a/lib/feature/common/presentation/widgets/widgets.dart b/lib/feature/common/presentation/widgets/widgets.dart index c98e350..4e67f74 100644 --- a/lib/feature/common/presentation/widgets/widgets.dart +++ b/lib/feature/common/presentation/widgets/widgets.dart @@ -5,3 +5,4 @@ export 'w_stories_list_item.dart'; export 'w_custom_modal_bottom_sheet.dart'; export 'app_button.dart'; export 'app_list_tile.dart'; +export 'w_back_button.dart'; diff --git a/lib/feature/onboarding/presentation/pages/onboarding_page/onboarding_page.dart b/lib/feature/onboarding/presentation/pages/onboarding_page/onboarding_page.dart index 4f45e09..2f94f31 100644 --- a/lib/feature/onboarding/presentation/pages/onboarding_page/onboarding_page.dart +++ b/lib/feature/onboarding/presentation/pages/onboarding_page/onboarding_page.dart @@ -73,9 +73,8 @@ class _OnboardingPageState extends State { onPressed: () { if (currentIndex < 1) { onPressed(); - } - if (currentIndex == 1) { - log("Navigate to login"); + } else { + context.go(Routes.login); } }, ), diff --git a/lib/feature/onboarding/presentation/pages/splash_page/splash_page.dart b/lib/feature/onboarding/presentation/pages/splash_page/splash_page.dart index 5640ddc..1d4d2eb 100644 --- a/lib/feature/onboarding/presentation/pages/splash_page/splash_page.dart +++ b/lib/feature/onboarding/presentation/pages/splash_page/splash_page.dart @@ -31,15 +31,11 @@ class SplashPage extends StatelessWidget { Center(child: SvgPicture.asset(AppIcons.icLogo)), ShaderMask( shaderCallback: (bounds) => - const LinearGradient( - begin: AlignmentGeometry.bottomCenter, - end: AlignmentGeometry.topCenter, - colors: [AppColors.cFF6F00, AppColors.cFFAB40], - ).createShader( + AppUtils.kGradient.createShader( Rect.fromLTWH(0, 0, bounds.width, bounds.height), ), child: Text( - "Felix Eats", + AppLocaleKeys.appName, style: context.appThemeTextStyles.size64Black, ), ), diff --git a/lib/main.dart b/lib/main.dart index 3570ede..ab2328e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -46,11 +46,11 @@ class _MyAppState extends State { builder: (context, state) { return ToastificationWrapper( child: MaterialApp.router( - title: "Felix Eats", + title: AppLocaleKeys.appName, debugShowCheckedModeBanner: false, theme: AppTheme.lightTheme, darkTheme: AppTheme.darkTheme, - themeMode: ThemeMode.light, + themeMode: ThemeMode.dark, routerConfig: sl().router, locale: state.currentLocale, supportedLocales: L10n.locales,