- Extract business logic from screens into dedicated controllers - Split large screen files into smaller, reusable widget components - Add controllers for AddSubscriptionScreen and DetailScreen - Create modular widgets for subscription and detail features - Improve code organization and maintainability - Remove duplicated code and improve reusability 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
154 lines
4.2 KiB
Dart
154 lines
4.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
import '../services/exchange_rate_service.dart';
|
|
|
|
/// 환율 정보를 표시하는 위젯
|
|
/// 달러 금액을 입력받아 원화 금액으로 변환하여 표시합니다.
|
|
class ExchangeRateWidget extends StatefulWidget {
|
|
/// 달러 금액 변화 감지용 TextEditingController
|
|
final TextEditingController costController;
|
|
|
|
/// 환율 정보를 보여줄지 여부 (통화가 달러일 때만 true)
|
|
final bool showExchangeRate;
|
|
|
|
const ExchangeRateWidget({
|
|
Key? key,
|
|
required this.costController,
|
|
required this.showExchangeRate,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
State<ExchangeRateWidget> createState() => _ExchangeRateWidgetState();
|
|
}
|
|
|
|
class _ExchangeRateWidgetState extends State<ExchangeRateWidget> {
|
|
final ExchangeRateService _exchangeRateService = ExchangeRateService();
|
|
String _exchangeRateInfo = '';
|
|
String _convertedAmount = '';
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_loadExchangeRate();
|
|
widget.costController.addListener(_updateConvertedAmount);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
widget.costController.removeListener(_updateConvertedAmount);
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
void didUpdateWidget(ExchangeRateWidget oldWidget) {
|
|
super.didUpdateWidget(oldWidget);
|
|
|
|
// 통화 변경 감지(달러->원화 또는 원화->달러)되면 리스너 해제 및 재등록
|
|
if (oldWidget.showExchangeRate != widget.showExchangeRate) {
|
|
oldWidget.costController.removeListener(_updateConvertedAmount);
|
|
|
|
if (widget.showExchangeRate) {
|
|
widget.costController.addListener(_updateConvertedAmount);
|
|
_loadExchangeRate();
|
|
_updateConvertedAmount();
|
|
} else {
|
|
setState(() {
|
|
_exchangeRateInfo = '';
|
|
_convertedAmount = '';
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 환율 정보 로드
|
|
Future<void> _loadExchangeRate() async {
|
|
if (!widget.showExchangeRate) return;
|
|
|
|
final rateInfo = await _exchangeRateService.getFormattedExchangeRateInfo();
|
|
if (mounted) {
|
|
setState(() {
|
|
_exchangeRateInfo = rateInfo;
|
|
});
|
|
}
|
|
}
|
|
|
|
/// 달러 금액이 변경될 때 원화 금액 업데이트
|
|
Future<void> _updateConvertedAmount() async {
|
|
if (!widget.showExchangeRate) return;
|
|
|
|
try {
|
|
// 금액 입력값에서 콤마 제거 후 숫자로 변환
|
|
final text = widget.costController.text.replaceAll(',', '');
|
|
if (text.isEmpty) {
|
|
setState(() {
|
|
_convertedAmount = '';
|
|
});
|
|
return;
|
|
}
|
|
|
|
final amount = double.tryParse(text);
|
|
if (amount != null) {
|
|
final converted =
|
|
await _exchangeRateService.getFormattedKrwAmount(amount);
|
|
if (mounted) {
|
|
setState(() {
|
|
_convertedAmount = converted;
|
|
});
|
|
}
|
|
}
|
|
} catch (e) {
|
|
// 오류 발생 시 빈 문자열 표시
|
|
setState(() {
|
|
_convertedAmount = '';
|
|
});
|
|
}
|
|
}
|
|
|
|
/// 환율 정보 텍스트 위젯 생성
|
|
Widget buildExchangeRateInfo() {
|
|
if (_exchangeRateInfo.isEmpty) return const SizedBox.shrink();
|
|
|
|
return Text(
|
|
_exchangeRateInfo,
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: Colors.grey[600],
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
);
|
|
}
|
|
|
|
/// 환산 금액 텍스트 위젯 생성
|
|
Widget buildConvertedAmount() {
|
|
if (_convertedAmount.isEmpty) return const SizedBox.shrink();
|
|
|
|
return Text(
|
|
_convertedAmount,
|
|
style: const TextStyle(
|
|
fontSize: 14,
|
|
color: Colors.blue,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (!widget.showExchangeRate) {
|
|
return const SizedBox.shrink(); // 표시할 필요가 없으면 빈 위젯 반환
|
|
}
|
|
|
|
return const Column(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
// 이 위젯은 이제 환율 정보만 제공하고, 실제 UI는 스크린에서 구성
|
|
],
|
|
);
|
|
}
|
|
|
|
// 익스포즈드 메서드: 환율 정보 문자열 가져오기
|
|
String get exchangeRateInfo => _exchangeRateInfo;
|
|
|
|
// 익스포즈드 메서드: 변환된 금액 문자열 가져오기
|
|
String get convertedAmount => _convertedAmount;
|
|
}
|