feat: login page ui done

This commit is contained in:
jahongireshonqulov
2025-10-31 19:27:21 +05:00
parent d8bd9c4925
commit 689cf29eab
31 changed files with 992 additions and 93 deletions

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 126 KiB

View File

@@ -0,0 +1,8 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M12.9833 10C12.9833 11.65 11.6499 12.9833 9.99993 12.9833C8.34993 12.9833 7.0166 11.65 7.0166 10C7.0166 8.35 8.34993 7.01666 9.99993 7.01666C11.6499 7.01666 12.9833 8.35 12.9833 10Z"
stroke="#A7AEC1" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M10.0001 16.8916C12.9418 16.8916 15.6834 15.1583 17.5918 12.1583C18.3418 10.9833 18.3418 9.00831 17.5918 7.83331C15.6834 4.83331 12.9418 3.09998 10.0001 3.09998C7.05845 3.09998 4.31678 4.83331 2.40845 7.83331C1.65845 9.00831 1.65845 10.9833 2.40845 12.1583C4.31678 15.1583 7.05845 16.8916 10.0001 16.8916Z"
stroke="#A7AEC1" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
</svg>

After

Width:  |  Height:  |  Size: 823 B

View File

@@ -0,0 +1,17 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M12.1083 7.89166L7.8916 12.1083C7.34994 11.5667 7.0166 10.825 7.0166 10C7.0166 8.35 8.34994 7.01666 9.99994 7.01666C10.8249 7.01666 11.5666 7.35 12.1083 7.89166Z"
stroke="#A7AEC1" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M14.8501 4.80834C13.3918 3.70834 11.7251 3.10834 10.0001 3.10834C7.05845 3.10834 4.31678 4.84167 2.40845 7.84167C1.65845 9.01667 1.65845 10.9917 2.40845 12.1667C3.06678 13.2 3.83345 14.0917 4.66678 14.8083"
stroke="#A7AEC1" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M7.0166 16.275C7.9666 16.675 8.97493 16.8917 9.99993 16.8917C12.9416 16.8917 15.6833 15.1583 17.5916 12.1583C18.3416 10.9833 18.3416 9.00834 17.5916 7.83334C17.3166 7.4 17.0166 6.99167 16.7083 6.60834"
stroke="#A7AEC1" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M12.925 10.5833C12.7083 11.7583 11.75 12.7166 10.575 12.9333" stroke="#A7AEC1"
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M7.89175 12.1083L1.66675 18.3333" stroke="#A7AEC1" stroke-width="1.5"
stroke-linecap="round" stroke-linejoin="round" />
<path d="M18.3334 1.66669L12.1084 7.89169" stroke="#A7AEC1" stroke-width="1.5"
stroke-linecap="round" stroke-linejoin="round" />
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,6 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.77254 5.43582L3.20837 11L8.77254 16.5642" stroke="white" stroke-width="1.5"
stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round" />
<path d="M18.7916 11H3.36414" stroke="white" stroke-width="1.5" stroke-miterlimit="10"
stroke-linecap="round" stroke-linejoin="round" />
</svg>

After

Width:  |  Height:  |  Size: 425 B

View File

@@ -0,0 +1,4 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.77217 5.43585L3.20801 11L8.77217 16.5642" stroke="#151B33" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M18.7918 11H3.36426" stroke="#151B33" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 403 B

View File

@@ -10,6 +10,26 @@
"onboarding_button_next": "Next", "onboarding_button_next": "Next",
"onboarding_title_2": "A place for extraordinary people in the world", "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_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": "Dont have an account?",
"register": "Register"
} }

View File

@@ -10,6 +10,26 @@
"onboarding_button_next": "Далее", "onboarding_button_next": "Далее",
"onboarding_title_2": "Место для выдающихся людей по всему миру", "onboarding_title_2": "Место для выдающихся людей по всему миру",
"onboarding_subtitle_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": "Зарегистрироваться"
} }

View File

@@ -10,6 +10,26 @@
"onboarding_button_next": "Keyingi", "onboarding_button_next": "Keyingi",
"onboarding_title_2": "Butun dunyodagi ajoyib insonlar uchun joy", "onboarding_title_2": "Butun dunyodagi ajoyib insonlar uchun joy",
"onboarding_subtitle_2": "Sevimli taomlaringizni toping va ularni tezda yetkazib oling, qaerda bolishingizdan qati nazar.", "onboarding_subtitle_2": "Sevimli taomlaringizni toping va ularni tezda yetkazib oling, qaerda bolishingizdan qati 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 yoqmi?",
"register": "Royxatdan otish"
} }

