Reputation: 29
This is my first stack overflow post so please bare with me and give me constructive criticism when needed.
I'm developing an app that needs to have two separate account types, a student account type and a counselor account type. I decided to use a custom claim code to differentiate the two account types. I made an it so that user account settings are present on the firestore database, and I'm trying to make it so that when I click a button in the registration screen it'll set a boolean value to true. I try to call the returnCounselor function in another authentification class, but I receive this error. "The method 'returnCounselor' isn't defined for the type 'Register'."
For further background In the class where I have authentification set up I call a function that takes in two parameters the name of the user and the state of the counselor variable and that is where I have the counselor variable input.
I've tried to have the button set the state of the counselor variable within the authentification class but apparently I can set the state of a viable unless it's in a stateful widget. Here is my code
//database class
import 'package:cloud_firestore/cloud_firestore.dart';
class DatabaseService {
final String uid;
DatabaseService({this.uid});
//collection reference
final CollectionReference userCollection = Firestore.instance.collection('User Data');
Future updateUserData(String name, bool counselor) async {
return await userCollection.document(uid).setData({
'name': name,
'Counselor': true,
});
}
}
//register class stful widget
import 'package:flutter/material.dart';
import 'package:strength_together/services/auth.dart';
import 'package:strength_together/shared/constants.dart';
import 'package:strength_together/shared/loading.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:strength_together/models/user.dart';
import 'package:strength_together/services/database.dart';
import 'package:strength_together/services/auth.dart';
class Register extends StatefulWidget {
final Function toggleView;
Register({this.toggleView });
@override
_RegisterState createState() => _RegisterState();
}
class _RegisterState extends State<Register> {
final AuthService _auth = AuthService();
final _formKey = GlobalKey<FormState>();
bool loading = false;
//text field state
String email = '';
String password = '';
String error = '';
//set counselor state
//setCounselor(){
//counselor = true;
//}
bool counselor = false;
bool returnCounselor(){
return counselor;
}
@override
Widget build(BuildContext context) {
return loading ? Loading() : Scaffold(
backgroundColor: Colors.grey[900],
appBar: AppBar(
backgroundColor: Colors.black,
elevation: 0.0,
title: Text(
'Sign up to Strength Together',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.yellow,
),
),
actions: <Widget>[
FlatButton.icon(
icon: Icon(
Icons.person,
color: Colors.yellow,
),
label: Text(
'Sign in',
style: TextStyle(
color: Colors.yellow,
),
),
onPressed: () {
widget.toggleView();
}
)
],
),
body: Container(
padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 50.0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
SizedBox(height: 20.0,),
TextFormField(
decoration: textInputDecoration.copyWith(hintText: 'Email'),
validator: (val) => val.isEmpty ? 'Enter an email': null,
onChanged: (val){
setState(() => email = val);
},
),
SizedBox(height: 20.0),
TextFormField(
decoration: textInputDecoration.copyWith(hintText: 'Password'),
validator: (val) => val.length < 6 ? 'Enter a password 6+ chars long': null,
obscureText: true,
onChanged: (val){
setState(() => password = val);
},
),
SizedBox(height: 20.0),
RaisedButton(
color: Colors.black,
child: Text(
'Register',
style: TextStyle(color: Colors.yellow),
),
onPressed: () async{
if(_formKey.currentState.validate()){
setState(() => loading = true);
dynamic result = await _auth.registerWithEmailAndPassword(email, password);
if(result == null){
setState(() {
error = 'Please supply a valid email';
loading = false;
});
}
}
}
),
SizedBox(height:12.0),
Text(
error,
style: TextStyle(color: Colors.red, fontSize: 14.0),
),
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () async{
counselor = true;
//setCounselor();
},
),
);
}
}
//authentification class
import 'package:firebase_auth/firebase_auth.dart';
import 'package:strength_together/Screens/authenticate/register.dart';
import 'package:strength_together/models/user.dart';
import 'package:strength_together/services/database.dart';
import 'package:flutter/material.dart';
class AuthService{
final FirebaseAuth _auth = FirebaseAuth.instance;
//instance of couns
bool counselor = Register().returnCounselor();
//bool counselor = false;
//setCounselor(){
//counselor = true;
//}
//create user obj based on firebase user
User _userFromFirebaseUser(FirebaseUser user){
return user != null ? User(uid: user.uid) : null;
}
//auth change user stream
Stream<User> get user {
return _auth.onAuthStateChanged
.map(_userFromFirebaseUser);
}
//method to sign in anon
Future signInAnon() async{
try{
AuthResult result = await _auth.signInAnonymously();
FirebaseUser user = result.user;
return _userFromFirebaseUser(user);
}catch(e){
print(e.toString());
return null;
}
}
//method to sign in with email/pass
Future signInWithEmailAndPassword(String email, String password) async{
try{
AuthResult result = await _auth.signInWithEmailAndPassword(email: email, password: password);
FirebaseUser user = result.user;
return _userFromFirebaseUser(user);
}catch(e){
print(e.toString());
return null;
}
}
//method to register with email/pass
Future registerWithEmailAndPassword(String email, String password) async{
try{
AuthResult result = await _auth.createUserWithEmailAndPassword(email: email, password: password);
FirebaseUser user = result.user;
//create a new document for that user with the uid
await DatabaseService(uid: user.uid).updateUserData('New user', counselor);
return _userFromFirebaseUser(user);
}catch(e){
print(e.toString());
return null;
}
}
//sign in with google
//sign out
Future signOut() async{
try{
return await _auth.signOut();
}catch(e){
print(e.toString());
return null;
}
}
Upvotes: 2
Views: 2138
Reputation: 671
I would put your get getCounselor method in your AuthService class make the counselor private. Like this:
bool _counselor;
bool get counselor => _counselor;
void setCounselor(bool counselor) {
_counselor = counselor;
}
Then, you can call it in your Register Widget.
_auth.couselor;
_auth.setCounselor;
The best way to handle this is with a ChangeNotifier class and then use Provider to inject it into your Register Class.
class AuthBloc extends ChangeNotifier {
bool _counselor;
String _userName;
String _email;
String _password;
bool get counselor => _counselor;
String get userName => _userName;
void setCounselor(bool counselor) {
_counselor = counselor;
notifyListeners();
}
void setUserName(String userName) {
_userName = userName;
notifyListeners();
}
void setEmail(String email) {
_email = email;
notifyListeners();
}
void setPassword(String password) {
_password = password;
notifyListeners();
}
AuthService _auth = AuthService();
Future<User> signInAnon() async{
return await _auth.signInAnon();
}
Future<User> signInWithEmailAndPassword() async{
_return await _auth.signInWithEmailAndPassword(_email, _password);
}
Future<User> createUserWithEmailAndPassword() async{
_return await _auth.createUserWithEmailAndPassword(_email, _password);
}
}
Then you can put your AuthService and Database Service methods in there too.
In your main.dart file:
ChangeNotifierProvider(
create: (context) => AuthBloc(),
child: MyApp(),
),
Then, in your Register Widget:
Consumer<AuthBloc>(
builder: (context, bloc, child) {
return TextFormField(
decoration: textInputDecoration.copyWith(hintText: 'Password'),
validator: (val) => val.length < 6 ? 'Enter a password 6+ chars long':
null,
obscureText: true,
onChanged: (val){
bloc.setPassword(val);
},
},
);
Just use the Consumer Widget wherever you need access to the bloc.
Upvotes: 2