import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../../controllers/detail_screen_controller.dart'; import '../../theme/color_scheme_ext.dart'; // import '../../theme/app_colors.dart'; import '../common/form_fields/currency_input_field.dart'; import '../common/form_fields/date_picker_field.dart'; import '../../l10n/app_localizations.dart'; /// 이벤트 가격 섹션 /// 할인 이벤트 정보를 관리하는 섹션입니다. class DetailEventSection extends StatelessWidget { final DetailScreenController controller; final Animation fadeAnimation; final Animation slideAnimation; const DetailEventSection({ super.key, required this.controller, required this.fadeAnimation, required this.slideAnimation, }); @override Widget build(BuildContext context) { return Consumer( builder: (context, controller, child) { final baseColor = controller.getCardColor(); return FadeTransition( opacity: fadeAnimation, child: SlideTransition( position: Tween( begin: const Offset(0.0, 0.8), end: Offset.zero, ).animate(CurvedAnimation( parent: controller.animationController!, curve: const Interval(0.4, 1.0, curve: Curves.easeOutCubic), )), child: Container( decoration: BoxDecoration( color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(20), border: Border.all( color: Theme.of(context) .colorScheme .outline .withValues(alpha: 0.3), width: 1, ), ), child: Padding( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 헤더 Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: baseColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), ), child: Icon( Icons.local_offer_rounded, color: baseColor, size: 24, ), ), const SizedBox(width: 12), Text( AppLocalizations.of(context).eventPrice, style: TextStyle( fontSize: 18, fontWeight: FontWeight.w700, color: Theme.of(context).colorScheme.onSurface, ), ), ], ), // 이벤트 활성화 스위치 Switch.adaptive( value: controller.isEventActive, onChanged: (value) { controller.isEventActive = value; if (!value) { // 이벤트 비활성화시 관련 정보 초기화 controller.eventStartDate = null; controller.eventEndDate = null; controller.eventPriceController.clear(); } }, activeThumbColor: baseColor, activeTrackColor: baseColor.withValues(alpha: 0.5), ), ], ), // 이벤트 활성화시 표시될 필드들 if (controller.isEventActive) ...[ const SizedBox(height: 20), // 이벤트 설명 Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Theme.of(context) .colorScheme .tertiary .withValues(alpha: 0.08), borderRadius: BorderRadius.circular(12), border: Border.all( color: Theme.of(context) .colorScheme .tertiary .withValues(alpha: 0.3), width: 1, ), ), child: Row( children: [ Icon( Icons.info_outline_rounded, color: Theme.of(context).colorScheme.tertiary, size: 20, ), const SizedBox(width: 8), Expanded( child: Text( AppLocalizations.of(context).eventPriceHint, style: TextStyle( fontSize: 14, color: Theme.of(context).colorScheme.onSurface, fontWeight: FontWeight.w500, ), ), ), ], ), ), const SizedBox(height: 20), // 이벤트 기간 DateRangePickerField( startDate: controller.eventStartDate, endDate: controller.eventEndDate, onStartDateSelected: (date) { controller.eventStartDate = date; // 시작일 설정 시 종료일이 없으면 자동으로 1달 후로 설정 if (date != null && controller.eventEndDate == null) { controller.eventEndDate = date.add(const Duration(days: 30)); } }, onEndDateSelected: (date) { controller.eventEndDate = date; }, startLabel: AppLocalizations.of(context).startDate, endLabel: AppLocalizations.of(context).endDate, primaryColor: baseColor, ), const SizedBox(height: 20), // 이벤트 가격 CurrencyInputField( controller: controller.eventPriceController, currency: controller.currency, label: AppLocalizations.of(context).eventPrice, hintText: AppLocalizations.of(context).eventPriceHint, validator: controller.isEventActive ? (value) { if (value == null || value.isEmpty) { return AppLocalizations.of(context) .eventPriceRequired; } final price = double.tryParse(value.replaceAll(',', '')); if (price == null || price <= 0) { return AppLocalizations.of(context) .invalidPrice; } return null; } : null, ), const SizedBox(height: 16), // 할인율 표시 if (controller.eventPriceController.text.isNotEmpty) _DiscountBadge( originalPrice: controller.subscription.monthlyCost, eventPrice: double.tryParse(controller .eventPriceController.text .replaceAll(',', '')) ?? 0, currency: controller.currency, ), ], ], ), ), ), ), ); }, ); } } /// 할인율 배지 class _DiscountBadge extends StatelessWidget { final double originalPrice; final double eventPrice; final String currency; const _DiscountBadge({ required this.originalPrice, required this.eventPrice, required this.currency, }); @override Widget build(BuildContext context) { if (eventPrice >= originalPrice || eventPrice <= 0) { return const SizedBox.shrink(); } final discountPercentage = ((originalPrice - eventPrice) / originalPrice * 100).round(); final discountAmount = originalPrice - eventPrice; return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Theme.of(context).colorScheme.success.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), ), child: Row( children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Theme.of(context).colorScheme.success, borderRadius: BorderRadius.circular(8), ), child: Text( AppLocalizations.of(context) .discountPercent .replaceAll('@', discountPercentage.toString()), style: TextStyle( color: Theme.of(context).colorScheme.onPrimary, fontSize: 12, fontWeight: FontWeight.w600, ), ), ), const SizedBox(width: 12), Text( _getLocalizedDiscountAmount(context, currency, discountAmount), style: TextStyle( color: Theme.of(context).colorScheme.success, fontSize: 14, fontWeight: FontWeight.w500, ), ), ], ), ); } String _getLocalizedDiscountAmount( BuildContext context, String currency, double amount) { final loc = AppLocalizations.of(context); switch (currency) { case 'KRW': return loc.discountAmountWon.replaceAll('@', amount.toInt().toString()); case 'JPY': return loc.discountAmountYen.replaceAll('@', amount.toInt().toString()); case 'CNY': return loc.discountAmountYuan .replaceAll('@', amount.toStringAsFixed(2)); default: // USD return loc.discountAmountDollar .replaceAll('@', amount.toStringAsFixed(2)); } } }