import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import '../../controllers/add_subscription_controller.dart'; import '../../providers/category_provider.dart'; import '../../l10n/app_localizations.dart'; import '../common/form_fields/base_text_field.dart'; import '../common/form_fields/currency_input_field.dart'; import '../common/form_fields/date_picker_field.dart'; import '../common/form_fields/currency_selector.dart'; import '../common/form_fields/billing_cycle_selector.dart'; import '../common/form_fields/category_selector.dart'; import '../glassmorphism_card.dart'; import '../../theme/app_colors.dart'; /// 구독 추가 화면의 폼 섹션 class AddSubscriptionForm extends StatelessWidget { final AddSubscriptionController controller; final Animation fadeAnimation; final Animation slideAnimation; final Function setState; const AddSubscriptionForm({ super.key, required this.controller, required this.fadeAnimation, required this.slideAnimation, required this.setState, }); @override Widget build(BuildContext context) { return FadeTransition( opacity: Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation( parent: controller.animationController!, curve: const Interval(0.2, 1.0, curve: Curves.easeIn), ), ), child: SlideTransition( position: Tween( begin: const Offset(0.0, 0.4), end: Offset.zero, ).animate(CurvedAnimation( parent: controller.animationController!, curve: const Interval(0.2, 1.0, curve: Curves.easeOutCubic), )), child: GlassmorphismCard( backgroundColor: AppColors.glassCard, child: Padding( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 헤더 Row( children: [ ShaderMask( shaderCallback: (bounds) => LinearGradient( colors: controller.gradientColors, begin: Alignment.topLeft, end: Alignment.bottomRight, ).createShader(bounds), child: const Icon( FontAwesomeIcons.fileLines, size: 20, color: Colors.white, ), ), const SizedBox(width: 12), Text( AppLocalizations.of(context).serviceInfo, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.w700, letterSpacing: -0.5, color: Color(0xFF1E293B), ), ), ], ), const SizedBox(height: 24), // 서비스명 필드 BaseTextField( controller: controller.serviceNameController, focusNode: controller.serviceNameFocus, label: AppLocalizations.of(context).labelServiceName, hintText: AppLocalizations.of(context).hintServiceName, textInputAction: TextInputAction.next, onEditingComplete: () { controller.monthlyCostFocus.requestFocus(); }, validator: (value) { if (value == null || value.isEmpty) { return AppLocalizations.of(context).serviceNameRequired; } return null; }, ), const SizedBox(height: 20), // 월 지출 및 통화 선택 Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( flex: 2, child: CurrencyInputField( controller: controller.monthlyCostController, currency: controller.currency, label: AppLocalizations.of(context).labelMonthlyExpense, focusNode: controller.monthlyCostFocus, textInputAction: TextInputAction.next, onEditingComplete: () { controller.billingCycleFocus.requestFocus(); }, validator: (value) { if (value == null || value.isEmpty) { return AppLocalizations.of(context).amountRequired; } return null; }, ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( AppLocalizations.of(context).currency, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 8), CurrencySelector( currency: controller.currency, isGlassmorphism: true, onChanged: (value) { setState(() { controller.currency = value; }); }, ), ], ), ), ], ), const SizedBox(height: 20), // 결제 주기 Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( AppLocalizations.of(context).billingCycle, style: const TextStyle( color: AppColors.textPrimary, fontSize: 16, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 8), BillingCycleSelector( billingCycle: controller.billingCycle, baseColor: controller.gradientColors[0], isGlassmorphism: true, onChanged: (value) { setState(() { controller.billingCycle = value; }); }, ), ], ), const SizedBox(height: 20), // 다음 결제일 DatePickerField( selectedDate: controller.nextBillingDate ?? DateTime.now(), onDateSelected: (date) { setState(() { controller.nextBillingDate = date; }); }, label: AppLocalizations.of(context).nextBillingDate, firstDate: DateTime.now(), lastDate: DateTime.now().add(const Duration(days: 365 * 2)), primaryColor: controller.gradientColors[0], ), const SizedBox(height: 20), // 웹사이트 URL BaseTextField( controller: controller.websiteUrlController, focusNode: controller.websiteUrlFocus, label: AppLocalizations.of(context).websiteUrlOptional, hintText: AppLocalizations.of(context).hintWebsiteUrl, keyboardType: TextInputType.url, prefixIcon: Icon( Icons.link_rounded, color: Colors.grey[600], ), ), const SizedBox(height: 20), // 카테고리 선택 Consumer( builder: (context, categoryProvider, child) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( AppLocalizations.of(context).category, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 8), CategorySelector( categories: categoryProvider.categories, selectedCategoryId: controller.selectedCategoryId, baseColor: controller.gradientColors[0], isGlassmorphism: true, onChanged: (categoryId) { setState(() { controller.selectedCategoryId = categoryId; }); }, ), ], ); }, ), ], ), ), ), ), ); } }