import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../utils/frequency_input_formatter.dart'; import 'final_clearance_page.dart'; class ComparisonPage extends StatefulWidget { final String expectedClearanceLimit; final String expectedRoute; final String expectedAltitude; final String expectedSquawk; final String expectedFrequency; final bool isDarkMode; final Function toggleDarkMode; const ComparisonPage({super.key, required this.expectedClearanceLimit, required this.expectedRoute, required this.expectedAltitude, required this.expectedSquawk, required this.expectedFrequency, required this.isDarkMode, required this.toggleDarkMode, }); @override ComparisonPageState createState() => ComparisonPageState(); } class ComparisonPageState extends State { final TextEditingController _actualClearanceLimitController = TextEditingController(); final TextEditingController _actualRouteController = TextEditingController(); final TextEditingController _actualAltitudeController = TextEditingController(); final TextEditingController _actualSquawkController = TextEditingController(); final TextEditingController _actualFrequencyController = TextEditingController(); final FocusNode _actualAltitudeFocusNode = FocusNode(); @override void initState() { super.initState(); _actualAltitudeFocusNode.addListener(() { if (!_actualAltitudeFocusNode.hasFocus) { _formatAltitude(_actualAltitudeController); } }); } @override void dispose() { _actualClearanceLimitController.dispose(); _actualRouteController.dispose(); _actualAltitudeController.dispose(); _actualSquawkController.dispose(); _actualFrequencyController.dispose(); _actualAltitudeFocusNode.dispose(); super.dispose(); } void _formatAltitude(TextEditingController controller) { String text = controller.text.trim(); if (text.isEmpty) { return; } if (text.startsWith('FL') || text.endsWith('ft')) { return; } if (RegExp(r'^\d{2,3}$').hasMatch(text)) { controller.text = 'FL$text'; } else if (RegExp(r'^\d{4,}$').hasMatch(text)) { controller.text = '$text ft'; } } void _validateFrequency() { String text = _actualFrequencyController.text; if (text.isEmpty) { _actualFrequencyController.text = widget.expectedFrequency; } } void _navigateToFinalClearance() { _validateFrequency(); if (_actualClearanceLimitController.text.isEmpty) { _actualClearanceLimitController.text = widget.expectedClearanceLimit; } if (_actualRouteController.text.isEmpty) { _actualRouteController.text = widget.expectedRoute; } if (_actualAltitudeController.text.isEmpty) { _actualAltitudeController.text = widget.expectedAltitude; } if (_actualSquawkController.text.isEmpty) { _actualSquawkController.text = widget.expectedSquawk; } if (_actualFrequencyController.text.isEmpty) { _actualFrequencyController.text = widget.expectedFrequency; } Navigator.push( context, MaterialPageRoute( builder: (context) => FinalClearanceDisplay( clearanceLimit: _actualClearanceLimitController.text, route: _actualRouteController.text, altitude: _actualAltitudeController.text, squawk: _actualSquawkController.text, frequency: _actualFrequencyController.text, isDarkMode: widget.isDarkMode, toggleDarkMode: widget.toggleDarkMode, ), ), ); } Widget buildExpectedClearanceField(String label, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 10), child: TextFormField( initialValue: value, readOnly: true, decoration: InputDecoration( labelText: label, border: const OutlineInputBorder(), ), ), ); } Widget buildActualClearanceField( String label, TextEditingController controller, String expectedValue, { List? formatterList, FocusNode? focusNode, }) { return Padding( padding: const EdgeInsets.symmetric(vertical: 10), child: TextFormField( controller: controller, focusNode: focusNode, decoration: InputDecoration( labelText: label, border: const OutlineInputBorder(), suffixIcon: IconButton( icon: const Icon(Icons.arrow_forward), tooltip: 'Use Expected Value', onPressed: () { setState(() { controller.text = expectedValue; }); }, ), ), inputFormatters: formatterList, ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('IFR Buddy'), // Global title actions: [ IconButton( icon: Icon(widget.isDarkMode ? Icons.dark_mode : Icons.light_mode), onPressed: () { widget.toggleDarkMode(); }, ), ], ), body: Padding( padding: const EdgeInsets.all(16.0), child: ListView( children: [ // Explanation Text Card const Card( elevation: 2, child: Padding( padding: EdgeInsets.all(16.0), child: Text( 'Use this Page while receiving your clearance. The arrow button copies the excpected value. Same if left empty.', style: TextStyle(fontSize: 16), textAlign: TextAlign.center, ), ), ), const SizedBox(height: 16), // Main content side-by-side Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Expected Clearance Column Expanded( child: Card( elevation: 2, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Expected', style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold), ), const Divider(), buildExpectedClearanceField('Clearance Limit', widget.expectedClearanceLimit), buildExpectedClearanceField('Route', widget.expectedRoute), buildExpectedClearanceField('Altitude', widget.expectedAltitude), buildExpectedClearanceField('Transponder (Squawk)', widget.expectedSquawk), buildExpectedClearanceField('Frequency', widget.expectedFrequency), ], ), ), ), ), const SizedBox(width: 16), // Spacer between columns // Actual Clearance Column Expanded( child: Card( elevation: 2, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Clearance', style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold), ), const Divider(), buildActualClearanceField( 'Clearance Limit', _actualClearanceLimitController, widget.expectedClearanceLimit, ), buildActualClearanceField( 'Route', _actualRouteController, widget.expectedRoute, ), buildActualClearanceField( 'Altitude', _actualAltitudeController, widget.expectedAltitude, focusNode: _actualAltitudeFocusNode, ), buildActualClearanceField( 'Transponder (Squawk)', _actualSquawkController, widget.expectedSquawk, formatterList: [ FilteringTextInputFormatter.allow(RegExp(r'[0-7]')), LengthLimitingTextInputFormatter(4), ], ), buildActualClearanceField( 'Frequency', _actualFrequencyController, widget.expectedFrequency, formatterList: [FrequencyInputFormatter()], ), ], ), ), ), ), ], ), const SizedBox(height: 20), // Proceed Button ElevatedButton( onPressed: _navigateToFinalClearance, child: const Text('Proceed to Clearance Display'), ), ], ), ), ); } }