| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- import 'package:flutter/material.dart';
- import 'package:flutter_riverpod/flutter_riverpod.dart';
- import 'package:gap/gap.dart';
- import 'package:go_router/go_router.dart';
- import 'package:supabase_flutter/supabase_flutter.dart';
- import 'package:tp5/core/core.dart';
- class LoginOtp extends ConsumerStatefulWidget {
- const LoginOtp({super.key});
- @override
- ConsumerState<LoginOtp> createState() => _LoginOtpState();
- }
- class _LoginOtpState extends ConsumerState<LoginOtp> {
- final TextEditingController _emailController = TextEditingController();
- final TextEditingController _otpController = TextEditingController();
- bool _isOtpSent = false;
- bool _isLoading = false;
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(
- title: Text('Sign In'),
- backgroundColor: Colors.blueAccent,
- ),
- body: SingleChildScrollView(
- child: Padding(
- padding: const EdgeInsets.all(16.0),
- child: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- crossAxisAlignment: CrossAxisAlignment.stretch,
- children: [
- SizedBox(height: 50),
- Image(
- image: AssetImage('assets/logo.png'),
- width: 100,
- height: 100,
- ),
- Gap(20),
- Text(
- 'Welcome to TAR Pilot v5',
- style: TextStyle(
- fontSize: 24,
- fontWeight: FontWeight.bold,
- color: Colors.blueAccent,
- ),
- textAlign: TextAlign.center,
- ),
- SizedBox(height: 20),
- Text(
- 'Please enter your email to sign in.',
- style: TextStyle(
- fontSize: 16,
- color: Colors.grey[700],
- ),
- textAlign: TextAlign.center,
- ),
- SizedBox(height: 40),
- TextField(
- controller: _emailController,
- decoration: InputDecoration(
- labelText: 'Email',
- hintText: 'Enter your email',
- border: OutlineInputBorder(
- borderRadius: BorderRadius.circular(10),
- ),
- prefixIcon: Icon(Icons.email),
- ),
- keyboardType: TextInputType.emailAddress,
- ),
- SizedBox(height: 20),
- if (_isOtpSent) ...[
- TextField(
- controller: _otpController,
- decoration: InputDecoration(
- labelText: 'OTP',
- hintText: 'Enter OTP sent to your email',
- border: OutlineInputBorder(
- borderRadius: BorderRadius.circular(10),
- ),
- prefixIcon: Icon(Icons.lock_outline),
- ),
- keyboardType: TextInputType.number,
- ),
- SizedBox(height: 20),
- ],
- ElevatedButton(
- onPressed: _isLoading
- ? null
- : () async {
- final email = _emailController.text;
- setState(() => _isLoading = true);
- try {
- if (!_isOtpSent) {
- await Supabase.instance.client.auth.signInWithOtp(
- email: email,
- shouldCreateUser: false,
- emailRedirectTo:
- 'com.example.tp5://magic-link');
- setState(() => _isOtpSent = true);
- } else {
- final response =
- await Supabase.instance.client.auth.verifyOTP(
- email: email,
- token: _otpController.text,
- type: OtpType.email,
- );
- if (response.session == null) {
- _otpController.clear();
- ScaffoldMessenger.of(context).showSnackBar(
- const SnackBar(
- content:
- Text('Invalid OTP. Please try again.'),
- backgroundColor: Colors.red,
- ),
- );
- } else {
- //logged in
- print(response.session?.accessToken);
- context.go("/home");
- }
- }
- } catch (e) {
- if (e is AuthApiException && !_isOtpSent) {
- //signup
- print("loginotp: new signup");
- setState(() => _isLoading = true);
- await Supabase.instance.client.auth.signInWithOtp(
- email: email,
- shouldCreateUser: true,
- emailRedirectTo:
- 'com.example.tp5://auth/magic-link');
- setState(() => _isOtpSent = true);
- //go profile after new registration
- context.go('/home');
- } else {
- //error
- _otpController.clear();
- context.showError('Error: ${e.toString()}');
- }
- } finally {
- if (mounted) {
- setState(() => _isLoading = false);
- }
- }
- },
- style: ElevatedButton.styleFrom(
- padding: EdgeInsets.symmetric(vertical: 15),
- backgroundColor: Colors.blueAccent,
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(10),
- ),
- ),
- child: _isLoading
- ? const SizedBox(
- height: 20,
- width: 20,
- child: CircularProgressIndicator(
- color: Colors.white,
- strokeWidth: 2,
- ),
- )
- : Text(
- _isOtpSent ? 'Verify OTP' : 'Send OTP',
- style: TextStyle(fontSize: 18),
- ),
- ),
- SizedBox(height: 20),
- if (_isOtpSent)
- TextButton(
- onPressed: () {
- // Handle use another email
- _emailController.clear();
- setState(() => _isOtpSent = false);
- },
- child: Text(
- 'Use another mail?',
- style: TextStyle(
- color: Colors.blueAccent,
- fontSize: 16,
- ),
- ),
- ),
- ],
- ),
- ),
- ),
- );
- }
- @override
- void dispose() {
- _emailController.dispose();
- _otpController.dispose();
- super.dispose();
- }
- }
|