feat: add auth screens and state management

This commit is contained in:
soragui
2026-01-19 14:50:21 +08:00
parent 58c40c5f00
commit 0ade16350a
10 changed files with 291 additions and 1 deletions

28
lib/app.dart Normal file
View File

@@ -0,0 +1,28 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:phone_login/auth/auth_state.dart';
import 'package:phone_login/auth/phone_input_screen.dart';
import 'package:phone_login/auth/sms_verification_screen.dart';
import 'package:provider/provider.dart';
final _router = GoRouter(
routes: [
GoRoute(path: '/', builder: (context, state) => const PhoneInputScreen()),
GoRoute(
path: '/sms_verify',
builder: (context, state) => const SmsVerificationScreen(),
),
],
);
class App extends StatelessWidget {
const App({super.key});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => AuthState(),
child: MaterialApp.router(routerConfig: _router),
);
}
}

18
lib/auth/auth_state.dart Normal file
View File

@@ -0,0 +1,18 @@
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
class AuthState extends ChangeNotifier {
User? _user;
User? get user => _user;
final FirebaseAuth _auth = FirebaseAuth.instance;
AuthState() {
_auth.authStateChanges().listen((user) {
_user = user;
notifyListeners();
});
}
bool get isLoggedIn => _user != null;
}

View File

@@ -0,0 +1,33 @@
import 'package:flutter/material.dart';
import 'package:intl_phone_field/intl_phone_field.dart';
class PhoneInputScreen extends StatelessWidget {
const PhoneInputScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Enter Phone Number')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
IntlPhoneField(
decoration: const InputDecoration(
labelText: 'Phone Number',
border: OutlineInputBorder(borderSide: BorderSide()),
),
initialCountryCode: 'US',
onChanged: (phone) {
// TODO: Handle phone number changes
},
),
const SizedBox(height: 20),
ElevatedButton(onPressed: () {}, child: const Text('Send OTP')),
],
),
),
);
}
}

View File

@@ -0,0 +1,35 @@
import 'package:flutter/material.dart';
import 'package:pinput/pinput.dart';
class SmsVerificationScreen extends StatelessWidget {
const SmsVerificationScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('SMS Verification')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'Enter the 6-digit code sent to you',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16),
),
const SizedBox(height: 20),
Pinput(
length: 6,
onCompleted: (pin) {
// TODO: Handle OTP completion
},
),
const SizedBox(height: 20),
ElevatedButton(onPressed: () {}, child: const Text('Verify')),
],
),
),
);
}
}

9
lib/main.dart Normal file
View File

@@ -0,0 +1,9 @@
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:phone_login/app.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const App());
}