From dcc7a921a0a71db62c2da465a54631b191127955 Mon Sep 17 00:00:00 2001 From: mohamedkaif356 Date: Tue, 14 Nov 2023 22:58:34 +0530 Subject: [PATCH] Offline Incubation time --- .../data/model/patient/HemoCubeTestData.kt | 2 + .../data/model/patient/UserData.kt | 1 + .../adapter/OfflineUserListAdapter.kt | 121 ++++++++++++++++++ .../presentation/dashboard/HomeFragment.kt | 64 +++++++-- .../hemocube/HemoCubeViewModel.kt | 5 + app/src/main/res/layout/fragment_home.xml | 38 +++++- .../res/layout/offline_user_list_view.xml | 71 ++++++++++ app/src/main/res/values/strings.xml | 4 +- 8 files changed, 287 insertions(+), 19 deletions(-) create mode 100644 app/src/main/java/com/example/hpostesting/presentation/adapter/OfflineUserListAdapter.kt create mode 100644 app/src/main/res/layout/offline_user_list_view.xml diff --git a/app/src/main/java/com/example/hpostesting/data/model/patient/HemoCubeTestData.kt b/app/src/main/java/com/example/hpostesting/data/model/patient/HemoCubeTestData.kt index 5599862..f21af33 100644 --- a/app/src/main/java/com/example/hpostesting/data/model/patient/HemoCubeTestData.kt +++ b/app/src/main/java/com/example/hpostesting/data/model/patient/HemoCubeTestData.kt @@ -8,6 +8,8 @@ data class HemoCubeTestData( @PrimaryKey var _id: String = "", var name: String = "", + var incubationTime: String = "", + var bloodGroup: String = "", var birthYear: String = "", var userImageURL: String = "", var location: UserData.Location? = null, diff --git a/app/src/main/java/com/example/hpostesting/data/model/patient/UserData.kt b/app/src/main/java/com/example/hpostesting/data/model/patient/UserData.kt index 1b6c95d..65d6e88 100644 --- a/app/src/main/java/com/example/hpostesting/data/model/patient/UserData.kt +++ b/app/src/main/java/com/example/hpostesting/data/model/patient/UserData.kt @@ -9,6 +9,7 @@ data class UserData( @PrimaryKey var _id: String = "", var name: String = "", + var bloodGroup: String = "", var incubationTime: String = "", var birthYear: String = "", var userImageURL: String = "", diff --git a/app/src/main/java/com/example/hpostesting/presentation/adapter/OfflineUserListAdapter.kt b/app/src/main/java/com/example/hpostesting/presentation/adapter/OfflineUserListAdapter.kt new file mode 100644 index 0000000..59dc423 --- /dev/null +++ b/app/src/main/java/com/example/hpostesting/presentation/adapter/OfflineUserListAdapter.kt @@ -0,0 +1,121 @@ +package com.example.hpostesting.presentation.adapter + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import androidx.navigation.findNavController +import androidx.recyclerview.widget.AsyncListDiffer +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.RecyclerView +import com.example.hpostesting.data.DataHolder +import com.example.hpostesting.data.model.patient.HemoCubeTestData +import com.example.hpostesting.data.model.patient.UserData +import `in`.sminnovations.hpostesting.R +import `in`.sminnovations.hpostesting.databinding.OfflineUserListViewBinding +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Date +import java.util.Locale + +class OfflineUserListAdapter(private val view: View, private val batLevel: Int) : + RecyclerView.Adapter() { + + inner class OfflineUserListViewHolder(val binding: OfflineUserListViewBinding) : + RecyclerView.ViewHolder(binding.root) + + private val differCallback = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame( + oldItem: HemoCubeTestData, newItem: HemoCubeTestData + ): Boolean { + return oldItem._id == newItem._id + } + + override fun areContentsTheSame( + oldItem: HemoCubeTestData, newItem: HemoCubeTestData + ): Boolean { + return oldItem == newItem + } + } + + val differ = AsyncListDiffer(this, differCallback) + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OfflineUserListViewHolder { + return OfflineUserListViewHolder( + OfflineUserListViewBinding.inflate(LayoutInflater.from(parent.context), parent, false) + ) + } + + override fun getItemCount(): Int { + return differ.currentList.size + } + + override fun onBindViewHolder(holder: OfflineUserListViewHolder, position: Int) { + val userList = differ.currentList[position] + holder.binding.apply { + userID.text = "User ID: ${userList._id}" + bloodGroup.text = "Blood group: ${userList.bloodGroup}" + time.text = "Time: ${userList.incubationTime}" + userCard.setOnClickListener { + if (batLevel < 40) { + Toast.makeText( + view.context, + "Battery level is low than 40%, please charge the device to continue testing", + Toast.LENGTH_SHORT + ).show() + return@setOnClickListener + } + if (userList.testStatus != null) { + if (userList.testStatus!!) { + Toast.makeText( + view.context, + "Test has been already conducted for this user", + Toast.LENGTH_SHORT + ).show() + } else { + if (userList.incubationTime != "") { + if (isBetween15And30Minutes(userList.incubationTime) < 15) { + Toast.makeText( + view.context, + "Incubation has not completed 15 minutes", + Toast.LENGTH_SHORT + ).show() + } else if (isBetween15And30Minutes(userList.incubationTime) > 30) { + Toast.makeText( + view.context, + "Incubation crossed 30 minutes, need to repeat the incubation", + Toast.LENGTH_SHORT + ).show() + } else { + DataHolder.selectedTest = UserData( + _id = userList._id, + bloodGroup = userList.bloodGroup, + incubationTime = userList.incubationTime + ) + view.findNavController() + .navigate(R.id.action_nav_home_to_mainActivity) + } + } else { + Toast.makeText( + view.context, + "Incubation not started for this user", + Toast.LENGTH_SHORT + ).show() + } + } + } + } + } + } + + private fun isBetween15And30Minutes(createdAt: String): Long { + val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()) + val createdAtDate: Date = formatter.parse(createdAt)!! + + val currentTime = Calendar.getInstance().time + + val diffMillis = currentTime.time - createdAtDate.time + + return diffMillis / (60 * 1000) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt index 1a6995f..9c5e2a8 100644 --- a/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt +++ b/app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt @@ -20,6 +20,7 @@ import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.presentation.KitScanActivity +import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter import com.example.hpostesting.presentation.adapter.UserListAdapter import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.testRight.TestRightViewModel @@ -33,6 +34,7 @@ import dagger.hilt.android.AndroidEntryPoint import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding import java.text.SimpleDateFormat +import java.util.Calendar import java.util.Date import java.util.Locale @@ -43,7 +45,9 @@ class HomeFragment : Fragment() { private val viewModel: TestRightViewModel by activityViewModels() private val hemoCubeViewModel: HemoCubeViewModel by activityViewModels() private lateinit var rvAdapter: UserListAdapter - private var batLevel: Int = 0 // Initialize with a default value, or obtain the actual battery level + private var batLevel: Int = + 0 // Initialize with a default value, or obtain the actual battery level + private lateinit var adapter: OfflineUserListAdapter private lateinit var sharedPreference: SharedPreferences @@ -73,6 +77,19 @@ class HomeFragment : Fragment() { } hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData -> deleteHemoCubeIncompleteRegistrations(userData) + if (userData.isNotEmpty()) { + val userList = mutableListOf() + userData.forEach { + if (it.testStatus == false) { + userList.add(it) + } + } + val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager + val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) + adapter = OfflineUserListAdapter(binding.root, batLevel) + adapter.differ.submitList(userList) + binding.rvOrderOffline.adapter = adapter + } } viewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isConnected -> if (isConnected) { @@ -120,10 +137,18 @@ class HomeFragment : Fragment() { private fun setUserId() { binding.btnSubmit.setOnClickListener { val userId = binding.userId.text.toString() - if (userId.length >= 18) { - val userData = UserData(_id = userId) - DataHolder.selectedTest = userData - findNavController().navigate(R.id.action_nav_home_to_mainActivity) + val bloodGroup = binding.etBloodGroup.text + if (userId.length >= 18 && !bloodGroup.equals("Select Blood Group") || !bloodGroup.isNullOrBlank()) { + hemoCubeViewModel.addUser( + HemoCubeTestData( + _id = userId, bloodGroup = bloodGroup.toString(), incubationTime = SimpleDateFormat( + "yyyy-MM-dd HH:mm:ss", Locale.getDefault() + ).format(Calendar.getInstance().time).toString() + ) + ) +// val userData = UserData(_id = userId) +// DataHolder.selectedTest = userData +// findNavController().navigate(R.id.action_nav_home_to_mainActivity) } else { val errorMessage = getString(R.string.user_id_error_message) Toast.makeText(requireContext(), errorMessage, Toast.LENGTH_SHORT).show() @@ -155,10 +180,12 @@ class HomeFragment : Fragment() { val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) - rvAdapter = view?.let { - UserListAdapter(requireContext(), hemoCubeViewModel, recyclerViewOptions, - it, batLevel, requireActivity()) - }!! + rvAdapter = view?.let { + UserListAdapter( + requireContext(), hemoCubeViewModel, recyclerViewOptions, + it, batLevel, requireActivity() + ) + }!! binding.rvOrder.adapter = rvAdapter rvAdapter.startListening() @@ -206,8 +233,9 @@ class HomeFragment : Fragment() { val partition = dateFormat.format(currentDate) val searchTerm = partition + search val searchField = field + "Search" - val query = Firebase.firestore.collection("patientData").orderBy(searchField).startAt(searchTerm) - .endAt(searchTerm + "\uf8ff") + val query = + Firebase.firestore.collection("patientData").orderBy(searchField).startAt(searchTerm) + .endAt(searchTerm + "\uf8ff") query.get().addOnSuccessListener { userSearchTrace.stop() } @@ -218,7 +246,14 @@ class HomeFragment : Fragment() { batLevel = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) rvAdapter = view?.let { - UserListAdapter(requireContext(), hemoCubeViewModel, recyclerViewOptions, it, batLevel, requireActivity()) + UserListAdapter( + requireContext(), + hemoCubeViewModel, + recyclerViewOptions, + it, + batLevel, + requireActivity() + ) }!! binding.rvOrder.adapter = rvAdapter rvAdapter.startListening() @@ -272,7 +307,8 @@ class HomeFragment : Fragment() { } hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> - val uploadDataVisibility = if (userDataList.any { !it.localFlag }) View.VISIBLE else View.GONE + val uploadDataVisibility = + if (userDataList.any { !it.localFlag }) View.VISIBLE else View.GONE binding.uploadData.visibility = uploadDataVisibility } } @@ -331,7 +367,7 @@ class HomeFragment : Fragment() { private fun deleteHemoCubeIncompleteRegistrations(userDataList: List) { userDataList.forEach { userData -> - if (userData.testTime?.isEmpty() == true) { + if (userData._id.isEmpty()) { hemoCubeViewModel.deleteById(userData._id) } } diff --git a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt index 73d05fc..7ce52d3 100644 --- a/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt +++ b/app/src/main/java/com/example/hpostesting/presentation/hemocube/HemoCubeViewModel.kt @@ -15,6 +15,7 @@ import com.example.hpostesting.data.model.Response import com.example.hpostesting.data.model.patient.BufferCheckData import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.HemoCubeTestData +import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.toHemoCubeTestData import com.example.hpostesting.data.repository.DatabaseRepository import dagger.hilt.android.lifecycle.HiltViewModel @@ -183,6 +184,10 @@ class HemoCubeViewModel @Inject constructor( hemoCubeDao.updateFieldById(id = userId, true) } + fun addUser(userData: HemoCubeTestData) = viewModelScope.launch { + hemoCubeDao.insertAll(userData) + } + fun deleteById(userId: String) = viewModelScope.launch { hemoCubeDao.deleteById(id = userId) } diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 9aa32ec..87f4636 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -22,7 +22,7 @@ android:id="@+id/internetNotAvailableCL" android:layout_width="match_parent" android:layout_height="match_parent" - android:visibility="gone" + android:visibility="visible" android:padding="24dp"> + + + + + + app:layout_constraintTop_toBottomOf="@+id/til_blood_group" /> + + @@ -74,7 +106,7 @@ android:id="@+id/internetAvailableCL" android:layout_width="match_parent" android:layout_height="match_parent" - android:visibility="visible" + android:visibility="gone" android:padding="24dp"> + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f75c24f..0c861a2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -183,8 +183,8 @@ User List User ID Aadhar ID - Internet not available, please enter the user ID manually - User ID should be 18 digits + Internet not available, please enter the user ID and blood group manually + User ID should be 18 digits and please select the blood group Upload DB Registration Do you want to upload the local DB Registration to the cloud? Upload