friends_tab.dart 9.32 KB
import 'package:doublefeel_flutter/app/routes/app_pages.dart';
import 'package:doublefeel_flutter/core/util/size_extensions.dart';
import 'package:doublefeel_flutter/r.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

import '../controllers/friends_controller.dart';
import '../widgets/friend_health_card.dart';

class FriendsTab extends GetView<FriendsController> {
  const FriendsTab({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFFF2F2F7),
      body: SafeArea(
        bottom: false,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const _FriendsHeader(),
            Expanded(
              child: Obx(
                () {
                  final friends = controller.friends;
                  final hasFriends = friends.isNotEmpty;
                  final isFull = controller.isFull;

                  return Stack(
                    children: [
                      RefreshIndicator(
                        onRefresh: controller.loadFriends,
                        child: ListView(
                          padding: EdgeInsets.fromLTRB(
                            16,
                            0,
                            16,
                            hasFriends ? 188.dp : 172,
                          ),
                          children: [
                            const FriendHealthCard(
                              name: '蓝胖子(我)',
                              updatedAt: '更新于15:12',
                              sleepQualityScore: 92,
                              steps: '8424步',
                              statusText: '注意压力',
                              stressValue: 72,
                              isSelf: true,
                            ),
                            if (!hasFriends)
                              const _EmptyFriendsView()
                            else ...[
                              const SizedBox(height: 12),
                              ...friends.map(
                                (friend) => Padding(
                                  padding: const EdgeInsets.only(bottom: 12),
                                  child: FriendHealthCard(
                                    name: friend.name,
                                    updatedAt: friend.updatedAt,
                                    sleepQualityScore: friend.sleepQualityScore,
                                    steps: friend.steps,
                                    statusText: friend.statusText,
                                    stressValue: friend.stressValue,
                                    isOnWatchFace: friend.isOnWatchFace,
                                    onMoreSelected: (action) {
                                      _handleFriendAction(action, friend);
                                    },
                                  ),
                                ),
                              ),
                            ],
                            if (!hasFriends) ...[
                              const SizedBox(height: 8),
                              _AddFriendButton(
                                enabled: !isFull,
                                onTap: isFull ? null : _handleAddFriend,
                              ),
                              if (isFull) const _FullFriendsTip(),
                            ],
                          ],
                        ),
                      ),
                      if (hasFriends)
                        Positioned(
                          left: 0,
                          right: 0,
                          bottom: _floatingAddButtonBottom(context),
                          child: Column(
                            children: [
                              _AddFriendButton(
                                enabled: !isFull,
                                friendCount: friends.length,
                                maxFriends: FriendsController.maxFriends,
                                onTap: isFull ? null : _handleAddFriend,
                              ),
                              if (isFull) const _FullFriendsTip(),
                            ],
                          ),
                        ),
                    ],
                  );
                },
              ),
            ),
          ],
        ),
      ),
    );
  }

  double _floatingAddButtonBottom(BuildContext context) {
    const tabBarHeight = 56.0;
    const tabBarBottomPadding = 8.0;
    return MediaQuery.viewPaddingOf(context).bottom +
        tabBarHeight +
        tabBarBottomPadding +
        23.dp;
  }

  Future<void> _handleAddFriend() async {
    await Get.toNamed(Routes.ADD_FRIEND);
    await controller.loadFriends();
  }

  void _handleFriendAction(FriendCardAction action, FriendHealthData friend) {
    switch (action) {
      case FriendCardAction.editRemark:
        controller.showEditRemarkDialog(friend);
      case FriendCardAction.remove:
        controller.showDeleteConfirmDialog(friend);
      case FriendCardAction.watchFace:
        Get.toNamed(Routes.SELECT_FRIEND);
    }
  }
}

class _FriendsHeader extends StatelessWidget {
  const _FriendsHeader();

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 44,
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 16),
        child: Row(
          children: [
            const Text(
              '好友',
              style: TextStyle(
                color: Color(0xFF0F0F11),
                fontSize: 24,
                fontWeight: FontWeight.w600,
                height: 1.4,
              ),
            ),
            const Spacer(),
            IconButton(
              onPressed: () {
                _navigatorToPrivacySettings();
              },
              icon: Image.asset(
                R.assetsImagesSettings,
                width: 24,
                height: 24,
              ),
              padding: EdgeInsets.zero,
              constraints: const BoxConstraints.tightFor(width: 40, height: 40),
            ),
          ],
        ),
      ),
    );
  }
}

_navigatorToPrivacySettings() {
  Get.toNamed(Routes.PRIVACY_SETTINGS);
}

class _EmptyFriendsView extends StatelessWidget {
  const _EmptyFriendsView();

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(top: 70),
      child: Column(
        children: [
          Container(
            width: 240,
            height: 180,
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(18),
            ),
            child: const Center(
              child: Icon(
                Icons.favorite_border_rounded,
                size: 68,
                color: Color(0xFFD8D2EA),
              ),
            ),
          ),
          const SizedBox(height: 16),
          const Text(
            '添加亲密联系人,多一个人关注你的健康',
            style: TextStyle(
              color: Color(0xFF78787D),
              fontSize: 12,
              fontWeight: FontWeight.w400,
            ),
          ),
        ],
      ),
    );
  }
}

class _FullFriendsTip extends StatelessWidget {
  const _FullFriendsTip();

  @override
  Widget build(BuildContext context) {
    return const Padding(
      padding: EdgeInsets.only(top: 10),
      child: Center(
        child: Text(
          '好友数量已达上限',
          style: TextStyle(
            color: Color(0xFFB0B0B6),
            fontSize: 12,
            fontWeight: FontWeight.w400,
          ),
        ),
      ),
    );
  }
}

class _AddFriendButton extends StatelessWidget {
  const _AddFriendButton({
    required this.enabled,
    this.friendCount,
    this.maxFriends,
    this.onTap,
  });

  final bool enabled;
  final int? friendCount;
  final int? maxFriends;
  final VoidCallback? onTap;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: GestureDetector(
        onTap: onTap,
        behavior: HitTestBehavior.opaque,
        child: Opacity(
          opacity: enabled ? 1 : 0.4,
          child: Container(
            width: 240,
            height: 48,
            decoration: BoxDecoration(
              color:
                  enabled ? const Color(0xFF845EEE) : const Color(0xFFD0D0D2),
              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,
                  style: const TextStyle(
                    color: Colors.white,
                    fontSize: 16,
                    fontWeight: FontWeight.w600,
                    height: 1.4,
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  String get _buttonText {
    final count = friendCount;
    final max = maxFriends;
    if (count == null || max == null) return '添加亲密联系人';
    return '添加亲密联系人($count/$max)';
  }
}