diff --git a/assets/svg/icon_rank.svg b/assets/svg/icon_rank.svg
new file mode 100644
index 0000000..7f2bd98
--- /dev/null
+++ b/assets/svg/icon_rank.svg
@@ -0,0 +1,9 @@
+
diff --git a/lib/common_ui/resources/my_assets.dart b/lib/common_ui/resources/my_assets.dart
index 98c589f..bf6a215 100644
--- a/lib/common_ui/resources/my_assets.dart
+++ b/lib/common_ui/resources/my_assets.dart
@@ -63,6 +63,7 @@ class MyAssets {
static const String castAwardGold = 'assets/svg/cast_award_gold.svg';
static const String castAwardSilver = 'assets/svg/cast_award_silver.svg';
static const String castAwardBronze = 'assets/svg/cast_award_bronze.svg';
+ static const String iconRank = 'assets/svg/icon_rank.svg';
/// ----- Audios -----
diff --git a/lib/core/widgets/app_bar/enums/app_bar_type.dart b/lib/core/widgets/app_bar/enums/app_bar_type.dart
new file mode 100644
index 0000000..5ab6666
--- /dev/null
+++ b/lib/core/widgets/app_bar/enums/app_bar_type.dart
@@ -0,0 +1,36 @@
+import 'package:flutter/cupertino.dart';
+import 'package:shia_game_flutter/core/widgets/app_bar/styles/battle_league_app_bar.dart';
+import 'package:shia_game_flutter/core/widgets/app_bar/styles/master_app_bar.dart';
+
+enum AppBarType {
+ master,
+ battleLeague;
+
+ static Map title({
+ void Function()? onDiamondTap,
+ void Function()? onFlashTap,
+ void Function()? onShareTap,
+ void Function()? onSettingTap,
+ void Function()? onInfoTap,
+ int? diamondNumber,
+ int? flashNumber,
+ String? title,
+ bool? hasInfo
+ }) {
+ return {
+ AppBarType.master: MasterAppBar(
+ onDiamondTap: onDiamondTap,
+ onFlashTap: onFlashTap,
+ onShareTap: onShareTap,
+ onSettingTap: onSettingTap,
+ diamondNumber: diamondNumber,
+ flashNumber: flashNumber,
+ ),
+ AppBarType.battleLeague: BattleLeagueAppBar(
+ title: title,
+ hasInfo: hasInfo,
+ onInfoTap: onInfoTap,
+ ),
+ };
+ }
+}
\ No newline at end of file
diff --git a/lib/core/widgets/app_bar/master_app_bar.dart b/lib/core/widgets/app_bar/master_app_bar.dart
deleted file mode 100644
index 5e4ba7f..0000000
--- a/lib/core/widgets/app_bar/master_app_bar.dart
+++ /dev/null
@@ -1,57 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:shia_game_flutter/common_ui/resources/my_assets.dart';
-import 'package:shia_game_flutter/common_ui/resources/my_spaces.dart';
-import 'package:shia_game_flutter/common_ui/theme/my_theme.dart';
-import 'package:shia_game_flutter/core/utils/gap.dart';
-import 'package:shia_game_flutter/core/widgets/app_bar/styles/app_bar_action.dart';
-import 'package:shia_game_flutter/core/widgets/app_bar/styles/app_bar_add_widget.dart';
-
-class MasterAppBar extends StatelessWidget implements PreferredSizeWidget {
- const MasterAppBar({
- super.key,
- });
-
- @override
- Widget build(BuildContext context) {
- return AppBar(
- backgroundColor: context.backgroundColor,
- titleSpacing: MySpaces.s30,
- title: Row(
- children: [
- AppBarAddWidget(
- onTap: () {},
- icon: MyAssets.iconDiamond,
- number: 999,
- gradientColors: [
- const Color(0XFF52C3ED),
- const Color(0XFF4F16A0),
- ],
- ),
- MySpaces.s6.gapWidth,
- AppBarAddWidget(
- onTap: () {},
- icon: MyAssets.iconFlash,
- number: 54,
- gradientColors: [
- const Color(0XFFEFB345),
- const Color(0XFF4F16A0),
- ],
- ),
- const Spacer(),
- AppBarAction(
- icon: MyAssets.iconShare,
- onTap: () {},
- ),
- MySpaces.s12.gapWidth,
- AppBarAction(
- icon: MyAssets.iconSetting,
- onTap: () {},
- ),
- ],
- ),
- );
- }
-
- @override
- Size get preferredSize => const Size.fromHeight(kToolbarHeight);
-}
diff --git a/lib/core/widgets/app_bar/my_app_bar.dart b/lib/core/widgets/app_bar/my_app_bar.dart
new file mode 100644
index 0000000..e4760de
--- /dev/null
+++ b/lib/core/widgets/app_bar/my_app_bar.dart
@@ -0,0 +1,56 @@
+import 'package:flutter/material.dart';
+import 'package:shia_game_flutter/common_ui/resources/my_spaces.dart';
+import 'package:shia_game_flutter/core/widgets/app_bar/enums/app_bar_type.dart';
+
+class MyAppBar extends StatelessWidget implements PreferredSizeWidget {
+ const MyAppBar({
+ super.key,
+ this.backgroundColor,
+ this.type = AppBarType.master,
+ this.onDiamondTap,
+ this.onFlashTap,
+ this.onInfoTap,
+ this.onSettingTap,
+ this.onShareTap,
+ this.diamondNumber,
+ this.flashNumber,
+ this.title,
+ this.hasInfo,
+ });
+
+ final AppBarType type;
+ final Color? backgroundColor;
+ final VoidCallback? onDiamondTap;
+ final VoidCallback? onFlashTap;
+ final VoidCallback? onInfoTap;
+ final VoidCallback? onSettingTap;
+ final VoidCallback? onShareTap;
+ final int? diamondNumber;
+ final int? flashNumber;
+ final String? title;
+ final bool? hasInfo;
+
+ @override
+ Widget build(BuildContext context) {
+ return AppBar(
+ backgroundColor: backgroundColor,
+ centerTitle: true,
+ titleSpacing: MySpaces.s30,
+ title: AppBarType.title(
+ title: title,
+ diamondNumber: diamondNumber,
+ flashNumber: flashNumber,
+ hasInfo: hasInfo,
+ onDiamondTap: onDiamondTap,
+ onFlashTap: onFlashTap,
+ onInfoTap: onInfoTap,
+ onSettingTap: onSettingTap,
+ onShareTap: onShareTap,
+ )[type],
+ automaticallyImplyLeading: false,
+ );
+ }
+
+ @override
+ Size get preferredSize => const Size.fromHeight(kToolbarHeight);
+}
diff --git a/lib/core/widgets/app_bar/styles/battle_league_app_bar.dart b/lib/core/widgets/app_bar/styles/battle_league_app_bar.dart
new file mode 100644
index 0000000..9684a4b
--- /dev/null
+++ b/lib/core/widgets/app_bar/styles/battle_league_app_bar.dart
@@ -0,0 +1,40 @@
+import 'package:flutter/material.dart';
+import 'package:shia_game_flutter/core/widgets/app_bar/widgets/app_bar_back_button.dart';
+import 'package:shia_game_flutter/core/widgets/app_bar/widgets/app_bar_gradient_title.dart';
+import 'package:shia_game_flutter/core/widgets/app_bar/widgets/app_bar_info.dart';
+
+class BattleLeagueAppBar extends StatelessWidget implements PreferredSizeWidget {
+ const BattleLeagueAppBar({
+ super.key,
+ this.title,
+ this.hasInfo,
+ this.onInfoTap,
+ });
+
+ final String? title;
+ final bool? hasInfo;
+ final VoidCallback? onInfoTap;
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ const AppBarBackButton(),
+ AppBarGradientTitle(title: title ?? ''),
+ Builder(
+ builder: (context) {
+ if(hasInfo ?? false){
+ return AppBarInfo(onTap: onInfoTap);
+ } else {
+ return const SizedBox.shrink();
+ }
+ },
+ ),
+ ],
+ );
+ }
+
+ @override
+ Size get preferredSize => const Size.fromHeight(kToolbarHeight);
+}
\ No newline at end of file
diff --git a/lib/core/widgets/app_bar/styles/master_app_bar.dart b/lib/core/widgets/app_bar/styles/master_app_bar.dart
new file mode 100644
index 0000000..f8c22c3
--- /dev/null
+++ b/lib/core/widgets/app_bar/styles/master_app_bar.dart
@@ -0,0 +1,66 @@
+import 'package:flutter/material.dart';
+import 'package:shia_game_flutter/common_ui/resources/my_assets.dart';
+import 'package:shia_game_flutter/common_ui/resources/my_spaces.dart';
+import 'package:shia_game_flutter/core/utils/gap.dart';
+import 'package:shia_game_flutter/core/widgets/app_bar/widgets/app_bar_action.dart';
+import 'package:shia_game_flutter/core/widgets/app_bar/widgets/app_bar_add_widget.dart';
+
+class MasterAppBar extends StatelessWidget implements PreferredSizeWidget {
+ const MasterAppBar({
+ super.key,
+ this.onDiamondTap,
+ this.onFlashTap,
+ this.onShareTap,
+ this.onSettingTap,
+ this.diamondNumber,
+ this.flashNumber,
+ });
+
+ final VoidCallback? onDiamondTap;
+ final VoidCallback? onFlashTap;
+ final VoidCallback? onShareTap;
+ final VoidCallback? onSettingTap;
+ final int? diamondNumber;
+ final int? flashNumber;
+
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ children: [
+ AppBarAddWidget(
+ onTap: onDiamondTap,
+ icon: MyAssets.iconDiamond,
+ number: diamondNumber ?? 0,
+ gradientColors: [
+ const Color(0XFF52C3ED),
+ const Color(0XFF4F16A0),
+ ],
+ ),
+ MySpaces.s6.gapWidth,
+ AppBarAddWidget(
+ onTap: onFlashTap,
+ icon: MyAssets.iconFlash,
+ number: flashNumber ?? 0,
+ gradientColors: [
+ const Color(0XFFEFB345),
+ const Color(0XFF4F16A0),
+ ],
+ ),
+ const Spacer(),
+ AppBarAction(
+ icon: MyAssets.iconShare,
+ onTap: onShareTap,
+ ),
+ MySpaces.s12.gapWidth,
+ AppBarAction(
+ icon: MyAssets.iconSetting,
+ onTap: onSettingTap,
+ ),
+ ],
+ );
+ }
+
+ @override
+ Size get preferredSize => const Size.fromHeight(kToolbarHeight);
+}
diff --git a/lib/core/widgets/app_bar/styles/app_bar_action.dart b/lib/core/widgets/app_bar/widgets/app_bar_action.dart
similarity index 86%
rename from lib/core/widgets/app_bar/styles/app_bar_action.dart
rename to lib/core/widgets/app_bar/widgets/app_bar_action.dart
index a8af150..493e601 100644
--- a/lib/core/widgets/app_bar/styles/app_bar_action.dart
+++ b/lib/core/widgets/app_bar/widgets/app_bar_action.dart
@@ -4,9 +4,9 @@ import 'package:shia_game_flutter/core/widgets/container/my_container.dart';
import 'package:shia_game_flutter/core/widgets/image/my_image.dart';
class AppBarAction extends StatelessWidget {
- const AppBarAction({super.key, this.icon, this.onTap});
+ const AppBarAction({super.key, required this.icon, this.onTap});
- final String? icon;
+ final String icon;
final VoidCallback? onTap;
@override
@@ -23,7 +23,7 @@ class AppBarAction extends StatelessWidget {
end: AlignmentDirectional.bottomEnd,
colors: [Color(0XFF823FEB), Color(0XFF4F09BF)],
),
- child: MyImage(asset: icon ?? ''),
+ child: MyImage(asset: icon),
);
}
}
\ No newline at end of file
diff --git a/lib/core/widgets/app_bar/styles/app_bar_add_widget.dart b/lib/core/widgets/app_bar/widgets/app_bar_add_widget.dart
similarity index 88%
rename from lib/core/widgets/app_bar/styles/app_bar_add_widget.dart
rename to lib/core/widgets/app_bar/widgets/app_bar_add_widget.dart
index 584b98e..a7392de 100644
--- a/lib/core/widgets/app_bar/styles/app_bar_add_widget.dart
+++ b/lib/core/widgets/app_bar/widgets/app_bar_add_widget.dart
@@ -10,16 +10,16 @@ import 'package:shia_game_flutter/core/widgets/image/my_image.dart';
class AppBarAddWidget extends StatelessWidget {
const AppBarAddWidget({
super.key,
- this.icon,
- this.number,
+ required this.icon,
+ required this.number,
this.onTap,
- this.gradientColors,
+ required this.gradientColors,
});
- final String? icon;
- final int? number;
+ final String icon;
+ final int number;
final VoidCallback? onTap;
- final List? gradientColors;
+ final List gradientColors;
@override
Widget build(BuildContext context) {
@@ -31,7 +31,7 @@ class AppBarAddWidget extends StatelessWidget {
borderGradient: LinearGradient(
begin: AlignmentDirectional.topStart,
end: AlignmentDirectional.bottomEnd,
- colors: gradientColors ?? [],
+ colors: gradientColors,
),
padding: const EdgeInsetsDirectional.only(
start: MySpaces.s8,
@@ -40,7 +40,7 @@ class AppBarAddWidget extends StatelessWidget {
color: context.backgroundColor,
child: Row(
children: [
- MyImage(asset: icon ?? ''),
+ MyImage(asset: icon),
Expanded(
child: Text(
'$number',
diff --git a/lib/core/widgets/app_bar/widgets/app_bar_back_button.dart b/lib/core/widgets/app_bar/widgets/app_bar_back_button.dart
new file mode 100644
index 0000000..939a50e
--- /dev/null
+++ b/lib/core/widgets/app_bar/widgets/app_bar_back_button.dart
@@ -0,0 +1,27 @@
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+import 'package:shia_game_flutter/common_ui/resources/my_spaces.dart';
+import 'package:shia_game_flutter/common_ui/theme/my_theme.dart';
+import 'package:shia_game_flutter/core/widgets/container/my_container.dart';
+
+class AppBarBackButton extends StatelessWidget {
+ const AppBarBackButton({
+ super.key,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return MyContainer(
+ onTap: () => Get.back(),
+ height: MySpaces.s32,
+ width: MySpaces.s32,
+ borderRadius: const BorderRadius.all(Radius.circular(12)),
+ color: context.primaryColor.withValues(alpha: 0.1),
+ child: Icon(
+ Icons.arrow_back_ios_new_rounded,
+ color: context.primaryColor,
+ size: MySpaces.s18,
+ ),
+ );
+ }
+}
diff --git a/lib/core/widgets/app_bar/widgets/app_bar_gradient_title.dart b/lib/core/widgets/app_bar/widgets/app_bar_gradient_title.dart
new file mode 100644
index 0000000..0588b94
--- /dev/null
+++ b/lib/core/widgets/app_bar/widgets/app_bar_gradient_title.dart
@@ -0,0 +1,23 @@
+import 'package:flutter/material.dart';
+import 'package:shia_game_flutter/core/widgets/text/gradient_text.dart';
+
+class AppBarGradientTitle extends StatelessWidget {
+ const AppBarGradientTitle({
+ super.key,
+ required this.title,
+ });
+
+ final String title;
+
+ @override
+ Widget build(BuildContext context) {
+ return GradientText(
+ text: title,
+ color: const Color(0XFFCAA8FF),
+ fontSize: 22,
+ shadowColor: const Color(0XFF3E1381),
+ offset: const Offset(0, 1.69),
+ blurRadius: 0.84,
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/core/widgets/app_bar/widgets/app_bar_info.dart b/lib/core/widgets/app_bar/widgets/app_bar_info.dart
new file mode 100644
index 0000000..893f4ec
--- /dev/null
+++ b/lib/core/widgets/app_bar/widgets/app_bar_info.dart
@@ -0,0 +1,29 @@
+import 'package:flutter/material.dart';
+import 'package:shia_game_flutter/common_ui/resources/my_spaces.dart';
+import 'package:shia_game_flutter/common_ui/theme/my_theme.dart';
+import 'package:shia_game_flutter/core/widgets/container/my_container.dart';
+
+class AppBarInfo extends StatelessWidget {
+ const AppBarInfo({
+ super.key,
+ this.onTap,
+ });
+
+ final VoidCallback? onTap;
+
+ @override
+ Widget build(BuildContext context) {
+ return MyContainer(
+ onTap: onTap,
+ height: MySpaces.s32,
+ width: MySpaces.s32,
+ borderRadius: const BorderRadius.all(Radius.circular(12)),
+ color: context.primaryColor.withValues(alpha: 0.1),
+ child: Icon(
+ Icons.info_outline_rounded,
+ color: context.primaryColor,
+ size: MySpaces.s20,
+ ),
+ );
+ }
+}
diff --git a/lib/features/battle_league/presentation/controller/battle_league_controller.dart b/lib/features/battle_league/presentation/controller/battle_league_controller.dart
index fd0db52..242cfc9 100644
--- a/lib/features/battle_league/presentation/controller/battle_league_controller.dart
+++ b/lib/features/battle_league/presentation/controller/battle_league_controller.dart
@@ -1,11 +1,12 @@
-import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
import 'package:shia_game_flutter/core/params/sample_params.dart';
import 'package:shia_game_flutter/core/status/base_status.dart';
import 'package:shia_game_flutter/features/battle_league/domain/entity/battle_league_entity.dart';
import 'package:shia_game_flutter/features/battle_league/domain/usecases/get_battle_league_usecase.dart';
import 'package:get/get.dart';
-class BattleLeagueController extends GetxController with StateMixin {
+class BattleLeagueController extends GetxController
+ with StateMixin, GetSingleTickerProviderStateMixin {
/// ----- Constructor -----
BattleLeagueController(this.getBattleLeagueUseCase);
@@ -13,6 +14,7 @@ class BattleLeagueController extends GetxController with StateMixin {
void onInit() {
super.onInit();
change('', status: RxStatus.success());
+ tabController = TabController(length: 2, vsync: this);
}
@override
@@ -30,6 +32,7 @@ class BattleLeagueController extends GetxController with StateMixin {
/// ------ Controllers ------
final TextEditingController textEditingController = TextEditingController();
+ late final TabController tabController;
/// ------ Statuses ------
final Rx getBattleLeagueStatus = Rx(const BaseInit());
diff --git a/lib/features/battle_league/presentation/ui/battle_league_page.dart b/lib/features/battle_league/presentation/ui/battle_league_page.dart
index 5f13dca..9d9954f 100644
--- a/lib/features/battle_league/presentation/ui/battle_league_page.dart
+++ b/lib/features/battle_league/presentation/ui/battle_league_page.dart
@@ -1,13 +1,73 @@
import 'package:flutter/material.dart';
-import 'package:shia_game_flutter/features/battle_league/presentation/controller/battle_league_controller.dart';
import 'package:get/get.dart';
+import 'package:shia_game_flutter/common_ui/resources/my_spaces.dart';
+import 'package:shia_game_flutter/common_ui/theme/my_theme.dart';
+import 'package:shia_game_flutter/core/utils/gap.dart';
+import 'package:shia_game_flutter/core/utils/my_localization.dart';
+import 'package:shia_game_flutter/core/widgets/app_bar/enums/app_bar_type.dart';
+import 'package:shia_game_flutter/core/widgets/app_bar/my_app_bar.dart';
+import 'package:shia_game_flutter/features/battle_league/presentation/controller/battle_league_controller.dart';
+import 'package:shia_game_flutter/features/battle_league/presentation/ui/widgets/battle_league_start_button.dart';
+import 'package:shia_game_flutter/features/battle_league/presentation/ui/widgets/battle_league_tab_bar.dart';
+import 'package:shia_game_flutter/features/battle_league/presentation/ui/widgets/regional_ranking.dart';
+import 'package:shia_game_flutter/features/battle_league/presentation/ui/widgets/time_ranking.dart';
class BattleLeaguePage extends GetView {
const BattleLeaguePage({super.key});
@override
Widget build(BuildContext context) {
- return const Scaffold();
+ return Scaffold(
+ backgroundColor: const Color(0XFF390C82),
+ appBar: MyAppBar(
+ type: AppBarType.battleLeague,
+ backgroundColor: context.noColor,
+ title: context.translate.battle_league,
+ hasInfo: true,
+ onInfoTap: () {},
+ ),
+ body: SafeArea(
+ child: Column(
+ children: [
+ MySpaces.s30.gapHeight,
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: MySpaces.s30),
+ child: BattleLeagueTabBar(
+ controller: controller.tabController,
+ tabs: [
+ context.translate.time_ranking,
+ context.translate.regional_ranking,
+ ],
+ ),
+ ),
+ MySpaces.s12.gapHeight,
+ Expanded(
+ child: TabBarView(
+ controller: controller.tabController,
+ children: const [
+ Padding(
+ padding: EdgeInsets.symmetric(horizontal: MySpaces.s30),
+ child: TimeRanking(),
+ ),
+ Padding(
+ padding: EdgeInsets.symmetric(horizontal: MySpaces.s30),
+ child: RegionalRanking(),
+ ),
+ ],
+ ),
+ ),
+ 56.0.gapHeight,
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: MySpaces.s30),
+ child: BattleLeagueStartButton(
+ title: context.translate.play_now,
+ onTap: () {},
+ ),
+ ),
+ MySpaces.s16.gapHeight,
+ ],
+ ),
+ ),
+ );
}
}
-
diff --git a/lib/features/battle_league/presentation/ui/widgets/battle_league_start_button.dart b/lib/features/battle_league/presentation/ui/widgets/battle_league_start_button.dart
new file mode 100644
index 0000000..d2b7ca1
--- /dev/null
+++ b/lib/features/battle_league/presentation/ui/widgets/battle_league_start_button.dart
@@ -0,0 +1,49 @@
+import 'package:flutter/material.dart';
+import 'package:shia_game_flutter/core/utils/screen_size.dart';
+import 'package:shia_game_flutter/core/widgets/container/my_container.dart';
+import 'package:shia_game_flutter/core/widgets/text/gradient_text.dart';
+
+class BattleLeagueStartButton extends StatelessWidget {
+ const BattleLeagueStartButton({
+ super.key,
+ this.onTap,
+ this.title,
+ });
+
+ final VoidCallback? onTap;
+ final String? title;
+
+ @override
+ Widget build(BuildContext context) {
+ return MyContainer(
+ onTap: onTap,
+ width: context.widthScreen,
+ height: 64,
+ borderRadius: const BorderRadius.all(Radius.circular(20)),
+ borderGradient: const LinearGradient(
+ begin: AlignmentDirectional.topStart,
+ end: AlignmentDirectional.bottomEnd,
+ colors: [
+ Color(0XFFFFD66E),
+ Color(0XFFD28F18),
+ ]
+ ),
+ gradient: const RadialGradient(
+ radius: 5,
+ center: Alignment(-0.5, 0),
+ colors: [
+ Color(0xFFF6BA0C),
+ Color(0xFFCD8402),
+ ],
+ ),
+ child: GradientText(
+ text: title,
+ fontSize: 22,
+ color: const Color(0xFFF5D69F),
+ offset: const Offset(0, 1.04),
+ blurRadius: 0.52,
+ shadowColor: const Color(0xFFC48F30),
+ ),
+ );
+ }
+}
diff --git a/lib/features/battle_league/presentation/ui/widgets/battle_league_tab_bar.dart b/lib/features/battle_league/presentation/ui/widgets/battle_league_tab_bar.dart
new file mode 100644
index 0000000..748254e
--- /dev/null
+++ b/lib/features/battle_league/presentation/ui/widgets/battle_league_tab_bar.dart
@@ -0,0 +1,39 @@
+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/common_ui/theme/my_theme.dart';
+
+class BattleLeagueTabBar extends StatelessWidget {
+ const BattleLeagueTabBar({
+ super.key,
+ required this.controller,
+ required this.tabs,
+ });
+
+ final TabController controller;
+ final List tabs;
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ padding: const EdgeInsets.all(3),
+ decoration: const BoxDecoration(
+ borderRadius: BorderRadius.all(Radius.circular(MySpaces.s10)),
+ color: Color(0XFF310D6F),
+ ),
+ child: TabBar(
+ controller: controller,
+ tabs: tabs.map((e) => Tab(text: e)).toList(),
+ indicator: const BoxDecoration(
+ borderRadius: BorderRadius.all(Radius.circular(MySpaces.s8)),
+ color: Color(0XFF897AB8),
+ ),
+ indicatorSize: TabBarIndicatorSize.tab,
+ labelColor: context.primaryColor,
+ unselectedLabelColor: const Color(0XFF897AB8),
+ labelStyle: Lexend.semiBold.copyWith(fontSize: 14),
+ dividerHeight: 0,
+ ),
+ );
+ }
+}
diff --git a/lib/features/battle_league/presentation/ui/widgets/filter_ranking_button.dart b/lib/features/battle_league/presentation/ui/widgets/filter_ranking_button.dart
new file mode 100644
index 0000000..3d853f6
--- /dev/null
+++ b/lib/features/battle_league/presentation/ui/widgets/filter_ranking_button.dart
@@ -0,0 +1,42 @@
+import 'package:flutter/material.dart';
+import 'package:shia_game_flutter/common_ui/resources/my_colors.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/widgets/container/my_container.dart';
+
+class FilterRankingButton extends StatelessWidget {
+ const FilterRankingButton({
+ super.key,
+ this.onTap,
+ this.title,
+ this.select = false,
+ });
+
+ final VoidCallback? onTap;
+ final String? title;
+ final bool select;
+
+ @override
+ Widget build(BuildContext context) {
+ return MyContainer(
+ onTap: select ? null : onTap,
+ padding: const EdgeInsets.symmetric(vertical: MySpaces.s16),
+ borderRadius: const BorderRadius.all(Radius.circular(7)),
+ color: select ? null : MyColors.black.withValues(alpha: 0.2),
+ gradient: select
+ ? const LinearGradient(
+ begin: Alignment.topCenter,
+ end: Alignment.bottomCenter,
+ colors: [Color(0XFFA672FF), Color(0XFF5B1DC3)],
+ )
+ : null,
+ child: Text(
+ title ?? '',
+ style: Lexend.semiBold.copyWith(
+ fontSize: 12,
+ color: select ? MyColors.white : const Color(0XFFBCA1EA),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/features/battle_league/presentation/ui/widgets/my_ranking_widget.dart b/lib/features/battle_league/presentation/ui/widgets/my_ranking_widget.dart
new file mode 100644
index 0000000..7cbb774
--- /dev/null
+++ b/lib/features/battle_league/presentation/ui/widgets/my_ranking_widget.dart
@@ -0,0 +1,35 @@
+import 'package:flutter/material.dart';
+import 'package:shia_game_flutter/common_ui/resources/my_assets.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';
+
+class MyRankingWidget extends StatelessWidget {
+ const MyRankingWidget({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return SizedBox(
+ height: 48,
+ child: Row(
+ children: [
+ Text('1', style: Lexend.extraBold.copyWith(fontSize: 12)),
+ MySpaces.s20.gapWidth,
+ const MyImage(asset: MyAssets.sampleAvatar, size: MySpaces.s20),
+ MySpaces.s6.gapWidth,
+ Expanded(
+ child: Text(
+ 'Amirreza',
+ style: Lexend.medium.copyWith(fontSize: 12),
+ ),
+ ),
+ MySpaces.s6.gapWidth,
+ const MyImage(asset: MyAssets.iconRank),
+ MySpaces.s6.gapWidth,
+ Text('1234', style: Lexend.black.copyWith(fontSize: 12)),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/features/battle_league/presentation/ui/widgets/ranking_region.dart b/lib/features/battle_league/presentation/ui/widgets/ranking_region.dart
new file mode 100644
index 0000000..8099757
--- /dev/null
+++ b/lib/features/battle_league/presentation/ui/widgets/ranking_region.dart
@@ -0,0 +1,35 @@
+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/my_localization.dart';
+
+class RankingRegion extends StatelessWidget {
+ const RankingRegion({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ spacing: MySpaces.s2,
+ children: [
+ const Icon(
+ Icons.location_on_rounded,
+ size: MySpaces.s18,
+ color: Color(0xFF8249E2),
+ ),
+ Text.rich(
+ style: Lexend.medium.copyWith(fontSize: 12),
+ TextSpan(
+ text: '${context.translate.region}: ',
+ style: const TextStyle(color: Color(0xFF8249E2)),
+ children: [
+ const TextSpan(
+ text: 'Iran - Tehran',
+ style: TextStyle(color: Color(0xFFBCA1EA)),
+ ),
+ ],
+ ),
+ ),
+ ],
+ );
+ }
+}
diff --git a/lib/features/battle_league/presentation/ui/widgets/ranking_scrollbar.dart b/lib/features/battle_league/presentation/ui/widgets/ranking_scrollbar.dart
new file mode 100644
index 0000000..70577f5
--- /dev/null
+++ b/lib/features/battle_league/presentation/ui/widgets/ranking_scrollbar.dart
@@ -0,0 +1,29 @@
+import 'package:flutter/material.dart';
+import 'package:shia_game_flutter/common_ui/resources/my_spaces.dart';
+
+class RankingScrollbar extends StatelessWidget {
+ const RankingScrollbar({
+ super.key,
+ required this.child,
+ required this.scrollController,
+ });
+
+ final Widget child;
+ final ScrollController scrollController;
+
+ @override
+ Widget build(BuildContext context) {
+ return RawScrollbar(
+ controller: scrollController,
+ thumbVisibility: true,
+ thumbColor: const Color(0XFF935BE0),
+ trackColor: const Color(0XFF541E9E),
+ trackRadius: const Radius.circular(10),
+ radius: const Radius.circular(10),
+ thickness: 3,
+ crossAxisMargin: MySpaces.s0,
+ trackVisibility: true,
+ child: child,
+ );
+ }
+}
diff --git a/lib/features/battle_league/presentation/ui/widgets/ranking_time.dart b/lib/features/battle_league/presentation/ui/widgets/ranking_time.dart
new file mode 100644
index 0000000..a10faad
--- /dev/null
+++ b/lib/features/battle_league/presentation/ui/widgets/ranking_time.dart
@@ -0,0 +1,62 @@
+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/common_ui/theme/my_theme.dart';
+import 'package:shia_game_flutter/core/utils/gap.dart';
+import 'package:shia_game_flutter/core/widgets/container/my_container.dart';
+
+class RankingTime extends StatelessWidget {
+ const RankingTime({
+ super.key,
+ required this.filterTitles,
+ required this.selectedIndex,
+ });
+
+ final List filterTitles;
+ final int selectedIndex;
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ children: [
+ Text(
+ '1ST ${filterTitles[selectedIndex]}',
+ style: Lexend.black.copyWith(
+ fontSize: 14,
+ ),
+ ),
+ MySpaces.s8.gapWidth,
+ Text(
+ '(May 2024)',
+ style: Lexend.medium.copyWith(
+ fontSize: 10,
+ ),
+ ),
+ const Spacer(),
+ MyContainer(
+ height: MySpaces.s32,
+ width: MySpaces.s32,
+ borderRadius: const BorderRadius.all(Radius.circular(7)),
+ color: const Color(0XFF5210AC),
+ child: Icon(
+ Icons.arrow_back_ios_rounded,
+ color: context.primaryColor,
+ size: MySpaces.s18,
+ ),
+ ),
+ MySpaces.s10.gapWidth,
+ MyContainer(
+ height: MySpaces.s32,
+ width: MySpaces.s32,
+ borderRadius: const BorderRadius.all(Radius.circular(7)),
+ color: const Color(0XFF5210AC),
+ child: Icon(
+ Icons.arrow_forward_ios_rounded,
+ color: context.primaryColor,
+ size: MySpaces.s18,
+ ),
+ )
+ ],
+ );
+ }
+}
\ No newline at end of file
diff --git a/lib/features/battle_league/presentation/ui/widgets/ranking_widget.dart b/lib/features/battle_league/presentation/ui/widgets/ranking_widget.dart
new file mode 100644
index 0000000..e6f7c32
--- /dev/null
+++ b/lib/features/battle_league/presentation/ui/widgets/ranking_widget.dart
@@ -0,0 +1,42 @@
+import 'package:flutter/material.dart';
+import 'package:shia_game_flutter/common_ui/resources/my_assets.dart';
+import 'package:shia_game_flutter/common_ui/resources/my_colors.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';
+
+class RankingWidget extends StatelessWidget {
+ const RankingWidget({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ height: 48,
+ decoration: BoxDecoration(
+ borderRadius: const BorderRadius.all(Radius.circular(MySpaces.s10)),
+ color: MyColors.black.withValues(alpha: 0.2),
+ ),
+ child: Row(
+ children: [
+ MySpaces.s10.gapWidth,
+ Text('1', style: Lexend.extraBold.copyWith(fontSize: 12)),
+ MySpaces.s20.gapWidth,
+ const MyImage(asset: MyAssets.sampleAvatar, size: MySpaces.s20),
+ MySpaces.s6.gapWidth,
+ Expanded(
+ child: Text(
+ 'Amirreza',
+ style: Lexend.medium.copyWith(fontSize: 12),
+ ),
+ ),
+ MySpaces.s6.gapWidth,
+ const MyImage(asset: MyAssets.iconRank),
+ MySpaces.s6.gapWidth,
+ Text('1234', style: Lexend.black.copyWith(fontSize: 12)),
+ MySpaces.s30.gapWidth,
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/features/battle_league/presentation/ui/widgets/regional_ranking.dart b/lib/features/battle_league/presentation/ui/widgets/regional_ranking.dart
new file mode 100644
index 0000000..c34f63e
--- /dev/null
+++ b/lib/features/battle_league/presentation/ui/widgets/regional_ranking.dart
@@ -0,0 +1,91 @@
+import 'package:flutter/material.dart';
+import 'package:shia_game_flutter/common_ui/resources/my_spaces.dart';
+import 'package:shia_game_flutter/core/utils/gap.dart';
+import 'package:shia_game_flutter/core/utils/my_localization.dart';
+import 'package:shia_game_flutter/features/battle_league/presentation/ui/widgets/filter_ranking_button.dart';
+import 'package:shia_game_flutter/features/battle_league/presentation/ui/widgets/my_ranking_widget.dart';
+import 'package:shia_game_flutter/features/battle_league/presentation/ui/widgets/ranking_region.dart';
+import 'package:shia_game_flutter/features/battle_league/presentation/ui/widgets/ranking_scrollbar.dart';
+import 'package:shia_game_flutter/features/battle_league/presentation/ui/widgets/ranking_widget.dart';
+
+class RegionalRanking extends StatefulWidget {
+ const RegionalRanking({super.key});
+
+ @override
+ State createState() => _RegionalRankingState();
+}
+
+class _RegionalRankingState extends State {
+ late final List filterTitles;
+ int selectedIndex = 0;
+ final ScrollController scrollController = ScrollController();
+
+ @override
+ void didChangeDependencies() {
+ super.didChangeDependencies();
+ filterTitles = [
+ context.translate.country,
+ context.translate.city,
+ ];
+ }
+
+ @override
+ void dispose() {
+ scrollController.dispose();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ padding: const EdgeInsets.only(
+ top: MySpaces.s12,
+ left: MySpaces.s12,
+ right: MySpaces.s12,
+ ),
+ decoration: const BoxDecoration(
+ borderRadius: BorderRadius.all(Radius.circular(MySpaces.s10)),
+ color: Color(0XFF310D6F),
+ ),
+ child: Column(
+ children: [
+ Row(
+ spacing: MySpaces.s10,
+ children: List.generate(
+ filterTitles.length,
+ (index) => Expanded(
+ child: FilterRankingButton(
+ onTap: () {
+ setState(() {
+ selectedIndex = index;
+ });
+ },
+ title: filterTitles[index],
+ select: index == selectedIndex,
+ ),
+ ),
+ ),
+ ),
+ MySpaces.s22.gapHeight,
+ const RankingRegion(),
+ MySpaces.s12.gapHeight,
+ Expanded(
+ child: RankingScrollbar(
+ scrollController: scrollController,
+ child: ListView.separated(
+ controller: scrollController,
+ itemCount: 10,
+ padding: const EdgeInsetsDirectional.only(end: MySpaces.s14),
+ itemBuilder: (context, index) => const RankingWidget(),
+ separatorBuilder: (context, index) => MySpaces.s10.gapHeight,
+ ),
+ ),
+ ),
+ const MyRankingWidget(),
+ ],
+ ),
+ );
+ }
+}
+
+
diff --git a/lib/features/battle_league/presentation/ui/widgets/time_ranking.dart b/lib/features/battle_league/presentation/ui/widgets/time_ranking.dart
new file mode 100644
index 0000000..dbaf45b
--- /dev/null
+++ b/lib/features/battle_league/presentation/ui/widgets/time_ranking.dart
@@ -0,0 +1,95 @@
+import 'package:flutter/material.dart';
+import 'package:shia_game_flutter/common_ui/resources/my_spaces.dart';
+import 'package:shia_game_flutter/core/utils/gap.dart';
+import 'package:shia_game_flutter/core/utils/my_localization.dart';
+import 'package:shia_game_flutter/features/battle_league/presentation/ui/widgets/filter_ranking_button.dart';
+import 'package:shia_game_flutter/features/battle_league/presentation/ui/widgets/my_ranking_widget.dart';
+import 'package:shia_game_flutter/features/battle_league/presentation/ui/widgets/ranking_scrollbar.dart';
+import 'package:shia_game_flutter/features/battle_league/presentation/ui/widgets/ranking_time.dart';
+import 'package:shia_game_flutter/features/battle_league/presentation/ui/widgets/ranking_widget.dart';
+
+class TimeRanking extends StatefulWidget {
+ const TimeRanking({super.key});
+
+ @override
+ State createState() => _TimeRankingState();
+}
+
+class _TimeRankingState extends State {
+ late final List filterTitles;
+ int selectedIndex = 0;
+ final ScrollController scrollController = ScrollController();
+
+ @override
+ void didChangeDependencies() {
+ super.didChangeDependencies();
+ filterTitles = [
+ context.translate.all_time,
+ context.translate.month,
+ context.translate.week,
+ ];
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ scrollController.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ padding: const EdgeInsets.only(
+ top: MySpaces.s12,
+ left: MySpaces.s12,
+ right: MySpaces.s12,
+ ),
+ decoration: const BoxDecoration(
+ borderRadius: BorderRadius.all(Radius.circular(MySpaces.s10)),
+ color: Color(0XFF310D6F),
+ ),
+ child: Column(
+ children: [
+ Row(
+ spacing: MySpaces.s10,
+ children: List.generate(
+ filterTitles.length,
+ (index) => Expanded(
+ child: FilterRankingButton(
+ onTap: () {
+ setState(() {
+ selectedIndex = index;
+ });
+ },
+ title: filterTitles[index],
+ select: index == selectedIndex,
+ ),
+ ),
+ ),
+ ),
+ MySpaces.s22.gapHeight,
+ if(selectedIndex != 0) ...{
+ RankingTime(
+ filterTitles: filterTitles,
+ selectedIndex: selectedIndex,
+ ),
+ MySpaces.s12.gapHeight,
+ },
+ Expanded(
+ child: RankingScrollbar(
+ scrollController: scrollController,
+ child: ListView.separated(
+ controller: scrollController,
+ itemCount: 10,
+ padding: const EdgeInsetsDirectional.only(end: MySpaces.s14),
+ itemBuilder: (context, index) => const RankingWidget(),
+ separatorBuilder: (context, index) => MySpaces.s10.gapHeight,
+ ),
+ ),
+ ),
+ const MyRankingWidget(),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/features/master/presentation/ui/master_page.dart b/lib/features/master/presentation/ui/master_page.dart
index d47546c..79786e2 100644
--- a/lib/features/master/presentation/ui/master_page.dart
+++ b/lib/features/master/presentation/ui/master_page.dart
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:shia_game_flutter/core/routers/my_routes.dart';
-import 'package:shia_game_flutter/core/widgets/app_bar/master_app_bar.dart';
+import 'package:shia_game_flutter/core/widgets/app_bar/styles/master_app_bar.dart';
import 'package:shia_game_flutter/core/widgets/bottom_nav_bar/bottom_nav_bar.dart';
import 'package:shia_game_flutter/features/master/presentation/controller/master_controller.dart';
import 'package:get/get.dart';
diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb
index f761f5f..1363b7c 100644
--- a/lib/l10n/app_en.arb
+++ b/lib/l10n/app_en.arb
@@ -28,5 +28,13 @@
"second_place": "Second Place",
"third_place": "Third Place",
"week": "Week",
- "do_not_have_award": "Don't Have Award"
+ "month": "Month",
+ "all_time": "All Time",
+ "do_not_have_award": "Don't Have Award",
+ "time_ranking": "Time Ranking",
+ "regional_ranking": "Regional Ranking",
+ "play_now": "Play Now",
+ "country": "Country",
+ "city": "City",
+ "region": "Region"
}
\ No newline at end of file
diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart
index a9d3172..4076f4a 100644
--- a/lib/l10n/app_localizations.dart
+++ b/lib/l10n/app_localizations.dart
@@ -262,11 +262,59 @@ abstract class AppLocalizations {
/// **'Week'**
String get week;
+ /// No description provided for @month.
+ ///
+ /// In en, this message translates to:
+ /// **'Month'**
+ String get month;
+
+ /// No description provided for @all_time.
+ ///
+ /// In en, this message translates to:
+ /// **'All Time'**
+ String get all_time;
+
/// No description provided for @do_not_have_award.
///
/// In en, this message translates to:
/// **'Don\'t Have Award'**
String get do_not_have_award;
+
+ /// No description provided for @time_ranking.
+ ///
+ /// In en, this message translates to:
+ /// **'Time Ranking'**
+ String get time_ranking;
+
+ /// No description provided for @regional_ranking.
+ ///
+ /// In en, this message translates to:
+ /// **'Regional Ranking'**
+ String get regional_ranking;
+
+ /// No description provided for @play_now.
+ ///
+ /// In en, this message translates to:
+ /// **'Play Now'**
+ String get play_now;
+
+ /// No description provided for @country.
+ ///
+ /// In en, this message translates to:
+ /// **'Country'**
+ String get country;
+
+ /// No description provided for @city.
+ ///
+ /// In en, this message translates to:
+ /// **'City'**
+ String get city;
+
+ /// No description provided for @region.
+ ///
+ /// In en, this message translates to:
+ /// **'Region'**
+ String get region;
}
class _AppLocalizationsDelegate
diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart
index 23f7712..0b5f8e8 100644
--- a/lib/l10n/app_localizations_en.dart
+++ b/lib/l10n/app_localizations_en.dart
@@ -92,6 +92,30 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get week => 'Week';
+ @override
+ String get month => 'Month';
+
+ @override
+ String get all_time => 'All Time';
+
@override
String get do_not_have_award => 'Don\'t Have Award';
+
+ @override
+ String get time_ranking => 'Time Ranking';
+
+ @override
+ String get regional_ranking => 'Regional Ranking';
+
+ @override
+ String get play_now => 'Play Now';
+
+ @override
+ String get country => 'Country';
+
+ @override
+ String get city => 'City';
+
+ @override
+ String get region => 'Region';
}
diff --git a/lib/main.dart b/lib/main.dart
index 98bea17..2939bb2 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -31,7 +31,7 @@ class MainApp extends StatelessWidget {
fallbackLocale: const Locale('en', 'US'),
supportedLocales: const [Locale('en', 'US')],
getPages: appPages,
- initialRoute: Routes.masterPage,
+ initialRoute: Routes.battleLeaguePage,
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
diff --git a/pubspec.lock b/pubspec.lock
index fc3519b..88903b8 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -73,6 +73,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.1"
+ draggable_scrollbar:
+ dependency: "direct main"
+ description:
+ name: draggable_scrollbar
+ sha256: a906e27fc1ee056e2942d66989dd0cb5b70a361e7d44af566cfa1b584054eac3
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.1.0"
equatable:
dependency: "direct main"
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index a55a011..0852b32 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -8,6 +8,7 @@ environment:
dependencies:
dio: ^5.9.0
+ draggable_scrollbar: ^0.1.0
equatable: ^2.0.7
flutter:
sdk: flutter