import 'package:flutter/material.dart'; class DurationFormField extends StatefulWidget { final String label; final int minutes; final void Function(int?) onChanged; final bool showSteppers; final bool readOnly; final int min; final int? max; final int step; const DurationFormField( {Key? key, required this.label, this.minutes = 0, required this.onChanged, this.showSteppers = false, this.readOnly = false, this.min = 0, this.max, this.step = 5}) : super(key: key); @override _DurationFormFieldState createState() => _DurationFormFieldState(); } class _DurationFormFieldState extends State { late Duration duration; final TextEditingController controller = TextEditingController(text: ''); @override void initState() { super.initState(); updateDuration(); } void updateDuration() { duration = Duration(minutes: widget.minutes); int days = duration.inDays; int hours = duration.inHours - days * 24; int minutes = duration.inMinutes - hours * 60; int seconds = duration.inSeconds - minutes * 60; String daysString = days > 9 ? '$days d' : days > 0 ? '0$days d' : '00 d'; String hoursString = hours > 9 ? ' $hours h' : hours > 0 ? ' 0$hours h' : ' 00 h'; String minutesString = minutes > 9 ? ' $minutes m' : minutes > 0 ? ' 0$minutes m' : ' 00 m'; String secondsString = seconds > 9 ? ' $seconds s' : seconds > 0 ? ' 0$seconds s' : ' 00 s'; controller.text = '$daysString $hoursString $minutesString $secondsString'.trim(); } void handleChange(String value) async { await Future.delayed(const Duration(seconds: 1)); int days = int.tryParse(value.split(' d')[0]) ?? 0; int hours = int.tryParse(value.split('d')[1].split(' h')[0]) ?? 0; int minutes = int.tryParse(value.split('h')[1].split(' m')[0]) ?? 0; int seconds = int.tryParse(value.split('m')[1].split(' s')[0]) ?? 0; int updatedMinutes = Duration(days: days, hours: hours, minutes: minutes, seconds: seconds) .inMinutes; widget.onChanged(updatedMinutes); setState(() { updateDuration(); }); } void onIncrease() { if (widget.max == null || widget.minutes + widget.step <= widget.max!) { int value = widget.minutes + widget.step; widget.onChanged(value); setState(() { updateDuration(); }); } } void onDecrease() { if (widget.minutes - widget.step >= widget.min) { int value = widget.minutes - widget.step; widget.onChanged(value); setState(() { updateDuration(); }); } } @override Widget build(BuildContext context) { return Row( mainAxisSize: MainAxisSize.min, children: [ widget.showSteppers ? IconButton( onPressed: onDecrease, icon: const Icon(Icons.remove), ) : Container(), Expanded( child: TextFormField( controller: controller, decoration: InputDecoration( labelText: widget.label, ), keyboardType: TextInputType.numberWithOptions( decimal: true, signed: widget.min.isNegative), onChanged: handleChange, ), ), widget.showSteppers ? IconButton( onPressed: onIncrease, icon: const Icon(Icons.add), ) : Container(), ], ); } }