233 lines
7.1 KiB
Dart
233 lines
7.1 KiB
Dart
import 'package:dropdown_search/dropdown_search.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
import '../../Services/navigation_service.dart';
|
|
import '../../Services/theme_service.dart';
|
|
import '../Misc/InputFields/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 {
|
|
/// Erstellt eine neue Instanz dieser Klasse
|
|
DynamicDialog({
|
|
this.title,
|
|
this.icon,
|
|
this.content,
|
|
final List<DialogInputField>? inputFields,
|
|
final List<DialogAction>? actions,
|
|
this.backgroundColor,
|
|
this.borderRadius = 16,
|
|
this.barrierDismissible = true,
|
|
this.dialogType = DialogTypeEnum.info,
|
|
this.hiddenValues,
|
|
}) : inputFields = inputFields ?? const [],
|
|
actions = actions ?? [DialogAction(label: 'Schließen')],
|
|
_values = hiddenValues ?? {};
|
|
|
|
/// Der Titel des Dialogs
|
|
final String? title;
|
|
|
|
/// Der Icon des Dialogs
|
|
final IconData? icon;
|
|
|
|
/// Der Inhalt des Dialogs
|
|
final Widget? content;
|
|
|
|
/// Die Hintergrundfarbe des Dialogs, Standard wenn nicht gesetzt
|
|
final Color? backgroundColor;
|
|
|
|
/// Der BorderRadius des Dialogs
|
|
final double borderRadius;
|
|
|
|
/// Ob der Dialog bei einem Klick auf die Barriere geschlossen werden kann
|
|
final bool barrierDismissible;
|
|
|
|
/// Die InputFelder des Dialogs
|
|
final List<DialogInputField> inputFields;
|
|
|
|
/// Die Aktionen des Dialogs
|
|
final List<DialogAction> actions;
|
|
|
|
/// Der Typ des Dialogs
|
|
final DialogTypeEnum dialogType;
|
|
|
|
/// Versteckte Werte, die beim Abschicken mit zurückgegeben werden
|
|
final Map<String, dynamic>? hiddenValues;
|
|
|
|
final Map<String, dynamic> _values;
|
|
|
|
BuildContext? _dialogContext;
|
|
|
|
/// Zeigt den vorher zusammengebauten Dialog an
|
|
Future<void> show() async {
|
|
final BuildContext? context = NavigationService.getCurrentBuildContext();
|
|
|
|
if (context != null) {
|
|
final ThemeData theme = Theme.of(context);
|
|
|
|
await showDialog(
|
|
context: context,
|
|
barrierDismissible: barrierDismissible,
|
|
builder: (final BuildContext ctx) {
|
|
_dialogContext = ctx;
|
|
final DialogAction primaryAction = actions.firstWhere(
|
|
(final a) => a.isPrimary,
|
|
orElse: () => actions.first,
|
|
);
|
|
|
|
Color backgroundColor =
|
|
this.backgroundColor ?? theme.colorScheme.surface;
|
|
|
|
if (dialogType == DialogTypeEnum.error) {
|
|
backgroundColor = theme.colorScheme.errorContainer;
|
|
} else if (dialogType == DialogTypeEnum.success) {
|
|
backgroundColor = ThemeService.getSuccessColor(
|
|
brightness: theme.brightness,
|
|
);
|
|
}
|
|
|
|
return AlertDialog(
|
|
backgroundColor: backgroundColor,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(borderRadius),
|
|
),
|
|
title: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
if (icon != null)
|
|
Icon(icon, size: 48, color: theme.colorScheme.primary),
|
|
if (title != null)
|
|
Padding(
|
|
padding: const EdgeInsets.only(top: 8),
|
|
child: Text(
|
|
title!,
|
|
style: theme.textTheme.titleLarge,
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
content: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
if (content != null) content!,
|
|
...inputFields.map(
|
|
(final DialogInputField field) => Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 6),
|
|
child: _getInputField(field, primaryAction),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
actions: actions
|
|
.map(
|
|
(final action) => TextButton(
|
|
onPressed: () {
|
|
close();
|
|
action.onPressed?.call(_values);
|
|
},
|
|
child: Text(action.label),
|
|
),
|
|
)
|
|
.toList(),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Schließt den dynamischen Dialog
|
|
void close() {
|
|
if (_dialogContext != null) {
|
|
Navigator.of(_dialogContext!).pop();
|
|
}
|
|
}
|
|
|
|
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);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
}
|