View File

@@ -4,6 +4,8 @@ abstract class AppLocaleKeys {
static const String browseSearchHistory = 'browse-search-history'; static const String browseSearchHistory = 'browse-search-history';
static const String token = 'token'; static const String token = 'token';
static const String appName = "Felix Eats";
static const String fontBlack = "fontBlack"; static const String fontBlack = "fontBlack";
static const String fontBold = "fontBold"; static const String fontBold = "fontBold";
static const String fontSemiBold = "fontSemiBold"; static const String fontSemiBold = "fontSemiBold";

View File

@@ -171,6 +171,84 @@ abstract class AppLocalizations {
/// In en, this message translates to: /// In en, this message translates to:
/// **'Get Started'** /// **'Get Started'**
String get onboarding_button_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:
/// **'Dont 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 class _AppLocalizationsDelegate

View File

@@ -49,4 +49,45 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get onboarding_button_get_started => 'Get Started'; 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 => 'Dont have an account?';
@override
String get register => 'Register';
} }

View File

@@ -47,4 +47,45 @@ class AppLocalizationsRu extends AppLocalizations {
@override @override
String get onboarding_button_get_started => 'Начать'; 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 => 'Зарегистрироваться';
} }

View File

@@ -47,4 +47,45 @@ class AppLocalizationsUz extends AppLocalizations {
@override @override
String get onboarding_button_get_started => 'Boshlash'; 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 yoqmi?';
@override
String get register => 'Royxatdan otish';
} }

View File

@@ -1,4 +1,5 @@
import 'package:flutter/cupertino.dart'; 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/onboarding_page/onboarding_page.dart';
import 'package:food_delivery_client/feature/onboarding/presentation/pages/splash_page/splash_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, path: Routes.onBoarding,
pageBuilder: (context, state) => CupertinoPage(child: OnboardingPage()), pageBuilder: (context, state) => CupertinoPage(child: OnboardingPage()),
), ),
GoRoute(
path: Routes.login,
pageBuilder: (context, state) => CupertinoPage(child: LoginPage()),
),
], ],
); );
} }

View File

@@ -51,6 +51,8 @@ abstract class AppColors {
static const Color cD6D4D4 = Color(0xFFD6D4D4); static const Color cD6D4D4 = Color(0xFFD6D4D4);
static const Color c1A202C = Color(0xFF1A202C); 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);
} }

View File

@@ -4,15 +4,20 @@ abstract class AppIcons {
static const String icOnBoarding1 = "$baseUrl/ic_onboarding1.svg"; static const String icOnBoarding1 = "$baseUrl/ic_onboarding1.svg";
static const String icOnBoarding2 = "$baseUrl/ic_onboarding2.svg"; static const String icOnBoarding2 = "$baseUrl/ic_onboarding2.svg";
static const String icOnBoarding3 = "$baseUrl/ic_onboarding3.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 { abstract class AppLightSvgs {
static const String baseUrl = "assets/icons/light"; static const String baseUrl = "assets/icons/light";
static const String icSplash = "$baseUrl/ic_splash.svg"; static const String icSplash = "$baseUrl/ic_splash.svg";
static const String icArrowLeft = "$baseUrl/ic_arrow_left.svg";
} }
abstract class AppDarkSvgs { abstract class AppDarkSvgs {
static const String baseUrl = "assets/icons/dark"; static const String baseUrl = "assets/icons/dark";
static const String icSplash = "$baseUrl/ic_splash.svg"; static const String icSplash = "$baseUrl/ic_splash.svg";
static const String icArrowLeft = "$baseUrl/ic_arrow_left.svg";
} }

View File

