From d8bd9c4925b9d980cacef9b49433254798f629f2 Mon Sep 17 00:00:00 2001 From: jahongireshonqulov Date: Fri, 31 Oct 2025 16:32:28 +0500 Subject: [PATCH] feat:onboarding page ui done --- assets/icons/common/ic_onboarding1.svg | 224 ++++++++++++++++++ assets/icons/common/ic_onboarding2.svg | 3 + assets/icons/common/ic_onboarding3.svg | 139 +++++++++++ assets/translations/app_en.arb | 8 +- assets/translations/app_ru.arb | 8 +- assets/translations/app_uz.arb | 8 +- .../extensions/build_context_extensions.dart | 3 + lib/core/l10n/app_localizations.dart | 36 +++ lib/core/l10n/app_localizations_en.dart | 22 ++ lib/core/l10n/app_localizations_ru.dart | 20 ++ lib/core/l10n/app_localizations_uz.dart | 20 ++ lib/core/theme/app_colors.dart | 5 + lib/core/theme/app_icons.dart | 3 + lib/core/theme/app_theme.dart | 13 +- lib/core/theme/app_theme_colors.dart | 39 +++ lib/core/theme/app_theme_textstyles.dart | 6 + .../presentation/widgets/app_button.dart | 4 +- .../widgets/w_animated_dots_indicator.dart | 58 +++++ .../blocs/splash_bloc/splash_bloc.dart | 2 - .../onboarding_page/onboarding_page.dart | 85 ++++++- .../onboarding_page/widgets/onboarding2.dart | 54 +++++ .../widgets/w_onbaording_background.dart | 31 +++ .../widgets/w_onboarding_body.dart | 73 ++++++ 23 files changed, 853 insertions(+), 11 deletions(-) create mode 100644 assets/icons/common/ic_onboarding1.svg create mode 100644 assets/icons/common/ic_onboarding2.svg create mode 100644 assets/icons/common/ic_onboarding3.svg create mode 100644 lib/core/theme/app_theme_colors.dart create mode 100644 lib/feature/common/presentation/widgets/w_animated_dots_indicator.dart create mode 100644 lib/feature/onboarding/presentation/pages/onboarding_page/widgets/onboarding2.dart create mode 100644 lib/feature/onboarding/presentation/pages/onboarding_page/widgets/w_onbaording_background.dart create mode 100644 lib/feature/onboarding/presentation/pages/onboarding_page/widgets/w_onboarding_body.dart diff --git a/assets/icons/common/ic_onboarding1.svg b/assets/icons/common/ic_onboarding1.svg new file mode 100644 index 0000000..1a8848e --- /dev/null +++ b/assets/icons/common/ic_onboarding1.svg @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/common/ic_onboarding2.svg b/assets/icons/common/ic_onboarding2.svg new file mode 100644 index 0000000..75089f5 --- /dev/null +++ b/assets/icons/common/ic_onboarding2.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/common/ic_onboarding3.svg b/assets/icons/common/ic_onboarding3.svg new file mode 100644 index 0000000..3a84da0 --- /dev/null +++ b/assets/icons/common/ic_onboarding3.svg @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/translations/app_en.arb b/assets/translations/app_en.arb index 038815a..9dc6d1f 100644 --- a/assets/translations/app_en.arb +++ b/assets/translations/app_en.arb @@ -4,6 +4,12 @@ "password_too_short": "Password must be at least 6 characters long", "passwords_do_not_match": "Passwords do not match", "otp_code_incomplete": "OTP code is incomplete", - "unexpected_error": "An unexpected error occurred. Please try again." + "unexpected_error": "An unexpected error occurred. Please try again.", + "onboarding_title_1": "Bringing the best flavors food in the world", + "onboarding_subtitle_1": "Discover your favorite meals and get them delivered fast wherever you are.", + "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" } \ No newline at end of file diff --git a/assets/translations/app_ru.arb b/assets/translations/app_ru.arb index 7d4052f..9e65f15 100644 --- a/assets/translations/app_ru.arb +++ b/assets/translations/app_ru.arb @@ -4,6 +4,12 @@ "password_too_short": "Пароль должен содержать не менее 6 символов", "passwords_do_not_match": "Пароли не совпадают", "otp_code_incomplete": "Код подтверждения введён не полностью", - "unexpected_error": "Произошла непредвиденная ошибка. Пожалуйста, попробуйте снова." + "unexpected_error": "Произошла непредвиденная ошибка. Пожалуйста, попробуйте снова.", + "onboarding_title_1": "Доставка лучших вкусов мира", + "onboarding_subtitle_1": "Находите свои любимые блюда и получайте их быстро, где бы вы ни находились.", + "onboarding_button_next": "Далее", + "onboarding_title_2": "Место для выдающихся людей по всему миру", + "onboarding_subtitle_2": "Находите свои любимые блюда и получайте их быстро, где бы вы ни находились.", + "onboarding_button_get_started": "Начать" } \ No newline at end of file diff --git a/assets/translations/app_uz.arb b/assets/translations/app_uz.arb index 46b7cc5..3920426 100644 --- a/assets/translations/app_uz.arb +++ b/assets/translations/app_uz.arb @@ -4,6 +4,12 @@ "password_too_short": "Parol kamida 6 ta belgidan iborat bo‘lishi kerak", "passwords_do_not_match": "Parollar mos emas", "otp_code_incomplete": "OTP kodi to‘liq kiritilmagan", - "unexpected_error": "Kutilmagan xatolik yuz berdi. Iltimos, qayta urinib ko‘ring." + "unexpected_error": "Kutilmagan xatolik yuz berdi. Iltimos, qayta urinib ko‘ring.", + "onboarding_title_1": "Dunyoning eng mazali taomlari siz uchun", + "onboarding_subtitle_1": "Sevimli taomlaringizni toping va ularni tezda yetkazib oling, qaerda bo‘lishingizdan qat’i nazar.", + "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" } \ No newline at end of file diff --git a/lib/core/extensions/build_context_extensions.dart b/lib/core/extensions/build_context_extensions.dart index e9ac99a..a888a6a 100644 --- a/lib/core/extensions/build_context_extensions.dart +++ b/lib/core/extensions/build_context_extensions.dart @@ -1,3 +1,4 @@ +import 'package:food_delivery_client/core/theme/app_theme_colors.dart'; import 'package:food_delivery_client/core/theme/app_theme_textstyles.dart'; import 'package:food_delivery_client/core/theme/theme_icons.dart'; @@ -18,4 +19,6 @@ extension BuildContextExtensions on BuildContext { AppThemeTextStyles get appThemeTextStyles => theme.extension()!; + + AppThemeColors get appThemeColors => theme.extension()!; } diff --git a/lib/core/l10n/app_localizations.dart b/lib/core/l10n/app_localizations.dart index aa18d46..c764e5b 100644 --- a/lib/core/l10n/app_localizations.dart +++ b/lib/core/l10n/app_localizations.dart @@ -135,6 +135,42 @@ abstract class AppLocalizations { /// In en, this message translates to: /// **'An unexpected error occurred. Please try again.'** String get unexpected_error; + + /// No description provided for @onboarding_title_1. + /// + /// In en, this message translates to: + /// **'Bringing the best flavors food in the world'** + String get onboarding_title_1; + + /// No description provided for @onboarding_subtitle_1. + /// + /// In en, this message translates to: + /// **'Discover your favorite meals and get them delivered fast wherever you are.'** + String get onboarding_subtitle_1; + + /// No description provided for @onboarding_button_next. + /// + /// In en, this message translates to: + /// **'Next'** + String get onboarding_button_next; + + /// No description provided for @onboarding_title_2. + /// + /// In en, this message translates to: + /// **'A place for extraordinary people in the world'** + String get onboarding_title_2; + + /// No description provided for @onboarding_subtitle_2. + /// + /// In en, this message translates to: + /// **'Discover your favorite meals and get them delivered fast wherever you are.'** + String get onboarding_subtitle_2; + + /// No description provided for @onboarding_button_get_started. + /// + /// In en, this message translates to: + /// **'Get Started'** + String get onboarding_button_get_started; } class _AppLocalizationsDelegate diff --git a/lib/core/l10n/app_localizations_en.dart b/lib/core/l10n/app_localizations_en.dart index b72badb..dc76b68 100644 --- a/lib/core/l10n/app_localizations_en.dart +++ b/lib/core/l10n/app_localizations_en.dart @@ -27,4 +27,26 @@ class AppLocalizationsEn extends AppLocalizations { @override String get unexpected_error => 'An unexpected error occurred. Please try again.'; + + @override + String get onboarding_title_1 => + 'Bringing the best flavors food in the world'; + + @override + String get onboarding_subtitle_1 => + 'Discover your favorite meals and get them delivered fast wherever you are.'; + + @override + String get onboarding_button_next => 'Next'; + + @override + String get onboarding_title_2 => + 'A place for extraordinary people in the world'; + + @override + String get onboarding_subtitle_2 => + 'Discover your favorite meals and get them delivered fast wherever you are.'; + + @override + String get onboarding_button_get_started => 'Get Started'; } diff --git a/lib/core/l10n/app_localizations_ru.dart b/lib/core/l10n/app_localizations_ru.dart index 6d92eb1..28df034 100644 --- a/lib/core/l10n/app_localizations_ru.dart +++ b/lib/core/l10n/app_localizations_ru.dart @@ -27,4 +27,24 @@ class AppLocalizationsRu extends AppLocalizations { @override String get unexpected_error => 'Произошла непредвиденная ошибка. Пожалуйста, попробуйте снова.'; + + @override + String get onboarding_title_1 => 'Доставка лучших вкусов мира'; + + @override + String get onboarding_subtitle_1 => + 'Находите свои любимые блюда и получайте их быстро, где бы вы ни находились.'; + + @override + String get onboarding_button_next => 'Далее'; + + @override + String get onboarding_title_2 => 'Место для выдающихся людей по всему миру'; + + @override + String get onboarding_subtitle_2 => + 'Находите свои любимые блюда и получайте их быстро, где бы вы ни находились.'; + + @override + String get onboarding_button_get_started => 'Начать'; } diff --git a/lib/core/l10n/app_localizations_uz.dart b/lib/core/l10n/app_localizations_uz.dart index 32a9c0f..eda4f42 100644 --- a/lib/core/l10n/app_localizations_uz.dart +++ b/lib/core/l10n/app_localizations_uz.dart @@ -27,4 +27,24 @@ class AppLocalizationsUz extends AppLocalizations { @override String get unexpected_error => 'Kutilmagan xatolik yuz berdi. Iltimos, qayta urinib ko‘ring.'; + + @override + String get onboarding_title_1 => 'Dunyoning eng mazali taomlari siz uchun'; + + @override + String get onboarding_subtitle_1 => + 'Sevimli taomlaringizni toping va ularni tezda yetkazib oling, qaerda bo‘lishingizdan qat’i nazar.'; + + @override + String get onboarding_button_next => 'Keyingi'; + + @override + String get onboarding_title_2 => 'Butun dunyodagi ajoyib insonlar uchun joy'; + + @override + String get onboarding_subtitle_2 => + 'Sevimli taomlaringizni toping va ularni tezda yetkazib oling, qaerda bo‘lishingizdan qat’i nazar.'; + + @override + String get onboarding_button_get_started => 'Boshlash'; } diff --git a/lib/core/theme/app_colors.dart b/lib/core/theme/app_colors.dart index 026e2d2..b5bb16c 100644 --- a/lib/core/theme/app_colors.dart +++ b/lib/core/theme/app_colors.dart @@ -48,4 +48,9 @@ abstract class AppColors { static const Color c9EA5B7 = Color(0xFF9EA5B7); static const Color c479B36 = Color(0xFF479B36); static const Color cFFAB40 = Color(0xFFFFAB40); + static const Color cD6D4D4 = Color(0xFFD6D4D4); + static const Color c1A202C = Color(0xFF1A202C); + static const Color c524242 = Color(0xFF524242 ); + + } diff --git a/lib/core/theme/app_icons.dart b/lib/core/theme/app_icons.dart index 3d30efc..30bcc16 100644 --- a/lib/core/theme/app_icons.dart +++ b/lib/core/theme/app_icons.dart @@ -1,6 +1,9 @@ abstract class AppIcons { static const String baseUrl = "assets/icons/common"; static const String icLogo = "$baseUrl/ic_logo.svg"; + static const String icOnBoarding1 = "$baseUrl/ic_onboarding1.svg"; + static const String icOnBoarding2 = "$baseUrl/ic_onboarding2.svg"; + static const String icOnBoarding3 = "$baseUrl/ic_onboarding3.svg"; } abstract class AppLightSvgs { diff --git a/lib/core/theme/app_theme.dart b/lib/core/theme/app_theme.dart index a1cef06..7483063 100644 --- a/lib/core/theme/app_theme.dart +++ b/lib/core/theme/app_theme.dart @@ -1,3 +1,4 @@ +import 'package:food_delivery_client/core/theme/app_theme_colors.dart'; import 'package:food_delivery_client/core/theme/app_theme_textstyles.dart'; import 'package:food_delivery_client/core/theme/theme_icons.dart'; @@ -6,7 +7,11 @@ import '../../food_delivery_client.dart'; abstract class AppTheme { static ThemeData get lightTheme => ThemeData.light().copyWith( brightness: Brightness.light, - extensions: [AppThemeIcons.light, AppThemeTextStyles.light], + extensions: [ + AppThemeIcons.light, + AppThemeTextStyles.light, + AppThemeColors.light, + ], // colorScheme: ColorScheme( // brightness: Brightness.light, @@ -93,7 +98,11 @@ abstract class AppTheme { static ThemeData get darkTheme => ThemeData.light().copyWith( brightness: Brightness.dark, - extensions: [AppThemeIcons.dark, AppThemeTextStyles.dark], + extensions: [ + AppThemeIcons.dark, + AppThemeTextStyles.dark, + AppThemeColors.dark, + ], // colorScheme: ColorScheme( // brightness: Brightness.light, diff --git a/lib/core/theme/app_theme_colors.dart b/lib/core/theme/app_theme_colors.dart new file mode 100644 index 0000000..86b1a97 --- /dev/null +++ b/lib/core/theme/app_theme_colors.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:food_delivery_client/food_delivery_client.dart'; + +class AppThemeColors extends ThemeExtension { + final Color onBoardingColor; + final Color boxShadow; + + AppThemeColors({required this.onBoardingColor, required this.boxShadow}); + + static AppThemeColors light = AppThemeColors( + onBoardingColor: AppColors.cFFFFFF, + boxShadow: AppColors.cD6D4D4, + ); + + static AppThemeColors dark = AppThemeColors( + onBoardingColor: AppColors.c131720, + boxShadow: AppColors.c524242, + ); + + @override + ThemeExtension copyWith({ + Color? onBoardingColor, + Color? boxShadow, + }) { + return AppThemeColors( + onBoardingColor: onBoardingColor ?? this.onBoardingColor, + boxShadow: boxShadow ?? this.boxShadow, + ); + } + + @override + ThemeExtension lerp( + 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 a47675c..0bbfa39 100644 --- a/lib/core/theme/app_theme_textstyles.dart +++ b/lib/core/theme/app_theme_textstyles.dart @@ -57,8 +57,11 @@ class AppThemeTextStyles extends ThemeExtension { ), size24SemiBold: TextStyle( fontSize: 24, + height: 1.3, + letterSpacing: -.48, fontWeight: FontWeight.w600, fontFamily: _fontSemiBold, + color: AppColors.c1A202C, ), size14Bold: TextStyle( fontSize: 14, @@ -96,8 +99,11 @@ class AppThemeTextStyles extends ThemeExtension { ), size24SemiBold: TextStyle( fontSize: 24, + height: 1.3, + letterSpacing: -.48, fontWeight: FontWeight.w600, fontFamily: _fontSemiBold, + color: AppColors.cFFFFFF, ), size14Bold: TextStyle( fontSize: 14, diff --git a/lib/feature/common/presentation/widgets/app_button.dart b/lib/feature/common/presentation/widgets/app_button.dart index 7863f49..dfbaf56 100644 --- a/lib/feature/common/presentation/widgets/app_button.dart +++ b/lib/feature/common/presentation/widgets/app_button.dart @@ -42,8 +42,8 @@ class AppButton extends StatelessWidget { alignment: Alignment.center, padding: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( - color: backgroundColor ?? AppColors.c000000, - borderRadius: BorderRadius.circular(borderRadius ?? 0), + color: backgroundColor ?? AppColors.cFF6F00, + borderRadius: BorderRadius.circular(borderRadius ?? 12), ), child: isLoading ? Center( diff --git a/lib/feature/common/presentation/widgets/w_animated_dots_indicator.dart b/lib/feature/common/presentation/widgets/w_animated_dots_indicator.dart new file mode 100644 index 0000000..f7979de --- /dev/null +++ b/lib/feature/common/presentation/widgets/w_animated_dots_indicator.dart @@ -0,0 +1,58 @@ +import 'package:flutter/material.dart'; +import 'package:food_delivery_client/core/core.dart'; + +import '../../../../core/theme/app_colors.dart'; + +/// A simple animated dot indicator that uses AnimatedContainer. +/// Update [activeIndex] to animate which dot is active. +class AnimatedDotsIndicator extends StatelessWidget { + final int count; + final int activeIndex; + final double dotSize; + final double activeDotWidth; + final double spacing; + final Duration duration; + final Curve curve; + final Color activeColor; + final Color inactiveColor; + final BorderRadius borderRadius; + + const AnimatedDotsIndicator({ + Key? key, + required this.count, + required this.activeIndex, + this.dotSize = 4, + this.activeDotWidth = 32.0, + this.spacing =4, + this.duration = const Duration(milliseconds: 300), + this.curve = Curves.easeInOut, + this.activeColor = AppColors.cFF6F00, + this.inactiveColor = AppColors.cFFEDCC, + this.borderRadius = const BorderRadius.all(Radius.circular(12)), + }) : assert(count >= 0), + assert(activeIndex >= 0), + super(key: key); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisSize: MainAxisSize.min, + children: List.generate(count, (index) { + final bool isActive = index == activeIndex; + return Padding( + padding: EdgeInsets.only(right: index == count - 1 ? 0 : spacing), + child: AnimatedContainer( + duration: duration, + curve: curve, + width: activeDotWidth, + height: dotSize, + decoration: BoxDecoration( + color: isActive ? activeColor : inactiveColor, + borderRadius: borderRadius, + ), + ), + ); + }), + ); + } +} diff --git a/lib/feature/onboarding/presentation/blocs/splash_bloc/splash_bloc.dart b/lib/feature/onboarding/presentation/blocs/splash_bloc/splash_bloc.dart index 3cec0de..08e94ef 100644 --- a/lib/feature/onboarding/presentation/blocs/splash_bloc/splash_bloc.dart +++ b/lib/feature/onboarding/presentation/blocs/splash_bloc/splash_bloc.dart @@ -1,6 +1,4 @@ -import 'package:bloc/bloc.dart'; import 'package:food_delivery_client/food_delivery_client.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; part 'splash_event.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 1dadf97..4f45e09 100644 --- a/lib/feature/onboarding/presentation/pages/onboarding_page/onboarding_page.dart +++ b/lib/feature/onboarding/presentation/pages/onboarding_page/onboarding_page.dart @@ -1,10 +1,91 @@ +import 'package:food_delivery_client/feature/common/presentation/widgets/w_animated_dots_indicator.dart'; +import 'package:food_delivery_client/feature/onboarding/presentation/pages/onboarding_page/widgets/w_onbaording_background.dart'; +import 'package:food_delivery_client/feature/onboarding/presentation/pages/onboarding_page/widgets/w_onboarding_body.dart'; + import '../../../../../food_delivery_client.dart'; -class OnboardingPage extends StatelessWidget { +class OnboardingPage extends StatefulWidget { const OnboardingPage({super.key}); + @override + State createState() => _OnboardingPageState(); +} + +class _OnboardingPageState extends State { + late PageController _pageController; + int currentIndex = 0; + + @override + void initState() { + _pageController = PageController(initialPage: 0); + super.initState(); + } + + @override + void dispose() { + _pageController.dispose(); + + super.dispose(); + } + + void onPressed() { + setState(() { + currentIndex++; + }); + _pageController.animateToPage( + currentIndex, + duration: TimeDelayConst.durationMill300, + curve: Curves.easeIn, + ); + } + + void onPageChanged(int int) { + setState(() { + currentIndex = int; + }); + } + @override Widget build(BuildContext context) { - return WLayout(child: Scaffold()); + return WLayout( + bottom: false, + child: Scaffold( + body: Stack( + children: [ + WOnBoardingBackground(), + WOnBoardingBody( + pageController: _pageController, + onPageChanged: onPageChanged, + ), + Positioned( + bottom: 18, + left: 24, + right: 24, + child: SafeArea( + child: Column( + children: [ + AnimatedDotsIndicator(count: 2, activeIndex: currentIndex), + 40.verticalSpace, + AppButton( + name: currentIndex == 0 + ? context.loc.onboarding_button_next + : context.loc.onboarding_button_get_started, + onPressed: () { + if (currentIndex < 1) { + onPressed(); + } + if (currentIndex == 1) { + log("Navigate to login"); + } + }, + ), + ], + ), + ), + ), + ], + ), + ), + ); } } diff --git a/lib/feature/onboarding/presentation/pages/onboarding_page/widgets/onboarding2.dart b/lib/feature/onboarding/presentation/pages/onboarding_page/widgets/onboarding2.dart new file mode 100644 index 0000000..38c617f --- /dev/null +++ b/lib/feature/onboarding/presentation/pages/onboarding_page/widgets/onboarding2.dart @@ -0,0 +1,54 @@ +import '../../../../../../food_delivery_client.dart'; + +class Onboarding2 extends StatelessWidget { + const Onboarding2({super.key}); + + @override + Widget build(BuildContext context) { + return SizedBox( + height: context.h, + width: context.w, + child: Column( + children: [ + Expanded( + child: Stack( + alignment: Alignment.center, + children: [ + SvgPicture.asset(AppIcons.icOnBoarding2), + SvgPicture.asset(AppIcons.icOnBoarding3), + ], + ), + ), + Expanded( + child: DecoratedBox( + decoration: BoxDecoration( + color: context.theme.scaffoldBackgroundColor, + boxShadow: [ + BoxShadow( + color: AppColors.cD6D4D4.newWithOpacity(.25), + offset: Offset(0, 0), + blurRadius: 10, + ), + ], + ), + child: Column( + spacing: 20, + children: [ + 25.verticalSpace, + Text( + "Bringing the best flavors food in the world", + textAlign: TextAlign.center, + ), + Text( + "Discover your favorite meals and get them delivered fast wherever you are.", + textAlign: TextAlign.center, + ), + ], + ).paddingSymmetric(horizontal: 22), + ), + ), + ], + ), + ); + } +} diff --git a/lib/feature/onboarding/presentation/pages/onboarding_page/widgets/w_onbaording_background.dart b/lib/feature/onboarding/presentation/pages/onboarding_page/widgets/w_onbaording_background.dart new file mode 100644 index 0000000..bf3d80c --- /dev/null +++ b/lib/feature/onboarding/presentation/pages/onboarding_page/widgets/w_onbaording_background.dart @@ -0,0 +1,31 @@ +import '../../../../../../food_delivery_client.dart'; + +class WOnBoardingBackground extends StatelessWidget { + const WOnBoardingBackground({super.key}); + + @override + Widget build(BuildContext context) { + return Positioned.fill( + child: Column( + children: [ + Expanded(child: SizedBox.expand()), + Expanded( + child: DecoratedBox( + decoration: BoxDecoration( + color: context.appThemeColors.onBoardingColor, + boxShadow: [ + BoxShadow( + color: context.appThemeColors.boxShadow.newWithOpacity(.25), + offset: Offset(0, 0), + blurRadius: 10, + ), + ], + ), + child: SizedBox.expand(), + ), + ), + ], + ), + ); + } +} diff --git a/lib/feature/onboarding/presentation/pages/onboarding_page/widgets/w_onboarding_body.dart b/lib/feature/onboarding/presentation/pages/onboarding_page/widgets/w_onboarding_body.dart new file mode 100644 index 0000000..fed02cb --- /dev/null +++ b/lib/feature/onboarding/presentation/pages/onboarding_page/widgets/w_onboarding_body.dart @@ -0,0 +1,73 @@ +import '../../../../../../food_delivery_client.dart'; + +class WOnBoardingBody extends StatelessWidget { + const WOnBoardingBody({ + super.key, + required this.pageController, + required this.onPageChanged, + }); + + final PageController pageController; + final Function(int value) onPageChanged; + + @override + Widget build(BuildContext context) { + final List titles = [ + context.loc.onboarding_title_1, + context.loc.onboarding_title_1, + ]; + final List descriptions = [ + context.loc.onboarding_subtitle_1, + context.loc.onboarding_subtitle_2, + ]; + + final List children = [ + SvgPicture.asset(AppIcons.icOnBoarding1), + Stack( + alignment: Alignment.center, + children: [ + Positioned( + top: 80, + left: 40, + child: SvgPicture.asset(AppIcons.icOnBoarding2), + ), + SvgPicture.asset(AppIcons.icOnBoarding3), + ], + ), + ]; + + return Positioned.fill( + child: PageView.builder( + itemCount: titles.length, + controller: pageController, + scrollDirection: Axis.horizontal, + onPageChanged: onPageChanged, + itemBuilder: (context, index) => Column( + children: [ + Expanded(child: children[index]), + Expanded( + child: Column( + spacing: 20, + children: [ + 25.verticalSpace, + Text( + titles[index], + textAlign: TextAlign.center, + style: context.appThemeTextStyles.size24SemiBold, + ), + Text( + descriptions[index], + textAlign: TextAlign.center, + style: AppTextStyles.size14Regular.copyWith( + color: AppColors.cA9A9A9, + ), + ), + ], + ).paddingSymmetric(horizontal: 22), + ), + ], + ), + ), + ); + } +}