From 7cfbc5bb6891d912c2827afee064c09d51f116c4 Mon Sep 17 00:00:00 2001 From: Mariya Date: Fri, 12 Jan 2024 14:14:28 +0530 Subject: [PATCH] Counselling app and Digital Card implemeted --- app/build.gradle | 138 +++++++ app/build.gradle.kts | 69 ---- app/google-services.json | 208 ++++++++++ app/src/main/AndroidManifest.xml | 29 +- .../counselling/HPOSCounsellingApplication.kt | 29 ++ .../java/com/smi/counselling/MainActivity.kt | 94 ----- .../com/smi/counselling/data/DataHolder.kt | 28 ++ .../data/InternetConnectionLiveData.kt | 62 +++ .../counselling/data/constant/Constants.kt | 381 ++++++++++++++++++ .../data/constant/HemoCubeCommands.kt | 14 + .../data/constant/LanguageManager.kt | 30 ++ .../data/constant/TestRightCommands.kt | 12 + .../smi/counselling/data/dao/Converters.kt | 38 ++ .../com/smi/counselling/data/dao/DeviceDao.kt | 24 ++ .../smi/counselling/data/dao/HemoCubeDao.kt | 29 ++ .../smi/counselling/data/dao/MyDataBase.kt | 16 + .../com/smi/counselling/data/dao/UserDao.kt | 23 ++ .../data/dashboard/DashboardActivity.kt | 38 ++ .../data/dashboard/DigitalCardActivity.kt | 34 ++ .../data/dashboard/DigitalCardFragment.kt | 183 +++++++++ .../data/dashboard/HomeFragment.kt | 336 +++++++++++++++ .../data/dashboard/HomeViewModel.kt | 59 +++ .../smi/counselling/data/domain/AppModule.kt | 55 +++ .../data/model/patient/DeviceData.kt | 19 + .../data/model/patient/HemoCubeTestData.kt | 77 ++++ .../data/model/patient/PatientData.kt | 70 ++++ .../data/model/patient/UserData.kt | 58 +++ .../com/smi/counselling/ui/theme/Color.kt | 11 - .../com/smi/counselling/ui/theme/Theme.kt | 70 ---- .../java/com/smi/counselling/ui/theme/Type.kt | 34 -- app/src/main/res/drawable/indianoil.jpg | Bin 0 -> 17734 bytes app/src/main/res/drawable/karnataka.png | Bin 0 -> 7208 bytes .../res/drawable/progressbar_drawable.xml | 27 ++ .../res/drawable/sickle_cell_gov_logo.png | Bin 0 -> 12702 bytes .../main/res/layout/activity_dashboard.xml | 37 ++ .../main/res/layout/activity_digital_card.xml | 37 ++ app/src/main/res/layout/dropdown_item.xml | 12 + .../main/res/layout/fragment_digital_card.xml | 263 ++++++++++++ app/src/main/res/layout/fragment_home.xml | 236 +++++++++++ app/src/main/res/menu/my_menu.xml | 14 + app/src/main/res/values/colors.xml | 13 + app/src/main/res/values/strings.xml | 265 +++++++++++- app/src/main/res/values/styles.xml | 55 +++ app/src/main/res/values/themes.xml | 53 ++- build.gradle | 29 ++ build.gradle.kts | 5 - 46 files changed, 3026 insertions(+), 288 deletions(-) create mode 100644 app/build.gradle delete mode 100644 app/build.gradle.kts create mode 100644 app/google-services.json create mode 100644 app/src/main/java/com/smi/counselling/HPOSCounsellingApplication.kt delete mode 100644 app/src/main/java/com/smi/counselling/MainActivity.kt create mode 100644 app/src/main/java/com/smi/counselling/data/DataHolder.kt create mode 100644 app/src/main/java/com/smi/counselling/data/InternetConnectionLiveData.kt create mode 100644 app/src/main/java/com/smi/counselling/data/constant/Constants.kt create mode 100644 app/src/main/java/com/smi/counselling/data/constant/HemoCubeCommands.kt create mode 100644 app/src/main/java/com/smi/counselling/data/constant/LanguageManager.kt create mode 100644 app/src/main/java/com/smi/counselling/data/constant/TestRightCommands.kt create mode 100644 app/src/main/java/com/smi/counselling/data/dao/Converters.kt create mode 100644 app/src/main/java/com/smi/counselling/data/dao/DeviceDao.kt create mode 100644 app/src/main/java/com/smi/counselling/data/dao/HemoCubeDao.kt create mode 100644 app/src/main/java/com/smi/counselling/data/dao/MyDataBase.kt create mode 100644 app/src/main/java/com/smi/counselling/data/dao/UserDao.kt create mode 100644 app/src/main/java/com/smi/counselling/data/dashboard/DashboardActivity.kt create mode 100644 app/src/main/java/com/smi/counselling/data/dashboard/DigitalCardActivity.kt create mode 100644 app/src/main/java/com/smi/counselling/data/dashboard/DigitalCardFragment.kt create mode 100644 app/src/main/java/com/smi/counselling/data/dashboard/HomeFragment.kt create mode 100644 app/src/main/java/com/smi/counselling/data/dashboard/HomeViewModel.kt create mode 100644 app/src/main/java/com/smi/counselling/data/domain/AppModule.kt create mode 100644 app/src/main/java/com/smi/counselling/data/model/patient/DeviceData.kt create mode 100644 app/src/main/java/com/smi/counselling/data/model/patient/HemoCubeTestData.kt create mode 100644 app/src/main/java/com/smi/counselling/data/model/patient/PatientData.kt create mode 100644 app/src/main/java/com/smi/counselling/data/model/patient/UserData.kt delete mode 100644 app/src/main/java/com/smi/counselling/ui/theme/Color.kt delete mode 100644 app/src/main/java/com/smi/counselling/ui/theme/Theme.kt delete mode 100644 app/src/main/java/com/smi/counselling/ui/theme/Type.kt create mode 100644 app/src/main/res/drawable/indianoil.jpg create mode 100644 app/src/main/res/drawable/karnataka.png create mode 100644 app/src/main/res/drawable/progressbar_drawable.xml create mode 100644 app/src/main/res/drawable/sickle_cell_gov_logo.png create mode 100644 app/src/main/res/layout/activity_dashboard.xml create mode 100644 app/src/main/res/layout/activity_digital_card.xml create mode 100644 app/src/main/res/layout/dropdown_item.xml create mode 100644 app/src/main/res/layout/fragment_digital_card.xml create mode 100644 app/src/main/res/layout/fragment_home.xml create mode 100644 app/src/main/res/menu/my_menu.xml create mode 100644 app/src/main/res/values/styles.xml create mode 100644 build.gradle delete mode 100644 build.gradle.kts diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..1f33c59 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,138 @@ +plugins { + id 'com.android.application' + id 'org.jetbrains.kotlin.android' + id 'com.google.firebase.appdistribution' + id 'com.google.gms.google-services' + id 'androidx.navigation.safeargs.kotlin' + id 'kotlin-kapt' + id 'com.google.firebase.crashlytics' + id 'dagger.hilt.android.plugin' +} + +android { + namespace = "com.smi.counselling" + compileSdk = 34 + + defaultConfig { + applicationId = "com.smi.counselling" + minSdk = 24 + targetSdk = 34 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + kotlinOptions { + jvmTarget = '17' + } + dataBinding { + enabled = true + } + buildFeatures { + viewBinding true + buildConfig = true + } + lint { + abortOnError false + checkReleaseBuilds false + } + packagingOptions { + exclude 'mockito-extensions/org.mockito.plugins.MockMaker' + } +} + +dependencies { + implementation "com.google.dagger:hilt-android:2.46" + kapt "com.google.dagger:hilt-android-compiler:2.46" + implementation 'com.google.dagger:hilt-android:2.46' + kapt 'com.google.dagger:hilt-android-compiler:2.46' + implementation 'androidx.core:core-ktx:1.12.0' + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'com.google.android.material:material:1.11.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.2' + implementation 'androidx.fragment:fragment-ktx:1.6.2' + + //firebase + implementation platform('com.google.firebase:firebase-bom:32.1.0') + implementation("com.google.firebase:firebase-perf-ktx") + implementation("com.google.firebase:firebase-crashlytics-ktx") + implementation("com.google.firebase:firebase-analytics-ktx") + implementation 'com.google.firebase:firebase-firestore-ktx' + implementation 'com.google.firebase:firebase-auth-ktx' + implementation 'com.google.firebase:firebase-storage-ktx' + implementation 'com.firebaseui:firebase-ui-firestore:8.0.2' + implementation 'com.google.android.gms:play-services-auth:20.7.0' + implementation 'com.google.android.gms:play-services-location:21.0.1' + implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1' + implementation 'com.google.android.things:androidthings:1.0' + implementation 'com.google.firebase:firebase-appdistribution:16.0.0-beta11' + implementation("com.google.firebase:firebase-appdistribution-api-ktx:16.0.0-beta11") + implementation 'androidx.preference:preference-ktx:1.2.1' + implementation 'androidx.preference:preference-ktx:1.2.1' + + + // Testing + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' + // Mockito dependencies + testImplementation 'org.mockito:mockito-core:3.12.4' + androidTestImplementation 'org.mockito:mockito-android:3.12.4' + androidTestImplementation 'org.mockito:mockito-inline:3.12.4' + testImplementation "androidx.arch.core:core-testing:2.2.0" + testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.1' + + + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2" + implementation 'com.opencsv:opencsv:5.5' + + implementation "androidx.fragment:fragment-ktx:1.6.2" + + // Barcode scanner + implementation 'com.journeyapps:zxing-android-embedded:4.3.0' + + // Google ML Kit usign play services + implementation 'com.google.android.gms:play-services-code-scanner:16.1.0' + + //Room + implementation "androidx.room:room-ktx:2.6.1" + implementation "androidx.room:room-runtime:2.6.1" + kapt ("androidx.room:room-compiler:2.6.1") + + //image + implementation 'com.github.bumptech.glide:glide:4.13.2' + annotationProcessor 'com.github.bumptech.glide:compiler:4.13.2' + + // Navigation Component + implementation "androidx.navigation:navigation-fragment-ktx:2.7.6" + implementation "androidx.navigation:navigation-ui-ktx:2.7.6" + + //Dagger - Hilt + implementation "com.google.dagger:hilt-android:2.46" + kapt "com.google.dagger:hilt-android-compiler:2.46" + kapt "androidx.hilt:hilt-compiler:1.1.0" + + // Retrofit + GSON + implementation "com.squareup.retrofit2:retrofit:2.9.0" + implementation "com.squareup.retrofit2:converter-gson:2.9.0" + + implementation "androidx.preference:preference-ktx:1.2.1" +// Add Hilt dependencies + + +} \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts deleted file mode 100644 index e752303..0000000 --- a/app/build.gradle.kts +++ /dev/null @@ -1,69 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - namespace = "com.smi.counselling" - compileSdk = 34 - - defaultConfig { - applicationId = "com.smi.counselling" - minSdk = 24 - targetSdk = 34 - versionCode = 1 - versionName = "1.0" - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - vectorDrawables { - useSupportLibrary = true - } - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) - } - } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - kotlinOptions { - jvmTarget = "1.8" - } - buildFeatures { - compose = true - } - composeOptions { - kotlinCompilerExtensionVersion = "1.4.3" - } - packaging { - resources { - excludes += "/META-INF/{AL2.0,LGPL2.1}" - } - } -} - -dependencies { - - implementation("androidx.core:core-ktx:1.9.0") - implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2") - implementation("androidx.activity:activity-compose:1.8.0") - implementation(platform("androidx.compose:compose-bom:2023.03.00")) - implementation("androidx.compose.ui:ui") - implementation("androidx.compose.ui:ui-graphics") - implementation("androidx.compose.ui:ui-tooling-preview") - implementation("androidx.compose.material3:material3") - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test.ext:junit:1.1.5") - androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") - androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00")) - androidTestImplementation("androidx.compose.ui:ui-test-junit4") - debugImplementation("androidx.compose.ui:ui-tooling") - debugImplementation("androidx.compose.ui:ui-test-manifest") -} \ No newline at end of file diff --git a/app/google-services.json b/app/google-services.json new file mode 100644 index 0000000..a73fe1e --- /dev/null +++ b/app/google-services.json @@ -0,0 +1,208 @@ +{ + "project_info": { + "project_number": "650071678820", + "project_id": "hpos-af3cc", + "storage_bucket": "hpos-af3cc.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:650071678820:android:f1435a1c07f710036c6471", + "android_client_info": { + "package_name": "com.example.hposconsentform" + } + }, + "oauth_client": [ + { + "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:650071678820:android:7865bef608cdee6f6c6471", + "android_client_info": { + "package_name": "com.smi.counselling" + } + }, + "oauth_client": [ + { + "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:650071678820:android:2925e9ce3417d2386c6471", + "android_client_info": { + "package_name": "in.sminnovations.hemocube" + } + }, + "oauth_client": [ + { + "client_id": "650071678820-srhm9spm9hjn4frcd3r6o02gdhdbtd15.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "in.sminnovations.hemocube", + "certificate_hash": "7714b9268a81d0cf0fb178b0af8dbb630f8fc70a" + } + }, + { + "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:650071678820:android:7569c1cad4fc99916c6471", + "android_client_info": { + "package_name": "in.sminnovations.hposregistration" + } + }, + "oauth_client": [ + { + "client_id": "650071678820-70kp5jvjda4r5diqch2kn4lc40p4f42g.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "in.sminnovations.hposregistration", + "certificate_hash": "7714b9268a81d0cf0fb178b0af8dbb630f8fc70a" + } + }, + { + "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:650071678820:android:f96be19e5d43102b6c6471", + "android_client_info": { + "package_name": "in.sminnovations.hpostesting" + } + }, + "oauth_client": [ + { + "client_id": "650071678820-l87dnr0bdj95get0khgnvfv2an1k6ogq.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "in.sminnovations.hpostesting", + "certificate_hash": "7714b9268a81d0cf0fb178b0af8dbb630f8fc70a" + } + }, + { + "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:650071678820:android:a53292637abb7c0d6c6471", + "android_client_info": { + "package_name": "in.sminnovations.hpostesting.dev" + } + }, + "oauth_client": [ + { + "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 39ab3ac..fcb8d27 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,7 +2,27 @@ + + + + + + + + + + + + + + + + + + + android:theme="@style/AppTheme.NoActionBar"> + + \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/HPOSCounsellingApplication.kt b/app/src/main/java/com/smi/counselling/HPOSCounsellingApplication.kt new file mode 100644 index 0000000..e66d20a --- /dev/null +++ b/app/src/main/java/com/smi/counselling/HPOSCounsellingApplication.kt @@ -0,0 +1,29 @@ +package com.smi.counselling + +import android.app.Application +import android.content.Context +import androidx.room.Room +import com.example.hpostesting.data.dao.MyDatabase +import com.google.android.datatransport.runtime.dagger.Provides +import com.google.firebase.firestore.FirebaseFirestore +import com.google.firebase.firestore.FirebaseFirestoreSettings +import dagger.hilt.android.HiltAndroidApp +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import javax.inject.Singleton +@HiltAndroidApp +class HPOSCounsellingApplication: Application() { + val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) + + override fun onCreate() { + super.onCreate() + val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) + val firestoreSettings = FirebaseFirestoreSettings.Builder() + .setPersistenceEnabled(true) // Enable offline persistence if needed + .build() + + val firestore = FirebaseFirestore.getInstance() + firestore.firestoreSettings = firestoreSettings + } +} \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/MainActivity.kt b/app/src/main/java/com/smi/counselling/MainActivity.kt deleted file mode 100644 index 0d52f39..0000000 --- a/app/src/main/java/com/smi/counselling/MainActivity.kt +++ /dev/null @@ -1,94 +0,0 @@ -package com.smi.counselling - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.material3.TextField -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import com.smi.counselling.ui.theme.HPOSCounsellingTheme - -class MainActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContent { - HPOSCounsellingTheme { - // A surface container using the 'background' color from the theme - Surface( - modifier = Modifier.fillMaxSize(), - color = MaterialTheme.colorScheme.background - ) { - HomeScreen("Home") - } - } - } - } -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun HomeScreen(name: String, modifier: Modifier = Modifier) { - var userId1 by remember { mutableStateOf("") } - var userId2 by remember { mutableStateOf("") } - Column( - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.SpaceBetween, - modifier = Modifier.background(Color.White) - ) { - Text( - text = "Digital Counselling", - modifier = modifier - ) - TextField( - value = userId1, onValueChange = { userId1 = it }, - modifier = Modifier - .width(240.dp).height(30.dp) - .padding(start = 15.dp, top = 10.dp, bottom = 10.dp, end = 15.dp) - .background(Color.Gray, RoundedCornerShape(5.dp)), - ) - - Text("Score: 75%", - style = TextStyle( - fontSize = 28.sp, - fontWeight = FontWeight.Medium, - textAlign = TextAlign.Center, - ), - modifier = Modifier - .padding(10.dp) - ) - } -} - -@Preview(showBackground = true) -@Composable -fun HomeScreenPreview() { - HPOSCounsellingTheme { - HomeScreen("Home") - } -} \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/data/DataHolder.kt b/app/src/main/java/com/smi/counselling/data/DataHolder.kt new file mode 100644 index 0000000..f366fae --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/DataHolder.kt @@ -0,0 +1,28 @@ +package com.smi.counselling.data + +import androidx.lifecycle.MutableLiveData +import com.example.hpostesting.data.model.patient.HemoCubeTestData +import com.example.hpostesting.data.model.patient.UserData + +object DataHolder { + + + val usbConnected = MutableLiveData(true) + var mobileUniqueId: String? = null + var isAppFolderCreated = false + var appFolderPath = "" + var isReferenceTaken = false + var sampleReadCounter = 0 + + + var deviceSerialNumber: String = "ABCD" + val deviceType = MutableLiveData() + val wavelengthToPixelArray = ArrayList() + val intensityReferenceArray = ArrayList() + var selectedTest: UserData? = null + var hemoCubeTestData: HemoCubeTestData? = null + var kitSerial: String = "" + var location: UserData.Location? = null + var testExp: Boolean = true + var hemocubeResult: Double? = null +} \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/data/InternetConnectionLiveData.kt b/app/src/main/java/com/smi/counselling/data/InternetConnectionLiveData.kt new file mode 100644 index 0000000..dcb2731 --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/InternetConnectionLiveData.kt @@ -0,0 +1,62 @@ +package com.smi.counselling.data + + +import android.content.Context +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkCapabilities +import android.net.NetworkRequest +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.lifecycle.LiveData + +class NetworkStatusLiveData(context: Context) : LiveData() { + + private val connectivityManager: ConnectivityManager = + context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + + private val networkCallback = object : ConnectivityManager.NetworkCallback() { + override fun onAvailable(network: Network) { + postValue(true) + } + + override fun onLost(network: Network) { + postValue(false) + } + } + + @RequiresApi(Build.VERSION_CODES.M) + override fun onActive() { + super.onActive() + postValue(isNetworkAvailable()) + registerNetworkCallback() + } + + override fun onInactive() { + super.onInactive() + unregisterNetworkCallback() + } + + private fun registerNetworkCallback() { + val networkRequest = NetworkRequest.Builder() + .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) + .build() + + connectivityManager.registerNetworkCallback(networkRequest, networkCallback) + } + + private fun unregisterNetworkCallback() { + connectivityManager.unregisterNetworkCallback(networkCallback) + } + + @RequiresApi(Build.VERSION_CODES.M) + private fun isNetworkAvailable(): Boolean { + val network = connectivityManager.activeNetwork + val networkCapabilities = connectivityManager.getNetworkCapabilities(network) + return networkCapabilities != null && + networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && + networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/data/constant/Constants.kt b/app/src/main/java/com/smi/counselling/data/constant/Constants.kt new file mode 100644 index 0000000..a2da229 --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/constant/Constants.kt @@ -0,0 +1,381 @@ +package com.example.hpostesting.data.constant + +object Constants { + const val ACTION_USB_PERMISSION = "shanmukha.in.sickle_cell.USB_PERMISSION" + const val HOMOCUBE_USB_PERMISSION = "shanmukha.in.sickle_cell_homocube.USB_PERMISSION" + + const val ABHA_APP_PACKAGE = "in.ndhm.phr" + + const val WRITE_TIMEOUT_MILLIS = 30000 // 30 sec + const val READ_TIMEOUT_MILLIS = 60000 // 1 min + const val DELAY_BETWEEN_COMMANDS: Long = 1000 + + const val TEST_RIGHT_TOTAL_PIXEL = 3694 + + const val MAXIMUM_TEST_ALLOWED_BEFORE_REFERENCE = 40 + + const val RANGE_IN_RESULT_CALCULATIONS = 10 + + const val WAVELENGTH_OF_INTEREST_ONE = 427 + const val WAVELENGTH_OF_INTEREST_TWO = 555 + + const val MIN_WAVELENGTH_RANGE_TO_RECORD = 350 + const val MAX_WAVELENGTH_RANGE_TO_RECORD = 750 + + const val DEVICE_PRODUCT_ID = 24597 + const val DEVICE_TYPE_HOMOCUBE = "HOMOCUBE" + const val DEVICE_TYPE_TEST_RIGHT = "TEST_RIGHT" + + const val DEVICE_VENDOR_ID = 1027 + const val HOMO_CUBE_ID = 29987 + const val VENDOR_ID = 6790 + const val HEMO_CUBE_V2_PRODUCT_ID = 24577 + const val HEMO_CUBE_V2_VENDOR_ID = 1027 + + const val ERROR_NORMAL = 400 + const val ERROR_CRITICAL = 401 + + const val NO_OF_TIMES_TO_RUN_SAMPLE = 1 + + const val USER_ID = "usernameId" + + val STATICID = listOf( + "ADMIN", + "VIZ-1000-0004", + "VIZ-1000-0005", + "VIZ-1000-0006", + "HC-V1-001", + "HC-V1-002", + "HC-V1-003", + "HC-V1-004", + "HC-V1-005", + "HC-V1-006", + "HC-V1-007", + "HC-V1-008", + "HC-V1-009", + "HC-V1-010", + "HC-V1-011", + "HC-V1-012", + "HC-V1-013", + "HC-V1-014", + "HC-V1-015", + "HC-V1-016", + "HC-V1-017", + "HC-V1-018", + "HC-V1-019", + "HC-V1-020", + "HCV-000-3001", + "HCV-000-3002", + "HCV-000-3003", + "HCV-000-3004", + "HCV-000-3005", + "HCV-000-3006", + "HCV-000-3007", + "HCV-000-3008", + "HCV-000-3009", + "HCV-000-3010", + "HCV-000-3011", + "HCV-000-3012", + "HCV-000-3013", + "HCV-000-3014", + "HCV-000-3015", + "HCV-000-3016", + "HCV-000-3017", + "HCV-000-3018", + "HCV-000-3019", + "HCV-000-3020" + ) + + const val password = "SMI@12345" + + const val KIT_NUMBER = "KitNumber" + const val KIT_COUNT = "KitCount" + const val BUFFER_VALUE_1 = "BufferValue1" + const val BUFFER_VALUE_2 = "BufferValue2" + const val BUFFER_VALUE_3 = "BufferValue3" + const val BUFFER_VALUE_4 = "BufferValue4" + const val DEVICE_ID = "DEVICE_ID" + + const val BUFFER_LED_LOWER_BOUND = 21000 + const val BUFFER_LED_UPPER_BOUND = 24500 + + const val TEST_STATUS_CODE_TEST_STARTED = 1.0 + const val TEST_STATUS_CODE_CONFIG_STARTED = 2.0 + const val TEST_STATUS_CODE_CONFIG_COMPLETED = 3.0 + const val TEST_STATUS_CODE_BUFFER_STARTED = 4.0 + const val TEST_STATUS_CODE_BUFFER_COMPLETED = 5.0 + const val TEST_STATUS_CODE_BUFFER_PRINT_STARTED = 6.0 + const val TEST_STATUS_CODE_BUFFER_PRINT_COMPLETED = 7.0 + const val TEST_STATUS_CODE_SAMPLE_STARTED = 8.0 + const val TEST_STATUS_CODE_SAMPLE_COMPLETED = 9.0 + const val TEST_STATUS_CODE_SAMPLE_PRINT_STARTED = 10.0 + const val TEST_STATUS_CODE_SAMPLE_PRINT_COMPLETED = 11.0 + const val TEST_STATUS_CODE_FIRST_GAIN_STARTED = 12.0 + const val TEST_STATUS_CODE_FIRST_GAIN_COMPLETED = 13.0 + const val TEST_STATUS_CODE_FIRST_GAIN_PRINT_STARTED = 14.0 + const val TEST_STATUS_CODE_FIRST_GAIN_PRINT_COMPLETED = 15.0 + const val TEST_STATUS_CODE_SECOND_GAIN_STARTED = 16.0 + const val TEST_STATUS_CODE_SECOND_GAIN_COMPLETED = 17.0 + const val TEST_STATUS_CODE_SECOND_GAIN_PRINT_STARTED = 18.0 + const val TEST_STATUS_CODE_SECOND_GAIN_PRINT_COMPLETED = 19.0 + const val TEST_STATUS_CODE_THIRD_GAIN_STARTED = 20.0 + const val TEST_STATUS_CODE_THIRD_GAIN_COMPLETED = 21.0 + const val TEST_STATUS_CODE_THIRD_GAIN_PRINT_STARTED = 22.0 + const val TEST_STATUS_CODE_THIRD_GAIN_PRINT_COMPLETED = 23.0 + const val TEST_STATUS_CODE_FORTH_GAIN_STARTED = 24.0 + const val TEST_STATUS_CODE_FORTH_GAIN_COMPLETED = 25.0 + const val TEST_STATUS_CODE_FORTH_GAIN_PRINT_STARTED = 26.0 + const val TEST_STATUS_CODE_FORTH_GAIN_PRINT_COMPLETED = 27.0 + const val TEST_STATUS_CODE_TEST_COMPLETED = 30.0 + + val DEVICE_CONFIGURATION: Map>> = mapOf>>( + "HCV-000-3001" to listOf( + listOf(1.313, -0.89), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.2012, 0.0092), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3002" to listOf( + listOf(0.723142, -0.09135), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.1964, 0.011565), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3003" to listOf( + listOf(0.723142, -0.09135), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.1964, 0.011565), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3004" to listOf( + listOf(1.7272, -1.1977), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.2304, -0.0145), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3005" to listOf( + listOf(1.3801, -0.372), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.4565, -0.0371), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3006" to listOf( + listOf(1.3801, -0.372), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.4565, -0.0371), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3007" to listOf( + listOf(1.8445, -0.8213), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.4613, -0.0831), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3008" to listOf( + listOf(1.7272, -1.1977), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.2304, -0.0145), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3009" to listOf( + listOf(1.7272, -1.1977), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.2304, -0.0145), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3010" to listOf( + listOf(1.7272, -1.1977), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.2304, -0.0145), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3011" to listOf( + listOf(1.7272, -1.1977), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.2304, -0.0145), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3012" to listOf( + listOf(1.7272, -1.1977), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.2304, -0.0145), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3013" to listOf( + listOf(1.7272, -1.1977), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.2304, -0.0145), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3014" to listOf( + listOf(1.7272, -1.1977), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.2304, -0.0145), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3015" to listOf( + listOf(1.7272, -1.1977), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.2304, -0.0145), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3016" to listOf( + listOf(1.7272, -1.1977), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.2304, -0.0145), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3017" to listOf( + listOf(1.7272, -1.1977), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.2304, -0.0145), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3018" to listOf( + listOf(1.7272, -1.1977), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.2304, -0.0145), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3019" to listOf( + listOf(1.7272, -1.1977), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.2304, -0.0145), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + "HCV-000-3020" to listOf( + listOf(1.7272, -1.1977), // LED1, 435nm + listOf(0.581462456, -0.58502), // LED2, 415nm + listOf(0.2304, -0.0145), // LED3, 555nm + listOf(1.0, 0.0) // LED4 + ), + ) + + const val INCUBATION_TIME_MIN = 0 + const val INCUBATION_TIME_MAX = 1400 + const val BATTERY_LEVEL_MIN = 0 + const val READINGS_PER_SAMPLE = 3 + + val BUFFER_INTENSITY_THRESHOLDS: Map>> = mapOf>>( + "HCV-000-3001" to listOf( + listOf(20000, 25074), + listOf(20000, 24596), + listOf(20000, 26065), + listOf(20000, 27093), + ), + "HCV-000-3002" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + "HCV-000-3003" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + "HCV-000-3004" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + "HCV-000-3005" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + "HCV-000-3006" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + "HCV-000-3007" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + "HCV-000-3008" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + "HCV-000-3009" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + "HCV-000-3010" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + "HCV-000-3011" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + "HCV-000-3012" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + "HCV-000-3013" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + "HCV-000-3014" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + "HCV-000-3015" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + "HCV-000-3016" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + "HCV-000-3017" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + "HCV-000-3018" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + "HCV-000-3019" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + "HCV-000-3020" to listOf( + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + listOf(24500, 26250), + ), + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/data/constant/HemoCubeCommands.kt b/app/src/main/java/com/smi/counselling/data/constant/HemoCubeCommands.kt new file mode 100644 index 0000000..280049f --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/constant/HemoCubeCommands.kt @@ -0,0 +1,14 @@ +package com.example.hpostesting.data.constant + +enum class HemoCubeCommands(val command: String) { + startBuffer("B\r"), + AUTO_DAC_COMMAND("C\r"), + runDiagnostics("D\r"), + startSample("S\r"), + PRINT_COMMAND("P\r"), + getDeviceId("I\r"), + FIRST_GAIN_COMMAND("T\r"), + SECOND_GAIN_COMMAND("U\r"), + THIRD_GAIN_COMMAND("V\r"), + FORTH_GAIN_COMMAND("W\r"), +} \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/data/constant/LanguageManager.kt b/app/src/main/java/com/smi/counselling/data/constant/LanguageManager.kt new file mode 100644 index 0000000..85d6a7c --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/constant/LanguageManager.kt @@ -0,0 +1,30 @@ +package com.example.hpostesting.data.constant + +import android.content.Context +import android.content.SharedPreferences +import java.util.Locale + +object LanguageManager { + private const val LANGUAGE_PREF_KEY = "language_pref" + + fun setLocale(context: Context, languageCode: String) { + val locale = Locale(languageCode) + Locale.setDefault(locale) + + val resources = context.resources + val configuration = resources.configuration + configuration.setLocale(locale) + + context.createConfigurationContext(configuration) + } + + fun persistLanguagePreference(context: Context, languageCode: String) { + val prefs: SharedPreferences = context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE) + prefs.edit().putString(LANGUAGE_PREF_KEY, languageCode).apply() + } + + fun getSavedLanguage(context: Context): String { + val prefs: SharedPreferences = context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE) + return prefs.getString(LANGUAGE_PREF_KEY, "en") ?: "en" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/data/constant/TestRightCommands.kt b/app/src/main/java/com/smi/counselling/data/constant/TestRightCommands.kt new file mode 100644 index 0000000..ac5ec1f --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/constant/TestRightCommands.kt @@ -0,0 +1,12 @@ +package com.example.hpostesting.data.constant + +enum class TestRightCommands(val command: String) { + led2Set50("led2 50\r"), + led2Set100("led2 100\r"), + read("read\r"), + autoset("autoset\r"), + run("run\r"), + printInRange("print 239 339\r"), + printAll("print\r"), + testByEnter("\n\r") +} \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/data/dao/Converters.kt b/app/src/main/java/com/smi/counselling/data/dao/Converters.kt new file mode 100644 index 0000000..d49838f --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/dao/Converters.kt @@ -0,0 +1,38 @@ +package com.example.hpostesting.data.dao + +import androidx.room.TypeConverter +import com.example.hpostesting.data.model.patient.UserData +import com.google.common.reflect.TypeToken +import com.google.gson.Gson + +class Converters { + private val gson = Gson() + + @TypeConverter + fun fromString(value: String?): UserData.Location? { + return if (value != null) { + gson.fromJson(value, UserData.Location::class.java) + } else { + null + } + } + @TypeConverter + fun toString(location: UserData.Location?): String? { + return if (location != null) { + gson.toJson(location) + } else { + null + } + } + + @TypeConverter + fun fromList(list: List): String { + return Gson().toJson(list) + } + + @TypeConverter + fun toList(json: String): List { + val type = object : TypeToken>() {}.type + return Gson().fromJson(json, type) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/data/dao/DeviceDao.kt b/app/src/main/java/com/smi/counselling/data/dao/DeviceDao.kt new file mode 100644 index 0000000..96b4eab --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/dao/DeviceDao.kt @@ -0,0 +1,24 @@ +package com.example.hpostesting.data.dao + +import androidx.lifecycle.LiveData +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import com.example.hpostesting.data.model.patient.DeviceData +import com.example.hpostesting.data.model.patient.HemoCubeTestData +import com.example.hpostesting.data.model.patient.UserData +@Dao +interface DeviceDao { + @Query("SELECT * from device_table") + fun getAll(): LiveData> + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertAll(deviceData: DeviceData) + + @Query("SELECT * FROM device_table WHERE deviceId = :id") + suspend fun getUserByID(id: String): HemoCubeTestData + + @Query("DELETE FROM device_table WHERE deviceId = :id") + suspend fun deleteById(id: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/data/dao/HemoCubeDao.kt b/app/src/main/java/com/smi/counselling/data/dao/HemoCubeDao.kt new file mode 100644 index 0000000..cc16700 --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/dao/HemoCubeDao.kt @@ -0,0 +1,29 @@ +package com.example.hpostesting.data.dao + +import androidx.lifecycle.LiveData +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import com.example.hpostesting.data.model.patient.HemoCubeTestData +import com.example.hpostesting.data.model.patient.UserData +import com.google.android.datatransport.runtime.dagger.Module + +@Dao +@Module +interface HemoCubeDao { + @Query("SELECT * from hemo_cube_test_table") + fun getAll(): LiveData> + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertAll(hemoCubeTestData: HemoCubeTestData) + + @Query("SELECT * FROM hemo_cube_test_table WHERE _id = :id") + suspend fun getUserByID(id: String): HemoCubeTestData + + @Query("DELETE FROM hemo_cube_test_table WHERE _id = :id") + suspend fun deleteById(id: String) + + @Query("UPDATE hemo_cube_test_table SET localFlag = :newValue WHERE _id = :id") + suspend fun updateFieldById(id: String, newValue: Boolean) +} \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/data/dao/MyDataBase.kt b/app/src/main/java/com/smi/counselling/data/dao/MyDataBase.kt new file mode 100644 index 0000000..3f26703 --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/dao/MyDataBase.kt @@ -0,0 +1,16 @@ +package com.example.hpostesting.data.dao + +import androidx.room.Database +import androidx.room.RoomDatabase +import androidx.room.TypeConverters +import com.example.hpostesting.data.model.patient.DeviceData +import com.example.hpostesting.data.model.patient.HemoCubeTestData +import com.example.hpostesting.data.model.patient.UserData + +@Database(entities = [UserData::class, HemoCubeTestData::class, DeviceData::class], version = 1, exportSchema = false) +@TypeConverters(Converters::class) +abstract class MyDatabase : RoomDatabase() { + abstract fun userDao(): UserDao + abstract fun hemoCubeDao(): HemoCubeDao + +} \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/data/dao/UserDao.kt b/app/src/main/java/com/smi/counselling/data/dao/UserDao.kt new file mode 100644 index 0000000..d0eb121 --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/dao/UserDao.kt @@ -0,0 +1,23 @@ +package com.example.hpostesting.data.dao + +import androidx.lifecycle.LiveData +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import com.example.hpostesting.data.model.patient.UserData + +@Dao +interface UserDao { + @Query("SELECT * from user_table") + fun getAll(): LiveData> + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertAll(userData: UserData) + + @Query("SELECT * FROM user_table WHERE _id = :id") + suspend fun getUserByID(id: String): UserData + + @Query("DELETE FROM user_table WHERE _id = :id") + suspend fun deleteById(id: String) +} \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/data/dashboard/DashboardActivity.kt b/app/src/main/java/com/smi/counselling/data/dashboard/DashboardActivity.kt new file mode 100644 index 0000000..1147958 --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/dashboard/DashboardActivity.kt @@ -0,0 +1,38 @@ +package com.smi.counselling.data.dashboard + +import android.content.Context +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import androidx.navigation.ui.AppBarConfiguration +import com.example.hpostesting.data.constant.LanguageManager +import com.smi.counselling.R +import com.smi.counselling.databinding.ActivityDashboardBinding +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class DashboardActivity : AppCompatActivity() { + private lateinit var appBarConfiguration: AppBarConfiguration + private lateinit var binding: ActivityDashboardBinding + + override fun attachBaseContext(newBase: Context?) { + val languageCode = LanguageManager.getSavedLanguage(newBase!!) + LanguageManager.setLocale(newBase, languageCode) + super.attachBaseContext(newBase) + } + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityDashboardBinding.inflate(layoutInflater) + setContentView(binding.root) + moveToNext() + } + + + private fun moveToNext() { + if (supportFragmentManager.isDestroyed) return + supportFragmentManager.beginTransaction().replace(binding.fghemocube.id, HomeFragment()) + .commit() + } + override fun onResume() { + super.onResume() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/data/dashboard/DigitalCardActivity.kt b/app/src/main/java/com/smi/counselling/data/dashboard/DigitalCardActivity.kt new file mode 100644 index 0000000..f0a8971 --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/dashboard/DigitalCardActivity.kt @@ -0,0 +1,34 @@ +package com.smi.counselling.data.dashboard + +import android.content.Context +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import com.example.hpostesting.data.constant.LanguageManager +import com.smi.counselling.databinding.ActivityDigitalCardBinding +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class DigitalCardActivity : AppCompatActivity() { + + private lateinit var binding: ActivityDigitalCardBinding + + override fun attachBaseContext(newBase: Context?) { + val languageCode = LanguageManager.getSavedLanguage(newBase!!) + LanguageManager.setLocale(newBase, languageCode) + super.attachBaseContext(newBase) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityDigitalCardBinding.inflate(layoutInflater) + setContentView(binding.root) + moveToNext() + } + + + private fun moveToNext() { + if (supportFragmentManager.isDestroyed) return + supportFragmentManager.beginTransaction().replace(binding.fghemocube.id, DigitalCardFragment()) + .commit() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/data/dashboard/DigitalCardFragment.kt b/app/src/main/java/com/smi/counselling/data/dashboard/DigitalCardFragment.kt new file mode 100644 index 0000000..348f8d9 --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/dashboard/DigitalCardFragment.kt @@ -0,0 +1,183 @@ +package com.smi.counselling.data.dashboard + +import android.annotation.SuppressLint +import android.content.Context +import android.content.SharedPreferences +import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher +import android.util.Log +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ArrayAdapter +import androidx.fragment.app.activityViewModels +import com.example.hpostesting.data.model.patient.HemoCubeTestData +import com.example.hpostesting.data.model.patient.toHemoCubeTestData +import com.google.firebase.crashlytics.ktx.crashlytics +import com.google.firebase.firestore.ktx.firestore +import com.google.firebase.ktx.Firebase +import com.smi.counselling.R +import com.smi.counselling.data.DataHolder +import com.smi.counselling.databinding.FragmentDigitalCardBinding +import dagger.hilt.android.AndroidEntryPoint +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Date +import java.util.Locale + +@AndroidEntryPoint +class DigitalCardFragment : Fragment() { + private lateinit var binding: FragmentDigitalCardBinding + private val hemoCubeViewModel: HomeViewModel by activityViewModels() + private lateinit var sharedPreferences: SharedPreferences + private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData() + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, + ): View { + binding = FragmentDigitalCardBinding.inflate(inflater, container, false) + sharedPreferences = + requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + + initViews() + } + + @SuppressLint("SetTextI18n") + private fun initViews() { + + + hemoCubeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isConnected -> + if (isConnected) { + loadUserData() + + } + } + + } + + private fun loadUserData() { + val AbhaIdList = mutableListOf() // Declare it outside the try block + + try { + val query = Firebase.firestore.collection("patientData") + + query.get().addOnSuccessListener { documents -> + for (document in documents) { + val abhaId = document.getString("abhaId") + + if (abhaId != null) { + AbhaIdList.add(abhaId) + } + } + } + + activity?.runOnUiThread { + val adapter = + ArrayAdapter(requireContext(), R.layout.dropdown_item, AbhaIdList) + binding.abhaidtext.addTextChangedListener(object : TextWatcher { + override fun beforeTextChanged( + s: CharSequence?, + start: Int, + count: Int, + after: Int + ) { + } + + override fun onTextChanged( + s: CharSequence?, + start: Int, + before: Int, + count: Int + ) { + } + + override fun afterTextChanged(s: Editable?) { + if (s?.length == 10) { + binding.abhaidtext.setAdapter(adapter) + } + } + }) + + + binding.abhaidtext.setOnItemClickListener { _, _, position, _ -> + val selectedAbhaId = adapter.getItem(position).toString() + loadUserDetails(selectedAbhaId) + } + } + } catch (e: Exception) { + // Handle exceptions + } + } + + private fun loadUserDetails(selectedAbhaId: String) { + try { + val patientQuery = Firebase.firestore.collection("patientData") + .whereEqualTo("abhaId", selectedAbhaId) + + patientQuery.get().addOnSuccessListener { patientDocuments -> + if (!patientDocuments.isEmpty) { + val patientDocument = patientDocuments.documents[0] + val commonId = patientDocument.getString("_id") + + val testQuery = Firebase.firestore.collection("testData") + .whereEqualTo("_id", commonId) + + testQuery.get().addOnSuccessListener { testDocuments -> + if (!testDocuments.isEmpty) { + val testDocument = testDocuments.documents[0] + val hemoCubeTestData = testDocument.toObject(HemoCubeTestData::class.java) + updateCategory(hemoCubeTestData) + + } + } + } + } + + } catch (e: Exception) { + Firebase.crashlytics.recordException(e) + } + } + + @SuppressLint("SetTextI18n") + private fun updateCategory(hemoCubeTestData: HemoCubeTestData?) { + binding.abhaid.visibility = View.GONE + binding.digitalcard.visibility = View.VISIBLE + binding.userCard.visibility = View.VISIBLE + + + activity?.runOnUiThread { + binding.name.text = "Name: ${hemoCubeTestData?.name ?: "N/A"}" + binding.dob.text = "DOB: ${hemoCubeTestData?.birthYear ?: "N/A"}" + binding.gender.text = "Gender: ${hemoCubeTestData?.gender ?: "N/A"}" + binding.State.text = "State: ${hemoCubeTestData?.state ?: "N/A"}" + binding.abhaid1.text = "ABHA ID: ${hemoCubeTestData?.abhaId ?: "N/A"}" + binding.blood.text = "Blood Group: ${hemoCubeTestData?.bloodGroup?: "N/A"}" + binding.sicklecell.text = "Sickle-Cell: ${hemoCubeTestData?.prdClassification ?: "N/A"}" + + Log.d("DigitalCardFragment", "State: ${hemoCubeTestData?.state}") + Log.d("DigitalCardFragment", "Blood Group: ${hemoCubeTestData?.bloodGroup}") + + } + // Update the UI with the fetched details + val originalDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()) + val originalDate: Date? = originalDateFormat.parse(SimpleDateFormat( + "yyyy-MM-dd HH:mm:ss", Locale.getDefault() + ).format(Calendar.getInstance().time)) + + val desiredDateFormat = SimpleDateFormat("MMM dd, yyyy", Locale.getDefault()) + val formattedDate: String = originalDate?.let { desiredDateFormat.format(it) } ?: "N/A" + activity?.runOnUiThread { + binding.issueDate.text = "Issue Date: ${formattedDate}" + } + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/data/dashboard/HomeFragment.kt b/app/src/main/java/com/smi/counselling/data/dashboard/HomeFragment.kt new file mode 100644 index 0000000..4162560 --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/dashboard/HomeFragment.kt @@ -0,0 +1,336 @@ +package com.smi.counselling.data.dashboard + +import android.annotation.SuppressLint +import android.content.Context +import android.content.Intent +import android.content.SharedPreferences +import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ArrayAdapter +import android.widget.TextView +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import com.example.hpostesting.data.model.patient.HemoCubeTestData +import com.example.hpostesting.data.model.patient.toHemoCubeTestData +import com.google.firebase.crashlytics.ktx.crashlytics +import com.google.firebase.firestore.ktx.firestore +import com.google.firebase.ktx.Firebase +import com.smi.counselling.R +import com.smi.counselling.data.DataHolder +import com.smi.counselling.databinding.FragmentHomeBinding +import dagger.hilt.android.AndroidEntryPoint +import java.util.Locale + +@AndroidEntryPoint +class HomeFragment : Fragment() { + private var _binding: FragmentHomeBinding? = null + private val binding get() = _binding!! + private val hemoCubeViewModel: HomeViewModel by activityViewModels() + private lateinit var sharedPreference: SharedPreferences + private var maleresult: String = "" + private var femaleresult: String = "" + private val testDetails = DataHolder.selectedTest?.toHemoCubeTestData() + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + _binding = FragmentHomeBinding.inflate(inflater, container, false) + + // Check if _binding is null + if (_binding == null) { + // Handle the case where binding could not be initialized + // You may want to log an error or return a default view in this case + return super.onCreateView(inflater, container, savedInstanceState) + } + + sharedPreference = + requireContext().getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE) + + + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + + + + + hemoCubeViewModel.networkStatusLiveData.observe(viewLifecycleOwner) { isConnected -> + if (isConnected) { + loadUserData() + + } + activity?.runOnUiThread { + binding.btnSubmit.setOnClickListener { + when { + binding.maledetails.visibility == View.VISIBLE && binding.femaledetails.visibility == View.VISIBLE -> { + binding.btnSubmit.visibility = View.GONE + classifyAndDisplay(testDetails, binding.result) + } + + + else -> { + // Handle the case where neither male nor female details are visible + } + } + + + binding.btnDigital.setOnClickListener { + val i = Intent( + requireContext().applicationContext, DigitalCardActivity::class.java + ) + startActivity(i) + } + } + } + } + + + } + + private fun loadUserData() { + try { + val query = Firebase.firestore.collection("patientData") + + query.get().addOnSuccessListener { documents -> + val maleAbhaIdList = mutableListOf() + val femaleAbhaIdList = mutableListOf() + + for (document in documents) { + val abhaId = document.getString("abhaId") + val gender = document.getString("gender") + + if (abhaId != null && gender != null) { + when (gender.lowercase(Locale.getDefault())) { + "male" -> maleAbhaIdList.add(abhaId) + "female" -> femaleAbhaIdList.add(abhaId) + } + } + } + + activity?.runOnUiThread { + + val femaleAdapter = + ArrayAdapter(requireContext(), R.layout.dropdown_item, femaleAbhaIdList) + + + val maleAdapter = + ArrayAdapter(requireContext(), R.layout.dropdown_item, maleAbhaIdList) + + binding.abhaidtext.addTextChangedListener(object : TextWatcher { + override fun beforeTextChanged( + s: CharSequence?, + start: Int, + count: Int, + after: Int + ) { + } + + override fun onTextChanged( + s: CharSequence?, + start: Int, + before: Int, + count: Int + ) { + } + + override fun afterTextChanged(s: Editable?) { + if (s?.length == 10) { + binding.abhaidtext.setAdapter(maleAdapter) + } + } + }) + + binding.abhaidtextfemale.addTextChangedListener(object : TextWatcher { + override fun beforeTextChanged( + s: CharSequence?, + start: Int, + count: Int, + after: Int + ) { + } + + override fun onTextChanged( + s: CharSequence?, + start: Int, + before: Int, + count: Int + ) { + } + + override fun afterTextChanged(s: Editable?) { + if (s?.length == 10) { + binding.abhaidtextfemale.setAdapter(femaleAdapter) + } + } + }) + + + + binding.abhaidtext.setOnItemClickListener { _, _, position, _ -> + val selectedAbhaId = maleAdapter.getItem(position).toString() + loadUserDetails(selectedAbhaId) + } + + binding.abhaidtextfemale.setOnItemClickListener { _, _, position, _ -> + val selectedAbhaId = femaleAdapter.getItem(position).toString() + loadUserDetails(selectedAbhaId) + } + } + } + } catch (e: Exception) { + // Handle exceptions + } + } + + private fun loadUserDetails(selectedAbhaId: String) { + try { + // Query the patientData collection to get the document with the selectedAbhaId + val patientQuery = Firebase.firestore.collection("patientData") + .whereEqualTo("abhaId", selectedAbhaId) + + patientQuery.get().addOnSuccessListener { patientDocuments -> + if (!patientDocuments.isEmpty) { + val patientDocument = patientDocuments.documents[0] + val commonId = patientDocument.getString("_id") + + // Query the testData collection using the commonId + val testQuery = Firebase.firestore.collection("testData") + .whereEqualTo("_id", commonId) + + testQuery.get().addOnSuccessListener { testDocuments -> + if (!testDocuments.isEmpty) { + val testDocument = testDocuments.documents[0] + val hemoCubeTestData = + testDocument.toObject(HemoCubeTestData::class.java) + + if (hemoCubeTestData?.gender.equals("male", ignoreCase = true)) { + updateMaleCategory(hemoCubeTestData) + } else if (hemoCubeTestData?.gender.equals( + "female", + ignoreCase = true + ) + ) { + updateFemaleCategory(hemoCubeTestData) + } + if (binding.maledetails.visibility == View.VISIBLE && binding.femaledetails.visibility == View.VISIBLE) { + activity?.runOnUiThread { + binding.btnSubmit.visibility = View.VISIBLE + } + } + } + } + } + } + + } catch (e: Exception) { + Firebase.crashlytics.recordException(e) + } + } + + + @SuppressLint("SetTextI18n") + private fun updateMaleCategory(hemoCubeTestData: HemoCubeTestData?) { + binding.maledetails.visibility = View.VISIBLE + + binding.userid.text = "userId: ${hemoCubeTestData?._id ?: "N/A"}" + binding.gender.text = "gender: ${hemoCubeTestData?.gender ?: "N/A"}" + binding.username.text = "Name: ${hemoCubeTestData?.name ?: "N/A"}" + maleresult = hemoCubeTestData?.prdClassification.toString() + Log.e("result", maleresult) + binding.State.text = "Result: $maleresult" + } + + @SuppressLint("SetTextI18n") + private fun updateFemaleCategory(hemoCubeTestData: HemoCubeTestData?) { + binding.femaledetails.visibility = View.VISIBLE + + binding.userid1.text = "userId: ${hemoCubeTestData?._id ?: "N/A"}" + binding.gender1.text = "gender: ${hemoCubeTestData?.gender ?: "N/A"}" + binding.username1.text = "Name: ${hemoCubeTestData?.name ?: "N/A"}" + femaleresult = hemoCubeTestData?.prdClassification.toString() + Log.e("result", maleresult) + binding.State1.text = "Result: $femaleresult" + } + + + private fun classifyAndDisplay(hemoCubeTestData: HemoCubeTestData?, textView: TextView) { + activity?.runOnUiThread { + binding.result.visibility = View.VISIBLE + binding.maledetails.visibility = View.GONE + binding.femaledetails.visibility = View.GONE + // Get the results at the time of classification + val parent1Classification = maleresult + val parent2Classification = femaleresult + + Log.e("Result", "Parent 1 Classification: $parent1Classification") + Log.e("Result", "Parent 2 Classification: $parent2Classification") + + // Perform the classification + val classification = classifyChild(parent1Classification, parent2Classification) + Log.e("Result", "Classification Result: $classification") + textView.text = "Sickle-cell-Result: $classification" + binding.btnDigital.visibility = View.VISIBLE + } + } + + private fun classifyChild( + parent1Classification: String, + parent2Classification: String + ): String { + val parent1 = parent1Classification.trim().lowercase(Locale.getDefault()) + val parent2 = parent2Classification.trim().lowercase(Locale.getDefault()) + + return when { + parent1 == "sickle cell disease" && parent2 == "sickle cell disease" -> { + "child will be 100% chance of the child having the disease" + } + + parent1 == "sickle cell trait" && parent2 == "sickle cell disease" -> { + "child will be 50% chance of being diseased and 50% chance of being a carrier" + } + + parent1 == "sickle cell disease" && parent2 == "sickle cell trait" -> { + "child will be 50% chance of being diseased and 50% chance of being a carrier" + } + + parent1 == "normal" && parent2 == "sickle cell disease" -> { + "child will be 100% chance of being a carrier" + } + + parent1 == "sickle cell disease" && parent2 == "normal" -> { + "child will be 100% chance of being a carrier" + } + + parent1 == "sickle cell trait" && parent2 == "sickle cell trait" -> { + "child will be 25% chance of being diseased, 25% chance of being normal, and 50% chance of being a carrier" + } + + parent1 == "sickle cell trait" && parent2 == "normal" -> { + "child will be 50% chance of being normal and 50% chance of being a carrier" + } + + parent1 == "normal" && parent2 == "sickle cell trait" -> { + "child will be 50% chance of being normal and 50% chance of being a carrier" + } + + else -> { + "Unknown result" + } + } + } + + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } +} + diff --git a/app/src/main/java/com/smi/counselling/data/dashboard/HomeViewModel.kt b/app/src/main/java/com/smi/counselling/data/dashboard/HomeViewModel.kt new file mode 100644 index 0000000..b537470 --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/dashboard/HomeViewModel.kt @@ -0,0 +1,59 @@ +package com.smi.counselling.data.dashboard + +import android.content.Context +import android.content.SharedPreferences +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.hpostesting.data.dao.HemoCubeDao +import com.example.hpostesting.data.dao.UserDao +import com.example.hpostesting.data.model.patient.DeviceData +import com.example.hpostesting.data.model.patient.HemoCubeTestData +import com.example.hpostesting.data.model.patient.toHemoCubeTestData +import com.smi.counselling.data.DataHolder +import com.smi.counselling.data.NetworkStatusLiveData +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import javax.inject.Inject +@HiltViewModel +class HomeViewModel @Inject constructor( + private val hemoCubeDao: HemoCubeDao, + private val userdao: UserDao, + context: Context, +) : ViewModel() { + var isServiceConnected = false + val progressBar = MutableLiveData(false) + val testDetails = DataHolder.selectedTest?.toHemoCubeTestData() + val messages = MutableLiveData() + private val sharedPreference: SharedPreferences = + context.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE) + + // Get the device ID of the device you want to retrieve data for (e.g., the first device in the list) + + private val _networkStatusLiveData = NetworkStatusLiveData(context) + val allUserData = hemoCubeDao.getAll() + val deviceData = MutableLiveData() + val networkStatusLiveData: LiveData + get() = _networkStatusLiveData + + private fun updateLocalFlag(userId: String) = + viewModelScope.launch { + 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/java/com/smi/counselling/data/domain/AppModule.kt b/app/src/main/java/com/smi/counselling/data/domain/AppModule.kt new file mode 100644 index 0000000..acc58a4 --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/domain/AppModule.kt @@ -0,0 +1,55 @@ +package com.smi.counselling.data.domain + +import android.app.Application +import android.content.Context +import androidx.room.Room +import com.example.hpostesting.data.dao.HemoCubeDao +import com.example.hpostesting.data.dao.MyDatabase +import com.example.hpostesting.data.dao.UserDao +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +object AppModule { + + @Provides + @Singleton + fun provideMyDatabase(@ApplicationContext context: Context): MyDatabase { + return Room.databaseBuilder( + context, MyDatabase::class.java, "my_database" + ) + .fallbackToDestructiveMigration() + .build() + } + + @Provides + @Singleton + fun provideMyDao(myDatabase: MyDatabase): UserDao { + return myDatabase.userDao() + } + + @Provides + @Singleton + fun provideMyHemo(myDatabase: MyDatabase): HemoCubeDao { + return myDatabase.hemoCubeDao() + } + + + @Provides + @Singleton + fun provideContext(application: Application): Context { + return application.applicationContext + } + + + + + + + +} \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/data/model/patient/DeviceData.kt b/app/src/main/java/com/smi/counselling/data/model/patient/DeviceData.kt new file mode 100644 index 0000000..cefc5b9 --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/model/patient/DeviceData.kt @@ -0,0 +1,19 @@ +package com.example.hpostesting.data.model.patient + +import androidx.room.Entity +import androidx.room.PrimaryKey +import com.google.firebase.firestore.PropertyName + +@Entity(tableName = "device_table") +data class DeviceData( + @PrimaryKey + var _id: String = "", + @get:PropertyName("deviceId") @set:PropertyName("deviceId") + var deviceId: String = "", + @get:PropertyName("deviceType") @set:PropertyName("deviceType") + var deviceType: String = "", + @get:PropertyName("coefficients") @set:PropertyName("coefficients") + var coefficients: List = emptyList(), + @get:PropertyName("calibratedAt") @set:PropertyName("calibratedAt") + var calibratedAt: String = "" +) \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/data/model/patient/HemoCubeTestData.kt b/app/src/main/java/com/smi/counselling/data/model/patient/HemoCubeTestData.kt new file mode 100644 index 0000000..6426955 --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/model/patient/HemoCubeTestData.kt @@ -0,0 +1,77 @@ +package com.example.hpostesting.data.model.patient + +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName = "hemo_cube_test_table") +data class HemoCubeTestData( + @PrimaryKey + var _id: String = "", + var name: String = "", + var incubationTime: String = "", + var bloodGroup: String = "", + var birthYear: String = "", + var state: String = "", + var abhaId: String = "", + var userImageURL: String = "", + var location: UserData.Location? = null, + var reportUploadTime: String? = "", + var testType: String? = "HEMOCUBE", + var testTime: String? = "", + var testStatus: Boolean? = false, + var gender: String = "", + var localFlag: Boolean = false, + var deviceId: String? = "", + var appVersion:String? = "", + var deviceSerialNumber: String = "", + var deviceType: String = "HEMOCUBE", + var kitSerial: String = "", + var resultData: String = "", + var led1Buffer: Double? = null, + var led2Buffer: Double? = null, + var led3Buffer: Double? = null, + var led4Buffer: Double? = null, + var led1Sample: Double? = null, + var led2Sample: Double? = null, + var led3Sample: Double? = null, + var led4Sample: Double? = null, + var led1Average: Double? = null, + var led2Average: Double? = null, + var led3Average: Double? = null, + var led4Average: Double? = null, + var abs1: Double? = null, + var abs2: Double? = null, + var abs3: Double? = null, + var abs4: Double? = null, + var led1Gain1: Double? = null, + var led2Gain1: Double? = null, + var led3Gain1: Double? = null, + var led4Gain1: Double? = null, + var led1Gain2: Double? = null, + var led2Gain2: Double? = null, + var led3Gain2: Double? = null, + var led4Gain2: Double? = null, + var led1Gain3: Double? = null, + var led2Gain3: Double? = null, + var led3Gain3: Double? = null, + var led4Gain3: Double? = null, + var led1Gain4: Double? = null, + var led2Gain4: Double? = null, + var led3Gain4: Double? = null, + var led4Gain4: Double? = null, + var deviceRatio: Double? = null, + var calculatedRatio: Double? = null, + var predictedDenovixRatio: Double? = null, + var slopeRatio: Double? = null, + var coefficients: String? = "", + var classificationResult: String = "", + var prdClassification: String = "", + var deviceRatioClass: String = "", + var slopeRatioClass: String = "", + var errorMessages: String = "", + var batteryLevel: String = "", + var batteryCapacity: String = "", + var batteryMaxCapacity: String = "", + var batteryTemperature: String = "", + var batteryVoltage: String = "", +) diff --git a/app/src/main/java/com/smi/counselling/data/model/patient/PatientData.kt b/app/src/main/java/com/smi/counselling/data/model/patient/PatientData.kt new file mode 100644 index 0000000..9d0408c --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/model/patient/PatientData.kt @@ -0,0 +1,70 @@ +package com.example.hpostesting.data.model.patient + +import java.util.Date + +data class PatientDetails( + var id: String, + var isIdABHA: Boolean, + var name: String?, + var yob: Int?, + var gender: Gender?, + var mobile: String?, + var isUnderMedication: Boolean?, + var isUnderTransfusion: Boolean?, + val photoUrl: String?, + var careOf: String?, + var isMarried: Boolean?, + var bloodGroup: String?, + var address: Address?, + var category: Category?, + var registerDate: Date?, + var uploadDate: Date? +) { + constructor() : this( + "", + false, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ) + + enum class Gender { + MALE, + FEMALE, + OTHER + } + + + data class Address( + var house: String?, + val street: String?, + var city: String?, + val landMark: String?, + var postOffice: String?, + var district: String?, + val subDistrict: String?, + var state: String?, + val vtc: String?, + var pinCode: Int?, + ) { + constructor() : this(null, null, null, null, null, null, null, null, null, null) + } + + enum class Category { + GENERAL, + OBC, + SC, + ST, + } +} diff --git a/app/src/main/java/com/smi/counselling/data/model/patient/UserData.kt b/app/src/main/java/com/smi/counselling/data/model/patient/UserData.kt new file mode 100644 index 0000000..ff30bdd --- /dev/null +++ b/app/src/main/java/com/smi/counselling/data/model/patient/UserData.kt @@ -0,0 +1,58 @@ +package com.example.hpostesting.data.model.patient + +import androidx.room.Entity +import androidx.room.PrimaryKey + + +@Entity(tableName = "user_table") +data class UserData( + @PrimaryKey + var _id: String = "", + var name: String = "", + var incubationTime: String = "", + var birthYear: String = "", + var abhaId: String = "", + var bloodGroup: String = "", + var userImageURL: String = "", + var gender: String ="", + var location: Location? = null, + var createdBy: String? = "", + var reportUploadTime: String? = "", + var testTime: String? = "", + var testStatus: Boolean? = false, + var mobileId: String = "", + var deviceId: String = "", + var state: String = "", + var deviceSerialNumber: String = "", + var kitSerial: String = "", + var csvPath: String = "", + var reportPath: String = "", + var resultRatio: Double? = null, + var prdClassification: String = "" +) { + enum class Gender { + MALE, + FEMALE, + OTHER + } + + data class Location( + var latitude: Double? = null, + var longitude: Double? = null + ) +} + +fun UserData.toHemoCubeTestData() = HemoCubeTestData( + _id = _id, + name = name, + birthYear = birthYear, + userImageURL = userImageURL, + testStatus = testStatus, + location = location, + gender = gender, + state = state, + abhaId = abhaId, + bloodGroup = bloodGroup, + prdClassification = prdClassification, + testTime = testTime +) diff --git a/app/src/main/java/com/smi/counselling/ui/theme/Color.kt b/app/src/main/java/com/smi/counselling/ui/theme/Color.kt deleted file mode 100644 index 77c2b13..0000000 --- a/app/src/main/java/com/smi/counselling/ui/theme/Color.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.smi.counselling.ui.theme - -import androidx.compose.ui.graphics.Color - -val Purple80 = Color(0xFFD0BCFF) -val PurpleGrey80 = Color(0xFFCCC2DC) -val Pink80 = Color(0xFFEFB8C8) - -val Purple40 = Color(0xFF6650a4) -val PurpleGrey40 = Color(0xFF625b71) -val Pink40 = Color(0xFF7D5260) \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/ui/theme/Theme.kt b/app/src/main/java/com/smi/counselling/ui/theme/Theme.kt deleted file mode 100644 index 1a785ca..0000000 --- a/app/src/main/java/com/smi/counselling/ui/theme/Theme.kt +++ /dev/null @@ -1,70 +0,0 @@ -package com.smi.counselling.ui.theme - -import android.app.Activity -import android.os.Build -import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.darkColorScheme -import androidx.compose.material3.dynamicDarkColorScheme -import androidx.compose.material3.dynamicLightColorScheme -import androidx.compose.material3.lightColorScheme -import androidx.compose.runtime.Composable -import androidx.compose.runtime.SideEffect -import androidx.compose.ui.graphics.toArgb -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalView -import androidx.core.view.WindowCompat - -private val DarkColorScheme = darkColorScheme( - primary = Purple80, - secondary = PurpleGrey80, - tertiary = Pink80 -) - -private val LightColorScheme = lightColorScheme( - primary = Purple40, - secondary = PurpleGrey40, - tertiary = Pink40 - - /* Other default colors to override - background = Color(0xFFFFFBFE), - surface = Color(0xFFFFFBFE), - onPrimary = Color.White, - onSecondary = Color.White, - onTertiary = Color.White, - onBackground = Color(0xFF1C1B1F), - onSurface = Color(0xFF1C1B1F), - */ -) - -@Composable -fun HPOSCounsellingTheme( - darkTheme: Boolean = isSystemInDarkTheme(), - // Dynamic color is available on Android 12+ - dynamicColor: Boolean = true, - content: @Composable () -> Unit -) { - val colorScheme = when { - dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { - val context = LocalContext.current - if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) - } - - darkTheme -> DarkColorScheme - else -> LightColorScheme - } - val view = LocalView.current - if (!view.isInEditMode) { - SideEffect { - val window = (view.context as Activity).window - window.statusBarColor = colorScheme.primary.toArgb() - WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme - } - } - - MaterialTheme( - colorScheme = colorScheme, - typography = Typography, - content = content - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/smi/counselling/ui/theme/Type.kt b/app/src/main/java/com/smi/counselling/ui/theme/Type.kt deleted file mode 100644 index ba875b2..0000000 --- a/app/src/main/java/com/smi/counselling/ui/theme/Type.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.smi.counselling.ui.theme - -import androidx.compose.material3.Typography -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.sp - -// Set of Material typography styles to start with -val Typography = Typography( - bodyLarge = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, - fontSize = 16.sp, - lineHeight = 24.sp, - letterSpacing = 0.5.sp - ) - /* Other default text styles to override - titleLarge = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, - fontSize = 22.sp, - lineHeight = 28.sp, - letterSpacing = 0.sp - ), - labelSmall = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Medium, - fontSize = 11.sp, - lineHeight = 16.sp, - letterSpacing = 0.5.sp - ) - */ -) \ No newline at end of file diff --git a/app/src/main/res/drawable/indianoil.jpg b/app/src/main/res/drawable/indianoil.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3f6e528be888181720051ffff466e6e4ace3e23f GIT binary patch literal 17734 zcmdqJXH-*byEYm{MMaHBuUU$85S5Nd)=~ihAyPtzhzLj!kR|~_vJ~kcYf%+}EDRWm z2uPC}A(RCONS7icK{`kx5GEvqZ?5;~jKXlLzfk7aLj{bWLhk1@1J;r$>Bf5@K=A6*Kl6{v+^B37vKnMuRKFki?8Hf75m7O5Svh$HMI{YQ zEo~iLy_>fTjf`)bm|EK)ZSCwG9NiyyczQkbMh69lJPE~wg-1P)j){$nPe@Hm&&bSr z`6~Mjv7qoRsi?T*LsfN6ZQaNEhBiujM`zdH-91CYBco&EUneGM^ttcz3yVw3E6ksp zTidK1V0Z5yyADBk{?qh-8}|RQ3v|Mv!$*$r9O3=Pu0w}I!9O1UBS+6)Id<+hOJ27C zfeTlk9v8gvXMSbt2^n=OhS2@M!IQ!lHE6QTe@y$AW&dY}J^LS7_Me9R-*!zxPVpQ9 zZypan1P<&60Z-TC{Bi(UFepuh^};wu@qg-Xa=r0X1c$;E zRcDDGK!{iN)8R}h+*$l4%=jWa6Aqj_fc&yZ*fcwU9L6tTNot$1 zz)`jYAU=%Dtv-Mp2VB)AdTADoOkTQht)oKz7XuiE&ya!KNYHmG=?l1C)09}~Jv8Cn zxgwE#f5*I1Ejah9WVz5QB+Fi3yCz_)VAoyThBy|2?)gFzOv7z9R#{qwi`sPzQ;hR! zyaczB!d~ahKK#wqD&o<*I$u=;B_#z`Etf%$znAz4#;}+Lq<3V7&x11t%?)Mi@bzO;asz|$4V=o$g?4ZXr@1K=nN;ylGMi4k*OY|-*=FgUzTiX z4iyf^@ALc-32nj+EZ^i$=%M{#UF>DPSpUN*v)>Yrw%7mQ&}k5zT}4W0`%*SOF=f{| zh3kfYkSgd7f<@u|Rh8^dzPz+`0GYC;#o`zH^^~4F58@`^S9!;rRbumW7?TOGv`=c3cD{>6pcD0FFhnlBdU%8?O zkX8ho`VtQD*B6OoVKp}JY&&kJt%1RazP5YV;SV=UIkzhrd0Fl%0n;m|J^f^#<4W7O zdKkX0Kw@kUkamGG$2_A!dye54Ll>@=Yd@qddE{8f_IkVfY-$kARLhb=P>rV6H3NSG zRZ9nuIRcMSGj=L!vj>pW%UOK!iMGT%gAzY$mnqkx7V9&&LR~Ua?6K||YKzb;Lkbn| zkr^l!`2g}P?BTfU3C8&P{sH7j-+m_ffgKPV_6Xf zDYF$8RU~`#p7GjK_W6|ti&8J&qUG$juNgelK2~ng@=irzU+#AFdinFh+NP?;y3}il zKBZv~o?#xC+z&Ojg=;Mr)rnbKraM_BCYWoi4V$}YYuKfXos?3SX!}qCiPJrj|lw&vwYReP;A(kss z-Uj8mFMW^w*>wOpg!(S|AF*lRI}i8FVc;f%K%HGrV+>PZ$8n z+M1X+$o?qHXlUs&7oK*R!fk$=ee(m4I)GGoabAwExgS70^Vxa_kd?m}k--#d3gEsg zlZ}@occ}Fd>_*Sw?&Di;;;Daaa(fnAQHOCn0Q?Rx#rESosUDS}cD1fHJ4&fha6*iQ ztfSL;7l3tUmy5PmB}Se~_}zD{yhh61mfSq_op~zTg_~74`*m`ed!ES~8<|t8WIyX2 z-(iy}p-R!&cRx$))9p7`aI5%I6>>$>$@Ge;sfbmoZ>IpggZ}M|qs^NVI-0b$Jkz5n zA6_FpNIE^`8{|+h`Wn^i1WdW4(J$386ODn&BJ7iWlD?7fFdfPfl7t7vJGPG!p_kByOl6tV7SJFp0)IO&HpR|GaqJqL1W2%#yz1h zsdowQ5edV^Ii$ec7+7DrD)xyvMJEfvpXISdW$Z5UyE$4%hg+9Qd=HZi9?Flm@p`#n zBe{AnllQbW?@QZ-;B|pJLyIHjzP{hK&Hb3$YG-}2cC;PKCYxsaR%U@Wk2UTUFonXJEf`H`-;ZU z@#*5rqFq>DV_?K}u&Ni+y$7FLne7|WTu;#~cze&MF<$(Z!Qi@_u~QQB6V5$xU;g;d z5@6aePac+#%9T@-aBPtyHWu5O*P_Qi6YdB??jCW4HH>4A=gA{tcf#ee3NiE2YVoks z93(ALy$i*IyW-G2AGYV;iHgb|M4iOYufnkm2QXQ>Sz`T^{aojlV z#49&<#o|b7wj_6A=JNhCf)i7%wM@RVMRh;9NnWr;cAo^l*XQ1zbpSbw`-R&r4Q(1# zrH+!l2fn6t>J1r|W0Ct=TiS z9dt}2&hPW?@?k!2at!~fmfZE3ibT%+E1VMIOTb` zVD6N;PFtb)D82#_LpaxTl$r8L8VVFM8au+ZU*M!M>|ckQEU5<&VF0)89~>ERWAvU= zqVlTlh%)5w8E4jTf%X%-D}7!ON1LYwT45n*&Bxp5yX6)(B}1>HO@nOHJw!aSIoS>9 zKCNu8?i-JbkN2OmdOno?pvL?Vs=LVSO~6q>p06FXk_2PT4y5}p>6&rzG0rtA!<@}w$;x0sP`SqprLq|`V_9#>L^;+jtxE;X={Gy zwlq=(kKu35TwiI%kq3fcek6W+&Iep<5= z;saB=6%WYUJnkap0Z!)lAAm(!(Dd?s@RkZIV)~gbVp=`3r{UxFGmPH@9`<0@c>i|v|)yK z+sAr+y7p$5qNuWJ{6U|MVN9H`CV+~)vgKy1R*uMyi6jh1>myZK-g)MrJ#;k{X#oz& zVy=1Dgit4*6|Yx}Y@SrR_#eH~Wr!pMLWSr+g3EvYRy*ZeJJslKJN2z@v}*r}$;DKY zi|m_-*$v3K>j-X`$@4WY&OKfa`+Q5uOi8;palvO5dUd3a;8? z6@dCebU41Fd;&ljlccN-nc6XB!MSJAlU)hrPWx>=K^#)M>*;P_>cV?wa6p)+h?MwG z%VeypgXZJ?iJZ*wM-f zTlct6V-4yWN=KCcsBe7@yxy4|qR=rEEZ#}wb%jrxft zpCqr1=$}4-l;Y>g0>^=Iz;2KH3*xBWbKs!1x+sWdC_skSL^B7yHRF_x4A_0TV;HZv=u>G`8z%?}sK;xW8*N+Cos5 z2=k9CbrgLhbjG_zXuT47-h5M2D5CDcBu8aPAMwDKG=jC8E8}aI)?f;gN`bnrJlQn6 z;Y_?BhTYMSI~&LGrAI`we?6f^rbi-dMqOo*3DYio7@36QZ{pz;82_e$3KRN5CoAd7 zgdC(=95Y%QGmYuCGdwRY+e)d0rC_uNP&VwgrEDs>DDk2AvOHja+qj~_jdFkl^Br5sZ0VMU|0mQEA z0J6uw2m>B<9zcHn{{Po6p{F{L+g)Vnq*n4FAhTz-3xAd)0`J`T-7zn|Xv*0qkAEL@ zgu9E36R^s#>yVawSePv(k7N=kQap3UZ7y~;805BY4f&Awum#F&$US9Wa_?jSE+DHn zjsqX4c$IPLDAbEE&nNY~eK240jGN;N>-LYLHsuyq(Dq42X0N`qS*OkiS3RMKHYBuLr}Fr8ruQaL$2CbmnC+bE+cpPM;n}B_OV|3aUVFU#c8@+m!&CuRL)!zic0gPt&SADX5URBT-?Jxp3j_82V|f~ zyL{6R2av4vIk`ry=J^ANU(f1yyey0nXvZO_wUx6qp*;ANSzy)G9G{Gj#y#3n_&?9m z94~xpP|L+x6Z$Nm3Qd>^tBhdEa8IPL`7w?mL5ouuM_8<@#(qi5FWzoH@95!(bEqTU z0?qHv2-DVG&58!Hd*GI|66FcTno4zH&Vss&6v79=V`{r09wO_>YDu{{AEevzs0}sS z>Xv2K+pYA|)ucz+qITSxUjB^0Fx)uoO{nr(*Jakxpaxp(3;zN|N0W7-+jpe9PXOo0L6Qt<)W1I8A#WcjQVddjXo@0y$V%$`o( zg%ajVeNB~1ddXgKMWmQ#y*>j%;=%I+HxR2Y>~W}++@HPQ=1q6%uIo1_C8N_yZ&B(+yMh@g0OK@g7X!byAHGT}Z{LU)mKFy5-(Z7) zMmHuet1pW6hEd)=o0umtT$6GNAhjBtWXQKgMzHQMP!whWT~%(eZBMPkZY-vlwx}(A zh1r=_ zS<2+W7AWpZEviZ+`E5%S>sj>}N12ItWg3*y5GOIp9od%%43wR?MdkZdz3bdGq4mNa z#WeMI4k&vEAP;a7o1IP(XuP}7qb{Uk#6RaEzE@xnb3AoP8xJJsYj5>*#lq zrQ>SHF{*qSDjpJ<^qN(dY%DL@X=44vx70;jVyR$21jq$l`2q-G_|Rh$TKKRQpjY2; z+obt{d}<1R9}Omixxs}_;v#PvF{PS{k4z%l_wZ|*VI&j%z`x^MCx1S?N;&sus-D8) zXr+10EX?xFKs=n?rm)L)z@#4(3ZY1xRoqnIkw#~THU8C+rH&`CR0!MiI<+HyJKna z(r`8@HedE+&58{&GUtB5q~*e5wXC8-SEg0@T7AjzUrf=5{b$ZP52pqeTLu~NC#I-B zscNndG12;w^$lLZ%Q-ts4Nbk0hBP6rC=(n|8qlN`l5lmK(I#f0E*Hza(oSFiJRh@iX?YJGh= zSppWNdr3al`KP4xk)~B`cgw}xeERu`$$!mgJs(adi3gBu&slJWp4B$%+^J2cv3E|` zgcO=yN%kH_m+92$35iq|l|A^rcq}h7DR&@QAB2UD$kYR*w-|T_{tTR&Pp+70q?N~$ zVT=2(IDA@JA#7vk)(GZk^$7C_?4-0A`RSE!Aao!u)X_rpk!#A1EMw)_vLq&mp5a?c z0ooNI=baQk6ZLeENu{4F;@@fRN=07Ldc0t+DN(&uIUre;Yjn4RmYs`omx%CUPodHP zJB!Ix4`08q7lq(dLKtHiYV9w7kf}sM<<=Lh6jQjI22aR-`-)mVCF1x6dx)-jlC@zm zT1^(hBpU6%QrnWc5MkEK_xGzGHG41hSJ;0r5M8KsI; zi>ss)?t%r`-b)QDX1(n8ILZn$#F+T;Uzg#TGrlOszc;e;U~7(4us~_&Dbaexn6f$67Hm zE05(DPx_oQc|WzEWm;dYEppb)?y5tlfX*kp7oG7l|9Sh3>eVK=tP;1QKOI(8X63vS zP%Qk0UN7}MFPd_CTkj(X1lbcUEoyXcTxMlu7~mXwXP(=smJ7dbX>?pyO$+d{J`8OROtDj85pL4IEXB0nF*V)RxsjZdP!u<6-`X>=-i2U^p z`5N6H54$P2)8$c*yM$;W#U@GM{3lk)#aj+ujj_chzBdKp-ZaZtcH@^_!PId8`7c=t zCI9bU@_NI6r{Kk(on<(uKwYomTTxi8bGI58b{xSp?ulOO6^-n{^TBqczK0 zW~5&;C*`^_AHDh6PWEcB{r!UJN!TcWM(>{5v*}TPr2m8~E7=RxRg>>2UwHRpjMTjV zR%G}TdpaWn26)933+^qwuFIlE#veeAo*w3?mvP%*Vq7Ke*8@mRY%Ad$fT!cvz7fCT zdf{iu?&VY3tbBhS+z<+elU~jf8`c=$QCmZlVWv7^RqN!a>g!%N2aVgy@U5(Hqu2Q; z*ABYVz$uJZduUeRk}J+?QE~u!Q|%M|yq;*czON)jtu^9~wD3EUydB#}W0{_7Vr0d- zQuO_M+Oyo-vVAS8hBP#S-!&)0RQW3c8du)y`0ku3%r?EyEJLGy+RB7IU74}o$#LCp z#6st0r-E3E407AXlmts}5bsqE15tb|kb6Y22i7TwqFtYLtJs2SNJpX_?){pUbr;i(U0Ds`&GD7DYB z355ulS*nhtuvWT^wS-l*4C+L3YL4u6*^^r%;?HxOr#&8&+$ZW=$Z0S|LyY{MZ>SiC zpG!+V-ue;wS9YqCY0m4WRJ67oUd9RE`YWEA1tx|xI_xW>Ze4Y5c4CSGW85u2${oS+ z?vt=mbBNeItwy#Hkmr=k3ldEG6-{1Dc4>|DX`1t& zrNPbPJ@wq0XV#gpogt#6vyV}=$B|Xj<+`|ZI!U3;&*CasJ-NK3ad(x~2rl@Flo&!y z?0OarHc?00Sc{nR6`=dCH`8HBdS2@R?>XXt3$wRNeB<{TDY)TaY*e*N1l=fl4t3mw zicGT*U&x5`C{X>86&h69k{fa)yKtVeeebH8@6+BDcclfvd1KWWDXL6dSxljLWnfly zxk^1InkcW=rRL8jAC1` zkdkwM`mSd)G2L0?d#c@hS|ehF>^T4^Zmjjr^*OO_jBBI%3FJGC_41p`BuMv1VCAbK<8%RC?ewHYf=m-E18kfj*r%c zf5=*orIQo5B0wU8+%bCsE5O#`7&HA}=%e%=&PwCayyHz8d0GS%;6sZqtB!C%+++$e zRvnMM%-l}w#;?H5n(uY3z2ST!IkWH_f5m!}Shu}uf)<$TL_V=Wqt ztTttPfwu7R=NsF;x*=s+s56I(yak*wYPJ@kl#GCnFPvTU{vgHm29j=yrh8Z)(ihUx zVCra|=++Cl0-a4Z6sGTPr6T!BtaOFe2CJk(giylbn<>k7qb8CPvi=Q0!<%zSwX{$Q zNgqgu`_4{A-QI6*`32v4dLuYR2zzO~v_e)t3@ z%D8}0r~K4#J^5n%hTa2l;pE3hXIa6Q5gOyxP2*NO9v>AwfA&NUSZIAfK8 ze%xl>UtUdMs$KF@RJ}Ag_|Pr>eWg{eW4e@4x|jG9({mxINnv)B!gqCbt|S%=Orf{k zO0d_#J01?h){Z*q)dyK}Ez zU$Q4WrNf`RN1AYKuBv=U&qB&t1bXjI`pmn}_SVE)a*^ z8;!5_; zx;1FsI&(d?vk`G-DbTbGty#{Gg_xt-CS`NKqUu({$rJ8>bZNxQt_QyJyOd|L{&PDv z&pmBU`JKiUKc5r5*)+5pV?$&uyQHG`GRvyn^tE-eki3M6@~)7An|!tv>81XyK+c1Q zk$xCM-UJ&)4b7T=+XJcR&%cfEUK6@SUHMroFF_d4fK})l$N<052BI%>hY2Dzh-bDl za$vnlBS0eG^!Oj10_xhcrCwwO%(=jS^|p8=T~o9qJeG-?^!B@C&_2{9@#fpNu-U~J zbyifs52sgikAYb}0Ku0{T^Z{Q_)?nOHy2N|<8=)#bwjuKJy;q~n$vOZ35d)f550q} zflfKqb?A8qwaJX0V}VM}zX^*fH9MMa8XYcLa=G*-zu9zEGFtsPP1)zfrA46w$eF)@ zfCGr3Q|Bz8_=OB)4{((xR^!U007c_c_`wDmoTIY{?b88d>+#3(1IX!JV^B%~W2``9VOz*1aNf^y`3@lQ z#Q$OvjEOkI3u-Zh0cXhr)@&u*FbsMC@y@mGblgeULQKHhX2HuIK?S`V)-zxE zxC!U7uLGvO{+~J=`)nPyr9$Tx>KIO~j>tbUd4fXee_jlHrTW|o{~PAe)~h)Jtja*9 zn>h{p^Ff%LQ`WsDy1GiE(97|5Gxh#}k{G_j#Q3ZaNlNoyoma(d3kwyxAb%0rGZ?(y z{smlelK@rAj53jl>Ztz_n&;(^r=;UtcbVcba+%p1*d$T*(!EecL&(A6g}OjG&3m}X zUH(N-;QqJ@`C~aCgZi{_77IEM>>YZg`I!ZFmYiRiUQai08rYk@zv(w4!7^v6J$#^J z{r;?7(oueNID#W*yC*e$UgYmcm0v$KJ?dkV&)#=S=)Y2M#3rWf zc&zParKc=NwxktC<%?kh6N|5H^dTEwaDB1|zHo!Ur~P~Rt^q0<#X?ITJAjOmnPV-1 zUh||RQ0R+h#wfY8j1W$o=OKt-5Tt(cYT@v@? zF#8I}5ZGmFE~EI#USHvJ;C+4okINI=FNS-*x?mJmLzcv9rJ9w6(%P9ug9gO6SPRCZ zhQ;UyU*6_PU9%f|uW@8lV$Jra`}E(H)sH`RTXv9Hl96K6%J_A0WCqdcLohmUWMQ;Z z3ENQp*uAK~Oh^yaMd{aE+U=2OeP0sL5JPit^idBywW;vRTfE)d`N2811iaq|b|J%^0 zm+zr-dM&?rywq(O5`1KZ(SxVBm!LyWMTyAU7`wBqpn9>UmeM*wQ9Hyg<61O|bd7m~OMP zXw^gvC&#C(fBF}50}?nV$FnlCLkh?8@j?C`?(V+V=hx?_2d5?{9i46sPlJbPx1ccN zMvBVt?OsVs;YLh3MbC>6G7!j@qV4}Vr}*iA{tfU z-*!Eq$&7uCJHSI@Md6G1(j+464_Pwca@7y zVXgLyn)n!9MtbD-l&=(4Y*j_$a2XsdGJbE7O3qZZresIwejCeW-^Lom%TzNF&&z8- z&EgKF?u+)b$VXj@-TF6ZP55I>1K}9G7w|*Ysx15ZK+DgMt<$|u37K{W(U>1izmO7o z0!AjwqB)kw6E`fmEXy)s&e{@TbXhkfTmBq>_ zC9Tk^BxP?cflYJi-7>M^qB&S^^Nj%;Mm1NonkigJOUB=3F8nDU$K~hPF=V$INNw*515}q- z5|jHea%DJYVf=RJ`iF^;+~RqxiA9o&KKXJYS`>@S&sscNE2EZ!-uL2p2DY?K$M*~w zmSrw)RV$@C_o3J|M(=9j_9MTm zXl@9c_zz>Ma5#@xw7h4SJX2hXa#+sxB>1a-;}VOUDPHa#K8MBR>KhwBVyJb`E*_oF z_CBX^*Wo3^Jmg-5&UCLxOz+P%Ib~Q%r!6U_m0Dq=M6blWGjvd}%8#MkeZFc}X60*? zt8_PgQI05DyB6dg@KL|+M10qRXp7f-8f0 zUOYtC6LfJVU&^W~z4@Hzc;-@>$$N~uPD72No{hpFD_sXCD2WasW|kNk^H6 zbTT@CAlf&F-snZ7Ro`ZjUV3T3ouWQ?2~Fk)0!q1DDx^1BqF~#ixrp%2eyf;w6jpC*K?%m89(*wFPCnH~vZTN|-? z$LbnhQ^-)xHAyWkJ-?TA;YoTHSz%=>!twjQuRT$dnzXgzebmwDw?+3Jm!dUfd_8=n z9Lp3(bEg77ETkrQFe77>brTN1C3YnMs|4;<6 z9cg(n=;rD6t5eg4lB~_Hi|VZ!J}T-rmC`d6??3Lo7$|eqM55Tv3i_)8Jl`yBv0cg!F3NEMD})eiSk1`A{S58};O%S#{6))g zOqAirS|)0(l=(*C6rh1P$lT!2wF3y>Lr3e0>HTwkmv!F@hxwm#BPLVE zC?l-{B1#$ono4d;9c^y~uC&q5Tc6Iphwk`jOQ9E!B;VFmY$K-W6b*OIzbw&>F-s_Y z+Tm6@+;KP92TAFVQA$r=zW*4LEkHsYO(?urXj*fk?QV7wQ6X>@@R%!V(q&Y2_)z^5 z>bM5`F*sRgGugtrRv4gg>CZAJj_yb~6{WXqa0)j|IDwU=BVzFUSXrMltG;rZbT7*6 z8MKJ{)a~rq_HRa>S$E+*(&r<20lviREk2*bqWwfVZPH5hbZy|ZS9N=QyGwH5$sM%K zJ8uh3>Oy|+Q>Ioh(4vptoK3oizmEypnw#SaC7-HF3FN@V?kRR^~g#W?rMr3p=5NaRYgZ zfCt+GaI&oq6w;KE+hK(>yV{c--d((}Usbx~sL8$TIsDh(LY!Cas2j7QKhc|{%=hAS zJ?|Fd=zjN9y6TW-Q2_E(g5XLG(+Xy|7sr;*i(bkpoR^{zJ4JR zSE;!`UL6%r-nz4wZ~!qQLllNW6q)bUgf6*09L#T%d|1-!Oa1XYGN0?m79KI`s2a`xQ?91kqh0zET{~$&j2rq@{{m$Nk5xghxS z4uQ|gTc@-6l&hCT?kK{;u|JLDpM)bw@@KX+pE*l&p400vx|*!w8j;ZYJuKq2ZS+Go zMq1zI9YclMLM6?LdSBB_5a@HULEYx|!9Jv{%dkz*lb4FwDx9;-JC0b9vAW0HSwh`L z8yg-=IN1bMxs*mq#6Q4)mHWYN*CVGinLipdEXIh?QC;QdFnhhmqrRv$D?oZ-wLgj- zN-5_7Y0CR&YR$8{1oHZ$^5Z_E>6t$5_Su2XH45~ga*xpIIv{TgB^q4kAMpS1mh8oB{Pwg0F)`Mprr6Z5is zRKU2%Csg$cWAVAF--V~a2%aUiV=1I5hvjwbWM>(A4@6OdUU_~^>KJ}bJY{e$=H(-y zqusIjQWQqpQyM7WU5U2Yt&Rf-(qsNOjtca_jEceJa)h5c{N(orI z%#foH{5isZ0sNh7xSCv{-KvtU*oxeYa$+5#Kh z){6anAwbNSZ^^c|5`&eKkg`pEAtC&|V*7fbuI|U#Y(`SfoDclP74pq&(QHj+Wc~@) zG6}su=TkpCscRZn{`P2QaTM9+CwORgm7X${!cqX@!Crg{3T}Idz9_9S0(Zy9MA1p> znlzLIR&4}}pf<~VGNGCIOPUn5`s0b{N&jTmS<1MjYfA?4>q_Xt-LVSC-rys~qcKh| zhYGXi6y?o5g_>hd7U~T~n;=;)GTs-8SvL(k4+XgRyJy-b>CeXz;bAl?$?)_Idk+6V`u$Q13~T1%Z^H;p!ig9&@hqRr z4Yo+T<3O~gcRr*1Y0Yf(PWZ1;E?>5tuK0%i<#omBu>6)5V)#@$+BBEHL_Pm8rx0PPU7dq!6yZZ> zk0~wM!>Kc~fUJ41lF#hnmS2DmomchCWIABg8|&9gy!kr|u1>v%0Zw0xuUE({)HSGg z{37dNcf+P@Z!~v52dU)$F8^7p5uzUyzzpt|3hie+jTp+wGE~~0M5%f2PO}kI7)KzA zb!tEB$9f3r_kT8`d?LrToUcsPeZ+Bdr>aWWGDk}()t$baFuIOrir6jwj0eZFsR)g* zjyvS*VPD_PYIKq$ZQ%m8&~U$ZM3cRtsAM=N>+hw)sJ6kejFWeLycOg@srL*jeu_Ir zsP$SKXP@S%zMd0Vhck^00S{_ofnF|?ZqBpdwa!tC6ZfHMg%5JQ7 z57WrCYqzA_oV3k;?(fkU7)cZgm0zlMY`i$ZK&;h+6x2GH@O^M&c%f?OGu%<2h7Lc% zF=J-*m1X_D1x=FX8Rtqn0YCQkYrPxrG1%XVjDu+P+vcuD2~vEwM?xaCk<6nb4Ev=g zj>%hzzOH%NG3rUDPuxd;iFVW&4)KaDJvq~@I!!Ip6fN_R6%kc^Ff=lspM7t&&pO#y zte1woKrNW*HeuIAT$~IHH`Iz;jbMA=2E_5}UIjSH4o&DK0VAcYQnJ|i>g$5Euu9yf8HBl9hXAFC`|S|tI!x4wi(d|cN6^>s^C z?@3-h23diAlgd8bo^|!Nlb)awd(mw#u4Wfn6^hzDw^<%(R_qB#Dz~sQ{c+B@tXLVH z@#Sv2ReNiHQaw@Zqjs;tq@_uX_r)!9AD=KncR5Eg;{YPx%P8gc-TXAWSI5;G|MNd6 z&XfNwic=kRLf?yykA*XA;DD|>UF2CvA_0mS_=Nvp&^QM_zRL39`L=|U2MIlenr0sR z8ndGJs(FidMj!dA-E)eQds_JP)}V>l1OG2R!_kkjqLytEa`ip}!^I*IrULCc{g?W# znW~aJ^BU9_y}Kz=uX`>Hy^!ir^~-+d&B?CcGzL?O_W+=56!j084uJ6E(ZJW-lT!3b z`gM^`J=CKK^f8>oX?S>3NFdB`Y^bqcl`zl68&Vb*yqi(ejMn%%-o)@`G#>Ib0@pc(&Sj-GTk+AFPz@K>*}u+ten_ z=+HGUMxyGgV$Hshk#B36c_;zz2^b%)`wQnG0A+{bTiYp}crib& zD(3-U!iM_Th2uLLH=vjxv#}<_5bA6c)0K0LDH5k~TCcn55?6URm=AiYmHwx6PVhIo z_G}y}G{F7CPoMBD=B!=&e2)AYV-*@({>o7QYR>e%lKZN*XJ2DEFZ}$Zx94~T^WqjL zY*Wm;scd4gm1v}rrr@lq_TQ6cS+5L@Uz_R5tr!0YhpsOu5~ollo-`k@3w3y6r=%>%8HL>ksIn`+5Qz9{E%KrVDWgYDo= zu1Vnt2C?j!p`Fkv`A*oW7GZ9O>-qh^xKR0Z8g*ZU0;}Hnon!ZQ+4Y2zl(Ex?7m?O? zD~2^I=fEw6usdUZ7o5tZyC~T?TuCqlB6Oj2A^F7BJ3_ORzHQubf z4&6okx?e!1mKlJH<(U$RBjkz)6uOeDQ_g|A`TiQlUSpKr0UQ`J=E`*A7?1t@cP(P* zy`2ukIkb52PfS|7)?Rs%SM{()_24gzLc+5qexf)2>$voVQBAe8c8?fgf;x%p(;kBJ zr_8VQG?qJMCvl5bjWmAA{vKtsA@_Y@#U{NzT}D*2G96odYD8` z-n#C?vff_7ci(?R!q|5)bLRV{WNI~;@mpicWRUsbd+sr;<$f|&hB;uyz%`%iW&GG+ zMFG(?SfaFAlu4rbsC;JU3VpH5RSJ-L+xpfy*KpeyB!qS>T?`{DcQ4x%KBfJTw^uZ| z|IkzDa(@9np(4HH?%R1xY56zAxhdQEor3JjGH<2b7xt?K%Lu4=0+h-cPBw9JfwdGX z`$SwEBaMRUkdWAz77>tvI>G?iykzug8Bp0r^`GRUHP?Nb6`B$SW45?GIy+r&y(_-j zABz5B;$QkUS1nefmwXoW)zM70XauYK2L0jJx@?!|Z*|Zk7FB&ER*C5q+m|!)=QP}f-XjO1erj`L)muDNg z;#-69o@&42G?*Tvq$sR8IK4IosRP`Ld6@7ke;u5bl5^NHEY`Sl1YEc zc$yG=cf zLS;iLQMYpt*lujD&umt6hjLGQ{)@*W!Pn2@rSaQN*b^mls9mvp(@1Ib$h*t7*kP|dG3%JurYrS|{c{J(_ zM~DFys*^iWIK^*1S=q3sO`2~p?k0_6e!&Njq)C_P&awcv!l}NZ0r$7wV?nO^Lr(US zH@f}Bkp-zH#cTubqC8VA|8fFg>Hqjbr(RO zwd&)2g6t({11*85`P?ZaxYc9Ep_FC$WCfFW0cWzm`LYC;Q`* zKzfvOF0>7N!Yud(PIEL9srcCUYwsU5A$^HJzJaotEUD8MLC?9r>YUZ7jxii;`mM;^ zldi_|YnPFI*=XiA>TYDwLddwtScifoE7_DePmpJ)pRcQ4n80gs9mNKC&Di3C^(BGd zd@!@X&rDA3Y_EGExWxPs$sm{v!rhvj@Zk%L@lUW6a+Uw@8lW2Z2)O4?zi$p~7H^Gk zc+R{sAo$V-L{O_Z9p;m?(yvo*3*Y};Ik7Z(_a!F9rLs{(&wPg!j14miii^hLP*yKQ z1fF#u%Us{W1WZGIDQOF}jxK5KXf)dKrzYB_*0*S@y#dAlMj^#x1;xY3ra?&$sKY~c zQO)nyYuB%l+!Fv9wll|SpRip%711s&m1x8y#gQKoCU)!rGiGT!UeLcOV9uW(Z3z(C z1ioS#>BnBbcfkxz*`VTFl}5Hz?K;HESal)q0nb^N5mM|e#``~MOB(yfdYz3T5;`cd zNlP?E%86GUgV86g3y*h-zHkiQMcPT}{`yb4F%KTJO@5RPs zy><)5tlCENU){*LVuQ9WRtmJK7`!`QV-FTVsklvZljRWM`WckrJYZ5h7JWy*VAH zyTB8I)r1L9=RW$OeL^{a^HpwdkRm+CUdspWt13mnk1sWxd3Ed+Sgu}Jn|}FjrA3A( zwr$_(=#3bt7D@lQ{&l7F5nWk@pR10}Jr)Iv+RFXbX=#5pt2AWjWhh5D8=7WR1R`av z9%t;%iD?&V`UDmVR$JOu?DK&?O+YEYx60|?1S8gTEx4-f0Ese}>FIBnl1Ny`X{M_- zVJD9BH>j=Xs2MMb9&^Pgq<+2?ze}7 zS*)BXAEy6&e){9!Ofx0ysIJotlg#eH_xgX@B24%pfFHuCU}XT=hj>rK zVL;vpkYT2^I-=UkPjh@3D!6kDLafHohG7o4sQGTNf6ewk>wxhxeBEvvisL63){m;F zgn%{Uu;z6&lZJ|)m+QIkOMT2L3R~oq>(%Njf=X@H`L^oi@B~R_Xo`NlW2(2d@U(N< zdT}Pmcsl9|Fj7ynnX8&d_xCKntws0AwO9jY?B76@uU#iR7A_8dxFLZV zW(|&TkFE&srBLukapNd{t^&sq2qU7O)Ct$wYJYeb0L)Pul82m7-r14cooScq_Mg5V z@IHl;AJXjob*yjQON=GY6N|x;`Ld`o$w?XEFZIH_$+iK$Dd`5UWQj^e_{86ijHTsxWUORj$juBR#(kE30x$I zYCtDe=BT-Z7&>F|#W?L|%=A zpOTRtZKIc`t9NBzmLyL)bEd1e5P4%eb`vdoxgXkwxuek*-kXug&hg~3KD8e+2aqdx zYBroG|GRxFd zuKu>D8o3zZ;QQClCRx2;rOvCb5&V`ba}kq#1$OQOpm;`YDv{o`KF4&Y%!;(AVIpX= zvHE7Tf!J^aB|-ugvxkTePCnxTHD;3hX7qqF;PlBR#Q_@IRG&;L3MeDUrrrYLjx=-F&-Z)fNC5oQ$qjY z04N^-&6fZG08+;Q002ZL9TxyfJOB_20Oi`u(Wq9}#Hf6@!pmliaoY&9@aWRtwK4hB`LF>QpS)Tq&7d7K|88_CWk5`cv32jFF1fm zB$8)adM_`3XIp<*T23M)Wfd1{KPk7KX{+Gay0fOBua&i!HhmFq56IJDbhGFeHMRfC&(oW%)<< zz3SF!I~UaPd#;L za$-DbXlh`v!7oYNm^wUt^l6$(XQDDb(M&o;pFTQ$c*^+YSnvlmC#H`)la+H;FdUX7 zNyG>KhQmQCCug5IGCg4qw0@H0;nzI;>~mR1=LJFFx!~}_u}^g;``ojK&4Ab8iBdNv zk3KhJD?lW8@B>UJ_RMofCygh_0S;sydo7z+qye!#J~)Mkzr5JzisL0EpMC9^`DCoX z#z@XmS?>|&B`FwGqD3TZ)0LvY+j7yucLLXCL6_-l@(FOjs2?vlqS%w1x3U?DQ&NlY z37@AlEs9x6^8zrF)5D_2B`1nb;dt_AT7hYP`gunYJh_}|#h{cf0Am#^ol-b)v62P_ z$soP}uncmnUr^A~CyYmC0Gh{Mka2DYc^>B$AWaq{s|9!siY|t2N>`O&IF$nMr-jut z&+#

5;4hEc1&L4dQdp%P+(p(FV|X;>A3(yr5*M&ILKWP)WgL12}LBjfx;*#p1%L zMF3(^sAPHgKn_DN0GgshSEw%7h!BQ?{EHKh!T>7kSi$2yoUgzzzzA49YexYDA}>}J zm7r(={viql6)UJXc}|4cmvQtku&Pi1q%JHnzC9Zhjy?QDMC6@FD?IaLQM#y03XpGq+6<()V$)Q%N3_d~0W_<=Sv)aQk5FqMo zmbn}bg)Zw3E#v`-Vi61tPKD=zv|T*4F!$2S)5ne-n|}GFxrI|j8<^mEK}3~V61pUG z1e^o<6PPo~&Z-ZC0Z`Ly)<+)rv?4$$qX?1>u!~y2ktkX6E3eK^B#r)H0V6pv|LQBU zC5hmkln4*Ag|0FU0w-llWGKwe1|G}+G&qrA((~yk^aH1!d0h~}@rWS0AX(9q^HXZq zQbXCVIyHYXYDoge<7}mt2a;6~An$1)bK-%s0Fj^eB8a$x9-h-v;B6MEjM0XREKHB9 zgOo>daCLloA;N)`^u;Kn$!DQwnsUsXO8VFX7=S@03Lf-=LXM&WU>X-zR&o+xJTf(Z=4eJ_c8gAHduXWdTzvNrwYA#Y$#cIC z>|sEg22aH6qscPIrw<(jfdDaSw*w@xIS4mw3JChb+fH^c=h_#|2)7a5#wl2 z0|Ia5ErxDsW_mCE07*WNE(<2T6BZz)r+Lh}tmAv6_lyO?UAy{UKp)7zf1M0`F|2{( z{tT3CRO=#Ube#Ttat{Lma-1d3;4xA2f`yqbuOHbXJ*n2}Ox@%^|N8ay4?zDP{PkV- zzE-d8ZEYN3QwmZtnk_;y!s@o&jqKc#r{NUT^>R_3PLF z{K0jW-&PZ@_r-Ag9(U5R5S;gk*kH0Rb}W%{|cnsxI)HY*GaX#4}CHn5m2jWd4Z-SMr7CtL91hO7pRa>!?U6b z%E^6Z9_h3-vev0%pPTxn_9q`_Lpb@#R%453?%F;*w37-X=Me~E5KxNVw33ev`T&5* zYkF^iE$YRnqwrF8d^p4L+BZOcfEpti`P;{z{PAy|G60mM>TZ!<%YNVStfVZ`yp>;t zHH#l#UK@;qV5BV53oi;mmg5PWV9)l)AX>Gm61A$STEeZtD@-LnmH&R}(wR$_W-i^t zq!oT@iHNFdtYx(y5eS*JMXOA4$<__WQg*UWAHZ`o&jPI#&5MfQxxU4|PbI3`0N6F$ z&RQqreu}mOmHp$hTg{hmH=DOUn+vc{%o~YNr_piOu%$b|fVs#Ex}1f-- zgXa{__t3mTGdW}>GC!a}&8-@dNGSCA$DvT7#$Z7X-9Gcl?K5Z2!0#<)DPq(Tq0prp zp+uyu)!YH_ka<`_iIT+jXu_D?a>{e&0R6-0dO4+B$iqybI7zs|u)oLgdinM`z z=LaSkxpn4~Gq*pvb>=oO(DFQDGLi@-iqJ3w?FYLXb1VTBB;GDAuAr>a%;7G5`2Jbj z+f2#>P|{X86&?~F4X_mg*+Ldd?+HdGndt1f?ITsy>ewn2vfZtri~tn?pvz|pIJa1s zv!CtGfUf#MbOjb_PIxsHmKKI0Dmu4_d-jVj&UUJ6o@B&4eCsxQZrz&nh>_Y_HH3{4 zuImoDVqz{xQWOA43lWRW!2tt6&YcxJA8kXPD=39**cx#?q`I`ezP=P+|1OcJ`P*uN zfBo~H|AObAPjy2Q_~x_g@i?@M4<`iRgeP2lMKaN&Kb>QX1%+1fQW*SC zUW$$n_t!20{rJ*){JomDj0|XXfZ+6_uot7)s;Qh#(TpIS9O-^Oj^i#Z#m{-`^LppQ_UB)20Cjl2`n>(2Tl3b} zSAaNZARZs~okTq;F%efXVS9z4O+V6ee$V*RQna&$l|obztReKlvy19qU%#^+-$h@u zmU!v(>CKIe&AVUUg+JS;Prs2s#F5=Nw84f;=SLO`^OhHSZCJN^F5nr@1qR4ewwtB% zlCCQfB<@oqy?4>5paA%%5u+1&>Ga0--MhcJw-k@R_nW(*2VkIM5+janK>bU5=ude8 z26Hga(+k-tpZ;OFze?b6;l#f(=si)d-+=Dd;~@U}()oHK@zd#z%{%e_v%U!ogc9}h zKzJP+Eycefe&4PEUKvTo1=;ri0S|uthf`i9J>pso0!!c<)c>73ch;BIFNa+B#wsW^;jUUD%>#r+_Z;3^{6$>8gKjN zhd5FP&tHcX9l{Dm#eeNYP5pB7z4*ErFm~g+Mj#0)-}u(3C)#n=VjXn_lv&?yAR_bj z2o>vuw~wGb9USINEKYd-MC-_I4Wg<>w73U9lCfe*^*_YFXIz3eY7=q;M%ZGjLy|l-vKR?d z!^=EVBlP(N!%J|XbK(a0UO>S27rwiE7IH1u2LDHlZ#VDVF-UUB)Xb$MF|L68sPK^6 zw%hL6v)^6#16V&{LZ+68xF31ZabX02;Z%}^?Qt(B8-U-O$MNTGC(_ZhP6PdasQV!O z*yhF^!%P~<@nkG%7^bnbxnY8|p?)iasGW|gbt1O=IU6l7Hv&K@J4=Z2mWv_$l)^7ra0i}UPS1t!;ISFiRe!Uwo%os>No=loX zVE5kXFA3QSh1_mKNYRPbNPK#;o@jW(y=-|~F}NwqvmM<@M*k3aCWy^~I5#7Tc?BlM zwAZ0tQyYmoHmUjIUs%6`^e47Amv+r$^4%X|v6!)&Od7jO8=GM5kacJ2g5@coii2+@ z*3`N$|1?Zi)thRpS=A=eChj8 zs1EAC8-K?%&%xw3!3CT%jc?+2wUz+6Z;3-)`KEFR3x`NXcXpJpOrg3FyyP6Cmw7OYu9N z5fTlUH-MZif3#yP?B;T|V=-4SNS}k1zOCrC#1G1krY1EuTEvFT;+yjXV_yR4$9Ewn z$KOrf#Q(tw+}(aTfiaMreP^7kP2l9~&CSi15*^GyJWui6`u8^L zxYl4FcjrGRT8?GsbGQ`f&VT0r5STNvgy*% zS#8wOTSCgDHHPUQnE%`-|6}wM7=efj22HG8`Uj96YmVWwJk~U)x2KKf*fM*MpDw?3 zse!idpq@HR|J{)e%KwJ*UyrqJ{)^Keq*r6jShZH|+<2>0DvgazsX*|}fZ1Gb1)A#4 za>)$53A6(-&_Jp5*5{3CO@kgPM6a&%y-)r-nE(5apZ_!Ooxt>|xts)?-YTJ(r7<8p zwp>c?jFpy?w_?ksv7IEawcIq}J7`kc0bC`Qo46;I01xEBa!MXazxw%qZ~fCZ4FZ4| zQ!0cn0Lgf1EN1SM7;(^XYbV(`c9vsbjW6%0vC>Yf zsga#h(^F81A)?d*^SNYaxk zcR)-DBf5-s1{-0W&QknkER#*39 zC89OooQlPoO_gY+nDG}QR?>*tY{rtUH$ev_zh$Y^GMWCtN>gn8KMKEr^}o0OF=T)R zlf+<{&msx8mTWT8IIy9T*z(R>rIv(!f6hQWk2jj5Z}`j1v#jhU+1 z>XL`qft}H2gzf(fYq-Dv)7}3X=5Nj*0#i+IN-vjM%iwqcccmsq*i%2v$dQQd zx|Xg(Zsy28$?}W>fqth1XfHKm%dHaAT50SST7QrDBl~~;{^yW_7V)gNg_118Dq|V2 zs1kLj)S9|vTX{L+oceI)r=R2**_Ia^`9sWI>`SdyX$N;_Tg%JIB)Y?~9hii;|2aDP z;QnWS|94OUZ2y;#sc}FxNj6&=V>H$}B|EmAhu{(o&3xGY3A7-$b-j_d?3^sOl5AM5 z)dYtL^J9vQF>8;AKfM1tvj5#{GVVKJ{G;{?D{B$Qvg(0qy#tA?Vu1y8yIu`cZ7br` zyGaO9`(1JWdlX$G``?56|9uk;?*9+8Hnt*GjlHPVf9(8-r#|>5Vy{&PBIyJT0<-4y?Wa_FIikV{7k0W1!w> zG`84wSFQ1Jw^#4{b5Q*K&OdwSzay;n&wsJN+S^f7_Y^#M3JQ2Tj_{*)r9ZmQ3HZL} zzrFMCQ3iVF-#wb-;QE`su{`OIMnqv$sRx~ZchCQa+KSu(=l>7!u=9T@!imFD9dQ0n z`t=We;q67`fcl3AQ)l%L99Hbv;Q=KaRR1ts|KX#rj3sCL)_**h{Nw@*rmWI3r71_3 zx`ibN)_*Vyqz5Xju@VAH!MJ_vUmidm>t6(~KsTSJv=H@b5AIk0LVEQ--ZT*wX;u;h zLD|3l=f32z{zp)7p;=i`!cjc+in7{=`_%so)ITwtWNAf?W>+bm+3#2XbTD;R|AfbR ztZGoUY04@V(6slje;TO&V)dTvSy@e|L5}_FzxE^U*M9{Cte3r87ilGDXQ-nn3R+I&AF2LL5IAL#?W;>NE$a_k|Ax%5`ace^mzTs0wYTY-s|QgGr+ z87epaZ6&fuDI4k$>VMh!s#pIkL}W<^)2Dfb zX4wUYOc@8{SSgoR`^;mpXAp>6a<*IuTa{FWf(8Kg6$^N>9jxVjl=^4JfM5R&{ee1o zf(({JiF8E|+gX|o%ZuzhA92m;w$6+4BKnGKQP5YiAi4t#U^}+2_o(&XgrU^0f9K?= z0ImlRAPPB}79|OWe?3dfB37zlQEr)L1u2_~;)E4AeI@lez_l3W^)hw5J35bA|L!s1 z)&Fz2Q!emXY70UJ&2Is;Uk7021aL5tZ)ibL!r*8{tl>y0Si(`1g#3!_)$l!f{XbJy z@BTwD2=iYD43r(LpD0*i_&*iaQ{Z60zh@v!aU3v`MW7WbWtx(K0p7cR@ObwhJQQ~C zf8gy8L3C&)Y|(UH5fqvR&!|_@Fgw#!NU?$f5sNj0Qi?7{#Bd%9rn#SS|AR1%b??7` z4tYLJ^8&vJiomM?>?bOLms@;2!jJ}V05-y@6$V^(4dv(Df9a~gyZ-||UCAKkqF`kn zuUe#O5ilv{AiZ+f^&>&X!jkYR?Pjq*_x_JJV|w?WU^sT+DJwuy<4AdM$vHtv0auz9bz;tAe=>*`?O{vW^^eL_$vMio&`v)HCs zSX1I>m{0WnUyp-5_a8YCG_81t37nrc|04GvyBz#__diKbm%rBiSAS48>aTMDcbJ7= q<^J;k6OZ)yFULk;Bm;ho=l=mnZ)i89jX + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/sickle_cell_gov_logo.png b/app/src/main/res/drawable/sickle_cell_gov_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..20d09526edaf23b358b7a048bb9669a9aecd5781 GIT binary patch literal 12702 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/activity_dashboard.xml b/app/src/main/res/layout/activity_dashboard.xml new file mode 100644 index 0000000..6b2e4b2 --- /dev/null +++ b/app/src/main/res/layout/activity_dashboard.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_digital_card.xml b/app/src/main/res/layout/activity_digital_card.xml new file mode 100644 index 0000000..6b2e4b2 --- /dev/null +++ b/app/src/main/res/layout/activity_digital_card.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/dropdown_item.xml b/app/src/main/res/layout/dropdown_item.xml new file mode 100644 index 0000000..f4edf82 --- /dev/null +++ b/app/src/main/res/layout/dropdown_item.xml @@ -0,0 +1,12 @@ + + diff --git a/app/src/main/res/layout/fragment_digital_card.xml b/app/src/main/res/layout/fragment_digital_card.xml new file mode 100644 index 0000000..24bbe28 --- /dev/null +++ b/app/src/main/res/layout/fragment_digital_card.xml @@ -0,0 +1,263 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +