flutter_kinetra/lib/kt_widgets/kt_store_widget.dart

551 lines
22 KiB
Dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_kinetra/kt_model/kt_goods_bean.dart';
import 'package:flutter_kinetra/kt_utils/kt_string_extend.dart';
import 'package:flutter_kinetra/kt_utils/kt_utils.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../kt_model/kt_store_bean.dart';
///商店组件
class KtStoreWidget extends StatefulWidget {
final KtStoreBean store;
final bool onlyCoins;
final bool isStoreDialog;
final void Function(KtGoodsBean goods)? onItemTap; // 新增回调
const KtStoreWidget({
super.key,
required this.store,
this.onItemTap,
this.isStoreDialog = false,
this.onlyCoins = false,
});
@override
State<KtStoreWidget> createState() => _KtStoreWidgetState();
}
class _KtStoreWidgetState extends State<KtStoreWidget> {
int selVip = -1;
int selCoin = -1;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: initWidget(),
);
}
Widget descView() {
return Text(
'''
1. Coins are virtual items and cannot be refunded. Use it for this product. \n
2. Gold coins will never expire, the reward coins will expire 24 hours a day.\n
3. Coins will be used first when unlocking episodes. If the amount is insufficient, reward coins will automatically be used. \n
4. The purchase has not been credited, click <Restore> to refresh. \n
5. For other questions, contact us via Profile>Help &feedback.\n
''',
style: TextStyle(fontSize: 12.sp, color: Color(0xFF848484), height: 0.95),
);
}
List<Widget> initWidget() {
// if (widget.onlyCoins) return [coinList()];
List<Widget> widgets = [SizedBox(height: 10.w)];
//
// int coinsIndex = widget.store.sort?.indexOf('list_coins') ?? 0;
// int vipIndex = widget.store.sort?.indexOf('list_sub_vip') ?? 0;
// if (coinsIndex < vipIndex) {
widgets.addAll([coinList(), SizedBox(height: 15.w), vipList()]);
// } else {
// widgets.addAll([vipList(), SizedBox(height: 15.w), coinList()]);
// }
widgets.addAll([
if (widget.store.payMode == 0 && widget.store.showType == 0)
SizedBox(height: 15.w),
descView(),
]);
return widgets;
}
List<KtGoodsBean> get smallList =>
widget.store.listCoins!.where((item) => item.size == 'small').toList();
List<KtGoodsBean> get bigList =>
widget.store.listCoins!.where((item) => item.size == 'big').toList();
Widget coinList() {
if (widget.store.listCoins?.isEmpty ?? true) return Container();
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!widget.onlyCoins)
Row(
children: [
Text(
'Go Coins',
style: TextStyle(
fontSize: 14.sp,
color: widget.isStoreDialog
? Color(0xFF1E1E20)
: Colors.white,
fontWeight: FontWeight.w600,
),
),
Text(
' | Limited-time coin packs',
style: TextStyle(
fontSize: 14.sp,
color: widget.isStoreDialog
? Color(0xFF1E1E20)
: Colors.white,
fontWeight: FontWeight.w200,
),
),
],
),
SizedBox(height: 10.w),
// big
// if (!onlyNewSubCoins)
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
...bigList.map((item) {
return GestureDetector(
onTap: () {
selCoin = item.id ?? -1;
setState(() {});
widget.onItemTap?.call(item); // 回调
},
child: Stack(
children: [
Container(
width: 167.w,
padding: EdgeInsets.fromLTRB(4.w, 17.w, 5.w, 3.w),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('coin_big_bg.png'.ktIcon),
fit: BoxFit.fill,
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('ic_coin.png'.ktIcon, width: 22.4.w),
Text(
'${item.coins ?? 0}',
style: TextStyle(
fontSize: 20.sp,
color: Color(0xFF1E1E20),
fontWeight: FontWeight.w500,
),
),
SizedBox(width: 4.w),
if ((item.sendCoins ?? 0) > 0)
Text(
'+${item.sendCoins}',
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: Color(0xFFAD8502),
),
),
],
),
SizedBox(height: 6.w),
Container(
width: 160.w,
alignment: Alignment.center,
padding: EdgeInsets.symmetric(vertical: 6.w),
decoration: BoxDecoration(
color: Color(0xFF1E1E20),
borderRadius: BorderRadius.circular(8.w),
),
child: Text(
'${item.productDetails?.price ?? 0}',
style: TextStyle(
fontSize: 13.sp,
color: Color(0xFFFFD321),
fontWeight: FontWeight.w700,
fontStyle: FontStyle.italic,
),
),
),
],
),
),
if (!item.cornerMarker.isNullString)
Positioned(
top: 4.w,
left: 4.w,
child: Image.asset('ic_fire.png'.ktIcon, width: 16.w),
),
if ((item.sendCoins ?? 0) > 0)
Positioned(
right: 0,
top: 0,
child: Container(
width: 42.w,
height: 16.w,
padding: EdgeInsets.symmetric(horizontal: 3.w),
alignment: Alignment.center,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment(0.50, 0.00),
end: Alignment(0.50, 1.00),
colors: [
const Color(0xFFFD9A68),
const Color(0xFFFF538D),
],
),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(8.w),
topRight: Radius.circular(8.w),
bottomLeft: Radius.circular(8.w),
),
),
child: Text(
'+${((item.sendCoins ?? 0) / (item.coins ?? 1) * 100).toInt()}%',
style: TextStyle(
fontSize: 10.sp,
color: Colors.white,
fontWeight: FontWeight.w500,
),
),
),
),
],
),
);
}),
],
),
SizedBox(height: 10.w),
// if (!widget.onlyCoins) subCoinList(),
// small
// if (!onlyNewSubCoins)
GridView.builder(
shrinkWrap: true,
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 10.w,
crossAxisSpacing: 10.w,
childAspectRatio: 108 / 90,
),
itemBuilder: (_, index) {
var item = smallList[index];
return GestureDetector(
onTap: () {
selCoin = item.id ?? -1;
setState(() {});
widget.onItemTap?.call(item); // 回调
},
child: Stack(
children: [
Container(
width: 108.w,
padding: EdgeInsets.fromLTRB(5.w, 14.w, 5.w, 4.w),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('coin_small_bg.png'.ktIcon),
fit: BoxFit.fill,
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'ic_coin.png'.ktIcon,
width: 22.4.w,
),
Text(
'${item.coins ?? 0}',
style: TextStyle(
fontSize: 20.sp,
color: Color(0xFF1E1E20),
fontWeight: FontWeight.w500,
height: 0.8,
),
),
],
),
if ((item.sendCoins ?? 0) > 0)
Text(
'+${item.sendCoins}',
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: Color(0xFF499C00),
),
),
],
),
const Spacer(),
Container(
alignment: Alignment.center,
padding: EdgeInsets.symmetric(vertical: 4.w),
decoration: BoxDecoration(
color: Color(0xFF1E1E20),
borderRadius: BorderRadius.circular(8.w),
),
child: Text(
'${item.productDetails?.price ?? 0}',
style: TextStyle(
fontSize: 13.sp,
color: Color(0xFF80FF00),
fontWeight: FontWeight.w700,
fontStyle: FontStyle.italic,
),
),
),
],
),
),
if (!item.cornerMarker.isNullString)
Positioned(
top: 4.w,
left: 4.w,
child: Image.asset('ic_fire.png'.ktIcon, width: 16.w),
),
if ((item.sendCoins ?? 0) > 0)
Positioned(
right: 0,
top: 0,
child: Container(
width: 42.w,
height: 16.w,
padding: EdgeInsets.symmetric(horizontal: 3.w),
alignment: Alignment.center,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment(0.50, 0.00),
end: Alignment(0.50, 1.00),
colors: [
const Color(0xFFFD9A68),
const Color(0xFFFF538D),
],
),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(8.w),
topRight: Radius.circular(8.w),
bottomLeft: Radius.circular(8.w),
),
),
child: Text(
'+${((item.sendCoins ?? 0) / (item.coins ?? 1) * 100).toInt()}%',
style: TextStyle(
fontSize: 10.sp,
color: Colors.white,
fontWeight: FontWeight.w500,
),
),
),
),
],
),
);
},
itemCount: smallList.length,
),
],
);
}
Widget vipList() {
if (widget.store.listSubVip?.isEmpty ?? true) return Container();
if (widget.store.payMode == 1) return Container();
final colors = {
"month": Color(0xFF00679A),
"week": Color(0xFF3D6D00),
"quarter": Color(0xFF5C5FB5),
"year": Color(0xFFAE6F00),
};
final textColors = {
"month": Color(0xFFBDEBFF),
"week": Color(0xFFE7FCCA),
"quarter": Color(0xFFDBDDFF),
"year": Color(0xFFFFF2DA),
};
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Go VIP Premium | Auto renew, cancel anytime ',
style: TextStyle(
fontSize: 14.sp,
color: Colors.white,
fontWeight: FontWeight.w500,
),
),
SizedBox(height: 10.w),
ListView.separated(
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (_, index) {
KtGoodsBean item = widget.store.listSubVip![index];
return GestureDetector(
onTap: () {
selVip = item.id ?? -1;
setState(() {});
widget.onItemTap?.call(item); // 回调
},
child: Container(
width: ScreenUtil().screenWidth - 30.w,
padding: EdgeInsets.fromLTRB(12.w, 19.w, 12.w, 5.w),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('vip_${item.vipTypeKey}_bg.png'.ktIcon),
fit: BoxFit.fill,
),
border: selVip == item.id
? Border.all(color: Colors.red, width: 1.5.w)
: null,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${item.shortType ?? ''} VIP',
style: TextStyle(
fontSize: 14.sp,
color: Color(0xFF2A0428),
fontWeight: FontWeight.w500,
),
),
item.discountType != 0
? RichText(
text: TextSpan(
children: [
TextSpan(
text: Platform.isAndroid
? item.productDetails?.price
: KtUtils.getDiscountPrice(
item.productDetails,
),
style: TextStyle(
fontSize: 26.sp,
color: Color(0xFF2A0428),
fontStyle: FontStyle.italic,
),
),
TextSpan(
text: Platform.isIOS
? item.productDetails?.price
: KtUtils.getDiscountPrice(
item.productDetails,
),
style: TextStyle(
fontSize: 16.sp,
color: Color(0xFFC2C2C2),
decoration:
TextDecoration.lineThrough, // 中间横线
),
),
],
),
)
: RichText(
text: TextSpan(
children: [
// TextSpan(
// text: item.productDetails?.currencySymbol ?? '',
// style: TextStyle(fontSize: 16.sp, color: ColorResource.mainBlack),
// ),
TextSpan(
text: Platform.isIOS
? item.productDetails?.price
: KtUtils.getDiscountPrice(
item.productDetails,
),
style: TextStyle(
fontSize: 26.sp,
color: Color(0xFF2A0428),
fontStyle: FontStyle.italic,
),
),
TextSpan(
text:
'/${KtUtils.filterVipType(item.vipType ?? '')['shortName']}',
style: TextStyle(
fontSize: 16.sp,
color: Colors.black,
),
),
],
),
),
SizedBox(height: 4.w),
SizedBox(height: 2.w),
Row(
children: [
Text(
'Unlimited access to all series',
// item.description ?? '',
style: TextStyle(
fontSize: 10.sp,
color: Color(0xFF99889B),
),
),
const Spacer(),
if ((item.sendCoins ?? 0) > 0)
Stack(
alignment: Alignment.topCenter,
children: [
Container(
padding: EdgeInsets.only(top: 8.w),
child: Image.asset(
'${KtUtils.filterVipType(item.vipType ?? '')['shortName']}_text_bg.png'.ktIcon,
height: 10.w,
),
),
Row(
children: [
Text(
'+Extra ${item.sendCoins}',
style: TextStyle(
fontSize: 12.sp,
color: Color(0xFF1E1E20),
fontWeight: FontWeight.w500,
),
),
SizedBox(width: 2.w),
Image.asset(
'ic_coin.png'.ktIcon,
width: 15.w,
),
],
),
],
),
],
),
],
),
),
);
},
separatorBuilder: (_, __) => SizedBox(height: 10.w),
itemCount: widget.store.listSubVip?.length ?? 0,
),
],
);
}
}