@@ -4,35 +4,57 @@ import 'package:food_delivery_client/food_delivery_client.dart';
class AppThemeColors extends ThemeExtension<AppThemeColors> { class AppThemeColors extends ThemeExtension<AppThemeColors> {
final Color onBoardingColor; final Color onBoardingColor;
final Color boxShadow; 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( static AppThemeColors light = AppThemeColors(
onBoardingColor: AppColors.cFFFFFF, onBoardingColor: AppColors.cFFFFFF,
boxShadow: AppColors.cD6D4D4, boxShadow: AppColors.cD6D4D4,
buttonInactiveColor: AppColors.cE2E4EA,
iconColor: AppColors.cFFFFFF,
borderColor:AppColors.cE2E4EA
); );
static AppThemeColors dark = AppThemeColors( static AppThemeColors dark = AppThemeColors(
onBoardingColor: AppColors.c131720, onBoardingColor: AppColors.c131720,
boxShadow: AppColors.c524242, boxShadow: AppColors.c524242,
buttonInactiveColor: AppColors.c292F3D,
iconColor: AppColors.c131720,
borderColor: AppColors.c292F3D
); );
@override @override
ThemeExtension<AppThemeColors> copyWith({ ThemeExtension<AppThemeColors> copyWith({
Color? onBoardingColor, Color? onBoardingColor,
Color? boxShadow, Color? boxShadow,
Color? iconColor,
Color? buttonInactiveColor,
Color? borderColor
}) { }) {
return AppThemeColors( return AppThemeColors(
onBoardingColor: onBoardingColor ?? this.onBoardingColor, onBoardingColor: onBoardingColor ?? this.onBoardingColor,
boxShadow: boxShadow ?? this.boxShadow, boxShadow: boxShadow ?? this.boxShadow,
iconColor: iconColor ?? this.iconColor,
buttonInactiveColor: buttonInactiveColor ?? this.buttonInactiveColor,
borderColor: borderColor??this.borderColor
); );
} }
@override @override
ThemeExtension<AppThemeColors> lerp( ThemeExtension<AppThemeColors> lerp(
covariant ThemeExtension<AppThemeColors>? other, covariant ThemeExtension<AppThemeColors>? other,
double t, double t,) {
) {
if (other is! AppThemeColors) return this; if (other is! AppThemeColors) return this;
return t < 0.5 ? this : other; return t < 0.5 ? this : other;
} }

View File

@@ -42,13 +42,17 @@ class AppThemeTextStyles extends ThemeExtension<AppThemeTextStyles> {
static AppThemeTextStyles light = AppThemeTextStyles( static AppThemeTextStyles light = AppThemeTextStyles(
size14Regular: TextStyle( size14Regular: TextStyle(
fontSize: 14, fontSize: 14,
height: 1.6,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
fontFamily: _fontRegular, fontFamily: _fontRegular,
color: AppColors.c151B33,
), ),
size16Medium: TextStyle( size16Medium: TextStyle(
fontSize: 16, fontSize: 16,
height: 1.3,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
fontFamily: _fontMedium, fontFamily: _fontMedium,
color: AppColors.c151B33,
), ),
size16SemiBold: TextStyle( size16SemiBold: TextStyle(
fontSize: 16, fontSize: 16,
@@ -70,8 +74,10 @@ class AppThemeTextStyles extends ThemeExtension<AppThemeTextStyles> {
), ),
size24Bold: TextStyle( size24Bold: TextStyle(
fontSize: 24, fontSize: 24,
height: 1.3,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
fontFamily: _fontBold, fontFamily: _fontBold,
color: AppColors.c151B33,
), ),
size64Black: TextStyle( size64Black: TextStyle(
fontSize: 64, fontSize: 64,
@@ -84,13 +90,17 @@ class AppThemeTextStyles extends ThemeExtension<AppThemeTextStyles> {
static AppThemeTextStyles dark = AppThemeTextStyles( static AppThemeTextStyles dark = AppThemeTextStyles(
size14Regular: TextStyle( size14Regular: TextStyle(
fontSize: 14, fontSize: 14,
height: 1.6,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
fontFamily: _fontRegular, fontFamily: _fontRegular,
color: AppColors.cFFFFFF,
), ),
size16Medium: TextStyle( size16Medium: TextStyle(
fontSize: 16, fontSize: 16,
height: 1.3,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
fontFamily: _fontMedium, fontFamily: _fontMedium,
color: AppColors.cFFFFFF,
), ),
size16SemiBold: TextStyle( size16SemiBold: TextStyle(
fontSize: 16, fontSize: 16,
@@ -112,8 +122,10 @@ class AppThemeTextStyles extends ThemeExtension<AppThemeTextStyles> {
), ),
size24Bold: TextStyle( size24Bold: TextStyle(
fontSize: 24, fontSize: 24,
height: 1.3,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
fontFamily: _fontBold, fontFamily: _fontBold,
color: AppColors.cFFFFFF,
), ),
size64Black: TextStyle( size64Black: TextStyle(
fontSize: 64, fontSize: 64,

View File

@@ -3,16 +3,29 @@ import 'package:food_delivery_client/core/core.dart';
class AppThemeIcons extends ThemeExtension<AppThemeIcons> { class AppThemeIcons extends ThemeExtension<AppThemeIcons> {
final String icSplash; 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 @override
ThemeExtension<AppThemeIcons> copyWith({String? icSplash}) { ThemeExtension<AppThemeIcons> copyWith({
return AppThemeIcons(icSplash: icSplash ?? this.icSplash); String? icSplash,
String? icArrowLeft,
}) {
return AppThemeIcons(
icSplash: icSplash ?? this.icSplash,
icArrowLeft: icArrowLeft ?? this.icArrowLeft,
);
} }
@override @override

View File

@@ -1,6 +1,12 @@
import '../../food_delivery_client.dart'; import '../../food_delivery_client.dart';
abstract class AppUtils { 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 SizedBox kSizedBox = SizedBox.shrink();
static const Radius kRadius = Radius.zero; static const Radius kRadius = Radius.zero;

View File

@@ -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();
}
}

View File

@@ -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<WLoginBody> createState() => _WLoginBodyState();
}
class _WLoginBodyState extends State<WLoginBody> {
late TextEditingController _phoneNumberController;
late TextEditingController _passwordController;
final _formKey = GlobalKey<FormState>();
@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,
),
),
),
],
),
),
),
);
}
}

View File

@@ -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),
],
),
);
}
}

