membership_detail_view.dart 16.5 KB
import 'package:doublefeel_flutter/app/modules/membership_offer/controllers/membership_detail_controller.dart';
import 'package:doublefeel_flutter/app/modules/purchase/widgets/refund_explanation_bottom_sheet.dart';
import 'package:doublefeel_flutter/app/utils/platform_compact.dart';
import 'package:doublefeel_flutter/app/widget/premium_benefit_list_view.dart';
import 'package:doublefeel_flutter/app/widget/purchase_legal_notes.dart';
import 'package:doublefeel_flutter/core/theme/app_theme.dart';
import 'package:doublefeel_flutter/data/local/user_preferences_storage.dart';
import 'package:doublefeel_flutter/data/models/local/user_preferences.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart' as context;
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';

class MembershipDetailView extends GetView<MembershipDetailController> {
  const MembershipDetailView({super.key});

  @override
  Widget build(BuildContext context) {
    final userPrefs = Get.find<UserPreferencesStorage>();
    return Scaffold(
      appBar: PreferredSize(
        preferredSize: const Size.fromHeight(kToolbarHeight),
        child: AnimatedBuilder(
          animation: controller.scrollController,
          builder: (context, _) {
            final opacity = controller.scrollController.hasClients
                ? (controller.scrollController.offset / 80).clamp(0.0, 1.0)
                : 0.0;
            return AppBar(
              backgroundColor:
                  context.colors.backgroundPage.withOpacity(opacity),
              surfaceTintColor: Colors.transparent,
              leading: IconButton(
                highlightColor: Colors.transparent,
                splashColor: Colors.transparent,
                padding: EdgeInsets.zero,
                onPressed: Get.back,
                icon: Image.asset(
                  'assets/images/common/ic_nav_back.webp',
                  width: 24,
                  height: 24,
                ),
              ),
              actions: [
                /*
                Padding(
                  padding: const EdgeInsets.only(right: 20.0),
                  child: TextButton(
                    onPressed: controller.isRestoring.value
                        ? null
                        : controller.restorePurchase,
                    style: TextButton.styleFrom(
                      foregroundColor: PurchaseColors.title,
                      padding: const EdgeInsets.symmetric(horizontal: 16),
                      textStyle: const TextStyle(fontSize: 14, height: 1.2),
                    ),
                    child: controller.isRestoring.value
                        ? const SizedBox(
                            width: 16,
                            height: 16,
                            child: CircularProgressIndicator(strokeWidth: 2),
                          )
                        : Text(context.l10n.purchaseRestore),
                  ),
                ),
                */
              ],
            );
          },
        ),
      ),
      extendBodyBehindAppBar: true,
      body: SingleChildScrollView(
        controller: controller.scrollController,
        physics: const ClampingScrollPhysics(),
        padding: EdgeInsets.only(
          bottom: MediaQuery.paddingOf(context).bottom + 16,
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Image.asset(
              'assets/images/today/bg_stress_state_4.png',
              width: Get.width,
              fit: BoxFit.cover,
            ),
            Padding(
              padding: const EdgeInsets.only(top: 31, left: 18),
              child: Text(
                'DoubleFeel Pro',
                style: TextStyle(
                  color: Colors.black,
                  fontSize: 24,
                  fontWeight: FontWeight.w600,
                ),
              ),
            ),
            Padding(
              padding: const EdgeInsets.only(top: 8, left: 18),
              child: Row(
                spacing: 4,
                children: [
                  Container(
                    width: 20,
                    height: 20,
                    clipBehavior: Clip.antiAlias,
                    padding: EdgeInsets.all(1),
                    decoration: ShapeDecoration(
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(20),
                        ),
                        color: context.colors.primary),
                    child: Image.asset('assets/images/common/ic_pro.png'),
                  ),
                  Obx(() {
                    final preferences = userPrefs.preferences.value;
                    final vipInfo = preferences.vipInfo;
                    return Text(
                      _vipSubtitle(vipInfo, context),
                      style: TextStyle(
                        color: context.colors.textPrimary,
                        fontSize: 14,
                        fontWeight: FontWeight.w500,
                      ),
                    );
                  })
                ],
              ),
            ),
            Container(
              color: Color(0xFFD9D9D9),
              height: 1,
              width: Get.width,
              margin: EdgeInsets.only(
                left: 16,
                right: 16,
                top: 28,
              ),
            ),
            Padding(
              padding: const EdgeInsets.only(
                  top: 28, left: 16, right: 16, bottom: 16),
              child: Text(
                context.l10n.enjoyAllPremiumBenefits,
                style: TextStyle(
                  color: Colors.black,
                  fontSize: 18,
                  fontWeight: FontWeight.w600,
                ),
              ),
            ),
            //todo
            PremiumBenefitListView(),

            Obx(() {
              final userPrefs = Get.find<UserPreferencesStorage>();
              final preferences = userPrefs.preferences.value;
              final vipInfo = preferences.vipInfo;
              return (vipInfo == null || vipInfo.vipType == 0)
                  ? SizedBox()
                  : Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Padding(
                          padding: const EdgeInsets.only(
                              top: 28, left: 16, right: 16),
                          child: Text(
                            context.l10n.membershipManagement,
                            style: TextStyle(
                              color: Colors.black,
                              fontSize: 18,
                              fontWeight: FontWeight.w600,
                            ),
                          ),
                        ),
                        Container(
                          margin: EdgeInsets.only(left: 16, right: 16, top: 16),
                          padding: const EdgeInsets.symmetric(horizontal: 20),
                          decoration: ShapeDecoration(
                            color: Colors.white,
                            shape: RoundedRectangleBorder(
                              borderRadius:
                                  BorderRadius.all(Radius.circular(16)),
                            ),
                          ),
                          child: Column(
                            children: [
                              SizedBox(
                                height: 56,
                                child: Row(
                                  children: [
                                    Text(
                                      context.l10n.membershipTypes,
                                      textAlign: TextAlign.center,
                                      style: TextStyle(
                                        color: context.colors.textPrimary,
                                        fontSize: 14,
                                        fontWeight: FontWeight.w400,
                                      ),
                                    ),
                                    Spacer(),
                                    Obx(() {
                                      final preferences =
                                          userPrefs.preferences.value;
                                      final vipInfo = preferences.vipInfo;
                                      return Text(
                                        _vipType(vipInfo),
                                        textAlign: TextAlign.center,
                                        style: TextStyle(
                                          color: context.colors.textPrimary,
                                          fontSize: 14,
                                          fontWeight: FontWeight.w400,
                                        ),
                                      );
                                    })
                                  ],
                                ),
                              ),
                              SizedBox(
                                height: 56,
                                child: Row(
                                  children: [
                                    Text(
                                      context.l10n.validUntil,
                                      textAlign: TextAlign.center,
                                      style: TextStyle(
                                        color: context.colors.textPrimary,
                                        fontSize: 14,
                                        fontWeight: FontWeight.w400,
                                      ),
                                    ),
                                    Spacer(),
                                    Obx(() {
                                      final preferences =
                                          userPrefs.preferences.value;
                                      final vipInfo = preferences.vipInfo;
                                      return Text(
                                        _vipExprieDate(vipInfo, context),
                                        textAlign: TextAlign.center,
                                        style: TextStyle(
                                          color: context.colors.textPrimary,
                                          fontSize: 14,
                                          fontWeight: FontWeight.w400,
                                        ),
                                      );
                                    })
                                  ],
                                ),
                              ),
                              if (isOhos() &&
                                  controller.subscriptionAgreementNo.value !=
                                      null)
                                GestureDetector(
                                  onTap:
                                      controller.showCancelSubscriptionDialog,
                                  behavior: HitTestBehavior.opaque,
                                  child: SizedBox(
                                    height: 56,
                                    child: Row(
                                      children: [
                                        Text(
                                          '取消自动续费',
                                          textAlign: TextAlign.center,
                                          style: TextStyle(
                                            color: context.colors.textPrimary,
                                            fontSize: 14,
                                            fontWeight: FontWeight.w400,
                                          ),
                                        ),
                                        Spacer(),
                                        Image.asset(
                                          'assets/images/common/ic_more_gray.png',
                                          width: 16,
                                          height: 16,
                                        ),
                                      ],
                                    ),
                                  ),
                                ),
                              if (!isOhos() &&
                                  (vipInfo?.vipType == 1 ||
                                      vipInfo?.vipType == 2 ||
                                      vipInfo?.vipType == 3 ||
                                      vipInfo?.vipType == 4))
                                GestureDetector(
                                  onTap: () {
                                    controller.manageSubscription();
                                  },
                                  behavior: HitTestBehavior.opaque,
                                  child: SizedBox(
                                    height: 56,
                                    child: Row(
                                      children: [
                                        Text(
                                          context.l10n.manageSubscriptions,
                                          textAlign: TextAlign.center,
                                          style: TextStyle(
                                            color: context.colors.textPrimary,
                                            fontSize: 14,
                                            fontWeight: FontWeight.w400,
                                          ),
                                        ),
                                        Spacer(),
                                        Image.asset(
                                          'assets/images/common/ic_more_gray.png',
                                          width: 16,
                                          height: 16,
                                        ),
                                      ],
                                    ),
                                  ),
                                ),
                            ],
                          ),
                        ),
                      ],
                    );
            }),
            SizedBox(
              height: 28,
            ),
            isOhos()
                ? OhosPurchaseLegalNotes(
                    onContactUsTap: controller.openContactUs,
                    onSupportEmailTap: controller.openSupportEmail,
                  )
                : IosPurchaseLegalNotes(
                    onRefundExplanationTap: showRefundExplanationBottomSheet,
                    onContactUsTap: controller.openContactUs,
                  )
          ],
        ),
      ),
    );
  }

  String _vipSubtitle(UserPreferencesVipInfo? vipInfo, BuildContext context) {
    final endDate = vipInfo?.vipEndDate ?? 0;
    if (vipInfo?.isVip != true || endDate <= 0) {
      return l10n.unlockNow;
    }

    if (vipInfo?.isForeverVip ?? false) {
      return l10n.purchaseLifetimePlan;
    }

    final milliseconds = endDate > 1000000000000 ? endDate : endDate * 1000;
    final date = DateTime.fromMillisecondsSinceEpoch(milliseconds);
    final locale = Localizations.localeOf(context).languageCode;

    final dateStr = DateFormat.yMMMd(locale).format(date);

    return l10n.membershipValidUntilDate(dateStr);
  }

  String _vipExprieDate(UserPreferencesVipInfo? vipInfo, BuildContext context) {
    final endDate = vipInfo?.vipEndDate ?? 0;
    if (vipInfo?.isVip != true || endDate <= 0) {
      return l10n.unlockNow;
    }

    if (vipInfo?.isForeverVip ?? false) {
      return l10n.purchaseLifetimePlan;
    }

    final milliseconds = endDate > 1000000000000 ? endDate : endDate * 1000;
    final date = DateTime.fromMillisecondsSinceEpoch(milliseconds);
    final locale = Localizations.localeOf(context).languageCode;

    final dateStr = DateFormat.yMMMd(locale).format(date);

    return isOhos() ? dateStr : l10n.membershipValidUntilDate(dateStr);
  }

  String _vipType(UserPreferencesVipInfo? vipInfo) {
    if (vipInfo == null || vipInfo.isVip != true || vipInfo.vipEndDate <= 0) {
      return l10n.unlockNow;
    }

    if (vipInfo.isForeverVip) {
      return l10n.purchaseLifetimePlan;
    }
    switch (vipInfo.vipType) {
      case 1:
        return context.l10n.monthlyMembership;
      case 2:
        return context.l10n.quarterlyMembership;
      case 3:
        return context.l10n.annualMembership;
      case 10:
        return context.l10n.lifetimeMembership;
      default:
        return '';
    }
  }
}