Implemented Login Feature

This commit is contained in:
mohamedkaif356
2023-07-07 15:26:11 +05:30
parent 90fd3a1e12
commit e74a69662e
20 changed files with 1840 additions and 77 deletions

5
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,5 @@
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

1496
Login_Feature.patch Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -43,7 +43,7 @@ class UserListOfflineAdapter(private val view: View) : RecyclerView.Adapter<User
holder.binding.apply {
userName.text = userList.name
userId.text = userList._id
Glide.with(view).load(userList.userImage).into(userImage)
Glide.with(view).load(userList.userImageURL).into(userImage)
}
}
}

View File

@@ -29,7 +29,7 @@ class UserListOnlineAdapter(options: FirestoreRecyclerOptions<UserData>, private
holder.binding.apply {
userName.text = model.name
userId.text = model._id
Glide.with(view).load(model.userImage).into(userImage)
Glide.with(view).load(model.userImageURL).into(userImage)
}
}
}

View File

@@ -1,27 +0,0 @@
package com.example.hposregistration.dao
import androidx.room.TypeConverter
import com.example.hposregistration.data.user.UserData
import com.google.gson.Gson
class Converters {
private val gson = Gson()
@TypeConverter
fun fromString(value: String?): UserData.Location? {
return if (value != null) {
gson.fromJson(value, UserData.Location::class.java)
} else {
null
}
}
@TypeConverter
fun toString(location: UserData.Location?): String? {
return if (location != null) {
gson.toJson(location)
} else {
null
}
}
}

View File

@@ -6,7 +6,6 @@ import androidx.room.TypeConverters
import com.example.hposregistration.data.user.UserData
@Database(entities = [UserData::class], version = 1, exportSchema = false)
@TypeConverters(Converters::class)
abstract class MyDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}

View File

@@ -18,4 +18,26 @@ object Constant {
UserData.Gender.OTHER
}
}
const val USER_ID = "usernameId"
val STATICID = listOf(
"SMIREG1",
"SMIREG2",
"SMIREG3",
"SMIREG4",
"SMIREG5",
"SMIREG6",
"SMIREG7",
"SMIREG8",
"SMIREG9",
"SMIREG10",
"SMIREG11",
"SMIREG12",
"SMIREG13",
"SMIREG14",
"SMIREG15"
)
const val password = "SMI@12345"
}

View File

