Add transfer tracking and secure admin access
This commit is contained in:
@@ -20,7 +20,9 @@ class _TransactionEditPageState extends State<TransactionEditPage> {
|
||||
late final TextEditingController _amount;
|
||||
late final TextEditingController _note;
|
||||
late final TextEditingController _payment;
|
||||
late final TextEditingController _counterparty;
|
||||
late String _type;
|
||||
late String _transferDirection;
|
||||
late int _ledgerId;
|
||||
late int _categoryId;
|
||||
late DateTime _occurredAt;
|
||||
@@ -37,7 +39,9 @@ class _TransactionEditPageState extends State<TransactionEditPage> {
|
||||
);
|
||||
_note = TextEditingController(text: transaction.note ?? '');
|
||||
_payment = TextEditingController(text: transaction.paymentMethod ?? '');
|
||||
_counterparty = TextEditingController(text: transaction.counterparty ?? '');
|
||||
_type = transaction.type;
|
||||
_transferDirection = transaction.transferDirection ?? 'out';
|
||||
_ledgerId = transaction.ledgerId;
|
||||
_categoryId = transaction.categoryId;
|
||||
_occurredAt = transaction.occurredAt;
|
||||
@@ -49,6 +53,7 @@ class _TransactionEditPageState extends State<TransactionEditPage> {
|
||||
_amount.dispose();
|
||||
_note.dispose();
|
||||
_payment.dispose();
|
||||
_counterparty.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -56,7 +61,12 @@ class _TransactionEditPageState extends State<TransactionEditPage> {
|
||||
setState(() => _loading = true);
|
||||
try {
|
||||
await CurrentLedgerStore.instance.ensureLoaded();
|
||||
final categories = await TxApi.categories(_type);
|
||||
final categoryType = _type == 'transfer'
|
||||
? _transferDirection == 'in'
|
||||
? 'income'
|
||||
: 'expense'
|
||||
: _type;
|
||||
final categories = await TxApi.categories(categoryType);
|
||||
if (!categories.any((category) => category.id == _categoryId) &&
|
||||
categories.isNotEmpty) {
|
||||
_categoryId = categories.first.id;
|
||||
@@ -75,6 +85,12 @@ class _TransactionEditPageState extends State<TransactionEditPage> {
|
||||
await _loadCategories();
|
||||
}
|
||||
|
||||
Future<void> _changeTransferDirection(String direction) async {
|
||||
if (direction == _transferDirection) return;
|
||||
setState(() => _transferDirection = direction);
|
||||
await _loadCategories();
|
||||
}
|
||||
|
||||
Future<void> _pickDateTime() async {
|
||||
final value = await showJzDateTimeSheet(
|
||||
context,
|
||||
@@ -143,6 +159,11 @@ class _TransactionEditPageState extends State<TransactionEditPage> {
|
||||
amount: amount,
|
||||
note: _note.text.trim(),
|
||||
paymentMethod: _payment.text.trim(),
|
||||
transferDirection: _type == 'transfer' ? _transferDirection : null,
|
||||
counterparty:
|
||||
_type == 'transfer' && _counterparty.text.trim().isNotEmpty
|
||||
? _counterparty.text.trim()
|
||||
: null,
|
||||
occurredAt: _occurredAt,
|
||||
);
|
||||
if (mounted) Navigator.pop(context, updated);
|
||||
@@ -178,10 +199,28 @@ class _TransactionEditPageState extends State<TransactionEditPage> {
|
||||
value: _type,
|
||||
options: const [
|
||||
JzOption(value: 'expense', label: '支出'),
|
||||
JzOption(value: 'transfer', label: '转账'),
|
||||
JzOption(value: 'income', label: '收入'),
|
||||
],
|
||||
onChanged: _changeType,
|
||||
),
|
||||
if (_type == 'transfer') ...[
|
||||
SizedBox(height: 12),
|
||||
JzSegmentedControl<String>(
|
||||
value: _transferDirection,
|
||||
options: const [
|
||||
JzOption(value: 'out', label: '转出'),
|
||||
JzOption(value: 'in', label: '转入'),
|
||||
],
|
||||
onChanged: _changeTransferDirection,
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
TextField(
|
||||
controller: _counterparty,
|
||||
maxLength: 40,
|
||||
decoration: InputDecoration(labelText: '转账对方'),
|
||||
),
|
||||
],
|
||||
SizedBox(height: 14),
|
||||
TextField(
|
||||
controller: _amount,
|
||||
|
||||
Reference in New Issue
Block a user