better UI
This commit is contained in:
@@ -85,14 +85,22 @@ Future<TransactionFilterSelection?> showTransactionFilterDialog(
|
||||
required TransactionFilterSelection initial,
|
||||
DateTime? currentMonth,
|
||||
}) {
|
||||
return showDialog<TransactionFilterSelection>(
|
||||
return showModalBottomSheet<TransactionFilterSelection>(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
useSafeArea: true,
|
||||
showDragHandle: true,
|
||||
builder: (dialogContext) {
|
||||
return _TransactionFilterDialog(
|
||||
available: available,
|
||||
transactions: transactions,
|
||||
initial: initial,
|
||||
currentMonth: currentMonth ?? monthStart(DateTime.now()),
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.viewInsetsOf(dialogContext).bottom,
|
||||
),
|
||||
child: _TransactionFilterDialog(
|
||||
available: available,
|
||||
transactions: transactions,
|
||||
initial: initial,
|
||||
currentMonth: currentMonth ?? monthStart(DateTime.now()),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -476,8 +484,6 @@ class _TransactionFilterDialogState extends State<_TransactionFilterDialog> {
|
||||
final colors = theme.colorScheme;
|
||||
final meta = context.watch<TxMetaController>();
|
||||
final size = MediaQuery.sizeOf(context);
|
||||
final dialogWidth =
|
||||
(size.width - 48).clamp(280.0, 560.0).toDouble();
|
||||
final needle = _labelSearchController.text.trim().toLowerCase();
|
||||
final entries = _filterLabelEntries(
|
||||
meta: meta,
|
||||
@@ -488,246 +494,285 @@ class _TransactionFilterDialogState extends State<_TransactionFilterDialog> {
|
||||
kUncategorizedFilterLabel.name.toLowerCase().contains(needle);
|
||||
final sectionStyle = _sectionStyle(theme, colors);
|
||||
|
||||
return AlertDialog(
|
||||
title: const Text('Filter transactions'),
|
||||
contentPadding: const EdgeInsets.fromLTRB(24, 8, 24, 0),
|
||||
content: SizedBox(
|
||||
width: dialogWidth,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Text(
|
||||
'Search, period, flow, amount, and labels.',
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: colors.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
Text('Search text', style: sectionStyle),
|
||||
const SizedBox(height: 8),
|
||||
TextField(
|
||||
controller: _queryController,
|
||||
textInputAction: TextInputAction.search,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Description, notes, amount…',
|
||||
prefixIcon: Icon(Icons.search),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
Text('Period', style: sectionStyle),
|
||||
const SizedBox(height: 8),
|
||||
_RectToggleBar<bool>(
|
||||
value: _monthOnly,
|
||||
onChanged: (value) => setState(() => _monthOnly = value),
|
||||
options: const [
|
||||
_RectToggleOption(
|
||||
value: false,
|
||||
label: 'All',
|
||||
),
|
||||
_RectToggleOption(
|
||||
value: true,
|
||||
label: 'Month',
|
||||
icon: Icons.calendar_month,
|
||||
),
|
||||
],
|
||||
),
|
||||
if (_monthOnly) ...[
|
||||
const SizedBox(height: 8),
|
||||
// Fixed sheet height so Expanded labels get a real viewport (not a tiny 220px box).
|
||||
final sheetHeight = (size.height * 0.92).clamp(420.0, size.height);
|
||||
|
||||
return SizedBox(
|
||||
height: sheetHeight,
|
||||
width: double.infinity,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 4, 24, 0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Uses ${formatMonthYear(widget.currentMonth)}. '
|
||||
'Change month on the transactions list.',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
'Filter transactions',
|
||||
style: theme.textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'Search, period, flow, amount, and labels.',
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: colors.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 14),
|
||||
Text('Income / expense', style: sectionStyle),
|
||||
const SizedBox(height: 8),
|
||||
_RectToggleBar<TxFlowFilter>(
|
||||
value: _flow,
|
||||
onChanged: (value) => setState(() => _flow = value),
|
||||
options: const [
|
||||
_RectToggleOption(
|
||||
value: TxFlowFilter.all,
|
||||
label: 'All',
|
||||
),
|
||||
_RectToggleOption(
|
||||
value: TxFlowFilter.income,
|
||||
label: 'In',
|
||||
icon: Icons.south_west,
|
||||
),
|
||||
_RectToggleOption(
|
||||
value: TxFlowFilter.expense,
|
||||
label: 'Out',
|
||||
icon: Icons.north_east,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
Text('Amount', style: sectionStyle),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Exact',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: colors.onSurfaceVariant,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
TextField(
|
||||
controller: _exactAmountController,
|
||||
keyboardType: const TextInputType.numberWithOptions(
|
||||
decimal: true,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
hintText: 'e.g. 12.50',
|
||||
prefixIcon: const Icon(Icons.pin, size: 20),
|
||||
suffixIcon: _exactAmountController.text.trim().isEmpty
|
||||
? null
|
||||
: IconButton(
|
||||
tooltip: 'Clear exact',
|
||||
onPressed: () {
|
||||
_exactAmountController.clear();
|
||||
setState(() {});
|
||||
},
|
||||
icon: const Icon(Icons.clear, size: 18),
|
||||
),
|
||||
),
|
||||
onChanged: (_) {
|
||||
setState(() {
|
||||
// Exact takes precedence; clear range filter intent.
|
||||
_rangeTouched = false;
|
||||
_amountRange = RangeValues(0, _amountCeil);
|
||||
});
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
'Range',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: colors.onSurfaceVariant,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
_rangeTouched
|
||||
? '${_amountRange.start.toStringAsFixed(0)} – ${_amountRange.end.toStringAsFixed(0)}'
|
||||
: 'Any amount',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: colors.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
RangeSlider(
|
||||
values: _amountRange,
|
||||
min: 0,
|
||||
max: _amountCeil,
|
||||
labels: RangeLabels(
|
||||
_amountRange.start.toStringAsFixed(0),
|
||||
_amountRange.end.toStringAsFixed(0),
|
||||
),
|
||||
onChanged: (values) {
|
||||
setState(() {
|
||||
_exactAmountController.clear();
|
||||
_rangeTouched = true;
|
||||
_amountRange = values;
|
||||
});
|
||||
},
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: TextButton(
|
||||
onPressed: !_rangeTouched
|
||||
? null
|
||||
: () {
|
||||
setState(() {
|
||||
_rangeTouched = false;
|
||||
_amountRange = RangeValues(0, _amountCeil);
|
||||
});
|
||||
},
|
||||
child: const Text('Reset range'),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text('Labels', style: sectionStyle),
|
||||
const SizedBox(height: 8),
|
||||
TextField(
|
||||
controller: _labelSearchController,
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
hintText: 'Filter labels',
|
||||
prefixIcon: const Icon(Icons.search, size: 20),
|
||||
suffixIcon: needle.isEmpty
|
||||
? null
|
||||
: IconButton(
|
||||
onPressed: () {
|
||||
_labelSearchController.clear();
|
||||
setState(() {});
|
||||
},
|
||||
icon: const Icon(Icons.clear, size: 18),
|
||||
),
|
||||
),
|
||||
onChanged: (_) => setState(() {}),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(
|
||||
height: 220,
|
||||
width: dialogWidth,
|
||||
child: _LabelChecklist(
|
||||
entries: entries,
|
||||
showUncategorized: showUncategorized,
|
||||
selected: _selected,
|
||||
onToggle: _toggle,
|
||||
allowMove: false,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Flexible(
|
||||
flex: 2,
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.fromLTRB(24, 4, 24, 8),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Text('Search text', style: sectionStyle),
|
||||
const SizedBox(height: 8),
|
||||
TextField(
|
||||
controller: _queryController,
|
||||
textInputAction: TextInputAction.search,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Description, notes, amount…',
|
||||
prefixIcon: Icon(Icons.search),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
Text('Period', style: sectionStyle),
|
||||
const SizedBox(height: 8),
|
||||
_RectToggleBar<bool>(
|
||||
value: _monthOnly,
|
||||
onChanged: (value) =>
|
||||
setState(() => _monthOnly = value),
|
||||
options: const [
|
||||
_RectToggleOption(
|
||||
value: false,
|
||||
label: 'All',
|
||||
),
|
||||
_RectToggleOption(
|
||||
value: true,
|
||||
label: 'Month',
|
||||
icon: Icons.calendar_month,
|
||||
),
|
||||
],
|
||||
),
|
||||
if (_monthOnly) ...[
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Uses ${formatMonthYear(widget.currentMonth)}. '
|
||||
'Change month on the transactions list.',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: colors.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 14),
|
||||
Text('Income / expense', style: sectionStyle),
|
||||
const SizedBox(height: 8),
|
||||
_RectToggleBar<TxFlowFilter>(
|
||||
value: _flow,
|
||||
onChanged: (value) => setState(() => _flow = value),
|
||||
options: const [
|
||||
_RectToggleOption(
|
||||
value: TxFlowFilter.all,
|
||||
label: 'All',
|
||||
),
|
||||
_RectToggleOption(
|
||||
value: TxFlowFilter.income,
|
||||
label: 'In',
|
||||
icon: Icons.south_west,
|
||||
),
|
||||
_RectToggleOption(
|
||||
value: TxFlowFilter.expense,
|
||||
label: 'Out',
|
||||
icon: Icons.north_east,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
Text('Amount', style: sectionStyle),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Exact',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: colors.onSurfaceVariant,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
TextField(
|
||||
controller: _exactAmountController,
|
||||
keyboardType: const TextInputType.numberWithOptions(
|
||||
decimal: true,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
hintText: 'e.g. 12.50',
|
||||
prefixIcon: const Icon(Icons.pin, size: 20),
|
||||
suffixIcon:
|
||||
_exactAmountController.text.trim().isEmpty
|
||||
? null
|
||||
: IconButton(
|
||||
tooltip: 'Clear exact',
|
||||
onPressed: () {
|
||||
_exactAmountController.clear();
|
||||
setState(() {});
|
||||
},
|
||||
icon: const Icon(Icons.clear, size: 18),
|
||||
),
|
||||
),
|
||||
onChanged: (_) {
|
||||
setState(() {
|
||||
_rangeTouched = false;
|
||||
_amountRange = RangeValues(0, _amountCeil);
|
||||
});
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
'Range',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: colors.onSurfaceVariant,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
_rangeTouched
|
||||
? '${_amountRange.start.toStringAsFixed(0)} – ${_amountRange.end.toStringAsFixed(0)}'
|
||||
: 'Any amount',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: colors.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
RangeSlider(
|
||||
values: _amountRange,
|
||||
min: 0,
|
||||
max: _amountCeil,
|
||||
labels: RangeLabels(
|
||||
_amountRange.start.toStringAsFixed(0),
|
||||
_amountRange.end.toStringAsFixed(0),
|
||||
),
|
||||
onChanged: (values) {
|
||||
setState(() {
|
||||
_exactAmountController.clear();
|
||||
_rangeTouched = true;
|
||||
_amountRange = values;
|
||||
});
|
||||
},
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: TextButton(
|
||||
onPressed: !_rangeTouched
|
||||
? null
|
||||
: () {
|
||||
setState(() {
|
||||
_rangeTouched = false;
|
||||
_amountRange =
|
||||
RangeValues(0, _amountCeil);
|
||||
});
|
||||
},
|
||||
child: const Text('Reset range'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 4, 24, 0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Text('Labels', style: sectionStyle),
|
||||
const SizedBox(height: 8),
|
||||
TextField(
|
||||
controller: _labelSearchController,
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
hintText: 'Filter labels',
|
||||
prefixIcon: const Icon(Icons.search, size: 20),
|
||||
suffixIcon: needle.isEmpty
|
||||
? null
|
||||
: IconButton(
|
||||
onPressed: () {
|
||||
_labelSearchController.clear();
|
||||
setState(() {});
|
||||
},
|
||||
icon: const Icon(Icons.clear, size: 18),
|
||||
),
|
||||
),
|
||||
onChanged: (_) => setState(() {}),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_selected
|
||||
..clear()
|
||||
..addAll(entries.map((e) => e.label.id));
|
||||
if (showUncategorized) {
|
||||
_selected.add(kUncategorizedFilterId);
|
||||
}
|
||||
});
|
||||
},
|
||||
child: const Text('All labels'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () =>
|
||||
setState(() => _selected.clear()),
|
||||
child: const Text('No labels'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 0, 24, 8),
|
||||
child: _LabelChecklist(
|
||||
entries: entries,
|
||||
showUncategorized: showUncategorized,
|
||||
selected: _selected,
|
||||
onToggle: _toggle,
|
||||
allowMove: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 4, 24, 20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
FilledButton(
|
||||
onPressed: _apply,
|
||||
child: const Text('Apply'),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
actionsAlignment: MainAxisAlignment.spaceBetween,
|
||||
actionsPadding: const EdgeInsets.fromLTRB(16, 8, 16, 16),
|
||||
actions: [
|
||||
Wrap(
|
||||
spacing: 4,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_selected
|
||||
..clear()
|
||||
..addAll(entries.map((e) => e.label.id));
|
||||
if (showUncategorized) {
|
||||
_selected.add(kUncategorizedFilterId);
|
||||
}
|
||||
});
|
||||
},
|
||||
child: const Text('All labels'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => setState(() => _selected.clear()),
|
||||
child: const Text('No labels'),
|
||||
),
|
||||
],
|
||||
),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: _apply,
|
||||
child: const Text('Apply'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -879,65 +924,80 @@ class _RectToggleBar<T> extends StatelessWidget {
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: colors.outlineVariant),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
for (var i = 0; i < options.length; i++) ...[
|
||||
if (i > 0)
|
||||
Container(
|
||||
width: 1,
|
||||
height: 36,
|
||||
color: colors.outlineVariant,
|
||||
),
|
||||
Expanded(
|
||||
child: Material(
|
||||
color: options[i].value == value
|
||||
? colors.secondaryContainer
|
||||
: colors.surface,
|
||||
child: InkWell(
|
||||
onTap: () => onChanged(options[i].value),
|
||||
child: SizedBox(
|
||||
height: 36,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (options[i].icon != null) ...[
|
||||
Icon(
|
||||
options[i].icon,
|
||||
size: 15,
|
||||
color: options[i].value == value
|
||||
? colors.onSecondaryContainer
|
||||
: colors.onSurfaceVariant,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
],
|
||||
Flexible(
|
||||
child: Text(
|
||||
options[i].label,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: theme.textTheme.labelLarge?.copyWith(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: colors.surfaceContainerHigh,
|
||||
border: Border.all(
|
||||
color: colors.outlineVariant.withValues(alpha: 0.7),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
for (var i = 0; i < options.length; i++) ...[
|
||||
if (i > 0)
|
||||
Container(
|
||||
width: 1,
|
||||
height: 36,
|
||||
color: colors.outlineVariant.withValues(alpha: 0.7),
|
||||
),
|
||||
Expanded(
|
||||
child: Material(
|
||||
color: options[i].value == value
|
||||
? colors.primary
|
||||
: Colors.transparent,
|
||||
borderRadius: BorderRadius.horizontal(
|
||||
left: i == 0 ? const Radius.circular(11) : Radius.zero,
|
||||
right: i == options.length - 1
|
||||
? const Radius.circular(11)
|
||||
: Radius.zero,
|
||||
),
|
||||
child: InkWell(
|
||||
onTap: () => onChanged(options[i].value),
|
||||
borderRadius: BorderRadius.horizontal(
|
||||
left: i == 0 ? const Radius.circular(11) : Radius.zero,
|
||||
right: i == options.length - 1
|
||||
? const Radius.circular(11)
|
||||
: Radius.zero,
|
||||
),
|
||||
child: SizedBox(
|
||||
height: 36,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (options[i].icon != null) ...[
|
||||
Icon(
|
||||
options[i].icon,
|
||||
size: 15,
|
||||
color: options[i].value == value
|
||||
? colors.onSecondaryContainer
|
||||
: colors.onSurface,
|
||||
fontWeight: options[i].value == value
|
||||
? FontWeight.w600
|
||||
: FontWeight.w500,
|
||||
? colors.onPrimary
|
||||
: colors.onSurfaceVariant,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
],
|
||||
Flexible(
|
||||
child: Text(
|
||||
options[i].label,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: theme.textTheme.labelLarge?.copyWith(
|
||||
color: options[i].value == value
|
||||
? colors.onPrimary
|
||||
: colors.onSurface,
|
||||
fontWeight: options[i].value == value
|
||||
? FontWeight.w700
|
||||
: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import '../models/bank.dart';
|
||||
import '../models/transaction_meta.dart';
|
||||
import '../utils/app_theme.dart';
|
||||
import '../utils/helpers.dart';
|
||||
|
||||
class _RegexExample {
|
||||
@@ -256,8 +257,8 @@ class _SimilarMatchDialogState extends State<_SimilarMatchDialog> {
|
||||
formatMoney(tx.amount, tx.currency),
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: tx.amount >= 0
|
||||
? colors.primary
|
||||
: colors.error,
|
||||
? AppTheme.accent
|
||||
: AppTheme.expense,
|
||||
fontWeight:
|
||||
isPrototype ? FontWeight.w700 : null,
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user