import 'package:flutter/material.dart'; import '../services/vanguard_api.dart'; import 'select_school_page.dart'; class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override State createState() => _LoginPageState(); } class _LoginPageState extends State { // ---- Controllers final emailController = TextEditingController(); final passwordController = TextEditingController(); // ---- UI state bool loading = false; String error = ''; @override void dispose() { emailController.dispose(); passwordController.dispose(); super.dispose(); } Future doLogin() async { setState(() { loading = true; error = ''; }); try { final token = await VanguardApi.login( username: emailController.text.trim(), password: passwordController.text.trim(), ); if (!mounted) return; Navigator.pushReplacement( context, MaterialPageRoute(builder: (_) => SelectSchoolPage(token: token)), ); } catch (e) { setState(() => error = 'Errore login: $e'); } finally { if (mounted) setState(() => loading = false); } } Future forgotPassword() async { final email = emailController.text.trim(); if (email.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Inserisci prima la tua email.')), ); return; } setState(() { loading = true; error = ''; }); try { await VanguardApi.requestPasswordResetEmail(email: email); if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Email inviata! Controlla la posta.')), ); } catch (e) { setState(() => error = 'Errore reset password: $e'); } finally { if (mounted) setState(() => loading = false); } } @override Widget build(BuildContext context) { const kBg1 = Color(0xFFF4F6FA); const kBg2 = Color(0xFFEFF7F3); // soft green wash const kGreen = Color(0xFF10B981); return Scaffold( body: Stack( children: [ // ---- Background gradient Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [kBg1, kBg2, kBg1], ), ), ), // ---- Decorative blobs const _BgBlob( color: Color(0x3310B981), size: 280, top: -70, left: -90, ), const _BgBlob( color: Color(0x22F59E0B), size: 230, bottom: 80, right: -70, ), const _BgBlob( color: Color(0x227C3AED), size: 190, bottom: -55, left: 35, ), // ---- Centered login card Center( child: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 24), child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 420), child: Container( padding: const EdgeInsets.all(24), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(18), boxShadow: const [ BoxShadow( blurRadius: 26, color: Colors.black12, offset: Offset(0, 14), ), ], border: Border.all(color: Colors.black12, width: 1), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Image.asset( 'assets/images/yogibook_logo.png', height: 74, ), const SizedBox(height: 14), const Text( 'Yogibook Login', style: TextStyle( fontSize: 22, fontWeight: FontWeight.w800, ), ), const SizedBox(height: 18), TextField( controller: emailController, keyboardType: TextInputType.emailAddress, textInputAction: TextInputAction.next, decoration: InputDecoration( labelText: 'Email / Username', border: const OutlineInputBorder(), enabled: !loading, ), ), const SizedBox(height: 12), TextField( controller: passwordController, obscureText: true, textInputAction: TextInputAction.done, onSubmitted: (_) => loading ? null : doLogin(), decoration: InputDecoration( labelText: 'Password', border: const OutlineInputBorder(), enabled: !loading, ), ), const SizedBox(height: 10), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ TextButton( onPressed: loading ? null : forgotPassword, child: const Text('Recupero password'), ), TextButton( onPressed: () => ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Registrazione: dopo.'), ), ), child: const Text('Registrati'), ), ], ), if (error.isNotEmpty) ...[ const SizedBox(height: 6), Text( error, textAlign: TextAlign.center, style: const TextStyle( color: Colors.red, fontWeight: FontWeight.w600, ), ), ], const SizedBox(height: 10), SizedBox( width: double.infinity, height: 48, child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: kGreen, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), ), ), onPressed: loading ? null : doLogin, child: loading ? const SizedBox( height: 18, width: 18, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white, ), ) : const Text( 'LOGIN', style: TextStyle(fontWeight: FontWeight.w900), ), ), ), ], ), ), ), ), ), ], ), ); } } class _BgBlob extends StatelessWidget { final Color color; final double size; final double? top; final double? left; final double? right; final double? bottom; const _BgBlob({ required this.color, required this.size, this.top, this.left, this.right, this.bottom, }); @override Widget build(BuildContext context) { return Positioned( top: top, left: left, right: right, bottom: bottom, child: IgnorePointer( child: Container( width: size, height: size, decoration: BoxDecoration( color: color, shape: BoxShape.circle, boxShadow: [ BoxShadow( blurRadius: 70, color: color, offset: const Offset(0, 18), ), ], ), ), ), ); } }