124 lines
3.4 KiB
Dart
124 lines
3.4 KiB
Dart
|
|
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<DurationFormField> {
|
|
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(),
|
|
],
|
|
);
|
|
}
|
|
}
|