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