prasule/lib/views/debts/setup_debt_scenario.dart
Matyáš Caras ef52caa836
feat: creating debt scenarios
also changed way of loading selected wallet
2024-07-19 17:34:45 +02:00

254 lines
11 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:prasule/api/debt_person.dart';
import 'package:prasule/api/debt_scenario.dart';
import 'package:prasule/api/wallet_manager.dart';
import 'package:prasule/pw/platformfield.dart';
import 'package:prasule/util/show_message.dart';
/// Used to create and/or edit [DebtScenario]s
class SetupDebtScenario extends StatefulWidget {
/// Used to create and/or edit [DebtScenario]s
const SetupDebtScenario({super.key, this.toEdit});
/// If not null, loads this [DebtScenario]'s data for editing
final DebtScenario? toEdit;
@override
State<SetupDebtScenario> createState() => _SetupDebtScenarioState();
}
class _SetupDebtScenarioState extends State<SetupDebtScenario> {
late DebtScenario _scenario;
final _nameController = TextEditingController();
final GlobalKey<FormState> _formKey = GlobalKey();
/// Stores data for each [ExpansionPanel]
final List<bool> _isOpen = [];
final List<TextEditingController> _panelControllers = [];
bool _isLoading = true;
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (!_isLoading) return;
_scenario = widget.toEdit ??
DebtScenario(
id: WalletManager.selectedWallet.nextDebtId,
name: AppLocalizations.of(context).debtNamePlaceholder,
isArchived: false,
people: [],
entries: [],
);
// Load stuff from the scenario
_nameController.text = _scenario.name;
_isOpen.addAll(List.filled(_scenario.people.length, false));
_panelControllers.addAll(
List.filled(_scenario.people.length * 2, TextEditingController()),
);
_isLoading = false;
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: SingleChildScrollView(
child: Center(
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.95,
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(8),
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.8,
child: PlatformField(
labelText: AppLocalizations.of(context).name,
controller: _nameController,
validator: (input) {
if (input == null || input.isEmpty) {
return AppLocalizations.of(context).errorEmptyName;
}
return null;
},
),
),
),
const SizedBox(
height: 15,
),
Text(AppLocalizations.of(context).people),
const SizedBox(
height: 10,
),
LimitedBox(
maxHeight: MediaQuery.of(context).size.height * 0.6,
child: Container(
width: MediaQuery.of(context).size.width * 0.8,
decoration: BoxDecoration(
border: Border.all(
color: Theme.of(context).colorScheme.secondary,
),
borderRadius: BorderRadius.circular(16),
),
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8),
child: (_scenario.people.isEmpty)
? Text(AppLocalizations.of(context).addSomePeople)
: ExpansionPanelList(
expansionCallback: (panelIndex, isExpanded) {
_isOpen[panelIndex] = isExpanded;
setState(() {});
},
children: List<ExpansionPanel>.generate(
_scenario.people.length,
(index) => ExpansionPanel(
isExpanded: _isOpen[index],
headerBuilder: (context, isOpen) => Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.all(4),
child: SizedBox(
width: MediaQuery.of(context)
.size
.width *
0.45,
child: PlatformField(
labelText:
AppLocalizations.of(context)
.name,
controller:
_panelControllers[index],
onChanged: (input) {
_scenario.people[index].name =
input;
setState(() {});
},
validator: (input) {
if (input == null ||
input.isEmpty) {
return AppLocalizations.of(
context,
).errorEmptyName;
}
return null;
},
),
),
),
IconButton(
onPressed: () {
_scenario.people.removeAt(index);
_panelControllers.removeRange(
index,
index + 2,
);
_isOpen.removeAt(index);
setState(() {});
},
icon: const Icon(
Icons.delete_forever,
),
),
],
),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(8),
child: SizedBox(
width: MediaQuery.of(context)
.size
.width *
0.8,
child: PlatformField(
labelText:
AppLocalizations.of(context)
.bankAccount,
controller: _panelControllers[
index + 1],
onChanged: (input) {
_scenario.people[index]
.bankAccount =
(input.isEmpty)
? null
: input;
setState(() {});
},
),
),
),
],
),
),
),
),
),
),
),
),
const SizedBox(
height: 10,
),
IconButton(
onPressed: () {
_scenario.people.add(
DebtPerson(id: _scenario.nextPersonId, name: ""),
);
_isOpen.add(false);
_panelControllers.addAll(
[TextEditingController(), TextEditingController()],
);
setState(() {});
},
icon: const Icon(Icons.add),
),
const SizedBox(
height: 15,
),
TextButton(
onPressed: () {
if (!_formKey.currentState!.validate()) {
return;
}
if (_scenario.people.isEmpty) {
showMessage(
AppLocalizations.of(context).noPersonError,
context,
);
return;
}
_scenario.name = _nameController.text;
if (widget.toEdit != null) {
// If editing, only replace
WalletManager.selectedWallet.debts[WalletManager
.selectedWallet.debts
.indexWhere((d) => d.id == widget.toEdit!.id)] =
_scenario;
} else {
// else add new
WalletManager.selectedWallet.debts.add(_scenario);
}
WalletManager.saveWallet(WalletManager.selectedWallet);
Navigator.of(context).pop();
},
child: Text(AppLocalizations.of(context).save),
),
],
),
),
),
),
),
);
}
}