2026-07-01 18:25:58 +08:00

667 lines
22 KiB
Dart

import 'package:aslan/chatvibe_data/models/enum/at_vip_type.dart';
import 'package:aslan/chatvibe_ui/theme/chatvibe_theme.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:aslan/app_localizations.dart';
import 'package:aslan/chatvibe_core/routes/at_fluro_navigator.dart';
import 'package:aslan/chatvibe_core/utilities/at_string_utils.dart';
import 'package:aslan/chatvibe_data/sources/local/user_manager.dart';
import 'package:aslan/chatvibe_data/sources/repositories/user_repository_impl.dart';
import 'package:aslan/chatvibe_domain/models/res/at_user_level_exp_res.dart';
import 'package:aslan/chatvibe_features/store/store_route.dart';
import 'package:aslan/chatvibe_ui/components/at_compontent.dart';
import '../../../../chatvibe_core/constants/at_global_config.dart';
import '../../../../chatvibe_core/utilities/at_date_utils.dart';
import '../../../../chatvibe_core/utilities/at_user_utils.dart';
import '../../../../chatvibe_data/models/enum/at_level_type.dart';
import '../../../../chatvibe_ui/components/text/at_text.dart';
class WealthLevelPage extends StatefulWidget {
const WealthLevelPage({super.key});
@override
State<WealthLevelPage> createState() => _WealthLevelPageState();
}
class _WealthLevelPageState extends State<WealthLevelPage> {
ATUserLevelExpRes? _levelExpRes;
@override
void initState() {
super.initState();
_loadLevelInfo();
}
Future<void> _loadLevelInfo() async {
final value = await AccountRepository().userLevelConsumptionExp(
AccountStorage().getCurrentUser()?.userProfile?.id ?? "",
ATLevelType.WEALTH.name,
);
if (!mounted) {
return;
}
setState(() {
_levelExpRes = value;
});
}
@override
Widget build(BuildContext context) {
if (_levelExpRes == null) {
return SizedBox(
height: 420.h,
child: const Center(
child: CupertinoActivityIndicator(color: Colors.white24),
),
);
}
return SingleChildScrollView(
padding: EdgeInsets.fromLTRB(12.w, 14.w, 12.w, 12.w),
child: Column(
children: [
_buildTopSummaryCard(context),
_buildTopPrivilegesCard(context),
SizedBox(height: 16.w),
_buildRewardCard(context),
],
),
);
}
Widget _buildTopSummaryCard(BuildContext context) {
final currentUser = AccountStorage().getCurrentUser()?.userProfile;
final int level = (_levelExpRes?.level ?? 0).toInt();
final int nextLevel = level >= 50 ? 50 : level + 1;
return Column(
children: [
Image.asset(
"atu_images/level/at_icon_wealth_level_tag${_wealthLevel2(level)}.png",
width: 88.w,
),
SizedBox(height: 15.w),
ShaderMask(
blendMode: BlendMode.srcIn,
shaderCallback:
(bounds) => const LinearGradient(
colors: [Color(0xFFFED90A), Color(0xFFFFB31E)],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
).createShader(bounds),
child: Text(
"Lv$level",
style: TextStyle(
fontSize: 32.sp,
fontWeight: FontWeight.w800,
color: Colors.white,
height: 1,
),
),
),
Container(
margin: EdgeInsets.only(top: 12.w),
padding: EdgeInsets.fromLTRB(20.w, 12.w, 20.w, 12.w),
decoration: _buildCardDecoration(
beginColor: const Color(0xFF563120),
middleColor: const Color(0xFF2b1910),
endColor: const Color(0xFF110a06),
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
child: Row(
children: [
netImage(
url: currentUser?.userAvatar ?? "",
width: 45.w,
shape: BoxShape.circle,
),
Expanded(
child: Column(
children: [
Row(
children: [
SizedBox(width: 10.w),
Expanded(
child: text(
AccountStorage()
.getCurrentUser()
?.userProfile
?.userNickname ??
"",
fontWeight: FontWeight.w700,
fontSize: 15.sp,
textColor: const Color(0xFFF6E62A),
),
),
],
),
SizedBox(height: 4.w),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(width: 10.w),
Expanded(
child: Text(
_buildUpgradeHint(nextLevel),
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: const Color(0xFFF6E62A),
height: 1.2,
),
),
),
],
),
SizedBox(height: 12.w),
Padding(
padding: EdgeInsetsDirectional.only(
start: 10.w,
end: 20.w,
),
child: ClipRRect(
borderRadius: BorderRadius.circular(99.r),
child: SizedBox(
height: 6.w,
child: LinearProgressIndicator(
value: _buildProgressRatio(),
backgroundColor: Colors.white.withValues(
alpha: 0.16,
),
valueColor: const AlwaysStoppedAnimation<Color>(
Color(0xFFFFC700),
),
),
),
),
),
],
),
),
],
),
),
],
);
}
int _wealthLevel2(int level) {
int level2 = 1;
if (level > 0 && level <= 10) {
level2 = 1;
} else if (level > 10 && level <= 20) {
level2 = 2;
} else if (level > 20 && level <= 30) {
level2 = 3;
} else if (level > 30 && level <= 40) {
level2 = 4;
} else if (level > 40 && level <= 50) {
level2 = 5;
}
return level2;
}
Widget _buildRewardCard(BuildContext context) {
final localizations = ATAppLocalizations.of(context)!;
final int level = (_levelExpRes?.level ?? 0).toInt();
return Container(
width: double.infinity,
padding: EdgeInsets.fromLTRB(0.w, 20.w, 0.w, 18.w),
decoration: _buildCardDecoration(
beginColor: const Color(0xFF563120),
middleColor: const Color(0xFF2b1910),
endColor: const Color(0xFF110a06),
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
child: Column(
children: [
_buildPanelTitle(
title: localizations.medalAndAvatarFrameRewards,
subtitle: localizations.higherLevelFancierAvatarFrame,
),
SizedBox(height: 16.w),
_buildSectionLabel(localizations.levelIcon),
SizedBox(height: 10.w),
Padding(
padding: EdgeInsets.symmetric(horizontal: 12.w),
child: _buildLevelTrack(level),
),
Image.asset(
"atu_images/level/at_icon_user_wealth_center_bg_1.png",
width: double.infinity,
fit: BoxFit.fitWidth,
),
SizedBox(height: 18.w),
_buildSectionLabel(localizations.levelMedal),
SizedBox(height: 10.w),
Container(
margin: EdgeInsets.symmetric(horizontal: 3.w),
child: Image.asset(
"atu_images/level/at_icon_user_wealth_center_bg_2.png",
width: double.infinity,
fit: BoxFit.fitWidth,
),
),
SizedBox(height: 18.w),
_buildPanelTitle(
title: localizations.howToUpgrade,
subtitle: localizations.spendCoinsToGainExperiencePoints,
),
SizedBox(height: 16.w),
GestureDetector(
onTap: () {
ATNavigatorUtils.push(context, StoreRoute.list);
},
child: Container(
width: 160.w,
height: 48.w,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(999.r),
border: Border.all(color: Colors.white, width: 1.w),
gradient: const LinearGradient(
colors: [Color(0xFFFF8B2A), Color(0xFFFF4E00)],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
boxShadow: [
BoxShadow(
color: const Color(0xFFFF5A00).withValues(alpha: 0.34),
blurRadius: 26,
offset: const Offset(0, 10),
),
],
),
child: Text(
localizations.toConsume,
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w700,
color: Colors.white,
height: 1,
),
),
),
),
],
),
);
}
Widget _buildLevelTrack(int level) {
const labels = ["LV.1-10", "LV.11-20", "LV.21-30", "LV.31-40", "LV.41-50"];
final int activeIndex = _resolveLevelStageIndex(level);
return LayoutBuilder(
builder: (context, constraints) {
final double itemWidth = constraints.maxWidth / labels.length;
final double dotSize = 10.w;
final double trackTop = 20.w;
final double activeCenter = itemWidth * activeIndex + itemWidth / 2;
return SizedBox(
height: 34.w,
child: Stack(
children: [
for (int i = 0; i < labels.length; i++)
Positioned(
left: itemWidth * i,
width: itemWidth,
top: 0,
child: Center(
child: text(
labels[i],
textColor:
i == activeIndex
? ChatVibeTheme.primaryLight
: Colors.white,
fontSize: 11.sp,
),
),
),
Positioned(
left: 0,
right: 0,
top: trackTop + dotSize / 2 - 1.w,
child: Container(
height: 4.w,
decoration: BoxDecoration(
color: Colors.white24,
borderRadius: BorderRadius.circular(50.r),
),
),
),
Positioned(
left: 0,
width: activeCenter,
top: trackTop + dotSize / 2 - 1.w,
child: Container(
height: 4.w,
decoration: BoxDecoration(
color: ChatVibeTheme.primaryLight,
borderRadius: BorderRadius.circular(50.r),
),
),
),
for (int i = 0; i < labels.length; i++)
Positioned(
left: itemWidth * i + (itemWidth - dotSize) / 2,
top: trackTop + 1,
child: Image.asset(
i == activeIndex
? "atu_images/level/at_icon_level_pd_en.png"
: "atu_images/level/at_icon_level_pd_no.png",
width: dotSize,
height: dotSize,
),
),
],
),
);
},
);
}
Widget _buildPanelTitle({required String title, required String subtitle}) {
return Column(
children: [
ShaderMask(
blendMode: BlendMode.srcIn,
shaderCallback:
(bounds) => const LinearGradient(
colors: [Color(0xFFFDFCF8), Color(0xFFFFB31E)],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
).createShader(bounds),
child: Text(
title,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w800,
color: Colors.white,
height: 1.15,
),
),
),
SizedBox(height: 6.w),
Text(
subtitle,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 11.sp,
fontWeight: FontWeight.w500,
color: Colors.white,
height: 1.3,
),
),
],
);
}
Widget _buildSectionLabel(String title) {
return Row(
children: [
SizedBox(width: 35.w),
Expanded(child: _buildGlowLine()),
SizedBox(width: 8.w),
ShaderMask(
blendMode: BlendMode.srcIn,
shaderCallback:
(bounds) => const LinearGradient(
colors: [Color(0xFFFDFCF8), Color(0xFFFFB31E)],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
).createShader(bounds),
child: Text(
title,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w800,
color: Colors.white,
height: 1,
),
),
),
SizedBox(width: 8.w),
Expanded(child: _buildGlowLine(reverse: true)),
SizedBox(width: 35.w),
],
);
}
Widget _buildGlowLine({bool reverse = false}) {
return Image.asset(
reverse
? "atu_images/level/at_icon_wealth_title_01_right.png"
: "atu_images/level/at_icon_wealth_title_01_left.png",
height: 14.w,
fit: BoxFit.fill,
);
}
BoxDecoration _buildCardDecoration({
required Color beginColor,
required Color middleColor,
required Color endColor,
required AlignmentGeometry begin,
required AlignmentGeometry end,
}) {
return BoxDecoration(
borderRadius: BorderRadius.circular(12.r),
border: Border.all(color: const Color(0xFFFFD673), width: 1.w),
gradient: LinearGradient(
colors: [beginColor, middleColor, endColor],
begin: begin,
end: end,
stops: const [0, 0.6, 1],
),
);
}
String _buildUpgradeHint(int nextLevel) {
final int needExp = ATStringUtils.toIntFunction(
_levelExpRes?.nextExperience ?? "0",
);
if (needExp <= 0) {
return "Max Level";
}
return "You Need ${ATStringUtils.formatNumber(needExp)} EXP To Lv$nextLevel";
}
double _buildProgressRatio() {
final int currentExp = ATStringUtils.toIntFunction(
_levelExpRes?.thatExperience ?? "0",
);
final int nextExp = ATStringUtils.toIntFunction(
_levelExpRes?.nextExperience ?? "0",
);
final int totalExp = currentExp + nextExp;
if (totalExp <= 0) {
return 0;
}
return (currentExp / totalExp).clamp(0, 1).toDouble();
}
int _resolveLevelStageIndex(int level) {
if (level >= 1 && level <= 10) {
return 0;
}
if (level <= 20) {
return 1;
}
if (level <= 30) {
return 2;
}
if (level <= 40) {
return 3;
}
return 4;
}
Widget _buildTopPrivilegesCard(BuildContext context) {
final int level = (_levelExpRes?.level ?? 0).toInt();
return Container(
margin: EdgeInsets.only(top: 12.w),
height: 140.w,
padding: EdgeInsets.fromLTRB(20.w, 12.w, 20.w, 0.w),
decoration: _buildCardDecoration(
beginColor: const Color(0xFF563120),
middleColor: const Color(0xFF2b1910),
endColor: const Color(0xFF110a06),
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
child: Column(
children: [
text(
ATAppLocalizations.of(
context,
)!.currentLevelPrivilegesAndCostumes("Lv.$level"),
fontSize: 12.sp,
textColor: const Color(0xFFF6E62A),
),
Spacer(),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
SizedBox(width: _levelExpRes?.idIconType != null ? 25.w : 50.w),
Expanded(
child: Column(
children: [
getWealthLevel(level, width: 60.w, height: 30.w),
SizedBox(height: 15.w),
Stack(
alignment: Alignment.center,
children: [
Image.asset(
"atu_images/level/at_icon_wealth_level_otsb_tg.png",
height: 30.w,
width: 72.w,
fit: BoxFit.fill,
),
PositionedDirectional(
bottom: 3.w,
child: Container(
alignment: Alignment.center,
width: 72.w,
child: text(
ATAppLocalizations.of(context)!.levelIcon,
fontSize: 10.sp,
),
),
),
],
),
],
),
),
if( _levelExpRes?.vipLevel!=null) Expanded(
child: Column(
children: [
Image.asset(
width: 65.w,
height: 65.w,
ATGlobalConfig.businessLogicStrategy.getVipPageLargeIcon(
int.parse(
ATAccountHelper.getVipLevel2(
_levelExpRes?.vipLevel ?? "",
),
),
),
),
SizedBox(height: 5.w),
Stack(
children: [
Image.asset(
"atu_images/level/at_icon_wealth_level_otsb_tg.png",
height: 30.w,
width: 72.w,
fit: BoxFit.fill,
),
PositionedDirectional(
bottom: 3.w,
child: Container(
alignment: Alignment.center,
width: 72.w,
child: text(
"${ATAccountHelper.getVipLevel(_levelExpRes?.vipLevel ?? "")}*${"${_levelExpRes?.vipDays ?? 0}${ATAppLocalizations.of(context)!.days}"}",
fontSize: 10.sp,
),
),
),
],
),
],
),
),
if (_levelExpRes?.idIconType != null)
Expanded(
child: Column(
children: [
getIdIconForLevel(
_levelExpRes?.idIconType ?? 0,
width: 50.w,
height: 50.w,
),
SizedBox(height: 10.w),
Stack(
alignment: Alignment.center,
children: [
Image.asset(
"atu_images/level/at_icon_wealth_level_otsb_tg.png",
height: 30.w,
width: 72.w,
fit: BoxFit.fill,
),
PositionedDirectional(
bottom: 3.w,
child: Container(
alignment: Alignment.center,
width: 72.w,
child: text(
ATAppLocalizations.of(context)!.idIcon,
fontSize: 10.sp,
),
),
),
],
),
],
),
),
SizedBox(width: _levelExpRes?.idIconType != null ? 25.w : 50.w),
],
),
],
),
);
}
getIdIconForLevel(
num idIconType, {
required double width,
required double height,
}) {
String icon = "";
if (idIconType == 1) {
icon = "atu_images/level/at_icon_wealth_id_icon_1.png";
} else if (idIconType == 2) {
icon = "atu_images/level/at_icon_wealth_id_icon_2.png";
} else if (idIconType == 3) {
icon = "atu_images/level/at_icon_wealth_id_icon_3.png";
} else if (idIconType == 4) {
icon = "atu_images/level/at_icon_wealth_id_icon_4.png";
}
return icon.isNotEmpty
? Image.asset(icon, width: width, height: height)
: Container();
}
}