Commit 76a7b3a9b3cfe68da52e82ad2d80932f38d722ab

Authored by 刘宏哲
1 parent ea1a3e95

feat(app): update ui

... ... @@ -191,7 +191,6 @@ class FriendsTab extends GetView<FriendsController> {
? () => _showFriendsLimitReached(context)
: _handleAddFriend,
),
if (isFull) const _FullFriendsTip(),
],
),
),
... ... @@ -408,34 +407,12 @@ class _EmptyFriendsView extends StatelessWidget {
enabled: enabled,
onTap: onTap,
),
if (!enabled) const _FullFriendsTip(),
],
),
);
}
}
class _FullFriendsTip extends StatelessWidget {
const _FullFriendsTip();
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(top: 10),
child: Center(
child: Text(
context.l10n.friendsLimitReached,
style: const TextStyle(
color: Color(0xFFB0B0B6),
fontSize: 12,
fontWeight: FontWeight.w400,
),
),
),
);
}
}
class _AddFriendButton extends StatelessWidget {
const _AddFriendButton({
required this.enabled,
... ... @@ -455,39 +432,53 @@ class _AddFriendButton extends StatelessWidget {
child: GestureDetector(
onTap: onTap,
behavior: HitTestBehavior.opaque,
child: Opacity(
opacity: enabled ? 1 : 0.4,
child: Container(
child: SizedBox(
width: 240,
height: 48,
decoration: BoxDecoration(
color:
enabled ? const Color(0xFF845EEE) : const Color(0xFFD0D0D2),
borderRadius: BorderRadius.circular(24),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
child: Stack(
children: [
Image.asset(
'assets/images/common/ic_add.png',
width: 18,
height: 18,
color: Colors.white,
),
const SizedBox(width: 6),
Text(
_buttonText(context),
style: const TextStyle(
Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600,
height: 1.4,
borderRadius: BorderRadius.circular(24),
),
),
Opacity(
opacity: enabled ? 1 : 0.4,
child: Container(
width: 240,
height: 48,
decoration: BoxDecoration(
color: const Color(0xFF845EEE),
borderRadius: BorderRadius.circular(24),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'assets/images/common/ic_add.png',
width: 18,
height: 18,
color: Colors.white,
),
const SizedBox(width: 6),
Text(
_buttonText(context),
style: const TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600,
height: 1.4,
),
),
],
),
),
)
],
),
),
),
)),
),
);
}
... ...
... ... @@ -158,15 +158,30 @@ class _HealthTrendContentState extends State<HealthTrendContent>
class _HealthTrendLoadingIndicator extends StatelessWidget {
const _HealthTrendLoadingIndicator();
static const _width = 130.0;
static const _height = 90.0;
static const _headerCenterOffset = Offset(0, -46);
static const _visualCenterOffset = Offset(0, -8);
@override
Widget build(BuildContext context) {
return Center(
child: Lottie.asset(
'assets/lottie/loading.json',
width: 130,
height: 90,
repeat: true,
animate: true,
child: Transform.translate(
offset: _headerCenterOffset,
child: SizedBox(
width: _width,
height: _height,
child: Transform.translate(
offset: _visualCenterOffset,
child: Lottie.asset(
'assets/lottie/loading.json',
width: _width,
height: _height,
repeat: true,
animate: true,
),
),
),
),
);
}
... ... @@ -211,7 +226,9 @@ class _HrvTrendSectionState extends State<_HrvTrendSection> {
_dateWorker = ever(_logic.selectedDate, (date) {
_scheduleQueryNotification();
});
_logic.loadReport();
if (widget.isVip) {
_logic.loadReport();
}
}
@override
... ... @@ -221,6 +238,10 @@ class _HrvTrendSectionState extends State<_HrvTrendSection> {
_syncExternalQuery();
} else if (oldWidget.refreshToken != widget.refreshToken &&
widget.isSelected) {
if (widget.isVip) {
_logic.loadReport();
}
} else if (!oldWidget.isVip && widget.isVip) {
_logic.loadReport();
}
}
... ... @@ -229,7 +250,11 @@ class _HrvTrendSectionState extends State<_HrvTrendSection> {
_syncingExternalQuery = true;
_logic.targetUserId.value = widget.query.targetUserId;
try {
await _logic.selectQuery(widget.query.period, widget.query.date);
if (widget.isVip) {
await _logic.selectQuery(widget.query.period, widget.query.date);
} else {
_logic.initializeQuery(widget.query.period, widget.query.date);
}
} finally {
_syncingExternalQuery = false;
}
... ...
... ... @@ -77,6 +77,8 @@ class WeeklyHrvReport implements HrvPeriodReport {
required this.days,
this.previousRelaxedDays,
this.previousStressedDays,
this.relaxedDaysOverride,
this.stressedDaysOverride,
this.distributionCounts,
this.minDayOverride,
this.maxDayOverride,
... ... @@ -89,6 +91,8 @@ class WeeklyHrvReport implements HrvPeriodReport {
final int? previousRelaxedDays;
@override
final int? previousStressedDays;
final int? relaxedDaysOverride;
final int? stressedDaysOverride;
final Map<HrvStressLevel, int>? distributionCounts;
final HrvDayReport? minDayOverride;
final HrvDayReport? maxDayOverride;
... ... @@ -114,10 +118,12 @@ class WeeklyHrvReport implements HrvPeriodReport {
@override
int get relaxedDays =>
relaxedDaysOverride ??
countFor(HrvStressLevel.excellent) + countFor(HrvStressLevel.normal);
@override
int get stressedDays =>
stressedDaysOverride ??
countFor(HrvStressLevel.attention) + countFor(HrvStressLevel.overload);
@override
... ... @@ -144,6 +150,71 @@ class WeeklyHrvReport implements HrvPeriodReport {
HrvDayReport(date: weekStart.add(Duration(days: i))),
],
);
factory WeeklyHrvReport.premiumPreview(DateTime weekStart) {
final start = DateTime(weekStart.year, weekStart.month, weekStart.day);
final minDay = HrvDayReport(
date: start.add(const Duration(days: 6)),
averageHrv: 15,
averageHeartRate: 71,
level: HrvStressLevel.overload,
);
final maxDay = HrvDayReport(
date: start.add(const Duration(days: 1)),
averageHrv: 90,
averageHeartRate: 84,
level: HrvStressLevel.excellent,
);
return WeeklyHrvReport(
weekStart: start,
previousRelaxedDays: 5,
previousStressedDays: 2,
relaxedDaysOverride: 4,
stressedDaysOverride: 1,
distributionCounts: const {
HrvStressLevel.excellent: 4,
HrvStressLevel.normal: 1,
HrvStressLevel.attention: 1,
HrvStressLevel.overload: 1,
},
minDayOverride: minDay,
maxDayOverride: maxDay,
days: [
HrvDayReport(
date: start,
averageHrv: 62,
averageHeartRate: 86,
level: HrvStressLevel.normal,
),
maxDay,
HrvDayReport(
date: start.add(const Duration(days: 2)),
averageHrv: 68,
averageHeartRate: 88,
level: HrvStressLevel.excellent,
),
HrvDayReport(
date: start.add(const Duration(days: 3)),
averageHrv: 85,
averageHeartRate: 85,
level: HrvStressLevel.excellent,
),
HrvDayReport(
date: start.add(const Duration(days: 4)),
averageHrv: 86,
averageHeartRate: 87,
level: HrvStressLevel.excellent,
),
HrvDayReport(
date: start.add(const Duration(days: 5)),
averageHrv: 45,
averageHeartRate: 70,
level: HrvStressLevel.attention,
),
minDay,
],
);
}
}
class MonthlyHrvReport implements HrvPeriodReport {
... ...
... ... @@ -9,6 +9,7 @@ import '../../report_common/widgets/report_date_picker_sheet.dart';
import '../../report_common/widgets/report_date_switcher.dart';
import '../../report_common/widgets/report_loading_indicator.dart';
import '../controllers/hrv_report_logic.dart';
import '../models/hrv_report_models.dart';
import '../widgets/hrv_week_report_view.dart';
import '../widgets/hrv_year_report_view.dart';
... ... @@ -86,7 +87,11 @@ class HrvReportView extends StatelessWidget {
HrvMonthReportView(report: logic.monthlyReport.value)
else
HrvWeekReportView(
report: logic.weeklyReport.value,
report: isVip
? logic.weeklyReport.value
: WeeklyHrvReport.premiumPreview(
logic.weekStart,
),
showExample: !isVip,
onSubscribe: () => onSubscribe('解锁每日压力-HRV心率'),
),
... ...