285 lines
10 KiB
Dart
285 lines
10 KiB
Dart
// * Widget for recording travel distances and track conditions during excursions
|
|
// * Features:
|
|
// * - Distance tracking by transportation mode (car, foot, bicycle)
|
|
// * - Track condition assessment (good, medium, poor)
|
|
// * - Automatic validation of total distances
|
|
// * - Input validation with user feedback
|
|
|
|
import 'package:fforte/screens/helper/snack_bar_helper.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:fforte/l10n/app_localizations.dart';
|
|
|
|
/// Widget for managing travel distances and track conditions
|
|
/// Tracks both how the distance was covered and the quality of tracks found
|
|
class StreckeUSpurbedingungen extends StatefulWidget {
|
|
/// Controller for distance traveled by car
|
|
final TextEditingController kmAutoController;
|
|
/// Controller for distance traveled on foot
|
|
final TextEditingController kmFussController;
|
|
/// Controller for distance traveled by bicycle
|
|
final TextEditingController kmRadController;
|
|
/// Controller for distance with good track conditions
|
|
final TextEditingController spGutController;
|
|
/// Controller for distance with medium track conditions
|
|
final TextEditingController spMittelController;
|
|
/// Controller for distance with poor track conditions
|
|
final TextEditingController spSchlechtController;
|
|
|
|
const StreckeUSpurbedingungen({
|
|
required this.kmAutoController,
|
|
required this.kmFussController,
|
|
required this.kmRadController,
|
|
required this.spGutController,
|
|
required this.spMittelController,
|
|
required this.spSchlechtController,
|
|
super.key,
|
|
});
|
|
|
|
@override
|
|
StreckeUSpurbedingungenState createState() => StreckeUSpurbedingungenState();
|
|
}
|
|
|
|
/// State class for the distance and track conditions widget
|
|
class StreckeUSpurbedingungenState extends State<StreckeUSpurbedingungen> {
|
|
// vars for percent text fields
|
|
// String carPercent = "0";
|
|
// String footPercent = "0";
|
|
// String bikePercent = "0";
|
|
//
|
|
// String goodPercent = "0";
|
|
// String middlePercent = "0";
|
|
// String badPercent = "0";
|
|
//
|
|
// String totalKm = "0";
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
// Travle Distance
|
|
// widget.kmAutoController.addListener(onDistanceTravledUpdated);
|
|
// widget.kmFussController.addListener(onDistanceTravledUpdated);
|
|
// widget.kmRadController.addListener(onDistanceTravledUpdated);
|
|
|
|
// Initialize distance values if not set
|
|
if (widget.kmAutoController.text == "") {
|
|
widget.kmAutoController.text = "0";
|
|
widget.kmFussController.text = "0";
|
|
widget.kmRadController.text = "0";
|
|
}
|
|
|
|
// Track Conditions
|
|
widget.spGutController.addListener(onTrackConditionsUpdated);
|
|
widget.spMittelController.addListener(onTrackConditionsUpdated);
|
|
widget.spSchlechtController.addListener(onTrackConditionsUpdated);
|
|
|
|
// Initialize track condition values if not set
|
|
if (widget.spGutController.text == "") {
|
|
widget.spGutController.text = "0";
|
|
widget.spMittelController.text = "0";
|
|
widget.spSchlechtController.text = "0";
|
|
}
|
|
}
|
|
|
|
// void onDistanceTravledUpdated() {
|
|
// try {
|
|
// double kmAuto = double.parse(widget.kmAutoController.text);
|
|
// double kmFuss = double.parse(widget.kmFussController.text);
|
|
// double kmRad = double.parse(widget.kmRadController.text);
|
|
// double gesKm = (kmAuto + kmFuss + kmRad);
|
|
//
|
|
// if (gesKm == 0) {
|
|
// carPercent = "0";
|
|
// footPercent = "0";
|
|
// bikePercent = "0";
|
|
// } else {
|
|
// carPercent = (kmAuto / gesKm * 100).round().toString();
|
|
// footPercent = (kmFuss / gesKm * 100).round().toString();
|
|
// bikePercent = (kmRad / gesKm * 100).round().toString();
|
|
// totalKm = gesKm.toString();
|
|
// }
|
|
// setState(() {});
|
|
// } catch (e) {
|
|
// return;
|
|
// }
|
|
// }
|
|
|
|
/// Validate that track condition distances don't exceed total travel distance
|
|
/// Shows warning if track conditions total is greater than distance traveled
|
|
void onTrackConditionsUpdated() {
|
|
try {
|
|
// Parse track condition distances
|
|
double kmGood = double.parse(widget.spGutController.text);
|
|
double kmMiddle = double.parse(widget.spMittelController.text);
|
|
double kmBad = double.parse(widget.spSchlechtController.text);
|
|
|
|
// Parse travel distances
|
|
double kmAuto = double.parse(widget.kmAutoController.text);
|
|
double kmFuss = double.parse(widget.kmFussController.text);
|
|
double kmRad = double.parse(widget.kmRadController.text);
|
|
|
|
// Calculate totals
|
|
double gesConditionsKm = (kmGood + kmMiddle + kmBad);
|
|
double gesDistanceKm = (kmAuto + kmFuss + kmRad);
|
|
|
|
// Show warning if track conditions exceed distance
|
|
if (gesConditionsKm > gesDistanceKm) {
|
|
SnackBarHelper.showSnackBarMessage(context, AppLocalizations.of(context)!.bedingungenGroesserAlsStrecke);
|
|
}
|
|
|
|
setState(() {});
|
|
} catch (e) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Column(
|
|
children: [
|
|
// Travel distance section header
|
|
Align(
|
|
alignment: Alignment.bottomLeft,
|
|
child: Text(
|
|
"${AppLocalizations.of(context)!.zurueckgelegteStrecke} (km)",
|
|
style: Theme.of(context).textTheme.titleMedium,
|
|
),
|
|
),
|
|
const SizedBox(height: 10),
|
|
|
|
// Travel distance inputs
|
|
Row(
|
|
children: [
|
|
// Car distance input
|
|
Expanded(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Column(
|
|
children: [
|
|
Align(
|
|
alignment: Alignment.bottomLeft,
|
|
child: Text(AppLocalizations.of(context)!.auto),
|
|
),
|
|
TextField(
|
|
keyboardType: TextInputType.number,
|
|
controller: widget.kmAutoController,
|
|
onTap: () => widget.kmAutoController.selection = TextSelection(baseOffset: 0, extentOffset: widget.kmAutoController.value.text.length),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
|
|
// Foot distance input
|
|
Expanded(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Column(
|
|
children: [
|
|
Align(
|
|
alignment: Alignment.bottomLeft,
|
|
child: Text(AppLocalizations.of(context)!.zuFuss),
|
|
),
|
|
TextField(
|
|
keyboardType: TextInputType.number,
|
|
controller: widget.kmFussController,
|
|
onTap: () => widget.kmFussController.selection = TextSelection(baseOffset: 0, extentOffset: widget.kmFussController.value.text.length),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
|
|
// Bicycle distance input
|
|
Expanded(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Column(
|
|
children: [
|
|
Align(
|
|
alignment: Alignment.bottomLeft,
|
|
child: Text(AppLocalizations.of(context)!.fahrrad),
|
|
),
|
|
TextField(
|
|
keyboardType: TextInputType.number,
|
|
controller: widget.kmRadController,
|
|
onTap: () => widget.kmRadController.selection = TextSelection(baseOffset: 0, extentOffset: widget.kmRadController.value.text.length),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 20),
|
|
],
|
|
),
|
|
|
|
const SizedBox(height: 20),
|
|
|
|
// Track conditions section header
|
|
Align(
|
|
alignment: Alignment.bottomLeft,
|
|
child: Text(
|
|
"${AppLocalizations.of(context)!.spurbedingungen} (km)",
|
|
style: Theme.of(context).textTheme.titleMedium,
|
|
),
|
|
),
|
|
const SizedBox(height: 10,),
|
|
|
|
// Track condition inputs
|
|
Row(
|
|
children: [
|
|
// Good conditions input
|
|
Expanded(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8),
|
|
child: Column(
|
|
children: [
|
|
Align(alignment: Alignment.bottomLeft, child: Text(AppLocalizations.of(context)!.gut)),
|
|
TextField(
|
|
keyboardType: TextInputType.number,
|
|
controller: widget.spGutController,
|
|
onTap: () => widget.spGutController.selection = TextSelection(baseOffset: 0, extentOffset: widget.spGutController.value.text.length),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
// Medium conditions input
|
|
Expanded(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8),
|
|
child: Column(
|
|
children: [
|
|
Align(alignment: Alignment.bottomLeft, child: Text(AppLocalizations.of(context)!.mittel)),
|
|
TextField(
|
|
keyboardType: TextInputType.number,
|
|
controller: widget.spMittelController,
|
|
onTap: () => widget.spMittelController.selection = TextSelection(baseOffset: 0, extentOffset: widget.spMittelController.value.text.length),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
// Poor conditions input
|
|
Expanded(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8),
|
|
child: Column(
|
|
children: [
|
|
Align(alignment: Alignment.bottomLeft, child: Text(AppLocalizations.of(context)!.schlecht)),
|
|
TextField(
|
|
keyboardType: TextInputType.number,
|
|
controller: widget.spSchlechtController,
|
|
onTap: () => widget.spSchlechtController.selection = TextSelection(baseOffset: 0, extentOffset: widget.spSchlechtController.value.text.length),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|