fix tx listing
This commit is contained in:
@@ -42,6 +42,9 @@ class _OverviewScreenState extends State<OverviewScreen> {
|
||||
/// Empty = include every label. Non-empty = only these ids on the Labels chart.
|
||||
final Set<String> _includedLabelIds = {};
|
||||
|
||||
/// Labels chart flow filter (defaults to expenses / labeled spend).
|
||||
var _labelFlow = TxFlowFilter.expense;
|
||||
|
||||
/// Selected calendar year for Monthly mode (`DateTime(year)`).
|
||||
late DateTime _cursor;
|
||||
|
||||
@@ -100,13 +103,12 @@ class _OverviewScreenState extends State<OverviewScreen> {
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _pickChartLabels(
|
||||
BuildContext context,
|
||||
List<TxLabel> available,
|
||||
) async {
|
||||
Future<void> _pickChartLabels(BuildContext context) async {
|
||||
final meta = context.read<TxMetaController>();
|
||||
final available = meta.allLabels;
|
||||
if (available.isEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('No labels in use for this period yet')),
|
||||
const SnackBar(content: Text('No labels yet — create some first')),
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -125,18 +127,22 @@ class _OverviewScreenState extends State<OverviewScreen> {
|
||||
subtitle:
|
||||
'Choose which labels appear. Long-press to nest under another.',
|
||||
allowMove: true,
|
||||
includeFlow: true,
|
||||
initialFlow: _labelFlow,
|
||||
);
|
||||
if (result == null || !mounted) return;
|
||||
|
||||
setState(() {
|
||||
_labelFlow = result.flow;
|
||||
final allIds = available.map((l) => l.id).toSet();
|
||||
if (result.isEmpty ||
|
||||
(result.length == allIds.length && result.containsAll(allIds))) {
|
||||
if (result.labelIds.isEmpty ||
|
||||
(result.labelIds.length == allIds.length &&
|
||||
result.labelIds.containsAll(allIds))) {
|
||||
_includedLabelIds.clear();
|
||||
} else {
|
||||
_includedLabelIds
|
||||
..clear()
|
||||
..addAll(result);
|
||||
..addAll(result.labelIds);
|
||||
}
|
||||
_metric = _MetricMode.labels;
|
||||
});
|
||||
@@ -203,7 +209,6 @@ class _OverviewScreenState extends State<OverviewScreen> {
|
||||
// all txs 3–4 times and resolving full meta each time.
|
||||
Map<DateTime, _MonthBucket> monthly = const {};
|
||||
var labelSpend = const <_LabelSpend>[];
|
||||
var availableLabels = const <TxLabel>[];
|
||||
Map<DateTime, Map<String, double>> labelAmountByPeriod = const {};
|
||||
|
||||
if (_metric == _MetricMode.flow) {
|
||||
@@ -215,9 +220,9 @@ class _OverviewScreenState extends State<OverviewScreen> {
|
||||
periods,
|
||||
_period,
|
||||
includedLabelIds: _includedLabelIds,
|
||||
flow: _labelFlow,
|
||||
);
|
||||
labelSpend = labels.spend;
|
||||
availableLabels = [for (final row in labels.allSpend) row.label];
|
||||
labelAmountByPeriod = labels.amountByPeriod;
|
||||
}
|
||||
|
||||
@@ -253,11 +258,14 @@ class _OverviewScreenState extends State<OverviewScreen> {
|
||||
labelSpend: labelSpend,
|
||||
labelAmountByMonth: labelAmountByPeriod,
|
||||
currency: currency,
|
||||
includedLabelCount: _includedLabelIds.isEmpty
|
||||
includedLabelCount: _includedLabelIds.isEmpty &&
|
||||
_labelFlow == TxFlowFilter.expense
|
||||
? null
|
||||
: _includedLabelIds.length,
|
||||
availableLabelCount: availableLabels.length,
|
||||
onPickLabels: () => _pickChartLabels(context, availableLabels),
|
||||
: (_includedLabelIds.isEmpty
|
||||
? meta.allLabels.length
|
||||
: _includedLabelIds.length),
|
||||
availableLabelCount: meta.allLabels.length,
|
||||
onPickLabels: () => _pickChartLabels(context),
|
||||
onLabelTap: (label) {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute<void>(
|
||||
@@ -309,7 +317,11 @@ class _OverviewScreenState extends State<OverviewScreen> {
|
||||
labelSpend.fold<double>(0, (s, e) => s + e.amount),
|
||||
currency,
|
||||
),
|
||||
label: 'Labeled spend · $_periodTitle',
|
||||
label: switch (_labelFlow) {
|
||||
TxFlowFilter.income => 'Labeled income · $_periodTitle',
|
||||
TxFlowFilter.expense => 'Labeled spend · $_periodTitle',
|
||||
TxFlowFilter.all => 'Labeled activity · $_periodTitle',
|
||||
},
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 20),
|
||||
@@ -518,13 +530,14 @@ class _LabelAggregates {
|
||||
int get availableCount => allSpend.length;
|
||||
}
|
||||
|
||||
/// One pass over outflows: totals, per-period series, and history amounts.
|
||||
/// One pass over labeled amounts: totals, per-period series, and history.
|
||||
_LabelAggregates _labelAggregates(
|
||||
List<BankTransaction> txs,
|
||||
TxMetaController meta,
|
||||
List<DateTime> periods,
|
||||
_PeriodMode mode, {
|
||||
Set<String> includedLabelIds = const {},
|
||||
TxFlowFilter flow = TxFlowFilter.expense,
|
||||
}) {
|
||||
final keys = {for (final p in periods) _periodKey(p, mode)};
|
||||
final allByLabel = <String, double>{};
|
||||
@@ -537,7 +550,7 @@ _LabelAggregates _labelAggregates(
|
||||
final filtering = includedLabelIds.isNotEmpty;
|
||||
|
||||
for (final tx in txs) {
|
||||
if (tx.amount >= 0) continue;
|
||||
if (!txMatchesFlow(tx, flow)) continue;
|
||||
final date = _txDate(tx);
|
||||
if (date == null) continue;
|
||||
final key = _periodKey(date, mode);
|
||||
|
||||
Reference in New Issue
Block a user