health_trend_content.dart 5.57 KB
import 'package:flutter/material.dart';

import '../../activity_burn_report/controllers/activity_burn_report_logic.dart';
import '../../activity_burn_report/views/activity_burn_report_view.dart';
import '../../home/widgets/trend/trend_type_tab_bar.dart';
import '../../hrv_report/controllers/hrv_report_logic.dart';
import '../../hrv_report/views/hrv_report_view.dart';
import '../../report_common/models/health_report_query.dart';
import '../../sleep_report/controllers/sleep_report_logic.dart';
import '../../sleep_report/views/sleep_report_view.dart';

class HealthTrendContent extends StatefulWidget {
  const HealthTrendContent({
    super.key,
    required this.query,
    required this.selectedTypeIndex,
    required this.onTypeChanged,
  });

  final HealthReportQuery query;
  final int selectedTypeIndex;
  final ValueChanged<int> onTypeChanged;

  @override
  State<HealthTrendContent> createState() => _HealthTrendContentState();
}

class _HealthTrendContentState extends State<HealthTrendContent>
    with SingleTickerProviderStateMixin {
  late final TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(
      length: 3,
      vsync: this,
      initialIndex: widget.selectedTypeIndex,
    );
    _tabController.addListener(() {
      if (!_tabController.indexIsChanging) {
        widget.onTypeChanged(_tabController.index);
      }
    });
  }

  @override
  void didUpdateWidget(covariant HealthTrendContent oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.selectedTypeIndex != widget.selectedTypeIndex &&
        _tabController.index != widget.selectedTypeIndex) {
      _tabController.animateTo(widget.selectedTypeIndex);
    }
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TrendTypeTabBar(tabController: _tabController),
        Expanded(
          child: TabBarView(
            controller: _tabController,
            children: [
              _KeepAliveWrapper(
                child: _HrvTrendSection(query: widget.query),
              ),
              _KeepAliveWrapper(
                child: _ActivityBurnTrendSection(query: widget.query),
              ),
              _KeepAliveWrapper(
                child: _SleepTrendSection(query: widget.query),
              ),
            ],
          ),
        ),
      ],
    );
  }
}

class _HrvTrendSection extends StatefulWidget {
  const _HrvTrendSection({required this.query});

  final HealthReportQuery query;

  @override
  State<_HrvTrendSection> createState() => _HrvTrendSectionState();
}

class _HrvTrendSectionState extends State<_HrvTrendSection> {
  late final HrvReportLogic _logic;

  @override
  void initState() {
    super.initState();
    _logic = HrvReportLogic(initialTargetUserId: widget.query.targetUserId);
    _logic.loadReport();
  }

  @override
  void didUpdateWidget(covariant _HrvTrendSection oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.query != widget.query) {
      _logic.updateTargetUserId(widget.query.targetUserId);
    }
  }

  @override
  void dispose() {
    _logic.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) => HrvReportView(logic: _logic);
}

class _ActivityBurnTrendSection extends StatefulWidget {
  const _ActivityBurnTrendSection({required this.query});

  final HealthReportQuery query;

  @override
  State<_ActivityBurnTrendSection> createState() =>
      _ActivityBurnTrendSectionState();
}

class _ActivityBurnTrendSectionState extends State<_ActivityBurnTrendSection> {
  late final ActivityBurnReportLogic _logic;

  @override
  void initState() {
    super.initState();
    _logic = ActivityBurnReportLogic(
      initialTargetUserId: widget.query.targetUserId,
    );
    _logic.loadReport();
  }

  @override
  void didUpdateWidget(covariant _ActivityBurnTrendSection oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.query != widget.query) {
      _logic.updateTargetUserId(widget.query.targetUserId);
    }
  }

  @override
  void dispose() {
    _logic.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) => ActivityBurnReportView(logic: _logic);
}

class _SleepTrendSection extends StatefulWidget {
  const _SleepTrendSection({required this.query});

  final HealthReportQuery query;

  @override
  State<_SleepTrendSection> createState() => _SleepTrendSectionState();
}

class _SleepTrendSectionState extends State<_SleepTrendSection> {
  late final SleepReportLogic _logic;

  @override
  void initState() {
    super.initState();
    _logic = SleepReportLogic(
      initialTargetUserId: widget.query.targetUserId,
    );
    _logic.loadReport();
  }

  @override
  void didUpdateWidget(covariant _SleepTrendSection oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.query != widget.query) {
      _logic.updateTargetUserId(widget.query.targetUserId);
    }
  }

  @override
  void dispose() {
    _logic.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) => SleepReportView(logic: _logic);
}

class _KeepAliveWrapper extends StatefulWidget {
  const _KeepAliveWrapper({required this.child});

  final Widget child;

  @override
  State<_KeepAliveWrapper> createState() => _KeepAliveWrapperState();
}

class _KeepAliveWrapperState extends State<_KeepAliveWrapper>
    with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return widget.child;
  }
}