Skip to content

Commit 82721e5

Browse files
committed
Feat : Added login button and google sign in button
1 parent 227ea5a commit 82721e5

File tree

14 files changed

+406
-24
lines changed

14 files changed

+406
-24
lines changed

lib/features/assets/googleimg.jpg

16.2 KB
Loading

lib/features/auth/data/firebase_auth_repo.dart

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import 'package:azt/features/auth/domain/entities/app_user.dart';
22
import 'package:azt/features/auth/domain/repos/auth_repo.dart';
33
import 'package:firebase_auth/firebase_auth.dart';
4+
import 'package:google_sign_in/google_sign_in.dart';
5+
6+
47

58
class FirebaseAuthRepo implements AuthRepo{
69
//firebase access
@@ -99,13 +102,38 @@ class FirebaseAuthRepo implements AuthRepo{
99102
Future<String> sendPasswordResetEmail(String email) async {
100103
try{
101104
await firebaseAuth.sendPasswordResetEmail(email: email);
102-
return 'Password reset email sent!';
105+
return "Password reset email sent!";
103106
}
104107
catch(e){
105-
return 'An error occured: $e';
108+
return "An error occured: $e";
106109
}
107110
}
111+
112+
@override
113+
Future<AppUser?> signInWithGoogle() async {
114+
try {
115+
// Begin the interactive sign-in process - V7 CHANGE: use signInWithProvider
116+
final UserCredential userCredential =
117+
await FirebaseAuth.instance.signInWithProvider(GoogleAuthProvider());
108118

119+
// user cancelled sign-in
120+
if (userCredential.user == null) return null;
109121

122+
// firebase user
123+
final firebaseUser = userCredential.user;
110124

125+
// user cancelled sign-in process
126+
if (firebaseUser == null) return null;
127+
128+
AppUser appUser = AppUser(
129+
uid: firebaseUser.uid,
130+
email: firebaseUser.email ?? '',
131+
);
132+
133+
return appUser;
134+
} catch (e) {
135+
print(e);
136+
return null;
137+
}
138+
}
111139
}

lib/features/auth/domain/repos/auth_repo.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ abstract class AuthRepo {
88
Future<AppUser?> getCurrentUser();
99
Future<String> sendPasswordResetEmail(String email);
1010
Future<void> deleteAccount();
11-
11+
Future<AppUser?> signInWithGoogle();
1212
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import 'package:flutter/widgets.dart';
2+
import 'package:flutter/material.dart';
3+
4+
class MyGoogleSignInButton extends StatelessWidget {
5+
final void Function()? onTap;
6+
const MyGoogleSignInButton({super.key, required this.onTap});
7+
8+
@override
9+
Widget build(BuildContext context) {
10+
return GestureDetector(
11+
onTap: onTap,
12+
child: Container(
13+
// Add some padding inside the button
14+
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
15+
decoration: BoxDecoration(
16+
color: Theme.of(context).colorScheme.secondary,
17+
borderRadius: BorderRadius.circular(12),
18+
), // BoxDecoration
19+
child: Row(
20+
mainAxisAlignment: MainAxisAlignment.center, // Center the content
21+
children: [
22+
// Your original image
23+
Image.asset(
24+
'lib/features/assets/googleimg.jpg',
25+
height: 30,
26+
), // Image.asset
27+
28+
// Add space between image and text
29+
const SizedBox(width: 12),
30+
31+
// Your new text
32+
const Text(
33+
"Sign In Using Google",
34+
style: TextStyle(
35+
fontWeight: FontWeight.bold,
36+
fontSize: 16,
37+
),
38+
),
39+
],
40+
), // Row
41+
), // Container
42+
); // GestureDetector
43+
}
44+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import 'package:flutter/material.dart';
2+
3+
class LoadingScreen extends StatelessWidget {
4+
const LoadingScreen({super.key});
5+
6+
@override
7+
Widget build(BuildContext context) {
8+
return const Scaffold(
9+
body: Center(
10+
child: CircularProgressIndicator(),
11+
),
12+
);
13+
}
14+
}

lib/features/auth/presentation/cubits/auth_cubit.dart

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,23 @@ class AuthCubit extends Cubit<AuthState>{
9898
emit(Unauthenticated());
9999
}
100100
}
101-
}
101+
102+
//google sign in
103+
Future<void> signInWithGoogle() async{
104+
try{
105+
emit(AuthLoading());
106+
final user = await authRepo.signInWithGoogle();
107+
108+
if (user != null){
109+
_currentUser = user;
110+
emit(Authenticated(user));
111+
} else{
112+
emit(Unauthenticated());
113+
}
114+
}
115+
catch(e){
116+
emit(AuthError(e.toString()));
117+
emit(Unauthenticated());
118+
}
119+
}
120+
}

