new favourites feature
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
/// Named Overview chart filter snapshots (local favourites).
|
||||
library;
|
||||
|
||||
import '../models/transaction_meta.dart';
|
||||
import '../widgets/label_filter_dialog.dart';
|
||||
|
||||
/// Persisted Overview lens: period, metric, and Labels-chart options.
|
||||
class OverviewFavourite {
|
||||
const OverviewFavourite({
|
||||
required this.id,
|
||||
required this.name,
|
||||
this.display = true,
|
||||
this.metric = OverviewMetricMode.flow,
|
||||
this.period = OverviewPeriodMode.monthly,
|
||||
this.labelIds = const [],
|
||||
this.flow = TxFlowFilter.expense,
|
||||
this.barStyle = LabelChartBarStyle.parallel,
|
||||
this.invertExpensePerspective = false,
|
||||
});
|
||||
|
||||
final String id;
|
||||
final String name;
|
||||
|
||||
/// When true, this favourite appears on the Favourites overview view.
|
||||
final bool display;
|
||||
|
||||
final OverviewMetricMode metric;
|
||||
final OverviewPeriodMode period;
|
||||
|
||||
/// Empty = all labels (Labels metric only).
|
||||
final List<String> labelIds;
|
||||
|
||||
final TxFlowFilter flow;
|
||||
final LabelChartBarStyle barStyle;
|
||||
final bool invertExpensePerspective;
|
||||
|
||||
OverviewFavourite copyWith({
|
||||
String? id,
|
||||
String? name,
|
||||
bool? display,
|
||||
OverviewMetricMode? metric,
|
||||
OverviewPeriodMode? period,
|
||||
List<String>? labelIds,
|
||||
TxFlowFilter? flow,
|
||||
LabelChartBarStyle? barStyle,
|
||||
bool? invertExpensePerspective,
|
||||
}) {
|
||||
return OverviewFavourite(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
display: display ?? this.display,
|
||||
metric: metric ?? this.metric,
|
||||
period: period ?? this.period,
|
||||
labelIds: labelIds ?? this.labelIds,
|
||||
flow: flow ?? this.flow,
|
||||
barStyle: barStyle ?? this.barStyle,
|
||||
invertExpensePerspective:
|
||||
invertExpensePerspective ?? this.invertExpensePerspective,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'display': display,
|
||||
'metric': metric.name,
|
||||
'period': period.name,
|
||||
'labelIds': labelIds,
|
||||
'flow': flow.name,
|
||||
'barStyle': barStyle.name,
|
||||
'invertExpensePerspective': invertExpensePerspective,
|
||||
};
|
||||
|
||||
factory OverviewFavourite.fromJson(Map<String, dynamic> json) {
|
||||
return OverviewFavourite(
|
||||
id: json['id'] as String? ?? 'fav_${DateTime.now().millisecondsSinceEpoch}',
|
||||
name: (json['name'] as String?)?.trim().isNotEmpty == true
|
||||
? (json['name'] as String).trim()
|
||||
: 'Favourite',
|
||||
display: json['display'] as bool? ?? true,
|
||||
metric: OverviewMetricMode.values.firstWhere(
|
||||
(e) => e.name == json['metric'],
|
||||
orElse: () => OverviewMetricMode.flow,
|
||||
),
|
||||
period: OverviewPeriodMode.values.firstWhere(
|
||||
(e) => e.name == json['period'],
|
||||
orElse: () => OverviewPeriodMode.monthly,
|
||||
),
|
||||
labelIds: [
|
||||
for (final id in (json['labelIds'] as List? ?? const []))
|
||||
if (id is String && id.isNotEmpty) id,
|
||||
],
|
||||
flow: TxFlowFilter.values.firstWhere(
|
||||
(e) => e.name == json['flow'],
|
||||
orElse: () => TxFlowFilter.expense,
|
||||
),
|
||||
barStyle: LabelChartBarStyle.values.firstWhere(
|
||||
(e) => e.name == json['barStyle'],
|
||||
orElse: () => LabelChartBarStyle.parallel,
|
||||
),
|
||||
invertExpensePerspective:
|
||||
json['invertExpensePerspective'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
enum OverviewMetricMode { flow, labels }
|
||||
|
||||
enum OverviewPeriodMode { monthly, yearly }
|
||||
Reference in New Issue
Block a user