@@ -7,8 +7,8 @@ import androidx.room.PrimaryKey
data class UserData(
@PrimaryKey
var _id: String = "",
var AbhaId: String = "",
var AadharId: String = "",
var abhaId: String = "",
var aadharId: String = "",
var name: String = "",
var birthYear: String = "",
var gender: String = "",
@@ -26,25 +26,14 @@ data class UserData(
var isUnderMedication: Boolean? = false,
var isUnderTransfusion: Boolean? = false,
var sickleCellHistory: String? = "",
var userImage: String = "",
var location: Location? = null,
var uploadTime: String? = "",
var testStatus: Boolean? = false,
var mobileId: String = "",
var deviceId: String = "",
var kitSerial: String = "",
var csvPath: String = "",
var reportPath: String = "",
var CenterName: String = ""
var userImageURL: String = "",
var createdBy: String? = "",
var createdAt: String? = "",
var registrationCenterName: String? = "",
){
enum class Gender {
MALE,
FEMALE,
OTHER
}
data class Location(
var latitude: Double? = null,
var longitude: Double? = null
)
}

View File

@@ -0,0 +1,92 @@
package com.example.hposregistration.ui.fragments
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.example.hposregistration.data.Constant
import `in`.sminnovations.hposregistration.R
import `in`.sminnovations.hposregistration.databinding.FragmentLoginBinding
class LoginFragment : Fragment() {
private var _binding: FragmentLoginBinding? = null
private val binding get() = _binding!!
private lateinit var sharedPreference: SharedPreferences
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentLoginBinding.inflate(inflater, container, false)
sharedPreference = requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
init()
}
private fun init() {
if (isUserLoggedIn()) {
navigateToUserListFragment()
return
}
binding.btnLogin.setOnClickListener {
val loginId = binding.loginId.text.toString()
val password = binding.password.text.toString()
if (loginId.isNotBlank() && password.isNotBlank()) {
performLogin(loginId, password)
} else {
if (loginId.isBlank()) {
binding.loginId.error = "Please enter a proper Login ID"
}
if (password.isBlank()) {
binding.password.error = "Please enter a proper password"
}
}
}
}
private fun isUserLoggedIn(): Boolean {
return sharedPreference.getString(Constant.USER_ID, "")?.isNotBlank() == true
}
private fun navigateToUserListFragment() {
findNavController().navigate(R.id.action_loginFragment_to_userListFragment)
}
private fun performLogin(loginId: String, password: String) {
val matchingId = Constant.STATICID.firstOrNull { it == loginId }
if (matchingId != null) {
if (password == Constant.password) {
saveUserId(loginId)
navigateToUserListFragment()
return
} else {
Toast.makeText(requireContext(), "Wrong Password", Toast.LENGTH_SHORT).show()
}
}
Toast.makeText(requireContext(), "Wrong UserID", Toast.LENGTH_SHORT).show()
}
private fun saveUserId(userId: String) {
with(sharedPreference.edit()) {
putString(Constant.USER_ID, userId)
apply()
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

View File

@@ -65,26 +65,26 @@ class AbhaRegistrationFragment : BaseFragment() {
viewModel.userData.observe(viewLifecycleOwner) { user ->
userData = user
with(binding) {
aadharID.setText(user.AadharId)
etAbhaId.setText(user.AbhaId)
aadharID.setText(user.aadharId)
etAbhaId.setText(user.abhaId)
etName.setText(user.name)
centerName.setText(user.CenterName)
centerName.setText(user.registrationCenterName)
}
}
binding.btnProceed.setOnClickListener {
val abhaId = binding.etAbhaId.text.toString()
val abhaIdInput = binding.etAbhaId.text.toString()
val userName = binding.etName.text.toString()
val aadharId = binding.aadharID.text.toString()
val aadharIdInput = binding.aadharID.text.toString()
val centerName = binding.centerName.text.toString()
if (validateInputs(abhaId, aadharId, userName, centerName)) {
if (validateInputs(abhaIdInput, aadharIdInput, userName, centerName)) {
userData.apply {
name = userName
AadharId = aadharId
AbhaId = abhaId
CenterName = centerName
aadharId = aadharIdInput
abhaId = abhaIdInput
registrationCenterName = centerName
_id = aadharId + userName.substring(0, 3).uppercase() + centerName.substring(0, 3).uppercase()
}
@@ -100,7 +100,7 @@ class AbhaRegistrationFragment : BaseFragment() {
val obj = JSONObject(contents)
userData.apply {
AbhaId = obj.getString("hidn").replace("-", "")
abhaId = obj.getString("hidn").replace("-", "")
name = obj.getString("name")
birthYear = obj.getString("dob").fetchYOBFromDOB().toString()
gender = obj.getString("gender").mapToGender().toString()
@@ -111,7 +111,7 @@ class AbhaRegistrationFragment : BaseFragment() {
house = obj.getString("address")
}
if (userData.AbhaId.isNotEmpty()) {
if (userData.abhaId.isNotEmpty()) {
saveUserDataAsPerAbhaId()
} else {
saveUserDataAsPerAadharId()
@@ -144,7 +144,7 @@ class AbhaRegistrationFragment : BaseFragment() {
with(binding) {
tvScanMessage.visibility = View.VISIBLE
tvScanMessage.text = "You have scanned the Abha ID, need to enter Aadhar ID manually"
etAbhaId.setText(userData.AbhaId)
etAbhaId.setText(userData.abhaId)
etName.setText(userData.name)
}
Toast.makeText(

View File

@@ -70,8 +70,8 @@ class CaptureUserImageFragment : Fragment() {
viewModel.getUserByID(args.userId)
viewModel.userData.observe(viewLifecycleOwner) { user ->
userData = user
if (userData.userImage.isNotEmpty()) {
binding.userImage.loadImageFromUri(Uri.parse(user.userImage))
if (userData.userImageURL.isNotEmpty()) {
binding.userImage.loadImageFromUri(Uri.parse(user.userImageURL))
binding.btnSubmit.isEnabled = true
binding.btnSubmit.setOnClickListener {
navigate()
@@ -122,7 +122,7 @@ class CaptureUserImageFragment : Fragment() {
}
private fun submitImage(uri: Uri) {
userData.userImage = uri.toString()
userData.userImageURL = uri.toString()
viewModel.insert(userData)
navigate()
}

View File

@@ -1,5 +1,7 @@
package com.example.hposregistration.ui.fragments.registration
import android.content.Context
import android.content.SharedPreferences
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
@@ -10,18 +12,23 @@ import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.bumptech.glide.Glide
import com.example.hposregistration.data.Constant
import com.example.hposregistration.data.user.UserData
import com.example.hposregistration.ui.fragments.BaseFragment
import com.example.hposregistration.ui.viewmodels.RegistrationViewModel
import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hposregistration.R
import `in`.sminnovations.hposregistration.databinding.FragmentReviewDetailsRegistrationBinding
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
@AndroidEntryPoint
class ReviewDetailsRegistrationFragment : BaseFragment() {
private var _binding: FragmentReviewDetailsRegistrationBinding? = null
private val binding get() = _binding!!
private lateinit var sharedPreference: SharedPreferences
private val viewModel by viewModels<RegistrationViewModel>()
private val args: ReviewDetailsRegistrationFragmentArgs by navArgs()
@@ -32,6 +39,8 @@ class ReviewDetailsRegistrationFragment : BaseFragment() {
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
_binding = FragmentReviewDetailsRegistrationBinding.inflate(inflater, container, false)
sharedPreference =
requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
return binding.root
}
@@ -75,26 +84,33 @@ class ReviewDetailsRegistrationFragment : BaseFragment() {
viewModel.fireBaseUpload.observe(viewLifecycleOwner) {
if (it == "Success") {
Toast.makeText(requireContext(), "Registration Done Successfully", Toast.LENGTH_SHORT)
.show()
Toast.makeText(
requireContext(),
"Registration Done Successfully",
Toast.LENGTH_SHORT
).show()
navigateToUserListFragment()
}
}
}
private fun addDataToFirebase() {
userData.createdAt = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time)
userData.createdBy = sharedPreference.getString(Constant.USER_ID, "")
viewModel.addUserToDatabase(userData)
viewModel.deleteById(args.userId)
}
private fun setUserData(userData: UserData) {
with(binding) {
Glide.with(requireActivity()).load(Uri.parse(userData.userImage)).into(userImage)
Glide.with(requireActivity()).load(Uri.parse(userData.userImageURL)).into(userImage)
binding.tvUserID.text = requireContext().getString(R.string.user_id, userData._id)
binding.tvAbhaId.text =
requireContext().getString(R.string.abha_number, userData.AbhaId)
requireContext().getString(R.string.abha_number, userData.abhaId)
binding.tvAadharId.text =
requireContext().getString(R.string.aadhar_number_details, userData.AadharId)
requireContext().getString(R.string.aadhar_number_details, userData.aadharId)
binding.tvUserName.text = requireContext().getString(R.string.user_name, userData.name)
binding.tvBirthYear.text =
requireContext().getString(R.string.birth_year_details, userData.birthYear)
@@ -121,7 +137,7 @@ class ReviewDetailsRegistrationFragment : BaseFragment() {
binding.tvPincode.text =
requireContext().getString(R.string.pincode_details, userData.pinCode)
binding.centerName.text =
requireContext().getString(R.string.centre_name, userData.CenterName)
requireContext().getString(R.string.centre_name, userData.registrationCenterName)
if (userData.isUnderMedication!!) {
binding.tvIsUnderMedication.text = requireContext().getString(
R.string.is_patient_under_any_medication_details, "Yes"

View File

@@ -28,7 +28,7 @@ class RegistrationViewModel @Inject constructor(
val fireBaseUpload = MutableLiveData<String>()
fun addUserToDatabase(userData: UserData) = viewModelScope.launch {
val file = Uri.parse(userData.userImage)
val file = Uri.parse(userData.userImageURL)
val storageRef = FirebaseStorage.getInstance().reference
val imageRef = storageRef.child("${userData._id}/${file.lastPathSegment}")
@@ -39,7 +39,7 @@ class RegistrationViewModel @Inject constructor(
}
imageRef.downloadUrl
}.addOnSuccessListener { uri ->
userData.userImage = uri.toString()
userData.userImageURL = uri.toString()
addDataToFirebase(userData)
}.addOnFailureListener { exception ->

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.fragments.registration.AbhaRegistrationFragment">
tools:context="com.example.hposregistration.ui.fragments.registration.AbhaRegistrationFragment">
<ScrollView
android:layout_width="match_parent"

View File

@@ -0,0 +1,145 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="com.example.hposregistration.ui.fragments.LoginFragment">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
<TextView
android:id="@+id/tv_title"
style="@style/title1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/login"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/imageView"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/smi_logo"
android:layout_marginTop="24dp"
app:layout_constraintEnd_toStartOf="@id/imageView2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_title" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="24dp"
android:src="@drawable/sickle_cell_gov_logo"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView"
app:layout_constraintTop_toBottomOf="@+id/tv_title" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/et_aadharID"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/loginId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/login_id"
android:inputType="textCapCharacters"
android:maxLength="12" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/et_centerName"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/et_aadharID">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/password"
android:inputType="text"
android:maxLength="12" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/btnLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/login"
app:cornerRadius="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/et_centerName" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/errorMessageCL"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#80000000"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<include
android:id="@+id/itemErrorMessage"
layout="@layout/item_error_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/progressBarCL"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#80000000"
android:visibility="gone">
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateDrawable="@drawable/progressbar_costume_view"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -3,7 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_nav_graph"
app:startDestination="@id/userListFragment">
app:startDestination="@id/loginFragment">
<fragment
android:id="@+id/registrationFragment"
@@ -26,6 +26,11 @@
<action
android:id="@+id/action_userListFragment_to_registrationFragment"
app:destination="@id/registrationFragment" />
<action
android:id="@+id/action_userListFragment_to_loginFragment"
app:destination="@id/loginFragment"
app:popUpTo="@id/main_nav_graph"
app:popUpToInclusive="true"/>
</fragment>
<fragment
android:id="@+id/profileFragment"
@@ -76,4 +81,16 @@
app:argType="string"
android:defaultValue="null" />
</fragment>
<fragment
android:id="@+id/loginFragment"
android:name="com.example.hposregistration.ui.fragments.LoginFragment"
android:label="fragment_login"
tools:layout="@layout/fragment_login" >
<action
android:id="@+id/action_loginFragment_to_userListFragment"
app:destination="@id/userListFragment"
app:popUpTo="@id/main_nav_graph"
app:popUpToInclusive="true"/>
</fragment>
</navigation>

View File

@@ -78,6 +78,9 @@
<string name="is_any_sickle">Is Any Sickle cell History: %1$s</string>
<string name="sickle_cell_family_history">Sickle cell Family History: %1$s</string>
<string name="center_name">Center Name</string>
<string name="login_id">Login ID</string>
<string name="password">Password</string>
<string name="login">Login</string>
<string-array name="category">