lib/features/auth/presentation/pages/login_page.dart

Lines changed: 109 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ if logged in, go to homepage
55
no account, go to register page
66
*/
77

8+
import 'package:azt/features/auth/presentation/components/google_sign_in_button.dart';
89
import 'package:azt/features/auth/presentation/components/my_button.dart';
910
import 'package:azt/features/auth/presentation/components/my_textfield.dart';
11+
import 'package:azt/features/auth/presentation/cubits/auth_cubit.dart';
1012
import 'package:flutter/material.dart';
13+
import 'package:flutter_bloc/flutter_bloc.dart';
1114

1215
class LoginPage extends StatefulWidget {
1316
final void Function()? togglePages;
@@ -22,6 +25,62 @@ class _LoginPageState extends State<LoginPage> {
2225
//text controller
2326
final emailController = TextEditingController();
2427
final pwController = TextEditingController();
28+
29+
//auth cubit
30+
late final authCubit = context.read<AuthCubit>();
31+
32+
//LOGIN button pressed
33+
void login(){
34+
//prepare email and password
35+
final String email = emailController.text;
36+
final String pw = pwController.text;
37+
38+
//ensure fields are filled
39+
if (email.isNotEmpty && pw.isNotEmpty){
40+
authCubit.login(email, pw);
41+
}
42+
43+
//fields are empty
44+
else{
45+
ScaffoldMessenger.of(context).showSnackBar(
46+
const SnackBar(content: Text("Please Enter Both Email and Password!")));
47+
}
48+
}
49+
void openForgotPasswordBox(){
50+
showDialog(
51+
context: context,
52+
builder: (context)=> AlertDialog(
53+
title: Text("Forgot Password"),
54+
content: MyTextField(
55+
controller: emailController, hintText: "Enter email", obscureText: false
56+
),
57+
actions: [
58+
//cancel button
59+
TextButton(
60+
onPressed: ()=>Navigator.pop(context),
61+
child: const Text("Cancel"),
62+
),
63+
64+
//reset button
65+
TextButton(
66+
onPressed: () async {
67+
String message = await authCubit.forgotPassword(emailController.text);
68+
if (message == "Password reset email sent!"){
69+
Navigator.pop(context);
70+
emailController.clear();
71+
}
72+
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message)));
73+
},
74+
75+
child: const Text("Reset"),
76+
),
77+
]
78+
),
79+
);
80+
}
81+
82+
83+
//BUILD UI
2584
@override
2685
Widget build(BuildContext context) {
2786

@@ -64,30 +123,70 @@ class _LoginPageState extends State<LoginPage> {
64123

65124
//password
66125
MyTextField(controller: pwController, hintText: "Password", obscureText: true),
67-
126+
127+
const SizedBox(height:10),
128+
68129
//forgot pass
69130
Row(
70131
mainAxisAlignment: MainAxisAlignment.center,
71132
children: [
72-
Text(
73-
"Forgot Password?",
74-
style: TextStyle(
75-
color: Theme.of(context).colorScheme.primary,
76-
fontWeight: FontWeight.bold,
77-
)
78-
133+
GestureDetector(
134+
onTap: ()=> openForgotPasswordBox(),
135+
child: Text(
136+
"Forgot Password?",
137+
style: TextStyle(
138+
color: Theme.of(context).colorScheme.primary,
139+
fontWeight: FontWeight.bold,
140+
)
141+
142+
),
79143
),
80144
],
81145
),
82146

83-
const SizedBox(height: 25),
147+
const SizedBox(height: 10),
84148

85149
//login
86150
MyButton(
87-
onTap: () {},
151+
onTap: login,
88152
text: "Login",
89153
),
90154

155+
const SizedBox(height: 10),
156+
157+
Row(
158+
children: [
159+
Expanded(
160+
child: Divider(
161+
color: Theme.of(context).colorScheme.tertiary,
162+
),
163+
),
164+
Text("Or sign in with"),
165+
Expanded(
166+
child: Divider(
167+
color: Theme.of(context).colorScheme.tertiary,
168+
),
169+
),
170+
],
171+
),
172+
173+
const SizedBox(height: 15),
174+
175+
176+
// oauth using google
177+
Row(
178+
mainAxisAlignment: MainAxisAlignment.center,
179+
children: [
180+
//google button
181+
MyGoogleSignInButton(
182+
onTap: () {},
183+
)
184+
185+
],
186+
),
187+
188+
const SizedBox(height: 25),
189+
91190
//dont have acc sign in later
92191
Row(
93192
mainAxisAlignment:MainAxisAlignment.center,

lib/features/auth/presentation/pages/register_page.dart

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import 'package:azt/features/auth/presentation/components/my_button.dart';
22
import 'package:azt/features/auth/presentation/components/my_textfield.dart';
3+
import 'package:azt/features/auth/presentation/cubits/auth_cubit.dart';
34
import 'package:flutter/material.dart';
5+
import 'package:flutter_bloc/flutter_bloc.dart';
46

57
class RegisterPage extends StatefulWidget {
68
final void Function()? togglePages;
@@ -16,6 +18,50 @@ class _RegisterPageState extends State<RegisterPage> {
1618
final pwController = TextEditingController();
1719
final confirmPwController = TextEditingController();
1820
final nameController = TextEditingController();
21+
22+
//register button pressed
23+
void register(){
24+
//prepare information to store
25+
final String name = nameController.text;
26+
final String email = emailController.text;
27+
final String pw = pwController.text;
28+
final String confirmPw = confirmPwController.text;
29+
30+
//auth cubit
31+
final authCubit = context.read<AuthCubit>();
32+
33+
//ensure fields entered arent empty
34+
if (email.isNotEmpty && name.isNotEmpty && pw.isNotEmpty && confirmPw.isNotEmpty){
35+
36+
//pw matches confirmpw
37+
if(pw == confirmPw){
38+
authCubit.register(name, email, pw); //registers user
39+
}
40+
41+
//pw doesnt match
42+
else{
43+
ScaffoldMessenger.of(context).showSnackBar(
44+
const SnackBar(content: Text("Passwords do not match!!")));
45+
}
46+
}
47+
//fields are empty
48+
else{
49+
ScaffoldMessenger.of(context).showSnackBar(
50+
const SnackBar(content: Text("Please enter all Fields!")));
51+
}
52+
}
53+
54+
//dispose memory controllers
55+
@override
56+
void dispose() {
57+
nameController.dispose();
58+
emailController.dispose();
59+
pwController.dispose();
60+
confirmPwController.dispose();
61+
super.dispose();
62+
}
63+
64+
//build ui
1965
@override
2066
Widget build(BuildContext context) {
2167

@@ -73,7 +119,7 @@ class _RegisterPageState extends State<RegisterPage> {
73119

74120
//register button
75121
MyButton(
76-
onTap: () {},
122+
onTap: register,
77123
text: "Sign Up",
78124
),
79125

0 commit comments

Comments
 (0)