31 changed files with 977 additions and 76 deletions
-
9assets/svg/icon_rank.svg
-
1lib/common_ui/resources/my_assets.dart
-
36lib/core/widgets/app_bar/enums/app_bar_type.dart
-
57lib/core/widgets/app_bar/master_app_bar.dart
-
56lib/core/widgets/app_bar/my_app_bar.dart
-
40lib/core/widgets/app_bar/styles/battle_league_app_bar.dart
-
66lib/core/widgets/app_bar/styles/master_app_bar.dart
-
6lib/core/widgets/app_bar/widgets/app_bar_action.dart
-
16lib/core/widgets/app_bar/widgets/app_bar_add_widget.dart
-
27lib/core/widgets/app_bar/widgets/app_bar_back_button.dart
-
23lib/core/widgets/app_bar/widgets/app_bar_gradient_title.dart
-
29lib/core/widgets/app_bar/widgets/app_bar_info.dart
-
7lib/features/battle_league/presentation/controller/battle_league_controller.dart
-
66lib/features/battle_league/presentation/ui/battle_league_page.dart
-
49lib/features/battle_league/presentation/ui/widgets/battle_league_start_button.dart
-
39lib/features/battle_league/presentation/ui/widgets/battle_league_tab_bar.dart
-
42lib/features/battle_league/presentation/ui/widgets/filter_ranking_button.dart
-
35lib/features/battle_league/presentation/ui/widgets/my_ranking_widget.dart
-
35lib/features/battle_league/presentation/ui/widgets/ranking_region.dart
-
29lib/features/battle_league/presentation/ui/widgets/ranking_scrollbar.dart
-
62lib/features/battle_league/presentation/ui/widgets/ranking_time.dart
-
42lib/features/battle_league/presentation/ui/widgets/ranking_widget.dart
-
91lib/features/battle_league/presentation/ui/widgets/regional_ranking.dart
-
95lib/features/battle_league/presentation/ui/widgets/time_ranking.dart
-
2lib/features/master/presentation/ui/master_page.dart
-
10lib/l10n/app_en.arb
-
48lib/l10n/app_localizations.dart
-
24lib/l10n/app_localizations_en.dart
-
2lib/main.dart
-
8pubspec.lock
-
1pubspec.yaml
@ -0,0 +1,9 @@ |
|||||
|
<svg width="15" height="16" viewBox="0 0 15 16" fill="none" xmlns="http://www.w3.org/2000/svg"> |
||||
|
<path d="M14.4905 1.28128C14.2839 1.05706 13.9979 0.944945 13.696 0.944945C13.2511 0.944945 12.7267 1.16917 12.0753 1.63363V0.672673C12.0753 0.304304 11.7734 0 11.4238 0H3.79673C3.43127 0 3.14525 0.304304 3.14525 0.656657V1.79379C2.38255 1.21722 1.77874 0.928929 1.28616 0.928929C0.968364 0.928929 0.698238 1.04104 0.491672 1.26527C-0.0485779 1.82583 -0.0167985 2.94695 0.014981 3.93994C0.014981 4.13213 0.0308707 4.32432 0.0308707 4.48448C0.0308707 6.27828 1.79463 7.75175 4.01919 7.86386C4.67067 8.92092 5.79884 10.3624 7.19713 10.6186V12.9089C7.16535 12.9089 7.13357 12.9089 7.10179 12.9089C6.41853 12.9089 5.75117 12.9249 5.2427 13.1652C4.63889 13.4535 4.32109 14.014 4.32109 14.8308V16H10.9312V14.8308C10.9312 14.014 10.6293 13.4374 10.0096 13.1652C9.50114 12.9249 8.84966 12.9089 8.15051 12.9089C8.11873 12.9089 8.08695 12.9089 8.05517 12.9089V10.6186C9.46936 10.3624 10.5975 8.88889 11.249 7.84785C13.3464 7.63964 14.9831 6.21421 14.9831 4.48448C14.9831 4.32432 14.9831 4.14815 14.999 3.93994C14.999 2.96296 15.0466 1.84184 14.4905 1.28128ZM0.857136 4.48448C0.857136 4.30831 0.857136 4.11612 0.841246 3.90791C0.825356 3.21922 0.777687 2.17818 1.07959 1.87387C1.11137 1.84184 1.15904 1.80981 1.27027 1.80981C1.50861 1.80981 2.03297 1.96997 3.12936 2.91491V5.49349C3.12936 5.86186 3.25648 6.42242 3.39949 6.75876C3.39949 6.75876 3.43127 6.82282 3.49483 6.95095C1.9853 6.67868 0.857136 5.68569 0.857136 4.48448ZM14.125 3.90791C14.125 4.11612 14.1092 4.30831 14.1092 4.48448C14.1092 5.60561 13.124 6.56657 11.7575 6.88689C11.8051 6.80681 11.821 6.75876 11.821 6.75876C11.964 6.42242 12.0912 5.86186 12.0912 5.49349V2.70671C13.0287 1.93794 13.4895 1.80981 13.7119 1.80981C13.8231 1.80981 13.8708 1.84184 13.9026 1.87387C14.1727 2.17818 14.1409 3.21922 14.125 3.90791Z" fill="url(#paint0_linear_1_13784)"/> |
||||
|
<defs> |
||||
|
<linearGradient id="paint0_linear_1_13784" x1="7.50001" y1="8" x2="7.49996" y2="20.4686" gradientUnits="userSpaceOnUse"> |
||||
|
<stop stop-color="white"/> |
||||
|
<stop offset="1" stop-color="white" stop-opacity="0"/> |
||||
|
</linearGradient> |
||||
|
</defs> |
||||
|
</svg> |
||||
@ -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<AppBarType, Widget> 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, |
||||
|
), |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -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); |
|
||||
} |
|
||||
@ -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); |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
@ -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, |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -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, |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -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, |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -1,13 +1,73 @@ |
|||||
import 'package:flutter/material.dart'; |
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: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<BattleLeagueController> { |
class BattleLeaguePage extends GetView<BattleLeagueController> { |
||||
const BattleLeaguePage({super.key}); |
const BattleLeaguePage({super.key}); |
||||
|
|
||||
@override |
@override |
||||
Widget build(BuildContext context) { |
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, |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
@ -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), |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -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<String> 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, |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -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), |
||||
|
), |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -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)), |
||||
|
], |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -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)), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -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, |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -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<String> 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, |
||||
|
), |
||||
|
) |
||||
|
], |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -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, |
||||
|
], |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -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<RegionalRanking> createState() => _RegionalRankingState(); |
||||
|
} |
||||
|
|
||||
|
class _RegionalRankingState extends State<RegionalRanking> { |
||||
|
late final List<String> 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(), |
||||
|
], |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
@ -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<TimeRanking> createState() => _TimeRankingState(); |
||||
|
} |
||||
|
|
||||
|
class _TimeRankingState extends State<TimeRanking> { |
||||
|
late final List<String> 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(), |
||||
|
], |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue