purchase_plan_card.dart 6.33 KB
import 'package:flutter/material.dart';

import '../controllers/purchase_controller.dart';
import 'purchase_colors.dart';

class PurchasePlanCard extends StatelessWidget {
  const PurchasePlanCard({
    super.key,
    required this.plan,
    required this.selected,
    required this.onTap,
  });

  final PurchasePlan plan;
  final bool selected;
  final VoidCallback onTap;

  @override
  Widget build(BuildContext context) {
    return Semantics(
      selected: selected,
      button: true,
      child: GestureDetector(
        onTap: onTap,
        behavior: HitTestBehavior.opaque,
        child: AnimatedScale(
          scale: selected ? 1 : 0.985,
          duration: const Duration(milliseconds: 180),
          curve: Curves.easeOutCubic,
          child: SizedBox(
            width: 220,
            height: 123,
            child: Stack(
              clipBehavior: Clip.none,
              children: [
                Positioned(
                  left: 0,
                  right: 0,
                  bottom: 0,
                  child: AnimatedContainer(
                    duration: const Duration(milliseconds: 180),
                    curve: Curves.easeOutCubic,
                    height: 115,
                    padding: const EdgeInsets.fromLTRB(17, 16, 17, 12),
                    decoration: BoxDecoration(
                      color:
                          selected ? PurchaseColors.selectedCard : Colors.white,
                      borderRadius: BorderRadius.circular(16),
                      border: Border.all(
                        color: selected
                            ? PurchaseColors.proPurple
                            : Colors.transparent,
                        width: 2,
                      ),
                    ),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Row(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Expanded(
                              child: Text(
                                plan.title,
                                maxLines: 1,
                                overflow: TextOverflow.ellipsis,
                                style: const TextStyle(
                                  color: PurchaseColors.title,
                                  fontSize: 16,
                                  fontWeight: FontWeight.w600,
                                  height: 1.2,
                                ),
                              ),
                            ),
                            _SelectionDot(selected: selected),
                          ],
                        ),
                        const SizedBox(height: 3),
                        Text(
                          plan.subtitle,
                          maxLines: 1,
                          overflow: TextOverflow.ellipsis,
                          style: const TextStyle(
                            color: PurchaseColors.subtitle,
                            fontSize: 12,
                            height: 1.2,
                          ),
                        ),
                        const Spacer(),
                        Row(
                          crossAxisAlignment: CrossAxisAlignment.end,
                          children: [
                            const Padding(
                              padding: EdgeInsets.only(bottom: 3),
                              child: Text(
                                '¥',
                                style: TextStyle(
                                  color: PurchaseColors.title,
                                  fontSize: 16,
                                  fontWeight: FontWeight.w600,
                                  height: 1,
                                ),
                              ),
                            ),
                            Text(
                              plan.price,
                              maxLines: 1,
                              overflow: TextOverflow.ellipsis,
                              style: const TextStyle(
                                color: PurchaseColors.title,
                                fontSize: 24,
                                fontWeight: FontWeight.w700,
                                height: 1,
                              ),
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),
                ),
                Positioned(
                  left: 16,
                  top: 0,
                  child: Container(
                    height: 20,
                    padding: const EdgeInsets.symmetric(horizontal: 6),
                    alignment: Alignment.center,
                    decoration: BoxDecoration(
                      color: PurchaseColors.proYellow,
                      borderRadius: BorderRadius.circular(8),
                    ),
                    child: Text(
                      plan.badge,
                      style: const TextStyle(
                        color: PurchaseColors.title,
                        fontSize: 12,
                        fontWeight: FontWeight.w500,
                        height: 1,
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class _SelectionDot extends StatelessWidget {
  const _SelectionDot({required this.selected});

  final bool selected;

  @override
  Widget build(BuildContext context) {
    return AnimatedContainer(
      duration: const Duration(milliseconds: 180),
      curve: Curves.easeOutCubic,
      width: 18,
      height: 18,
      decoration: BoxDecoration(
        color: selected ? PurchaseColors.proPurple : Colors.transparent,
        shape: BoxShape.circle,
        border: selected ? null : Border.all(color: const Color(0xFFE2E0EA)),
      ),
      child: AnimatedSwitcher(
        duration: const Duration(milliseconds: 120),
        child: selected
            ? const Icon(
                Icons.check,
                key: ValueKey('selected'),
                size: 13,
                color: Colors.white,
              )
            : const SizedBox(key: ValueKey('unselected')),
      ),
    );
  }
}