254 lines
11 KiB
Dart
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),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|