Feat: Fügt die Liste für wiederkehrende Transaktionen hinzu
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
import 'package:dropdown_search/dropdown_search.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../Entities/dialog_type_enum.dart';
|
||||
import '../../Services/navigation_service.dart';
|
||||
import '../../Services/theme_service.dart';
|
||||
import '../Misc/dynamic_date_time_field.dart';
|
||||
import 'dialog_action.dart';
|
||||
import 'dialog_input_field.dart';
|
||||
import 'dialog_input_field_select_item.dart';
|
||||
import 'dialog_input_field_type_enum.dart';
|
||||
import 'dialog_type_enum.dart';
|
||||
|
||||
/// Erstellt einen neuen dynamischen Dialog
|
||||
class DynamicDialog {
|
||||
@@ -19,9 +23,10 @@ class DynamicDialog {
|
||||
this.borderRadius = 16,
|
||||
this.barrierDismissible = true,
|
||||
this.dialogType = DialogTypeEnum.info,
|
||||
this.hiddenValues
|
||||
this.hiddenValues,
|
||||
}) : inputFields = inputFields ?? const [],
|
||||
actions = actions ?? [DialogAction(label: 'Schließen')];
|
||||
actions = actions ?? [DialogAction(label: 'Schließen')],
|
||||
_values = hiddenValues ?? {};
|
||||
|
||||
/// Der Titel des Dialogs
|
||||
final String? title;
|
||||
@@ -53,36 +58,10 @@ class DynamicDialog {
|
||||
/// Versteckte Werte, die beim Abschicken mit zurückgegeben werden
|
||||
final Map<String, dynamic>? hiddenValues;
|
||||
|
||||
Map<String, TextEditingController>? _controllers;
|
||||
Map<String, FocusNode>? _focusNodes;
|
||||
final Map<String, dynamic> _values;
|
||||
|
||||
BuildContext? _dialogContext;
|
||||
|
||||
void _prepareControllers() {
|
||||
_controllers = {
|
||||
for (final field in inputFields)
|
||||
field.id: TextEditingController(text: field.initialValue ?? ''),
|
||||
};
|
||||
}
|
||||
|
||||
void _prepareFocusNodes() {
|
||||
_focusNodes = {for (final field in inputFields) field.id: FocusNode()};
|
||||
}
|
||||
|
||||
void _disposeControllers() {
|
||||
for (final TextEditingController controller in _controllers!.values) {
|
||||
controller.dispose();
|
||||
}
|
||||
_controllers = null;
|
||||
}
|
||||
|
||||
void _disposeFocusNodes() {
|
||||
for (final FocusNode node in _focusNodes!.values) {
|
||||
node.dispose();
|
||||
}
|
||||
_focusNodes = null;
|
||||
}
|
||||
|
||||
/// Zeigt den vorher zusammengebauten Dialog an
|
||||
Future<void> show() async {
|
||||
final BuildContext? context = NavigationService.getCurrentBuildContext();
|
||||
@@ -90,30 +69,13 @@ class DynamicDialog {
|
||||
if (context != null) {
|
||||
final ThemeData theme = Theme.of(context);
|
||||
|
||||
_prepareControllers();
|
||||
_prepareFocusNodes();
|
||||
|
||||
await showDialog(
|
||||
context: context,
|
||||
barrierDismissible: barrierDismissible,
|
||||
builder: (final BuildContext ctx) {
|
||||
_dialogContext = ctx;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final DialogInputField? autoFocusField = inputFields
|
||||
.where((final DialogInputField f) => f.autoFocus)
|
||||
.cast<DialogInputField?>()
|
||||
.firstWhere(
|
||||
(final DialogInputField? f) => f != null,
|
||||
orElse: () => null,
|
||||
);
|
||||
|
||||
if (autoFocusField != null) {
|
||||
_focusNodes![autoFocusField.id]!.requestFocus();
|
||||
}
|
||||
});
|
||||
|
||||
final DialogAction primaryAction = actions.firstWhere(
|
||||
(final a) => a.isPrimary,
|
||||
(final a) => a.isPrimary,
|
||||
orElse: () => actions.first,
|
||||
);
|
||||
|
||||
@@ -154,58 +116,23 @@ class DynamicDialog {
|
||||
children: [
|
||||
if (content != null) content!,
|
||||
...inputFields.map(
|
||||
(final DialogInputField field) =>
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6),
|
||||
child: TextField(
|
||||
controller: _controllers![field.id],
|
||||
focusNode: _focusNodes![field.id],
|
||||
keyboardType: field.keyboardType,
|
||||
obscureText: field.obscureText,
|
||||
onChanged: field.onChanged,
|
||||
decoration: InputDecoration(
|
||||
labelText: field.label,
|
||||
border: const OutlineInputBorder(),
|
||||
isDense: true,
|
||||
),
|
||||
onSubmitted: (_) {
|
||||
final Map<String, dynamic> values = {
|
||||
for (final entry in _controllers!.entries)
|
||||
entry.key: entry.value.text,
|
||||
};
|
||||
|
||||
hiddenValues?.forEach((final key, final value) {
|
||||
values[key] = value;
|
||||
});
|
||||
|
||||
close();
|
||||
primaryAction.onPressed?.call(values);
|
||||
},
|
||||
),
|
||||
),
|
||||
(final DialogInputField field) => Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6),
|
||||
child: _getInputField(field, primaryAction),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: actions
|
||||
.map(
|
||||
(final action) =>
|
||||
TextButton(
|
||||
(final action) => TextButton(
|
||||
onPressed: () {
|
||||
final Map<String, dynamic> values = {
|
||||
for (final entry in _controllers!.entries)
|
||||
entry.key: entry.value.text,
|
||||
};
|
||||
|
||||
hiddenValues?.forEach((final key, final value) {
|
||||
values[key] = value;
|
||||
});
|
||||
|
||||
close();
|
||||
action.onPressed?.call(values);
|
||||
action.onPressed?.call(_values);
|
||||
},
|
||||
child: Text(action.label),
|
||||
),
|
||||
)
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
},
|
||||
@@ -218,8 +145,88 @@ class DynamicDialog {
|
||||
if (_dialogContext != null) {
|
||||
Navigator.of(_dialogContext!).pop();
|
||||
}
|
||||
}
|
||||
|
||||
_disposeControllers();
|
||||
_disposeFocusNodes();
|
||||
Widget _getInputField(
|
||||
final DialogInputField inputField,
|
||||
final DialogAction primaryAction,
|
||||
) {
|
||||
_values[inputField.id] = inputField.initialValue;
|
||||
|
||||
if (inputField.inputType == DialogInputFieldTypeEnum.date) {
|
||||
return DynamicDateTimeField(
|
||||
initialValue: inputField.initialValue,
|
||||
autofocus: inputField.autoFocus,
|
||||
onChanged: (final value) {
|
||||
inputField.onChanged?.call(value);
|
||||
_values[inputField.id] = value;
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
labelText: inputField.label,
|
||||
border: const OutlineInputBorder(),
|
||||
isDense: true,
|
||||
),
|
||||
);
|
||||
} else if (inputField.inputType == DialogInputFieldTypeEnum.select) {
|
||||
DialogInputFieldSelectItem? initialValue;
|
||||
|
||||
if (inputField.initialValue is Enum) {
|
||||
final Enum inputFieldInitialValue = inputField.initialValue;
|
||||
|
||||
for (final DialogInputFieldSelectItem value in inputField.selectItems) {
|
||||
if (value.id == inputFieldInitialValue.index) {
|
||||
initialValue = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_values[inputField.id] = initialValue;
|
||||
|
||||
return DropdownSearch<DialogInputFieldSelectItem>(
|
||||
items: (final f, final cs) => inputField.selectItems,
|
||||
itemAsString: (final DialogInputFieldSelectItem value) => value.value,
|
||||
selectedItem: initialValue,
|
||||
onChanged: (final DialogInputFieldSelectItem? value) {
|
||||
inputField.onChanged?.call(value);
|
||||
_values[inputField.id] = value;
|
||||
},
|
||||
decoratorProps: DropDownDecoratorProps(
|
||||
decoration: InputDecoration(
|
||||
labelText: inputField.label,
|
||||
border: const OutlineInputBorder(),
|
||||
isDense: true,
|
||||
),
|
||||
),
|
||||
compareFn:
|
||||
(
|
||||
final DialogInputFieldSelectItem v1,
|
||||
final DialogInputFieldSelectItem v2,
|
||||
) => v1.id == v2.id,
|
||||
);
|
||||
} else {
|
||||
return TextField(
|
||||
controller: TextEditingController(
|
||||
text: inputField.initialValue is String
|
||||
? inputField.initialValue
|
||||
: '',
|
||||
),
|
||||
autofocus: inputField.autoFocus,
|
||||
keyboardType: inputField.keyboardType,
|
||||
obscureText: inputField.obscureText,
|
||||
onChanged: (final value) {
|
||||
inputField.onChanged?.call(value);
|
||||
_values[inputField.id] = value;
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
labelText: inputField.label,
|
||||
border: const OutlineInputBorder(),
|
||||
isDense: true,
|
||||
),
|
||||
onSubmitted: (_) {
|
||||
close();
|
||||
primaryAction.onPressed?.call(_values);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user