diff --git a/assets/images/book_1.jpg b/assets/images/book_1.jpg new file mode 100644 index 0000000..26ce944 Binary files /dev/null and b/assets/images/book_1.jpg differ diff --git a/assets/images/book_2.jpg b/assets/images/book_2.jpg new file mode 100644 index 0000000..5b99c7c Binary files /dev/null and b/assets/images/book_2.jpg differ diff --git a/assets/images/book_3.png b/assets/images/book_3.png new file mode 100644 index 0000000..c734a28 Binary files /dev/null and b/assets/images/book_3.png differ diff --git a/assets/images/boost_1.png b/assets/images/boost_1.png new file mode 100644 index 0000000..eb9efec Binary files /dev/null and b/assets/images/boost_1.png differ diff --git a/assets/images/boost_2.png b/assets/images/boost_2.png new file mode 100644 index 0000000..8026adb Binary files /dev/null and b/assets/images/boost_2.png differ diff --git a/assets/images/boost_3.png b/assets/images/boost_3.png new file mode 100644 index 0000000..bd8d58d Binary files /dev/null and b/assets/images/boost_3.png differ diff --git a/assets/images/boost_4.png b/assets/images/boost_4.png new file mode 100644 index 0000000..796cd6b Binary files /dev/null and b/assets/images/boost_4.png differ diff --git a/assets/images/character_1.png b/assets/images/character_1.png new file mode 100644 index 0000000..4d1e1d6 Binary files /dev/null and b/assets/images/character_1.png differ diff --git a/assets/images/character_2.png b/assets/images/character_2.png new file mode 100644 index 0000000..5814b66 Binary files /dev/null and b/assets/images/character_2.png differ diff --git a/assets/images/character_3.png b/assets/images/character_3.png new file mode 100644 index 0000000..bd93e19 Binary files /dev/null and b/assets/images/character_3.png differ diff --git a/assets/images/gem_1.png b/assets/images/gem_1.png new file mode 100644 index 0000000..550cf77 Binary files /dev/null and b/assets/images/gem_1.png differ diff --git a/assets/images/gem_2.png b/assets/images/gem_2.png new file mode 100644 index 0000000..ed98414 Binary files /dev/null and b/assets/images/gem_2.png differ diff --git a/assets/images/gem_3.png b/assets/images/gem_3.png new file mode 100644 index 0000000..16253a1 Binary files /dev/null and b/assets/images/gem_3.png differ diff --git a/assets/images/gem_4.png b/assets/images/gem_4.png new file mode 100644 index 0000000..9b47010 Binary files /dev/null and b/assets/images/gem_4.png differ diff --git a/assets/images/member_1.png b/assets/images/member_1.png new file mode 100644 index 0000000..d549a03 Binary files /dev/null and b/assets/images/member_1.png differ diff --git a/assets/images/member_2.png b/assets/images/member_2.png new file mode 100644 index 0000000..0e5cd98 Binary files /dev/null and b/assets/images/member_2.png differ diff --git a/assets/images/member_3.png b/assets/images/member_3.png new file mode 100644 index 0000000..4b2ae22 Binary files /dev/null and b/assets/images/member_3.png differ diff --git a/assets/images/member_4.png b/assets/images/member_4.png new file mode 100644 index 0000000..b8bee5a Binary files /dev/null and b/assets/images/member_4.png differ diff --git a/assets/svg/gem.svg b/assets/svg/gem.svg new file mode 100644 index 0000000..f5e9a53 --- /dev/null +++ b/assets/svg/gem.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svg/icon_info.svg b/assets/svg/icon_info.svg new file mode 100644 index 0000000..ddc1e96 --- /dev/null +++ b/assets/svg/icon_info.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lib/common_ui/resources/my_assets.dart b/lib/common_ui/resources/my_assets.dart index f3092c6..6cf99fe 100644 --- a/lib/common_ui/resources/my_assets.dart +++ b/lib/common_ui/resources/my_assets.dart @@ -16,6 +16,24 @@ class MyAssets { static const String mic = 'assets/images/mic.png'; static const String micBLur = 'assets/images/mic_blur.png'; static const String sampleAvatar = 'assets/images/sample_avatar.png'; + static const String gem1 = 'assets/images/gem_1.png'; + static const String gem2 = 'assets/images/gem_2.png'; + static const String gem3 = 'assets/images/gem_3.png'; + static const String gem4 = 'assets/images/gem_4.png'; + static const String book1 = 'assets/images/book_1.jpg'; + static const String book2 = 'assets/images/book_2.jpg'; + static const String book3 = 'assets/images/book_3.png'; + static const String boost1 = 'assets/images/boost_1.png'; + static const String boost2 = 'assets/images/boost_2.png'; + static const String boost3 = 'assets/images/boost_3.png'; + static const String boost4 = 'assets/images/boost_4.png'; + static const String character1 = 'assets/images/character_1.png'; + static const String character2 = 'assets/images/character_2.png'; + static const String character3 = 'assets/images/character_3.png'; + static const String member1 = 'assets/images/member_1.png'; + static const String member2 = 'assets/images/member_2.png'; + static const String member3 = 'assets/images/member_3.png'; + static const String member4 = 'assets/images/member_4.png'; /// ----- Svg ----- static const String sampleSvg = 'assets/svg/sample.svg'; @@ -32,6 +50,9 @@ class MyAssets { static const String introStar = 'assets/svg/intro_star.svg'; static const String iconLocation = 'assets/svg/icon_location.svg'; static const String iconLogout = 'assets/svg/icon_logout.svg'; + static const String iconInfo = 'assets/svg/icon_info.svg'; + static const String gem = 'assets/svg/gem.svg'; + /// ----- Audios ----- static const String sampleAudio = 'assets/audios/sample.mp3'; diff --git a/lib/core/widgets/background/my_background.dart b/lib/core/widgets/background/my_background.dart index 7252a15..54c5604 100644 --- a/lib/core/widgets/background/my_background.dart +++ b/lib/core/widgets/background/my_background.dart @@ -3,9 +3,10 @@ import 'package:shia_game_flutter/common_ui/resources/my_spaces.dart'; import 'package:shia_game_flutter/common_ui/theme/my_theme.dart'; class MyBackground extends StatelessWidget { - const MyBackground({super.key, required this.child}); + const MyBackground({super.key, this.child, this.listChild}); - final Widget child; + final Widget? child; + final Widget? listChild; @override Widget build(BuildContext context) { @@ -16,7 +17,7 @@ class MyBackground extends StatelessWidget { colors: [const Color(0xFF321A6D), context.backgroundColor], ), ), - child: SingleChildScrollView( + child: listChild ?? SingleChildScrollView( padding: EdgeInsets.symmetric(horizontal: MySpaces.s30), child: child, ), diff --git a/lib/core/widgets/button/my_gradient_button.dart b/lib/core/widgets/button/my_gradient_button.dart index 3ce7d78..890c486 100644 --- a/lib/core/widgets/button/my_gradient_button.dart +++ b/lib/core/widgets/button/my_gradient_button.dart @@ -1,12 +1,22 @@ 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/widgets/container/my_container.dart'; import 'package:shia_game_flutter/core/widgets/text/gradient_text.dart'; class MyGradientButton extends StatelessWidget { - const MyGradientButton({super.key, this.onTap, this.title}); + const MyGradientButton({ + super.key, + this.onTap, + this.title, + this.fontSize, + this.icon, + }); final VoidCallback? onTap; final String? title; + final double? fontSize; + final Widget? icon; @override Widget build(BuildContext context) { @@ -21,12 +31,21 @@ class MyGradientButton extends StatelessWidget { end: AlignmentDirectional.bottomEnd, colors: [Color(0XFF823FEB), Color(0XFF4F09BF)], ), - child: GradientText( - text: title, - color: Color(0XFF9C8CC2), - shadowColor: Color(0xFF1B0D31), - offset: Offset(0, 1.69), - fontSize: 12, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GradientText( + text: title, + color: Color(0XFF9C8CC2), + shadowColor: Color(0xFF1B0D31), + offset: Offset(0, 1.69), + fontSize: fontSize ?? 12, + ), + if (icon != null) ...{ + MySpaces.s6.gapWidth, + icon ?? SizedBox.shrink(), + }, + ], ), ); } diff --git a/lib/core/widgets/text/gradient_text.dart b/lib/core/widgets/text/gradient_text.dart index e9da190..9a244fb 100644 --- a/lib/core/widgets/text/gradient_text.dart +++ b/lib/core/widgets/text/gradient_text.dart @@ -12,6 +12,7 @@ class GradientText extends StatelessWidget { this.blurRadius = 0, this.spreadRadius = 0, this.offset = Offset.zero, + this.textAlign, }); final String? text; @@ -21,6 +22,7 @@ class GradientText extends StatelessWidget { final double blurRadius; final double spreadRadius; final Offset offset; + final TextAlign? textAlign; @override Widget build(BuildContext context) { @@ -37,6 +39,8 @@ class GradientText extends StatelessWidget { ).createShader(bounds), child: Text( text ?? '', + textAlign: textAlign, + maxLines: 1, style: Lexend.extraBold.copyWith( fontSize: fontSize, shadows: [ diff --git a/lib/features/shop/data/model/shop_model.dart b/lib/features/shop/data/model/shop_model.dart index 3f3a933..362e5df 100644 --- a/lib/features/shop/data/model/shop_model.dart +++ b/lib/features/shop/data/model/shop_model.dart @@ -1,13 +1,9 @@ import 'package:shia_game_flutter/features/shop/domain/entity/shop_entity.dart'; class ShopModel extends ShopEntity { - const ShopModel({ - super.id, - }); + const ShopModel(); factory ShopModel.fromJson(Map json) { - return ShopModel( - id: json['id'], - ); + return ShopModel(); } } diff --git a/lib/features/shop/domain/entity/book_entity.dart b/lib/features/shop/domain/entity/book_entity.dart new file mode 100644 index 0000000..8f8f1b4 --- /dev/null +++ b/lib/features/shop/domain/entity/book_entity.dart @@ -0,0 +1,9 @@ +import 'package:shia_game_flutter/features/shop/domain/entity/shop_entity.dart'; + +class BookEntity extends ShopEntity { + const BookEntity({ + super.type = ShopType.book, + super.image, + super.title, + }); +} diff --git a/lib/features/shop/domain/entity/boost_entity.dart b/lib/features/shop/domain/entity/boost_entity.dart new file mode 100644 index 0000000..3538fb8 --- /dev/null +++ b/lib/features/shop/domain/entity/boost_entity.dart @@ -0,0 +1,11 @@ +import 'package:shia_game_flutter/features/shop/domain/entity/shop_entity.dart'; + +class BoostEntity extends ShopEntity { + const BoostEntity({ + super.type = ShopType.boost, + super.number, + super.price, + super.image, + super.title = 'Boost', + }); +} diff --git a/lib/features/shop/domain/entity/character_entity.dart b/lib/features/shop/domain/entity/character_entity.dart new file mode 100644 index 0000000..2edf2bc --- /dev/null +++ b/lib/features/shop/domain/entity/character_entity.dart @@ -0,0 +1,11 @@ +import 'package:shia_game_flutter/features/shop/domain/entity/shop_entity.dart'; + +class CharacterEntity extends ShopEntity { + const CharacterEntity({ + super.type = ShopType.character, + super.image, + super.isActive, + super.isBuy, + super.price, + }); +} diff --git a/lib/features/shop/domain/entity/gem_entity.dart b/lib/features/shop/domain/entity/gem_entity.dart new file mode 100644 index 0000000..6cbecbc --- /dev/null +++ b/lib/features/shop/domain/entity/gem_entity.dart @@ -0,0 +1,11 @@ +import 'package:shia_game_flutter/features/shop/domain/entity/shop_entity.dart'; + +class GemEntity extends ShopEntity { + const GemEntity({ + super.type = ShopType.gem, + super.image, + super.price, + super.title = 'Gems', + super.number, + }); +} diff --git a/lib/features/shop/domain/entity/pro_membership_entity.dart b/lib/features/shop/domain/entity/pro_membership_entity.dart new file mode 100644 index 0000000..821fbd6 --- /dev/null +++ b/lib/features/shop/domain/entity/pro_membership_entity.dart @@ -0,0 +1,11 @@ +import 'package:shia_game_flutter/features/shop/domain/entity/shop_entity.dart'; + +class ProMembershipEntity extends ShopEntity { + const ProMembershipEntity({ + super.type = ShopType.proMembership, + super.image, + super.price, + super.title = 'Month', + super.number, + }); +} diff --git a/lib/features/shop/domain/entity/shop_entity.dart b/lib/features/shop/domain/entity/shop_entity.dart index 1e453aa..527dd6b 100644 --- a/lib/features/shop/domain/entity/shop_entity.dart +++ b/lib/features/shop/domain/entity/shop_entity.dart @@ -1,14 +1,42 @@ import 'package:equatable/equatable.dart'; +enum ShopType { + gem, + boost, + character, + book, + proMembership, +} + class ShopEntity extends Equatable { - final int? id; + final ShopType? type; + final String? image; + final int? number; + final String? title; + final double? price; + final bool? isActive; + final bool? isBuy; + + const ShopEntity({ - this.id, + this.type, + this.image, + this.number, + this.title, + this.price, + this.isActive, + this.isBuy, }); @override List get props => [ - id, - ]; + type, + image, + number, + title, + price, + isActive, + isBuy, + ]; } diff --git a/lib/features/shop/domain/entity/shop_package_entity.dart b/lib/features/shop/domain/entity/shop_package_entity.dart new file mode 100644 index 0000000..af3027b --- /dev/null +++ b/lib/features/shop/domain/entity/shop_package_entity.dart @@ -0,0 +1,21 @@ +import 'package:equatable/equatable.dart'; +import 'package:shia_game_flutter/features/shop/domain/entity/shop_entity.dart'; + +class ShopPackageEntity extends Equatable { + final String? title; + final String? info; + final List? shopList; + + const ShopPackageEntity({ + this.title, + this.info, + this.shopList, + }); + + @override + List get props => [ + title, + info, + shopList, + ]; +} diff --git a/lib/features/shop/presentation/controller/shop_controller.dart b/lib/features/shop/presentation/controller/shop_controller.dart index 7098604..ba997a3 100644 --- a/lib/features/shop/presentation/controller/shop_controller.dart +++ b/lib/features/shop/presentation/controller/shop_controller.dart @@ -1,7 +1,13 @@ import 'package:flutter/cupertino.dart'; +import 'package:shia_game_flutter/common_ui/resources/my_assets.dart'; import 'package:shia_game_flutter/core/params/shop_params.dart'; import 'package:shia_game_flutter/core/status/base_status.dart'; -import 'package:shia_game_flutter/features/shop/domain/entity/shop_entity.dart'; +import 'package:shia_game_flutter/features/shop/domain/entity/book_entity.dart'; +import 'package:shia_game_flutter/features/shop/domain/entity/boost_entity.dart'; +import 'package:shia_game_flutter/features/shop/domain/entity/character_entity.dart'; +import 'package:shia_game_flutter/features/shop/domain/entity/gem_entity.dart'; +import 'package:shia_game_flutter/features/shop/domain/entity/pro_membership_entity.dart'; +import 'package:shia_game_flutter/features/shop/domain/entity/shop_package_entity.dart'; import 'package:shia_game_flutter/features/shop/domain/usecases/get_shop_usecase.dart'; import 'package:get/get.dart'; @@ -26,7 +32,52 @@ class ShopController extends GetxController with StateMixin { /// ----- Variables ----- final Rx shopParams = Rx(ShopParams()); - final Rx shopEntity = Rx(const ShopEntity()); + final RxList shopList = RxList([ + ShopPackageEntity( + title: 'Gem Package', + shopList: [ + GemEntity(number: 30, image: MyAssets.gem1, price: 12), + GemEntity(number: 60, image: MyAssets.gem2, price: 24), + GemEntity(number: 120, image: MyAssets.gem3, price: 48), + GemEntity(number: 270, image: MyAssets.gem4, price: 96), + ], + ), + ShopPackageEntity( + title: 'Boost Package', + shopList: [ + BoostEntity(number: 10, image: MyAssets.boost1, price: 10), + BoostEntity(number: 20, image: MyAssets.boost2, price: 20), + BoostEntity(number: 30, image: MyAssets.boost3, price: 30), + BoostEntity(number: 40, image: MyAssets.boost4, price: 40), + ], + ), + ShopPackageEntity( + title: 'Character Package', + shopList: [ + CharacterEntity(image: MyAssets.character1, price: 12, isActive: true, isBuy: true), + CharacterEntity(image: MyAssets.character2, price: 12, isActive: false, isBuy: true), + CharacterEntity(image: MyAssets.character3, price: 12, isActive: false, isBuy: false), + CharacterEntity(image: MyAssets.character1, price: 12, isActive: false, isBuy: false), + ], + ), + ShopPackageEntity( + title: 'Books', + shopList: [ + BookEntity(image: MyAssets.book1, title: 'Super Stories of the Prophets'), + BookEntity(image: MyAssets.book2, title: 'Super Stories of the Prophets'), + BookEntity(image: MyAssets.book3, title: 'Super Stories of the Prophets'), + ], + ), + ShopPackageEntity( + title: 'Pro Membership', + shopList: [ + ProMembershipEntity(image: MyAssets.member1, price: 2.5, number: 1), + ProMembershipEntity(image: MyAssets.member2, price: 7, number: 3), + ProMembershipEntity(image: MyAssets.member3, price: 10, number: 5), + ProMembershipEntity(image: MyAssets.member4, price: 12, number: 6), + ], + ), + ]); /// ------ Controllers ------ final TextEditingController textEditingController = TextEditingController(); @@ -42,7 +93,6 @@ class ShopController extends GetxController with StateMixin { await getShopUseCase(shopParams.value).then( (value) => value.fold( (data) { - shopEntity.value = data; change('', status: RxStatus.success()); }, (error) { diff --git a/lib/features/shop/presentation/ui/shop_page.dart b/lib/features/shop/presentation/ui/shop_page.dart index a1f6f85..d26eba5 100644 --- a/lib/features/shop/presentation/ui/shop_page.dart +++ b/lib/features/shop/presentation/ui/shop_page.dart @@ -1,14 +1,32 @@ import 'package:flutter/material.dart'; -import 'package:shia_game_flutter/features/shop/presentation/controller/shop_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/shop/presentation/controller/shop_controller.dart'; +import 'package:shia_game_flutter/features/shop/presentation/ui/widgets/shop_package_entity.dart'; class ShopPage extends GetView { const ShopPage({super.key}); @override Widget build(BuildContext context) { - return const Center( - child: Text('Shop Page'), + return MyBackground( + listChild: Obx( + () => ListView.separated( + itemCount: controller.shopList.length, + padding: EdgeInsets.only( + left: MySpaces.s30, + right: MySpaces.s30, + bottom: MySpaces.s30, + top: 60, + ), + itemBuilder: (context, index) => ShopPackageWidget( + shopPackage: controller.shopList[index], + ), + separatorBuilder: (context, index) => MySpaces.s20.gapHeight, + ), + ), ); } } diff --git a/lib/features/shop/presentation/ui/widgets/shop_item_widget.dart b/lib/features/shop/presentation/ui/widgets/shop_item_widget.dart new file mode 100644 index 0000000..4293789 --- /dev/null +++ b/lib/features/shop/presentation/ui/widgets/shop_item_widget.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import 'package:shia_game_flutter/common_ui/resources/my_spaces.dart'; +import 'package:shia_game_flutter/core/widgets/button/my_gradient_button.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'; +import 'package:shia_game_flutter/features/shop/domain/entity/shop_entity.dart'; + +class ShopItemWidget extends StatelessWidget { + const ShopItemWidget({ + super.key, + required this.shop, + }); + + final ShopEntity shop; + + @override + Widget build(BuildContext context) { + return MyContainer( + height: 213, + color: Color(0XFF1B0B38), + borderColor: Color(0XFF462A79), + borderRadius: BorderRadius.all(Radius.circular(MySpaces.s14)), + padding: EdgeInsets.all(MySpaces.s12), + child: MyContainer( + color: Color(0XFF070D1C), + borderRadius: BorderRadius.all(Radius.circular(7)), + padding: EdgeInsets.all(7), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GradientText( + text: '270 Gem', + fontSize: 18, + color: Color(0XFF9C8CC2), + shadowColor: Color(0XFF1B0D31), + offset: Offset(0, 1.69), + ), + MyImage( + asset: shop.image ?? '', + size: 80, + fit: BoxFit.contain, + ), + MyGradientButton( + onTap: () {}, + title: '\$ 12', + fontSize: 20, + ), + ], + ), + ), + ); + } +} diff --git a/lib/features/shop/presentation/ui/widgets/shop_package_entity.dart b/lib/features/shop/presentation/ui/widgets/shop_package_entity.dart new file mode 100644 index 0000000..99d35e1 --- /dev/null +++ b/lib/features/shop/presentation/ui/widgets/shop_package_entity.dart @@ -0,0 +1,79 @@ +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/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'; +import 'package:shia_game_flutter/features/shop/domain/entity/shop_entity.dart'; +import 'package:shia_game_flutter/features/shop/domain/entity/shop_package_entity.dart'; +import 'package:shia_game_flutter/features/shop/presentation/ui/widgets/shop_item_widget.dart'; + +class ShopPackageWidget extends StatelessWidget { + const ShopPackageWidget({super.key, required this.shopPackage,}); + + final ShopPackageEntity shopPackage; + + @override + Widget build(BuildContext context) { + return MyContainer( + width: context.widthScreen, + borderRadius: BorderRadius.all(Radius.circular(12)), + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0XFF411183), Color(0XFF2F0E5C)], + ), + borderGradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0XFF7D44CC), Color(0XFF7D44CC).withValues(alpha: 0)], + ), + padding: EdgeInsets.all(MySpaces.s10), + child: Column( + children: [ + Stack( + alignment: Alignment.center, + children: [ + SizedBox( + width: context.widthScreen, + child: GradientText( + textAlign: TextAlign.center, + text: shopPackage.title, + color: Color(0XFFCAA8FF), + shadowColor: Color(0XFF3E1381), + offset: Offset(0, 1.69), + blurRadius: 0.84, + fontSize: 22, + ), + ), + PositionedDirectional( + end: 0, + child: MyImage(asset: MyAssets.iconInfo), + ), + ], + ), + MySpaces.s30.gapHeight, + Wrap( + direction: Axis.horizontal, + spacing: 7, + runSpacing: 7, + children: List.generate( + shopPackage.shopList?.length ?? 0, + (index) => + Row( + mainAxisSize: MainAxisSize.min, + children: [ + ShopItemWidget( + shop: shopPackage.shopList?[index] ?? ShopEntity(), + ), + ], + ), + ), + ), + ], + ), + ); + } +}