diff --git a/lib/screens/expectation_input_page.dart b/lib/screens/expectation_input_page.dart index 913ed2b..98bf842 100644 --- a/lib/screens/expectation_input_page.dart +++ b/lib/screens/expectation_input_page.dart @@ -44,7 +44,6 @@ class ExpectationInputPageState extends State { final FocusNode _frequencyFocusNode = FocusNode(); final FocusNode _squawkFocusNode = FocusNode(); - // Neue Variablen bool _saveSimbriefId = false; static const String _simbriefIdKey = 'simbrief_id'; @@ -54,7 +53,6 @@ class ExpectationInputPageState extends State { _loadSavedSimbriefId(); } - // Methode zum Laden der gespeicherten ID Future _loadSavedSimbriefId() async { final prefs = await SharedPreferences.getInstance(); final savedId = prefs.getString(_simbriefIdKey); @@ -66,7 +64,6 @@ class ExpectationInputPageState extends State { } } - // Methode zum Speichern der ID Future _saveSimbriefIdToPrefs() async { final prefs = await SharedPreferences.getInstance(); if (_saveSimbriefId) { @@ -100,7 +97,6 @@ class ExpectationInputPageState extends State { Uri.parse('https://www.simbrief.com/api/xml.fetcher.php?userid=${_simbriefIdController.text}&json=1'), ); - // Prüfe ob Widget noch mounted ist if (!mounted) return; if (response.statusCode == 200) { @@ -116,15 +112,15 @@ class ExpectationInputPageState extends State { _expectedFrequencyController.text = ''; }); - if (!mounted) return; // Zweiter Check vor ScaffoldMessenger + if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('SimBrief Daten erfolgreich geladen')), + const SnackBar(content: Text('SimBrief data successfully loaded')), ); } } catch (e) { - if (!mounted) return; // Check vor Error-SnackBar + if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Fehler beim Laden der SimBrief Daten: $e')), + SnackBar(content: Text('Error loading SimBrief data: $e')), ); } } @@ -250,217 +246,246 @@ class ExpectationInputPageState extends State { ), ], ), - body: GestureDetector( - // Dismiss the keyboard when tapping outside - onTap: () => FocusScope.of(context).unfocus(), - child: SingleChildScrollView( - padding: const EdgeInsets.all(16.0), - child: Column( - children: [ - // IntrinsicHeight Widget hinzufügen - IntrinsicHeight( - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, // Stretch hinzufügen - children: [ - // Welcome Card - nimmt 60% der Breite - Expanded( - flex: 3, - child: Card( - elevation: 2, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: const [ - Text( - 'Welcome to IFR Buddy!', - style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - SizedBox(height: 10), - Text( - 'Just an easy tool for writing down IFR clearances without a pen.', - style: TextStyle(fontSize: 16), - ), - ], - ), - ), - ), - ), - const SizedBox(width: 16), // Abstand zwischen den Cards - // SimBrief Card - nimmt 40% der Breite - Expanded( - flex: 2, - child: Card( - elevation: 2, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'SimBrief Import', - style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - const SizedBox(height: 10), - TextFormField( - controller: _simbriefIdController, - decoration: const InputDecoration( - labelText: 'SimBrief Pilot ID', - border: OutlineInputBorder(), - ), - ), - const SizedBox(height: 10), - Row( - children: [ - Checkbox( - value: _saveSimbriefId, - onChanged: (bool? value) { - setState(() { - _saveSimbriefId = value ?? false; - }); - _saveSimbriefIdToPrefs(); - }, - ), - const Text('Save SimBrief ID'), - ], - ), - SizedBox( - width: double.infinity, - child: ElevatedButton( - onPressed: _fetchSimbriefData, - child: const Text('Load SimBrief Data'), - ), - ), - ], - ), - ), - ), - ), - ], + body: LayoutBuilder( + builder: (context, constraints) { + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: SingleChildScrollView( + padding: const EdgeInsets.all(16.0), + // ConstrainedBox hinzufügen + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 100, // AppBar-Höhe abziehen ), - ), - 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 (Or use the SimBrief import). ' - 'Use the listening page or skip to the readback page.', - style: TextStyle(fontSize: 16), - textAlign: TextAlign.left, - ), - const SizedBox(height: 16), - Padding( - padding: const EdgeInsets.all(8.0), - ), - Form( - key: _formKey, - child: Column( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (constraints.maxWidth > 600) + // Desktop Layout + IntrinsicHeight( + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, 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 + Expanded( + flex: 3, + child: _buildWelcomeCard(), ), - 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'), + const SizedBox(width: 16), + Expanded( + flex: 2, + child: _buildSimbriefCard(), ), ], ), + ) + else + // Mobile Layout + Column( + children: [ + _buildWelcomeCard(), + const SizedBox(height: 16), + _buildSimbriefCard(), + ], ), - ], - ), + _buildMainContent(), + ], ), ), - ], - ), + ), + ); + }, + ), + ); + } + // Hilfsmethoden zum Erstellen der Cards + Widget _buildWelcomeCard() { + return Card( + elevation: 2, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: const [ + Text( + 'Welcome to IFR Buddy!', + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + SizedBox(height: 10), + Text( + 'Just an easy tool for writing down IFR clearances without a pen.', + style: TextStyle(fontSize: 16), + ), + ], + ), + ), + ); + } + + Widget _buildSimbriefCard() { + return Card( + elevation: 2, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'SimBrief Import', + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + TextFormField( + controller: _simbriefIdController, + decoration: const InputDecoration( + labelText: 'SimBrief Pilot ID', + border: OutlineInputBorder(), + ), + ), + const SizedBox(height: 10), + Row( + children: [ + Checkbox( + value: _saveSimbriefId, + onChanged: (bool? value) { + setState(() { + _saveSimbriefId = value ?? false; + }); + _saveSimbriefIdToPrefs(); + }, + ), + const Text('Save SimBrief ID'), + ], + ), + SizedBox( + width: double.infinity, + child: ElevatedButton( + onPressed: _fetchSimbriefData, + child: const Text('Load SimBrief Data'), + ), + ), + ], + ), + ), + ); + } + + Widget _buildMainContent() { + return 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 (Or use the SimBrief import). ' + 'Use the listening page or skip to the readback page.', + style: TextStyle(fontSize: 16), + textAlign: TextAlign.left, + ), + const SizedBox(height: 16), + Padding( + padding: const EdgeInsets.all(8.0), + ), + 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'), + ), + ], + ), + ), + ], ), ), );