Compare commits

...

23 Commits

Author SHA1 Message Date
Mariya
628b84bfef changed the time zone for result upload for molbio 2024-04-05 14:23:51 +05:30
chandrashekhar reddy
c825ebbda3 Removed the finish activity in HomeFragment while calling kit activity so onback pressed app will not exit instead come back to home 2024-04-03 17:13:15 +05:30
chandrashekhar reddy
fe8a340021 Added details in AboutFragment about SMI 2024-04-03 17:04:51 +05:30
chandrashekhar reddy
6bbbcea227 For security added sql cipher to room and removed bug in ActivitiesFragment 2024-04-03 13:45:41 +05:30
chandrashekhar reddy
ad237e75ae Duplicate test data in local database removed by adding update query in HemoCubeDao 2024-03-31 00:03:48 +05:30
chandrashekhar reddy
5cfb04c680 HemoCubeFragment test cases updated 2024-03-30 14:19:47 +05:30
chandrashekhar reddy
31e92a0cbb HemoCubeFragment changes in device ratio and borderline metric 2024-03-30 13:45:47 +05:30
chandrashekhar reddy
96ba5ce92f HomeFragment network change edited 2024-03-28 16:32:21 +05:30
chandrashekhar reddy
0635cb6813 Location fetch code added in login fragment without gps 2024-03-27 15:13:37 +05:30
chandrashekhar reddy
326936fc26 Merge remote-tracking branch 'origin/dev' into dev
# Conflicts:
#	app/src/main/java/com/example/hpostesting/data/constant/Constants.kt
#	app/src/main/java/com/example/hpostesting/presentation/dashboard/HomeFragment.kt
2024-03-27 15:12:57 +05:30
chandrashekhar reddy
da195ab573 Location fetch code added in login fragment without gps 2024-03-27 15:10:06 +05:30
Mariya
47f586ff63 Merge remote-tracking branch 'origin/dev' into dev
# Conflicts:
#	app/src/main/res/values-hi/strings.xml
#	app/src/main/res/values-kn/strings.xml
#	app/src/main/res/values/strings.xml
2024-03-26 12:32:30 +05:30
Mariya
9c22bdabf9 Lab Name is Added inside the settings screen, and added for molbio login request 2024-03-26 12:30:51 +05:30
chandrashekhar reddy
0a103795cd About screen added in drawer 2024-03-25 17:12:24 +05:30
Mariya
541b555c05 Panel screen specific options will only visible to ADMIN only 2024-03-23 17:22:32 +05:30
Mariya
d14afa0942 Merge remote-tracking branch 'origin/dev-usb-terminal-inapp' into dev 2024-03-23 17:02:12 +05:30
Mariya
71a364a9a2 csv file downloading changes added 2024-03-23 15:29:40 +05:30
Mariya
9aa89f810e error fixing 2024-03-23 12:21:49 +05:30
Mariya
12af81d142 error fixing 2024-03-22 15:16:09 +05:30
Mariya
29115786fa changed reverted back for csv option for ADMIN 2024-03-21 20:53:48 +05:30
Mariya
614192c04c Revert "changes made for dropdownlist for pq , for iocl 122 version added, for E command , RS AND RC changed to ES and EC"
This reverts commit 4fe1a0e187.
2024-03-20 18:04:22 +05:30
Mariya
4fe1a0e187 changes made for dropdownlist for pq , for iocl 122 version added, for E command , RS AND RC changed to ES and EC 2024-03-20 17:48:55 +05:30
Mariya
688165eaad changes made for dropdownlist for pq , for iocl 122 version added, for E command , RS AND RC changed to ES and EC 2024-03-20 17:46:07 +05:30
31 changed files with 825 additions and 293 deletions

View File