View File

@@ -60,7 +60,7 @@ class AppButton extends StatelessWidget {
leading ?? AppUtils.kSizedBox, leading ?? AppUtils.kSizedBox,
Text( Text(
name, name,
style: AppTextStyles.size16Bold.copyWith( style: AppTextStyles.size14Bold.copyWith(
color: AppColors.cFFFFFF, color: AppColors.cFFFFFF,
), ),
), ),

View File

@@ -55,7 +55,17 @@ class _AppTextFormFieldState extends State<AppTextFormField> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return TextFormField( return DecoratedBox(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
offset: const Offset(0, 4),
color: AppColors.cA7AEC1.newWithOpacity(.15),
blurRadius: 70,
),
],
),
child: TextFormField(
enabled: true, enabled: true,
//autofocus: true, //autofocus: true,
maxLines: widget.maxLines ?? 1, maxLines: widget.maxLines ?? 1,
@@ -64,7 +74,7 @@ class _AppTextFormFieldState extends State<AppTextFormField> {
focusNode: widget.focusNode, focusNode: widget.focusNode,
inputFormatters: widget.inputFormatters, inputFormatters: widget.inputFormatters,
keyboardType: widget.keyBoardType, keyboardType: widget.keyBoardType,
style: widget.textStyle ?? AppTextStyles.size16Regular, style: widget.textStyle ?? context.appThemeTextStyles.size14Regular,
onTap: widget.onTap, onTap: widget.onTap,
textAlign: widget.textAlign ?? TextAlign.start, textAlign: widget.textAlign ?? TextAlign.start,
controller: widget.controller, controller: widget.controller,
@@ -72,15 +82,17 @@ class _AppTextFormFieldState extends State<AppTextFormField> {
obscureText: widget.obscureText ? visibility : false, obscureText: widget.obscureText ? visibility : false,
obscuringCharacter: "*", obscuringCharacter: "*",
autovalidateMode: AutovalidateMode.onUserInteraction, autovalidateMode: AutovalidateMode.onUserInteraction,
cursorColor: AppColors.cFF6F00,
decoration: InputDecoration( decoration: InputDecoration(
enabled: true, enabled: true,
filled: true, filled: true,
fillColor: context.appThemeColors.iconColor ?? AppColors.cEEEEEE,
fillColor: widget.fillColor ?? AppColors.cEEEEEE,
hintText: widget.hintText, hintText: widget.hintText,
hintStyle: hintStyle:
widget.hintTextStyle ?? widget.hintTextStyle ??
AppTextStyles.size16Regular.copyWith(color: AppColors.c7F7F7F), context.appThemeTextStyles.size14Regular.copyWith(
color: AppColors.cA7AEC1,
),
suffixIcon: widget.obscureText suffixIcon: widget.obscureText
? IconButton( ? IconButton(
onPressed: () { onPressed: () {
@@ -88,34 +100,47 @@ class _AppTextFormFieldState extends State<AppTextFormField> {
visibility = !visibility; visibility = !visibility;
}); });
}, },
icon: Icon( icon: SvgPicture.asset(
visibility ? Icons.visibility : Icons.visibility_off, visibility ? AppIcons.icVisibility : AppIcons.icVisibilityOff,
color: AppColors.c000000, color: AppColors.c000000,
), ),
) )
: widget.suffixIcon, : widget.suffixIcon,
prefixIconConstraints: BoxConstraints(minHeight: 24, minWidth: 0), prefixIconConstraints: BoxConstraints(minHeight: 24, minWidth: 0),
prefixIcon: widget.prefixIcon?.paddingOnly(left: 10).paddingAll(3), prefixIcon: widget.prefixIcon?.paddingOnly(left: 10).paddingAll(3),
contentPadding: EdgeInsets.symmetric(vertical: 12, horizontal: 12), contentPadding: EdgeInsets.symmetric(vertical: 16, horizontal: 14),
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40, borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius16,
borderSide: BorderSide.none, borderSide: BorderSide(
color: context.appThemeColors.borderColor,
width: 1,
),
), ),
errorBorder: OutlineInputBorder( errorBorder: OutlineInputBorder(
borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40, borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius16,
borderSide: BorderSide.none, borderSide: BorderSide(
color: context.appThemeColors.borderColor,
width: 1,
),
), ),
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40, borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius16,
borderSide: BorderSide.none, borderSide: BorderSide(
color: context.appThemeColors.borderColor,
width: 1,
),
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40, borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius16,
borderSide: BorderSide.none, borderSide: BorderSide(color: AppColors.cFF6F00, width: 1),
), ),
disabledBorder: OutlineInputBorder( disabledBorder: OutlineInputBorder(
borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40, borderRadius: widget.borderRadius ?? AppUtils.kBorderRadius40,
borderSide: BorderSide.none, borderSide: BorderSide(
color: context.appThemeColors.borderColor,
width: 1,
),
),
), ),
), ),
); );

