feat: 폼 필드 컴포넌트 분리 및 구독 카드 인터랙션 개선
- billing_cycle_selector, category_selector, currency_selector 컴포넌트 분리 - 구독 카드 클릭 이슈 해결을 위한 리팩토링 - SMS 스캔 화면 UI/UX 개선 및 기능 강화 - 상세 화면 컨트롤러 로직 개선 - 알림 서비스 및 구독 URL 매칭 기능 추가 - CLAUDE.md 프로젝트 가이드라인 대폭 확장 - 전반적인 코드 구조 개선 및 타입 안정성 강화 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import 'package:hive/hive.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
import '../models/subscription_model.dart';
|
||||
import '../services/notification_service.dart';
|
||||
import 'category_provider.dart';
|
||||
|
||||
class SubscriptionProvider extends ChangeNotifier {
|
||||
late Box<SubscriptionModel> _subscriptionBox;
|
||||
@@ -46,6 +47,9 @@ class SubscriptionProvider extends ChangeNotifier {
|
||||
_subscriptionBox = await Hive.openBox<SubscriptionModel>('subscriptions');
|
||||
await refreshSubscriptions();
|
||||
|
||||
// categoryId 마이그레이션
|
||||
await _migrateCategoryIds();
|
||||
|
||||
// 앱 시작 시 이벤트 상태 확인
|
||||
await checkAndUpdateEventStatus();
|
||||
|
||||
@@ -290,4 +294,105 @@ class SubscriptionProvider extends ChangeNotifier {
|
||||
];
|
||||
return months[month.month - 1];
|
||||
}
|
||||
|
||||
/// categoryId가 없는 기존 구독들에 대해 자동으로 카테고리 할당
|
||||
Future<void> _migrateCategoryIds() async {
|
||||
debugPrint('❎ CategoryId 마이그레이션 시작...');
|
||||
|
||||
final categoryProvider = CategoryProvider();
|
||||
await categoryProvider.init();
|
||||
final categories = categoryProvider.categories;
|
||||
|
||||
int migratedCount = 0;
|
||||
|
||||
for (var subscription in _subscriptions) {
|
||||
if (subscription.categoryId == null) {
|
||||
final serviceName = subscription.serviceName.toLowerCase();
|
||||
String? categoryId;
|
||||
|
||||
debugPrint('🔍 ${subscription.serviceName} 카테고리 매칭 시도...');
|
||||
|
||||
// OTT 서비스
|
||||
if (serviceName.contains('netflix') ||
|
||||
serviceName.contains('youtube') ||
|
||||
serviceName.contains('disney') ||
|
||||
serviceName.contains('왓차') ||
|
||||
serviceName.contains('티빙') ||
|
||||
serviceName.contains('디즈니') ||
|
||||
serviceName.contains('넷플릭스')) {
|
||||
categoryId = categories.firstWhere(
|
||||
(cat) => cat.name == 'OTT 서비스',
|
||||
orElse: () => categories.first,
|
||||
).id;
|
||||
}
|
||||
// 음악 서비스
|
||||
else if (serviceName.contains('spotify') ||
|
||||
serviceName.contains('apple music') ||
|
||||
serviceName.contains('멜론') ||
|
||||
serviceName.contains('지니') ||
|
||||
serviceName.contains('플로') ||
|
||||
serviceName.contains('벡스')) {
|
||||
categoryId = categories.firstWhere(
|
||||
(cat) => cat.name == '음악 서비스',
|
||||
orElse: () => categories.first,
|
||||
).id;
|
||||
}
|
||||
// AI 서비스
|
||||
else if (serviceName.contains('chatgpt') ||
|
||||
serviceName.contains('claude') ||
|
||||
serviceName.contains('midjourney') ||
|
||||
serviceName.contains('copilot')) {
|
||||
categoryId = categories.firstWhere(
|
||||
(cat) => cat.name == 'AI 서비스',
|
||||
orElse: () => categories.first,
|
||||
).id;
|
||||
}
|
||||
// 프로그래밍/개발
|
||||
else if (serviceName.contains('github') ||
|
||||
serviceName.contains('intellij') ||
|
||||
serviceName.contains('webstorm') ||
|
||||
serviceName.contains('jetbrains')) {
|
||||
categoryId = categories.firstWhere(
|
||||
(cat) => cat.name == '프로그래밍/개발',
|
||||
orElse: () => categories.first,
|
||||
).id;
|
||||
}
|
||||
// 오피스/협업 툴
|
||||
else if (serviceName.contains('notion') ||
|
||||
serviceName.contains('microsoft') ||
|
||||
serviceName.contains('office') ||
|
||||
serviceName.contains('slack') ||
|
||||
serviceName.contains('figma') ||
|
||||
serviceName.contains('icloud') ||
|
||||
serviceName.contains('아이클라우드')) {
|
||||
categoryId = categories.firstWhere(
|
||||
(cat) => cat.name == '오피스/협업 툴',
|
||||
orElse: () => categories.first,
|
||||
).id;
|
||||
}
|
||||
// 기타 서비스 (기본값)
|
||||
else {
|
||||
categoryId = categories.firstWhere(
|
||||
(cat) => cat.name == '기타 서비스',
|
||||
orElse: () => categories.first,
|
||||
).id;
|
||||
}
|
||||
|
||||
if (categoryId != null) {
|
||||
subscription.categoryId = categoryId;
|
||||
await subscription.save();
|
||||
migratedCount++;
|
||||
final categoryName = categories.firstWhere((cat) => cat.id == categoryId).name;
|
||||
debugPrint('✅ ${subscription.serviceName} → $categoryName');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (migratedCount > 0) {
|
||||
debugPrint('❎ 총 ${migratedCount}개의 구독에 categoryId 할당 완료');
|
||||
await refreshSubscriptions();
|
||||
} else {
|
||||
debugPrint('❎ 모든 구독이 이미 categoryId를 가지고 있습니다');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user