feat: add payment card grouping and analysis

This commit is contained in:
JiWoong Sul
2025-11-14 16:53:41 +09:00
parent cba7d082bd
commit 132ae758de
40 changed files with 2846 additions and 522 deletions

View File

@@ -0,0 +1,124 @@
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:uuid/uuid.dart';
import '../models/payment_card_model.dart';
class PaymentCardProvider extends ChangeNotifier {
late Box<PaymentCardModel> _cardBox;
final List<PaymentCardModel> _cards = [];
List<PaymentCardModel> get cards => List.unmodifiable(_cards);
PaymentCardModel? get defaultCard {
try {
return _cards.firstWhere((card) => card.isDefault);
} catch (_) {
return _cards.isNotEmpty ? _cards.first : null;
}
}
Future<void> init() async {
_cardBox = await Hive.openBox<PaymentCardModel>('payment_cards');
_cards
..clear()
..addAll(_cardBox.values);
_sortCards();
notifyListeners();
}
Future<PaymentCardModel> addCard({
required String issuerName,
required String last4,
required String colorHex,
required String iconName,
bool isDefault = false,
}) async {
if (isDefault) {
await _unsetDefaultCard();
}
final card = PaymentCardModel(
id: const Uuid().v4(),
issuerName: issuerName,
last4: last4,
colorHex: colorHex,
iconName: iconName,
isDefault: isDefault,
);
await _cardBox.put(card.id, card);
_cards.add(card);
_sortCards();
notifyListeners();
return card;
}
Future<void> updateCard(PaymentCardModel updated) async {
final index = _cards.indexWhere((card) => card.id == updated.id);
if (index == -1) return;
if (updated.isDefault) {
await _unsetDefaultCard(exceptId: updated.id);
}
_cards[index] = updated;
await _cardBox.put(updated.id, updated);
_sortCards();
notifyListeners();
}
Future<void> deleteCard(String id) async {
await _cardBox.delete(id);
_cards.removeWhere((card) => card.id == id);
if (!_cards.any((card) => card.isDefault) && _cards.isNotEmpty) {
_cards.first.isDefault = true;
await _cardBox.put(_cards.first.id, _cards.first);
}
_sortCards();
notifyListeners();
}
Future<void> setDefaultCard(String id) async {
final index = _cards.indexWhere((card) => card.id == id);
if (index == -1) return;
await _unsetDefaultCard(exceptId: id);
_cards[index].isDefault = true;
await _cardBox.put(id, _cards[index]);
_sortCards();
notifyListeners();
}
PaymentCardModel? getCardById(String? id) {
if (id == null) return null;
try {
return _cards.firstWhere((card) => card.id == id);
} catch (_) {
return null;
}
}
void _sortCards() {
_cards.sort((a, b) {
if (a.isDefault != b.isDefault) {
return a.isDefault ? -1 : 1;
}
final issuerCompare =
a.issuerName.toLowerCase().compareTo(b.issuerName.toLowerCase());
if (issuerCompare != 0) return issuerCompare;
return a.last4.compareTo(b.last4);
});
}
Future<void> _unsetDefaultCard({String? exceptId}) async {
for (final card in _cards) {
if (card.isDefault && card.id != exceptId) {
card.isDefault = false;
await _cardBox.put(card.id, card);
}
}
}
}