667 lines
22 KiB
Dart
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();
|
|
}
|
|
}
|