feat: SMS 스캔 화면 리팩토링 및 MVC 패턴 적용
- SMS 스캔 화면을 컨트롤러/서비스/위젯으로 분리 - 코드 가독성 및 유지보수성 향상 - 새로운 다국어 지원 키 추가 - Git 커밋 가이드라인 문서화
This commit is contained in:
53
lib/utils/sms_scan/category_icon_mapper.dart
Normal file
53
lib/utils/sms_scan/category_icon_mapper.dart
Normal file
@@ -0,0 +1,53 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../models/category_model.dart';
|
||||
|
||||
class CategoryIconMapper {
|
||||
// 카테고리 아이콘 반환
|
||||
static IconData getCategoryIcon(CategoryModel category) {
|
||||
switch (category.name) {
|
||||
case 'music':
|
||||
return Icons.music_note_rounded;
|
||||
case 'ottVideo':
|
||||
return Icons.movie_filter_rounded;
|
||||
case 'storageCloud':
|
||||
return Icons.cloud_outlined;
|
||||
case 'telecomInternetTv':
|
||||
return Icons.wifi_rounded;
|
||||
case 'lifestyle':
|
||||
return Icons.home_outlined;
|
||||
case 'shoppingEcommerce':
|
||||
return Icons.shopping_cart_outlined;
|
||||
case 'programming':
|
||||
return Icons.code_rounded;
|
||||
case 'collaborationOffice':
|
||||
return Icons.business_center_outlined;
|
||||
case 'aiService':
|
||||
return Icons.smart_toy_outlined;
|
||||
case 'other':
|
||||
default:
|
||||
return Icons.category_outlined;
|
||||
}
|
||||
}
|
||||
|
||||
// 카테고리별 배경색 반환
|
||||
static Color getCategoryColor(CategoryModel category) {
|
||||
final colorString = category.color;
|
||||
try {
|
||||
return Color(int.parse(colorString.replaceFirst('#', '0xFF')));
|
||||
} catch (e) {
|
||||
// 파싱 실패 시 기본 색상 반환
|
||||
return const Color(0xFF6B7280); // 기본 회색
|
||||
}
|
||||
}
|
||||
|
||||
// 카테고리별 아이콘 크기 반환
|
||||
static double getCategoryIconSize(CategoryModel category) {
|
||||
switch (category.name) {
|
||||
case 'music':
|
||||
case 'ottVideo':
|
||||
return 18.0;
|
||||
default:
|
||||
return 16.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
165
lib/utils/sms_scan/date_formatter.dart
Normal file
165
lib/utils/sms_scan/date_formatter.dart
Normal file
@@ -0,0 +1,165 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
|
||||
class SmsDateFormatter {
|
||||
// 날짜 상태 텍스트 가져오기
|
||||
static String getNextBillingText(
|
||||
BuildContext context,
|
||||
DateTime date,
|
||||
String billingCycle,
|
||||
) {
|
||||
final now = DateTime.now();
|
||||
|
||||
if (date.isBefore(now)) {
|
||||
return _getPastDateText(context, date, billingCycle, now);
|
||||
} else {
|
||||
return _getFutureDateText(context, date, now);
|
||||
}
|
||||
}
|
||||
|
||||
// 과거 날짜 처리
|
||||
static String _getPastDateText(
|
||||
BuildContext context,
|
||||
DateTime date,
|
||||
String billingCycle,
|
||||
DateTime now,
|
||||
) {
|
||||
// 주기에 따라 다음 결제일 예측
|
||||
DateTime? predictedDate = _predictNextBillingDate(date, billingCycle, now);
|
||||
|
||||
if (predictedDate != null) {
|
||||
final daysUntil = predictedDate.difference(now).inDays;
|
||||
return AppLocalizations.of(context).nextBillingDateEstimated(
|
||||
AppLocalizations.of(context).formatDate(predictedDate),
|
||||
daysUntil,
|
||||
);
|
||||
}
|
||||
|
||||
return '다음 결제일 확인 필요 (과거 날짜)';
|
||||
}
|
||||
|
||||
// 미래 날짜 처리
|
||||
static String _getFutureDateText(
|
||||
BuildContext context,
|
||||
DateTime date,
|
||||
DateTime now,
|
||||
) {
|
||||
final daysUntil = date.difference(now).inDays;
|
||||
return AppLocalizations.of(context).nextBillingDateInfo(
|
||||
AppLocalizations.of(context).formatDate(date),
|
||||
daysUntil,
|
||||
);
|
||||
}
|
||||
|
||||
// 다음 결제일 예측
|
||||
static DateTime? _predictNextBillingDate(
|
||||
DateTime lastDate,
|
||||
String billingCycle,
|
||||
DateTime now,
|
||||
) {
|
||||
switch (billingCycle) {
|
||||
case '월간':
|
||||
return _getNextMonthlyDate(lastDate, now);
|
||||
case '연간':
|
||||
return _getNextYearlyDate(lastDate, now);
|
||||
case '주간':
|
||||
return _getNextWeeklyDate(lastDate, now);
|
||||
case '일간':
|
||||
return _getNextDailyDate(lastDate, now);
|
||||
case '분기별':
|
||||
return _getNextQuarterlyDate(lastDate, now);
|
||||
case '반기별':
|
||||
return _getNextSemiAnnuallyDate(lastDate, now);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 다음 월간 결제일 계산
|
||||
static DateTime _getNextMonthlyDate(DateTime lastDate, DateTime now) {
|
||||
int day = lastDate.day;
|
||||
|
||||
// 현재 월의 마지막 날을 초과하는 경우 조정
|
||||
final lastDay = DateTime(now.year, now.month + 1, 0).day;
|
||||
if (day > lastDay) {
|
||||
day = lastDay;
|
||||
}
|
||||
|
||||
DateTime adjusted = DateTime(now.year, now.month, day);
|
||||
if (adjusted.isBefore(now)) {
|
||||
// 다음 달의 마지막 날을 초과하는 경우 조정
|
||||
final nextMonthLastDay = DateTime(now.year, now.month + 2, 0).day;
|
||||
if (day > nextMonthLastDay) {
|
||||
day = nextMonthLastDay;
|
||||
}
|
||||
adjusted = DateTime(now.year, now.month + 1, day);
|
||||
}
|
||||
|
||||
return adjusted;
|
||||
}
|
||||
|
||||
// 다음 연간 결제일 계산
|
||||
static DateTime _getNextYearlyDate(DateTime lastDate, DateTime now) {
|
||||
int day = lastDate.day;
|
||||
|
||||
// 해당 월의 마지막 날을 초과하는 경우 조정
|
||||
final lastDay = DateTime(now.year, lastDate.month + 1, 0).day;
|
||||
if (day > lastDay) {
|
||||
day = lastDay;
|
||||
}
|
||||
|
||||
DateTime adjusted = DateTime(now.year, lastDate.month, day);
|
||||
if (adjusted.isBefore(now)) {
|
||||
// 다음 해 해당 월의 마지막 날을 초과하는 경우 조정
|
||||
final nextYearLastDay = DateTime(now.year + 1, lastDate.month + 1, 0).day;
|
||||
if (day > nextYearLastDay) {
|
||||
day = nextYearLastDay;
|
||||
}
|
||||
adjusted = DateTime(now.year + 1, lastDate.month, day);
|
||||
}
|
||||
|
||||
return adjusted;
|
||||
}
|
||||
|
||||
// 다음 주간 결제일 계산
|
||||
static DateTime _getNextWeeklyDate(DateTime lastDate, DateTime now) {
|
||||
DateTime next = lastDate;
|
||||
while (next.isBefore(now)) {
|
||||
next = next.add(const Duration(days: 7));
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
// 다음 일간 결제일 계산
|
||||
static DateTime _getNextDailyDate(DateTime lastDate, DateTime now) {
|
||||
return now.add(const Duration(days: 1));
|
||||
}
|
||||
|
||||
// 다음 분기별 결제일 계산
|
||||
static DateTime _getNextQuarterlyDate(DateTime lastDate, DateTime now) {
|
||||
DateTime next = lastDate;
|
||||
while (next.isBefore(now)) {
|
||||
next = DateTime(next.year, next.month + 3, next.day);
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
// 다음 반기별 결제일 계산
|
||||
static DateTime _getNextSemiAnnuallyDate(DateTime lastDate, DateTime now) {
|
||||
DateTime next = lastDate;
|
||||
while (next.isBefore(now)) {
|
||||
next = DateTime(next.year, next.month + 6, next.day);
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
// 날짜 포맷 함수
|
||||
static String formatDate(DateTime date) {
|
||||
return '${date.year}년 ${date.month}월 ${date.day}일';
|
||||
}
|
||||
|
||||
// 결제 반복 횟수 텍스트
|
||||
static String getRepeatCountText(BuildContext context, int count) {
|
||||
return AppLocalizations.of(context).repeatCountDetected(count);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user