import 'dart:async'; import 'package:flutter/material.dart'; import 'package:routemaster/routemaster.dart'; import '../../Services/date_service.dart'; import '../Misc/InputFields/date_range_picker.dart'; /// Stellt die Inputfelder für die Verlaufsübersicht dar class InputFields extends StatefulWidget { /// Erstellt eine neue Instanz dieser Klasse const InputFields({ super.key, this.amountMax, this.amountMin, this.dateFrom, this.dateTo, this.name, }); /// Der Name der Transaktion, nach der gesucht werden soll final String? name; /// Der Mindestbetrag der Transaktion, nach der gesucht werden soll final double? amountMin; /// Der Maximalbetrag der Transaktion, nach der gesucht werden soll final double? amountMax; /// Das Datum der Transaktionen, ab dem gestartet wurde final DateTime? dateFrom; ///Das Datum der Transaktionen, bis zu welchen beendet wurde final DateTime? dateTo; @override State createState() => _InputFields(); } class _InputFields extends State { final TextEditingController _nameController = TextEditingController(); final TextEditingController _amountMinController = TextEditingController(); final TextEditingController _amountMaxController = TextEditingController(); final TextEditingController _dateTimeController = TextEditingController(); static const double _filterBreakpoint = 600; @override void initState() { super.initState(); if (widget.name != null) { _nameController.text = widget.name!; } if (widget.amountMin != null) { _amountMinController.text = widget.amountMin!.toString(); } if (widget.amountMax != null) { _amountMaxController.text = widget.amountMax!.toString(); } if (widget.dateFrom != null && widget.dateTo != null) { final DateTimeRange dateTimeRange = DateTimeRange( start: widget.dateFrom!, end: widget.dateTo!, ); _dateTimeController.text = DateService.dateTimeRangeToString( dateTimeRange, )!; } } @override void dispose() { _nameController.dispose(); _amountMinController.dispose(); _amountMaxController.dispose(); _dateTimeController.dispose(); super.dispose(); } @override Widget build(final BuildContext context) { final ThemeData theme = Theme.of(context); return LayoutBuilder( builder: (final context, final constraints) { if (constraints.maxWidth < _filterBreakpoint) { return _buildFilterButton(context, theme); } return _buildInlineFilters(theme); }, ); } Widget _buildInlineFilters(final ThemeData theme) => Row( children: [ Expanded( child: TextField( controller: _nameController, decoration: const InputDecoration( labelText: 'Name', border: OutlineInputBorder(), ), onChanged: (_) => _updateUrl(), ), ), const SizedBox(width: 8), Expanded( child: TextField( controller: _amountMinController, decoration: const InputDecoration( labelText: 'Min Betrag €', border: OutlineInputBorder(), ), keyboardType: const TextInputType.numberWithOptions(decimal: true), onChanged: (_) => _updateUrl(), ), ), const SizedBox(width: 8), Expanded( child: TextField( controller: _amountMaxController, decoration: const InputDecoration( labelText: 'Max Betrag €', border: OutlineInputBorder(), ), keyboardType: const TextInputType.numberWithOptions(decimal: true), onChanged: (_) => _updateUrl(), ), ), const SizedBox(width: 8), Expanded( child: DateRangePicker( controller: _dateTimeController, onChanged: (_) => _updateUrl(), decoration: InputDecoration( labelText: 'Zeitraum', border: const OutlineInputBorder(), suffixIcon: Icon( Icons.calendar_month, color: theme.colorScheme.onSurface, ), ), ), ), const SizedBox(width: 8), IconButton(onPressed: _clear, icon: const Icon(Icons.clear)), ], ); Widget _buildFilterButton( final BuildContext context, final ThemeData theme, ) => Align( alignment: Alignment.centerLeft, child: ElevatedButton.icon( icon: const Icon(Icons.filter_alt), label: const Text('Filter'), onPressed: () => _openFilterDialog(context), ), ); void _openFilterDialog(final BuildContext context) { unawaited( showDialog( context: context, builder: (final context) => AlertDialog( title: const Text('Filter'), content: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, children: [ TextField( controller: _nameController, decoration: const InputDecoration( labelText: 'Name', border: OutlineInputBorder(), ), ), const SizedBox(height: 12), TextField( controller: _amountMinController, decoration: const InputDecoration( labelText: 'Min Betrag €', border: OutlineInputBorder(), ), keyboardType: const TextInputType.numberWithOptions( decimal: true, ), ), const SizedBox(height: 12), TextField( controller: _amountMaxController, decoration: const InputDecoration( labelText: 'Max Betrag €', border: OutlineInputBorder(), ), keyboardType: const TextInputType.numberWithOptions( decimal: true, ), ), const SizedBox(height: 12), DateRangePicker( controller: _dateTimeController, onChanged: (_) {}, decoration: const InputDecoration( labelText: 'Zeitraum', border: OutlineInputBorder(), ), ), ], ), ), actions: [ TextButton( onPressed: () { _clear(); Navigator.of(context).pop(); }, child: const Text('Zurücksetzen'), ), ElevatedButton( onPressed: () { _updateUrl(); Navigator.of(context).pop(); }, child: const Text('Anwenden'), ), ], ), ), ); } void _clear() { _nameController.clear(); _amountMinController.clear(); _amountMaxController.clear(); _dateTimeController.clear(); _updateUrl(); } void _updateUrl() { final params = { if (_nameController.text != '') 'name': _nameController.text, if (_amountMinController.text != '') 'amountMin': _amountMinController.text, if (_amountMaxController.text != '') 'amountMax': _amountMaxController.text, }; if (_dateTimeController.text != '') { final DateTimeRange? range = DateService.stringToDateTimeRange( _dateTimeController.text, ); if (range != null) { params['dateFrom'] = range.start.toIso8601String(); params['dateTo'] = range.end.toIso8601String(); } } Routemaster.of(context).replace('/trend', queryParameters: params); } }