diff --git a/lib/features/authentication/presentation/pages/login_page.dart b/lib/features/authentication/presentation/pages/login_page.dart new file mode 100644 index 0000000..53f50c1 --- /dev/null +++ b/lib/features/authentication/presentation/pages/login_page.dart @@ -0,0 +1,202 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import '../widgets/auth_form.dart'; +import '../widgets/auth_button.dart'; + +/// Login screen with email/password authentication +class LoginPage extends StatefulWidget { + const LoginPage({super.key}); + + @override + State createState() => _LoginPageState(); +} + +class _LoginPageState extends State { + final _formKey = GlobalKey(); + final _emailController = TextEditingController(); + final _passwordController = TextEditingController(); + + bool _isLoading = false; + String? _emailError; + String? _passwordError; + + @override + void dispose() { + _emailController.dispose(); + _passwordController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Sign In'), + centerTitle: true, + elevation: 0, + backgroundColor: Colors.transparent, + foregroundColor: Theme.of(context).colorScheme.onSurface, + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(24.0), + child: Center( + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // Logo or app title could go here + Icon( + Icons.inventory_2_outlined, + size: 80, + color: Theme.of(context).colorScheme.primary, + ), + const SizedBox(height: 32), + + Text( + 'Welcome Back', + style: Theme.of(context).textTheme.headlineMedium?.copyWith( + fontWeight: FontWeight.bold, + color: Theme.of(context).colorScheme.onSurface, + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 8), + + Text( + 'Sign in to track your household inventory', + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 32), + + // Authentication form + AuthForm( + formKey: _formKey, + email: _emailController.text, + onEmailChanged: (value) { + setState(() { + _emailError = null; + _emailController.text = value; + }); + }, + emailError: _emailError, + password: _passwordController.text, + onPasswordChanged: (value) { + setState(() { + _passwordError = null; + _passwordController.text = value; + }); + }, + passwordError: _passwordError, + onSubmit: _handleLogin, + submitButtonText: 'Sign In', + isLoading: _isLoading, + autofocusEmail: true, + ), + const SizedBox(height: 16), + + // Forgot password link + Align( + alignment: Alignment.centerRight, + child: TextButton( + onPressed: _handleForgotPassword, + child: Text( + 'Forgot Password?', + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: Theme.of(context).colorScheme.primary, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + const SizedBox(height: 24), + + // Sign up link + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Don\'t have an account? ', + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + TextButton( + onPressed: _handleSignUp, + child: Text( + 'Sign Up', + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: Theme.of(context).colorScheme.primary, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ); + } + + Future _handleLogin() async { + // Clear previous errors + setState(() { + _emailError = null; + _passwordError = null; + }); + + // Validate form + if (!_formKey.currentState!.validate()) { + return; + } + + // Show loading state + setState(() { + _isLoading = true; + }); + + try { + // TODO: Implement actual authentication logic + // For now, simulate API call + await Future.delayed(const Duration(seconds: 2)); + + // Simulate successful login + if (mounted) { + // Navigate to home or dashboard + context.go('/home'); + } + } catch (e) { + // Handle authentication errors + setState(() { + _isLoading = false; + + // TODO: Implement proper error handling + // For now, show generic error + _passwordError = 'Invalid email or password'; + }); + } + } + + void _handleForgotPassword() { + // TODO: Navigate to forgot password screen + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Forgot password feature coming soon'), + duration: Duration(seconds: 2), + ), + ); + } + + void _handleSignUp() { + // Navigate to sign up page + context.go('/signup'); + } +} \ No newline at end of file