import 'package:flutter/material.dart'; import 'core/api.dart'; import 'core/theme.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'eventpicker.dart'; import 'settings.dart'; import 'package:url_launcher/url_launcher.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Login Page', theme: laserTheme, home: const LoginPage(), ); } } class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override State createState() => _LoginPageState();} class _LoginPageState extends State { final TextEditingController _teamNumberController = TextEditingController(); bool _isLoading = false; @override void initState() { super.initState(); _loadSavedData(); } Future _loadSavedData() async { final prefs = await SharedPreferences.getInstance(); if (mounted) { _teamNumberController.text = prefs.getString('teamNumber') ?? ''; } } Future _saveData() async { final prefs = await SharedPreferences.getInstance(); await prefs.setString('teamNumber', _teamNumberController.text); } Future _launchUrl(Uri url) async { if (!await launchUrl(url)) { throw Exception('Could not launch $url'); } } @override void dispose() { _teamNumberController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Login'), ), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset('assets/main.png', height: 75, alignment: Alignment.center), const SizedBox(height: 16.0), TextField( controller: _teamNumberController, decoration: const InputDecoration( labelText: 'Team Number', border: OutlineInputBorder(), ), ), const SizedBox(height: 16.0), ElevatedButton( onPressed: _isLoading ? null : () async { final navigator = Navigator.of(context); final scaffoldMessenger = ScaffoldMessenger.of(context); setState(() { _isLoading = true; }); try { await _saveData(); String teamNumber = _teamNumberController.text; final result = await teamSearch(teamNumber); navigator.push( MaterialPageRoute( builder: (context) => EventPicker( eventNames: result.eventNames, eventCodes: result.eventCodes, ), ), ); } catch (e) { scaffoldMessenger.showSnackBar( SnackBar(content: Text('Error: ${e.toString()}')), ); } finally { if (mounted) { setState(() { _isLoading = false; }); } } }, child: _isLoading ? const SizedBox( height: 20, width: 20, child: CircularProgressIndicator( strokeWidth: 2.0, color: Colors.white, ), ) : const Text('Login'), ) ], ), ), bottomNavigationBar: Padding ( padding: const EdgeInsets.all(50.0), child: Row ( mainAxisAlignment: MainAxisAlignment.center, children: [ TextButton( child: const Text('Info'), onPressed: () { showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: const Text('Info'), content: const Text( "This app makes use of The Blue Alliance APIv3 through Laser Proxy. No API keys are stored on device. Laser Scouter was created by FRC 2077 Laser Robotics. \n\nVersion: Rebuilt 26.1.23" ), ); } ); }, ), TextButton( child: const Text('Github'), onPressed: () { _launchUrl(Uri.parse('https://github.com/raktbastr/laserscouter')); } ), TextButton( onPressed: _isLoading ? null : () { Navigator.push( context, MaterialPageRoute( builder: (context) => const SettingsPage(), ) ); }, child: const Text('Settings'), ) ] ) ) ); } }