feat: SMS 스캔 화면 리팩토링 및 MVC 패턴 적용

- SMS 스캔 화면을 컨트롤러/서비스/위젯으로 분리
- 코드 가독성 및 유지보수성 향상
- 새로운 다국어 지원 키 추가
- Git 커밋 가이드라인 문서화
This commit is contained in:
JiWoong Sul
2025-07-17 16:59:19 +09:00
parent 91bc91383b
commit 186d1bbf66
20 changed files with 1794 additions and 1408 deletions

View 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);
}
}