// * 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 { // 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), ), ], ), ), ), ], ), ], ); } }