diff --git a/assets/images/icon_profile.png b/assets/images/icon_profile.png
new file mode 100644
index 0000000..f48afff
Binary files /dev/null and b/assets/images/icon_profile.png differ
diff --git a/assets/svg/icon_awards.svg b/assets/svg/icon_awards.svg
new file mode 100644
index 0000000..67901d2
--- /dev/null
+++ b/assets/svg/icon_awards.svg
@@ -0,0 +1,41 @@
+
diff --git a/assets/svg/icon_home.svg b/assets/svg/icon_home.svg
new file mode 100644
index 0000000..a88c424
--- /dev/null
+++ b/assets/svg/icon_home.svg
@@ -0,0 +1,41 @@
+
diff --git a/assets/svg/icon_shop.svg b/assets/svg/icon_shop.svg
new file mode 100644
index 0000000..57c2ab6
--- /dev/null
+++ b/assets/svg/icon_shop.svg
@@ -0,0 +1,41 @@
+
diff --git a/lib/common_ui/resources/my_assets.dart b/lib/common_ui/resources/my_assets.dart
index 09d8c1c..dc5ec20 100644
--- a/lib/common_ui/resources/my_assets.dart
+++ b/lib/common_ui/resources/my_assets.dart
@@ -7,9 +7,13 @@ class MyAssets {
static const String sample = 'assets/images/sample.png';
static const String shiaMind = 'assets/images/shia_mind.png';
static const String question = 'assets/images/question.png';
+ static const String iconProfile = 'assets/images/icon_profile.png';
/// ----- Svg -----
static const String sampleSvg = 'assets/svg/sample.svg';
+ static const String iconHome = 'assets/svg/icon_home.svg';
+ static const String iconShop = 'assets/svg/icon_shop.svg';
+ static const String iconAwards = 'assets/svg/icon_awards.svg';
/// ----- Audios -----
static const String sampleAudio = 'assets/audios/sample.mp3';
diff --git a/lib/core/params/home_params.dart b/lib/core/params/home_params.dart
new file mode 100644
index 0000000..22518f3
--- /dev/null
+++ b/lib/core/params/home_params.dart
@@ -0,0 +1,13 @@
+class HomeParams {
+ int? id;
+
+ HomeParams({this.id});
+
+ HomeParams copyWith({
+ int? id,
+ }) {
+ return HomeParams(
+ id: id ?? this.id,
+ );
+ }
+}
diff --git a/lib/core/routers/my_routes.dart b/lib/core/routers/my_routes.dart
index 4fece1a..449cc34 100644
--- a/lib/core/routers/my_routes.dart
+++ b/lib/core/routers/my_routes.dart
@@ -1,3 +1,5 @@
+import 'package:shia_game_flutter/features/home/presentation/binding/home_binding.dart';
+import 'package:shia_game_flutter/features/home/presentation/pages/home_page.dart';
import 'package:shia_game_flutter/features/intro/presentation/binding/intro_binding.dart';
import 'package:shia_game_flutter/features/intro/presentation/ui/intro_page.dart';
import 'package:shia_game_flutter/features/sample/presentation/binding/sample_binding.dart';
@@ -11,6 +13,7 @@ class Routes {
static const String samplePage = '/sample_page';
static const String introPage = '/intro_page';
+ static const String homePage = '/home_page';
}
List get appPages => [
@@ -24,4 +27,9 @@ List get appPages => [
page: () => const IntroPage(),
binding: IntroBinding(),
),
+ GetPage(
+ name: Routes.homePage,
+ page: () => const HomePage(),
+ binding: HomeBinding(),
+ ),
];
diff --git a/lib/core/widgets/bottom_nav_bar/bottom_nav_bar.dart b/lib/core/widgets/bottom_nav_bar/bottom_nav_bar.dart
new file mode 100644
index 0000000..44f08f1
--- /dev/null
+++ b/lib/core/widgets/bottom_nav_bar/bottom_nav_bar.dart
@@ -0,0 +1,74 @@
+import 'package:flutter/material.dart';
+import 'package:get/get_state_manager/src/rx_flutter/rx_obx_widget.dart';
+import 'package:get/get_state_manager/src/simple/get_view.dart';
+import 'package:shia_game_flutter/common_ui/resources/my_text_style.dart';
+import 'package:shia_game_flutter/features/home/presentation/controller/home_controller.dart';
+import 'package:shia_game_flutter/core/widgets/bottom_nav_bar/styles/bottom_nav_bar_item.dart';
+import 'package:shia_game_flutter/core/widgets/bottom_nav_bar/styles/bottom_nav_bar_profile_item.dart';
+
+class BottomNavBar extends GetView {
+ const BottomNavBar({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ decoration: BoxDecoration(
+ gradient: RadialGradient(
+ radius: 2.5,
+ colors: [Color(0XFF4F09BF), Color(0XFF250459)],
+ ),
+ ),
+ child: Obx(
+ () => BottomNavigationBar(
+ onTap: (int index) => controller.onChangeBottomNavBar(index),
+ currentIndex: controller.selectedIndex.value,
+ backgroundColor: Colors.transparent,
+ elevation: 0,
+ type: BottomNavigationBarType.fixed,
+ unselectedFontSize: 8,
+ selectedFontSize: 8,
+ unselectedLabelStyle: Lexend.bold,
+ selectedLabelStyle: Lexend.bold,
+ showSelectedLabels: false,
+ showUnselectedLabels: false,
+ items: List.generate(
+ controller.bottomNavList.length,
+ (index) => index == 3
+ ? _bottomNavBarProfileItem(index)
+ : _bottomNavBarItem(index),
+ ),
+ ),
+ ),
+ );
+ }
+
+ BottomNavigationBarItem _bottomNavBarItem(int index) {
+ return BottomNavigationBarItem(
+ icon: Opacity(
+ opacity: 0.7,
+ child: BottomNavBarItem(
+ bottomNavEntity: controller.bottomNavList[index],
+ ),
+ ),
+ activeIcon: BottomNavBarItem(
+ bottomNavEntity: controller.bottomNavList[index],
+ ),
+ label: '',
+ );
+ }
+
+ BottomNavigationBarItem _bottomNavBarProfileItem(int index) {
+ return BottomNavigationBarItem(
+ icon: Opacity(
+ opacity: 0.7,
+ child: BottomNavBarProfileItem(
+ bottomNavEntity: controller.bottomNavList[index],
+ ),
+ ),
+ activeIcon: BottomNavBarProfileItem(
+ bottomNavEntity: controller.bottomNavList[index],
+ ),
+ label: '',
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/core/widgets/bottom_nav_bar/styles/bottom_nav_bar_item.dart b/lib/core/widgets/bottom_nav_bar/styles/bottom_nav_bar_item.dart
new file mode 100644
index 0000000..f1c1a30
--- /dev/null
+++ b/lib/core/widgets/bottom_nav_bar/styles/bottom_nav_bar_item.dart
@@ -0,0 +1,26 @@
+import 'package:flutter/material.dart';
+import 'package:shia_game_flutter/common_ui/resources/my_spaces.dart';
+import 'package:shia_game_flutter/common_ui/resources/my_text_style.dart';
+import 'package:shia_game_flutter/core/utils/gap.dart';
+import 'package:shia_game_flutter/core/widgets/image/my_image.dart';
+import 'package:shia_game_flutter/features/home/domain/entity/bottom_nav_entity.dart';
+
+class BottomNavBarItem extends StatelessWidget {
+ const BottomNavBarItem({super.key, required this.bottomNavEntity});
+
+ final BottomNavEntity bottomNavEntity;
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ children: [
+ MyImage(asset: bottomNavEntity.icon ?? ''),
+ MySpaces.s4.gapHeight,
+ Text(
+ bottomNavEntity.title ?? '',
+ style: Lexend.bold.copyWith(fontSize: MySpaces.s8),
+ ),
+ ],
+ );
+ }
+}
diff --git a/lib/core/widgets/bottom_nav_bar/styles/bottom_nav_bar_profile_item.dart b/lib/core/widgets/bottom_nav_bar/styles/bottom_nav_bar_profile_item.dart
new file mode 100644
index 0000000..23b0afe
--- /dev/null
+++ b/lib/core/widgets/bottom_nav_bar/styles/bottom_nav_bar_profile_item.dart
@@ -0,0 +1,38 @@
+import 'package:flutter/material.dart';
+import 'package:shia_game_flutter/common_ui/resources/my_spaces.dart';
+import 'package:shia_game_flutter/common_ui/resources/my_text_style.dart';
+import 'package:shia_game_flutter/core/utils/gap.dart';
+import 'package:shia_game_flutter/core/widgets/image/my_image.dart';
+import 'package:shia_game_flutter/features/home/domain/entity/bottom_nav_entity.dart';
+
+class BottomNavBarProfileItem extends StatelessWidget {
+ const BottomNavBarProfileItem({super.key, required this.bottomNavEntity});
+
+ final BottomNavEntity bottomNavEntity;
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ children: [
+ Container(
+ height: 26,
+ width: 26,
+ padding: EdgeInsets.all(3),
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ border: Border.all(
+ width: 1,
+ color: Color(0XFFF4EEFF),
+ )
+ ),
+ child: MyImage(asset: bottomNavEntity.icon ?? ''),
+ ),
+ MySpaces.s4.gapHeight,
+ Text(
+ bottomNavEntity.title ?? '',
+ style: Lexend.bold.copyWith(fontSize: MySpaces.s8),
+ ),
+ ],
+ );
+ }
+}
diff --git a/lib/features/home/data/datasource/home_datasource.dart b/lib/features/home/data/datasource/home_datasource.dart
new file mode 100644
index 0000000..5cb70c4
--- /dev/null
+++ b/lib/features/home/data/datasource/home_datasource.dart
@@ -0,0 +1,28 @@
+import 'package:shia_game_flutter/core/constants/my_api.dart';
+import 'package:shia_game_flutter/core/network/http_request.dart';
+import 'package:shia_game_flutter/core/params/home_params.dart';
+import 'package:shia_game_flutter/core/response/base_response.dart';
+import 'package:shia_game_flutter/features/home/data/model/home_model.dart';
+import 'package:shia_game_flutter/features/home/domain/entity/home_entity.dart';
+
+abstract class IHomeDatasource {
+ Future getData({required HomeParams params});
+}
+
+class HomeDatasourceImpl implements IHomeDatasource {
+ final IHttpRequest httpRequest;
+
+ const HomeDatasourceImpl(this.httpRequest);
+
+ @override
+ Future getData({required HomeParams params}) async {
+ final response = await httpRequest.get(
+ path: MyApi.baseUrl,
+ );
+
+ return BaseResponse.getData(
+ response?['data'],
+ (json) => HomeModel.fromJson(json),
+ );
+ }
+}
diff --git a/lib/features/home/data/model/home_model.dart b/lib/features/home/data/model/home_model.dart
new file mode 100644
index 0000000..b1d2b84
--- /dev/null
+++ b/lib/features/home/data/model/home_model.dart
@@ -0,0 +1,13 @@
+import 'package:shia_game_flutter/features/home/domain/entity/home_entity.dart';
+
+class HomeModel extends HomeEntity {
+ const HomeModel({
+ super.id,
+ });
+
+ factory HomeModel.fromJson(Map json) {
+ return HomeModel(
+ id: json['id'],
+ );
+ }
+}
diff --git a/lib/features/home/data/repository_impl/home_repository_impl.dart b/lib/features/home/data/repository_impl/home_repository_impl.dart
new file mode 100644
index 0000000..203d244
--- /dev/null
+++ b/lib/features/home/data/repository_impl/home_repository_impl.dart
@@ -0,0 +1,29 @@
+import 'package:flutter/foundation.dart';
+import 'package:shia_game_flutter/core/error_handler/my_exception.dart';
+import 'package:shia_game_flutter/core/params/home_params.dart';
+import 'package:shia_game_flutter/core/utils/data_state.dart';
+import 'package:shia_game_flutter/features/home/data/datasource/home_datasource.dart';
+import 'package:shia_game_flutter/features/home/domain/entity/home_entity.dart';
+import 'package:shia_game_flutter/features/home/domain/repository/home_repository.dart';
+
+class HomeRepositoryImpl implements IHomeRepository {
+ final IHomeDatasource datasource;
+
+ const HomeRepositoryImpl(this.datasource);
+
+ @override
+ Future> getData({required HomeParams params}) async {
+ try {
+ final HomeEntity response = await datasource.getData(params: params);
+ return DataState.success(response);
+ } on MyException catch (e) {
+ return DataState.error(e);
+ } catch (e) {
+ if (kDebugMode) {
+ rethrow;
+ } else {
+ return DataState.error(MyException(errorMessage: '$e'));
+ }
+ }
+ }
+}
diff --git a/lib/features/home/domain/entity/bottom_nav_entity.dart b/lib/features/home/domain/entity/bottom_nav_entity.dart
new file mode 100644
index 0000000..43aea96
--- /dev/null
+++ b/lib/features/home/domain/entity/bottom_nav_entity.dart
@@ -0,0 +1,11 @@
+import 'package:equatable/equatable.dart';
+
+class BottomNavEntity extends Equatable {
+ final String? icon;
+ final String? title;
+
+ const BottomNavEntity({this.icon, this.title});
+
+ @override
+ List