Files
flutter_ecommerce_portal/lib/screens/login_screen.dart
rbhat 39a4f3283f Initialize project and update portal port configuration
Set default portal port to 8081, fix Dart build issue in cart screen, and update setup documentation.

Co-Authored-By: Oz <oz-agent@warp.dev>
2026-04-10 19:08:30 +05:30

169 lines
6.1 KiB
Dart

import 'package:flutter/material.dart';
import '../services/auth_service.dart';
import 'forgot_password_screen.dart';
import 'register_screen.dart';
class LoginScreen extends StatefulWidget {
const LoginScreen({super.key});
@override
State<LoginScreen> createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final _formKey = GlobalKey<FormState>();
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
bool _loading = false;
@override
void dispose() {
_emailController.dispose();
_passwordController.dispose();
super.dispose();
}
Future<void> _run(Future<void> Function() action) async {
setState(() => _loading = true);
try {
await action();
} catch (e) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(e.toString())),
);
} finally {
if (mounted) setState(() => _loading = false);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 420),
child: Card(
margin: const EdgeInsets.all(20),
child: Padding(
padding: const EdgeInsets.all(20),
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text(
'Welcome Back',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
TextFormField(
controller: _emailController,
decoration: const InputDecoration(labelText: 'Email'),
validator: (value) =>
(value == null || value.trim().isEmpty)
? 'Email is required'
: null,
),
const SizedBox(height: 12),
TextFormField(
controller: _passwordController,
obscureText: true,
decoration: const InputDecoration(labelText: 'Password'),
validator: (value) =>
(value == null || value.isEmpty)
? 'Password is required'
: null,
),
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
child: FilledButton(
onPressed: _loading
? null
: () {
if (!_formKey.currentState!.validate()) return;
_run(() async {
await AuthService.instance
.signInWithEmailPassword(
email: _emailController.text.trim(),
password: _passwordController.text,
);
});
},
child: _loading
? const SizedBox(
width: 18,
height: 18,
child:
CircularProgressIndicator(strokeWidth: 2),
)
: const Text('Sign In'),
),
),
TextButton(
onPressed: _loading
? null
: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => const ForgotPasswordScreen(),
),
);
},
child: const Text('Forgot Password?'),
),
const Divider(height: 24),
SizedBox(
width: double.infinity,
child: OutlinedButton.icon(
onPressed: _loading
? null
: () => _run(() async {
await AuthService.instance.signInWithGoogle();
}),
icon: const Icon(Icons.login),
label: const Text('Continue with Google'),
),
),
const SizedBox(height: 8),
SizedBox(
width: double.infinity,
child: OutlinedButton.icon(
onPressed: _loading
? null
: () => _run(() async {
await AuthService.instance.signInWithGithub();
}),
icon: const Icon(Icons.code),
label: const Text('Continue with GitHub'),
),
),
const SizedBox(height: 8),
TextButton(
onPressed: _loading
? null
: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => const RegisterScreen(),
),
);
},
child: const Text('Create an account'),
),
],
),
),
),
),
),
),
);
}
}