import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'comparison_page.dart'; import 'final_clearance_page.dart'; // Import final clearance page import '../utils/frequency_input_formatter.dart'; // Ensure this path is correct class ExpectationInputPage extends StatefulWidget { final bool isDarkMode; final Function toggleDarkMode; const ExpectationInputPage({ super.key, required this.isDarkMode, required this.toggleDarkMode, }); @override ExpectationInputPageState createState() => ExpectationInputPageState(); } class ExpectationInputPageState extends State { final _formKey = GlobalKey(); final TextEditingController _expectedClearanceLimitController = TextEditingController(); final TextEditingController _expectedRouteController = TextEditingController(); final TextEditingController _expectedAltitudeController = TextEditingController(); final TextEditingController _expectedSquawkController = TextEditingController(); final TextEditingController _expectedFrequencyController = TextEditingController(); // FocusNodes for each field final FocusNode _clearanceLimitFocusNode = FocusNode(); final FocusNode _routeFocusNode = FocusNode(); final FocusNode _altitudeFocusNode = FocusNode(); final FocusNode _frequencyFocusNode = FocusNode(); final FocusNode _squawkFocusNode = FocusNode(); @override void dispose() { _expectedClearanceLimitController.dispose(); _expectedRouteController.dispose(); _expectedAltitudeController.dispose(); _expectedSquawkController.dispose(); _expectedFrequencyController.dispose(); _clearanceLimitFocusNode.dispose(); _routeFocusNode.dispose(); _altitudeFocusNode.dispose(); _frequencyFocusNode.dispose(); _squawkFocusNode.dispose(); super.dispose(); } void _navigateToComparisonPage() { if (_formKey.currentState?.validate() ?? false) { Navigator.push( context, MaterialPageRoute( builder: (context) => ComparisonPage( expectedClearanceLimit: _expectedClearanceLimitController.text, expectedRoute: _expectedRouteController.text, expectedAltitude: _expectedAltitudeController.text, expectedSquawk: _expectedSquawkController.text, expectedFrequency: _expectedFrequencyController.text, isDarkMode: widget.isDarkMode, toggleDarkMode: widget.toggleDarkMode, ), ), ); } } // Function to skip directly to final clearance page void _skipReadback() { if (_formKey.currentState?.validate() ?? false) { Navigator.push( context, MaterialPageRoute( builder: (context) => FinalClearanceDisplay( clearanceLimit: _expectedClearanceLimitController.text, route: _expectedRouteController.text, altitude: _expectedAltitudeController.text, squawk: _expectedSquawkController.text, frequency: _expectedFrequencyController.text, isDarkMode: widget.isDarkMode, toggleDarkMode: widget.toggleDarkMode, ), ), ); } } // Method to build a text field with optional input and standard keyboard Widget buildTextField({ required String label, required TextEditingController controller, required FocusNode currentFocus, FocusNode? nextFocus, TextInputType keyboardType = TextInputType.text, List? inputFormatters, bool isLastField = false, bool enableAutocorrect = false, // To disable autocorrect bool enableSuggestions = false, // To disable suggestions bool enableIMEPersonalizedLearning = false, // iOS-specific }) { return Padding( padding: const EdgeInsets.symmetric(vertical: 10), child: TextFormField( controller: controller, focusNode: currentFocus, keyboardType: keyboardType, textInputAction: isLastField ? TextInputAction.done : TextInputAction.next, inputFormatters: inputFormatters, autocorrect: enableAutocorrect, enableSuggestions: enableSuggestions, enableIMEPersonalizedLearning: enableIMEPersonalizedLearning, onFieldSubmitted: (_) { if (isLastField) { // If it's the last field, unfocus to close the keyboard and submit currentFocus.unfocus(); _navigateToComparisonPage(); } else if (nextFocus != null) { FocusScope.of(context).requestFocus(nextFocus); } }, // Validator allows empty inputs but validates if input is present validator: (value) { if (value != null && value.isNotEmpty) { if (keyboardType == TextInputType.number || keyboardType == const TextInputType.numberWithOptions(decimal: true)) { final number = double.tryParse(value); if (number == null) { return 'Please enter a valid number'; } // Add more specific validations if needed } // Validate Transponder (Squawk) field if (label == 'Transponder (Squawk)') { if (!RegExp(r'^[0-7]{1,4}$').hasMatch(value)) { return 'Squawk must be 1-4 digits between 0 and 7'; } } // Add other conditional validations as necessary } // If no issues, return null return null; }, decoration: InputDecoration( labelText: label, border: const OutlineInputBorder(), ), ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('IFR Buddy'), actions: [ IconButton( icon: Icon( widget.isDarkMode ? Icons.dark_mode : Icons.light_mode), onPressed: () { widget.toggleDarkMode(); }, ), ], ), body: GestureDetector( // Dismiss the keyboard when tapping outside onTap: () => FocusScope.of(context).unfocus(), child: SingleChildScrollView( padding: const EdgeInsets.all(16.0), child: Column( children: [ const Card( elevation: 2, child: Padding( padding: EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Welcome to IFR Buddy!', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold), textAlign: TextAlign.left, ), SizedBox(height: 10), Text( 'Just an easy tool for writing down IFR clearances without a pen.', style: TextStyle(fontSize: 16), textAlign: TextAlign.left, ), ], ), ), ), const SizedBox(height: 16), Card( elevation: 2, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Expected Clearance', style: TextStyle( fontSize: 22, fontWeight: FontWeight.bold), ), const SizedBox(height: 10), const Text( 'Enter your expected clearance information below. ' 'Use the listening page or skip to the readback page.', style: TextStyle(fontSize: 16), textAlign: TextAlign.left, ), const SizedBox(height: 16), Form( key: _formKey, child: Column( children: [ buildTextField( label: 'Clearance Limit', controller: _expectedClearanceLimitController, currentFocus: _clearanceLimitFocusNode, nextFocus: _routeFocusNode, keyboardType: TextInputType.text, // Standard keyboard inputFormatters: [ // Allow letters, numbers, spaces, and hyphens FilteringTextInputFormatter.allow( RegExp(r'[A-Za-z0-9\s\-]')), ], enableAutocorrect: false, // Disable autocorrect enableSuggestions: false, // Disable suggestions enableIMEPersonalizedLearning: false, // iOS-specific ), buildTextField( label: 'Route/Sid', controller: _expectedRouteController, currentFocus: _routeFocusNode, nextFocus: _altitudeFocusNode, keyboardType: TextInputType.text, // Standard keyboard inputFormatters: [ // Allow letters, numbers, spaces, and hyphens FilteringTextInputFormatter.allow( RegExp(r'[A-Za-z0-9\s\-]')), ], enableAutocorrect: false, // Disable autocorrect enableSuggestions: false, // Disable suggestions enableIMEPersonalizedLearning: false, // iOS-specific ), buildTextField( label: 'Altitude', controller: _expectedAltitudeController, currentFocus: _altitudeFocusNode, nextFocus: _frequencyFocusNode, // Updated next focus keyboardType: TextInputType.text, // Standard keyboard inputFormatters: null, // No restrictions enableAutocorrect: false, // Disable autocorrect enableSuggestions: false, // Disable suggestions enableIMEPersonalizedLearning: false, // iOS-specific ), buildTextField( label: 'Departure Frequency', // Changed label controller: _expectedFrequencyController, currentFocus: _frequencyFocusNode, nextFocus: _squawkFocusNode, // Next focus to Squawk keyboardType: TextInputType.text, // Standard keyboard inputFormatters: [ FrequencyInputFormatter(), // Handles decimal inputs ], enableAutocorrect: false, // Disable autocorrect enableSuggestions: false, // Disable suggestions enableIMEPersonalizedLearning: false, // iOS-specific ), buildTextField( label: 'Transponder (Squawk)', // Now last field controller: _expectedSquawkController, currentFocus: _squawkFocusNode, isLastField: true, // Mark as last field keyboardType: TextInputType.text, // Standard keyboard inputFormatters: [ // Allow only digits 0-7 and limit to 4 characters FilteringTextInputFormatter.allow( RegExp(r'[0-7]')), LengthLimitingTextInputFormatter(4), ], enableAutocorrect: false, // Disable autocorrect enableSuggestions: false, // Disable suggestions enableIMEPersonalizedLearning: false, // iOS-specific ), const SizedBox(height: 20), ElevatedButton( onPressed: _navigateToComparisonPage, child: const Text('Next'), ), const SizedBox(height: 10), TextButton( onPressed: _skipReadback, child: const Text('Skip to end'), ), ], ), ), ], ), ), ), ], ), ), ), ); } }