├── .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 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
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 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/options.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------