First of all thanks for your time. I'm trying to add a two option login in my app. One for a doctor and one for patient. I achieved to store both of them in realtime database as you can see below.
patient / doctor --> realtime database
As you can see, i have one tag ("isDoctor") with true o false for distinguish between both users. Wat i want to is to check the value of this "isDoctor" tag to send the user to the corresponding activity. If isDoctor is true i want to send the user to Doctor activity and if is a patient to the corresponding one. Is thinks that this checking should go in "State.Succes" once the user is sign in but i don't know how to perform it.
Here is my login code from RemoteDataSource class and from the login activity. I am using mvvm with flow for this project.
mBinding.btnLogin.setOnClickListener {
if (areFieldsReady()) {
lifecycleScope.launchWhenStarted {
loginViewModel.login(email, password).collect { loginResult ->
when (loginResult) {
is State.Loading -> {
if (loginResult.flag == true) loadingDialog.startLoading()
}
is State.Succes -> {
loadingDialog.stopLoading()
Snackbar.make(
mBinding.root,
loginResult.data.toString(),
Snackbar.LENGTH_SHORT
).show()
}
is State.Failed -> {
loadingDialog.stopLoading()
Snackbar.make(
mBinding.root,
loginResult.error,
Snackbar.LENGTH_SHORT
).show()
}
}
}
}
}
}
fun login(email: String, password: String): Flow<State<Any>> = flow<State<Any>> {
emit(State.loading(true))
val auth = Firebase.auth
val data = auth.signInWithEmailAndPassword(email, password).await()
//if the task was performend in backend
data?.let {
if (auth.currentUser?.isEmailVerified!!) {
emit(State.succes(R.string.login_succes)) //emiting the class directly by using the function
} else {
auth.currentUser?.sendEmailVerification()?.await()
emit(State.failed(R.string.verify_email_first.toString()))
}
}
}.catch {
emit(State.failed(it.message!!))
}.flowOn(Dispatchers.IO)
Of course before the login I have a "sing up" method for this propuse. I don't added here because i thinks it is not adding more information about the code and question
CodePudding user response:
Since the "doctors" and the "patients" nodes exist in a different hierarchy in your database, you cannot perform a query to filter them. The queries in the Realtime Database work on a flat list of nodes, where the value on which you want to perform the filter must be at a fixed path under each direct child node. That being said, you should use a simpler database schema that can allow you to perform the desired query.
Please note that we are structuring a Realtime Database database according to the queries that we want to perform. Since both doctors and patients can be considered users of your app, and since you already differentiate them using the boolean field "doctor", then there is no need to create two different nodes inside your database. So a simpler solution for structuring such a schema would be:
Firebase-root
|
--- users
|
--- $uid
| |
| --- doctor: true
| |
| --- email: "[email protected]"
|
--- $uid
|
--- doctor: false
|
--- email: "[email protected]"
So to be able to redirect a user to the corresponding activity, inside your State.Succes
you should use the following lines of code:
val uid = FirebaseAuth.getInstance().currentUser?.uid
val db = FirebaseDatabase.getInstance().reference
val uidRef = db.child("users").child(uid)
val valueEventListener = object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
val doctor = snapshot.child("doctor").getValue(Boolean.class)
if(doctor) {
startActivity(Intent(context, DoctorActivity::class.java));
} else () {
startActivity(Intent(context, PatientActivity::class.java));
}
}
override fun onCancelled(databaseError: error) {
Log.d("TAG", error.getMessage()) //Don't ignore potential errors!
}
}
uidRef.addListenerForSingleValueEvent(valueEventListener)