├── .gitignore ├── .idea ├── .gitignore ├── compiler.xml ├── discord.xml ├── gradle.xml ├── kotlinc.xml ├── misc.xml └── vcs.xml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── google-services.json ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── geekymusketeers │ │ └── medify │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── geekymusketeers │ │ │ └── medify │ │ │ ├── adapter │ │ │ └── CustomSpinnerAdapter.kt │ │ │ ├── base │ │ │ ├── BaseViewModel.kt │ │ │ └── ViewModelFactory.kt │ │ │ ├── model │ │ │ ├── DoctorAppointment.kt │ │ │ ├── PatientAppointment.kt │ │ │ ├── SettingsItem.kt │ │ │ ├── Statistics.kt │ │ │ ├── Summary.kt │ │ │ └── User.kt │ │ │ ├── ui │ │ │ ├── HomeActivity.kt │ │ │ ├── adapter │ │ │ │ ├── DoctorListAdapter.kt │ │ │ │ ├── PatientAppointmentAdapter.kt │ │ │ │ ├── PatientQueueAdapter.kt │ │ │ │ ├── SettingsAdapter.kt │ │ │ │ └── StatsListAdapter.kt │ │ │ ├── auth │ │ │ │ ├── forgotPassword │ │ │ │ │ ├── ForgotPasswordActivity.kt │ │ │ │ │ └── ForgotPasswordViewModel.kt │ │ │ │ ├── signInScreen │ │ │ │ │ ├── SignInRepository.kt │ │ │ │ │ ├── SignInScreen.kt │ │ │ │ │ └── SignInViewModel.kt │ │ │ │ └── signUpScreen │ │ │ │ │ ├── SecondScreen │ │ │ │ │ ├── SignUpSecondScreen.kt │ │ │ │ │ └── SignUpSecondViewModel.kt │ │ │ │ │ ├── SignUpRepository.kt │ │ │ │ │ └── firstScreen │ │ │ │ │ ├── SignUpFirstScreen.kt │ │ │ │ │ └── SignUpFirstViewModel.kt │ │ │ ├── custom_views │ │ │ │ ├── CustomButton.kt │ │ │ │ ├── CustomEditText.kt │ │ │ │ ├── CustomSearchSpinnerDialog.kt │ │ │ │ └── CustomSpinnerEditText.kt │ │ │ ├── introduction │ │ │ │ └── Splashscreen.kt │ │ │ ├── mainFragments │ │ │ │ ├── ReminderFragment.kt │ │ │ │ ├── appointments │ │ │ │ │ ├── MyAppointmentFragment.kt │ │ │ │ │ ├── MyAppointmentsViewModel.kt │ │ │ │ │ ├── PatientQueueFragment.kt │ │ │ │ │ └── PatientQueueViewModel.kt │ │ │ │ ├── home │ │ │ │ │ ├── HomeFragment.kt │ │ │ │ │ ├── HomeViewModel.kt │ │ │ │ │ └── appointment_booking │ │ │ │ │ │ ├── AppointmentBookingFragment.kt │ │ │ │ │ │ ├── AppointmentBookingViewModel.kt │ │ │ │ │ │ ├── BookingSummaryFragment.kt │ │ │ │ │ │ ├── DoctorDetailsFragment.kt │ │ │ │ │ │ └── DoctorDetailsViewModel.kt │ │ │ │ ├── settings │ │ │ │ │ ├── SettingsFragment.kt │ │ │ │ │ ├── SettingsViewModel.kt │ │ │ │ │ ├── prescription │ │ │ │ │ │ └── AddPrescriptionActivity.kt │ │ │ │ │ ├── profile │ │ │ │ │ │ ├── ProfileFragment.kt │ │ │ │ │ │ └── ProfileViewModel.kt │ │ │ │ │ └── upi │ │ │ │ │ │ └── UPImanager.kt │ │ │ │ └── stats │ │ │ │ │ ├── AddStatsDataFragment.kt │ │ │ │ │ ├── AddStatsDataViewModel.kt │ │ │ │ │ ├── StatisticsFragment.kt │ │ │ │ │ └── StatisticsViewModel.kt │ │ │ └── profile │ │ │ │ ├── EditProfileActivity.kt │ │ │ │ └── ProfileActivity.kt │ │ │ └── utils │ │ │ ├── Constants.kt │ │ │ ├── DateTimeExtension.kt │ │ │ ├── DialogUtil.kt │ │ │ ├── Encryption.java │ │ │ ├── Logger.kt │ │ │ ├── RemoveCountryCode.kt │ │ │ ├── SharedPrefsExtension.kt │ │ │ ├── StringExtensions.kt │ │ │ ├── Utils.kt │ │ │ ├── ValidationExtension.kt │ │ │ └── shared_preference │ │ │ ├── AppPreference.kt │ │ │ ├── EncryptedSharedPreference.kt │ │ │ ├── IPreferences.kt │ │ │ ├── SharedPreference.kt │ │ │ ├── SharedPreferenceKeys.kt │ │ │ └── UserPreference.kt │ └── res │ │ ├── color │ │ ├── chip_color.xml │ │ └── color.xml │ │ ├── drawable-v24 │ │ ├── cancel_icon.webp │ │ ├── ic_launcher_foreground.xml │ │ ├── pdf_icon.png │ │ └── profile.xml │ │ ├── drawable │ │ ├── add.xml │ │ ├── app_icon.xml │ │ ├── appointment.xml │ │ ├── arrow_forward.xml │ │ ├── back.xml │ │ ├── background.xml │ │ ├── background_gradient.xml │ │ ├── banner.xml │ │ ├── bell_reminer.xml │ │ ├── bottom_nav.xml │ │ ├── button.xml │ │ ├── calendar_month.xml │ │ ├── card_bg.xml │ │ ├── cardview_background.xml │ │ ├── curve_box_final.xml │ │ ├── date.xml │ │ ├── demo.png │ │ ├── demo_doctor.xml │ │ ├── doctor.png │ │ ├── doctor_front_facing.png │ │ ├── download.xml │ │ ├── drag_handle.xml │ │ ├── drop_down.xml │ │ ├── edit.xml │ │ ├── edit_profile.xml │ │ ├── editfield.xml │ │ ├── email.xml │ │ ├── fab_drawable.xml │ │ ├── feedback.xml │ │ ├── gradient_background.xml │ │ ├── graph.xml │ │ ├── home_icon.xml │ │ ├── ic_baseline_upload_file_24.xml │ │ ├── ic_close.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_pill.xml │ │ ├── info.xml │ │ ├── logout.xml │ │ ├── mail.png │ │ ├── medify_logo.xml │ │ ├── modal_drawable.xml │ │ ├── more.xml │ │ ├── need_help.xml │ │ ├── negative_button.xml │ │ ├── normal_button.xml │ │ ├── pass_hide.xml │ │ ├── pass_show.xml │ │ ├── person.xml │ │ ├── phone.png │ │ ├── primary_button.xml │ │ ├── ripple_black.xml │ │ ├── search.xml │ │ ├── search_button.xml │ │ ├── settings_icon.xml │ │ ├── shape_oval.xml │ │ ├── sign_up.png │ │ ├── star_rate.xml │ │ ├── stroked.xml │ │ ├── time.xml │ │ ├── update.xml │ │ ├── upi.xml │ │ ├── upi_id.xml │ │ ├── upload_prescription.xml │ │ ├── visibility.xml │ │ ├── visibility_off.xml │ │ └── white_bar.xml │ │ ├── font │ │ ├── dm_sans.xml │ │ ├── dm_sans_bold.xml │ │ └── dm_sans_medium.xml │ │ ├── layout │ │ ├── activity_add_prescription.xml │ │ ├── activity_edit_profile.xml │ │ ├── activity_forgot_password.xml │ │ ├── activity_home.xml │ │ ├── activity_profile.xml │ │ ├── activity_sign_in.xml │ │ ├── activity_sign_up.xml │ │ ├── activity_sign_up_first.xml │ │ ├── activity_splashscreen.xml │ │ ├── activity_upimanager.xml │ │ ├── appointment_list.xml │ │ ├── bottomsheet_modal.xml │ │ ├── doctor_card_layout.xml │ │ ├── fragment_add_stats_data.xml │ │ ├── fragment_appointment_booking.xml │ │ ├── fragment_booking_summary.xml │ │ ├── fragment_doctor_details.xml │ │ ├── fragment_home.xml │ │ ├── fragment_my_appointment.xml │ │ ├── fragment_patient_queue.xml │ │ ├── fragment_profile.xml │ │ ├── fragment_reminder.xml │ │ ├── fragment_settings.xml │ │ ├── fragment_statistics.xml │ │ ├── item_pill.xml │ │ ├── layout_custom_edit_text.xml │ │ ├── layout_custom_search_spinner_dialog.xml │ │ ├── layout_custom_spinner.xml │ │ ├── layout_dual_text_view.xml │ │ ├── layout_primary_button.xml │ │ ├── layout_spinner_item.xml │ │ ├── list_items.xml │ │ ├── patient_list.xml │ │ ├── rating_dispute_layout.xml │ │ ├── rating_modal.xml │ │ ├── settings_item.xml │ │ └── statisctics_card_list.xml │ │ ├── menu │ │ ├── bottom_menu.xml │ │ └── options.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── navigation │ │ └── my_nav.xml │ │ ├── raw │ │ ├── bookingdone.json │ │ └── help_lottie.json │ │ ├── values-night │ │ └── themes.xml │ │ ├── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── font_certs.xml │ │ ├── integers.xml │ │ ├── preloaded_fonts.xml │ │ ├── strings.xml │ │ ├── themes.xml │ │ └── view_tags.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ └── data_extraction_rules.xml │ └── test │ └── java │ └── com │ └── geekymusketeers │ └── medify │ ├── ExampleUnitTest.kt │ ├── RemoveCountryCodeTest.kt │ └── utils │ └── ValidatorTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/discord.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Aritra Das 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'org.jetbrains.kotlin.android' 4 | id 'com.google.gms.google-services' 5 | id 'kotlin-parcelize' 6 | id 'kotlin-kapt' 7 | id 'androidx.navigation.safeargs' 8 | } 9 | 10 | 11 | android { 12 | compileSdk 33 13 | 14 | defaultConfig { 15 | applicationId "com.geekymusketeers.medify" 16 | minSdk 23 17 | targetSdk 33 18 | versionCode 1 19 | versionName "1.0" 20 | 21 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 22 | } 23 | buildFeatures { 24 | viewBinding = true 25 | } 26 | 27 | 28 | buildTypes { 29 | release { 30 | minifyEnabled false 31 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 32 | } 33 | } 34 | compileOptions { 35 | sourceCompatibility JavaVersion.VERSION_1_8 36 | targetCompatibility JavaVersion.VERSION_1_8 37 | } 38 | kotlinOptions { 39 | jvmTarget = '1.8' 40 | } 41 | } 42 | 43 | dependencies { 44 | 45 | def lifecycle_version = "2.6.1" 46 | 47 | implementation 'androidx.core:core-ktx:1.8.0' 48 | implementation 'androidx.appcompat:appcompat:1.5.0' 49 | implementation 'com.google.android.material:material:1.6.1' 50 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 51 | implementation 'androidx.navigation:navigation-fragment-ktx:2.5.1' 52 | implementation 'androidx.navigation:navigation-ui-ktx:2.5.1' 53 | testImplementation 'junit:junit:4.13.2' 54 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 55 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 56 | testImplementation "com.google.truth:truth:1.1.3" 57 | 58 | //Firebase 59 | implementation platform('com.google.firebase:firebase-bom:30.3.2') 60 | implementation 'com.google.firebase:firebase-analytics' 61 | implementation 'com.google.firebase:firebase-auth-ktx:21.0.8' 62 | implementation 'com.google.firebase:firebase-database-ktx:20.0.6' 63 | implementation 'com.google.firebase:firebase-storage-ktx:20.0.2' 64 | 65 | //Switch 66 | implementation 'com.github.GwonHyeok:StickySwitch:0.0.16' 67 | 68 | //Swipe/Slide button 69 | implementation "com.ncorti:slidetoact:0.9.0" 70 | 71 | // Material Design 72 | implementation 'com.google.android.material:material:1.6.1' 73 | 74 | //QR Code generator 75 | implementation 'com.google.zxing:core:3.4.1' 76 | implementation 'com.journeyapps:zxing-android-embedded:4.3.0@aar' 77 | 78 | //Chart / Graph 79 | implementation 'com.github.majorkik:SparkLineLayout:1.0.1' 80 | 81 | // Includes the core logic for charts and other elements. 82 | // implementation "com.patrykandpatrick.vico:core:1.6.5" 83 | // For the view system. 84 | // implementation "com.patrykandpatrick.vico:views:1.6.5" 85 | 86 | // Lottie 87 | implementation 'com.airbnb.android:lottie:5.2.0' 88 | 89 | //Cryptography 90 | implementation("androidx.security:security-crypto:1.0.0") 91 | 92 | //Requesting permissions at runtime. 93 | implementation 'com.karumi:dexter:6.2.3' 94 | 95 | 96 | //Coroutines 97 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.6.4' 98 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4' 99 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4' 100 | 101 | //ViewModel 102 | implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" 103 | 104 | // LiveData 105 | implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" 106 | 107 | //GSON 108 | implementation 'com.google.code.gson:gson:2.10.1' 109 | 110 | } -------------------------------------------------------------------------------- /app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "664762172591", 4 | "firebase_url": "https://medify-28dac-default-rtdb.firebaseio.com", 5 | "project_id": "medify-28dac", 6 | "storage_bucket": "medify-28dac.appspot.com" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "1:664762172591:android:314457721fbd773cfd405a", 12 | "android_client_info": { 13 | "package_name": "com.geekymusketeers.medify" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "664762172591-cieoc14ihdk1ocq650e851el2p1qaqb9.apps.googleusercontent.com", 19 | "client_type": 1, 20 | "android_info": { 21 | "package_name": "com.geekymusketeers.medify", 22 | "certificate_hash": "fd28bb7958553070a4f348a9e24d0551193a8f1d" 23 | } 24 | }, 25 | { 26 | "client_id": "664762172591-i6ip89ftgk80jk9lk275247dc0ugg4mu.apps.googleusercontent.com", 27 | "client_type": 1, 28 | "android_info": { 29 | "package_name": "com.geekymusketeers.medify", 30 | "certificate_hash": "b173ac0895ca8a013f2878558ea080755d04fe3a" 31 | } 32 | }, 33 | { 34 | "client_id": "664762172591-j480kmafq2f2ak07k9r9knla4f9vgvfr.apps.googleusercontent.com", 35 | "client_type": 3 36 | } 37 | ], 38 | "api_key": [ 39 | { 40 | "current_key": "AIzaSyBGnv9DHdJAJ_xfXy4uNCMoQw3_S_G2l30" 41 | } 42 | ], 43 | "services": { 44 | "appinvite_service": { 45 | "other_platform_oauth_client": [ 46 | { 47 | "client_id": "664762172591-j480kmafq2f2ak07k9r9knla4f9vgvfr.apps.googleusercontent.com", 48 | "client_type": 3 49 | } 50 | ] 51 | } 52 | } 53 | } 54 | ], 55 | "configuration_version": "1" 56 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/geekymusketeers/medify/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.geekymusketeers.medify", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 26 | 29 | 32 | 35 | 38 | 41 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 53 | 57 | 61 | 65 | 66 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/adapter/CustomSpinnerAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.adapter 2 | 3 | import android.annotation.SuppressLint 4 | import android.view.LayoutInflater 5 | import android.view.ViewGroup 6 | import androidx.recyclerview.widget.RecyclerView 7 | import com.geekymusketeers.medify.databinding.LayoutSpinnerItemBinding 8 | 9 | 10 | class CustomSpinnerAdapter( 11 | private val onClickListener: (item: String) -> Unit 12 | ) : RecyclerView.Adapter() { 13 | 14 | private val items = mutableListOf() 15 | 16 | class CustomSpinnerViewHolder(val binding: LayoutSpinnerItemBinding) : 17 | RecyclerView.ViewHolder(binding.root) 18 | 19 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomSpinnerViewHolder { 20 | return CustomSpinnerViewHolder( 21 | LayoutSpinnerItemBinding.inflate( 22 | LayoutInflater.from(parent.context), 23 | parent, false 24 | ) 25 | ) 26 | } 27 | 28 | override fun onBindViewHolder(holder: CustomSpinnerViewHolder, position: Int) { 29 | val item = items[position] 30 | 31 | holder.binding.apply { 32 | spinnerRecyclerViewItem.text = item 33 | root.setOnClickListener { 34 | onClickListener(item) 35 | } 36 | } 37 | } 38 | 39 | override fun getItemCount(): Int { 40 | return items.size 41 | } 42 | 43 | @SuppressLint("NotifyDataSetChanged") 44 | fun setItem(list: List) { 45 | items.clear() 46 | items.addAll(list) 47 | notifyDataSetChanged() 48 | } 49 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/base/BaseViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.base 2 | 3 | import android.app.Application 4 | import androidx.lifecycle.AndroidViewModel 5 | import androidx.lifecycle.MutableLiveData 6 | import java.net.HttpURLConnection 7 | 8 | 9 | open class BaseViewModel(application: Application) : 10 | AndroidViewModel(application) { 11 | /** 12 | * LiveData to show progress in activity/fragment 13 | */ 14 | val progressLiveData: MutableLiveData by lazy { MutableLiveData() } 15 | 16 | /** 17 | * Common LiveData to handle error in activity/fragment. If required, you can use your own live data to handle error scenarios also. 18 | */ 19 | // val errorLiveData: SingleLiveEvent by lazy { SingleLiveEvent() } 20 | 21 | /** 22 | * LiveData to handle exceptions like no internet connection etc 23 | */ 24 | // val exceptionLiveData: SingleLiveEvent by lazy { SingleLiveEvent() } 25 | 26 | /** 27 | * Method to help processing of API response. If further processing of response is not needed you can pass the LiveData to directly post value 28 | * @param call: Network call to be executed 29 | * @param updateProgress: Boolean value indicating if you want to track the progress using progressLiveData 30 | * @return 31 | */ 32 | // suspend fun processCoroutine( 33 | // call: suspend () -> NetworkResponse, 34 | // updateProgress: Boolean = true 35 | // ): NetworkResponse { 36 | // if (updateProgress) progressLiveData.postValue(true) 37 | // val response = call.invoke() 38 | // response.onError { 39 | // if (it.responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) { 40 | // getApplication().showUnAuthorizedAPICallForceLogoutScreen(getApplication(), AnalyticsData.EventName.UNAUTHORIZED_ACCESS) 41 | // } 42 | // }.onException { 43 | // exceptionLiveData.postValue(it) 44 | // } 45 | // progressLiveData.postValue(false) 46 | // return response 47 | // } 48 | 49 | /** 50 | * Return User preference data(i.e user profile) being set and used throughout the app. 51 | * @return [UserPreference] 52 | */ 53 | // protected fun getUserPreference(): UserPreference = 54 | // (getApplication() as NagarApp).userSharedPreference 55 | 56 | /** 57 | * Return App preference being set and used throughout the app. 58 | * @return [AppPreference] 59 | */ 60 | // protected fun getAppPreference(): AppPreference = 61 | // (getApplication() as NagarApp).appSharedPreference 62 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/model/DoctorAppointment.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.model 2 | 3 | data class DoctorAppointment( 4 | var PatientName: String? = null, 5 | var Disease: String? = null, 6 | var PatientPhone: String? = null, 7 | var Time: String? = null, 8 | var Date: String? = null, 9 | var PatientCondition: String? = null, 10 | var Prescription: String? = null, 11 | var TotalPoints: String? = null, 12 | var DoctorUID: String? = null, 13 | var PatientID: String? = null, 14 | ) 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/model/PatientAppointment.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.model 2 | 3 | data class PatientAppointment( 4 | var DoctorName: String? = null, 5 | var DoctorPhone: String? = null, 6 | var DoctorUID: String? = null, 7 | var Disease: String? = null, 8 | var Time: String? = null, 9 | var Date: String? = null, 10 | var PatientCondition: String? = null, 11 | var prescriptionLink: String? = null, 12 | var PatientID: String? = null, 13 | ) 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/model/SettingsItem.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.model 2 | 3 | data class SettingsItem( 4 | val itemID: Int, 5 | val drawableInt: Int, 6 | val itemName: String 7 | ) 8 | 9 | enum class SettingsState { 10 | TO_EDIT_PROFILE, 11 | TO_UPLOAD_PRESCRIPTION, 12 | TO_UPI_QR, 13 | TO_ABOUT_US, 14 | TO_FEEDBACK, 15 | TO_NEED_HELP, 16 | TO_LOGOUT; 17 | 18 | companion object { 19 | fun getSettingsState(state: SettingsState) : Int { 20 | return when (state) { 21 | TO_EDIT_PROFILE -> 0 22 | TO_UPLOAD_PRESCRIPTION -> 1 23 | TO_UPI_QR -> 2 24 | TO_ABOUT_US -> 3 25 | TO_FEEDBACK-> 4 26 | TO_NEED_HELP-> 5 27 | TO_LOGOUT-> 6 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/model/Statistics.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.model 2 | 3 | import android.os.Parcelable 4 | import kotlinx.parcelize.Parcelize 5 | import java.util.TreeMap 6 | 7 | //@Parcelize 8 | //data class HealthData( 9 | // var name: String? = null, 10 | // var tests: TreeMap? = null, 11 | // var healthId : String? = null 12 | //) : Parcelable 13 | 14 | @Parcelize 15 | data class HealthData( 16 | var name: String? = null, 17 | var tests: List? = null, 18 | var healthId: String? = null 19 | ) : Parcelable { 20 | // fun getSortedTests(): List { 21 | // return tests?.sortedBy { it.dateTime } ?: emptyList() 22 | // } 23 | } 24 | 25 | @Parcelize 26 | data class TestResult( 27 | var result: String? = null, 28 | var dateTime: String? = null 29 | ) : Parcelable -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/model/Summary.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.model 2 | 3 | import android.os.Parcelable 4 | import kotlinx.parcelize.Parcelize 5 | 6 | @Parcelize 7 | data class Summary( 8 | val doctorName: String, 9 | val doctorSpeciality: String, 10 | val doctorEmail: String, 11 | val doctorPhone: String, 12 | val appointmentDate: String, 13 | val appointmentTime: String, 14 | val disease: String, 15 | val painLevel: String, 16 | val totalPoint: Int 17 | ) : Parcelable 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/HomeActivity.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import android.os.Bundle 5 | import android.view.View 6 | import android.widget.Toast 7 | import androidx.navigation.NavController 8 | import androidx.navigation.findNavController 9 | import androidx.navigation.ui.AppBarConfiguration 10 | import androidx.navigation.ui.setupWithNavController 11 | import com.geekymusketeers.medify.R 12 | import com.geekymusketeers.medify.databinding.ActivityHomeBinding 13 | import com.google.android.material.bottomnavigation.BottomNavigationView 14 | 15 | class HomeActivity : AppCompatActivity() { 16 | 17 | private lateinit var _binding: ActivityHomeBinding 18 | private var timer = 0L 19 | 20 | override fun onCreate(savedInstanceState: Bundle?) { 21 | super.onCreate(savedInstanceState) 22 | _binding = ActivityHomeBinding.inflate(layoutInflater) 23 | setContentView(_binding.root) 24 | 25 | //Hides action bar 26 | supportActionBar?.hide() 27 | 28 | val bottomNavigationView = _binding.bottomNav 29 | val navController: NavController = findNavController(R.id.fragmentContainerView) 30 | AppBarConfiguration(setOf(R.id.home, R.id.stats, R.id.appointment, R.id.settings)) 31 | 32 | bottomNavigationView.setupWithNavController(navController) 33 | 34 | navController.addOnDestinationChangedListener { _, destination, _ -> 35 | when (destination.id) { 36 | R.id.home -> showBottomNav(bottomNavigationView) 37 | R.id.stats -> showBottomNav(bottomNavigationView) 38 | R.id.appointment -> showBottomNav(bottomNavigationView) 39 | R.id.settings -> showBottomNav(bottomNavigationView) 40 | else -> hideBottomNav(bottomNavigationView) 41 | } 42 | } 43 | } 44 | 45 | private fun showBottomNav(bottomNavigationView: BottomNavigationView) { 46 | bottomNavigationView.visibility = View.VISIBLE 47 | } 48 | 49 | private fun hideBottomNav(bottomNavigationView: BottomNavigationView) { 50 | bottomNavigationView.visibility = View.GONE 51 | } 52 | 53 | @Deprecated("Deprecated in Java") 54 | override fun onBackPressed() { 55 | 56 | val navController: NavController = findNavController(R.id.fragmentContainerView) 57 | val count = navController.backQueue.size 58 | 59 | if (count <= 2) { 60 | if (timer + 2000L > System.currentTimeMillis()) { 61 | finish() 62 | // onBackPressedDispatcher.onBackPressed() 63 | } else { 64 | Toast.makeText( 65 | applicationContext, getString(R.string.press_once_again_to_exit), 66 | Toast.LENGTH_SHORT 67 | ).show() 68 | } 69 | timer = System.currentTimeMillis() 70 | } else { 71 | navController.popBackStack() 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/adapter/DoctorListAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.adapter 2 | 3 | import android.annotation.SuppressLint 4 | import android.util.Log 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import android.widget.Button 9 | import android.widget.TextView 10 | import androidx.recyclerview.widget.RecyclerView 11 | import com.geekymusketeers.medify.R 12 | import com.geekymusketeers.medify.model.User 13 | 14 | class DoctorListAdapter(val listener: (User)-> Unit) : RecyclerView.Adapter() { 15 | 16 | private var doctorList : MutableList = mutableListOf() 17 | 18 | class DoctorListViewModel(itemView: View) : RecyclerView.ViewHolder(itemView) { 19 | 20 | val doctorName : TextView = itemView.findViewById(R.id.nameDisplay) 21 | val category : TextView = itemView.findViewById(R.id.categoryDisplay) 22 | val bookButton : Button = itemView.findViewById(R.id.book_button) 23 | } 24 | 25 | override fun onCreateViewHolder( 26 | parent: ViewGroup, 27 | viewType: Int 28 | ): DoctorListViewModel { 29 | 30 | val itemView = LayoutInflater.from(parent.context).inflate(R.layout.doctor_card_layout,parent,false) 31 | return DoctorListViewModel(itemView) 32 | } 33 | 34 | override fun onBindViewHolder(holder: DoctorListViewModel, position: Int) { 35 | 36 | val currentItem = doctorList[position] 37 | Log.d("", "Doctors are: $currentItem") 38 | 39 | holder.itemView.setOnClickListener { 40 | listener(currentItem) 41 | } 42 | 43 | holder.bookButton.setOnClickListener { 44 | listener(currentItem) 45 | } 46 | 47 | holder.doctorName.text = currentItem.Name 48 | holder.category.text = currentItem.Specialist 49 | } 50 | 51 | override fun getItemCount(): Int { 52 | return doctorList.size 53 | } 54 | 55 | @SuppressLint("NotifyDataSetChanged") 56 | fun addItems(list: List) { 57 | doctorList.clear() 58 | doctorList.addAll(list) 59 | Log.d("", "Doctor List size: ${list.size} and lists items are : $list") 60 | notifyDataSetChanged() 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/adapter/PatientAppointmentAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.adapter 2 | 3 | import android.annotation.SuppressLint 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import android.widget.TextView 8 | import androidx.recyclerview.widget.RecyclerView 9 | import com.geekymusketeers.medify.model.PatientAppointment 10 | import com.geekymusketeers.medify.R 11 | 12 | class PatientAppointmentAdapter( 13 | val listener: (PatientAppointment) -> Unit 14 | ) : 15 | RecyclerView.Adapter() { 16 | 17 | private var appointmentList = mutableListOf() 18 | 19 | override fun onCreateViewHolder( 20 | parent: ViewGroup, 21 | viewType: Int 22 | ): PatientAppointmentViewHolder { 23 | val itemView = 24 | LayoutInflater.from(parent.context).inflate(R.layout.patient_list, parent, false) 25 | return PatientAppointmentViewHolder(itemView) 26 | } 27 | 28 | override fun getItemCount(): Int { 29 | return appointmentList.size 30 | } 31 | 32 | @SuppressLint("SetTextI18n") 33 | override fun onBindViewHolder(holder: PatientAppointmentViewHolder, position: Int) { 34 | val currentItem = appointmentList[position] 35 | 36 | holder.apply { 37 | name.text = currentItem.DoctorName 38 | disease.text = currentItem.Disease 39 | time.text = currentItem.Time 40 | date.text = currentItem.Date 41 | itemView.setOnClickListener { 42 | listener(currentItem) 43 | } 44 | } 45 | } 46 | 47 | class PatientAppointmentViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { 48 | val name: TextView = itemView.findViewById(R.id.nameDisplay) 49 | val disease: TextView = itemView.findViewById(R.id.diseaseDisplay) 50 | val time: TextView = itemView.findViewById(R.id.timeDisplay) 51 | val date: TextView = itemView.findViewById(R.id.dateDisplay) 52 | } 53 | 54 | @SuppressLint("NotifyDataSetChanged") 55 | fun setData(appointment: List) { 56 | this.appointmentList.clear() 57 | this.appointmentList.addAll(appointment) 58 | notifyDataSetChanged() 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/adapter/SettingsAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.adapter 2 | 3 | import android.content.Context 4 | import android.graphics.Typeface 5 | import android.view.LayoutInflater 6 | import android.view.ViewGroup 7 | import androidx.core.content.res.ResourcesCompat 8 | import androidx.recyclerview.widget.RecyclerView 9 | import com.geekymusketeers.medify.R 10 | import com.geekymusketeers.medify.databinding.SettingsItemBinding 11 | import com.geekymusketeers.medify.model.SettingsItem 12 | 13 | class SettingsAdapter( 14 | val context : Context, 15 | private val settingsItemList: ArrayList, 16 | private val listener: (Int) -> Unit 17 | ) : 18 | RecyclerView.Adapter() { 19 | 20 | class SettingsViewHolder(val binding: SettingsItemBinding) : RecyclerView.ViewHolder(binding.root) 21 | 22 | override fun onCreateViewHolder( 23 | parent: ViewGroup, 24 | viewType: Int 25 | ): SettingsViewHolder { 26 | return SettingsViewHolder( 27 | SettingsItemBinding.inflate( 28 | LayoutInflater.from(parent.context), parent, false 29 | ) 30 | ) 31 | } 32 | 33 | override fun onBindViewHolder(holder: SettingsViewHolder, position: Int) { 34 | val settingsList = settingsItemList[position] 35 | holder.binding.apply { 36 | settingsItemName.apply { 37 | text = settingsList.itemName 38 | if (settingsList.itemID == 6) { 39 | setTextColor(ResourcesCompat.getColor(resources, R.color.red, null)) 40 | setTypeface(null, Typeface.BOLD) 41 | } 42 | } 43 | } 44 | holder.binding.root.setOnClickListener { 45 | listener(position) 46 | } 47 | 48 | holder.binding.settingsItemIcon.setImageResource(settingsList.drawableInt) 49 | } 50 | 51 | override fun getItemCount() = settingsItemList.size 52 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/adapter/StatsListAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.adapter 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Build 5 | import android.view.LayoutInflater 6 | import android.view.ViewGroup 7 | import androidx.annotation.RequiresApi 8 | import androidx.recyclerview.widget.RecyclerView 9 | import com.geekymusketeers.medify.databinding.StatiscticsCardListBinding 10 | import com.geekymusketeers.medify.model.HealthData 11 | import com.geekymusketeers.medify.utils.DateTimeExtension.convertTimestampToDateTime 12 | 13 | 14 | class StatsListAdapter( 15 | private val listener: (HealthData) -> Unit 16 | ) : RecyclerView.Adapter() { 17 | 18 | private var testList: List = ArrayList() 19 | 20 | class StatsViewHolder(val binding: StatiscticsCardListBinding) : 21 | RecyclerView.ViewHolder(binding.root) 22 | 23 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StatsViewHolder { 24 | return StatsViewHolder( 25 | StatiscticsCardListBinding.inflate(LayoutInflater.from(parent.context), parent, false) 26 | ) 27 | } 28 | 29 | override fun getItemCount(): Int { 30 | return testList.size 31 | } 32 | 33 | @RequiresApi(Build.VERSION_CODES.O) 34 | @SuppressLint("SetTextI18n") 35 | override fun onBindViewHolder(holder: StatsViewHolder, position: Int) { 36 | val healthData = testList[position] 37 | 38 | holder.binding.apply { 39 | testName.text = healthData.name 40 | val sortedTests = healthData.tests?.sortedBy { it.dateTime } ?: emptyList() 41 | val sortedResults = sortedTests.map { it.result?.toInt() ?: 0 } 42 | // val sortedResults = sortedTests.map { it.result?.toFloat() ?: 0f } 43 | val min = sortedResults.minOrNull() ?: 0f 44 | val max = sortedResults.maxOrNull() ?: 0f 45 | testDataRange.text = "Min: $min - Max: $max" 46 | testDataStats.setData(sortedResults as ArrayList) 47 | // val chartEntryModel = entryModelOf((sortedResults.indices).map { index -> 48 | // entryOf(index.toFloat(), sortedResults[index]) 49 | // } as ArrayList) 50 | // testDataStats.setModel(chartEntryModel) 51 | testDateTime.text = healthData.healthId?.convertTimestampToDateTime() 52 | 53 | parentLayout.setOnClickListener { 54 | listener(healthData) 55 | } 56 | } 57 | } 58 | 59 | @SuppressLint("NotifyDataSetChanged") 60 | fun addItems(list: List) { 61 | testList = list 62 | notifyDataSetChanged() 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/auth/forgotPassword/ForgotPasswordActivity.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.auth.forgotPassword 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import android.os.Bundle 5 | import android.widget.Toast 6 | import androidx.activity.viewModels 7 | import com.geekymusketeers.medify.base.ViewModelFactory 8 | import com.geekymusketeers.medify.databinding.ActivityForgotPasswordBinding 9 | 10 | class ForgotPasswordActivity : AppCompatActivity() { 11 | 12 | private lateinit var binding : ActivityForgotPasswordBinding 13 | private val forgotPasswordViewModel by viewModels { ViewModelFactory() } 14 | 15 | override fun onCreate(savedInstanceState: Bundle?) { 16 | super.onCreate(savedInstanceState) 17 | binding = ActivityForgotPasswordBinding.inflate(layoutInflater) 18 | setContentView(binding.root) 19 | 20 | initObservers() 21 | initViews() 22 | } 23 | 24 | private fun initViews() { 25 | binding.run { 26 | forgotPasswordButton.setOnClickListener { 27 | forgotPasswordViewModel.sendResetLinkMail() 28 | } 29 | emailEditText.setUserInputListener { 30 | forgotPasswordViewModel.setEmail(it) 31 | } 32 | } 33 | } 34 | 35 | private fun initObservers() { 36 | forgotPasswordViewModel.run { 37 | errorLiveData.observe(this@ForgotPasswordActivity) { 38 | Toast.makeText(this@ForgotPasswordActivity, it, Toast.LENGTH_SHORT).show() 39 | } 40 | enableSendMailButton.observe(this@ForgotPasswordActivity) { 41 | binding.forgotPasswordButton.isEnabled = it 42 | binding.forgotPasswordButton.setButtonEnabled(it) 43 | } 44 | forgotPasswordLiveData.observe(this@ForgotPasswordActivity) { 45 | Toast.makeText(this@ForgotPasswordActivity, "Reset link sent to ${getEmail()}", Toast.LENGTH_SHORT).show() 46 | finish() 47 | } 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/auth/forgotPassword/ForgotPasswordViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.auth.forgotPassword 2 | 3 | import android.app.Application 4 | import androidx.lifecycle.MutableLiveData 5 | import com.geekymusketeers.medify.base.BaseViewModel 6 | import com.google.firebase.auth.FirebaseAuth 7 | 8 | 9 | class ForgotPasswordViewModel(application: Application) : BaseViewModel(application) { 10 | 11 | private var email = MutableLiveData() 12 | var forgotPasswordLiveData = MutableLiveData() 13 | var enableSendMailButton = MutableLiveData() 14 | var errorLiveData = MutableLiveData() 15 | 16 | fun setEmail(email: String) { 17 | this.email.value = email 18 | updateEnableSendMailButton() 19 | } 20 | 21 | fun getEmail() = email.value.toString() 22 | 23 | fun sendResetLinkMail() { 24 | val email = email.value!! 25 | FirebaseAuth.getInstance().sendPasswordResetEmail(email).addOnCompleteListener { 26 | if (it.isSuccessful) { 27 | forgotPasswordLiveData.value = true 28 | } else { 29 | errorLiveData.postValue(it.exception?.message) 30 | } 31 | }.addOnFailureListener { 32 | errorLiveData.postValue(it.message) 33 | } 34 | } 35 | 36 | 37 | private fun updateEnableSendMailButton() { 38 | enableSendMailButton.value = email.value?.isNotEmpty() 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/auth/signInScreen/SignInRepository.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.auth.signInScreen 2 | 3 | import com.google.firebase.auth.FirebaseAuth 4 | import com.google.firebase.auth.FirebaseAuthInvalidUserException 5 | import com.google.firebase.auth.FirebaseUser 6 | import kotlinx.coroutines.tasks.await 7 | 8 | 9 | class SignInRepository { 10 | suspend fun loginUser(email: String, password: String): FirebaseUser? { 11 | return try { 12 | val authResult = FirebaseAuth.getInstance().signInWithEmailAndPassword(email, password).await() 13 | authResult.user 14 | } catch (e: FirebaseAuthInvalidUserException) { 15 | null // Return null if the user is not registered 16 | } catch (e: Exception) { 17 | null 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/auth/signInScreen/SignInScreen.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.auth.signInScreen 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.content.Intent 6 | import androidx.appcompat.app.AppCompatActivity 7 | import android.os.Bundle 8 | import android.widget.Toast 9 | import androidx.activity.viewModels 10 | import androidx.core.content.res.ResourcesCompat 11 | import com.geekymusketeers.medify.R 12 | import com.geekymusketeers.medify.base.ViewModelFactory 13 | import com.geekymusketeers.medify.databinding.ActivitySignInBinding 14 | import com.geekymusketeers.medify.ui.HomeActivity 15 | import com.geekymusketeers.medify.ui.auth.forgotPassword.ForgotPasswordActivity 16 | import com.geekymusketeers.medify.ui.auth.signUpScreen.firstScreen.SignUpFirstScreen 17 | import com.geekymusketeers.medify.utils.Constants 18 | 19 | class SignInScreen : AppCompatActivity() { 20 | 21 | private lateinit var binding: ActivitySignInBinding 22 | private val signInViewModel by viewModels { ViewModelFactory() } 23 | 24 | @SuppressLint("ClickableViewAccessibility") 25 | override fun onCreate(savedInstanceState: Bundle?) { 26 | super.onCreate(savedInstanceState) 27 | binding = ActivitySignInBinding.inflate(layoutInflater) 28 | setContentView(binding.root) 29 | 30 | initObservers() 31 | initViews() 32 | 33 | } 34 | 35 | private fun initViews() { 36 | binding.run { 37 | emailEditText.setUserInputListener { 38 | signInViewModel.setEmail(it) 39 | } 40 | passwordEditText.apply { 41 | setUserInputListener { 42 | signInViewModel.setPassword(it) 43 | } 44 | setEndDrawableIcon( 45 | ResourcesCompat.getDrawable(resources, R.drawable.pass_show, null) 46 | ) 47 | 48 | } 49 | forgotPasswordTextView.setOnClickListener { 50 | startActivity(Intent(this@SignInScreen, ForgotPasswordActivity::class.java)) 51 | } 52 | bottomDualEditText.apply { 53 | firstTextView.text = getString(R.string.don_t_have_an_account) 54 | secondTextView.apply { 55 | text = context.getString(R.string.sign_up) 56 | setOnClickListener { 57 | startActivity(Intent(this@SignInScreen, SignUpFirstScreen::class.java)) 58 | } 59 | } 60 | } 61 | loginButton.setOnClickListener { 62 | signInViewModel.login() 63 | } 64 | } 65 | } 66 | 67 | private fun initObservers() { 68 | signInViewModel.run { 69 | errorLiveData.observe(this@SignInScreen) { 70 | Toast.makeText(this@SignInScreen, it, Toast.LENGTH_SHORT).show() 71 | } 72 | enableLoginButton.observe(this@SignInScreen) { 73 | binding.loginButton.isEnabled = it 74 | binding.loginButton.setButtonEnabled(it) 75 | } 76 | userIDLiveData.observe(this@SignInScreen) { 77 | getUserFromFirebase() 78 | } 79 | userLiveData.observe(this@SignInScreen) { 80 | val sharedPreferences = 81 | getSharedPreferences(Constants.UserData, Context.MODE_PRIVATE) 82 | saveInSharedPreference(sharedPreferences) 83 | } 84 | sharedPreferenceLiveData.observe(this@SignInScreen) { 85 | if (it) { 86 | Toast.makeText( 87 | this@SignInScreen, 88 | getString(R.string.logged_in), 89 | Toast.LENGTH_SHORT 90 | ).show() 91 | startActivity(Intent(this@SignInScreen, HomeActivity::class.java)) 92 | finishAffinity() 93 | } 94 | } 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/auth/signUpScreen/SignUpRepository.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.auth.signUpScreen 2 | 3 | import com.google.firebase.auth.FirebaseAuth 4 | import com.google.firebase.auth.FirebaseAuthUserCollisionException 5 | import com.google.firebase.auth.FirebaseUser 6 | import kotlinx.coroutines.tasks.await 7 | 8 | 9 | class SignUpRepository { 10 | 11 | suspend fun registerUser(email: String, password: String): FirebaseUser? { 12 | return try { 13 | val authResult = FirebaseAuth.getInstance().createUserWithEmailAndPassword(email, password).await() 14 | authResult.user 15 | } catch (e: FirebaseAuthUserCollisionException) { 16 | null // Return null if the user email already exists 17 | } catch (e: Exception) { 18 | null 19 | } 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/auth/signUpScreen/firstScreen/SignUpFirstViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.auth.signUpScreen.firstScreen 2 | 3 | import android.app.Application 4 | import androidx.lifecycle.MutableLiveData 5 | import com.geekymusketeers.medify.base.BaseViewModel 6 | import com.geekymusketeers.medify.model.User 7 | import com.geekymusketeers.medify.utils.Validator.Companion.isValidEmail 8 | import com.geekymusketeers.medify.utils.Validator.Companion.isValidName 9 | import com.geekymusketeers.medify.utils.Validator.Companion.isValidPassword 10 | import com.geekymusketeers.medify.utils.Validator.Companion.isValidPhone 11 | 12 | 13 | class SignUpFirstViewModel(application: Application) : BaseViewModel(application) { 14 | 15 | var userName = MutableLiveData() 16 | var userEmail = MutableLiveData() 17 | var userPhone = MutableLiveData() 18 | var userPassword = MutableLiveData() 19 | var userAge = MutableLiveData() 20 | var userGender = MutableLiveData() 21 | var userLiveData = MutableLiveData() 22 | val enableNextButtonLiveData: MutableLiveData by lazy { MutableLiveData() } 23 | 24 | //Validation 25 | val isValidName: MutableLiveData by lazy { MutableLiveData() } 26 | val isValidEmail: MutableLiveData by lazy { MutableLiveData() } 27 | val isValidPhoneNumber: MutableLiveData by lazy { MutableLiveData() } 28 | val isValidPassword: MutableLiveData by lazy { MutableLiveData() } 29 | 30 | init { 31 | userGender.value = "male" 32 | userAge.value = 0 33 | } 34 | 35 | fun setUserName(name: String) { 36 | userName.value = name 37 | updateButtonState() 38 | } 39 | 40 | fun setUserEmail(email: String) { 41 | userEmail.value = email 42 | updateButtonState() 43 | } 44 | 45 | fun setUserPhone(phone: String) { 46 | userPhone.value = phone 47 | updateButtonState() 48 | } 49 | 50 | fun setUserPassword(password: String) { 51 | userPassword.value = password 52 | updateButtonState() 53 | } 54 | 55 | fun setUserAge(age: Int) { 56 | userAge.value = age 57 | updateButtonState() 58 | } 59 | 60 | fun setUserGender(gender: String) { 61 | userGender.value = gender 62 | updateButtonState() 63 | } 64 | 65 | fun setUpUser() { 66 | val name: String = userName.value.toString().trim() 67 | val email: String = userEmail.value.toString().trim().lowercase() 68 | val phone: String = userPhone.value.toString().trim() 69 | val password: String = userPassword.value.toString().trim() 70 | val age: Int = userAge.value!! 71 | val gender: String = userGender.value.toString().trim() 72 | 73 | 74 | if (name.isValidName().not()) { 75 | isValidName.postValue(false) 76 | return 77 | } 78 | if (email.isValidEmail().not()) { 79 | isValidEmail.postValue(false) 80 | return 81 | } 82 | if (phone.isValidPhone().not()) { 83 | isValidPhoneNumber.postValue(false) 84 | return 85 | } 86 | if (password.isValidPassword().not()) { 87 | isValidPassword.postValue(false) 88 | return 89 | } 90 | val user = User( 91 | Name = name, 92 | Email = email, 93 | Phone = phone, 94 | Age = age, 95 | Gender = gender 96 | ) 97 | userLiveData.postValue(user) 98 | } 99 | 100 | 101 | private fun updateButtonState() { 102 | val requiredField = userName.value.isNullOrEmpty() || 103 | userEmail.value.isNullOrEmpty() || userPhone.value.isNullOrEmpty() || 104 | userPassword.value.isNullOrEmpty() || userAge.value == 0 || 105 | userGender.value.isNullOrEmpty() 106 | enableNextButtonLiveData.value = requiredField.not() 107 | // setProgressValue() 108 | } 109 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/custom_views/CustomButton.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.presin.ui.custom_views 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.graphics.drawable.Drawable 6 | import android.util.AttributeSet 7 | import android.view.LayoutInflater 8 | import androidx.constraintlayout.widget.ConstraintLayout 9 | import androidx.core.content.ContextCompat 10 | import com.geekymusketeers.medify.R 11 | import com.geekymusketeers.medify.databinding.LayoutPrimaryButtonBinding 12 | import com.geekymusketeers.medify.utils.Utils.hide 13 | import com.geekymusketeers.medify.utils.Utils.show 14 | 15 | 16 | class CustomButton @JvmOverloads constructor( 17 | context: Context, 18 | attrs: AttributeSet? = null, 19 | defStyleAttr: Int = 0 20 | ) : ConstraintLayout(context, attrs, defStyleAttr) { 21 | 22 | private lateinit var binding: LayoutPrimaryButtonBinding 23 | private var isEnabled: Boolean = false 24 | 25 | init { 26 | initView(context, attrs) 27 | } 28 | 29 | @SuppressLint("CustomViewStyleable") 30 | private fun initView(context: Context, attrs: AttributeSet?) { 31 | 32 | binding = LayoutPrimaryButtonBinding.inflate(LayoutInflater.from(context), this, true) 33 | context.obtainStyledAttributes(attrs, R.styleable.ButtonCustomLayout).apply { 34 | try { 35 | val header = getString(R.styleable.ButtonCustomLayout_header) 36 | // val endDrawableIcon = getDrawable(R.styleable.ButtonCustomLayout_endIcon) 37 | val inputEnabled = getBoolean(R.styleable.ButtonCustomLayout_inputEnabled, false) 38 | setHeader(header) 39 | // setEndDrawableIcon(endDrawableIcon) 40 | setButtonEnabled(inputEnabled) 41 | } finally { 42 | recycle() 43 | } 44 | } 45 | } 46 | 47 | fun setEndDrawableIcon(drawable: Drawable?) { 48 | drawable?.let { 49 | binding.buttonIcon.apply { 50 | setImageDrawable(it) 51 | show() 52 | } 53 | } 54 | } 55 | 56 | fun setButtonEnabled(inputEnabled: Boolean) { 57 | binding.run { 58 | isEnabled = inputEnabled 59 | buttonConstraintLayout.setBackgroundColor( 60 | ContextCompat.getColor( 61 | context, 62 | if (inputEnabled) R.color.button_enable_color else R.color.button_disable_color 63 | ) 64 | ) 65 | } 66 | } 67 | 68 | fun showButtonProgress() { 69 | binding.apply { 70 | buttonLinearLayoutWithTextViewAndEndDrawable.hide() 71 | buttonProgress.show() 72 | } 73 | } 74 | 75 | fun hideButtonProgress() { 76 | binding.apply { 77 | buttonLinearLayoutWithTextViewAndEndDrawable.show() 78 | buttonProgress.hide() 79 | } 80 | } 81 | 82 | fun setHeader(header: String?) { 83 | binding.buttonText.text = header 84 | } 85 | 86 | fun getHeader() : String { 87 | return binding.buttonText.text.toString() 88 | } 89 | 90 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/introduction/Splashscreen.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.introduction 2 | 3 | import android.content.Intent 4 | import androidx.appcompat.app.AppCompatActivity 5 | import android.os.Bundle 6 | import com.geekymusketeers.medify.ui.HomeActivity 7 | import com.geekymusketeers.medify.R 8 | import com.geekymusketeers.medify.ui.auth.signInScreen.SignInScreen 9 | import com.geekymusketeers.medify.utils.Logger 10 | import com.google.firebase.auth.FirebaseAuth 11 | import com.google.firebase.auth.FirebaseUser 12 | import kotlinx.coroutines.CoroutineScope 13 | import kotlinx.coroutines.Dispatchers 14 | import kotlinx.coroutines.delay 15 | import kotlinx.coroutines.launch 16 | 17 | class Splashscreen : AppCompatActivity() { 18 | 19 | private lateinit var auth: FirebaseAuth 20 | 21 | override fun onCreate(savedInstanceState: Bundle?) { 22 | super.onCreate(savedInstanceState) 23 | setContentView(R.layout.activity_splashscreen) 24 | 25 | supportActionBar?.hide() 26 | auth = FirebaseAuth.getInstance(); //initialize Firebase Auth 27 | val currentUser: FirebaseUser? = auth.currentUser //Get the current user 28 | Logger.debugLog("Current User: $currentUser") 29 | 30 | if (currentUser == null) sendUserToLoginActivity() //If the user has not logged in, send them to On-Boarding Activity 31 | else { 32 | //If user was logged in last time 33 | CoroutineScope(Dispatchers.Main).launch { 34 | //If the user has logged in, send them to Home Activity 35 | delay(2000L) 36 | val loginIntent = 37 | Intent( 38 | this@Splashscreen, 39 | HomeActivity::class.java 40 | ) //If the user email is verified 41 | loginIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) 42 | startActivity(loginIntent) 43 | finish() 44 | } 45 | } 46 | } 47 | 48 | private fun sendUserToLoginActivity() { 49 | CoroutineScope(Dispatchers.Main).launch { 50 | delay(2000L) 51 | val loginIntent = Intent( 52 | this@Splashscreen, 53 | SignInScreen::class.java 54 | ) 55 | loginIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) 56 | startActivity(loginIntent) 57 | finish() 58 | } 59 | } 60 | 61 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/mainFragments/ReminderFragment.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.mainFragments 2 | 3 | import android.os.Bundle 4 | import androidx.fragment.app.Fragment 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import com.geekymusketeers.medify.R 9 | 10 | class ReminderFragment : Fragment() { 11 | 12 | override fun onCreateView( 13 | inflater: LayoutInflater, container: ViewGroup?, 14 | savedInstanceState: Bundle? 15 | ): View? { 16 | // Inflate the layout for this fragment 17 | return inflater.inflate(R.layout.fragment_reminder, container, false) 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/mainFragments/appointments/MyAppointmentsViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.mainFragments.appointments 2 | 3 | import android.app.Application 4 | import android.content.SharedPreferences 5 | import androidx.lifecycle.MutableLiveData 6 | import com.geekymusketeers.medify.base.BaseViewModel 7 | import com.geekymusketeers.medify.model.PatientAppointment 8 | import com.geekymusketeers.medify.model.User 9 | import com.geekymusketeers.medify.utils.Constants 10 | import com.geekymusketeers.medify.utils.Logger 11 | import com.geekymusketeers.medify.utils.SharedPrefsExtension.getUserFromSharedPrefs 12 | import com.google.firebase.database.DataSnapshot 13 | import com.google.firebase.database.DatabaseError 14 | import com.google.firebase.database.FirebaseDatabase 15 | import com.google.firebase.database.ValueEventListener 16 | 17 | 18 | class MyAppointmentsViewModel(application: Application) : BaseViewModel(application) { 19 | 20 | val userLiveData = MutableLiveData() 21 | private val databaseReference = FirebaseDatabase.getInstance().reference.child(Constants.Users) 22 | val myAppointmentList = MutableLiveData>() 23 | 24 | fun getAppointmentsForTheDate(date: String) { 25 | myAppointmentList.value = ArrayList() 26 | val helperAppointmentList = mutableListOf() 27 | val userID = userLiveData.value!!.UID!! 28 | databaseReference.child(userID).child("PatientsAppointments") 29 | .child(date).addValueEventListener(object : ValueEventListener { 30 | override fun onDataChange(snapshot: DataSnapshot) { 31 | if (snapshot.exists()) { 32 | for (appointmentSnapshot in snapshot.children) { 33 | val appointment = 34 | appointmentSnapshot.getValue(PatientAppointment::class.java) 35 | helperAppointmentList.add(appointment!!) 36 | } 37 | myAppointmentList.postValue(helperAppointmentList as ArrayList?) 38 | } else { 39 | Logger.debugLog("No appointments found for the date: $date") 40 | } 41 | } 42 | 43 | override fun onCancelled(error: DatabaseError) { 44 | Logger.debugLog("Error in getting appointments for the date: $date is: ${error.message}") 45 | } 46 | }) 47 | } 48 | 49 | 50 | fun getUserDetails(sharedPreference: SharedPreferences) { 51 | userLiveData.postValue(sharedPreference.getUserFromSharedPrefs()) 52 | } 53 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/mainFragments/home/appointment_booking/BookingSummaryFragment.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.mainFragments.home.appointment_booking 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Bundle 5 | import androidx.fragment.app.Fragment 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import androidx.navigation.fragment.findNavController 10 | import androidx.navigation.fragment.navArgs 11 | import com.geekymusketeers.medify.databinding.FragmentBookingSummaryBinding 12 | 13 | 14 | class BookingSummaryFragment : Fragment() { 15 | 16 | private lateinit var _binding: FragmentBookingSummaryBinding 17 | private val binding get() = _binding 18 | private val args: BookingSummaryFragmentArgs by navArgs() 19 | 20 | override fun onCreateView( 21 | inflater: LayoutInflater, container: ViewGroup?, 22 | savedInstanceState: Bundle? 23 | ): View { 24 | _binding = FragmentBookingSummaryBinding.inflate(inflater, container, false) 25 | 26 | initView() 27 | 28 | return binding.root 29 | } 30 | 31 | @SuppressLint("SetTextI18n") 32 | private fun initView() { 33 | binding.apply { 34 | summaryDoctorName.text = "Doctor's Name: ${args.summary.doctorName}" 35 | summaryDoctorSpeciality.text = "Speciality: ${args.summary.doctorSpeciality}" 36 | // summaryDoctorEmail.text = "Doctor's Email: ${args.summary.doctorEmail}" 37 | // summaryDoctorPhoneNumber.text = "Doctor's Phone ${args.summary.doctorPhone}" 38 | summaryDate.text = "Appointment Date: ${args.summary.appointmentDate}" 39 | summaryTime.text = "Appointment Time: ${args.summary.appointmentTime}" 40 | btnHome.setOnClickListener { 41 | findNavController().popBackStack() 42 | } 43 | } 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/mainFragments/home/appointment_booking/DoctorDetailsFragment.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.mainFragments.home.appointment_booking 2 | 3 | import android.os.Bundle 4 | import androidx.fragment.app.Fragment 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import androidx.fragment.app.viewModels 9 | import androidx.navigation.fragment.findNavController 10 | import androidx.navigation.fragment.navArgs 11 | import com.geekymusketeers.medify.base.ViewModelFactory 12 | import com.geekymusketeers.medify.databinding.FragmentDoctorDetailsBinding 13 | import com.geekymusketeers.medify.model.User 14 | import com.geekymusketeers.medify.utils.Logger 15 | import com.geekymusketeers.medify.utils.Utils 16 | 17 | 18 | class DoctorDetailsFragment : Fragment() { 19 | 20 | private var _binding: FragmentDoctorDetailsBinding? = null 21 | private val detailsViewModel by viewModels { ViewModelFactory() } 22 | private val binding get() = _binding!! 23 | private val args: DoctorDetailsFragmentArgs by navArgs() 24 | private var doctor: User = User() 25 | 26 | 27 | override fun onCreateView( 28 | inflater: LayoutInflater, container: ViewGroup?, 29 | savedInstanceState: Bundle? 30 | ): View? { 31 | // Inflate the layout for this fragment 32 | _binding = FragmentDoctorDetailsBinding.inflate(inflater, container, false) 33 | 34 | initDoctor() 35 | initViews() 36 | return binding.root 37 | } 38 | 39 | private fun initDoctor() { 40 | val doctorDetails = args.doctorDetails 41 | detailsViewModel.initDoctor(doctorDetails) 42 | } 43 | 44 | private fun initViews() { 45 | binding.run { 46 | doctorName.text = detailsViewModel.getDoctor().Name 47 | doctorSpecialization.text = detailsViewModel.getDoctor().Specialist 48 | Logger.debugLog("Doctor is ${detailsViewModel.getDoctor().Address}") 49 | detailsViewModel.getDoctor().let { 50 | if (it.Address != "null") 51 | doctorAddress.text = it.Address.toString() 52 | } 53 | back.setOnClickListener { 54 | findNavController().popBackStack() 55 | } 56 | bookAppointment.setOnClickListener { 57 | val action = 58 | DoctorDetailsFragmentDirections.actionDoctorDetailsFragmentToAppointmentBookingFragment( 59 | detailsViewModel.getDoctor() 60 | ) 61 | findNavController().navigate(action) 62 | } 63 | emailId.setOnClickListener { 64 | Utils.sendEmailToGmail( 65 | activity = requireActivity(), 66 | subject = "", 67 | body = "", 68 | email = detailsViewModel.getDoctor().Email 69 | ) 70 | } 71 | phoneCall.setOnClickListener { 72 | Utils.makePhoneCall( 73 | activity = requireActivity(), 74 | phone = detailsViewModel.getDoctor().Phone 75 | ) 76 | } 77 | } 78 | Logger.debugLog("Doctor is ${detailsViewModel.getDoctor()}") 79 | } 80 | 81 | 82 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/mainFragments/home/appointment_booking/DoctorDetailsViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.mainFragments.home.appointment_booking 2 | 3 | import android.app.Application 4 | import com.geekymusketeers.medify.base.BaseViewModel 5 | import com.geekymusketeers.medify.model.User 6 | 7 | class DoctorDetailsViewModel(application: Application) : BaseViewModel(application) { 8 | 9 | private var doctor: User = User() 10 | 11 | fun initDoctor(doctorDetails: User) { 12 | doctor = doctorDetails 13 | } 14 | 15 | fun getDoctor(): User { 16 | return doctor 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/mainFragments/settings/SettingsViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.mainFragments.settings 2 | 3 | import android.app.Application 4 | import android.content.SharedPreferences 5 | import androidx.lifecycle.MutableLiveData 6 | import androidx.lifecycle.viewModelScope 7 | import com.geekymusketeers.medify.base.BaseViewModel 8 | import com.geekymusketeers.medify.model.User 9 | import com.geekymusketeers.medify.utils.SharedPrefsExtension.getUserFromSharedPrefs 10 | import kotlinx.coroutines.Dispatchers 11 | import kotlinx.coroutines.launch 12 | 13 | 14 | class SettingsViewModel(application: Application) : BaseViewModel(application) { 15 | 16 | var userLiveData = MutableLiveData() 17 | var allDataDeletedLiveData = MutableLiveData() 18 | 19 | fun getDataFromSharedPreferences(sharedPreferences: SharedPreferences) = 20 | viewModelScope.launch(Dispatchers.IO) { 21 | userLiveData.postValue(sharedPreferences.getUserFromSharedPrefs()) 22 | } 23 | 24 | fun deleteAllDataFromSharedPreferences(sharedPreferences: SharedPreferences) = 25 | viewModelScope.launch(Dispatchers.IO) { 26 | sharedPreferences.edit().clear().apply() 27 | allDataDeletedLiveData.postValue(true) 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/mainFragments/stats/AddStatsDataFragment.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.mainFragments.stats 2 | 3 | import android.content.Context 4 | import android.content.SharedPreferences 5 | import android.os.Bundle 6 | import androidx.fragment.app.Fragment 7 | import android.view.LayoutInflater 8 | import android.view.View 9 | import android.view.ViewGroup 10 | import android.widget.Toast 11 | import androidx.fragment.app.viewModels 12 | import androidx.navigation.fragment.findNavController 13 | import androidx.navigation.fragment.navArgs 14 | import com.geekymusketeers.medify.base.ViewModelFactory 15 | import com.geekymusketeers.medify.databinding.FragmentAddStatsDataBinding 16 | import com.geekymusketeers.medify.utils.Constants 17 | import com.geekymusketeers.medify.utils.Logger 18 | 19 | 20 | class AddStatsDataFragment : Fragment() { 21 | 22 | private var _binding: FragmentAddStatsDataBinding? = null 23 | private val args by navArgs() 24 | private val addStatsDataViewModel by viewModels { ViewModelFactory() } 25 | private lateinit var sharedPreferences: SharedPreferences 26 | private val binding get() = _binding!! 27 | 28 | override fun onCreateView( 29 | inflater: LayoutInflater, container: ViewGroup?, 30 | savedInstanceState: Bundle? 31 | ): View { 32 | // Inflate the layout for this fragment 33 | _binding = FragmentAddStatsDataBinding.inflate(inflater, container, false) 34 | sharedPreferences = requireActivity().getSharedPreferences(Constants.UserData, Context.MODE_PRIVATE) 35 | 36 | initObserver() 37 | initView() 38 | 39 | return binding.root 40 | } 41 | 42 | private fun initObserver() { 43 | addStatsDataViewModel.run { 44 | saveDataFromSharedPreferences(sharedPreferences) 45 | if (args.stats.healthId != null) { 46 | Logger.debugLog("AddStatsDataFragment HealthId: ${args.stats}") 47 | setHealthData(args.stats) 48 | binding.testNameEditText.setEditTextBox(args.stats.name) 49 | } else { 50 | setHealthId() 51 | } 52 | // statsList.observe(viewLifecycleOwner) { 53 | // Toast.makeText(context, "Added new data", Toast.LENGTH_SHORT).show() //Temporary 54 | // } 55 | enableButton.observe(viewLifecycleOwner) { 56 | binding.saveButton.isEnabled = it 57 | binding.saveButton.setButtonEnabled(it) 58 | } 59 | isDataSaved.observe(viewLifecycleOwner) { 60 | if (it) { 61 | Toast.makeText(context, "Data saved", Toast.LENGTH_SHORT).show() 62 | findNavController().navigateUp() 63 | } 64 | } 65 | } 66 | } 67 | 68 | private fun initView() { 69 | binding.run { 70 | testNameEditText.setUserInputListener { 71 | addStatsDataViewModel.setTestName(it) 72 | } 73 | testResultEditText.setUserInputListener { 74 | addStatsDataViewModel.setTestResult(it) 75 | } 76 | saveButton.setOnClickListener { 77 | addStatsDataViewModel.saveDataInFirebase() 78 | } 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/mainFragments/stats/StatisticsFragment.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.mainFragments.stats 2 | 3 | import android.annotation.SuppressLint 4 | import android.app.AlertDialog 5 | import android.content.Context 6 | import android.content.DialogInterface 7 | import android.content.SharedPreferences 8 | import android.os.Bundle 9 | import android.os.Handler 10 | import android.text.InputType 11 | import android.view.LayoutInflater 12 | import android.view.View 13 | import android.view.ViewGroup 14 | import android.widget.EditText 15 | import androidx.core.content.ContextCompat 16 | import androidx.fragment.app.Fragment 17 | import androidx.fragment.app.viewModels 18 | import androidx.navigation.fragment.findNavController 19 | import androidx.recyclerview.widget.LinearLayoutManager 20 | import com.geekymusketeers.medify.R 21 | import com.geekymusketeers.medify.base.ViewModelFactory 22 | import com.geekymusketeers.medify.databinding.FragmentStatisticsBinding 23 | import com.geekymusketeers.medify.model.HealthData 24 | import com.geekymusketeers.medify.ui.adapter.StatsListAdapter 25 | import com.geekymusketeers.medify.utils.Constants 26 | import com.geekymusketeers.medify.utils.Logger 27 | import com.google.firebase.database.DatabaseReference 28 | import com.google.firebase.database.FirebaseDatabase 29 | import java.util.* 30 | import java.util.Collections.max 31 | import java.util.Collections.min 32 | import kotlin.collections.ArrayList 33 | 34 | 35 | class StatisticsFragment : Fragment() { 36 | 37 | private var _binding: FragmentStatisticsBinding? = null 38 | private val binding get() = _binding!! 39 | private lateinit var sharedPreference: SharedPreferences 40 | private val statisticsViewModel by viewModels { ViewModelFactory() } 41 | private lateinit var statsListAdapter: StatsListAdapter 42 | 43 | 44 | override fun onCreateView( 45 | inflater: LayoutInflater, container: ViewGroup?, 46 | savedInstanceState: Bundle? 47 | ): View { 48 | // Inflate the layout for this fragment 49 | _binding = FragmentStatisticsBinding.inflate(inflater, container, false) 50 | sharedPreference = 51 | requireActivity().getSharedPreferences(Constants.UserData, Context.MODE_PRIVATE) 52 | 53 | initObserver() 54 | initView() 55 | 56 | return binding.root 57 | } 58 | 59 | private fun initView() { 60 | binding.run { 61 | fabCircle.setOnClickListener { 62 | val action = StatisticsFragmentDirections.actionStatsToAddStatsDataFragment( 63 | HealthData(null) 64 | ) 65 | findNavController().navigate(action) 66 | } 67 | statsListAdapter = StatsListAdapter { 68 | val action = StatisticsFragmentDirections.actionStatsToAddStatsDataFragment(it) 69 | findNavController().navigate(action) 70 | } 71 | recyclerView.apply { 72 | layoutManager = LinearLayoutManager(requireContext()) 73 | adapter = statsListAdapter 74 | } 75 | } 76 | } 77 | 78 | private fun initObserver() { 79 | statisticsViewModel.run { 80 | getDataFromSharedPreference(sharedPreference) 81 | userLiveData.observe(viewLifecycleOwner) { 82 | setStatsList() 83 | } 84 | statsList.observe(viewLifecycleOwner) { 85 | Logger.debugLog("StatsList from statsFrag: $it") 86 | if (it != null) 87 | statsListAdapter.addItems(it) 88 | } 89 | } 90 | } 91 | 92 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/mainFragments/stats/StatisticsViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.mainFragments.stats 2 | 3 | import android.app.Application 4 | import android.content.SharedPreferences 5 | import androidx.lifecycle.MutableLiveData 6 | import androidx.lifecycle.viewModelScope 7 | import com.geekymusketeers.medify.base.BaseViewModel 8 | import com.geekymusketeers.medify.model.HealthData 9 | import com.geekymusketeers.medify.model.TestResult 10 | import com.geekymusketeers.medify.model.User 11 | import com.geekymusketeers.medify.utils.Constants 12 | import com.geekymusketeers.medify.utils.Logger 13 | import com.geekymusketeers.medify.utils.SharedPrefsExtension.getUserFromSharedPrefs 14 | import com.google.firebase.database.DataSnapshot 15 | import com.google.firebase.database.DatabaseError 16 | import com.google.firebase.database.FirebaseDatabase 17 | import com.google.firebase.database.ValueEventListener 18 | import kotlinx.coroutines.Dispatchers 19 | import kotlinx.coroutines.launch 20 | 21 | 22 | class StatisticsViewModel(application: Application) : BaseViewModel(application) { 23 | 24 | var statsList = MutableLiveData>() 25 | var userLiveData = MutableLiveData() 26 | val errorLiveData = MutableLiveData() 27 | 28 | fun setStatsList() = viewModelScope.launch(Dispatchers.IO) { 29 | val userId = userLiveData.value?.UID 30 | val tempStatsList = mutableListOf() 31 | FirebaseDatabase.getInstance().reference.child(Constants.Users).child(userId!!) 32 | .child(Constants.HealthData).addValueEventListener(object : ValueEventListener { 33 | override fun onDataChange(snapshot: DataSnapshot) { 34 | snapshot.children.forEach { healthDataSnapshot -> 35 | try { 36 | val healthData = healthDataSnapshot.getValue(HealthData::class.java) 37 | val testsList = mutableListOf() 38 | Logger.debugLog("healthData: $healthData") 39 | healthData?.tests?.let { tests -> 40 | testsList.addAll(tests) 41 | } 42 | Logger.debugLog("testsList: $testsList") 43 | healthData?.tests = testsList 44 | tempStatsList.add(healthData!!) 45 | statsList.postValue(tempStatsList) 46 | } catch (e: Exception) { 47 | e.printStackTrace() 48 | Logger.debugLog("Error in StatisticsViewModel: ${e.message}") 49 | errorLiveData.postValue(e.message) 50 | } 51 | } 52 | } 53 | override fun onCancelled(error: DatabaseError) {} 54 | }) 55 | } 56 | 57 | fun getDataFromSharedPreference(sharedPreference: SharedPreferences) { 58 | userLiveData.postValue(sharedPreference.getUserFromSharedPrefs()) 59 | } 60 | 61 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/profile/EditProfileActivity.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.profile 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.content.SharedPreferences 6 | import androidx.appcompat.app.AppCompatActivity 7 | import android.os.Bundle 8 | import android.widget.Toast 9 | import com.geekymusketeers.medify.ui.mainFragments.settings.prescription.AddPrescriptionActivity 10 | import com.geekymusketeers.medify.databinding.ActivityEditProfileBinding 11 | import com.google.firebase.database.DatabaseReference 12 | import com.google.firebase.database.FirebaseDatabase 13 | 14 | class EditProfileActivity : AppCompatActivity() { 15 | 16 | private lateinit var binding: ActivityEditProfileBinding 17 | private lateinit var db : DatabaseReference 18 | private lateinit var sharedPreference : SharedPreferences 19 | 20 | override fun onCreate(savedInstanceState: Bundle?) { 21 | super.onCreate(savedInstanceState) 22 | binding = ActivityEditProfileBinding.inflate(layoutInflater) 23 | setContentView(binding.root) 24 | sharedPreference = baseContext.getSharedPreferences("UserData", Context.MODE_PRIVATE) 25 | 26 | binding.confirm.setOnClickListener { 27 | 28 | val name = binding.editName.text.toString() 29 | val age = binding.editAge.text.toString() 30 | val phoneno = binding.editPhoneNumber.text.toString() 31 | 32 | updateData(name,age,phoneno) 33 | } 34 | binding.updatepres.setOnClickListener { 35 | startActivity(Intent(baseContext, AddPrescriptionActivity::class.java)) 36 | } 37 | } 38 | 39 | private fun updateData(name: String, age: String, phoneno: String) { 40 | 41 | var userID = sharedPreference.getString("uid", "Not found").toString() 42 | db = FirebaseDatabase.getInstance().getReference("Users") 43 | val user = mapOf( 44 | "name" to name, 45 | "age" to age, 46 | "phone" to phoneno 47 | ) 48 | 49 | db.child(userID).updateChildren(user).addOnSuccessListener { 50 | 51 | binding.editName.text.clear() 52 | binding.editAge.text.clear() 53 | binding.editPhoneNumber.text.clear() 54 | Toast.makeText(baseContext, "Successfully Updated", Toast.LENGTH_SHORT).show() 55 | }.addOnFailureListener { 56 | Toast.makeText(baseContext, "Failed to update", Toast.LENGTH_SHORT).show() 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/ui/profile/ProfileActivity.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.ui.profile 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.content.SharedPreferences 7 | import androidx.appcompat.app.AppCompatActivity 8 | import android.os.Bundle 9 | import com.geekymusketeers.medify.databinding.ActivityProfileBinding 10 | import com.geekymusketeers.medify.utils.Constants 11 | import com.geekymusketeers.medify.utils.SharedPrefsExtension.getUserFromSharedPrefs 12 | import com.google.firebase.database.* 13 | 14 | class ProfileActivity : AppCompatActivity() { 15 | 16 | private lateinit var binding: ActivityProfileBinding 17 | private lateinit var sharedPreference : SharedPreferences 18 | 19 | 20 | override fun onCreate(savedInstanceState: Bundle?) { 21 | super.onCreate(savedInstanceState) 22 | binding = ActivityProfileBinding.inflate(layoutInflater) 23 | setContentView(binding.root) 24 | sharedPreference = baseContext.getSharedPreferences(Constants.UserData, Context.MODE_PRIVATE) 25 | 26 | getUserData() 27 | 28 | binding.ProfileToEdit.setOnClickListener { 29 | startActivity(Intent(baseContext, EditProfileActivity::class.java)) 30 | } 31 | 32 | } 33 | 34 | @SuppressLint("SetTextI18n") 35 | private fun getUserData() { 36 | val user = sharedPreference.getUserFromSharedPrefs() 37 | binding.name.text = "Name : ${user.Name}" 38 | binding.age.text = "Age : ${user.Age}" 39 | binding.email.text = "Email : ${user.Email}" 40 | binding.phone.text = "Phone Number : ${user.Phone}" 41 | 42 | } 43 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/utils/Constants.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.utils 2 | 3 | 4 | object Constants { 5 | const val HealthData: String = "HealthData" 6 | const val SAVED_USER: String = "saved_user" 7 | const val INVALID_NAME_MESSAGE: String = "Name is Invalid" 8 | const val INVALID_EMAIL_MESSAGE: String = "Email is Invalid" 9 | const val INVALID_PHONE_MESSAGE: String = "Phone number is Invalid" 10 | const val INVALID_PASSWORD_MESSAGE: String = "Password is Invalid" 11 | const val supportEmail: String = "geekymusketeers2024@gmail.com" 12 | const val ratingThreshold: Float = 3.0F 13 | const val dateFormat: String = "dd-MM-yyyy" 14 | const val user: String = "user" 15 | const val password: String = "password" 16 | const val Users: String = "Users" 17 | const val uid: String = "uid" 18 | const val date: String = "date" 19 | const val hide: String = "hide" 20 | const val Prescription: String = "Prescription" 21 | const val Doctor: String = "Doctor" 22 | const val UserData: String = "UserData" 23 | const val DatePicker: String = "DatePicker" 24 | const val KEY_APP_PREFERENCE = "com.humara.nagar.APP_INFO_PREF" 25 | const val USER_PREFERENCE_KEY = "com.humara.nagar.USER_INFO_PREF" 26 | const val PREF_DEFAULT_IN_MEMORY_CACHE_SIZE = 15 27 | const val English = "en" 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/utils/DateTimeExtension.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.utils 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Build 5 | import androidx.annotation.RequiresApi 6 | import java.text.SimpleDateFormat 7 | import java.time.Instant 8 | import java.time.LocalDate 9 | import java.time.LocalDateTime 10 | import java.time.Period 11 | import java.time.ZoneId 12 | import java.time.format.DateTimeFormatter 13 | import java.util.Date 14 | import java.util.Locale 15 | 16 | object DateTimeExtension { 17 | 18 | @RequiresApi(Build.VERSION_CODES.O) 19 | fun getCurrentDateAsString(): String { 20 | return SimpleDateFormat(Constants.dateFormat, Locale.getDefault()).format(Date()) 21 | } 22 | 23 | @SuppressLint("SimpleDateFormat") 24 | @RequiresApi(Build.VERSION_CODES.O) 25 | fun getCurrentDate(): Date? { 26 | val currentDateTime = LocalDateTime.now() 27 | val format = SimpleDateFormat(Constants.dateFormat) 28 | val formatter = DateTimeFormatter.ofPattern(Constants.dateFormat) 29 | val formattedDateTime = currentDateTime.format(formatter) 30 | return format.parse(formattedDateTime) 31 | } 32 | 33 | @RequiresApi(Build.VERSION_CODES.O) 34 | fun calculateAge(dateOfBirth: LocalDate): Int { 35 | val period = Period.between(dateOfBirth, LocalDate.now()) 36 | return period.years 37 | } 38 | 39 | @RequiresApi(Build.VERSION_CODES.O) 40 | fun convertDateToLocalDate(date: Date): LocalDate { 41 | val instant: Instant = date.toInstant() 42 | val zoneId: ZoneId = ZoneId.systemDefault() 43 | val zonedDateTime = instant.atZone(zoneId) 44 | return zonedDateTime.toLocalDate() 45 | } 46 | 47 | @RequiresApi(Build.VERSION_CODES.O) 48 | fun String.convertTimestampToDateTime(): String { 49 | val timestampLong = this.toLongOrNull() ?: return "" // Return empty string if parsing fails 50 | val instant = Instant.ofEpochMilli(timestampLong) 51 | val dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()) 52 | val formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm", Locale.getDefault()) 53 | return dateTime.format(formatter) 54 | } 55 | 56 | fun getTimeStamp(): String { 57 | return System.currentTimeMillis().toString() 58 | } 59 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/utils/DialogUtil.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.utils 2 | 3 | import android.app.Activity 4 | import android.content.Context 5 | import android.view.View 6 | import com.geekymusketeers.medify.R 7 | import com.google.android.material.bottomsheet.BottomSheetBehavior 8 | import com.google.android.material.bottomsheet.BottomSheetDialog 9 | 10 | 11 | object DialogUtil { 12 | 13 | fun Context.createBottomSheet(): BottomSheetDialog { 14 | return BottomSheetDialog(this, R.style.BottomSheetDialogTheme) 15 | } 16 | 17 | fun Activity.createBottomSheet(): BottomSheetDialog { 18 | return BottomSheetDialog(this, R.style.BottomSheetDialogTheme) 19 | } 20 | 21 | fun View.setBottomSheet(bottomSheet: BottomSheetDialog) { 22 | bottomSheet.behavior.state = BottomSheetBehavior.STATE_EXPANDED 23 | bottomSheet.setContentView(this) 24 | bottomSheet.create() 25 | bottomSheet.show() 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/utils/Logger.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.utils 2 | 3 | import android.util.Log 4 | import com.geekymusketeers.medify.BuildConfig 5 | 6 | 7 | object Logger { 8 | 9 | fun errorLog(value: String) { 10 | Log.e("", value) 11 | } 12 | 13 | fun debugLog(value: String) { 14 | Log.d("", value) 15 | } 16 | 17 | fun debugLog(tag: String?, msg: String?) { 18 | if (BuildConfig.DEBUG) { 19 | Log.d(tag, msg!!) 20 | } 21 | } 22 | 23 | fun logException(tag: String, exception: Exception, logLevel: LogLevel, logToCrashlytics : Boolean = false) { 24 | when (logLevel) { 25 | LogLevel.DEBUG -> Log.d(tag, null, exception) 26 | LogLevel.ERROR -> Log.e(tag, null, exception) 27 | LogLevel.INFO -> Log.i(tag, null, exception) 28 | LogLevel.VERBOSE -> Log.v(tag, null, exception) 29 | LogLevel.WARN -> Log.w(tag, null, exception) 30 | } 31 | if (logToCrashlytics) { 32 | //TODO: send log to crashlytics like Firebase 33 | } 34 | } 35 | 36 | enum class LogLevel { 37 | DEBUG, ERROR, INFO, VERBOSE, WARN 38 | } 39 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/utils/RemoveCountryCode.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.utils 2 | 3 | object RemoveCountryCode { 4 | fun remove(number: String) : String { 5 | val numLength = number.length 6 | return if (numLength > 10) { 7 | val startIndex: Int = numLength - 10 8 | val newNumber: String = number.substring(startIndex, numLength) 9 | newNumber 10 | } else if (numLength < 10) { 11 | "" 12 | } else { 13 | number 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/utils/SharedPrefsExtension.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.utils 2 | 3 | import android.content.SharedPreferences 4 | import androidx.core.content.edit 5 | import com.geekymusketeers.medify.model.User 6 | import com.google.gson.Gson 7 | 8 | 9 | object SharedPrefsExtension { 10 | fun SharedPreferences.getUserFromSharedPrefs() : User { 11 | val userFromSharedPreferencesAsGson = 12 | this.getString(Constants.SAVED_USER, null) 13 | val gson = Gson() 14 | return gson.fromJson(userFromSharedPreferencesAsGson, User::class.java) as User 15 | } 16 | 17 | fun SharedPreferences.saveUserToSharedPrefs(user: User) { 18 | val gson = Gson() 19 | val json = gson.toJson(user) 20 | this.edit().putString(Constants.SAVED_USER, json).apply() 21 | } 22 | 23 | inline fun SharedPreferences.put(key: String, value: T) { 24 | edit() { 25 | when (value) { 26 | is Boolean -> putBoolean(key, value) 27 | is Float -> putFloat(key, value) 28 | is Int -> putInt(key, value) 29 | is Long -> putLong(key, value) 30 | is String -> putString(key, value) 31 | else -> { 32 | throw UnsupportedOperationException("SharedPreferences put() not support ${T::class.qualifiedName.toString()} type of data.") 33 | } 34 | } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/utils/StringExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.utils 2 | 3 | 4 | object StringExtensions { 5 | 6 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/utils/shared_preference/AppPreference.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.utils.shared_preference 2 | 3 | import android.content.Context 4 | import com.geekymusketeers.medify.utils.Constants 5 | import com.geekymusketeers.medify.utils.shared_preference.SharedPreferenceKeys 6 | import java.util.Locale 7 | 8 | /** 9 | * Shared preference class for app related data 10 | */ 11 | class AppPreference(context: Context) : SharedPreference(context, Constants.KEY_APP_PREFERENCE) { 12 | companion object { 13 | //Keys which needs to be stored even after user logs out 14 | private val reservedKeys = HashSet() 15 | } 16 | 17 | init { 18 | reservedKeys.add(SharedPreferenceKeys.AppPreferenceKeys.APP_LANGUAGE) 19 | } 20 | 21 | inline var appLanguage: String 22 | get() = getString(SharedPreferenceKeys.AppPreferenceKeys.APP_LANGUAGE, Constants.English)!! 23 | set(value) = putString(SharedPreferenceKeys.AppPreferenceKeys.APP_LANGUAGE, value) 24 | 25 | @Suppress("ApplySharedPref") 26 | fun logOut(hardLogout: Boolean = false) { 27 | val editor = getPreference().edit() 28 | if (hardLogout) { 29 | editor.clear() 30 | } else { 31 | for (key in getPreference().all.keys) { 32 | if (!reservedKeys.contains(key)) 33 | editor.remove(key) 34 | } 35 | } 36 | editor.commit() 37 | } 38 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/utils/shared_preference/IPreferences.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.utils.shared_preference 2 | 3 | import android.content.SharedPreferences 4 | import com.google.gson.Gson 5 | 6 | interface IPreferences { 7 | fun clearLocalCacheData(key: String? = null) 8 | 9 | fun getString(key: String, defaultValue: String?): String? 10 | 11 | fun putString(key: String, value: String?) 12 | 13 | fun getInt(key: String, defaultValue: Int): Int 14 | 15 | fun putInt(key: String, value: Int?) 16 | 17 | fun getLong(key: String, defaultValue: Long): Long 18 | 19 | fun putLong(key: String, value: Long?) 20 | 21 | fun getFloat(key: String, defaultValue: Float): Float 22 | 23 | fun putFloat(key: String, value: Float?) 24 | 25 | fun getBoolean(key: String, defaultValue: Boolean): Boolean 26 | 27 | fun putBoolean(key: String, value: Boolean?) 28 | 29 | fun remove(key: String) { 30 | clearLocalCacheData(key) 31 | getPreference().edit().remove(key).apply() 32 | } 33 | 34 | fun containsKey(key: String): Boolean { 35 | return getPreference().contains(key) 36 | } 37 | 38 | fun clearAll(): Boolean { 39 | clearLocalCacheData() 40 | return getPreference().edit().clear().commit() 41 | } 42 | 43 | fun putObject(key: String, value: Any?) { 44 | if (value == null) 45 | remove(key) 46 | else 47 | putString(key, getGsonParser().toJson(value)) 48 | } 49 | 50 | fun getObject(key: String, clazz: Class): T? { 51 | val data = getString(key, null) 52 | data?.let { 53 | return getGsonParser().fromJson(it, clazz) 54 | } ?: run { 55 | return null 56 | } 57 | } 58 | 59 | fun getPreference(): SharedPreferences 60 | 61 | fun getGsonParser(): Gson 62 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/utils/shared_preference/SharedPreference.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.utils.shared_preference 2 | 3 | import android.content.Context 4 | import android.content.SharedPreferences 5 | import com.geekymusketeers.medify.utils.Logger 6 | import com.geekymusketeers.medify.utils.SharedPrefsExtension.put 7 | import com.google.gson.Gson 8 | 9 | open class SharedPreference(context: Context, preferenceName: String) : IPreferences { 10 | private val gson = Gson() 11 | 12 | private val sharedPreferences: SharedPreferences = context.getSharedPreferences( 13 | preferenceName, Context.MODE_PRIVATE 14 | ) 15 | 16 | override fun getString(key: String, defaultValue: String?): String? { 17 | return sharedPreferences.getString(key, defaultValue) 18 | } 19 | 20 | override fun putString(key: String, value: String?) = putValue(key, value) 21 | 22 | override fun getInt(key: String, defaultValue: Int): Int { 23 | return sharedPreferences.getInt(key, defaultValue) 24 | } 25 | 26 | override fun putInt(key: String, value: Int?) = putValue(key, value) 27 | 28 | override fun getLong(key: String, defaultValue: Long): Long { 29 | return sharedPreferences.getLong(key, defaultValue) 30 | } 31 | 32 | override fun putLong(key: String, value: Long?) = putValue(key, value) 33 | 34 | override fun getFloat(key: String, defaultValue: Float): Float { 35 | return sharedPreferences.getFloat(key, defaultValue) 36 | } 37 | 38 | override fun putFloat(key: String, value: Float?) = putValue(key, value) 39 | 40 | override fun getBoolean(key: String, defaultValue: Boolean): Boolean { 41 | return sharedPreferences.getBoolean(key, defaultValue) 42 | } 43 | 44 | override fun putBoolean(key: String, value: Boolean?) = putValue(key, value) 45 | 46 | /** 47 | * Generic function to put the value in SharedPreferences and the Cache. 48 | */ 49 | private inline fun putValue(key: String, value: T?) { 50 | if (value == null) 51 | remove(key) 52 | else { 53 | try { 54 | sharedPreferences.put(key, value) 55 | } catch (e: UnsupportedOperationException) { 56 | Logger.logException(TAG, e, Logger.LogLevel.ERROR, true) 57 | } 58 | } 59 | } 60 | 61 | override fun getPreference() = sharedPreferences 62 | 63 | override fun getGsonParser() = gson 64 | 65 | override fun clearLocalCacheData(key: String?) { 66 | //NA 67 | } 68 | 69 | companion object { 70 | private const val TAG = "SharedPreference" 71 | } 72 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/utils/shared_preference/SharedPreferenceKeys.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.utils.shared_preference 2 | 3 | 4 | /** 5 | * class containing @see[AppPreference] and @see[UserPreference] keys 6 | */ 7 | interface SharedPreferenceKeys { 8 | 9 | /** 10 | * Preference keys holds user session related data 11 | */ 12 | interface UserPreferenceKeys { 13 | companion object { 14 | const val MOBILE_NUMBER = "MOBILE_NUMBER" 15 | const val USER_PROFILE = "USER_PROFILE" 16 | const val HISTORY_TOOLTIP_COUNTER = "HISTORY_TOOLTIP_COUNTER" 17 | const val ADMIN_USER = "ADMIN_USER" 18 | } 19 | } 20 | 21 | /** 22 | * Preference keys holding app related data 23 | */ 24 | interface AppPreferenceKeys { 25 | companion object { 26 | const val APP_LANGUAGE = "APP_LANGUAGE" 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /app/src/main/java/com/geekymusketeers/medify/utils/shared_preference/UserPreference.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify.utils.shared_preference 2 | 3 | import android.content.Context 4 | import com.geekymusketeers.medify.model.User 5 | import com.geekymusketeers.medify.utils.Constants 6 | 7 | /** 8 | * encrypted shared preference class for user-session related data 9 | */ 10 | class UserPreference(context: Context) : EncryptedSharedPreference(context, Constants.USER_PREFERENCE_KEY) { 11 | // The inline modifier can be used on accessors of properties that don't have backing fields 12 | inline var mobileNumber: String 13 | get() = getString(SharedPreferenceKeys.UserPreferenceKeys.MOBILE_NUMBER, "") ?: "" 14 | set(value) = putString(SharedPreferenceKeys.UserPreferenceKeys.MOBILE_NUMBER, value) 15 | 16 | inline var userProfile: User? 17 | get() = getObject(SharedPreferenceKeys.UserPreferenceKeys.USER_PROFILE, User::class.java) 18 | set(value) = putObject(SharedPreferenceKeys.UserPreferenceKeys.USER_PROFILE, value) 19 | 20 | inline var historyToolTipCounter: Int 21 | get() = getInt(SharedPreferenceKeys.UserPreferenceKeys.HISTORY_TOOLTIP_COUNTER, 0) 22 | set(value) = putInt(SharedPreferenceKeys.UserPreferenceKeys.HISTORY_TOOLTIP_COUNTER, value) 23 | 24 | inline var isUserAdmin: Boolean 25 | get() = getBoolean(SharedPreferenceKeys.UserPreferenceKeys.ADMIN_USER, false) 26 | set(value) = putBoolean(SharedPreferenceKeys.UserPreferenceKeys.ADMIN_USER, value) 27 | 28 | inline val isUserLoggedIn: Boolean 29 | get() = false 30 | // get() = (userProfile != null) 31 | } -------------------------------------------------------------------------------- /app/src/main/res/color/chip_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/color/color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/cancel_icon.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/app/src/main/res/drawable-v24/cancel_icon.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/pdf_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/app/src/main/res/drawable-v24/pdf_icon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/profile.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/add.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/app_icon.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | 15 | 18 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/appointment.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 20 | 25 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/arrow_forward.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/back.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/background_gradient.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/banner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bell_reminer.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bottom_nav.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/calendar_month.xml: -------------------------------------------------------------------------------- 1 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/card_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/cardview_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/curve_box_final.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 10 | 12 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/date.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/app/src/main/res/drawable/demo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/demo_doctor.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/doctor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/app/src/main/res/drawable/doctor.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/doctor_front_facing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/app/src/main/res/drawable/doctor_front_facing.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/download.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/drag_handle.xml: -------------------------------------------------------------------------------- 1 | 6 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/drop_down.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/edit.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/edit_profile.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/editfield.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/email.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/fab_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/feedback.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/gradient_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/graph.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/home_icon.xml: -------------------------------------------------------------------------------- 1 | 7 | 13 | 14 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_upload_file_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_close.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_pill.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/info.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/logout.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/mail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/app/src/main/res/drawable/mail.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/medify_logo.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | 15 | 18 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/modal_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/more.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/need_help.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/negative_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/normal_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/pass_hide.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 16 | 23 | 30 | 37 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/pass_show.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 16 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/app/src/main/res/drawable/phone.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/primary_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ripple_black.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/search.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/search_button.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/settings_icon.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_oval.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/sign_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/app/src/main/res/drawable/sign_up.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/star_rate.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/stroked.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/time.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/update.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/upi.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/upi_id.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 16 | 23 | 30 | 37 | 44 | 51 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/upload_prescription.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/visibility.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/visibility_off.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/white_bar.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/font/dm_sans.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/font/dm_sans_bold.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/font/dm_sans_medium.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_forgot_password.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 21 | 22 | 32 | 33 | 34 | 43 | 44 | 52 | 53 | 56 | 57 | 69 | 70 | 71 | 72 | 73 | 74 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 21 | 22 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_splashscreen.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 21 | 22 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/layout/appointment_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 19 | 20 | 32 | 33 | 44 | 45 | 54 | 55 | 63 | 64 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /app/src/main/res/layout/bottomsheet_modal.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 18 | 19 | 24 | 25 | 26 | 35 | 36 | 45 | 46 | 47 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /app/src/main/res/layout/doctor_card_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 20 | 21 | 35 | 36 | 51 | 52 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_patient_queue.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 22 | 23 | 34 | 35 | 36 | 47 | 48 | 57 | 58 | 59 | 68 | 69 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_reminder.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 23 | 24 | 25 | 36 | 37 | 46 | 47 | 48 | 49 | 59 | 60 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 22 | 23 | 34 | 35 | 44 | 45 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_custom_edit_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 17 | 18 | 29 | 30 | 45 | 46 | 47 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_custom_spinner.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 17 | 18 | 29 | 30 | 41 | 42 | 52 | 53 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_dual_text_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_primary_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 28 | 29 | 36 | 37 | 43 | 44 | 45 | 46 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_spinner_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/list_items.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/patient_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 19 | 20 | 30 | 31 | 39 | 40 | 46 | 47 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 72 | 73 | 81 | 82 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /app/src/main/res/layout/rating_modal.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 25 | 26 | 36 | 37 | 53 | 54 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /app/src/main/res/layout/settings_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 22 | 23 | 24 | 30 | 31 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/res/menu/bottom_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 12 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/menu/options.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | #DAD6D6 11 | #656464 12 | #FF3C3C 13 | #B0D6FF 14 | #F9FCFF 15 | #03DAC5 16 | #1DCDFE 17 | #1DBDEA 18 | #7A7A7A 19 | #F5F8FA 20 | #BBE3E1 21 | #3E7E82 22 | #5E979B 23 | #84B9BE 24 | #D6EAE9 25 | #F4FAF9 26 | #00C2B7 27 | #B1B1B1 28 | #206971 29 | #2C909A 30 | #206971 31 | #707070 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/values/font_certs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @array/com_google_android_gms_fonts_certs_dev 5 | @array/com_google_android_gms_fonts_certs_prod 6 | 7 | 8 | 9 | MIIEqDCCA5CgAwIBAgIJANWFuGx90071MA0GCSqGSIb3DQEBBAUAMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAeFw0wODA0MTUyMzM2NTZaFw0zNTA5MDEyMzM2NTZaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBANbOLggKv+IxTdGNs8/TGFy0PTP6DHThvbbR24kT9ixcOd9W+EaBPWW+wPPKQmsHxajtWjmQwWfna8mZuSeJS48LIgAZlKkpFeVyxW0qMBujb8X8ETrWy550NaFtI6t9+u7hZeTfHwqNvacKhp1RbE6dBRGWynwMVX8XW8N1+UjFaq6GCJukT4qmpN2afb8sCjUigq0GuMwYXrFVee74bQgLHWGJwPmvmLHC69EH6kWr22ijx4OKXlSIx2xT1AsSHee70w5iDBiK4aph27yH3TxkXy9V89TDdexAcKk/cVHYNnDBapcavl7y0RiQ4biu8ymM8Ga/nmzhRKya6G0cGw8CAQOjgfwwgfkwHQYDVR0OBBYEFI0cxb6VTEM8YYY6FbBMvAPyT+CyMIHJBgNVHSMEgcEwgb6AFI0cxb6VTEM8YYY6FbBMvAPyT+CyoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJANWFuGx90071MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADggEBABnTDPEF+3iSP0wNfdIjIz1AlnrPzgAIHVvXxunW7SBrDhEglQZBbKJEk5kT0mtKoOD1JMrSu1xuTKEBahWRbqHsXclaXjoBADb0kkjVEJu/Lh5hgYZnOjvlba8Ld7HCKePCVePoTJBdI4fvugnL8TsgK05aIskyY0hKI9L8KfqfGTl1lzOv2KoWD0KWwtAWPoGChZxmQ+nBli+gwYMzM1vAkP+aayLe0a1EQimlOalO762r0GXO0ks+UeXde2Z4e+8S/pf7pITEI/tP+MxJTALw9QUWEv9lKTk+jkbqxbsh8nfBUapfKqYn0eidpwq2AzVp3juYl7//fKnaPhJD9gs= 10 | 11 | 12 | 13 | 14 | MIIEQzCCAyugAwIBAgIJAMLgh0ZkSjCNMA0GCSqGSIb3DQEBBAUAMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDAeFw0wODA4MjEyMzEzMzRaFw0zNjAxMDcyMzEzMzRaMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAKtWLgDYO6IIrgqWbxJOKdoR8qtW0I9Y4sypEwPpt1TTcvZApxsdyxMJZ2JORland2qSGT2y5b+3JKkedxiLDmpHpDsz2WCbdxgxRczfey5YZnTJ4VZbH0xqWVW/8lGmPav5xVwnIiJS6HXk+BVKZF+JcWjAsb/GEuq/eFdpuzSqeYTcfi6idkyugwfYwXFU1+5fZKUaRKYCwkkFQVfcAs1fXA5V+++FGfvjJ/CxURaSxaBvGdGDhfXE28LWuT9ozCl5xw4Yq5OGazvV24mZVSoOO0yZ31j7kYvtwYK6NeADwbSxDdJEqO4k//0zOHKrUiGYXtqw/A0LFFtqoZKFjnkCAQOjgdkwgdYwHQYDVR0OBBYEFMd9jMIhF1Ylmn/Tgt9r45jk14alMIGmBgNVHSMEgZ4wgZuAFMd9jMIhF1Ylmn/Tgt9r45jk14aloXikdjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLR29vZ2xlIEluYy4xEDAOBgNVBAsTB0FuZHJvaWQxEDAOBgNVBAMTB0FuZHJvaWSCCQDC4IdGZEowjTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4IBAQBt0lLO74UwLDYKqs6Tm8/yzKkEu116FmH4rkaymUIE0P9KaMftGlMexFlaYjzmB2OxZyl6euNXEsQH8gjwyxCUKRJNexBiGcCEyj6z+a1fuHHvkiaai+KL8W1EyNmgjmyy8AW7P+LLlkR+ho5zEHatRbM/YAnqGcFh5iZBqpknHf1SKMXFh4dd239FJ1jWYfbMDMy3NS5CTMQ2XFI1MvcyUTdZPErjQfTbQe3aDQsQcafEQPD+nqActifKZ0Np0IS9L9kR/wbNvyz6ENwPiTrjV2KRkEjH78ZMcUQXg0L3BYHJ3lc69Vs5Ddf9uUGGMYldX3WfMBEmh/9iFBDAaTCK 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/values/integers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2000 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/preloaded_fonts.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @font/dm_sans 5 | @font/dm_sans_bold 6 | @font/dm_sans_medium 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/view_tags.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /app/src/test/java/com/geekymusketeers/medify/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/test/java/com/geekymusketeers/medify/RemoveCountryCodeTest.kt: -------------------------------------------------------------------------------- 1 | package com.geekymusketeers.medify 2 | 3 | import com.geekymusketeers.medify.utils.RemoveCountryCode 4 | import org.junit.Assert.* 5 | import org.junit.Test 6 | 7 | 8 | class RemoveCountryCodeTest { 9 | 10 | @Test 11 | fun `phone number length is less than 10` () { 12 | val phone = "123456789" 13 | val result = RemoveCountryCode.remove(phone) 14 | assertEquals("", result) 15 | } 16 | 17 | @Test 18 | fun `phone number length is more than 10` () { 19 | val phone = "012345678910" 20 | val result = RemoveCountryCode.remove(phone) 21 | assertEquals("2345678910", result) 22 | } 23 | 24 | @Test 25 | fun `phone number length is exactly 10` () { 26 | val phone = "0123456789" 27 | val result = RemoveCountryCode.remove(phone) 28 | assertEquals("0123456789", result) 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | repositories { 4 | // Check that you have the following line (if not, add it): 5 | google() // Google's Maven repository 6 | } 7 | dependencies { 8 | // Add this line 9 | classpath 'com.google.gms:google-services:4.3.13' 10 | // classpath 'com.google.dagger:hilt-android-gradle-plugin:2.30.1-alpha' 11 | classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.5.3") 12 | } 13 | } 14 | 15 | 16 | plugins { 17 | id 'com.android.application' version '7.4.0' apply false 18 | id 'com.android.library' version '7.4.0' apply false 19 | id 'org.jetbrains.kotlin.android' version '1.8.10' apply false 20 | } 21 | 22 | task clean(type: Delete) { 23 | delete rootProject.buildDir 24 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Kotlin code style for this project: "official" or "obsolete": 19 | kotlin.code.style=official 20 | # Enables namespacing of each library's R class so that its R class includes only the 21 | # resources declared in the library itself and none from the library's dependencies, 22 | # thereby reducing the size of the R class for that library 23 | android.nonTransitiveRClass=true 24 | #android.enableJetifier=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheMedifyApp/Medify/968fa0a29540bdbaa5c42e3098bdd0b56545d78b/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat May 13 00:56:51 IST 2023 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | google() 5 | mavenCentral() 6 | maven { url 'https://jitpack.io' } 7 | } 8 | } 9 | dependencyResolutionManagement { 10 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 11 | repositories { 12 | google() 13 | mavenCentral() 14 | maven { url 'https://jitpack.io' } 15 | } 16 | } 17 | rootProject.name = "Medify" 18 | include ':app' 19 | --------------------------------------------------------------------------------