@@ -19,8 +19,8 @@ android {
applicationId "in.sminnovations.hpostesting.dev" applicationId "in.sminnovations.hpostesting.dev"
minSdk 21 minSdk 21
targetSdk 34 targetSdk 34
versionCode 121 versionCode 122
versionName "2.1.121" versionName "2.1.122"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@@ -138,6 +138,7 @@ dependencies {
implementation "androidx.room:room-ktx:2.6.1" implementation "androidx.room:room-ktx:2.6.1"
implementation "androidx.room:room-runtime:2.6.1" implementation "androidx.room:room-runtime:2.6.1"
kapt ("androidx.room:room-compiler:2.6.1") kapt ("androidx.room:room-compiler:2.6.1")
implementation "net.zetetic:android-database-sqlcipher:4.4.0"
//image //image
implementation 'com.github.bumptech.glide:glide:4.13.2' implementation 'com.github.bumptech.glide:glide:4.13.2'

View File

@@ -16,7 +16,7 @@ package com.example.hpostesting.data.constant
object Constants { object Constants {
const val ACTION_USB_PERMISSION = "shanmukha.in.sickle_cell.USB_PERMISSION" const val ACTION_USB_PERMISSION = "shanmukha.in.sickle_cell.USB_PERMISSION"
const val HEMOCUBE_USB_PERMISSION = "shanmukha.in.sickle_cell_homocube.USB_PERMISSION" const val HEMOCUBE_USB_PERMISSION = "shanmukha.in.sickle_cell_homocube.USB_PERMISSION"
const val passphrase = "smi_#@sql"
const val BASE_URL = "www.google.com" const val BASE_URL = "www.google.com"
const val DOCUMENT_ID_FOR_UPDATE ="2o71vBKLqdgEKYtFG8Lb" const val DOCUMENT_ID_FOR_UPDATE ="2o71vBKLqdgEKYtFG8Lb"
const val ABHA_APP_PACKAGE = "in.ndhm.phr" const val ABHA_APP_PACKAGE = "in.ndhm.phr"
@@ -259,7 +259,9 @@ object Constants {
const val BUFFER_VALUE_3 = "BufferValue3" const val BUFFER_VALUE_3 = "BufferValue3"
const val BUFFER_VALUE_4 = "BufferValue4" const val BUFFER_VALUE_4 = "BufferValue4"
const val DEVICE_ID = "DEVICE_ID" const val DEVICE_ID = "DEVICE_ID"
const val LABNAME = "LAB_NAME"
const val IS_TOKEN_AVAILABLE = "IS_TOKEN_AVAILABLE"
const val BUFFER_LED_LOWER_BOUND = 21000 const val BUFFER_LED_LOWER_BOUND = 21000
const val BUFFER_LED_UPPER_BOUND = 23500 const val BUFFER_LED_UPPER_BOUND = 23500

View File

@@ -53,4 +53,8 @@ interface HemoCubeDao {
@Query("SELECT * from hemo_cube_test_table WHERE localFlag = 0") @Query("SELECT * from hemo_cube_test_table WHERE localFlag = 0")
fun getPendingUser(): LiveData<List<HemoCubeTestData>> fun getPendingUser(): LiveData<List<HemoCubeTestData>>
@Update
suspend fun updateTest(hemoCubeTestData: HemoCubeTestData)
} }

View File

@@ -23,7 +23,7 @@ import com.example.hpostesting.data.model.patient.UserData
@Database( @Database(
entities = [UserData::class, HemoCubeTestData::class, DeviceData::class, BufferCheckData::class], entities = [UserData::class, HemoCubeTestData::class, DeviceData::class, BufferCheckData::class],
version = 30, version = 32,
exportSchema = false exportSchema = false
) )
@TypeConverters(Converters::class) @TypeConverters(Converters::class)

View File

@@ -106,4 +106,5 @@ data class HemoCubeTestData(
var filter: String? = "", var filter: String? = "",
var volume: String? = "", var volume: String? = "",
var isCSVCreated: Boolean = false, var isCSVCreated: Boolean = false,
var labName: String? = ""
) )

View File

@@ -43,6 +43,7 @@ data class UserData(
var result: TestRightResultType? = null, var result: TestRightResultType? = null,
var resultRatio: Double? = null, var resultRatio: Double? = null,
var prdClassification: String = "", var prdClassification: String = "",
var sampleid: Int = 0
) { ) {
enum class Gender { enum class Gender {
MALE, MALE,
@@ -59,7 +60,9 @@ data class UserData(
fun UserData.toHemoCubeTestData() = HemoCubeTestData( fun UserData.toHemoCubeTestData() = HemoCubeTestData(
_id = _id, _id = _id,
name = name, name = name,
sampleid = sampleid,
bloodGroup = bloodGroup, bloodGroup = bloodGroup,
incubationTime = incubationTime,
birthYear = birthYear, birthYear = birthYear,
gender = gender, gender = gender,
state = state, state = state,

View File

@@ -20,6 +20,7 @@ import android.content.res.AssetManager
import androidx.room.Room import androidx.room.Room
import com.example.hpostesting.data.api.MolbioAuthApi import com.example.hpostesting.data.api.MolbioAuthApi
import com.example.hpostesting.data.api.MolbioResultApi import com.example.hpostesting.data.api.MolbioResultApi
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.util.PropertyProvider import com.example.hpostesting.util.PropertyProvider
import com.example.hpostesting.data.dao.HemoCubeBufferDao import com.example.hpostesting.data.dao.HemoCubeBufferDao
import com.example.hpostesting.data.dao.HemoCubeDao import com.example.hpostesting.data.dao.HemoCubeDao
@@ -43,6 +44,8 @@ import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent import dagger.hilt.components.SingletonComponent
import net.sqlcipher.database.SQLiteDatabase
import net.sqlcipher.database.SupportFactory
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory import retrofit2.converter.gson.GsonConverterFactory
@@ -57,9 +60,12 @@ object AppModule {
@Provides @Provides
@Singleton @Singleton
fun provideMyDatabase(@ApplicationContext context: Context): MyDatabase { fun provideMyDatabase(@ApplicationContext context: Context): MyDatabase {
val passphraseBytes: ByteArray = SQLiteDatabase.getBytes(Constants.passphrase.toCharArray())
val factory = SupportFactory(passphraseBytes)
return Room.databaseBuilder( return Room.databaseBuilder(
context, MyDatabase::class.java, "my_database" context, MyDatabase::class.java, "my_database"
).fallbackToDestructiveMigration().build() ).openHelperFactory(factory).fallbackToDestructiveMigration().build()
} }
@Provides @Provides

View File

@@ -84,10 +84,10 @@ class MainActivity : AppCompatActivity() {
locationCallback = object : LocationCallback() { locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) { override fun onLocationResult(locationResult: LocationResult) {
locationResult.lastLocation?.let { location -> locationResult.lastLocation?.let { location ->
DataHolder.location = // DataHolder.location =
UserData.Location(location.latitude, location.longitude) // UserData.Location(location.latitude, location.longitude)
DataHolder.selectedTest?.location = // DataHolder.selectedTest?.location =
UserData.Location(location.latitude, location.longitude) // UserData.Location(location.latitude, location.longitude)
Log.i("Location", DataHolder.location.toString()) Log.i("Location", DataHolder.location.toString())
} }
} }
@@ -314,14 +314,14 @@ class MainActivity : AppCompatActivity() {
fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? -> fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? ->
location?.let { location?.let {
if (DataHolder.selectedTest != null) { if (DataHolder.selectedTest != null) {
DataHolder.selectedTest!!.location = // DataHolder.selectedTest!!.location =
UserData.Location(location.latitude, location.longitude) // UserData.Location(location.latitude, location.longitude)
} else { } else {
startActivity(Intent(this, DashboardActivity::class.java)) startActivity(Intent(this, DashboardActivity::class.java))
finish() finish()
} }
DataHolder.location = // DataHolder.location =
UserData.Location(location.latitude, location.longitude) // UserData.Location(location.latitude, location.longitude)
} ?: run { } ?: run {
requestLocationUpdates() requestLocationUpdates()
} }

View File

@@ -35,7 +35,7 @@ import java.util.Calendar
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
class OfflineUserListAdapter(private val view: View, private val batLevel: Int) : class OfflineUserListAdapter(private val view: View, private val batLevel: Int,private val fromWhere:String) :
RecyclerView.Adapter<OfflineUserListAdapter.OfflineUserListViewHolder>() { RecyclerView.Adapter<OfflineUserListAdapter.OfflineUserListViewHolder>() {
inner class OfflineUserListViewHolder(val binding: OfflineUserListViewBinding) : inner class OfflineUserListViewHolder(val binding: OfflineUserListViewBinding) :
@@ -88,58 +88,59 @@ class OfflineUserListAdapter(private val view: View, private val batLevel: Int)
} else { } else {
teststatus.text = view.context.getString(R.string.test_pending) teststatus.text = view.context.getString(R.string.test_pending)
} }
if(fromWhere == "Home") {
userCard.setOnClickListener { userCard.setOnClickListener {
if (false) { if (false) {
Toast.makeText(
view.context,
view.context.getString(R.string.low_battery_warning),
Toast.LENGTH_SHORT
).show()
return@setOnClickListener
}
if (userList.testStatus != null) {
if (userList.testStatus!!) {
Toast.makeText( Toast.makeText(
view.context, view.context,
view.context.getString(R.string.test_already_conducted), view.context.getString(R.string.low_battery_warning),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
} else { return@setOnClickListener
if (userList.incubationTime != "") { }
if (isBetween15And30Minutes(userList.incubationTime) < Constants.INCUBATION_TIME_MIN) { if (userList.testStatus != null) {
Toast.makeText( if (userList.testStatus!!) {
view.context,
view.context.getString(R.string.incubation_not_completed),
Toast.LENGTH_SHORT
).show()
} else
if (isBetween15And30Minutes(userList.incubationTime) > Constants.INCUBATION_TIME_MAX) {
Toast.makeText(
view.context,
view.context.getString(R.string.incubation_crossed_30_minutes),
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( Toast.makeText(
view.context, view.context,
view.context.getString(R.string.incubation_not_started), view.context.getString(R.string.test_already_conducted),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
} else {
if (userList.incubationTime != "") {
if (isBetween15And30Minutes(userList.incubationTime) < Constants.INCUBATION_TIME_MIN) {
Toast.makeText(
view.context,
view.context.getString(R.string.incubation_not_completed),
Toast.LENGTH_SHORT
).show()
} else
if (isBetween15And30Minutes(userList.incubationTime) > Constants.INCUBATION_TIME_MAX) {
Toast.makeText(
view.context,
view.context.getString(R.string.incubation_crossed_30_minutes),
Toast.LENGTH_SHORT
).show()
} else {
DataHolder.selectedTest = UserData(
sampleid = userList.sampleid,
_id = userList._id,
bloodGroup = userList.bloodGroup,
incubationTime = userList.incubationTime
)
view.findNavController()
.navigate(R.id.action_nav_home_to_mainActivity)
}
} else {
Toast.makeText(
view.context,
view.context.getString(R.string.incubation_not_started),
Toast.LENGTH_SHORT
).show()
}
} }
} }
} }
} }
} }
} }

View File

@@ -26,6 +26,7 @@ import android.widget.AdapterView
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.Spinner import android.widget.Spinner
import android.widget.Toast import android.widget.Toast
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.example.hpostesting.data.constant.DataHolder import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
@@ -58,7 +59,7 @@ class AssuranceControlsFragment : Fragment() {
private fun initViews() { private fun initViews() {
// binding.btnSubmit.visibility = View.GONE // binding.btnSubmit.visibility = View.GONE
val solutionSpinner: Spinner = binding.spinnerSolutions val solutionSpinner: Spinner = binding.spinnerSolutions
val solutionOptions = arrayOf("Select solution", "Tartrazine", "Acid Red") val solutionOptions = arrayOf("Select solution", "Tartrazine", "Acid Red","Sickle-Cert-Buffer", "1 Abs Holo Filter", "0.25 Abs Holo Filter", "Air Blank")
val solutionAdapter = val solutionAdapter =
ArrayAdapter(requireContext(), R.layout.simple_spinner_item, solutionOptions) ArrayAdapter(requireContext(), R.layout.simple_spinner_item, solutionOptions)
solutionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) solutionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
@@ -70,9 +71,27 @@ class AssuranceControlsFragment : Fragment() {
position: Int, position: Int,
id: Long, id: Long,
) { ) {
val selectedValue: String = solutionOptions[position] val selectedSolution: String = solutionOptions[position]
if (!selectedValue.equals("Select solution")) { if (selectedSolution != "Select solution") {
DataHolder.hemoCubeTestData!!.solution = selectedValue DataHolder.hemoCubeTestData!!.solution = selectedSolution
// Update visibility and name based on selected solution
if(selectedSolution == "Tartrazine" || selectedSolution == "Acid Red"){
activity?.runOnUiThread {
binding.spinnerConcentration.visibility = View.VISIBLE
// Ensure the name is updated only after concentration is selected.
// You might need to adjust this logic based on how and when you want to update the name.
// For now, it simply shows that the visibility is being handled.
}
} else {
activity?.runOnUiThread {
binding.spinnerConcentration.visibility = View.GONE
}
}
} else {
activity?.runOnUiThread {
binding.spinnerConcentration.visibility = View.GONE
}
} }
} }
@@ -184,17 +203,26 @@ class AssuranceControlsFragment : Fragment() {
val selectedadminOption = binding.spinnerAdmin.selectedItem.toString() val selectedadminOption = binding.spinnerAdmin.selectedItem.toString()
// Check if any of the selections are default values // Check if any of the selections are default values
// if (selectedSolution == "Select solution") { if (selectedSolution == "Select solution") {
// Toast.makeText(requireContext(), "Please select a solution", Toast.LENGTH_LONG).show() Toast.makeText(requireContext(), "Please select a solution", Toast.LENGTH_LONG).show()
// return@setOnClickListener // Prevent further execution return@setOnClickListener // Prevent further execution
// } }else{
// DataHolder.hemoCubeTestData!!.name = selectedSolution
// if (selectedConcentration == "Select concentration") { }
// Toast.makeText(requireContext(), "Please select a concentration", Toast.LENGTH_LONG).show()
// return@setOnClickListener // Prevent further execution
// }
if (selectedadminOption == "Select options") { if (selectedConcentration == "Select concentration" && binding.spinnerConcentration.isVisible) {
Toast.makeText(requireContext(), "Please select a concentration", Toast.LENGTH_LONG).show()
return@setOnClickListener // Prevent further execution
}else if(binding.spinnerConcentration.isVisible){
DataHolder.hemoCubeTestData!!.name = "$selectedSolution $selectedConcentration"
}else{
DataHolder.hemoCubeTestData!!.name = selectedSolution
}
if (selectedadminOption == "Select options" && binding.spinnerAdmin.isVisible) {
Toast.makeText(requireContext(), "Please select a option", Toast.LENGTH_LONG).show() Toast.makeText(requireContext(), "Please select a option", Toast.LENGTH_LONG).show()
return@setOnClickListener // Prevent further execution return@setOnClickListener // Prevent further execution
} }
@@ -208,11 +236,11 @@ class AssuranceControlsFragment : Fragment() {
DataHolder.hemoCubeTestData!!.solution = binding.spinnerSolutions.selectedItem.toString() DataHolder.hemoCubeTestData!!.solution = binding.spinnerSolutions.selectedItem.toString()
DataHolder.hemoCubeTestData!!.concentration = binding.spinnerConcentration.selectedItem.toString() DataHolder.hemoCubeTestData!!.concentration = binding.spinnerConcentration.selectedItem.toString()
DataHolder.hemoCubeTestData!!.filter = binding.spinnerAdmin.selectedItem.toString() DataHolder.hemoCubeTestData!!.filter = binding.spinnerAdmin.selectedItem.toString()
if(binding.spinnerAdmin.selectedItem.toString().equals("Select options")){ // if(binding.spinnerAdmin.selectedItem.toString().equals("Select options") && binding.spinnerAdmin.isVisible){
Toast.makeText(requireContext(), "Please select a option", Toast.LENGTH_LONG).show() // Toast.makeText(requireContext(), "Please select a option", Toast.LENGTH_LONG).show()
}else { // }else {
DataHolder.hemoCubeTestData!!.name = DataHolder.hemoCubeTestData!!.filter.toString() // DataHolder.hemoCubeTestData!!.name = DataHolder.hemoCubeTestData!!.filter.toString()
} // }

View File

@@ -0,0 +1,60 @@
/*
* // Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved.
* // Notice: All information contained herein is, and remains
* // the property of ShanMukha Innovations Pvt. Ltd. and its suppliers,
* // if any. The intellectual and technical concepts contained
* // herein are proprietary to ShanMukha Innovations Pvt. Ltd.
* // and its suppliers and may be covered by Indian and Foreign Patents,
* // patents in process, and are protected by trade secret or copyright law.
* // Dissemination of this information or reproduction of this material
* // is strictly forbidden unless prior written permission is obtained
* // from ShanMukha Innovations Pvt. Ltd.
*/
package com.example.hpostesting.presentation.dashboard
import android.content.Context
import android.content.SharedPreferences
import android.os.BatteryManager
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.activityViewModels
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.model.patient.HemoCubeTestData
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
import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentAboutBinding
import `in`.sminnovations.hpostesting.databinding.FragmentActivitiesBinding
import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding
class AboutFragment : Fragment() {
private lateinit var binding: FragmentAboutBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentAboutBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// binding.linkClick.setOnClickListener {
// val url = "https://sminnovations.in/"
// val intent = Intent(Intent.ACTION_VIEW)
// intent.data = Uri.parse(url)
// startActivity(intent)
// }
}
}

View File

@@ -58,7 +58,7 @@ class ActivitiesFragment : Fragment() {
val bm = val bm =
requireContext().getSystemService(Context.BATTERY_SERVICE) as BatteryManager requireContext().getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
adapter = OfflineUserListAdapter(binding.root, batLevel) adapter = OfflineUserListAdapter(binding.root, batLevel,"Activities")
adapter.differ.submitList(userData) adapter.differ.submitList(userData)
binding.rvOrderOffline.adapter = adapter binding.rvOrderOffline.adapter = adapter
}else{ }else{

View File

@@ -150,7 +150,7 @@ class DashboardActivity : AppCompatActivity(), IDataCollector {
appBarConfiguration = AppBarConfiguration( appBarConfiguration = AppBarConfiguration(
setOf( setOf(
R.id.nav_home, R.id.nav_profile, R.id.nav_activity,R.id.nav_settings R.id.nav_home, R.id.nav_profile, R.id.nav_activity,R.id.nav_settings,R.id.nav_about
), drawerLayout ), drawerLayout
) )
setupActionBarWithNavController(navController, appBarConfiguration) setupActionBarWithNavController(navController, appBarConfiguration)

View File

@@ -72,7 +72,31 @@ class GalleryFragment : Fragment() {
) { ) {
binding.btnDeviceProvision.visibility = View.VISIBLE binding.btnDeviceProvision.visibility = View.VISIBLE
} else { } else {
binding.btnDeviceProvision.visibility = View.GONE
}
if (sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN") {
binding.btnDeviceProvision.visibility = View.VISIBLE binding.btnDeviceProvision.visibility = View.VISIBLE
binding.btnAutoDac.visibility = View.VISIBLE
binding.btnDeviceProvision.visibility = View.VISIBLE
binding.btnDiagnostics.visibility = View.VISIBLE
binding.btnFiles.visibility = View.VISIBLE
binding.btnFirefox.visibility = View.VISIBLE
binding.btnCalibration.visibility = View.VISIBLE
binding.btnUsbTerminal.visibility = View.VISIBLE
binding.btnSubmit.visibility = View.VISIBLE
binding.btnDeviceInfo.visibility = View.VISIBLE
}else{
binding.btnDeviceProvision.visibility = View.GONE
binding.btnAutoDac.visibility = View.GONE
binding.btnDeviceProvision.visibility = View.GONE
binding.btnDiagnostics.visibility = View.GONE
binding.btnFiles.visibility = View.GONE
binding.btnFirefox.visibility = View.GONE
binding.btnCalibration.visibility = View.GONE
binding.btnUsbTerminal.visibility = View.GONE
binding.btnSubmit.visibility = View.GONE
binding.btnDeviceInfo.visibility = View.VISIBLE
} }
binding.btnDeviceProvision.setOnClickListener { binding.btnDeviceProvision.setOnClickListener {

View File

@@ -13,16 +13,6 @@
package com.example.hpostesting.presentation.dashboard package com.example.hpostesting.presentation.dashboard
// Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved.
// Notice: All information contained herein is, and remains
// the property of ShanMukha Innovations Pvt. Ltd. and its suppliers,
// if any. The intellectual and technical concepts contained
// herein are proprietary to ShanMukha Innovations Pvt. Ltd.
// and its suppliers and may be covered by Indian and Foreign Patents,
// patents in process, and are protected by trade secret or copyright law.
// Dissemination of this information or reproduction of this material
// is strictly forbidden unless prior written permission is obtained
// from ShanMukha Innovations Pvt. Ltd.
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.AlertDialog import android.app.AlertDialog
import android.app.DownloadManager import android.app.DownloadManager
@@ -51,15 +41,11 @@ import androidx.core.content.FileProvider
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.util.Result
import com.example.hpostesting.presentation.utils.DeviceCommunicationHandler
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.HemoCubeCommands import com.example.hpostesting.data.constant.HemoCubeCommands
import com.example.hpostesting.data.model.login.LoginRequest import com.example.hpostesting.data.model.login.LoginRequest
import com.example.hpostesting.data.model.login.LoginResponse import com.example.hpostesting.data.model.login.LoginResponse
import com.example.hpostesting.data.model.molbioresult.MolbioV2Result
import com.example.hpostesting.data.model.molbioresult.MolbioV2ResultRequest
import com.example.hpostesting.data.model.patient.DeviceData import com.example.hpostesting.data.model.patient.DeviceData
import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.data.model.patient.HemoCubeTestData
import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.patient.UserData
@@ -67,12 +53,14 @@ import com.example.hpostesting.data.model.updates.CheckUpdateRequest
import com.example.hpostesting.data.model.updates.DeviceUpdateRequest import com.example.hpostesting.data.model.updates.DeviceUpdateRequest
import com.example.hpostesting.encryption.Encryption import com.example.hpostesting.encryption.Encryption
import com.example.hpostesting.presentation.KitScanActivity import com.example.hpostesting.presentation.KitScanActivity
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter
import com.example.hpostesting.presentation.adapter.UserListAdapter import com.example.hpostesting.presentation.adapter.UserListAdapter
import com.example.hpostesting.presentation.assurance.AssuranceControlsActivity import com.example.hpostesting.presentation.assurance.AssuranceControlsActivity
import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel
import com.example.hpostesting.presentation.testRight.TestRightViewModel import com.example.hpostesting.presentation.testRight.TestRightViewModel
import com.example.hpostesting.presentation.utils.DeviceCommunicationHandler
import com.example.hpostesting.presentation.utils.UsbServiceListener
import com.example.hpostesting.util.Result
import com.firebase.ui.firestore.FirestoreRecyclerOptions import com.firebase.ui.firestore.FirestoreRecyclerOptions
import com.google.firebase.crashlytics.ktx.crashlytics import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.firestore.Query import com.google.firebase.firestore.Query
@@ -82,7 +70,6 @@ import com.google.firebase.perf.ktx.performance
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding
import kotlinx.coroutines.tasks.await
import okhttp3.ResponseBody import okhttp3.ResponseBody
import org.json.JSONObject import org.json.JSONObject
import java.io.BufferedOutputStream import java.io.BufferedOutputStream
@@ -96,9 +83,11 @@ import java.util.Date
import java.util.Locale import java.util.Locale
import java.util.zip.ZipEntry import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream import java.util.zip.ZipInputStream
import kotlin.properties.Delegates
@AndroidEntryPoint @AndroidEntryPoint
class HomeFragment : Fragment() { class HomeFragment : Fragment() {
private var wasConnected = false
private var isRegistered = false private var isRegistered = false
private var downloadId: Long = 0 private var downloadId: Long = 0
private lateinit var binding: FragmentHomeBinding private lateinit var binding: FragmentHomeBinding
@@ -109,8 +98,7 @@ class HomeFragment : Fragment() {
0 // Initialize with a default value, or obtain the actual battery level 0 // Initialize with a default value, or obtain the actual battery level
private lateinit var adapter: OfflineUserListAdapter private lateinit var adapter: OfflineUserListAdapter
private val homeViewModel: HemoCubeViewModel by activityViewModels() private val homeViewModel: HemoCubeViewModel by activityViewModels()
private var isTokenAvailable by Delegates.notNull<Boolean>()
private var isTokenAvailable = false
private var natsToken: String = "" private var natsToken: String = ""
private var deviceId: String = "" private var deviceId: String = ""
private lateinit var sharedPreference: SharedPreferences private lateinit var sharedPreference: SharedPreferences
@@ -122,6 +110,7 @@ class HomeFragment : Fragment() {
sharedPreference = requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) sharedPreference = requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
DataHolder.selectedTest = null DataHolder.selectedTest = null
isTokenAvailable = sharedPreference.getBoolean(Constants.IS_TOKEN_AVAILABLE, false)
return binding.root return binding.root
} }
@@ -148,11 +137,13 @@ class HomeFragment : Fragment() {
userData.forEach { userData.forEach {
if (it.testStatus == false) { if (it.testStatus == false) {
userList.add(it) userList.add(it)
}else if(it.testStatus == true){
userList.removeAll(userData)
} }
} }
val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager val bm = requireContext().getSystemService(BATTERY_SERVICE) as BatteryManager
val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) val batLevel: Int = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
adapter = OfflineUserListAdapter(binding.root, batLevel) adapter = OfflineUserListAdapter(binding.root, batLevel,"Home")
adapter.differ.submitList(userList) adapter.differ.submitList(userList)
binding.rvOrderOffline.adapter = adapter binding.rvOrderOffline.adapter = adapter
} }
@@ -164,20 +155,109 @@ class HomeFragment : Fragment() {
// } // }
// //
// } // }
viewModel.networkStatusLiveData?.observe(viewLifecycleOwner) { isConnected ->
if (isConnected) {
binding.internetAvailableCL.visibility = View.VISIBLE
binding.internetNotAvailableCL.visibility = View.GONE
binding.pendingTest.visibility = View.VISIBLE
loadUserData()
setSearch()
checkForLocalDBData()
if (Constants.MOLBIO_INTEGRATION) {
checkForTokenAndUpdate()
}
// Now re-subscribe to allUserData
/* hemoCubeViewModel.allLocalData.observe(viewLifecycleOwner) { originalUserDataList -> hemoCubeViewModel.fireBaseBulkUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
Toast.makeText(
requireContext(), R.string.test_upload, Toast.LENGTH_SHORT
).show()
}
if (result == "Error") {
Toast.makeText(requireContext(), R.string.test_upload_failed, Toast.LENGTH_SHORT)
.show()
}
}
binding.btnLogout.setOnClickListener {
logoutUser(requireContext())
}
binding.btnLogout1.setOnClickListener {
logoutUser(requireContext())
}
binding.uploadData.setOnClickListener {
// showUploadDialog(requireContext())
}
hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
if (sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN") {
val btnSaveLocalVisibility =
if (userData.any { it.testStatus == true }) View.VISIBLE else View.GONE
binding.downloadCSV.visibility = btnSaveLocalVisibility
binding.downloadCSV.setOnClickListener {
if (btnSaveLocalVisibility == View.VISIBLE) {
// Execute the action when the button is visible (testStatus is true for at least one user)
showDownloadDialog(requireContext())
} else {
// Handle the case when the button is not visible
Toast.makeText(
requireContext(),
"No test details stored locally",
Toast.LENGTH_SHORT
).show()
}
}
}else{
binding.downloadCSV.visibility = View.GONE
}
}
binding.btnNewKit.setOnClickListener {
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "")
putInt(Constants.KIT_COUNT, 0)
apply()
}
startActivity(Intent(requireContext(), KitScanActivity::class.java))
// requireActivity().finish()
}
binding.btnNewKitoffline.setOnClickListener {
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "")
putInt(Constants.KIT_COUNT, 0)
apply()
}
startActivity(Intent(requireContext(), KitScanActivity::class.java))
// requireActivity().finish()
}
binding.btnQuickCapture.setOnClickListener {
DataHolder.hemoCubeTestData = HemoCubeTestData()
val i = Intent(
requireContext().applicationContext, AssuranceControlsActivity::class.java
)
startActivity(i)
}
binding.downloadCSV.setOnClickListener {
showDownloadDialog(requireContext())
}
//calling network change listener
checkNetworkStatus()
}
@RequiresApi(Build.VERSION_CODES.P)
private fun checkNetworkStatus() {
hemoCubeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isConnected ->
// Toast.makeText(requireContext(),"connected"+isConnected+wasConnected, Toast.LENGTH_SHORT).show()
if (isConnected != wasConnected) {
if (isConnected) {
binding.internetAvailableCL.visibility = View.VISIBLE
binding.internetNotAvailableCL.visibility = View.GONE
binding.pendingTest.visibility = View.VISIBLE
loadUserData()
setSearch()
checkForLocalDBData()
if (Constants.MOLBIO_INTEGRATION) {
checkForTokenAndUpdate()
}
// Now re-subscribe to allUserData
/* hemoCubeViewModel.allLocalData.observe(viewLifecycleOwner) { originalUserDataList ->
Log.d("LOCAL_DB OBSERVE", "OBSERVE CALLED") Log.d("LOCAL_DB OBSERVE", "OBSERVE CALLED")
@@ -240,94 +320,25 @@ class HomeFragment : Fragment() {
} }
}*/ }*/
hemoCubeViewModel.sendDataToMolbio() hemoCubeViewModel.sendDataToMolbio()
hemoCubeViewModel.sendDataToFirebase() hemoCubeViewModel.sendDataToFirebase()
} else { } else {
binding.internetAvailableCL.visibility = View.GONE binding.internetAvailableCL.visibility = View.GONE
binding.pendingTest.visibility = View.GONE binding.pendingTest.visibility = View.GONE
binding.internetNotAvailableCL.visibility = View.VISIBLE binding.internetNotAvailableCL.visibility = View.VISIBLE
setUserId() setUserId()
}
wasConnected = isConnected
}else{
if(!wasConnected){
binding.internetAvailableCL.visibility = View.GONE
binding.pendingTest.visibility = View.GONE
binding.internetNotAvailableCL.visibility = View.VISIBLE
setUserId()
}
} }
} }
hemoCubeViewModel.fireBaseBulkUpload.observe(viewLifecycleOwner) { result ->
if (result == "Success") {
Toast.makeText(
requireContext(), R.string.test_upload, Toast.LENGTH_SHORT
).show()
}
if (result == "Error") {
Toast.makeText(requireContext(), R.string.test_upload_failed, Toast.LENGTH_SHORT)
.show()
}
}
binding.btnLogout.setOnClickListener {
logoutUser(requireContext())
}
binding.btnLogout1.setOnClickListener {
logoutUser(requireContext())
}
binding.uploadData.setOnClickListener {
// showUploadDialog(requireContext())
}
// hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userData ->
//
// val btnSaveLocalVisibility =
// if (userData.any { it.testStatus == true }) View.GONE else View.GONE
//
// binding.downloadCSV.visibility = btnSaveLocalVisibility
//
// binding.downloadCSV.setOnClickListener {
// if (btnSaveLocalVisibility == View.VISIBLE) {
// // Execute the action when the button is visible (testStatus is true for at least one user)
// showDownloadDialog(requireContext())
// } else {
// // Handle the case when the button is not visible
// Toast.makeText(
// requireContext(),
// "No test details stored locally",
// Toast.LENGTH_SHORT
// ).show()
// }
// }
// }
binding.btnNewKit.setOnClickListener {
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "")
putInt(Constants.KIT_COUNT, 0)
apply()
}
startActivity(Intent(requireContext(), KitScanActivity::class.java))
// requireActivity().finish()
}
binding.btnNewKitoffline.setOnClickListener {
with(sharedPreference.edit()) {
putString(Constants.KIT_NUMBER, "")
putInt(Constants.KIT_COUNT, 0)
apply()
}
startActivity(Intent(requireContext(), KitScanActivity::class.java))
// requireActivity().finish()
}
binding.btnQuickCapture.setOnClickListener {
DataHolder.hemoCubeTestData = HemoCubeTestData()
val i = Intent(
requireContext().applicationContext, AssuranceControlsActivity::class.java
)
startActivity(i)
}
binding.downloadCSV.setOnClickListener {
showDownloadDialog(requireContext())
}
} }
@RequiresApi(Build.VERSION_CODES.P) @RequiresApi(Build.VERSION_CODES.P)
@@ -345,18 +356,20 @@ class HomeFragment : Fragment() {
if (!isTokenAvailable) { if (!isTokenAvailable) {
Log.d("istoken1", isTokenAvailable.toString()) Log.d("istoken1", isTokenAvailable.toString())
hemoCubeViewModel.login(createLoginRequestData(userID, password)) hemoCubeViewModel.login(createLoginRequestData(userID, password))
isTokenAvailable = true
//isTokenAvailable = true
} else if (isTokenAvailable) { } else if (isTokenAvailable) {
Log.d("istoken7", isTokenAvailable.toString()) Log.d("istoken7", isTokenAvailable.toString())
isTokenAvailable = true
hemoCubeViewModel.startPeriodicCheckUpdate()
hemoCubeViewModel.checkUpdate(createCheckUpdateRequestData())
} else {
if (isTokenExpired(accessToken)) { if (isTokenExpired(accessToken)) {
Log.d("istoken8", isTokenAvailable.toString()) Log.d("istoken8", isTokenAvailable.toString())
hemoCubeViewModel.login(createLoginRequestData(userID, password)) hemoCubeViewModel.login(createLoginRequestData(userID, password))
//hemoCubeViewModel.startPeriodicCheckUpdate()
}else{
hemoCubeViewModel.checkUpdate(createCheckUpdateRequestData())
} }
//isTokenAvailable = true
// hemoCubeViewModel.startPeriodicCheckUpdate()
} }
} else if (userID == "deviceIDAPI" && password == "devicePasswordAPI" && deviceId.isNotEmpty()) { } else if (userID == "deviceIDAPI" && password == "devicePasswordAPI" && deviceId.isNotEmpty()) {
fetchDeviceCredentials() fetchDeviceCredentials()
@@ -371,18 +384,15 @@ class HomeFragment : Fragment() {
Toast.makeText(context, "DECRYPTED: $credentials", Toast.LENGTH_SHORT).show() Toast.makeText(context, "DECRYPTED: $credentials", Toast.LENGTH_SHORT).show()
if (!isTokenAvailable) { if (!isTokenAvailable) {
hemoCubeViewModel.login(createLoginRequestData(userID, password)) hemoCubeViewModel.login(createLoginRequestData(userID, password))
isTokenAvailable = true
} }
// else if (isTokenAvailable) { else if (isTokenAvailable) {
// isTokenAvailable = true //hemoCubeViewModel.startPeriodicCheckUpdate()
// hemoCubeViewModel.startPeriodicCheckUpdate() if (isTokenExpired(accessToken)) {
// hemoCubeViewModel.checkUpdate(createCheckUpdateRequestData()) hemoCubeViewModel.login(createLoginRequestData(userID, password))
// } else { }else{
// if (isTokenExpired(accessToken)) { hemoCubeViewModel.checkUpdate(createCheckUpdateRequestData())
// hemoCubeViewModel.login(createLoginRequestData(userID, password)) }
// } }
// }
} else { } else {
Toast.makeText( Toast.makeText(
requireContext(), requireContext(),
@@ -396,7 +406,10 @@ class HomeFragment : Fragment() {
is Result.Success -> { is Result.Success -> {
updateTokens(response) updateTokens(response)
response.data.data?.accessToken response.data.data?.accessToken
isTokenAvailable = true with(sharedPreference.edit()) {
putBoolean(Constants.IS_TOKEN_AVAILABLE, true)
apply()
}
Log.d("istoken2", isTokenAvailable.toString()) Log.d("istoken2", isTokenAvailable.toString())
} }
@@ -619,7 +632,10 @@ class HomeFragment : Fragment() {
) )
apply() apply()
} }
isTokenAvailable = true with(sharedPreference.edit()) {
putBoolean(Constants.IS_TOKEN_AVAILABLE, true)
apply()
}
Log.d("istoken3", isTokenAvailable.toString()) Log.d("istoken3", isTokenAvailable.toString())
} }
@@ -628,10 +644,11 @@ class HomeFragment : Fragment() {
requireActivity().packageName, 0 requireActivity().packageName, 0
) )
val version = pInfo.versionName val version = pInfo.versionName
var labname = sharedPreference.getString(Constants.LABNAME,"")
return LoginRequest( return LoginRequest(
password = password, serialNumber = userID, username = userID, version = version password = password, serialNumber = userID, username = userID, version = version, lab = labname
) )
} }//latitude = DataHolder.location!!.latitude.toString(), longitude = DataHolder.location!!.longitude.toString(), location = DataHolder.location.toString()
private fun createCheckUpdateRequestData(): CheckUpdateRequest { private fun createCheckUpdateRequestData(): CheckUpdateRequest {
val pInfo = requireActivity().packageManager.getPackageInfo( val pInfo = requireActivity().packageManager.getPackageInfo(
@@ -949,11 +966,15 @@ class HomeFragment : Fragment() {
} }
private fun checkUnprocessedCSVData() { private fun checkUnprocessedCSVData() {
// hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
// val downloadDataVisibility = if (sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN") {
// if (userDataList.any { !it.isCSVCreated && it.testStatus == true }) View.GONE else View.GONE val downloadDataVisibility =
// binding.downloadCSV.visibility = downloadDataVisibility if (userDataList.any { !it.isCSVCreated && it.testStatus == true }) View.VISIBLE else View.GONE
// } binding.downloadCSV.visibility = downloadDataVisibility
}else{
binding.downloadCSV.visibility = View.GONE
}
}
} }
private fun sanitizeDoubleValues(hemoCubeTestData: HemoCubeTestData): HemoCubeTestData { private fun sanitizeDoubleValues(hemoCubeTestData: HemoCubeTestData): HemoCubeTestData {
@@ -987,22 +1008,22 @@ class HomeFragment : Fragment() {
dialog.show() dialog.show()
} }
// private fun showDownloadDialog(context: Context) { private fun showDownloadDialog(context: Context) {
// val builder = AlertDialog.Builder(context) val builder = AlertDialog.Builder(context)
// builder.setTitle(R.string.download_db_registration_title) builder.setTitle(R.string.download_db_registration_title)
// builder.setMessage(R.string.download_db_registration_message) builder.setMessage(R.string.download_db_registration_message)
//
// builder.setPositiveButton(R.string.downloadcsv) { dialog, _ -> builder.setPositiveButton(R.string.downloadcsv) { dialog, _ ->
// downloadLocalDBData(dialog) downloadLocalDBData(dialog)
// } }
//
// builder.setNegativeButton(R.string.cancel) { dialog, _ -> builder.setNegativeButton(R.string.cancel) { dialog, _ ->
// dialog.dismiss() dialog.dismiss()
// } }
//
// val dialog = builder.create() val dialog = builder.create()
// dialog.show() dialog.show()
// } }
private fun uploadLocalDBData(dialog: DialogInterface) { private fun uploadLocalDBData(dialog: DialogInterface) {
// viewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> // viewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
@@ -1064,9 +1085,10 @@ class HomeFragment : Fragment() {
} }
} }
// private fun downloadLocalDBData(dialog: DialogInterface) { private fun downloadLocalDBData(dialog: DialogInterface) {
// hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList -> var csvDownloaded = false
// val downloadList = mutableListOf<HemoCubeTestData>() hemoCubeViewModel.allUserData.observe(viewLifecycleOwner) { userDataList ->
// //
// userDataList.forEach { userData -> // userDataList.forEach { userData ->
// if (!userData.isCSVCreated) { // if (!userData.isCSVCreated) {
@@ -1079,12 +1101,51 @@ class HomeFragment : Fragment() {
// hemoCubeViewModel.createCSV(downloadList, requireContext()) // hemoCubeViewModel.createCSV(downloadList, requireContext())
// Toast.makeText(requireContext(), "Done", Toast.LENGTH_SHORT).show() // Toast.makeText(requireContext(), "Done", Toast.LENGTH_SHORT).show()
// } else { // } else {
// Toast.makeText(requireContext(), "Failed", Toast.LENGTH_SHORT).show() // Toast.makeText(requireContext(), "", Toast.LENGTH_SHORT).show()
// } // }
//
// dialog.dismiss() try {
// } if (!csvDownloaded) {
// }
val downloadList = mutableListOf<HemoCubeTestData>()
userDataList.forEach { userData ->
Log.d(
"DownloadDebug",
"userData: $userData, isCSVCreated: ${userData.isCSVCreated}"
)
// if (!userData.isCSVCreated) {
// userData.isCSVCreated = false
downloadList.add(userData)
// }
}
// Log the size of downloadList for debugging
Log.d("DownloadDebug", "downloadList size: ${downloadList.size}")
if (downloadList.isNotEmpty()) {
// Call ViewModel function to create CSV with filtered data
hemoCubeViewModel.createCSV(downloadList, requireContext())
csvDownloaded = true
Toast.makeText(
requireContext(),
"CSV file downloaded successfully",
Toast.LENGTH_SHORT
).show()
} else {
Toast.makeText(requireContext(), "No data to download", Toast.LENGTH_SHORT)
.show()
}
}
} catch (e: Exception) {
e.printStackTrace()
Toast.makeText(requireContext(), "Error downloading CSV file", Toast.LENGTH_SHORT).show()
} finally {
dialog.dismiss()
}
}
}
private fun deleteIncompleteRegistrations(userDataList: List<UserData>) { private fun deleteIncompleteRegistrations(userDataList: List<UserData>) {
userDataList.forEach { userData -> userDataList.forEach { userData ->
@@ -1104,6 +1165,8 @@ class HomeFragment : Fragment() {
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
hemoCubeViewModel.networkStatusLiveData.removeObservers(viewLifecycleOwner)
} }
private fun downloadCsv() { private fun downloadCsv() {
@@ -1120,22 +1183,22 @@ class HomeFragment : Fragment() {
} }
} }
private fun showDownloadDialog(context: Context) { // private fun showDownloadDialog(context: Context) {
val builder = AlertDialog.Builder(context) // val builder = AlertDialog.Builder(context)
builder.setTitle(R.string.download_db_registration_title) // builder.setTitle(R.string.download_db_registration_title)
builder.setMessage(R.string.download_db_registration_message) // builder.setMessage(R.string.download_db_registration_message)
//
builder.setPositiveButton(R.string.downloadcsv) { dialog, _ -> // builder.setPositiveButton(R.string.downloadcsv) { dialog, _ ->
// downloadLocalDBData(dialog) //// downloadLocalDBData(dialog)
} // }
//
builder.setNegativeButton(R.string.cancel) { dialog, _ -> // builder.setNegativeButton(R.string.cancel) { dialog, _ ->
dialog.dismiss() // dialog.dismiss()
} // }
//
val dialog = builder.create() // val dialog = builder.create()
dialog.show() // dialog.show()
} // }
// private fun downloadLocalDBData(dialog: DialogInterface) { // private fun downloadLocalDBData(dialog: DialogInterface) {
// var csvDownloaded = false // var csvDownloaded = false
@@ -1411,4 +1474,5 @@ class HomeFragment : Fragment() {
} }
} }

View File

@@ -14,18 +14,68 @@
package com.example.hpostesting.presentation.dashboard package com.example.hpostesting.presentation.dashboard
import android.content.Context import android.content.Context
import android.content.SharedPreferences
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.preference.ListPreference import androidx.preference.ListPreference
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import com.example.hpostesting.data.constant.Constants
import com.example.hpostesting.data.constant.DataHolder
import com.example.hpostesting.data.constant.LanguageManager import com.example.hpostesting.data.constant.LanguageManager
import com.example.hpostesting.data.model.TestState
import com.example.hpostesting.data.model.patient.toHemoCubeTestData
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding
import `in`.sminnovations.hpostesting.databinding.FragmentSlideshowBinding
private var isLanguageChanged = false private var isLanguageChanged = false
class SlideshowFragment : PreferenceFragmentCompat() { class SlideshowFragment : Fragment(){
private lateinit var binding: FragmentSlideshowBinding
private lateinit var sharedPreferences: SharedPreferences
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?,
): View {
binding = FragmentSlideshowBinding.inflate(inflater, container, false)
sharedPreferences =
requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.nameEditText.setText(sharedPreferences.getString(Constants.LABNAME,""))
binding.btnGo.setOnClickListener {
var labname = binding.nameEditText.text.toString()
DataHolder.hemoCubeTestData?.apply {
this.labName = labname
}
with(sharedPreferences.edit()) {
putString(Constants.LABNAME, labname)
apply()
}
Toast.makeText(
requireContext(),
"Lab Name is Added successfully.",
Toast.LENGTH_SHORT
).show()
}
childFragmentManager.beginTransaction().replace(binding.container.id,PrefsFragment()).commit()
}
}
class PrefsFragment: PreferenceFragmentCompat(){
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
val preferenceScreen = preferenceManager.createPreferenceScreen(requireContext()) val preferenceScreen = preferenceManager.createPreferenceScreen(requireContext())
@@ -56,19 +106,17 @@ class SlideshowFragment : PreferenceFragmentCompat() {
preferenceScreen.addPreference(languagePreference) preferenceScreen.addPreference(languagePreference)
preferenceScreen.addPreference(appVersionPreference) preferenceScreen.addPreference(appVersionPreference)
setPreferenceScreen(preferenceScreen) setPreferenceScreen(preferenceScreen)
if (isLanguageChanged) { if (isLanguageChanged) {
Toast.makeText(requireContext(), R.string.language_update, Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), R.string.language_update, Toast.LENGTH_SHORT).show()
} }
}
}
private fun updateLanguage(context: Context, languageCode: String) { private fun updateLanguage(context: Context, languageCode: String) {
LanguageManager.persistLanguagePreference(context, languageCode) LanguageManager.persistLanguagePreference(context, languageCode)
LanguageManager.setLocale(context, languageCode) LanguageManager.setLocale(context, languageCode)
requireActivity().recreate() // Recreate activity to apply language changes requireActivity().recreate() // Recreate activity to apply language changes
isLanguageChanged = true isLanguageChanged = true
} }
private fun getAppVersion(context: Context): String { private fun getAppVersion(context: Context): String {
return try { return try {
val pInfo = context.packageManager.getPackageInfo(context.packageName, 0) val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)

View File

@@ -13,21 +13,41 @@
package com.example.hpostesting.presentation.dashboard.ui package com.example.hpostesting.presentation.dashboard.ui
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Context.WIFI_SERVICE
import android.content.SharedPreferences import android.content.SharedPreferences
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.net.ConnectivityManager
import android.net.wifi.WifiManager
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat.getSystemService
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.Constants
import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.R
import `in`.sminnovations.hpostesting.databinding.FragmentLoginBinding import `in`.sminnovations.hpostesting.databinding.FragmentLoginBinding
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.net.HttpURLConnection
import java.net.URL
import java.util.Scanner
class LoginFragment : Fragment() { class LoginFragment : Fragment() {
var latitude = 0.0
var longitude = 0.0
var TAG = "LoginFragmentCheck"
private var _binding: FragmentLoginBinding? = null private var _binding: FragmentLoginBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
private lateinit var sharedPreference: SharedPreferences private lateinit var sharedPreference: SharedPreferences
@@ -41,11 +61,12 @@ class LoginFragment : Fragment() {
return binding.root return binding.root
} }
@RequiresApi(Build.VERSION_CODES.M)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
init() init()
checkLocation()
} }
private fun init() { private fun init() {
if (isUserLoggedIn()) { if (isUserLoggedIn()) {
navigateToHomeFragment() navigateToHomeFragment()
@@ -53,6 +74,8 @@ class LoginFragment : Fragment() {
} }
binding.btnLogin.setOnClickListener { binding.btnLogin.setOnClickListener {
// Toast.makeText(requireContext(), "$latitude/$longitude",Toast.LENGTH_SHORT).show()
val loginId = binding.loginId.text.toString() val loginId = binding.loginId.text.toString()
val password = binding.password.text.toString() val password = binding.password.text.toString()
@@ -102,4 +125,126 @@ class LoginFragment : Fragment() {
super.onDestroyView() super.onDestroyView()
_binding = null _binding = null
} }
/** Check if we can get our location */
@SuppressLint("MissingPermission")
fun checkLocation() {
// Get the location manager
val locationManager = requireActivity().getSystemService(Context.LOCATION_SERVICE) as LocationManager
val locationProviderWifi = LocationManager.NETWORK_PROVIDER
val locationProviderGPS = LocationManager.GPS_PROVIDER
val locationListenerNetwork: LocationListener
val locationListenerGPS: LocationListener
var gps_enabled = false
var network_enabled = false
//check wifi
val connectivityManager = requireActivity().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
if (mWifi!!.isConnected) {
Log.d(TAG, "Wifi connected")
}
//check gps and wifi availability
try {
gps_enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
} catch (ex: Exception) {
}
try {
network_enabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
} catch (ex: Exception) {
}
if (!gps_enabled) {
Log.d(TAG, "GPS: Missing")
}else{
// getPublicIpAddr { ipAddress ->
// // Do something with the ipAddress
// Log.d(TAG, "GPS: PRESENT"+ipAddress)
// }
}
if (!network_enabled) {
Log.d(TAG, "Network: Missing")
}
/* Location change listeners */try {
Log.d(TAG, "GPS: PRESENT TRy")
// Define a listener that responds to gps location updates
locationListenerGPS = object : LocationListener {
override fun onLocationChanged(location: Location) {
Log.d(TAG, "GPS: PRESENT loc")
Log.d(
TAG,
"GPS: Latitude: " + location.latitude + ", Longitude = " + location.longitude
)
}
override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
Log.d(TAG, "GP location found 1")
}
override fun onProviderEnabled(provider: String) {
Log.d(TAG, "GP location found 2")
}
override fun onProviderDisabled(provider: String) {
Log.d(TAG, "GP location found 3")
}
}
locationManager.requestLocationUpdates(locationProviderGPS, 0, 0f, locationListenerGPS)
Log.d(TAG, "GPS: PRESENT Req")
} catch (e: Exception) {
Log.e(TAG, "Location Exception: " + e.message)
}
try {
// Define a listener that responds to wifi location updates
locationListenerNetwork = object : LocationListener {
override fun onLocationChanged(location: Location) {
Log.d(
TAG,
"NW: Latitude: " + location.latitude + ", Longitude = " + location.longitude
)
}
override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
Log.d(TAG, "location found 1")
}
override fun onProviderEnabled(provider: String) {
Log.d(TAG, "location found 2")
}
override fun onProviderDisabled(provider: String) {
Log.d(TAG, "location found 3")
}
}
locationManager.requestLocationUpdates(
locationProviderWifi,
0,
0f,
locationListenerNetwork
)
} catch (e: Exception) {
Log.e(TAG, "NW Location Exception: " + e.message)
}
}
// fun getPublicIpAddr(callback: (String) -> Unit) {
// GlobalScope.launch(Dispatchers.IO) {
// val url = URL("https://api.ipify.org")
// val conn = url.openConnection() as HttpURLConnection
// try {
// conn.connect()
// if (conn.responseCode == HttpURLConnection.HTTP_OK) {
// val scanner = Scanner(conn.inputStream)
// scanner.useDelimiter("\\A")
// if (scanner.hasNext()) {
// val ipAddress = scanner.next()
// callback(ipAddress)
// }
// }
// } finally {
// conn.disconnect()
// }
// }
// }
} }

View File

@@ -189,7 +189,7 @@ class HemoCubeFragment : Fragment() {
if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") { if (sharedPreferences.getString(Constants.USER_ID, "").toString() == "ADMIN") {
activity?.runOnUiThread { activity?.runOnUiThread {
binding.tvDeviceMessages.visibility = View.GONE binding.tvDeviceMessages.visibility = View.VISIBLE
} }
} }
} }
@@ -463,9 +463,9 @@ class HemoCubeFragment : Fragment() {
fetchResult() fetchResult()
} }
//#EC for v0 and v1 and #RC for v2 //#EC for v0 and v1 and #RC for v2
(resultData.contains("#EC") && this.testStatusCode < TestStatus.EPROM_ADC_RETRIEVAL_COMPLETED.code) -> { (resultData.contains("#RC") && this.testStatusCode < TestStatus.EPROM_ADC_RETRIEVAL_COMPLETED.code) -> {
this.testStatusCode = TestStatus.EPROM_ADC_RETRIEVAL_COMPLETED.code this.testStatusCode = TestStatus.EPROM_ADC_RETRIEVAL_COMPLETED.code
hemoCubeViewModel.messages.postValue("EPROM ADC Loaded") hemoCubeViewModel.messages.postValue("Ready to test")//EPROM ADC Loaded
//checkCuvettePresence() //checkCuvettePresence()
activity?.runOnUiThread { activity?.runOnUiThread {
binding.btnPlacebuffer.visibility = View.VISIBLE binding.btnPlacebuffer.visibility = View.VISIBLE
@@ -476,7 +476,7 @@ class HemoCubeFragment : Fragment() {
(resultData.contains("#AC") && this.testStatusCode < TestStatus.TEMPERATURE_CHECK.code) -> { (resultData.contains("#AC") && this.testStatusCode < TestStatus.TEMPERATURE_CHECK.code) -> {
this.testStatusCode = TestStatus.TEMPERATURE_CHECK.code this.testStatusCode = TestStatus.TEMPERATURE_CHECK.code
temperature = resultData.substringAfter("#AS").substringBefore("#AC") temperature = resultData.substringAfter("#AS").substringBefore("#AC")
hemoCubeViewModel.messages.postValue("EPROM ADC Loaded and Temperature fetched \n Temp : $temperature") hemoCubeViewModel.messages.postValue("Ready to test \n Temperature : $temperature")
} }
resultData.contains("#CIN") && sampleClick && this.testStatusCode < TestStatus.CUVETTE_PRESENTS.code -> { resultData.contains("#CIN") && sampleClick && this.testStatusCode < TestStatus.CUVETTE_PRESENTS.code -> {
hemoCubeViewModel.messages.postValue(getString(R.string.cuvette_present)) hemoCubeViewModel.messages.postValue(getString(R.string.cuvette_present))
@@ -1019,6 +1019,7 @@ class HemoCubeFragment : Fragment() {
led3Buffer = led3BufferForDevice led3Buffer = led3BufferForDevice
led4Buffer = led4BufferForDevice led4Buffer = led4BufferForDevice
appVersion = version appVersion = version
labName = sharedPreferences.getString(Constants.LABNAME,"")
this.led1Sample = led1SampleForDevice this.led1Sample = led1SampleForDevice
this.led2Sample = led2SampleForDevice this.led2Sample = led2SampleForDevice
this.led3Sample = led3SampleForDevice this.led3Sample = led3SampleForDevice
@@ -1126,7 +1127,7 @@ class HemoCubeFragment : Fragment() {
"Borderline. Sickle Cell Trait" "Borderline. Sickle Cell Trait"
} }
if (deviceRatioClass == "Positive for Sickle Cell. HPLC for Confirmation") { if (deviceRatioClass == "Positive for Sickle Cell. HPLC for Confirmation") {
return if (borderlineMetric >= 1.34) return if (borderlineMetric >= 1.4)//1.34
"Borderline. Sickle Cell Trait" "Borderline. Sickle Cell Trait"
else else
"Borderline. Sickle Cell Disease" "Borderline. Sickle Cell Disease"
@@ -1168,7 +1169,7 @@ class HemoCubeFragment : Fragment() {
fun deviceRatioClassification(ratio: Double?): String { fun deviceRatioClassification(ratio: Double?): String {
try { try {
if (ratio != null) { if (ratio != null) {
if (ratio in 0.16..0.23) { if (ratio in 0.11..0.23) {
// setSubtitleTextColor(R.color.green_2) // setSubtitleTextColor(R.color.green_2)
return "Normal" return "Normal"
} }
@@ -1176,9 +1177,9 @@ class HemoCubeFragment : Fragment() {
return "Negative Borderline" return "Negative Borderline"
if (ratio in 0.25..0.31) if (ratio in 0.25..0.31)
return "Sickle Cell Trait" return "Sickle Cell Trait"
if (ratio in 0.31..0.36) if (ratio in 0.31..0.39)//0.36
return "Positive for Sickle Cell. HPLC for Confirmation" return "Positive for Sickle Cell. HPLC for Confirmation"
if (ratio in 0.36..0.7) if (ratio in 0.39..1.0)
return "Sickle Cell Disease" return "Sickle Cell Disease"
} else { } else {
return "Invalid" return "Invalid"

View File

@@ -136,7 +136,7 @@ class HemoCubeViewModel @Inject constructor(
testDetails?.testTime = SimpleDateFormat( testDetails?.testTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
hemoCubeDao.insertAll(testDetails!!) hemoCubeDao.updateTest(testDetails!!)
fireBaseUpload.postValue("Local") fireBaseUpload.postValue("Local")
} }
} catch (e: Exception) { } catch (e: Exception) {
@@ -413,6 +413,7 @@ class HemoCubeViewModel @Inject constructor(
testDetails?.concentration = DataHolder.hemoCubeTestData?.concentration testDetails?.concentration = DataHolder.hemoCubeTestData?.concentration
testDetails?.volume = DataHolder.hemoCubeTestData?.volume testDetails?.volume = DataHolder.hemoCubeTestData?.volume
testDetails?.filter = DataHolder.hemoCubeTestData?.filter testDetails?.filter = DataHolder.hemoCubeTestData?.filter
testDetails?.labName = DataHolder.hemoCubeTestData?.labName
} }
@@ -422,7 +423,10 @@ class HemoCubeViewModel @Inject constructor(
testDetails!!.reportUploadTime = SimpleDateFormat( testDetails!!.reportUploadTime = SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", Locale.getDefault() "yyyy-MM-dd HH:mm:ss", Locale.getDefault()
).format(Calendar.getInstance().time) ).format(Calendar.getInstance().time)
val currentTimeFormatted = SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssZZZZZ",
Locale.getDefault()
).format(Calendar.getInstance().time)
when (val response = repository.addTestToDatabase(testDetails)) { when (val response = repository.addTestToDatabase(testDetails)) {
is Response.Success -> { is Response.Success -> {
val kitCount = sharedPreference.getInt(Constants.KIT_COUNT, 0) val kitCount = sharedPreference.getInt(Constants.KIT_COUNT, 0)
@@ -444,26 +448,26 @@ class HemoCubeViewModel @Inject constructor(
MolbioV2Result( MolbioV2Result(
rawData = sanitizedTestDetails, rawData = sanitizedTestDetails,
analysisId = sanitizedTestDetails._id, analysisId = sanitizedTestDetails._id,
analysisDate = sanitizedTestDetails.testTime, analysisDate = currentTimeFormatted,
analysisStatus = sanitizedTestDetails.classificationResult, analysisStatus = sanitizedTestDetails.classificationResult,
thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[sanitizedTestDetails.deviceId]?.toString(), thresholds = Constants.BUFFER_INTENSITY_THRESHOLDS[sanitizedTestDetails.deviceId]?.toString(),
interpretation = sanitizedTestDetails.classificationResult, interpretation = sanitizedTestDetails.classificationResult,
testId = sanitizedTestDetails._id, testId = sanitizedTestDetails._id,
testTime = sanitizedTestDetails.testTime, testTime = currentTimeFormatted,
collectionTime = sanitizedTestDetails.testTime, collectionTime = currentTimeFormatted,
expiryTime = sanitizedTestDetails.testTime, expiryTime = currentTimeFormatted,
) )
) )
) )
) )
} }
hemoCubeDao.insertAll(testDetails) hemoCubeDao.updateTest(testDetails)
} }
is Response.Error -> { is Response.Error -> {
Log.e("Testdb", "Error uploading data to Firestore: $response") Log.e("Testdb", "Error uploading data to Firestore: $response")
fireBaseUpload.postValue("Error") fireBaseUpload.postValue("Error")
hemoCubeDao.insertAll(testDetails) hemoCubeDao.updateTest(testDetails)
} }
else -> {} else -> {}

View File

@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M11.5,2C6.81,2 3,5.81 3,10.5S6.81,19 11.5,19h0.5v3c4.86,-2.34 8,-7 8,-11.5C20,5.81 16.19,2 11.5,2zM12.5,16.5h-2v-2h2v2zM12.5,13h-2c0,-3.25 3,-3 3,-5 0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2h-2c0,-2.21 1.79,-4 4,-4s4,1.79 4,4c0,2.5 -3,2.75 -3,5z"/>
</vector>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ // Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved.
~ // Notice: All information contained herein is, and remains
~ // the property of ShanMukha Innovations Pvt. Ltd. and its suppliers,
~ // if any. The intellectual and technical concepts contained
~ // herein are proprietary to ShanMukha Innovations Pvt. Ltd.
~ // and its suppliers and may be covered by Indian and Foreign Patents,
~ // patents in process, and are protected by trade secret or copyright law.
~ // Dissemination of this information or reproduction of this material
~ // is strictly forbidden unless prior written permission is obtained
~ // from ShanMukha Innovations Pvt. Ltd.
-->
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:src="@drawable/smi_logo"
android:contentDescription="@string/smi" />
<TextView
android:id="@+id/titleText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/smi_desp"
android:layout_marginTop="12dp"
android:layout_marginEnd="12dp"
android:layout_marginStart="12dp"
android:textSize="18sp"
android:textColor="@color/black"
/>
<TextView
android:id="@+id/link_click"
android:clickable="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/learn_more"
android:layout_marginTop="5dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:textSize="18sp"
android:textColor="@color/red"
android:focusable="true" />
</LinearLayout>
</ScrollView>

View File

@@ -52,7 +52,7 @@
<Spinner <Spinner
android:id="@+id/spinner_solutions" android:id="@+id/spinner_solutions"
android:layout_width="0dp" android:layout_width="0dp"
android:visibility="gone" android:visibility="visible"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="40dp" android:layout_marginTop="40dp"
android:background="@drawable/spinner_border" android:background="@drawable/spinner_border"
@@ -78,7 +78,7 @@
<Spinner <Spinner
android:id="@+id/spinner_admin" android:id="@+id/spinner_admin"
android:layout_width="0dp" android:layout_width="0dp"
android:visibility="visible" android:visibility="gone"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="52dp" android:layout_marginTop="52dp"
android:background="@drawable/spinner_border" android:background="@drawable/spinner_border"

View File

@@ -27,7 +27,7 @@
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:gravity="center" android:gravity="center"
android:text="Start" android:text="Start"
android:visibility="invisible" android:visibility="visible"
android:textColor="@color/black" android:textColor="@color/black"
android:textSize="16sp" android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View File

@@ -193,7 +193,7 @@
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:src="@drawable/upload_data" android:src="@drawable/upload_data"
android:visibility="visible" android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/tv_title" app:layout_constraintBottom_toBottomOf="@+id/tv_title"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/tv_title" /> app:layout_constraintTop_toTopOf="@+id/tv_title" />

View File

@@ -12,11 +12,60 @@
~ // from ShanMukha Innovations Pvt. Ltd. ~ // from ShanMukha Innovations Pvt. Ltd.
--> -->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.hpostesting.presentation.dashboard.SlideshowFragment"> tools:context="com.example.hpostesting.presentation.dashboard.SlideshowFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.constraintlayout.widget.ConstraintLayout> <com.google.android.material.textfield.TextInputLayout
android:id="@+id/lab_name"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="20dp"
app:layout_constraintEnd_toStartOf="@id/btn_go"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/name_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLength="17"
android:inputType="text"
android:hint="@string/lab_name" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_go"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:text="@string/add"
app:cornerRadius="16dp"
app:layout_constraintBottom_toBottomOf="@id/lab_name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toEndOf="@id/lab_name"
app:layout_constraintTop_toTopOf="@id/lab_name" />
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/lab_name"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="10dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -33,5 +33,9 @@
android:id="@+id/nav_settings" android:id="@+id/nav_settings"
android:icon="@drawable/baseline_settings_24" android:icon="@drawable/baseline_settings_24"
android:title="@string/menu_settings" /> android:title="@string/menu_settings" />
<item
android:id="@+id/nav_about"
android:icon="@drawable/baseline_contact_support_24"
android:title="@string/menu_about" />
</group> </group>
</menu> </menu>

View File

@@ -45,6 +45,11 @@
android:name="com.example.hpostesting.presentation.dashboard.SlideshowFragment" android:name="com.example.hpostesting.presentation.dashboard.SlideshowFragment"
android:label="@string/action_settings" android:label="@string/action_settings"
tools:layout="@layout/fragment_slideshow" /> tools:layout="@layout/fragment_slideshow" />
<fragment
android:id="@+id/nav_about"
android:name="com.example.hpostesting.presentation.dashboard.AboutFragment"
android:label="@string/action_about"
tools:layout="@layout/fragment_about" />
<fragment <fragment
android:id="@+id/nav_activity" android:id="@+id/nav_activity"
android:name="com.example.hpostesting.presentation.dashboard.ActivitiesFragment" android:name="com.example.hpostesting.presentation.dashboard.ActivitiesFragment"
@@ -57,7 +62,7 @@
<fragment <fragment
android:id="@+id/loginFragment" android:id="@+id/loginFragment"
android:name="com.example.hpostesting.presentation.dashboard.ui.LoginFragment" android:name="com.example.hpostesting.presentation.dashboard.ui.LoginFragment"
android:label="fragment_login" android:label="@string/login"
tools:layout="@layout/fragment_login" > tools:layout="@layout/fragment_login" >
<action <action
android:id="@+id/action_loginFragment_to_homeFragment" android:id="@+id/action_loginFragment_to_homeFragment"

View File

@@ -292,4 +292,10 @@
<string name="Firefox">Firefox</string> <string name="Firefox">Firefox</string>
<string name="Files">Files</string> <string name="Files">Files</string>
<string name="usb_terminal">Usb Terminal</string> <string name="usb_terminal">Usb Terminal</string>
<string name="lab_name">Lab Name</string>
<string name="menu_about">About</string>
<string name="action_about">About</string>
<string name="smi">SMI</string>
<string name="smi_desp"><b>ShanMukha Innovations</b> is a spin-off from Indian Institute of Science, Bangalore. Incorporated in 2016, the company has been delivering innovative Made in India first of its kind deep technology-based products in healthcare.\\n\\nNotable solutions include Mobile Infection Testing and Reporting Labs (MITR Labs), portable thermal cycler (PolyCube).\\n\\nThe company launched Sicklecert ®, Indias first CDSCO approved indigenous diagnostic test for sickle-cell anemia.\\n\\nOur customers include government, non-profit and private sector companies. Leading research institutes such as IISc, IIT Tirupati have engaged us for unique projects. We take pride in supporting Indian and global customers with world-class products.</string>
<string name="learn_more">Visit to learn more: <u>sminnovations.in</u></string>
</resources> </resources>

View File

@@ -291,6 +291,12 @@
<string name="Firefox">Firefox</string> <string name="Firefox">Firefox</string>
<string name="Files">Files</string> <string name="Files">Files</string>
<string name="usb_terminal">Usb Terminal</string> <string name="usb_terminal">Usb Terminal</string>
<string name="menu_about">About</string>
<string name="action_about">About</string>
<string name="lab_name">Lab Name</string>
<string name="smi">SMI</string>
<string name="smi_desp"><b>ShanMukha Innovations</b> is a spin-off from Indian Institute of Science, Bangalore. Incorporated in 2016, the company has been delivering innovative Made in India first of its kind deep technology-based products in healthcare.\\n\\nNotable solutions include Mobile Infection Testing and Reporting Labs (MITR Labs), portable thermal cycler (PolyCube).\\n\\nThe company launched Sicklecert ®, Indias first CDSCO approved indigenous diagnostic test for sickle-cell anemia.\\n\\nOur customers include government, non-profit and private sector companies. Leading research institutes such as IISc, IIT Tirupati have engaged us for unique projects. We take pride in supporting Indian and global customers with world-class products.</string>
<string name="learn_more">Visit to learn more: <u>sminnovations.in</u></string>
<!-- Add translations for other strings --> <!-- Add translations for other strings -->
</resources> </resources>

View File

@@ -292,4 +292,10 @@
<string name="cuvette_absent">Cuvette is absent , please place the cuvette and retry again</string> <string name="cuvette_absent">Cuvette is absent , please place the cuvette and retry again</string>
<string name="retry">Retry again</string> <string name="retry">Retry again</string>
<string name="usb_terminal">Usb Terminal</string> <string name="usb_terminal">Usb Terminal</string>
<string name="menu_about">About</string>
<string name="action_about">About</string>
<string name="lab_name">Lab Name</string>
<string name="smi">SMI</string>
<string name="smi_desp"><b>ShanMukha Innovations</b> is a spin-off from Indian Institute of Science, Bangalore. Incorporated in 2016, the company has been delivering innovative Made in India first of its kind deep technology-based products in healthcare.\\n\\nNotable solutions include Mobile Infection Testing and Reporting Labs (MITR Labs), portable thermal cycler (PolyCube).\\n\\nThe company launched Sicklecert ®, Indias first CDSCO approved indigenous diagnostic test for sickle-cell anemia.\\n\\nOur customers include government, non-profit and private sector companies. Leading research institutes such as IISc, IIT Tirupati have engaged us for unique projects. We take pride in supporting Indian and global customers with world-class products.</string>
<string name="learn_more">Visit to learn more: <u>sminnovations.in</u></string>
</resources> </resources>

View File

@@ -353,14 +353,14 @@ class HemoCubeFragmentTest {
@Test @Test
fun testDeviceRatioClassificationPositiveForSickleCell() { fun testDeviceRatioClassificationPositiveForSickleCell() {
val ratio = 0.359 val ratio = 0.39
val result = hemoCubeFragment.deviceRatioClassification(ratio) val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Positive for Sickle Cell. HPLC for Confirmation", result) assertEquals("Positive for Sickle Cell. HPLC for Confirmation", result)
} }
@Test @Test
fun testDeviceRatioClassificationSickleCellDiseaseLowerBound() { fun testDeviceRatioClassificationSickleCellDiseaseLowerBound() {
val ratio = 0.361 val ratio = 0.391
val result = hemoCubeFragment.deviceRatioClassification(ratio) val result = hemoCubeFragment.deviceRatioClassification(ratio)
assertEquals("Sickle Cell Disease", result) assertEquals("Sickle Cell Disease", result)
} }
@@ -398,7 +398,7 @@ class HemoCubeFragmentTest {
val result = hemoCubeFragment.findResultWithAdditionalMethods( val result = hemoCubeFragment.findResultWithAdditionalMethods(
0.5, 0.5,
"Positive for Sickle Cell. HPLC for Confirmation", "Positive for Sickle Cell. HPLC for Confirmation",
1.35 1.4
) )
assertEquals("Borderline. Sickle Cell Trait", result) assertEquals("Borderline. Sickle Cell Trait", result)
} }
@@ -441,7 +441,7 @@ class HemoCubeFragmentTest {
val result = hemoCubeFragment.findResultWithAdditionalMethods( val result = hemoCubeFragment.findResultWithAdditionalMethods(
0.5, 0.5,
"Positive for Sickle Cell. HPLC for Confirmation", "Positive for Sickle Cell. HPLC for Confirmation",
1.35 1.4
) )
assertEquals("Borderline. Sickle Cell Trait", result) assertEquals("Borderline. Sickle Cell Trait", result)
} }