import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../../models/subscription_model.dart'; import '../../services/subscription_service.dart'; class SubscriptionDetailsScreen extends StatefulWidget { final SubscriptionPlan plan; final bool isYearly; const SubscriptionDetailsScreen({ super.key, required this.plan, required this.isYearly, }); @override State createState() => _SubscriptionDetailsScreenState(); } class _SubscriptionDetailsScreenState extends State { bool _isLoading = false; @override Widget build(BuildContext context) { final price = widget.isYearly ? widget.plan.yearlyPrice : widget.plan.monthlyPrice; final period = widget.isYearly ? '년' : '월'; return Scaffold( appBar: AppBar( title: Text('${widget.plan.name} 플랜'), ), body: Stack( children: [ SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 플랜 헤더 _buildPlanHeader(price, period), const SizedBox(height: 24), // 플랜 설명 Text( widget.plan.description, style: const TextStyle(fontSize: 16), ), const SizedBox(height: 24), // 플랜 혜택 const Text( '플랜 혜택', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 16), ...widget.plan.features.map((feature) => _buildFeatureItem(feature)), const SizedBox(height: 24), // 플랜 세부 정보 const Text( '세부 정보', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 16), _buildDetailItem('최대 회원 수', '${widget.plan.maxMembers}명'), _buildDetailItem('최대 이벤트 수', '${widget.plan.maxEvents}개'), _buildDetailItem( '고급 통계 기능', widget.plan.hasAdvancedStats ? '제공' : '미제공', isAvailable: widget.plan.hasAdvancedStats, ), _buildDetailItem( '맞춤형 기능', widget.plan.hasCustomization ? '제공' : '미제공', isAvailable: widget.plan.hasCustomization, ), _buildDetailItem( '우선 지원', widget.plan.hasPriority ? '제공' : '미제공', isAvailable: widget.plan.hasPriority, ), const SizedBox(height: 24), // 결제 정보 const Text( '결제 정보', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 16), _buildDetailItem( '결제 주기', widget.isYearly ? '연간' : '월간', ), _buildDetailItem( '결제 금액', '₩${_formatPrice(price)}/${widget.isYearly ? '년' : '월'}', ), if (widget.isYearly) _buildDetailItem( '월 환산 금액', '₩${_formatPrice(widget.plan.yearlyPrice / 12)}/월', ), _buildDetailItem( '자동 갱신', '활성화 (설정에서 변경 가능)', ), // 하단 여백 (버튼 높이만큼) const SizedBox(height: 80), ], ), ), // 하단 구독 버튼 Positioned( left: 0, right: 0, bottom: 0, child: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 10, offset: const Offset(0, -5), ), ], ), child: ElevatedButton( onPressed: _isLoading ? null : () => _subscribe(context), style: ElevatedButton.styleFrom( backgroundColor: Colors.blue, foregroundColor: Colors.white, minimumSize: const Size(double.infinity, 50), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: _isLoading ? const CircularProgressIndicator(color: Colors.white) : Text( widget.plan.type == SubscriptionPlanType.free ? '무료 플랜 시작하기' : '구독하기', ), ), ), ), ], ), ); } Widget _buildPlanHeader(double price, String period) { return Card( elevation: 4, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), side: BorderSide( color: _getPlanColor(), width: 2, ), ), child: Padding( padding: const EdgeInsets.all(16), child: Column( children: [ Row( children: [ Icon( _getPlanIcon(), color: _getPlanColor(), size: 32, ), const SizedBox(width: 16), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.plan.name, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, ), ), if (widget.plan.type == SubscriptionPlanType.premium) Container( margin: const EdgeInsets.only(top: 4), padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 2, ), decoration: BoxDecoration( color: Colors.amber.withOpacity(0.1), borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.amber), ), child: const Text( '인기 플랜', style: TextStyle( color: Colors.amber, fontSize: 12, fontWeight: FontWeight.bold, ), ), ), ], ), ], ), const SizedBox(height: 16), const Divider(), const SizedBox(height: 16), Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( '₩${_formatPrice(price)}', style: const TextStyle( fontSize: 32, fontWeight: FontWeight.bold, ), ), const SizedBox(width: 4), Padding( padding: const EdgeInsets.only(bottom: 4), child: Text( '/$period', style: const TextStyle(fontSize: 16), ), ), ], ), if (widget.isYearly) Padding( padding: const EdgeInsets.only(top: 8), child: Text( '월 ₩${_formatPrice(widget.plan.yearlyPrice / 12)} (20% 할인)', style: TextStyle( color: Colors.green[700], fontWeight: FontWeight.bold, ), ), ), ], ), ), ); } Widget _buildFeatureItem(String feature) { return Padding( padding: const EdgeInsets.only(bottom: 12), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Icon(Icons.check_circle, color: Colors.green, size: 20), const SizedBox(width: 12), Expanded(child: Text(feature, style: const TextStyle(fontSize: 16))), ], ), ); } Widget _buildDetailItem(String label, String value, {bool isAvailable = true}) { return Padding( padding: const EdgeInsets.only(bottom: 12), child: Row( children: [ Expanded( flex: 2, child: Text( label, style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 16, ), ), ), Expanded( flex: 3, child: Text( value, style: TextStyle( fontSize: 16, color: isAvailable ? null : Colors.grey, ), ), ), ], ), ); } Color _getPlanColor() { switch (widget.plan.type) { case SubscriptionPlanType.free: return Colors.grey; case SubscriptionPlanType.basic: return Colors.blue; case SubscriptionPlanType.premium: return Colors.amber; case SubscriptionPlanType.enterprise: return Colors.purple; } } IconData _getPlanIcon() { switch (widget.plan.type) { case SubscriptionPlanType.free: return Icons.star_border; case SubscriptionPlanType.basic: return Icons.star_half; case SubscriptionPlanType.premium: return Icons.star; case SubscriptionPlanType.enterprise: return Icons.workspace_premium; } } String _formatPrice(double price) { if (price == 0) { return '0'; } // 천 단위 콤마 추가 final priceInt = price.toInt(); return priceInt.toString().replaceAllMapped( RegExp(r'(\d{1,3})(?=(\d{3})+(?!\d))'), (Match m) => '${m[1]},', ); } Future _subscribe(BuildContext context) async { setState(() { _isLoading = true; }); try { final subscriptionService = Provider.of(context, listen: false); final success = await subscriptionService.createSubscription( widget.plan.type, widget.isYearly, ); if (success && mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('구독이 성공적으로 완료되었습니다')), ); Navigator.of(context).pop(); // 상세 화면 닫기 } else if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(subscriptionService.error ?? '구독 처리 중 오류가 발생했습니다'), backgroundColor: Colors.red, ), ); } } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('오류: $e'), backgroundColor: Colors.red, ), ); } } finally { if (mounted) { setState(() { _isLoading = false; }); } } } }