ok for now
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
/// Local transaction categories and per-transaction annotations.
|
||||
library;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// User-facing spend / income categories (stored locally, not on the bank API).
|
||||
enum TxCategory {
|
||||
uncategorized,
|
||||
groceries,
|
||||
energy,
|
||||
salary,
|
||||
mortgage,
|
||||
transport,
|
||||
dining,
|
||||
shopping,
|
||||
health,
|
||||
transfer,
|
||||
other,
|
||||
}
|
||||
|
||||
extension TxCategoryX on TxCategory {
|
||||
String get label => switch (this) {
|
||||
TxCategory.uncategorized => 'Uncategorized',
|
||||
TxCategory.groceries => 'Groceries',
|
||||
TxCategory.energy => 'Energy',
|
||||
TxCategory.salary => 'Salary',
|
||||
TxCategory.mortgage => 'Mortgage',
|
||||
TxCategory.transport => 'Transport',
|
||||
TxCategory.dining => 'Dining',
|
||||
TxCategory.shopping => 'Shopping',
|
||||
TxCategory.health => 'Health',
|
||||
TxCategory.transfer => 'Transfer',
|
||||
TxCategory.other => 'Other',
|
||||
};
|
||||
|
||||
IconData get icon => switch (this) {
|
||||
TxCategory.uncategorized => Icons.label_outline,
|
||||
TxCategory.groceries => Icons.shopping_cart_outlined,
|
||||
TxCategory.energy => Icons.bolt_outlined,
|
||||
TxCategory.salary => Icons.payments_outlined,
|
||||
TxCategory.mortgage => Icons.home_work_outlined,
|
||||
TxCategory.transport => Icons.directions_bus_outlined,
|
||||
TxCategory.dining => Icons.restaurant_outlined,
|
||||
TxCategory.shopping => Icons.shopping_bag_outlined,
|
||||
TxCategory.health => Icons.local_hospital_outlined,
|
||||
TxCategory.transfer => Icons.swap_horiz,
|
||||
TxCategory.other => Icons.more_horiz,
|
||||
};
|
||||
|
||||
Color get color => switch (this) {
|
||||
TxCategory.uncategorized => const Color(0xFF64748B),
|
||||
TxCategory.groceries => const Color(0xFF16A34A),
|
||||
TxCategory.energy => const Color(0xFFEAB308),
|
||||
TxCategory.salary => const Color(0xFF0F766E),
|
||||
TxCategory.mortgage => const Color(0xFF7C3AED),
|
||||
TxCategory.transport => const Color(0xFF2563EB),
|
||||
TxCategory.dining => const Color(0xFFEA580C),
|
||||
TxCategory.shopping => const Color(0xFFDB2777),
|
||||
TxCategory.health => const Color(0xFFDC2626),
|
||||
TxCategory.transfer => const Color(0xFF0891B2),
|
||||
TxCategory.other => const Color(0xFF57534E),
|
||||
};
|
||||
|
||||
static TxCategory fromName(String? name) {
|
||||
if (name == null || name.isEmpty) return TxCategory.uncategorized;
|
||||
return TxCategory.values.firstWhere(
|
||||
(c) => c.name == name,
|
||||
orElse: () => TxCategory.uncategorized,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Local overlay for a bank transaction.
|
||||
class TxMeta {
|
||||
const TxMeta({
|
||||
this.category = TxCategory.uncategorized,
|
||||
this.recurring = false,
|
||||
this.notes = '',
|
||||
});
|
||||
|
||||
final TxCategory category;
|
||||
final bool recurring;
|
||||
final String notes;
|
||||
|
||||
static const empty = TxMeta();
|
||||
|
||||
bool get hasCategory => category != TxCategory.uncategorized;
|
||||
bool get hasNotes => notes.trim().isNotEmpty;
|
||||
|
||||
TxMeta copyWith({
|
||||
TxCategory? category,
|
||||
bool? recurring,
|
||||
String? notes,
|
||||
}) {
|
||||
return TxMeta(
|
||||
category: category ?? this.category,
|
||||
recurring: recurring ?? this.recurring,
|
||||
notes: notes ?? this.notes,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'category': category.name,
|
||||
'recurring': recurring,
|
||||
'notes': notes,
|
||||
};
|
||||
|
||||
factory TxMeta.fromJson(Map<String, dynamic> json) {
|
||||
return TxMeta(
|
||||
category: TxCategoryX.fromName(json['category'] as String?),
|
||||
recurring: json['recurring'] as bool? ?? false,
|
||||
notes: json['notes'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Notes / recurring template keyed by exact merchant+amount match.
|
||||
class TxExactTemplate {
|
||||
const TxExactTemplate({this.notes = '', this.recurring = false});
|
||||
|
||||
final String notes;
|
||||
final bool recurring;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'notes': notes,
|
||||
'recurring': recurring,
|
||||
};
|
||||
|
||||
factory TxExactTemplate.fromJson(Map<String, dynamic> json) {
|
||||
return TxExactTemplate(
|
||||
notes: json['notes'] as String? ?? '',
|
||||
recurring: json['recurring'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user