import 'package:fbla_ui/shared/api_logic.dart'; import 'package:fbla_ui/shared/global_vars.dart'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; class SignInPage extends StatefulWidget { final void Function(bool) refreshAccount; const SignInPage({super.key, required this.refreshAccount}); @override State createState() => _SignInPageState(); } class _SignInPageState extends State { final _signInKey = GlobalKey(); final TextEditingController _usernameController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); String username = ''; String password = ''; bool obscurePassword = true; bool rememberMe = false; bool _isloading = false; String? errorMessage; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Admin Sign In'), centerTitle: true, ), body: SingleChildScrollView( child: Form( key: _signInKey, child: Center( heightFactor: 1.0, child: Container( padding: const EdgeInsets.fromLTRB(12, 50, 12, 50), height: 450, width: 500, child: Card( child: Padding( padding: const EdgeInsets.fromLTRB(16, 8, 16, 24), child: Column( children: [ const Center( child: Text( 'Admin Sign In', style: TextStyle( fontSize: 30, fontWeight: FontWeight.bold), ), ), Padding( padding: const EdgeInsets.all(8.0), child: TextFormField( onChanged: (value) { username = value.trim(); }, controller: _usernameController, autocorrect: false, decoration: const InputDecoration( prefixIcon: Padding( padding: EdgeInsets.all(16.0), child: Icon(Icons.person_outline), ), labelText: 'Username', ), ), ), Padding( padding: const EdgeInsets.all(8.0), child: TextFormField( onChanged: (value) { password = value.trim(); }, onFieldSubmitted: (value) async { password = value.trim(); setState(() { errorMessage = null; _isloading = true; }); jwt = await signIn(username, password).timeout( const Duration(seconds: 20), onTimeout: () { _isloading = false; ScaffoldMessenger.of(context).showSnackBar( const SnackBar( width: 300, behavior: SnackBarBehavior.floating, content: Text('Could not Sign in (timeout)!')), ); }); if (!jwt.contains('Error:')) { final SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setString('username', username); await prefs.setString('password', password); await prefs.setBool('rememberMe', rememberMe); widget.refreshAccount(true); Navigator.of(context).pop(); } else { setState(() { errorMessage = 'Invalid Username/Password'; _isloading = false; }); } }, controller: _passwordController, autocorrect: false, obscureText: obscurePassword, decoration: InputDecoration( prefixIcon: const Padding( padding: EdgeInsets.all(16.0), child: Icon(Icons.fingerprint), ), labelText: 'Password', suffixIcon: Padding( padding: const EdgeInsets.only(right: 16.0), child: IconButton( onPressed: () { setState(() { obscurePassword = !obscurePassword; }); }, icon: obscurePassword ? const Icon(Icons.visibility_off) : const Icon(Icons.visibility), ), ), ), ), ), if (errorMessage != null) Text( errorMessage!, style: const TextStyle(color: Colors.red), ), Padding( padding: const EdgeInsets.only( top: 8.0, left: 8.0, right: 8.0), child: FilledButton( style: FilledButton.styleFrom( shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(6)))), child: SizedBox( width: 374, height: 40, child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ _isloading ? const Padding( padding: EdgeInsets.only(right: 8.0), child: SizedBox( width: 20, height: 20, child: CircularProgressIndicator( color: Colors.white, strokeWidth: 3, )), ) : const Padding( padding: EdgeInsets.only(right: 8.0), child: Icon(Icons.done, color: Colors.white), ), const Text('Sign in', style: TextStyle( color: Colors.white, fontSize: 18)), ], ), ), onPressed: () async { setState(() { _isloading = true; }); jwt = await signIn(username, password).timeout( const Duration(seconds: 20), onTimeout: () { _isloading = false; ScaffoldMessenger.of(context).showSnackBar( const SnackBar( width: 300, behavior: SnackBarBehavior.floating, content: Text('Could not Sign in (timeout)!')), ); }); if (!jwt.contains('Error:')) { final SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setString('username', username); await prefs.setString('password', password); await prefs.setBool('rememberMe', rememberMe); widget.refreshAccount(true); Navigator.of(context).pop(); } else { setState(() { errorMessage = 'Invalid Username/Password'; _isloading = false; }); } }, ), ), Expanded( child: Align( alignment: Alignment.bottomLeft, child: Row( children: [ Padding( padding: const EdgeInsets.only(left: 8.0), child: MouseRegion( cursor: SystemMouseCursors.click, child: GestureDetector( child: Row( children: [ Checkbox( value: rememberMe, onChanged: (value) { setState(() { rememberMe = value!; }); }), const Padding( padding: EdgeInsets.all(8.0), child: Text('Remember me'), ) ], ), onTap: () { setState(() { rememberMe = !rememberMe; }); }, ), ), ), ], ), ), ), ], ), ), ), ), ), ), ), ); } }