View File

@@ -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),
),
);
}
}

View File

@@ -5,3 +5,4 @@ export 'w_stories_list_item.dart';
export 'w_custom_modal_bottom_sheet.dart'; export 'w_custom_modal_bottom_sheet.dart';
export 'app_button.dart'; export 'app_button.dart';
export 'app_list_tile.dart'; export 'app_list_tile.dart';
export 'w_back_button.dart';

View File

@@ -73,9 +73,8 @@ class _OnboardingPageState extends State<OnboardingPage> {
onPressed: () { onPressed: () {
if (currentIndex < 1) { if (currentIndex < 1) {
onPressed(); onPressed();
} } else {
if (currentIndex == 1) { context.go(Routes.login);
log("Navigate to login");
} }
}, },
), ),

View File

@@ -31,15 +31,11 @@ class SplashPage extends StatelessWidget {
Center(child: SvgPicture.asset(AppIcons.icLogo)), Center(child: SvgPicture.asset(AppIcons.icLogo)),
ShaderMask( ShaderMask(
shaderCallback: (bounds) => shaderCallback: (bounds) =>
const LinearGradient( AppUtils.kGradient.createShader(
begin: AlignmentGeometry.bottomCenter,
end: AlignmentGeometry.topCenter,
colors: [AppColors.cFF6F00, AppColors.cFFAB40],
).createShader(
Rect.fromLTWH(0, 0, bounds.width, bounds.height), Rect.fromLTWH(0, 0, bounds.width, bounds.height),
), ),
child: Text( child: Text(
"Felix Eats", AppLocaleKeys.appName,
style: context.appThemeTextStyles.size64Black, style: context.appThemeTextStyles.size64Black,
), ),
), ),

View File

@@ -46,11 +46,11 @@ class _MyAppState extends State<MyApp> {
builder: (context, state) { builder: (context, state) {
return ToastificationWrapper( return ToastificationWrapper(
child: MaterialApp.router( child: MaterialApp.router(
title: "Felix Eats", title: AppLocaleKeys.appName,
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
theme: AppTheme.lightTheme, theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme, darkTheme: AppTheme.darkTheme,
themeMode: ThemeMode.light, themeMode: ThemeMode.dark,
routerConfig: sl<AppRoutes>().router, routerConfig: sl<AppRoutes>().router,
locale: state.currentLocale, locale: state.currentLocale,
supportedLocales: L10n.locales, supportedLocales: L10n.locales,