|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:get/get.dart';
|
|
|
|
|
|
|
|
import '../../../../r.dart';
|
|
|
|
import '../../report_common/models/report_period.dart';
|
|
|
|
import '../../report_common/widgets/report_bottom_slogan.dart';
|
|
|
|
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 '../widgets/hrv_week_report_view.dart';
|
|
|
|
import '../widgets/hrv_year_report_view.dart';
|
|
|
|
|
|
|
|
class HrvReportView extends StatelessWidget {
|
|
|
|
const HrvReportView({super.key, required this.logic});
|
|
|
|
const HrvReportView({
|
|
|
|
super.key,
|
|
|
|
required this.logic,
|
|
|
|
required this.isVip,
|
|
|
|
required this.onSubscribe,
|
|
|
|
});
|
|
|
|
|
|
|
|
final HrvReportLogic logic;
|
|
|
|
final bool isVip;
|
|
|
|
final VoidCallback onSubscribe;
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return ColoredBox(
|
|
|
|
color: Colors.transparent,
|
|
|
|
child: Column(
|
|
|
|
child: Stack(
|
|
|
|
children: [
|
|
|
|
Padding(
|
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
|
|
child: Column(
|
|
|
|
children: [
|
|
|
|
const SizedBox(height: 8),
|
|
|
|
Obx(
|
|
|
|
() => _HrvPeriodBar(
|
|
|
|
selectedPeriod: logic.selectedPeriod.value,
|
|
|
|
onChanged: logic.selectPeriod,
|
|
|
|
),
|
|
|
|
Column(
|
|
|
|
children: [
|
|
|
|
Padding(
|
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
|
|
child: Column(
|
|
|
|
children: [
|
|
|
|
const SizedBox(height: 8),
|
|
|
|
Obx(
|
|
|
|
() => _HrvPeriodBar(
|
|
|
|
selectedPeriod: logic.selectedPeriod.value,
|
|
|
|
onChanged: logic.selectPeriod,
|
|
|
|
lockedPeriods: isVip
|
|
|
|
? const {}
|
|
|
|
: const {ReportPeriod.month, ReportPeriod.year},
|
|
|
|
onLockedPeriodTap: (_) => onSubscribe(),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
const SizedBox(height: 8),
|
|
|
|
Obx(
|
|
|
|
() => ReportDateSwitcher(
|
|
|
|
label: logic.dateLabel,
|
|
|
|
onPrevious: isVip ? logic.previousDay : onSubscribe,
|
|
|
|
onNext: isVip ? logic.nextDay : onSubscribe,
|
|
|
|
onTapLabel: isVip
|
|
|
|
? () => _showDatePicker(context)
|
|
|
|
: onSubscribe,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
const SizedBox(height: 8),
|
|
|
|
Obx(() {
|
|
|
|
print("------, ${logic.dateLabel}");
|
|
|
|
return ReportDateSwitcher(
|
|
|
|
label: logic.dateLabel,
|
|
|
|
onPrevious: logic.previousDay,
|
|
|
|
onNext: logic.nextDay,
|
|
|
|
onTapLabel: () => _showDatePicker(context),
|
|
|
|
),
|
|
|
|
Expanded(
|
|
|
|
child: Obx(
|
|
|
|
() {
|
|
|
|
if (logic.isLoading.value) {
|
|
|
|
return const ReportLoadingIndicator();
|
|
|
|
}
|
|
|
|
return ListView(
|
|
|
|
physics: const ClampingScrollPhysics(),
|
|
|
|
padding: const EdgeInsets.fromLTRB(16, 20, 16, 0),
|
|
|
|
children: [
|
|
|
|
if (logic.selectedPeriod.value == ReportPeriod.year)
|
|
|
|
HrvYearReportView(report: logic.yearlyReport.value)
|
|
|
|
else if (logic.selectedPeriod.value ==
|
|
|
|
ReportPeriod.month)
|
|
|
|
HrvMonthReportView(report: logic.monthlyReport.value)
|
|
|
|
else
|
|
|
|
HrvWeekReportView(
|
|
|
|
report: logic.weeklyReport.value,
|
|
|
|
showExample: !isVip,
|
|
|
|
onSubscribe: onSubscribe,
|
|
|
|
),
|
|
|
|
const ReportBottomSlogan(),
|
|
|
|
],
|
|
|
|
);
|
|
|
|
},
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
Expanded(
|
|
|
|
child: Obx(
|
|
|
|
() => ListView(
|
|
|
|
physics: const ClampingScrollPhysics(),
|
|
|
|
padding: const EdgeInsets.fromLTRB(16, 20, 16, 0),
|
|
|
|
children: [
|
|
|
|
if (logic.selectedPeriod.value == ReportPeriod.year)
|
|
|
|
HrvYearReportView(report: logic.yearlyReport.value)
|
|
|
|
else if (logic.selectedPeriod.value == ReportPeriod.month)
|
|
|
|
HrvMonthReportView(report: logic.monthlyReport.value)
|
|
|
|
else
|
|
|
|
HrvWeekReportView(report: logic.weeklyReport.value),
|
|
|
|
const ReportBottomSlogan(),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
if (!isVip)
|
|
|
|
Obx(
|
|
|
|
() => logic.selectedPeriod.value == ReportPeriod.week
|
|
|
|
? Positioned(
|
|
|
|
left: 0,
|
|
|
|
right: 0,
|
|
|
|
bottom: MediaQuery.paddingOf(context).bottom + 88,
|
|
|
|
child: Center(
|
|
|
|
child: _UnlockButton(onPressed: onSubscribe),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
: const SizedBox.shrink(),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
...
|
...
|
@@ -78,14 +118,61 @@ class HrvReportView extends StatelessWidget { |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class _UnlockButton extends StatelessWidget {
|
|
|
|
const _UnlockButton({required this.onPressed});
|
|
|
|
|
|
|
|
final VoidCallback onPressed;
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return SizedBox(
|
|
|
|
width: 240,
|
|
|
|
height: 48,
|
|
|
|
child: ElevatedButton(
|
|
|
|
onPressed: onPressed,
|
|
|
|
style: ElevatedButton.styleFrom(
|
|
|
|
elevation: 0,
|
|
|
|
shadowColor: Colors.transparent,
|
|
|
|
backgroundColor: const Color(0xFFFFDF51),
|
|
|
|
foregroundColor: const Color(0xFF0F0F11),
|
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
|
|
|
shape: RoundedRectangleBorder(
|
|
|
|
borderRadius: BorderRadius.circular(24),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
child: Row(
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
children: [
|
|
|
|
Image.asset(
|
|
|
|
R.assetsImagesProIcon,
|
|
|
|
width: 24,
|
|
|
|
height: 24,
|
|
|
|
color: const Color(0xFF0F0F11),
|
|
|
|
),
|
|
|
|
const SizedBox(width: 8),
|
|
|
|
const Text(
|
|
|
|
'立即解锁',
|
|
|
|
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class _HrvPeriodBar extends StatelessWidget {
|
|
|
|
const _HrvPeriodBar({
|
|
|
|
required this.selectedPeriod,
|
|
|
|
required this.onChanged,
|
|
|
|
required this.lockedPeriods,
|
|
|
|
required this.onLockedPeriodTap,
|
|
|
|
});
|
|
|
|
|
|
|
|
final ReportPeriod selectedPeriod;
|
|
|
|
final ValueChanged<ReportPeriod> onChanged;
|
|
|
|
final Set<ReportPeriod> lockedPeriods;
|
|
|
|
final ValueChanged<ReportPeriod> onLockedPeriodTap;
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
...
|
...
|
@@ -106,7 +193,13 @@ class _HrvPeriodBar extends StatelessWidget { |
|
|
|
Expanded(
|
|
|
|
child: GestureDetector(
|
|
|
|
behavior: HitTestBehavior.opaque,
|
|
|
|
onTap: () => onChanged(item.period),
|
|
|
|
onTap: () {
|
|
|
|
if (lockedPeriods.contains(item.period)) {
|
|
|
|
onLockedPeriodTap(item.period);
|
|
|
|
} else {
|
|
|
|
onChanged(item.period);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
child: Container(
|
|
|
|
alignment: Alignment.center,
|
|
|
|
decoration: BoxDecoration(
|
|
...
|
...
|
@@ -117,15 +210,30 @@ class _HrvPeriodBar extends StatelessWidget { |
|
|
|
selectedPeriod == item.period ? 26 : 8,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
child: Text(
|
|
|
|
item.label,
|
|
|
|
style: TextStyle(
|
|
|
|
color: selectedPeriod == item.period
|
|
|
|
? const Color(0xFF0F0F11)
|
|
|
|
: const Color(0xFF78787D),
|
|
|
|
fontSize: 14,
|
|
|
|
fontWeight: FontWeight.w500,
|
|
|
|
),
|
|
|
|
child: Row(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
children: [
|
|
|
|
if (lockedPeriods.contains(item.period)) ...[
|
|
|
|
Image.asset(
|
|
|
|
R.assetsImagesLockIcon,
|
|
|
|
width: 14,
|
|
|
|
height: 14,
|
|
|
|
color: const Color(0xFF845EEE),
|
|
|
|
colorBlendMode: BlendMode.srcIn,
|
|
|
|
),
|
|
|
|
const SizedBox(width: 2),
|
|
|
|
],
|
|
|
|
Text(
|
|
|
|
item.label,
|
|
|
|
style: TextStyle(
|
|
|
|
color: selectedPeriod == item.period
|
|
|
|
? const Color(0xFF0F0F11)
|
|
|
|
: const Color(0xFF78787D),
|
|
|
|
fontSize: 14,
|
|
|
|
fontWeight: FontWeight.w500,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
...
|
...
|
|