diff --git a/analysis_options.yaml b/analysis_options.yaml index f9b3034..31e4275 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1 +1,14 @@ include: package:flutter_lints/flutter.yaml + +linter: + rules: + prefer_const_constructors: true + prefer_const_declarations: true + prefer_const_constructors_in_immutables: true + prefer_final_fields: true + prefer_final_locals: true + avoid_classes_with_only_static_members: true + avoid_print: true + always_declare_return_types: true + use_key_in_widget_constructors: true + require_trailing_commas: true \ No newline at end of file diff --git a/assets/svg/cast_award_bronze.svg b/assets/svg/cast_award_bronze.svg new file mode 100644 index 0000000..65fcbec --- /dev/null +++ b/assets/svg/cast_award_bronze.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/svg/cast_award_gold.svg b/assets/svg/cast_award_gold.svg new file mode 100644 index 0000000..6e58ad5 --- /dev/null +++ b/assets/svg/cast_award_gold.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/svg/cast_award_silver.svg b/assets/svg/cast_award_silver.svg new file mode 100644 index 0000000..f95b5e4 --- /dev/null +++ b/assets/svg/cast_award_silver.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/svg/custom_award_bronze.svg b/assets/svg/custom_award_bronze.svg new file mode 100644 index 0000000..c41ec8f --- /dev/null +++ b/assets/svg/custom_award_bronze.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/svg/custom_award_gold.svg b/assets/svg/custom_award_gold.svg new file mode 100644 index 0000000..2bf43bf --- /dev/null +++ b/assets/svg/custom_award_gold.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/svg/custom_award_silver.svg b/assets/svg/custom_award_silver.svg new file mode 100644 index 0000000..732f668 --- /dev/null +++ b/assets/svg/custom_award_silver.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/svg/league_award_bronze.svg b/assets/svg/league_award_bronze.svg new file mode 100644 index 0000000..5392a27 --- /dev/null +++ b/assets/svg/league_award_bronze.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/svg/league_award_gold.svg b/assets/svg/league_award_gold.svg new file mode 100644 index 0000000..ae95d08 --- /dev/null +++ b/assets/svg/league_award_gold.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/svg/league_award_silver.svg b/assets/svg/league_award_silver.svg new file mode 100644 index 0000000..2af9688 --- /dev/null +++ b/assets/svg/league_award_silver.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/lib/common_ui/resources/my_assets.dart b/lib/common_ui/resources/my_assets.dart index d6a78dc..98c589f 100644 --- a/lib/common_ui/resources/my_assets.dart +++ b/lib/common_ui/resources/my_assets.dart @@ -54,6 +54,15 @@ class MyAssets { static const String iconInfo = 'assets/svg/icon_info.svg'; static const String gem = 'assets/svg/gem.svg'; static const String lock = 'assets/svg/lock.svg'; + static const String leagueAwardGold = 'assets/svg/league_award_gold.svg'; + static const String leagueAwardSilver = 'assets/svg/league_award_silver.svg'; + static const String leagueAwardBronze = 'assets/svg/league_award_bronze.svg'; + static const String customAwardGold = 'assets/svg/custom_award_gold.svg'; + static const String customAwardSilver = 'assets/svg/custom_award_silver.svg'; + static const String customAwardBronze = 'assets/svg/custom_award_bronze.svg'; + 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'; /// ----- Audios ----- diff --git a/lib/common_ui/resources/my_text_style.dart b/lib/common_ui/resources/my_text_style.dart index 0f11748..d779438 100644 --- a/lib/common_ui/resources/my_text_style.dart +++ b/lib/common_ui/resources/my_text_style.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:shia_game_flutter/common_ui/resources/my_colors.dart'; class Lexend { static const Lexend _i = Lexend._internal(); @@ -6,49 +7,59 @@ class Lexend { factory Lexend() => _i; static const String fontFamily = 'Lexend'; + static const Color textColor = MyColors.white; static const TextStyle thin = TextStyle( fontFamily: fontFamily, fontWeight: FontWeight.w100, + color: textColor, ); static const TextStyle extraLight = TextStyle( fontFamily: fontFamily, fontWeight: FontWeight.w200, + color: textColor, ); static const TextStyle light = TextStyle( fontFamily: fontFamily, fontWeight: FontWeight.w300, + color: textColor, ); static const TextStyle regular = TextStyle( fontFamily: fontFamily, fontWeight: FontWeight.w400, + color: textColor, ); static const TextStyle medium = TextStyle( fontFamily: fontFamily, fontWeight: FontWeight.w500, + color: textColor, ); static const TextStyle semiBold = TextStyle( fontFamily: fontFamily, fontWeight: FontWeight.w600, + color: textColor, ); static const TextStyle bold = TextStyle( fontFamily: fontFamily, fontWeight: FontWeight.w700, + color: textColor, ); static const TextStyle extraBold = TextStyle( fontFamily: fontFamily, fontWeight: FontWeight.w800, + color: textColor, ); static const TextStyle black = TextStyle( fontFamily: fontFamily, fontWeight: FontWeight.w900, + color: textColor, ); } diff --git a/lib/core/utils/page_scalable.dart b/lib/core/utils/page_scalable.dart new file mode 100644 index 0000000..c729e6b --- /dev/null +++ b/lib/core/utils/page_scalable.dart @@ -0,0 +1,15 @@ +class PageScalable { + static const PageScalable _i = PageScalable._internal(); + const PageScalable._internal(); + factory PageScalable() => _i; + + static double scale({ + required double currentPage, + required int index, + required double scaleFactor, + }) { + final double difference = (currentPage - index).abs(); + final double scale = 1 - (difference * scaleFactor).clamp(0.0, scaleFactor); + return scale; + } +} diff --git a/lib/core/widgets/text/gradient_text.dart b/lib/core/widgets/text/gradient_text.dart index ed0ec13..c5be681 100644 --- a/lib/core/widgets/text/gradient_text.dart +++ b/lib/core/widgets/text/gradient_text.dart @@ -14,6 +14,7 @@ class GradientText extends StatelessWidget { this.spreadRadius = 0, this.offset = Offset.zero, this.textAlign, + this.textStyle, }); final String? text; @@ -25,6 +26,7 @@ class GradientText extends StatelessWidget { final double spreadRadius; final Offset offset; final TextAlign? textAlign; + final TextStyle? textStyle; @override Widget build(BuildContext context) { @@ -43,7 +45,7 @@ class GradientText extends StatelessWidget { text ?? '', textAlign: textAlign, maxLines: 1, - style: Lexend.extraBold.copyWith( + style: textStyle ?? Lexend.extraBold.copyWith( fontSize: fontSize, shadows: [ BoxShadow( diff --git a/lib/features/awards/presentation/controller/awards_controller.dart b/lib/features/awards/presentation/controller/awards_controller.dart index e1b0bb4..d8ef81f 100644 --- a/lib/features/awards/presentation/controller/awards_controller.dart +++ b/lib/features/awards/presentation/controller/awards_controller.dart @@ -1,4 +1,5 @@ import 'package:flutter/cupertino.dart'; +import 'package:shia_game_flutter/common_ui/resources/my_assets.dart'; import 'package:shia_game_flutter/core/params/awards_params.dart'; import 'package:shia_game_flutter/core/status/base_status.dart'; import 'package:shia_game_flutter/features/awards/domain/entity/awards_entity.dart'; @@ -27,6 +28,22 @@ class AwardsController extends GetxController with StateMixin { /// ----- Variables ----- final Rx awardsParams = Rx(AwardsParams()); final Rx awardsEntity = Rx(const AwardsEntity()); + final RxDouble currentPage = RxDouble(0); + final List leagueAwards = [ + MyAssets.leagueAwardGold, + MyAssets.leagueAwardSilver, + MyAssets.leagueAwardBronze, + ]; + final List customAwards = [ + MyAssets.customAwardGold, + MyAssets.customAwardSilver, + MyAssets.customAwardBronze, + ]; + final List castAwards = [ + MyAssets.castAwardGold, + MyAssets.castAwardSilver, + MyAssets.castAwardBronze, + ]; /// ------ Controllers ------ final TextEditingController textEditingController = TextEditingController(); diff --git a/lib/features/awards/presentation/ui/awards_page.dart b/lib/features/awards/presentation/ui/awards_page.dart index f7d27b5..cda3c81 100644 --- a/lib/features/awards/presentation/ui/awards_page.dart +++ b/lib/features/awards/presentation/ui/awards_page.dart @@ -1,14 +1,33 @@ import 'package:flutter/material.dart'; -import 'package:shia_game_flutter/features/awards/presentation/controller/awards_controller.dart'; import 'package:get/get.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/background/my_background.dart'; +import 'package:shia_game_flutter/features/awards/presentation/controller/awards_controller.dart'; +import 'package:shia_game_flutter/features/awards/presentation/ui/widgets/award_widget.dart'; class AwardsPage extends GetView { const AwardsPage({super.key}); @override Widget build(BuildContext context) { - return const Center( - child: Text('Awards Page'), + return MyBackground( + child: Column( + children: [ + 60.0.gapHeight, + AwardWidget( + images: controller.leagueAwards, + ), + MySpaces.s28.gapHeight, + AwardWidget( + images: controller.customAwards, + ), + MySpaces.s28.gapHeight, + AwardWidget( + images: controller.castAwards, + ), + ], + ), ); } } diff --git a/lib/features/awards/presentation/ui/widgets/award_widget.dart b/lib/features/awards/presentation/ui/widgets/award_widget.dart new file mode 100644 index 0000000..06fe414 --- /dev/null +++ b/lib/features/awards/presentation/ui/widgets/award_widget.dart @@ -0,0 +1,186 @@ +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'; +import 'package:shia_game_flutter/core/utils/page_scalable.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/image/my_image.dart'; +import 'package:shia_game_flutter/core/widgets/text/gradient_text.dart'; + +class AwardWidget extends StatefulWidget { + const AwardWidget({super.key, required this.images}); + + final List images; + + @override + State createState() => _AwardWidgetState(); +} + +class _AwardWidgetState extends State { + final PageController pageController = PageController(viewportFraction: 0.35); + double currentPage = 0; + + void pageControllerListener() { + setState(() { + currentPage = pageController.page ?? 0; + }); + } + + void goToPrePage() { + pageController.previousPage( + duration: const Duration(milliseconds: 300), + curve: Curves.easeIn, + ); + } + + void goToNextPage() { + pageController.nextPage( + duration: const Duration(milliseconds: 300), + curve: Curves.easeIn, + ); + } + + @override + void initState() { + super.initState(); + pageController.addListener(pageControllerListener); + } + + @override + void dispose() { + pageController + ..removeListener(pageControllerListener) + ..dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Stack( + alignment: Alignment.center, + clipBehavior: Clip.none, + children: [ + MyContainer( + width: context.widthScreen, + borderRadius: const BorderRadius.all(Radius.circular(12)), + borderGradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + const Color(0XFF7D44CC), + const Color(0XFF7D44CC).withValues(alpha: 0), + ], + ), + color: const Color(0XFF2B105A), + padding: const EdgeInsets.only( + bottom: MySpaces.s10, + top: MySpaces.s40, + ), + child: Column( + spacing: MySpaces.s12, + children: [ + SizedBox( + height: 100, + child: Stack( + alignment: Alignment.center, + children: [ + Padding( + padding: const EdgeInsets.symmetric( + horizontal: MySpaces.s16, + ), + child: PageView.builder( + controller: pageController, + itemCount: widget.images.length, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + return Transform.scale( + scale: PageScalable.scale( + currentPage: currentPage, + index: index, + scaleFactor: 0.4, + ), + child: MyImage(asset: widget.images[index]), + ); + }, + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + IconButton( + onPressed: currentPage == 0 ? null : goToPrePage, + icon: const Icon(Icons.keyboard_arrow_left_rounded), + iconSize: 30, + ), + IconButton( + onPressed: currentPage == widget.images.length - 1 + ? null + : goToNextPage, + icon: const Icon(Icons.keyboard_arrow_right_rounded), + iconSize: 30, + ), + ], + ), + ], + ), + ), + Column( + spacing: MySpaces.s2, + children: [ + Text( + context.translate.first_place, + style: Lexend.extraBold.copyWith(fontSize: 14), + ), + GradientText( + text: '1ST Week (May 2024)', + textStyle: Lexend.semiBold.copyWith( + fontSize: 10, + shadows: [ + const BoxShadow( + color: Color(0XFF3E1381), + offset: Offset(0, 1.69), + blurRadius: 0.84, + ), + ], + ), + color: const Color(0XFFCAA8FF), + ), + ], + ), + ], + ), + ), + Positioned( + top: -MySpaces.s14, + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: MySpaces.s10, + vertical: MySpaces.s6, + ), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(12)), + color: Color(0XFF7D44CB), + ), + child: Opacity( + opacity: 0.6, + child: GradientText( + text: context.translate.battle_league_awards, + color: const Color(0XFFCAA8FF), + textStyle: Lexend.medium.copyWith( + fontSize: 14, + shadows: [ + const BoxShadow( + color: Color(0XFF3E1381), + offset: Offset(0, 0.69), + ), + ], + ), + ), + ), + ), + ), + ], + ); + } +} diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index dbb8f6e..f761f5f 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -20,5 +20,13 @@ "battle_cast": "Battle Cast", "no_one_online": "No one's online", "active": "Active", - "select": "Select" + "select": "Select", + "battle_league_awards": "Battle League Awards", + "custom_league_awards": "Custom League Awards", + "battle_cast_swards": "Custom Cast Awards", + "first_place": "First Place", + "second_place": "Second Place", + "third_place": "Third Place", + "week": "Week", + "do_not_have_award": "Don't Have Award" } \ No newline at end of file diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index b782c96..a9d3172 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -219,6 +219,54 @@ abstract class AppLocalizations { /// In en, this message translates to: /// **'Select'** String get select; + + /// No description provided for @battle_league_awards. + /// + /// In en, this message translates to: + /// **'Battle League Awards'** + String get battle_league_awards; + + /// No description provided for @custom_league_awards. + /// + /// In en, this message translates to: + /// **'Custom League Awards'** + String get custom_league_awards; + + /// No description provided for @battle_cast_swards. + /// + /// In en, this message translates to: + /// **'Custom Cast Awards'** + String get battle_cast_swards; + + /// No description provided for @first_place. + /// + /// In en, this message translates to: + /// **'First Place'** + String get first_place; + + /// No description provided for @second_place. + /// + /// In en, this message translates to: + /// **'Second Place'** + String get second_place; + + /// No description provided for @third_place. + /// + /// In en, this message translates to: + /// **'Third Place'** + String get third_place; + + /// No description provided for @week. + /// + /// In en, this message translates to: + /// **'Week'** + String get week; + + /// No description provided for @do_not_have_award. + /// + /// In en, this message translates to: + /// **'Don\'t Have Award'** + String get do_not_have_award; } class _AppLocalizationsDelegate diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index a3f8e1d..23f7712 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -70,4 +70,28 @@ class AppLocalizationsEn extends AppLocalizations { @override String get select => 'Select'; + + @override + String get battle_league_awards => 'Battle League Awards'; + + @override + String get custom_league_awards => 'Custom League Awards'; + + @override + String get battle_cast_swards => 'Custom Cast Awards'; + + @override + String get first_place => 'First Place'; + + @override + String get second_place => 'Second Place'; + + @override + String get third_place => 'Third Place'; + + @override + String get week => 'Week'; + + @override + String get do_not_have_award => 'Don\'t Have Award'; }