2025-10-16 16:34:07 +08:00

773 lines
31 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import '../../kt_model/kt_receive_coin_info.dart';
import '../../kt_model/kt_goods_bean.dart';
import '../../kt_utils/kt_string_extend.dart';
import '../kt_mine/kt_store/logic.dart';
import 'logic.dart';
class KtRefillPage extends StatefulWidget {
const KtRefillPage({super.key});
@override
State<KtRefillPage> createState() => _KtRefillPageState();
}
class _KtRefillPageState extends State<KtRefillPage> {
final logic = Get.put(KtRefillLogic());
final state = Get.find<KtRefillLogic>().state;
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
body: Container(
padding: EdgeInsets.fromLTRB(
15.w,
ScreenUtil().statusBarHeight,
15.w,
0,
),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('bg1.png'.ktIcon),
fit: BoxFit.fill,
),
),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
icon: Image.asset('ic_back.png'.ktIcon, width: 10.w),
onPressed: () => Navigator.of(context).maybePop(),
),
Text(
'My Refills',
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
SizedBox(width: 24.w),
],
),
Expanded(
child: GetBuilder<KtRefillLogic>(
builder: (ctrl) {
return SmartRefresher(
controller: logic.refreshController,
physics: const ClampingScrollPhysics(),
enablePullUp: false,
enablePullDown: true,
onRefresh: logic.refreshInfo,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
cardView(),
if (state.hasSubCoin) activeRefillView(),
weeklyRefillView(),
ruleView(),
],
),
),
);
},
),
),
],
),
),
);
}
Widget cardView() {
return Container(
width: 345.w,
height: 258.w,
padding: EdgeInsets.only(top: 59.w, left: 14.w),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('refills_top_bg.png'.ktIcon),
fit: BoxFit.fill,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Rewards Overview',
style: TextStyle(
fontFamily: 'Inter',
color: Color(0xFF1E1E20),
fontSize: 15.sp,
fontWeight: FontWeight.w600,
),
),
Container(
margin: EdgeInsets.symmetric(vertical: 16.w),
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Weekly Total',
style: TextStyle(
fontFamily: 'Inter',
color: Color(0xFF5E5E5E),
fontSize: 12.sp,
fontWeight: FontWeight.w600,
),
),
SizedBox(height: 4.w),
Row(
children: [
Image.asset('ic_coin.png'.ktIcon, width: 17),
SizedBox(width: 4.w),
Text(
'${state.receiveCoinInfo?.weekMaxTotal ?? 0}',
style: TextStyle(
fontFamily: 'Inter',
color: Color(0xFFFF9500),
fontSize: 18.sp,
fontWeight: FontWeight.w700,
),
),
],
),
],
),
Container(
margin: EdgeInsets.symmetric(horizontal: 18.w),
width: 1.w,
height: 32.w,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('refills_top_bg_line.png'.ktIcon),
fit: BoxFit.fill,
),
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Claimable Coins',
style: TextStyle(
fontFamily: 'Inter',
color: Color(0xFF5E5E5E),
fontSize: 12.sp,
fontWeight: FontWeight.w600,
),
),
SizedBox(height: 4.w),
Row(
children: [
Image.asset('ic_coin.png'.ktIcon, width: 17),
SizedBox(width: 4.w),
Text(
'${state.receiveCoinInfo?.weekTotal ?? 0}',
style: TextStyle(
fontFamily: 'Inter',
color: Color(0xFFFF9500),
fontSize: 18.sp,
fontWeight: FontWeight.w700,
),
),
],
),
],
),
],
),
),
Row(
children: [
Text(
'Active Refills:',
style: TextStyle(
fontFamily: 'Inter',
color: Color(0xFF777777),
fontSize: 12.sp,
fontWeight: FontWeight.w400,
),
),
Text(
'${state.receiveCoinInfo?.receiveCount ?? 0}',
style: TextStyle(
fontFamily: 'Inter',
color: Color(0xFF79C900),
fontSize: 12.sp,
fontWeight: FontWeight.w700,
),
),
],
),
SizedBox(height: 6.w),
GestureDetector(
onTap: () {
if (!state.hasSubCoin) return;
logic.receiveDayCoin();
},
child: state.hasSubCoin
? Stack(
children: [
Image.asset(
'refills_top_btn_all.png'.ktIcon,
width: 337.w,
height: 68.w,
),
Container(
height: 46.w,
margin: EdgeInsets.only(top: 5.w),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Claim All',
style: TextStyle(
fontFamily: 'Inter',
color: Color(0xFF1E1E20),
fontSize: 15.sp,
fontWeight: FontWeight.w600,
),
),
SizedBox(width: 6.w),
Image.asset('ic_coin.png'.ktIcon, width: 13),
SizedBox(width: 2.w),
Text(
'${state.receiveCoinInfo?.receiveCoins ?? 0}',
style: TextStyle(
fontFamily: 'Inter',
color: Color(0xFF1E1E20),
fontSize: 14.sp,
fontWeight: FontWeight.w700,
),
),
],
),
),
],
)
: Stack(
children: [
Image.asset(
'refills_top_btn.png'.ktIcon,
width: 337.w,
height: 68.w,
),
Container(
height: 46.w,
margin: EdgeInsets.only(top: 5.w),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Get a Refill to Claim',
style: TextStyle(
fontFamily: 'Inter',
color: Color(0xFFF7F7F7),
fontSize: 15.sp,
fontWeight: FontWeight.w600,
),
),
],
),
),
],
),
),
],
),
);
}
Widget activeRefillView() {
return GetBuilder<KtRefillLogic>(
builder: (ctrl) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 20.w),
Text(
'Active Refills',
style: TextStyle(
fontSize: 15.sp,
fontFamily: 'Inter',
fontWeight: FontWeight.w600,
color: Color(0xFF1C1C1C),
),
),
ListView.builder(
padding: EdgeInsets.only(top: 0.w),
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: state.receiveCoinInfo?.receiveList?.length ?? 2,
itemBuilder: (context, index) {
ReceiveList? item = state.receiveCoinInfo?.receiveList?[index];
return Container(
width: 345.w,
height: 122.w,
padding: EdgeInsets.only(top: 14.w, left: 12.w),
margin: EdgeInsets.only(top: 10.w),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('refills_center_bg-s.png'.ktIcon),
fit: BoxFit.fill,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
item?.title ?? '',
style: TextStyle(
fontFamily: 'Inter',
fontSize: 14.sp,
fontWeight: FontWeight.w700,
color: Colors.white,
),
),
SizedBox(width: 8.w),
Text(
'(Day ${item?.dayText ?? ''}/7)',
style: TextStyle(
fontFamily: 'Inter',
fontSize: 14.sp,
fontWeight: FontWeight.w400,
color: Colors.white.withValues(alpha: 0.70),
),
),
],
),
Container(
margin: EdgeInsets.symmetric(vertical: 12.w),
width: 320.w,
height: 1.w,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('refills_center_line.png'.ktIcon),
fit: BoxFit.fill,
),
),
),
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Total Reward',
style: TextStyle(
fontFamily: 'Inter',
color: Color(0xFFCAB7A9),
fontSize: 12.sp,
fontWeight: FontWeight.w700,
),
),
SizedBox(height: 8.w),
Row(
children: [
Image.asset('ic_coin.png'.ktIcon, width: 14),
SizedBox(width: 4.w),
Text(
'${item?.weekMaxTotal ?? 0}',
style: TextStyle(
fontFamily: 'Inter',
color: Color(0xFFFFF9E8),
fontSize: 14.sp,
fontWeight: FontWeight.w700,
),
),
],
),
],
),
Container(
margin: EdgeInsets.symmetric(horizontal: 12.w),
width: 1.w,
height: 32.w,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
'refills_center_line2.png'.ktIcon,
),
fit: BoxFit.fill,
),
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Remaining',
style: TextStyle(
fontFamily: 'Inter',
color: Color(0xFFCAB7A9),
fontSize: 12.sp,
fontWeight: FontWeight.w700,
),
),
SizedBox(height: 8.w),
Row(
children: [
Image.asset('ic_coin.png'.ktIcon, width: 14),
SizedBox(width: 4.w),
Text(
'${item?.weekRemainingTotal ?? 0}',
style: TextStyle(
fontFamily: 'Inter',
color: Color(0xFFFFF9E8),
fontSize: 14.sp,
fontWeight: FontWeight.w700,
),
),
],
),
],
),
const Spacer(),
GestureDetector(
onTap: () {
if (item?.receiveCoins == 0) return;
logic.receiveDayCoin(id: item!.id);
},
child: item?.receiveCoins == 0
? Container(
width: 100.w,
height: 48.w,
decoration: BoxDecoration(
color: Color(0xE5B1B1B1),
borderRadius: BorderRadius.all(
Radius.circular(14.w),
),
),
child: Center(
child: Text(
'Claimed',
style: TextStyle(
color: Color(0xFFF7F7F7),
fontSize: 14.sp,
fontWeight: FontWeight.w600,
),
),
),
)
: Stack(
children: [
Container(
width: 100.w,
height: 48.w,
padding: EdgeInsets.only(top: 5.w),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
const Color(0xFF986100),
const Color(0xFF322000),
],
),
border: Border.all(
width: 0.5.w,
color: Colors.white,
),
borderRadius: BorderRadius.all(
Radius.circular(14.w),
),
),
child: Column(
children: [
Text(
'Claim',
style: TextStyle(
fontFamily: 'Inter',
color: Colors.white,
fontSize: 14.sp,
fontWeight: FontWeight.w700,
),
),
Row(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Image.asset(
'ic_coin.png'.ktIcon,
width: 14,
),
SizedBox(width: 4.w),
Text(
'${item?.receiveCoins ?? 0}',
style: TextStyle(
fontFamily: 'Inter',
color: Colors.white
.withValues(
alpha: 0.70,
),
fontSize: 12.sp,
fontWeight: FontWeight.w600,
),
),
],
),
],
),
),
Positioned(
left: -6.w,
top: -6.w,
child: Image.asset(
'refills_center_star.png'.ktIcon,
width: 20.w,
),
),
Positioned(
right: -6.w,
bottom: -6.w,
child: Image.asset(
'refills_center_star.png'.ktIcon,
width: 20.w,
),
),
],
),
),
SizedBox(width: 12.w),
],
),
],
),
);
},
),
],
);
},
);
}
Widget weeklyRefillView() {
Get.put(KtStoreLogic());
return GetBuilder<KtStoreLogic>(
builder: (ctrl) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 20.w),
if (ctrl.state.refillCoinList.isNotEmpty)
Text(
'Weekly Refill',
style: TextStyle(
fontFamily: 'Inter',
fontSize: 15.sp,
fontWeight: FontWeight.w600,
color: Color(0xFF1C1C1C),
),
),
ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: ctrl.state.refillCoinList.length,
itemBuilder: (context, index) {
KtGoodsBean? item = ctrl.state.refillCoinList[index];
return GestureDetector(
onTap: () => ctrl.buyGoods(item),
child: Container(
width: 345.w,
height: 80.w,
padding: EdgeInsets.only(left: 16.w, right: 13.w),
margin: EdgeInsets.only(top: 10.w),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('refills_center_bg.png'.ktIcon),
fit: BoxFit.fill,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Weekly Refill',
style: TextStyle(
fontFamily: 'Inter',
color: Colors.white,
fontSize: 14.sp,
fontWeight: FontWeight.w700,
),
),
SizedBox(height: 5.w),
Row(
children: [
Image.asset('ic_coin.png'.ktIcon, width: 16),
SizedBox(width: 4.w),
Text(
'${item.extInfo?.maxTotalCoins ?? 0}',
style: TextStyle(
fontFamily: 'Inter',
color: Color(0xFFFFF9E8),
fontSize: 18.sp,
fontWeight: FontWeight.w600,
),
),
SizedBox(width: 4.w),
Container(
height: 18.w,
padding: EdgeInsets.symmetric(
horizontal: 8.w,
),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.15),
borderRadius: BorderRadius.all(
Radius.circular(4.w),
),
),
child: Text(
item.extInfo?.receiveCoinsRate ?? '',
style: TextStyle(
fontFamily: 'Inter',
color: Colors.white,
fontSize: 12.sp,
fontWeight: FontWeight.w400,
),
),
),
],
),
],
),
Stack(
children: [
Container(
constraints: BoxConstraints(minWidth: 90.w),
height: 48.w,
padding: EdgeInsets.only(
top: 5.w,
left: 15.w,
right: 15.w,
),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
const Color(0xFF986100),
const Color(0xFF322000),
],
),
border: Border.all(
width: 0.5.w,
color: Colors.white,
),
borderRadius: BorderRadius.all(
Radius.circular(14.w),
),
),
child: Column(
children: [
Text(
item.productDetails?.price ?? '',
style: TextStyle(
fontFamily: 'Inter',
height: 1,
color: Colors.white,
fontSize: 18.sp,
fontWeight: FontWeight.w700,
),
),
Text(
'/week',
style: TextStyle(
fontFamily: 'Inter',
color: Colors.white.withValues(
alpha: 0.50,
),
fontSize: 12.sp,
fontWeight: FontWeight.w400,
),
),
],
),
),
Positioned(
left: -6.w,
top: -6.w,
child: Image.asset(
'refills_center_star.png'.ktIcon,
width: 20.w,
),
),
Positioned(
right: -6.w,
bottom: -6.w,
child: Image.asset(
'refills_center_star.png'.ktIcon,
width: 20.w,
),
),
],
),
],
),
),
);
},
),
],
);
},
);
}
Widget ruleView() {
return Container(
margin: EdgeInsets.only(top: 10.w, bottom: 43.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Subscription Rules',
style: TextStyle(
fontFamily: 'Inter',
fontSize: 14.sp,
fontWeight: FontWeight.w600,
color: Color(0xFF94949B),
),
),
SizedBox(height: 6.w),
...[
'1.Up to 2 subscriptions can be active at once.',
'2.Coins are delivered instantly upon purchase.',
'3.Daily bonus coins available from the next day.',
'4.All coins will be revoked when the subscription expires,',
'including both initial and daily coins.',
].map(
(text) => Container(
margin: EdgeInsets.only(bottom: 4.w),
child: Text(
text,
style: TextStyle(
fontFamily: 'Inter',
fontSize: 12.sp,
fontWeight: FontWeight.w400,
color: Color(0xFF94949B),
),
),
),
),
],
),
);
}
}