Files
submanager/lib/providers/category_provider.dart
JiWoong Sul 111c519883 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>
2025-07-14 15:47:46 +09:00

120 lines
3.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import '../models/category_model.dart';
import 'package:uuid/uuid.dart';
class CategoryProvider extends ChangeNotifier {
List<CategoryModel> _categories = [];
late Box<CategoryModel> _categoryBox;
// 카테고리 표시 순서 정의
static const List<String> _categoryOrder = [
'음악',
'OTT(동영상)',
'저장/클라우드',
'통신 · 인터넷 · TV',
'생활/라이프스타일',
'쇼핑/이커머스',
'프로그래밍',
'협업/오피스',
'AI 서비스',
'기타',
];
List<CategoryModel> get categories {
// 정의된 순서로 카테고리 정렬
final sortedCategories = List<CategoryModel>.from(_categories);
sortedCategories.sort((a, b) {
final aIndex = _categoryOrder.indexOf(a.name);
final bIndex = _categoryOrder.indexOf(b.name);
// 순서 목록에 없는 카테고리는 맨 뒤로
if (aIndex == -1) return 1;
if (bIndex == -1) return -1;
return aIndex.compareTo(bIndex);
});
return sortedCategories;
}
Future<void> init() async {
_categoryBox = await Hive.openBox<CategoryModel>('categories');
_categories = _categoryBox.values.toList();
// 카테고리가 비어있으면 기본 카테고리 추가
if (_categories.isEmpty) {
await _initDefaultCategories();
}
notifyListeners();
}
// 기본 카테고리 초기화
Future<void> _initDefaultCategories() async {
final defaultCategories = [
{'name': '음악', 'color': '#E91E63', 'icon': 'music_note'},
{'name': 'OTT(동영상)', 'color': '#9C27B0', 'icon': 'movie_filter'},
{'name': '저장/클라우드', 'color': '#2196F3', 'icon': 'cloud'},
{'name': '통신 · 인터넷 · TV', 'color': '#00BCD4', 'icon': 'wifi'},
{'name': '생활/라이프스타일', 'color': '#4CAF50', 'icon': 'home'},
{'name': '쇼핑/이커머스', 'color': '#FF9800', 'icon': 'shopping_cart'},
{'name': '프로그래밍', 'color': '#795548', 'icon': 'code'},
{'name': '협업/오피스', 'color': '#607D8B', 'icon': 'business_center'},
{'name': 'AI 서비스', 'color': '#673AB7', 'icon': 'smart_toy'},
{'name': '기타', 'color': '#9E9E9E', 'icon': 'category'},
];
for (final category in defaultCategories) {
final newCategory = CategoryModel(
id: const Uuid().v4(),
name: category['name']!,
color: category['color']!,
icon: category['icon']!,
);
await _categoryBox.put(newCategory.id, newCategory);
_categories.add(newCategory);
}
}
Future<void> addCategory({
required String name,
required String color,
required String icon,
}) async {
final newCategory = CategoryModel(
id: const Uuid().v4(),
name: name,
color: color,
icon: icon,
);
await _categoryBox.put(newCategory.id, newCategory);
_categories.add(newCategory);
notifyListeners();
}
Future<void> updateCategory(CategoryModel updated) async {
await _categoryBox.put(updated.id, updated);
int index = _categories.indexWhere((cat) => cat.id == updated.id);
if (index != -1) {
_categories[index] = updated;
notifyListeners();
}
}
Future<void> deleteCategory(String id) async {
await _categoryBox.delete(id);
_categories.removeWhere((cat) => cat.id == id);
notifyListeners();
}
CategoryModel? getCategoryById(String id) {
try {
return _categories.firstWhere((cat) => cat.id == id);
} catch (_) {
return null;
}
}
}