import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:get_it/get_it.dart'; import 'package:okane/database/collections/account.dart'; import 'package:okane/database/collections/beneficiary.dart'; import 'package:okane/database/collections/expense_category.dart'; import 'package:okane/database/collections/template.dart'; import 'package:okane/database/database.dart'; import 'package:okane/ui/state/core.dart'; import 'package:okane/ui/transaction.dart'; import 'package:okane/ui/utils.dart'; import 'package:okane/ui/widgets/add_expense_category.dart'; import 'package:searchfield/searchfield.dart'; class AddTransactionTemplateWidget extends StatefulWidget { final VoidCallback onAdd; final Account activeAccountItem; const AddTransactionTemplateWidget({ super.key, required this.activeAccountItem, required this.onAdd, }); @override State createState() => _AddTransactionTemplateWidgetState(); } class _AddTransactionTemplateWidgetState extends State { final TextEditingController _beneficiaryTextController = TextEditingController(); final TextEditingController _amountTextController = TextEditingController(); final TextEditingController _templateNameController = TextEditingController(); SearchFieldListItem? _selectedBeneficiary; TransactionDirection _selectedDirection = TransactionDirection.send; ExpenseCategory? _expenseCategory = null; String getBeneficiaryName(Beneficiary item) { return switch (item.type) { BeneficiaryType.account => "${item.name} (Account)", BeneficiaryType.other => item.name, }; } Future _submit(BuildContext context) async { final beneficiaryName = _beneficiaryTextController.text; if (_selectedBeneficiary == null && beneficiaryName.isEmpty) { return; } if (_templateNameController.text.isEmpty) { return; } Beneficiary? beneficiary = _selectedBeneficiary?.item; if (beneficiary == null || getBeneficiaryName(beneficiary) != beneficiaryName) { // Add a new beneficiary, if none was selected final result = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text("Add Beneficiary"), content: Text( "The beneficiary '$beneficiaryName' does not exist. Do you want to add it?", ), actions: [ TextButton( style: TextButton.styleFrom( textStyle: Theme.of(context).textTheme.labelLarge, ), child: const Text('Add'), onPressed: () => Navigator.of(context).pop(true), ), TextButton( style: TextButton.styleFrom( textStyle: Theme.of(context).textTheme.labelLarge, ), child: const Text('Cancel'), onPressed: () => Navigator.of(context).pop(false), ), ], ), ); if (result == null || !result) { return; } beneficiary = Beneficiary() ..name = beneficiaryName ..type = BeneficiaryType.other; await upsertBeneficiary(beneficiary); } final factor = switch (_selectedDirection) { TransactionDirection.send => -1, TransactionDirection.receive => 1, }; final amount = factor * double.parse(_amountTextController.text).abs(); final transaction = TransactionTemplate() ..name = _templateNameController.text ..account.value = widget.activeAccountItem ..beneficiary.value = beneficiary ..expenseCategory.value = _expenseCategory ..recurring = false ..amount = amount; await upsertTransactionTemplate(transaction); widget.onAdd(); } @override Widget build(BuildContext context) { return Padding( padding: EdgeInsets.symmetric(horizontal: 16), child: ListView( shrinkWrap: true, children: [ Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: TextField( controller: _templateNameController, decoration: InputDecoration(label: Text("Template name")), ), ), Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: BlocBuilder( builder: (context, state) => SearchField( suggestions: state.beneficiaries .where((el) { final bloc = GetIt.I.get(); if (el.type == BeneficiaryType.account) { return el.account.value?.id != bloc.activeAccount?.id; } return true; }) .map((el) { return SearchFieldListItem( getBeneficiaryName(el), item: el, ); }) .toList(), hint: "Beneficiary", controller: _beneficiaryTextController, selectedValue: _selectedBeneficiary, onSuggestionTap: (beneficiary) { setState(() => _selectedBeneficiary = beneficiary); }, ), ), ), Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: TextField( controller: _amountTextController, keyboardType: TextInputType.numberWithOptions( signed: false, decimal: false, ), decoration: InputDecoration(hintText: "Amount"), ), ), Row( children: [ Text("Expense category"), OutlinedButton( onPressed: () async { final category = await showDialogOrModal( context: context, builder: (_) => AddExpenseCategory(), ); if (category == null) { return; } setState(() => _expenseCategory = category); }, child: Text(_expenseCategory?.name ?? "None"), ), ], ), Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: SegmentedButton( segments: [ ButtonSegment( value: TransactionDirection.send, label: Text("Send"), icon: Icon(Icons.remove), ), ButtonSegment( value: TransactionDirection.receive, label: Text("Receive"), icon: Icon(Icons.add), ), ], selected: {_selectedDirection}, multiSelectionEnabled: false, onSelectionChanged: (selection) { setState(() => _selectedDirection = selection.first); }, ), ), Align( alignment: Alignment.centerRight, child: OutlinedButton( onPressed: () => _submit(context), child: Text("Add"), ), ), ], ), ); } }