diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..aa724b7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,15 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+local.properties
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..27bdd2f
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+MVVMDemoWithDI
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..fb7f4a8
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..526b4c2
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..e6a8b91
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c26d7b5
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+# Doctor-Care-App
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..3de5d21
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,100 @@
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+ id 'dagger.hilt.android.plugin'
+ id 'kotlin-kapt'
+ id 'com.google.gms.google-services'
+}
+
+android {
+ compileSdk 31
+
+ defaultConfig {
+ applicationId "com.ketub4.mvvmdemowithdi"
+ minSdk 21
+ targetSdk 31
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+ buildFeatures {
+ viewBinding true
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+
+ }
+
+}
+
+dependencies {
+
+ implementation 'androidx.core:core-ktx:1.7.0'
+ implementation 'androidx.appcompat:appcompat:1.4.1'
+ implementation 'com.google.android.material:material:1.5.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
+ implementation 'com.google.firebase:firebase-firestore-ktx:24.0.1'
+// implementation 'com.firebaseui:firebase-ui-storage:7.2.0'
+// implementation 'com.google.firebase:firebase-storage-ktx'
+ implementation 'androidx.legacy:legacy-support-v4:1.0.0'
+ testImplementation 'junit:junit:4.+'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+
+ implementation("com.google.dagger:hilt-android:2.38.1")
+ kapt("com.google.dagger:hilt-android-compiler:2.38.1")
+
+
+ def lifecycle_version = "2.3.1"
+ def retorfit_version = '2.9.0'
+
+ //coroutines
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9")
+ // ViewModel
+ implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version")
+ // LiveData
+ implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version")
+ // Saved state module for ViewModel
+ implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version")
+ // Annotation processor
+ kapt("androidx.lifecycle:lifecycle-compiler:$lifecycle_version")
+ // alternately - if using Java8, use the following instead of lifecycle-compiler
+ implementation("androidx.lifecycle:lifecycle-common-java8:$lifecycle_version")
+ implementation("androidx.activity:activity-ktx:1.2.3")
+ //glide
+ implementation 'com.github.bumptech.glide:glide:4.12.0'
+ annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
+
+ //retrofit
+ implementation "com.squareup.retrofit2:retrofit:$retorfit_version"
+ implementation "com.squareup.retrofit2:converter-gson:$retorfit_version"
+
+
+ implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
+ implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
+
+ implementation 'com.synnapps:carouselview:0.1.5'
+
+ implementation 'de.hdodenhof:circleimageview:3.1.0'
+
+ implementation("androidx.viewpager2:viewpager2:1.0.0")
+
+ implementation 'com.google.code.gson:gson:2.9.0'
+
+
+}
+kapt {
+ correctErrorTypes = true
+
+}
\ No newline at end of file
diff --git a/app/google-services.json b/app/google-services.json
new file mode 100644
index 0000000..77801cc
--- /dev/null
+++ b/app/google-services.json
@@ -0,0 +1,39 @@
+{
+ "project_info": {
+ "project_number": "546168156556",
+ "project_id": "mvvmdemowithdi",
+ "storage_bucket": "mvvmdemowithdi.appspot.com"
+ },
+ "client": [
+ {
+ "client_info": {
+ "mobilesdk_app_id": "1:546168156556:android:753224458e6d62c31066a9",
+ "android_client_info": {
+ "package_name": "com.ketub4.mvvmdemowithdi"
+ }
+ },
+ "oauth_client": [
+ {
+ "client_id": "546168156556-svdf9jakr5235qagvfuc8dli8en8s6bn.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ],
+ "api_key": [
+ {
+ "current_key": "AIzaSyB4pEVksO097Lvl4FtEusECeQFIwkOVeVM"
+ }
+ ],
+ "services": {
+ "appinvite_service": {
+ "other_platform_oauth_client": [
+ {
+ "client_id": "546168156556-svdf9jakr5235qagvfuc8dli8en8s6bn.apps.googleusercontent.com",
+ "client_type": 3
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "configuration_version": "1"
+}
\ No newline at end of file
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/app/src/androidTest/java/com/ketub4/mvvmdemowithdi/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/ketub4/mvvmdemowithdi/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..7c82420
--- /dev/null
+++ b/app/src/androidTest/java/com/ketub4/mvvmdemowithdi/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package com.ketub4.mvvmdemowithdi
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.ketub4.mvvmdemowithdi", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..06f9234
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/activities/AppointmentDetailsActivity.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/activities/AppointmentDetailsActivity.kt
new file mode 100644
index 0000000..9645eb0
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/activities/AppointmentDetailsActivity.kt
@@ -0,0 +1,161 @@
+package com.ketub4.mvvmdemowithdi.activities
+
+import android.content.Intent
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import android.view.View
+import android.view.WindowManager
+import android.widget.Toast
+import com.google.gson.Gson
+import com.ketub4.mvvmdemowithdi.R
+import com.ketub4.mvvmdemowithdi.databinding.ActivityAppointmentDetailsBinding
+import com.ketub4.mvvmdemowithdi.model.Doctors
+import java.util.regex.Matcher
+import java.util.regex.Pattern
+
+
+class AppointmentDetailsActivity : AppCompatActivity() {
+ private var _binding: ActivityAppointmentDetailsBinding? = null
+ private val binding: ActivityAppointmentDetailsBinding get() = _binding!!
+ private val VALID_EMAIL_ADDRESS_REGEX: Pattern =
+ Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE)
+ private val gson = Gson()
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ _binding = ActivityAppointmentDetailsBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
+ binding.appBar.toolbarTitle.text = "Personal Details"
+
+ _binding?.appBar?.back?.setOnClickListener {
+ finish()
+ }
+ _binding?.appBar?.rightIcon?.visibility = View.INVISIBLE
+
+ val doctorObjString = intent.extras?.get("doctorObj").toString()
+ if (doctorObjString.isNotEmpty()){
+ setupDoctorDetails(doctorObjString)
+ }
+
+ binding.DoneBtn.setOnClickListener {
+ if (validateInputs()){
+ val intent = Intent(this@AppointmentDetailsActivity, SuccessfulActivity::class.java)
+ startActivity(intent)
+ }
+ }
+
+
+ }
+
+ private fun setupDoctorDetails(doctorData:String){
+ val doctor = gson.fromJson(doctorData, Doctors::class.java)
+ _binding?.doctorDetails?.apply {
+ doctorName.text = doctor.name
+ categoryName.text = doctor.category
+ distance.text = "Distance: "+doctor.distance
+ address.text = doctor.address
+ categoryImage.setImageResource(this@AppointmentDetailsActivity.resources.getIdentifier(
+ getImageName(doctor.name), "drawable", "com.ketub4.mvvmdemowithdi"));
+ setRatingView(doctor.rating)
+ }
+ }
+
+ fun validateInputs():Boolean{
+ if (binding.name.text.isEmpty()){
+ binding.name.error = "Enter your Name"
+ // Toast.makeText(this, "Enter Your Name", Toast.LENGTH_SHORT).show()
+ return false
+ }
+
+ if (binding.mobile.text.isEmpty()){
+ binding.mobile.error = "Enter Your Phone Number"
+ //Toast.makeText(this, "Enter Your Phone Number", Toast.LENGTH_SHORT).show()
+ return false
+ }else if (binding.mobile.text.length != 10){
+ binding.mobile.error = "Enter Your 10 Digit Phone Number"
+ //Toast.makeText(this, "Enter Your 10 Digit Phone Number", Toast.LENGTH_SHORT).show()
+ return false
+ }
+ if (binding.email.text.isEmpty()){
+ binding.email.error = "Enter Your Email Id"
+ //Toast.makeText(this, "Enter Your Email Id", Toast.LENGTH_SHORT).show()
+ return false
+ }else if (!validateEmail(binding.email.text.toString())){
+ binding.email.error = "Enter Valid Email Id"
+ //Toast.makeText(this, "Enter Valid Email Id", Toast.LENGTH_SHORT).show()
+ return false
+ }
+ if (binding.comments.text.isEmpty()){
+ binding.comments.error = "Enter details of the illness"
+ //Toast.makeText(this, "Enter details of the illness", Toast.LENGTH_SHORT).show()
+ return false
+ }
+ return true
+ }
+
+
+
+ fun validateEmail(emailStr: String): Boolean {
+ val matcher: Matcher = VALID_EMAIL_ADDRESS_REGEX.matcher(emailStr)
+ return matcher.find()
+ }
+
+ private fun getImageName(doctorName:String):String{
+ var imageName = "doc_m2" // demo purpose hard coded
+ if (doctorName.contains("Urmila") || doctorName.contains("Varsha") ||doctorName.contains("Vasanti"))
+ {
+ // For demo project this condition is applied. In actual get the profile pic from API.
+ imageName = "doc_f1"
+ }
+
+ return imageName
+ }
+
+ private fun setRatingView(rating: Int) {
+ if (rating==1){
+ _binding?.doctorDetails?.apply {
+ rate1.setImageResource(R.drawable.start_filled)
+ rate2.setImageResource(R.drawable.start)
+ rate3.setImageResource(R.drawable.start)
+ rate4.setImageResource(R.drawable.start)
+ rate5.setImageResource(R.drawable.start)
+ }
+ }
+ if (rating==2){
+ _binding?.doctorDetails?.apply {
+ rate1.setImageResource(R.drawable.start_filled)
+ rate2.setImageResource(R.drawable.start_filled)
+ rate3.setImageResource(R.drawable.start)
+ rate4.setImageResource(R.drawable.start)
+ rate5.setImageResource(R.drawable.start)
+ }
+ }
+ if (rating==3){
+ _binding?.doctorDetails?.apply {
+ rate1.setImageResource(R.drawable.start_filled)
+ rate2.setImageResource(R.drawable.start_filled)
+ rate3.setImageResource(R.drawable.start_filled)
+ rate4.setImageResource(R.drawable.start)
+ rate5.setImageResource(R.drawable.start)
+ }
+ }
+ if (rating==4){
+ _binding?.doctorDetails?.apply {
+ rate1.setImageResource(R.drawable.start_filled)
+ rate2.setImageResource(R.drawable.start_filled)
+ rate3.setImageResource(R.drawable.start_filled)
+ rate4.setImageResource(R.drawable.start_filled)
+ rate5.setImageResource(R.drawable.start)
+ }
+ }
+ if (rating==5){
+ _binding?.doctorDetails?.apply {
+ rate1.setImageResource(R.drawable.start_filled)
+ rate2.setImageResource(R.drawable.start_filled)
+ rate3.setImageResource(R.drawable.start_filled)
+ rate4.setImageResource(R.drawable.start_filled)
+ rate5.setImageResource(R.drawable.start_filled)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/activities/BookAppointmentActivity.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/activities/BookAppointmentActivity.kt
new file mode 100644
index 0000000..7b8c7b2
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/activities/BookAppointmentActivity.kt
@@ -0,0 +1,342 @@
+package com.ketub4.mvvmdemowithdi.activities
+
+import android.content.Intent
+import android.os.Build
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import android.util.Log
+import android.view.View
+import android.widget.Toast
+import androidx.activity.viewModels
+import androidx.annotation.RequiresApi
+import androidx.lifecycle.Observer
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.viewpager.widget.ViewPager
+import androidx.viewpager2.widget.ViewPager2
+import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
+import com.google.gson.Gson
+import com.ketub4.mvvmdemowithdi.R
+import com.ketub4.mvvmdemowithdi.adapter.*
+import com.ketub4.mvvmdemowithdi.databinding.ActivityBookAppointmentBinding
+import com.ketub4.mvvmdemowithdi.fragments.SearchFragment
+import com.ketub4.mvvmdemowithdi.model.Appointment
+import com.ketub4.mvvmdemowithdi.model.Doctors
+import com.ketub4.mvvmdemowithdi.utils.CalendarUtils
+import com.ketub4.mvvmdemowithdi.utils.CalendarUtils.Companion.daysInWeekArray
+import com.ketub4.mvvmdemowithdi.viewModel.CustomViewModel
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import java.time.LocalDate
+
+@AndroidEntryPoint
+class BookAppointmentActivity : AppCompatActivity(), ITimeSlotLitener, IViewPagerListener,
+ ICalendarAdapter {
+ private var _binding: ActivityBookAppointmentBinding? = null
+ private val binding: ActivityBookAppointmentBinding get() = _binding!!
+ private val customViewModel: CustomViewModel by viewModels()
+ private var category_name: String = ""
+ lateinit var appointmentAdapter: AppointmentAdapter
+ lateinit var timeslotList: ArrayList
+ lateinit var viewPager2Adapter: ViewPager2Adapter
+ lateinit var calendarAdapter: CalendarAdapter
+ lateinit var sortedfList: ArrayList
+ private val gson = Gson()
+ private var bookedTimeSlot: String = ""
+ @RequiresApi(Build.VERSION_CODES.O)
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ _binding = ActivityBookAppointmentBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ title = ""
+
+ setSupportActionBar(binding.appBar.toolbar)
+ binding.appBar.toolbarTitle.text = "Book Appointment"
+
+ _binding?.appBar?.back?.setOnClickListener {
+ finish()
+ }
+ _binding?.appBar?.rightIcon?.visibility = View.INVISIBLE
+ val doctorObjString = intent.extras?.get("doctorObj").toString()
+ if (doctorObjString.isNotEmpty()){
+ setupDoctorDetails(doctorObjString)
+ }
+
+ loadTimeSlots("22/02/2022",1, true)//for demo purpose
+
+ binding.viewpager.registerOnPageChangeCallback(object : OnPageChangeCallback() {
+ // This method is triggered when there is any scrolling activity for the current page
+ override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
+ super.onPageScrolled(position, positionOffset, positionOffsetPixels)
+ //Log.i("onPageScrolled","Scrolling="+position)
+ }
+
+ // triggered when you select a new page
+ override fun onPageSelected(position: Int) {
+ super.onPageSelected(position)
+ Log.i("onPageSelected","Scrolling="+position)
+ sortedListData(position)
+
+ }
+
+ // triggered when there is
+ // scroll state will be changed
+ override fun onPageScrollStateChanged(state: Int) {
+ super.onPageScrollStateChanged(state)
+ //Log.i("onPageScrollState","Scrolling="+state)
+ }
+ })
+
+ binding.nextBtn.setOnClickListener {
+ if (bookedTimeSlot.isEmpty()){
+ Toast.makeText(this@BookAppointmentActivity, "Please select the Time.", Toast.LENGTH_SHORT).show()
+ }else{
+ val intent = Intent(this@BookAppointmentActivity, AppointmentDetailsActivity::class.java)
+ intent.putExtra("doctorObj",doctorObjString)
+ startActivity(intent)
+ }
+
+ }
+
+ }
+
+ private fun setupDoctorDetails(doctorData:String){
+ val doctor = gson.fromJson(doctorData, Doctors::class.java)
+ _binding?.calendarView?.doctorDetails?.apply {
+ doctorName.text = doctor.name
+ categoryName.text = doctor.category
+ distance.text = "Distance: "+doctor.distance
+ address.text = doctor.address
+ categoryImage.setImageResource(this@BookAppointmentActivity.resources.getIdentifier(
+ getImageName(doctor.name), "drawable", "com.ketub4.mvvmdemowithdi"));
+ setRatingView(doctor.rating)
+ }
+ }
+ @RequiresApi(Build.VERSION_CODES.O)
+ private fun loadTimeSlots(date: String, doctorId: Int, isFirstTime: Boolean){
+ showHideProgressBar()
+ customViewModel.getTimeSlots(date, doctorId) //For demo this is hard coded.
+
+ GlobalScope.launch(Dispatchers.Main) {
+ if (isFirstTime){
+ setupWeekCalendar()
+ }else{
+ sortedfList.clear()
+ appointmentAdapter.updateTimeSlotList(sortedfList)
+ }
+ delay(2000)
+ customViewModel.timeSlotList.observe(this@BookAppointmentActivity, Observer { list ->
+ Log.i("timeSlotList", "=$list")
+ timeslotList = list
+ if (list.size>0)
+ showHideProgressBar()
+
+ })
+
+ setupPageViewer()
+
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.O)
+ private fun setupWeekCalendar() {
+ Log.i("selectedDate", "selectedDate=" + LocalDate.now())
+ binding.calendarView.monthYearTV.text =
+ CalendarUtils.monthYearFromDate(CalendarUtils.selectedDate)
+ val days: ArrayList = CalendarUtils.daysInWeekArray(CalendarUtils.selectedDate)
+
+
+ calendarAdapter = CalendarAdapter(days, this)
+
+ binding.calendarView.calendarRecyclerView.apply {
+ layoutManager = GridLayoutManager(this@BookAppointmentActivity, 7)
+ hasFixedSize()
+ adapter = calendarAdapter
+ }
+
+ binding.calendarView.previousWeek.setOnClickListener {
+ val oldDate = CalendarUtils.selectedDate.minusWeeks(1)
+ if (oldDate < LocalDate.now()) {
+ Toast.makeText(
+ this@BookAppointmentActivity,
+ "You can not select Previous Week.",
+ Toast.LENGTH_SHORT
+ )
+ .show()
+ } else {
+ CalendarUtils.selectedDate = oldDate
+ setupWeekCalendar()
+ }
+
+
+ }
+ binding.calendarView.nextWeek.setOnClickListener {
+
+ CalendarUtils.selectedDate = CalendarUtils.selectedDate.plusWeeks(1)
+ setupWeekCalendar()
+ }
+ binding.calendarView.calenderIcon.setOnClickListener {
+ val isVisibile = binding.calendarView.calendarMainView.visibility
+ Log.i("isVisibile", "isVisibile=" + isVisibile)
+ if (isVisibile == View.VISIBLE) {
+ binding.calendarView.calendarMainView.visibility = View.GONE
+ } else {
+ binding.calendarView.calendarMainView.visibility = View.VISIBLE
+ }
+ }
+ }
+
+ private fun setupPageViewer() {
+ sortedfList = timeslotList.filter {
+ s->s.timeSlot == "m"
+ } as ArrayList
+ Log.i("morningList="+sortedfList.size,"morningList="+sortedfList.toString())
+ appointmentAdapter = AppointmentAdapter(sortedfList,this, this)
+ viewPager2Adapter =
+ ViewPager2Adapter(this@BookAppointmentActivity, appointmentAdapter,this)
+ binding.viewpager.apply {
+ adapter = viewPager2Adapter
+ }
+ }
+
+ override fun onTimeSlotClicked(appointId: Int, isBooked: Boolean, time: String) {
+ if (isBooked) {
+ Toast.makeText(
+ this@BookAppointmentActivity,
+ "TimeSlot Already Booked.",
+ Toast.LENGTH_SHORT
+ )
+ .show()
+ bookedTimeSlot = ""
+ } else {
+ bookedTimeSlot = time
+ }
+ }
+
+ override fun nextPage() {
+
+ binding.viewpager.currentItem = binding.viewpager.currentItem + 1
+ val currentItem = binding.viewpager.currentItem
+ Log.i("currentItem123","currentItem="+currentItem)
+ sortedListData(currentItem)
+ }
+
+ override fun previousPage() {
+ binding.viewpager.currentItem = binding.viewpager.currentItem - 1
+ val currentItem = binding.viewpager.currentItem
+ Log.i("currentItem","currentItem="+currentItem)
+ sortedListData(currentItem)
+ }
+
+ private fun sortedListData(currentPos:Int){
+ sortedfList.clear()
+ when(currentPos){
+ 0->{
+ sortedfList = timeslotList.filter { s->s.timeSlot == "m" } as ArrayList
+ true
+ }
+ 1->{
+ sortedfList = timeslotList.filter { s->s.timeSlot == "a" } as ArrayList
+ true
+ }
+ 2->{
+ sortedfList = timeslotList.filter { s->s.timeSlot == "e" } as ArrayList
+ true
+ }
+
+ }
+ Log.i("morningList="+sortedfList.size,"morningList="+sortedfList.toString())
+ appointmentAdapter.updateTimeSlotList(sortedfList)
+ }
+
+
+ @RequiresApi(Build.VERSION_CODES.O)
+ override fun onCalendarItemClicked(position: Int, localDate: LocalDate) {
+ if (localDate < LocalDate.now()) {
+ Toast.makeText(
+ this@BookAppointmentActivity,
+ "You can not Select Older dates.",
+ Toast.LENGTH_SHORT
+ ).show()
+ } else {
+ CalendarUtils.selectedDate = localDate
+ setupWeekCalendar()
+
+ loadTimeSlots("22/02/2022",1, false)//for demo same date and doctor id
+ }
+
+ }
+
+ private fun showHideProgressBar() {
+ binding.progressBar
+ if (binding.progressBar.visibility== View.VISIBLE){
+ binding.progressBar.visibility = View.GONE
+ }else{
+ binding.progressBar.visibility = View.VISIBLE
+ }
+
+ }
+
+ private fun getImageName(doctorName:String):String{
+ var imageName = "doc_m2" // demo purpose hard coded
+ if (doctorName.contains("Urmila") || doctorName.contains("Varsha") ||doctorName.contains("Vasanti"))
+ {
+ // For demo project this condition is applied. In actual get the profile pic from API.
+ imageName = "doc_f1"
+ }
+
+ return imageName
+ }
+
+ private fun setRatingView(rating: Int) {
+ if (rating==1){
+ _binding?.calendarView?.doctorDetails?.apply {
+ rate1.setImageResource(R.drawable.start_filled)
+ rate2.setImageResource(R.drawable.start)
+ rate3.setImageResource(R.drawable.start)
+ rate4.setImageResource(R.drawable.start)
+ rate5.setImageResource(R.drawable.start)
+ }
+ }
+ if (rating==2){
+ _binding?.calendarView?.doctorDetails?.apply {
+ rate1.setImageResource(R.drawable.start_filled)
+ rate2.setImageResource(R.drawable.start_filled)
+ rate3.setImageResource(R.drawable.start)
+ rate4.setImageResource(R.drawable.start)
+ rate5.setImageResource(R.drawable.start)
+ }
+ }
+ if (rating==3){
+ _binding?.calendarView?.doctorDetails?.apply {
+ rate1.setImageResource(R.drawable.start_filled)
+ rate2.setImageResource(R.drawable.start_filled)
+ rate3.setImageResource(R.drawable.start_filled)
+ rate4.setImageResource(R.drawable.start)
+ rate5.setImageResource(R.drawable.start)
+ }
+ }
+ if (rating==4){
+ _binding?.calendarView?.doctorDetails?.apply {
+ rate1.setImageResource(R.drawable.start_filled)
+ rate2.setImageResource(R.drawable.start_filled)
+ rate3.setImageResource(R.drawable.start_filled)
+ rate4.setImageResource(R.drawable.start_filled)
+ rate5.setImageResource(R.drawable.start)
+ }
+ }
+ if (rating==5){
+ _binding?.calendarView?.doctorDetails?.apply {
+ rate1.setImageResource(R.drawable.start_filled)
+ rate2.setImageResource(R.drawable.start_filled)
+ rate3.setImageResource(R.drawable.start_filled)
+ rate4.setImageResource(R.drawable.start_filled)
+ rate5.setImageResource(R.drawable.start_filled)
+ }
+ }
+ }
+
+}
+
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/activities/DoctorListActivity.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/activities/DoctorListActivity.kt
new file mode 100644
index 0000000..0a5638e
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/activities/DoctorListActivity.kt
@@ -0,0 +1,94 @@
+package com.ketub4.mvvmdemowithdi.activities
+
+import android.content.Intent
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import android.util.Log
+import android.view.View
+import androidx.activity.viewModels
+import androidx.lifecycle.Observer
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.gson.Gson
+import com.ketub4.mvvmdemowithdi.R
+import com.ketub4.mvvmdemowithdi.adapter.DoctorListAdapter
+import com.ketub4.mvvmdemowithdi.adapter.IDoctorListAdapter
+import com.ketub4.mvvmdemowithdi.databinding.ActivityDoctorListBinding
+import com.ketub4.mvvmdemowithdi.databinding.ActivityMainBinding
+import com.ketub4.mvvmdemowithdi.model.Doctors
+import com.ketub4.mvvmdemowithdi.viewModel.CustomViewModel
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+@AndroidEntryPoint
+class DoctorListActivity : AppCompatActivity(), IDoctorListAdapter {
+ private var _binding: ActivityDoctorListBinding?=null
+ private val binding: ActivityDoctorListBinding get() = _binding!!
+ private val customViewModel: CustomViewModel by viewModels()
+ private var category_id:Int = 0
+ private var category_name: String=""
+ lateinit var doctorListAdapter:DoctorListAdapter
+ lateinit var doctorList: ArrayList
+ private val gson = Gson()
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ _binding = ActivityDoctorListBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ title = ""
+
+ setSupportActionBar(binding.appBarMain.toolbar)
+ supportActionBar?.setDisplayShowHomeEnabled(true)
+ category_id = intent.extras!!.getInt("categoryId")
+ category_name = intent.extras!!.getString("categoryName")!!
+ binding.appBarMain.toolbarTitle.text = category_name+" Doctors List"
+ showHideProgressBar()
+ customViewModel.getDoctorsList(category_id)
+
+ GlobalScope.launch(Dispatchers.Main) {
+ delay(1500)
+ customViewModel.doctorsList.observe(this@DoctorListActivity, Observer { list->
+ Log.i("DoctorList", "=$list")
+ doctorList = list
+ if (list.size>0)
+ showHideProgressBar()
+
+ })
+ setupRV()
+ }
+
+ binding.appBarMain.back.setOnClickListener {
+ this.finish()
+ }
+
+
+
+ }
+
+ private fun setupRV() {
+ doctorListAdapter = DoctorListAdapter(doctorList, this, this@DoctorListActivity)
+ binding.recyclerView.apply {
+ layoutManager = LinearLayoutManager(this@DoctorListActivity)
+ hasFixedSize()
+ adapter = doctorListAdapter
+ }
+
+ }
+
+ override fun onBookBtnClick(doctor: Doctors) {
+ val intent = Intent(this, BookAppointmentActivity::class.java)
+ val objString = gson.toJson(doctor)
+ intent.putExtra("doctorObj",objString)
+ startActivity(intent)
+ }
+
+ private fun showHideProgressBar() {
+ if (_binding!!.proressBar.visibility== View.VISIBLE){
+ _binding!!.proressBar.visibility = View.GONE
+ }else{
+ _binding!!.proressBar.visibility = View.VISIBLE
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/activities/MainActivity.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/activities/MainActivity.kt
new file mode 100644
index 0000000..28dd6f8
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/activities/MainActivity.kt
@@ -0,0 +1,166 @@
+package com.ketub4.mvvmdemowithdi.activities
+
+import android.graphics.Color
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import android.view.View
+import android.view.animation.TranslateAnimation
+import androidx.activity.viewModels
+import androidx.fragment.app.FragmentManager
+import androidx.fragment.app.FragmentTransaction
+import androidx.navigation.NavController
+import androidx.navigation.findNavController
+import androidx.navigation.ui.setupWithNavController
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.android.material.bottomnavigation.BottomNavigationView
+import com.ketub4.mvvmdemowithdi.R
+import com.ketub4.mvvmdemowithdi.adapter.DrawerMenuAdapter
+import com.ketub4.mvvmdemowithdi.adapter.IDrawerMenuAdapter
+import com.ketub4.mvvmdemowithdi.databinding.ActivityMainBinding
+import com.ketub4.mvvmdemowithdi.fragments.SearchFragment
+
+import com.ketub4.mvvmdemowithdi.network.FirebaseService
+import com.ketub4.mvvmdemowithdi.viewModel.CustomViewModel
+import dagger.hilt.android.AndroidEntryPoint
+
+@AndroidEntryPoint
+class MainActivity : AppCompatActivity(), IDrawerMenuAdapter {
+ private var _binding: ActivityMainBinding?=null
+ val binding: ActivityMainBinding get() = _binding!!
+ private val customViewModel: CustomViewModel by viewModels()
+ lateinit var listener: FirebaseService
+ private var drawerOpened: Boolean = false
+ lateinit var drawerMenuAdapter: DrawerMenuAdapter
+ lateinit var navController: NavController
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ _binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ setupNavigation()
+ title=""
+ actionBar?.elevation= 0f
+ setSupportActionBar(binding.mainAppBar.toolbar)
+ binding.mainAppBar.appbarLayout.outlineProvider = null
+ binding.mainAppBar.toolbarTitle.text = "Mumbai"
+
+ binding.mainAppBar.home.setOnClickListener {
+ toggleDrawerNavigation()
+ }
+ binding.mainAppBar.homeSearch.setOnClickListener {
+ navController.navigate(R.id.searchFragment)
+ }
+
+ binding.drawerInnerLayout.backBtn.setOnClickListener {
+ toggleDrawerNavigation()
+ }
+ drawerMenuAdapter = DrawerMenuAdapter(this)
+ binding.menuRV.apply {
+ layoutManager = LinearLayoutManager(this@MainActivity)
+ hasFixedSize()
+ adapter = drawerMenuAdapter
+ }
+
+// binding.menuItem1.setOnClickListener {
+// binding.menuItem1.setBackgroundResource(R.drawable.background_shape_square_blue)
+// binding.menuText1.setTextColor(Color.WHITE)
+// binding.menuImage1.setColorFilter(Color.argb(255, 255, 255, 255));
+// }
+// binding.menuItem2.setOnClickListener {
+// binding.menuItem2.setBackgroundResource(R.drawable.background_shape_square_blue)
+// binding.menuText2.setTextColor(Color.WHITE)
+// binding.menuImage2.setColorFilter(Color.argb(255, 255, 255, 255));
+// }
+
+ // movieViewModel.getMovieData();
+ //movieViewModel.getCategoryList()
+// customViewModel.movieList.observe(this, Observer { list->
+// Log.i("data=","data"+list.size)
+// })
+
+ //movieViewModel.insertRecords()
+ //movieViewModel.insertDoctorData()
+
+// GlobalScope.launch(Dispatchers.Main) {
+// delay(3000)
+// movieViewModel.categoryList.observe(this@MainActivity, Observer { list->
+// Log.i("category=","category"+list.toString())
+// })
+// }
+
+
+
+
+
+ }
+
+
+
+ private fun setupNavigation() {
+ val navView: BottomNavigationView = _binding!!.bottomNavigation
+
+ navController = findNavController(R.id.fragmentContainerView)
+
+ navView.setupWithNavController(navController)
+ }
+
+ private fun toggleDrawerNavigation() {
+ if (!drawerOpened){
+ binding.drawerLayout.visibility = View.VISIBLE
+ val animate = TranslateAnimation(
+ -binding.drawerLayout.width.toFloat(),
+ 0F,
+ 0f,
+ 0F
+ )
+ animate.duration = 500
+ animate.fillAfter = true
+ binding.drawerLayout.startAnimation(animate)
+ binding.menuRV.visibility = View.VISIBLE
+ }else{
+ binding.drawerLayout.visibility = View.GONE
+ val animate = TranslateAnimation(
+ 0F,
+ -binding.drawerLayout.width.toFloat(),
+ 0F,
+ 0F
+ )
+ animate.duration = 500
+ animate.fillAfter = true
+ binding.drawerLayout.startAnimation(animate)
+ binding.menuRV.visibility = View.GONE
+
+ }
+ //binding.drawerLayout.setOnClickListener(null)
+ drawerOpened = !drawerOpened
+ }
+
+ override fun onMenuItemClicked(id:Int) {
+ toggleDrawerNavigation()
+ when(id){
+ 0->{
+ navController.navigate(R.id.homeFragment)
+ true
+ }
+ 1->{
+ navController.navigate(R.id.searchFragment)
+ true
+ }
+ 2->{
+ navController.navigate(R.id.notificationFragment2)
+ true
+ }
+ 3->{
+ navController.navigate(R.id.profileFragment)
+ true
+ }
+ else ->{
+ navController.navigate(R.id.homeFragment)
+ true
+ }
+ }
+
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/activities/SuccessfulActivity.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/activities/SuccessfulActivity.kt
new file mode 100644
index 0000000..f455df0
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/activities/SuccessfulActivity.kt
@@ -0,0 +1,32 @@
+package com.ketub4.mvvmdemowithdi.activities
+
+import android.content.Intent
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import android.view.View
+import com.ketub4.mvvmdemowithdi.databinding.ActivitySuccessfulBinding
+
+class SuccessfulActivity : AppCompatActivity() {
+ private var _binding: ActivitySuccessfulBinding? = null
+ private val binding: ActivitySuccessfulBinding get() = _binding!!
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ _binding = ActivitySuccessfulBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ _binding?.appBar?.toolbarTitle?.text = "Confirmation"
+ _binding?.appBar?.rightIcon?.visibility = View.INVISIBLE
+ _binding?.homeBtn?.setOnClickListener {
+ launchMainActivity()
+ }
+ _binding?.appBar?.back?.setOnClickListener {
+ launchMainActivity()
+ }
+ }
+
+ private fun launchMainActivity(){
+ val intent = Intent(this@SuccessfulActivity, MainActivity::class.java)
+ intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
+ startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/activities/WelcomeActivity.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/activities/WelcomeActivity.kt
new file mode 100644
index 0000000..cad40f6
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/activities/WelcomeActivity.kt
@@ -0,0 +1,23 @@
+package com.ketub4.mvvmdemowithdi.activities
+
+import android.content.Intent
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import com.ketub4.mvvmdemowithdi.databinding.ActivityWelcomeBinding
+import dagger.hilt.android.AndroidEntryPoint
+
+@AndroidEntryPoint
+class WelcomeActivity : AppCompatActivity() {
+ private var _binding: ActivityWelcomeBinding?=null
+ private val binding: ActivityWelcomeBinding get() = _binding!!
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ _binding = ActivityWelcomeBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ binding.proceedBtn.setOnClickListener {
+ val intent = Intent(this@WelcomeActivity, MainActivity::class.java)
+ startActivity(intent)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/AppointmentAdapter.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/AppointmentAdapter.kt
new file mode 100644
index 0000000..2af256a
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/AppointmentAdapter.kt
@@ -0,0 +1,83 @@
+package com.ketub4.mvvmdemowithdi.adapter
+
+import android.content.Context
+import android.graphics.Color
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import com.ketub4.mvvmdemowithdi.R
+import com.ketub4.mvvmdemowithdi.databinding.TimeItemBinding
+import com.ketub4.mvvmdemowithdi.model.Appointment
+
+class AppointmentAdapter(private var appointmentList: ArrayList,
+ private val listener:ITimeSlotLitener,
+ private val context:Context):RecyclerView.Adapter() {
+
+ class AppointmentViewHolder(val binding: TimeItemBinding): RecyclerView.ViewHolder(binding.root)
+
+ private var selectedPosition: Int? = -1
+ private var selectedTime: String = ""
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppointmentViewHolder {
+ return (AppointmentViewHolder(
+ TimeItemBinding.inflate(LayoutInflater.from(parent.context),
+ parent, false)
+ ))
+ }
+
+ override fun onBindViewHolder(holder: AppointmentViewHolder, position: Int) {
+ val appointment = appointmentList[position]
+ holder.binding.apply {
+ appointTime.text = appointment.time
+
+ appointTime.setOnClickListener {
+ if (!appointment.booked){
+ if (selectedPosition == holder.adapterPosition){
+ selectedPosition = RecyclerView.NO_POSITION
+ notifyDataSetChanged()
+ selectedTime = ""
+ listener.onTimeSlotClicked(appointment.id, appointment.booked, selectedTime)
+ return@setOnClickListener
+ }
+ selectedTime = appointment.time
+ selectedPosition = holder.adapterPosition
+ notifyDataSetChanged()
+ listener.onTimeSlotClicked(appointment.id, appointment.booked, selectedTime)
+ }
+ Log.i("selectedTime=","selectedTime="+selectedTime)
+
+ }
+
+ if (selectedPosition==position){
+ appointTime.setBackgroundResource(R.drawable.background_shape_green)
+ appointTime.setTextColor(Color.WHITE)
+
+ }else{
+ appointTime.setBackgroundResource(R.drawable.background_shape_white)
+ appointTime.setTextColor(context.resources.getColor(R.color.basicGreen))
+
+ }
+ Log.i("appointment.isBooked","selectedTime outside="+selectedTime)
+ if (appointment.booked){
+ appointTime.setBackgroundResource(R.drawable.background_shape_gray)
+ appointTime.setTextColor(Color.BLACK)
+ selectedTime = ""
+ }
+
+ }
+ }
+
+ override fun getItemCount(): Int = appointmentList.size
+
+ fun updateTimeSlotList(newList: ArrayList){
+ appointmentList.clear()
+ appointmentList = newList
+ notifyDataSetChanged()
+ }
+
+
+}
+
+interface ITimeSlotLitener{
+ fun onTimeSlotClicked(appointId:Int, isBooked:Boolean, time: String)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/CalendarAdapter.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/CalendarAdapter.kt
new file mode 100644
index 0000000..301f474
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/CalendarAdapter.kt
@@ -0,0 +1,54 @@
+package com.ketub4.mvvmdemowithdi.adapter
+
+import android.graphics.Color
+import android.os.Build
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.annotation.RequiresApi
+import androidx.recyclerview.widget.RecyclerView
+import com.ketub4.mvvmdemowithdi.R
+import com.ketub4.mvvmdemowithdi.databinding.CalendarCellBinding
+import com.ketub4.mvvmdemowithdi.utils.CalendarUtils
+import java.time.LocalDate
+import java.util.ArrayList
+
+class CalendarAdapter(private val days: ArrayList,
+ private val listener:ICalendarAdapter):RecyclerView.Adapter() {
+
+ class CalendarViewHolder(val binding: CalendarCellBinding): RecyclerView.ViewHolder(binding.root)
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CalendarViewHolder {
+ return (CalendarViewHolder(CalendarCellBinding.inflate(
+ LayoutInflater.from(parent.context),
+ parent,
+ false
+ )))
+
+ }
+
+ @RequiresApi(Build.VERSION_CODES.O)
+ override fun onBindViewHolder(holder: CalendarViewHolder, position: Int) {
+ val localDate = days[position]
+ if (localDate== null){
+ holder.binding.cellDayText.text = ""
+ }else{
+ holder.binding.cellDayText.text = localDate.dayOfMonth.toString()
+ if (localDate == CalendarUtils.selectedDate){
+ holder.binding.parentView.setBackgroundResource(R.drawable.background_shape_blue)
+ holder.binding.cellDayText.setTextColor(Color.WHITE)
+ }
+ holder.binding.parentView.setOnClickListener {
+ listener.onCalendarItemClicked(holder.adapterPosition, localDate)
+ }
+ }
+
+ }
+
+ override fun getItemCount() = days.size
+
+
+}
+
+interface ICalendarAdapter{
+ fun onCalendarItemClicked(position: Int, localDate: LocalDate)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/CategoryAdapter.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/CategoryAdapter.kt
new file mode 100644
index 0000000..a1773a5
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/CategoryAdapter.kt
@@ -0,0 +1,52 @@
+package com.ketub4.mvvmdemowithdi
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.ketub4.mvvmdemowithdi.databinding.CateoryItemBinding
+import com.ketub4.mvvmdemowithdi.model.Category
+import java.util.*
+import kotlin.collections.ArrayList
+
+class CategoryAdapter(private val listener: ICategoryListener,
+ private val categoryList: ArrayList,
+ private val context: Context):RecyclerView.Adapter() {
+
+ class CategoryViewHolder(val binding: CateoryItemBinding):RecyclerView.ViewHolder(binding.root)
+
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CategoryViewHolder {
+ return CategoryViewHolder(
+ CateoryItemBinding.inflate(
+ LayoutInflater.from(parent.context),
+ parent,
+ false
+ )
+ )
+ }
+
+ override fun onBindViewHolder(holder: CategoryViewHolder, position: Int) {
+
+ val category = categoryList[position]
+ holder.binding.apply {
+ categoryTitle.text = category.name
+ subCategoryTitle.text = category.description
+ val imageName = "cat_"+category.id
+ categoryImage.setImageResource(context.resources.getIdentifier(
+ imageName, "drawable", "com.ketub4.mvvmdemowithdi"));
+ categoryLayout.setOnClickListener {
+ listener.onCategoryClick(category.id, category.name)
+ }
+
+
+ }
+ }
+
+ override fun getItemCount() = categoryList.size
+}
+
+interface ICategoryListener{
+ fun onCategoryClick(category_id:Int, category_name: String)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/DoctotListAdapter.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/DoctotListAdapter.kt
new file mode 100644
index 0000000..d323579
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/DoctotListAdapter.kt
@@ -0,0 +1,109 @@
+package com.ketub4.mvvmdemowithdi.adapter
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import com.ketub4.mvvmdemowithdi.R
+import com.ketub4.mvvmdemowithdi.databinding.DoctorListItemBinding
+import com.ketub4.mvvmdemowithdi.model.Doctors
+
+class DoctorListAdapter(private val doctorList: ArrayList,
+ private val listener: IDoctorListAdapter,
+ private val context: Context):
+ RecyclerView.Adapter() {
+
+ class DoctorListViewHolder(val binding: DoctorListItemBinding): RecyclerView.ViewHolder(binding.root)
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DoctorListViewHolder {
+ return DoctorListViewHolder(
+ DoctorListItemBinding.inflate(
+ LayoutInflater.from(parent.context),
+ parent,
+ false
+ )
+ )
+ }
+
+ override fun onBindViewHolder(holder: DoctorListViewHolder, position: Int) {
+ val doctor = doctorList[position]
+ holder.binding.apply {
+ categoryName.text = doctor.category
+ doctorName.text = doctor.name
+ distance.text = "Distance: "+doctor.distance
+ address.text = doctor.address
+ setRatingView(doctor.rating, holder)
+
+ var imageName = "doc_m2"
+ if (doctor.name.contains("Urmila") || doctor.name.contains("Varsha") ||doctor.name.contains("Vasanti"))
+ {
+ // For demo project this condition is applied. In actual get the profile pic from API.
+ imageName = "doc_f1"
+ }
+
+ categoryImage.setImageResource(context.resources.getIdentifier(
+ imageName, "drawable", "com.ketub4.mvvmdemowithdi"));
+
+ bookBtn.setOnClickListener {
+ listener.onBookBtnClick(doctor)
+ }
+
+ }
+ }
+
+
+
+ override fun getItemCount()= doctorList.size
+
+ private fun setRatingView(rating: Int, holder: DoctorListViewHolder) {
+ if (rating==1){
+ holder.binding.apply {
+ rate1.setImageResource(R.drawable.start_filled)
+ rate2.setImageResource(R.drawable.start)
+ rate3.setImageResource(R.drawable.start)
+ rate4.setImageResource(R.drawable.start)
+ rate5.setImageResource(R.drawable.start)
+ }
+ }
+ if (rating==2){
+ holder.binding.apply {
+ rate1.setImageResource(R.drawable.start_filled)
+ rate2.setImageResource(R.drawable.start_filled)
+ rate3.setImageResource(R.drawable.start)
+ rate4.setImageResource(R.drawable.start)
+ rate5.setImageResource(R.drawable.start)
+ }
+ }
+ if (rating==3){
+ holder.binding.apply {
+ rate1.setImageResource(R.drawable.start_filled)
+ rate2.setImageResource(R.drawable.start_filled)
+ rate3.setImageResource(R.drawable.start_filled)
+ rate4.setImageResource(R.drawable.start)
+ rate5.setImageResource(R.drawable.start)
+ }
+ }
+ if (rating==4){
+ holder.binding.apply {
+ rate1.setImageResource(R.drawable.start_filled)
+ rate2.setImageResource(R.drawable.start_filled)
+ rate3.setImageResource(R.drawable.start_filled)
+ rate4.setImageResource(R.drawable.start_filled)
+ rate5.setImageResource(R.drawable.start)
+ }
+ }
+ if (rating==5){
+ holder.binding.apply {
+ rate1.setImageResource(R.drawable.start_filled)
+ rate2.setImageResource(R.drawable.start_filled)
+ rate3.setImageResource(R.drawable.start_filled)
+ rate4.setImageResource(R.drawable.start_filled)
+ rate5.setImageResource(R.drawable.start_filled)
+ }
+ }
+ }
+}
+
+interface IDoctorListAdapter{
+ fun onBookBtnClick(doctor: Doctors)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/DrawerMenuAdapter.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/DrawerMenuAdapter.kt
new file mode 100644
index 0000000..12f2f11
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/DrawerMenuAdapter.kt
@@ -0,0 +1,90 @@
+package com.ketub4.mvvmdemowithdi.adapter
+
+import android.graphics.Color
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import com.ketub4.mvvmdemowithdi.databinding.DrawerMenuItemBinding
+import com.ketub4.mvvmdemowithdi.R
+
+class DrawerMenuAdapter(private val listener:IDrawerMenuAdapter):RecyclerView.Adapter() {
+
+ class MenuViewHolder(val binding: DrawerMenuItemBinding): RecyclerView.ViewHolder(binding.root)
+
+ private val menuList:ArrayList = ArrayList(4)
+ private var selectedPosition: Int? = -1
+ init {
+ menuList.add("Home")
+ menuList.add("Search")
+ menuList.add("Notifications")
+ menuList.add("Profile")
+
+ }
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MenuViewHolder {
+ return (MenuViewHolder(DrawerMenuItemBinding.inflate(
+ LayoutInflater.from(parent.context),
+ parent,
+ false
+ )))
+ }
+
+ override fun onBindViewHolder(holder: MenuViewHolder, position: Int) {
+ val menu = menuList[position]
+ holder.binding.apply {
+ menuText.text = menu
+ when(menu){
+ "Home"->{
+ menuImage.setImageResource(R.drawable.home)
+ true
+ }
+ "Search"->{
+ menuImage.setImageResource(R.drawable.search)
+ true
+ }
+ "Notifications"->{
+ menuImage.setImageResource(R.drawable.notification)
+ true
+ }
+ "Profile"->{
+ menuImage.setImageResource(R.drawable.profile)
+ true
+ }
+ else->{
+ menuImage.setImageResource(R.drawable.home)
+ true
+ }
+ }
+
+ holder.binding.menuItem.setOnClickListener {
+ if (selectedPosition == holder.adapterPosition){
+ selectedPosition = RecyclerView.NO_POSITION
+ notifyDataSetChanged()
+ return@setOnClickListener
+ }
+ selectedPosition = holder.adapterPosition
+ notifyDataSetChanged()
+
+ listener.onMenuItemClicked(position)
+ }
+
+ if (selectedPosition == position){
+ menuItem.setBackgroundResource(R.drawable.background_shape_square_blue)
+ menuText.setTextColor(Color.WHITE)
+ menuImage.setColorFilter(Color.argb(255, 255, 255, 255));
+ }else{
+ menuItem.setBackgroundResource(R.drawable.background_shape_white)
+ menuText.setTextColor(Color.BLACK)
+ menuImage.setColorFilter(Color.argb(0, 0, 0, 0));
+ }
+
+ }
+ }
+
+ override fun getItemCount()= menuList.size
+
+
+}
+
+interface IDrawerMenuAdapter{
+ fun onMenuItemClicked(id:Int)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/NotificationAdapter.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/NotificationAdapter.kt
new file mode 100644
index 0000000..db623a2
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/NotificationAdapter.kt
@@ -0,0 +1,99 @@
+package com.ketub4.mvvmdemowithdi.adapter
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import com.ketub4.mvvmdemowithdi.R
+import com.ketub4.mvvmdemowithdi.databinding.NotificationItemBinding
+import com.ketub4.mvvmdemowithdi.model.Notification
+
+class NotificationAdapter(
+ private val notificatioList: ArrayList,
+ private val context: Context
+): RecyclerView.Adapter() {
+
+ class NotificationViewHolder(val binding: NotificationItemBinding): RecyclerView.ViewHolder(binding.root)
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NotificationViewHolder {
+ return NotificationViewHolder(
+ NotificationItemBinding.inflate(
+ LayoutInflater.from(parent.context),
+ parent,
+ false
+ )
+
+ )
+ }
+
+ override fun onBindViewHolder(holder: NotificationViewHolder, position: Int) {
+ val notification = notificatioList[position]
+ holder.binding.apply {
+ notificationTitle.text = notification.title
+ notificationText.text = notification.message
+ notificationDate.text = notification.date
+
+ val imageName = "cat_"+notification.categoryId
+ categoryImage.setImageResource(context.resources.getIdentifier(
+ imageName, "drawable", "com.ketub4.mvvmdemowithdi"));
+
+ when(notification.categoryId){
+ 1->{
+ leftBar.setBackgroundColor(context.resources.getColor(R.color.basicGreen))
+ rightBar.setBackgroundColor(context.resources.getColor(R.color.basicGreen))
+ true
+ }
+ 2->{
+ leftBar.setBackgroundColor(context.resources.getColor(R.color.basicOrange))
+ rightBar.setBackgroundColor(context.resources.getColor(R.color.basicOrange))
+ true
+ }
+ 3->{
+ leftBar.setBackgroundColor(context.resources.getColor(R.color.basicBlue))
+ rightBar.setBackgroundColor(context.resources.getColor(R.color.basicBlue))
+ true
+ }
+ 4->{
+ leftBar.setBackgroundColor(context.resources.getColor(R.color.basicGreen))
+ rightBar.setBackgroundColor(context.resources.getColor(R.color.basicGreen))
+ true
+ }
+ 5->{
+ leftBar.setBackgroundColor(context.resources.getColor(R.color.basicYellow))
+ rightBar.setBackgroundColor(context.resources.getColor(R.color.basicYellow))
+ true
+ }
+ 6->{
+ leftBar.setBackgroundColor(context.resources.getColor(R.color.basicBlue))
+ rightBar.setBackgroundColor(context.resources.getColor(R.color.basicBlue))
+ true
+ }
+ 7->{
+ leftBar.setBackgroundColor(context.resources.getColor(R.color.basicGreen))
+ rightBar.setBackgroundColor(context.resources.getColor(R.color.basicGreen))
+ true
+ }
+ 8->{
+ leftBar.setBackgroundColor(context.resources.getColor(R.color.basicBlue))
+ rightBar.setBackgroundColor(context.resources.getColor(R.color.basicBlue))
+ true
+ }
+ 10->{
+ leftBar.setBackgroundColor(context.resources.getColor(R.color.basicOrange))
+ rightBar.setBackgroundColor(context.resources.getColor(R.color.basicOrange))
+ true
+ }
+ else ->{
+ leftBar.setBackgroundColor(context.resources.getColor(R.color.basicPink))
+ rightBar.setBackgroundColor(context.resources.getColor(R.color.basicPink))
+ true
+ }
+ }
+
+ }
+ }
+
+ override fun getItemCount()= notificatioList.size
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/ViewPager2Adapter.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/ViewPager2Adapter.kt
new file mode 100644
index 0000000..b46c777
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/adapter/ViewPager2Adapter.kt
@@ -0,0 +1,71 @@
+package com.ketub4.mvvmdemowithdi.adapter
+
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import com.ketub4.mvvmdemowithdi.databinding.ViewpagerItemBinding
+
+import android.content.Context
+import android.util.Log
+import android.view.LayoutInflater
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.ketub4.mvvmdemowithdi.R
+import com.ketub4.mvvmdemowithdi.model.Appointment
+
+
+
+
+
+
+class ViewPager2Adapter(private val context: Context,
+ private val appointmentAdapter: AppointmentAdapter,
+ private val listener: IViewPagerListener):RecyclerView.Adapter() {
+
+ class PageViewHolder(val binding: ViewpagerItemBinding): RecyclerView.ViewHolder(binding.root)
+
+ private val timings = arrayOf(
+ "Morning", "Afternoon", "Evening"
+ )
+ private val timeImages = intArrayOf(
+ R.drawable.morning,
+ R.drawable.afternoon,
+ R.drawable.night,
+
+ )
+
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PageViewHolder {
+ return (PageViewHolder(ViewpagerItemBinding.inflate(
+ LayoutInflater.from(parent.context),
+ parent,
+ false
+ )))
+ }
+
+ override fun onBindViewHolder(holder: PageViewHolder, position: Int) {
+
+ holder.binding.apply {
+ recyclerView.layoutManager = GridLayoutManager(context,4)
+ recyclerView.hasFixedSize()
+ recyclerView.adapter = appointmentAdapter
+ Log.i("position","position="+position)
+ pageTitle.text = timings[position]
+ pageTitleImage.setImageResource(timeImages[position])
+
+ previous.setOnClickListener {
+ listener.previousPage()
+ }
+ next.setOnClickListener {
+ listener.nextPage()
+ }
+
+ }
+ }
+
+ override fun getItemCount()=timings.size
+}
+
+interface IViewPagerListener{
+ fun nextPage()
+ fun previousPage()
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/container/BaseApplication.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/container/BaseApplication.kt
new file mode 100644
index 0000000..406898d
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/container/BaseApplication.kt
@@ -0,0 +1,8 @@
+package com.ketub4.mvvmdemowithdi.container
+
+import android.app.Application
+import dagger.hilt.android.HiltAndroidApp
+
+@HiltAndroidApp
+class BaseApplication:Application() {
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/di/AppModule.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/di/AppModule.kt
new file mode 100644
index 0000000..1029477
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/di/AppModule.kt
@@ -0,0 +1,44 @@
+package com.ketub4.mvvmdemowithdi.di
+
+import android.content.Context
+import com.google.firebase.firestore.FirebaseFirestore
+import com.ketub4.mvvmdemowithdi.network.APIService
+import com.ketub4.mvvmdemowithdi.network.FirebaseService
+
+import com.ketub4.mvvmdemowithdi.utils.Constant
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
+import retrofit2.Retrofit
+import retrofit2.converter.gson.GsonConverterFactory
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+class AppModule {
+
+ @Provides
+ @Singleton
+ fun provideRetrofitInstance(): APIService{
+ return Retrofit.Builder()
+ .baseUrl(Constant.BASE_URL)
+ .addConverterFactory(GsonConverterFactory.create())
+ .build()
+ .create(APIService::class.java)
+ }
+
+ @Provides
+ @Singleton
+ fun provideFireStoreInstance():FirebaseFirestore {
+ return FirebaseFirestore.getInstance()
+ }
+
+ @Provides
+ @Singleton
+ fun getContext(@ApplicationContext context: Context):Context{
+ return context
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/fragments/HomeFragment.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/fragments/HomeFragment.kt
new file mode 100644
index 0000000..d7afdaa
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/fragments/HomeFragment.kt
@@ -0,0 +1,126 @@
+package com.ketub4.mvvmdemowithdi.fragments
+
+import android.content.Intent
+import android.os.Bundle
+import android.util.Log
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.activityViewModels
+import androidx.lifecycle.Observer
+import androidx.recyclerview.widget.LinearLayoutManager
+
+import com.ketub4.mvvmdemowithdi.CategoryAdapter
+import com.ketub4.mvvmdemowithdi.ICategoryListener
+import com.ketub4.mvvmdemowithdi.R
+import com.ketub4.mvvmdemowithdi.activities.DoctorListActivity
+import com.ketub4.mvvmdemowithdi.databinding.FragmentHomeBinding
+
+import com.ketub4.mvvmdemowithdi.model.Category
+import com.ketub4.mvvmdemowithdi.viewModel.CustomViewModel
+import com.synnapps.carouselview.ImageListener
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+class HomeFragment : Fragment(),ICategoryListener {
+ private var _binding: FragmentHomeBinding?=null
+ private val binding: FragmentHomeBinding get() = _binding!!
+ private val customViewModel: CustomViewModel by activityViewModels()
+ lateinit var categoryAdapter: CategoryAdapter
+ private lateinit var categoryList: ArrayList
+
+ var sampleImages = intArrayOf(
+ R.drawable.banner_image1,
+ R.drawable.banner_image2,
+ R.drawable.banner_image1,
+ R.drawable.banner_image2,
+ R.drawable.banner_image1,
+ R.drawable.banner_image2,
+ )
+
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ // Inflate the layout for this fragment
+ _binding = FragmentHomeBinding.inflate(layoutInflater, container, false)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ customViewModel.getCategoryList()
+ //customViewModel.insertDoctorData()
+ showHideProgressBar()
+
+ //setupRV()
+
+// customViewModel._categoryList.observe(requireActivity(), Observer { list->
+// Log.i("category=", "category$list")
+// categoryList = list
+// if (list.size>0) {
+// showHideProgressBar()
+// setupRV()
+// }
+// })
+
+
+ GlobalScope.launch(Dispatchers.Main) {
+ delay(1500)
+ customViewModel.categoryList.observe(viewLifecycleOwner, Observer { list->
+ Log.i("category=", "category$list")
+ categoryList = list
+ if (list.size>0) {
+ showHideProgressBar()
+ setupRV()
+ }
+ })
+
+
+ }
+
+ val imageListener =
+ ImageListener { position, imageView -> imageView.setImageResource(sampleImages[position]) }
+ _binding!!.carouselView.apply {
+ setImageListener(imageListener)
+ pageCount = sampleImages.size
+
+ }
+ }
+
+ private fun setupRV() {
+ categoryAdapter = CategoryAdapter(this,categoryList, requireContext())
+ binding.categoryRV.apply {
+ layoutManager = LinearLayoutManager(requireContext())
+ hasFixedSize()
+ adapter = categoryAdapter
+ }
+
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ _binding = null
+ }
+
+ override fun onCategoryClick(category_id:Int, category_name:String) {
+ val intent = Intent(requireContext(), DoctorListActivity::class.java)
+ intent.putExtra("categoryId", category_id)
+ intent.putExtra("categoryName", category_name)
+ startActivity(intent)
+ }
+
+ private fun showHideProgressBar() {
+ if (_binding!!.proressBar.visibility== View.VISIBLE){
+ _binding!!.proressBar.visibility = View.GONE
+ }else{
+ _binding!!.proressBar.visibility = View.VISIBLE
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/fragments/NotificationFragment.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/fragments/NotificationFragment.kt
new file mode 100644
index 0000000..bf45741
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/fragments/NotificationFragment.kt
@@ -0,0 +1,78 @@
+package com.ketub4.mvvmdemowithdi.fragments
+
+import android.os.Bundle
+import android.util.Log
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import androidx.appcompat.widget.Toolbar
+import androidx.fragment.app.activityViewModels
+import androidx.lifecycle.Observer
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.ketub4.mvvmdemowithdi.R
+import com.ketub4.mvvmdemowithdi.adapter.DoctorListAdapter
+import com.ketub4.mvvmdemowithdi.adapter.NotificationAdapter
+import com.ketub4.mvvmdemowithdi.databinding.FragmentNotificationBinding
+import com.ketub4.mvvmdemowithdi.model.Notification
+import com.ketub4.mvvmdemowithdi.viewModel.CustomViewModel
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+
+class NotificationFragment : Fragment() {
+ private var _binding: FragmentNotificationBinding?=null
+ private val binding: FragmentNotificationBinding get() = _binding!!
+ private val customViewModel: CustomViewModel by activityViewModels()
+ lateinit var notificationAdapter: NotificationAdapter
+ lateinit var notificationList: ArrayList
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ // Inflate the layout for this fragment
+ _binding = FragmentNotificationBinding.inflate(layoutInflater, container, false)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ showHideProgressBar()
+
+ customViewModel.getNotifications()
+ GlobalScope.launch(Dispatchers.Main) {
+ delay(1500)
+ customViewModel.notificationsList.observe(requireActivity(), Observer { list ->
+ Log.i("doctors=", "doctors=${list.size}")
+ notificationList = list
+ if (list.size>0)
+ showHideProgressBar()
+ })
+ setupRV()
+ }
+
+ }
+
+ private fun setupRV() {
+ notificationAdapter = NotificationAdapter(notificationList, requireActivity())
+ binding.recyclerView.apply {
+ layoutManager = LinearLayoutManager(requireActivity())
+ hasFixedSize()
+ adapter = notificationAdapter
+ }
+
+ }
+
+ private fun showHideProgressBar() {
+ if (_binding!!.progressBar.visibility== View.VISIBLE){
+ _binding!!.progressBar.visibility = View.GONE
+ }else{
+ _binding!!.progressBar.visibility = View.VISIBLE
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/fragments/ProfileFragment.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/fragments/ProfileFragment.kt
new file mode 100644
index 0000000..b44ad4e
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/fragments/ProfileFragment.kt
@@ -0,0 +1,24 @@
+package com.ketub4.mvvmdemowithdi.fragments
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.ketub4.mvvmdemowithdi.R
+import com.ketub4.mvvmdemowithdi.databinding.FragmentHomeBinding
+import com.ketub4.mvvmdemowithdi.databinding.FragmentProfileBinding
+
+class ProfileFragment : Fragment() {
+ private var _binding: FragmentProfileBinding?=null
+ private val binding: FragmentProfileBinding get() = _binding!!
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ // Inflate the layout for this fragment
+ _binding = FragmentProfileBinding.inflate(layoutInflater, container, false)
+ return binding.root
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/fragments/SearchFragment.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/fragments/SearchFragment.kt
new file mode 100644
index 0000000..f2031b6
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/fragments/SearchFragment.kt
@@ -0,0 +1,87 @@
+package com.ketub4.mvvmdemowithdi.fragments
+
+import android.content.Intent
+import android.os.Bundle
+import android.util.Log
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.activityViewModels
+import androidx.lifecycle.Observer
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.gson.Gson
+import com.ketub4.mvvmdemowithdi.R
+import com.ketub4.mvvmdemowithdi.activities.BookAppointmentActivity
+import com.ketub4.mvvmdemowithdi.adapter.DoctorListAdapter
+import com.ketub4.mvvmdemowithdi.adapter.IDoctorListAdapter
+import com.ketub4.mvvmdemowithdi.databinding.FragmentHomeBinding
+import com.ketub4.mvvmdemowithdi.databinding.FragmentSearchBinding
+import com.ketub4.mvvmdemowithdi.model.Doctors
+import com.ketub4.mvvmdemowithdi.viewModel.CustomViewModel
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+class SearchFragment : Fragment(), IDoctorListAdapter {
+ private var _binding: FragmentSearchBinding?=null
+ private val binding: FragmentSearchBinding get() = _binding!!
+ private val customViewModel: CustomViewModel by activityViewModels()
+ lateinit var doctorListAdapter:DoctorListAdapter
+ lateinit var doctorList: ArrayList
+ private val gson = Gson()
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ // Inflate the layout for this fragment
+ _binding = FragmentSearchBinding.inflate(layoutInflater, container, false)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ showHideProgressBar()
+
+ customViewModel.getDoctorsList(0)
+ GlobalScope.launch(Dispatchers.Main) {
+ delay(5000)
+ customViewModel.doctorsList.observe(requireActivity(), Observer { list ->
+ Log.i("doctors=", "doctors=${list.size}")
+ doctorList = list
+ if (list.size>0)
+ showHideProgressBar()
+ })
+ setupRV()
+ }
+
+ }
+
+ private fun setupRV() {
+ doctorListAdapter = DoctorListAdapter(doctorList, this, requireActivity())
+ binding.recyclerView.apply {
+ layoutManager = LinearLayoutManager(requireActivity())
+ hasFixedSize()
+ adapter = doctorListAdapter
+ }
+
+ }
+
+ private fun showHideProgressBar() {
+ if (_binding!!.progressBar.visibility== View.VISIBLE){
+ _binding!!.progressBar.visibility = View.GONE
+ }else{
+ _binding!!.progressBar.visibility = View.VISIBLE
+ }
+
+ }
+
+ override fun onBookBtnClick(doctor: Doctors) {
+ val intent = Intent(requireActivity(), BookAppointmentActivity::class.java)
+ val objString = gson.toJson(doctor)
+ intent.putExtra("doctorObj",objString)
+ startActivity(intent)
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/model/Appointment.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/model/Appointment.kt
new file mode 100644
index 0000000..c6abe1d
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/model/Appointment.kt
@@ -0,0 +1,14 @@
+package com.ketub4.mvvmdemowithdi.model
+
+data class Appointment(
+ val id: Int,
+ val doctorId: Int,
+ val categoryId: Int,
+ val timeSlot: String,
+ val date: String,
+ val time: String,
+ val booked: Boolean
+
+) {
+ constructor(): this(0,0,0,"","","", false)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/model/Category.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/model/Category.kt
new file mode 100644
index 0000000..798629e
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/model/Category.kt
@@ -0,0 +1,10 @@
+package com.ketub4.mvvmdemowithdi.model
+
+data class Category(val id: Int,
+ val name: String,
+ val description: String){
+
+ constructor(): this(
+ 0,"",""
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/model/Doctors.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/model/Doctors.kt
new file mode 100644
index 0000000..9ca4665
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/model/Doctors.kt
@@ -0,0 +1,16 @@
+package com.ketub4.mvvmdemowithdi.model
+
+data class Doctors(
+ val category_id: Int,
+ val id: Int,
+ val category: String,
+ val name: String,
+ val address: String,
+ val distance: String,
+ val rating: Int,
+
+) {
+ constructor(): this(
+ 0,0,"","","","",0
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/model/MovieResult.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/model/MovieResult.kt
new file mode 100644
index 0000000..57c69e0
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/model/MovieResult.kt
@@ -0,0 +1,8 @@
+package com.ketub4.mvvmdemowithdi.model
+
+data class MovieResult(
+ val page: Int,
+ val results: List,
+ val total_pages: Int,
+ val total_results: Int
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/model/Notification.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/model/Notification.kt
new file mode 100644
index 0000000..742f750
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/model/Notification.kt
@@ -0,0 +1,15 @@
+package com.ketub4.mvvmdemowithdi.model
+
+data class Notification(
+ val id: Int,
+ val categoryId: Int,
+ val categoryName: String,
+ val title:String,
+ val message: String,
+ val date: String,
+
+) {
+ constructor(): this(
+ 0,0,"","","",""
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/model/Result.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/model/Result.kt
new file mode 100644
index 0000000..6dddfd1
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/model/Result.kt
@@ -0,0 +1,18 @@
+package com.ketub4.mvvmdemowithdi.model
+
+data class Result(
+ val adult: Boolean,
+ val backdrop_path: String,
+ val genre_ids: List,
+ val id: Int,
+ val original_language: String,
+ val original_title: String,
+ val overview: String,
+ val popularity: Double,
+ val poster_path: String,
+ val release_date: String,
+ val title: String,
+ val video: Boolean,
+ val vote_average: Double,
+ val vote_count: Int
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/network/APIService.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/network/APIService.kt
new file mode 100644
index 0000000..03afa8c
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/network/APIService.kt
@@ -0,0 +1,12 @@
+package com.ketub4.mvvmdemowithdi.network
+
+import com.ketub4.mvvmdemowithdi.model.MovieResult
+import com.ketub4.mvvmdemowithdi.utils.Constant
+import retrofit2.http.GET
+
+interface APIService {
+
+ @GET("/3/movie/popular?api_key="+Constant.API_KEY)
+ suspend fun getListofMovies():MovieResult
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/network/FirebaseService.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/network/FirebaseService.kt
new file mode 100644
index 0000000..b54a09d
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/network/FirebaseService.kt
@@ -0,0 +1,5 @@
+package com.ketub4.mvvmdemowithdi.network
+
+interface FirebaseService {
+ suspend fun onGetCategoryListFetch()
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/repository/MovieRepository.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/repository/MovieRepository.kt
new file mode 100644
index 0000000..bff0842
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/repository/MovieRepository.kt
@@ -0,0 +1,574 @@
+package com.ketub4.mvvmdemowithdi.repository
+
+import android.content.Context
+import android.util.Log
+import com.google.firebase.firestore.FirebaseFirestore
+import com.google.firebase.firestore.Query
+import com.ketub4.mvvmdemowithdi.model.*
+import com.ketub4.mvvmdemowithdi.network.APIService
+import com.ketub4.mvvmdemowithdi.network.FirebaseService
+import javax.inject.Inject
+
+
+class MovieRepository @Inject constructor(private val apiService: APIService,
+ private val firebaseDB: FirebaseFirestore,
+ private val context: Context
+
+) {
+
+
+
+ suspend fun getMovieList():MovieResult{
+ return apiService.getListofMovies()
+ }
+
+ fun insertData(){
+ firebaseDB.collection("Categories")
+ .add(Category(8,"Nutritionist ","Be healthy"))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+
+ }
+ fun insertDoctorData(){
+
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(1,1,1,"m","22/02/2022","9.30",true))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(2,1,1,"m","22/02/2022","9.45",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(3,1,1,"m","22/02/2022","10.00",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(4,1,1,"m","22/02/2022","10.15",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(5,1,1,"m","22/02/2022","10.30",true))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(6,1,1,"m","22/02/2022","10.45",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(7,1,1,"m","22/02/2022","11.00",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(8,1,1,"m","22/02/2022","11.15",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(9,1,1,"m","22/02/2022","11.30",true))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(10,1,1,"m","22/02/2022","11.45",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(11,1,1,"m","22/02/2022","12.00",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+
+ ////////////////////////////////////////////////////////////////////
+
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(12,1,1,"a","22/02/2022","12.15",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(13,1,1,"a","22/02/2022","12.30",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(14,1,1,"a","22/02/2022","12.45",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(15,1,1,"a","22/02/2022","01.00",true))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(16,1,1,"a","22/02/2022","01.15",true))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(17,1,1,"a","22/02/2022","01.30",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(18,1,1,"a","22/02/2022","01.45",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(19,1,1,"a","22/02/2022","02.00",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(20,1,1,"a","22/02/2022","02.15",true))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(21,1,1,"a","22/02/2022","02,30",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(22,1,1,"a","22/02/2022","02.45",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(23,1,1,"a","22/02/2022","03.00",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(24,1,1,"a","22/02/2022","03.15",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(25,1,1,"a","22/02/2022","03.30",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(26,1,1,"a","22/02/2022","03.45",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(27,1,1,"a","22/02/2022","04.00",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+
+ ////////////////////////////////////////////////////////////////////
+
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(28,1,1,"e","22/02/2022","06.15",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(29,1,1,"e","22/02/2022","06.30",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(30,1,1,"e","22/02/2022","06.45",true))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(31,1,1,"e","22/02/2022","07.00",true))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(32,1,1,"e","22/02/2022","07.15",true))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(33,1,1,"e","22/02/2022","07.30",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(34,1,1,"e","22/02/2022","07.45",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(35,1,1,"e","22/02/2022","08.00",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(36,1,1,"e","22/02/2022","08.15",true))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(37,1,1,"e","22/02/2022","08,30",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(38,1,1,"e","22/02/2022","08.45",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(39,1,1,"e","22/02/2022","09.00",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(40,1,1,"e","22/02/2022","09.15",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(41,1,1,"e","22/02/2022","09.30",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(42,1,1,"e","22/02/2022","09.45",true))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+ firebaseDB.collection("TimeSlots")
+ .add(Appointment(43,1,1,"e","22/02/2022","10.00",false))
+
+ .addOnSuccessListener {
+ Log.i("Successful","Addition of Record")
+ }
+ .addOnFailureListener {
+ Log.i("Error","Adding Record")
+ }
+
+
+
+ }
+
+ fun getCategoryList():ArrayList{
+ var categoryList = ArrayList()
+ firebaseDB.collection("Categories")
+ .orderBy("id", Query.Direction.ASCENDING)
+ .get()
+ .addOnSuccessListener { results->
+
+ for (document in results){
+ categoryList.add(document.toObject(Category::class.java))
+ }
+ Log.i("Successful","Fetching of Record")
+
+ }
+ .addOnFailureListener {
+ Log.i("Error","Fetching Record")
+ }
+
+ return categoryList
+ }
+
+ suspend fun getDoctorList(category_id: Int):ArrayList{
+ Log.i("category_id", "category_id=$category_id")
+ var doctorList = ArrayList()
+ val collection = firebaseDB.collection("Doctors")
+ var collectionReference:Query = collection
+ if (category_id!=0){
+ collectionReference = collection.whereEqualTo("category_id", category_id)
+ }
+
+ collectionReference.orderBy("id", Query.Direction.ASCENDING)
+ .get()
+ .addOnSuccessListener { result->
+ for (document in result){
+ doctorList.add(document.toObject(Doctors::class.java))
+ }
+ Log.i("Successful","Fetching of Doctors Record")
+
+ }
+
+ .addOnFailureListener {
+ Log.i("Error","Fetching Doctors Record")
+ }
+
+ return doctorList
+ }
+
+ suspend fun getNotifications():ArrayList{
+ var notificationList = ArrayList()
+ val collection = firebaseDB.collection("Notifications")
+ collection.orderBy("id", Query.Direction.ASCENDING)
+ .get()
+ .addOnSuccessListener { result->
+ for (document in result){
+ notificationList.add(document.toObject(Notification::class.java))
+ }
+ Log.i("Successful","Fetching of notificationList Record")
+
+ }
+
+ .addOnFailureListener {
+ Log.i("Error","Fetching notificationList Record")
+ }
+
+ return notificationList
+ }
+
+ suspend fun getTimeSlots(date:String, doctorId: Int):ArrayList{
+ var timeSlotList = ArrayList()
+ val collection = firebaseDB.collection("TimeSlots")
+ var query = collection.whereEqualTo("date","22/02/2022")// hardcoded for demo
+ //query = query.whereEqualTo(doctorId,1)//later add doctor Id filter
+ query
+ .orderBy("id", Query.Direction.ASCENDING)
+ .get()
+ .addOnSuccessListener { result->
+ for (document in result){
+ timeSlotList.add(document.toObject(Appointment::class.java))
+ }
+ Log.i("Successful","Fetching of getTimeSlots Record")
+
+ }
+
+ .addOnFailureListener {
+ Log.i("Error","Fetching getTimeSlots Record")
+ }
+
+ return timeSlotList
+ }
+
+
+// suspend fun getTimeSlots():ArrayList{
+//// var appointmentList = ArrayList()
+//// appointmentList.add(Appointment(1, "m", "22/02/2022","9.30",false))
+//// appointmentList.add(Appointment(2, "10.30",false))
+//// appointmentList.add(Appointment(3, "11.30",true))
+//// appointmentList.add(Appointment(4, "12.30",false))
+//// appointmentList.add(Appointment(5, "01.30",false))
+//// appointmentList.add(Appointment(6, "02.30",true))
+//// appointmentList.add(Appointment(7, "03.30",false))
+//// appointmentList.add(Appointment(9, "09.30",false))
+//// appointmentList.add(Appointment(10, "10.30",false))
+//// appointmentList.add(Appointment(11, "11.30",true))
+//// appointmentList.add(Appointment(12, "12.30",false))
+//// appointmentList.add(Appointment(13, "01.30",false))
+//// appointmentList.add(Appointment(14, "02.30",true))
+//// appointmentList.add(Appointment(15, "03.30",false))
+//// appointmentList.add(Appointment(16, "09.30",false))
+//// appointmentList.add(Appointment(17, "10.30",false))
+//// appointmentList.add(Appointment(18, "11.30",true))
+//// appointmentList.add(Appointment(19, "12.30",false))
+//// appointmentList.add(Appointment(20, "31.30",false))
+//// appointmentList.add(Appointment(21, "32.30",true))
+//// appointmentList.add(Appointment(22, "33.30",false))
+//// val collection = firebaseDB.collection("TimeSlots")
+//// collection.orderBy("id", Query.Direction.ASCENDING)
+//// .get()
+//// .addOnSuccessListener { result->
+//// for (document in result){
+//// notificationList.add(document.toObject(Notification::class.java))
+//// }
+//// Log.i("Successful","Fetching of notificationList Record")
+////
+//// }
+////
+//// .addOnFailureListener {
+//// Log.i("Error","Fetching notificationList Record")
+//// }
+//
+// return appointmentList
+// }
+
+
+
+}
+
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/utils/CalendarUtils.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/utils/CalendarUtils.kt
new file mode 100644
index 0000000..dc33293
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/utils/CalendarUtils.kt
@@ -0,0 +1,75 @@
+package com.ketub4.mvvmdemowithdi.utils
+
+import android.os.Build
+import androidx.annotation.RequiresApi
+import java.time.DayOfWeek
+import java.time.LocalDate
+
+import java.time.LocalTime
+import java.time.YearMonth
+import java.time.format.DateTimeFormatter
+import java.util.ArrayList
+
+class CalendarUtils {
+
+ companion object{
+
+ @RequiresApi(Build.VERSION_CODES.O)
+ var selectedDate: LocalDate = LocalDate.now()
+
+ @RequiresApi(Build.VERSION_CODES.O)
+ fun formattedDate(date: LocalDate): String? {
+ val formatter = DateTimeFormatter.ofPattern("dd MMMM yyyy")
+ return date.format(formatter)
+ }
+ @RequiresApi(Build.VERSION_CODES.O)
+ fun formattedTime(time: LocalTime): String? {
+ val formatter = DateTimeFormatter.ofPattern("hh:mm:ss a")
+ return time.format(formatter)
+ }
+ @RequiresApi(Build.VERSION_CODES.O)
+ fun monthYearFromDate(date: LocalDate): String? {
+ val formatter = DateTimeFormatter.ofPattern("MMMM yyyy")
+ return date.format(formatter)
+ }
+ @RequiresApi(Build.VERSION_CODES.O)
+ fun daysInMonthArray(date: LocalDate?): ArrayList? {
+ val daysInMonthArray = ArrayList()
+ val yearMonth = YearMonth.from(date)
+ val daysInMonth = yearMonth.lengthOfMonth()
+ val firstOfMonth: LocalDate = this.selectedDate!!.withDayOfMonth(1)
+ val dayOfWeek = firstOfMonth.dayOfWeek.value
+ for (i in 1..42) {
+ if (i <= dayOfWeek || i > daysInMonth + dayOfWeek) daysInMonthArray.add(null) else daysInMonthArray.add(
+ LocalDate.of(
+ this.selectedDate!!.year,
+ this.selectedDate!!.month,
+ i - dayOfWeek
+ )
+ )
+ }
+ return daysInMonthArray
+ }
+ @RequiresApi(Build.VERSION_CODES.O)
+ fun daysInWeekArray(selectedDate: LocalDate): ArrayList {
+ val days = ArrayList()
+ var current = sundayForDate(selectedDate)
+ val endDate = current!!.plusWeeks(1)
+ while (current!!.isBefore(endDate)) {
+ days.add(current)
+ current = current.plusDays(1)
+ }
+ return days
+ }
+ @RequiresApi(Build.VERSION_CODES.O)
+ private fun sundayForDate(current: LocalDate): LocalDate? {
+ var current = current
+ val oneWeekAgo = current.minusWeeks(1)
+ while (current.isAfter(oneWeekAgo)) {
+ if (current.dayOfWeek == DayOfWeek.SUNDAY) return current
+ current = current.minusDays(1)
+ }
+ return null
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/utils/Constant.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/utils/Constant.kt
new file mode 100644
index 0000000..7ca7012
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/utils/Constant.kt
@@ -0,0 +1,10 @@
+package com.ketub4.mvvmdemowithdi.utils
+
+class Constant {
+
+ companion object{
+ const val BASE_URL ="https://api.themoviedb.org"
+ const val API_KEY = "70b3c31685d50c114975c4fffba51594"
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ketub4/mvvmdemowithdi/viewModel/CustomViewModel.kt b/app/src/main/java/com/ketub4/mvvmdemowithdi/viewModel/CustomViewModel.kt
new file mode 100644
index 0000000..467db1a
--- /dev/null
+++ b/app/src/main/java/com/ketub4/mvvmdemowithdi/viewModel/CustomViewModel.kt
@@ -0,0 +1,76 @@
+package com.ketub4.mvvmdemowithdi.viewModel
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.ketub4.mvvmdemowithdi.model.*
+import com.ketub4.mvvmdemowithdi.network.FirebaseService
+import com.ketub4.mvvmdemowithdi.repository.MovieRepository
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+@HiltViewModel
+class CustomViewModel @Inject constructor(private val repository: MovieRepository) :ViewModel() {
+
+ private var _movieList =MutableLiveData>()
+ val movieList: LiveData> get()= _movieList
+
+ var _categoryList =MutableLiveData>()
+ val categoryList: LiveData> get()= _categoryList
+
+ private var _doctorsList =MutableLiveData>()
+ val doctorsList: LiveData> get()= _doctorsList
+
+ private var _notificationsList =MutableLiveData>()
+ val notificationsList: LiveData> get()= _notificationsList
+
+ private var _timeSlotList =MutableLiveData>()
+ val timeSlotList: LiveData> get()= _timeSlotList
+
+ fun getMovieData(){
+ viewModelScope.launch {
+ _movieList.postValue(repository.getMovieList().results)
+ }
+ }
+
+ fun insertRecords(){
+ viewModelScope.launch {
+ repository.insertData()
+ }
+ }
+ fun insertDoctorData(){
+ viewModelScope.launch {
+ repository.insertDoctorData()
+ }
+ }
+
+ fun getCategoryList(){
+ //viewModelScope.launch(Dispatchers.Main) {
+ _categoryList.postValue(repository.getCategoryList())
+ //_categoryList.value =
+ //_categoryList.value = repository.getCategoryList()
+ //}
+ }
+
+ fun getDoctorsList(category_id: Int){
+ viewModelScope.launch {
+ _doctorsList.postValue(repository.getDoctorList(category_id))
+ }
+ }
+
+ fun getNotifications(){
+ viewModelScope.launch {
+ _notificationsList.postValue(repository.getNotifications())
+ }
+ }
+
+ fun getTimeSlots(date:String, doctorId: Int){
+ viewModelScope.launch {
+ _timeSlotList.postValue(repository.getTimeSlots(date, doctorId))
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable-v24/address.png b/app/src/main/res/drawable-v24/address.png
new file mode 100644
index 0000000..82b6b3f
Binary files /dev/null and b/app/src/main/res/drawable-v24/address.png differ
diff --git a/app/src/main/res/drawable-v24/afternoon.png b/app/src/main/res/drawable-v24/afternoon.png
new file mode 100644
index 0000000..a1198ad
Binary files /dev/null and b/app/src/main/res/drawable-v24/afternoon.png differ
diff --git a/app/src/main/res/drawable-v24/back_arrow.png b/app/src/main/res/drawable-v24/back_arrow.png
new file mode 100644
index 0000000..6267b23
Binary files /dev/null and b/app/src/main/res/drawable-v24/back_arrow.png differ
diff --git a/app/src/main/res/drawable-v24/banner_image1.png b/app/src/main/res/drawable-v24/banner_image1.png
new file mode 100644
index 0000000..67654be
Binary files /dev/null and b/app/src/main/res/drawable-v24/banner_image1.png differ
diff --git a/app/src/main/res/drawable-v24/banner_image2.png b/app/src/main/res/drawable-v24/banner_image2.png
new file mode 100644
index 0000000..67654be
Binary files /dev/null and b/app/src/main/res/drawable-v24/banner_image2.png differ
diff --git a/app/src/main/res/drawable-v24/calendar.png b/app/src/main/res/drawable-v24/calendar.png
new file mode 100644
index 0000000..5488f9f
Binary files /dev/null and b/app/src/main/res/drawable-v24/calendar.png differ
diff --git a/app/src/main/res/drawable-v24/cat_1.png b/app/src/main/res/drawable-v24/cat_1.png
new file mode 100644
index 0000000..df4ed09
Binary files /dev/null and b/app/src/main/res/drawable-v24/cat_1.png differ
diff --git a/app/src/main/res/drawable-v24/cat_10.png b/app/src/main/res/drawable-v24/cat_10.png
new file mode 100644
index 0000000..d015496
Binary files /dev/null and b/app/src/main/res/drawable-v24/cat_10.png differ
diff --git a/app/src/main/res/drawable-v24/cat_2.png b/app/src/main/res/drawable-v24/cat_2.png
new file mode 100644
index 0000000..060184f
Binary files /dev/null and b/app/src/main/res/drawable-v24/cat_2.png differ
diff --git a/app/src/main/res/drawable-v24/cat_3.png b/app/src/main/res/drawable-v24/cat_3.png
new file mode 100644
index 0000000..a150374
Binary files /dev/null and b/app/src/main/res/drawable-v24/cat_3.png differ
diff --git a/app/src/main/res/drawable-v24/cat_4.png b/app/src/main/res/drawable-v24/cat_4.png
new file mode 100644
index 0000000..3ee0980
Binary files /dev/null and b/app/src/main/res/drawable-v24/cat_4.png differ
diff --git a/app/src/main/res/drawable-v24/cat_5.png b/app/src/main/res/drawable-v24/cat_5.png
new file mode 100644
index 0000000..a76dcaa
Binary files /dev/null and b/app/src/main/res/drawable-v24/cat_5.png differ
diff --git a/app/src/main/res/drawable-v24/cat_6.png b/app/src/main/res/drawable-v24/cat_6.png
new file mode 100644
index 0000000..48dac43
Binary files /dev/null and b/app/src/main/res/drawable-v24/cat_6.png differ
diff --git a/app/src/main/res/drawable-v24/cat_7.png b/app/src/main/res/drawable-v24/cat_7.png
new file mode 100644
index 0000000..9138677
Binary files /dev/null and b/app/src/main/res/drawable-v24/cat_7.png differ
diff --git a/app/src/main/res/drawable-v24/cat_8.png b/app/src/main/res/drawable-v24/cat_8.png
new file mode 100644
index 0000000..bde42b8
Binary files /dev/null and b/app/src/main/res/drawable-v24/cat_8.png differ
diff --git a/app/src/main/res/drawable-v24/dob.png b/app/src/main/res/drawable-v24/dob.png
new file mode 100644
index 0000000..6f15daf
Binary files /dev/null and b/app/src/main/res/drawable-v24/dob.png differ
diff --git a/app/src/main/res/drawable-v24/doc_f1.png b/app/src/main/res/drawable-v24/doc_f1.png
new file mode 100644
index 0000000..8e676e1
Binary files /dev/null and b/app/src/main/res/drawable-v24/doc_f1.png differ
diff --git a/app/src/main/res/drawable-v24/doc_f2.png b/app/src/main/res/drawable-v24/doc_f2.png
new file mode 100644
index 0000000..0762280
Binary files /dev/null and b/app/src/main/res/drawable-v24/doc_f2.png differ
diff --git a/app/src/main/res/drawable-v24/doc_m1.png b/app/src/main/res/drawable-v24/doc_m1.png
new file mode 100644
index 0000000..8378158
Binary files /dev/null and b/app/src/main/res/drawable-v24/doc_m1.png differ
diff --git a/app/src/main/res/drawable-v24/doc_m2.png b/app/src/main/res/drawable-v24/doc_m2.png
new file mode 100644
index 0000000..29c52f4
Binary files /dev/null and b/app/src/main/res/drawable-v24/doc_m2.png differ
diff --git a/app/src/main/res/drawable-v24/doc_m3.png b/app/src/main/res/drawable-v24/doc_m3.png
new file mode 100644
index 0000000..03ed336
Binary files /dev/null and b/app/src/main/res/drawable-v24/doc_m3.png differ
diff --git a/app/src/main/res/drawable-v24/down_arrow.png b/app/src/main/res/drawable-v24/down_arrow.png
new file mode 100644
index 0000000..6c52d57
Binary files /dev/null and b/app/src/main/res/drawable-v24/down_arrow.png differ
diff --git a/app/src/main/res/drawable-v24/edit.png b/app/src/main/res/drawable-v24/edit.png
new file mode 100644
index 0000000..5cb993c
Binary files /dev/null and b/app/src/main/res/drawable-v24/edit.png differ
diff --git a/app/src/main/res/drawable-v24/email.png b/app/src/main/res/drawable-v24/email.png
new file mode 100644
index 0000000..24e5989
Binary files /dev/null and b/app/src/main/res/drawable-v24/email.png differ
diff --git a/app/src/main/res/drawable-v24/error.png b/app/src/main/res/drawable-v24/error.png
new file mode 100644
index 0000000..0c5d33b
Binary files /dev/null and b/app/src/main/res/drawable-v24/error.png differ
diff --git a/app/src/main/res/drawable-v24/failed.png b/app/src/main/res/drawable-v24/failed.png
new file mode 100644
index 0000000..844c8a8
Binary files /dev/null and b/app/src/main/res/drawable-v24/failed.png differ
diff --git a/app/src/main/res/drawable-v24/general.png b/app/src/main/res/drawable-v24/general.png
new file mode 100644
index 0000000..c99063d
Binary files /dev/null and b/app/src/main/res/drawable-v24/general.png differ
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..2b068d1
--- /dev/null
+++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-v24/left_arrow.png b/app/src/main/res/drawable-v24/left_arrow.png
new file mode 100644
index 0000000..1ae2f34
Binary files /dev/null and b/app/src/main/res/drawable-v24/left_arrow.png differ
diff --git a/app/src/main/res/drawable-v24/logout.png b/app/src/main/res/drawable-v24/logout.png
new file mode 100644
index 0000000..3bf6511
Binary files /dev/null and b/app/src/main/res/drawable-v24/logout.png differ
diff --git a/app/src/main/res/drawable-v24/menu.png b/app/src/main/res/drawable-v24/menu.png
new file mode 100644
index 0000000..31f956a
Binary files /dev/null and b/app/src/main/res/drawable-v24/menu.png differ
diff --git a/app/src/main/res/drawable-v24/morning.png b/app/src/main/res/drawable-v24/morning.png
new file mode 100644
index 0000000..e12f4df
Binary files /dev/null and b/app/src/main/res/drawable-v24/morning.png differ
diff --git a/app/src/main/res/drawable-v24/name.png b/app/src/main/res/drawable-v24/name.png
new file mode 100644
index 0000000..d68ea7f
Binary files /dev/null and b/app/src/main/res/drawable-v24/name.png differ
diff --git a/app/src/main/res/drawable-v24/next.png b/app/src/main/res/drawable-v24/next.png
new file mode 100644
index 0000000..f8f80da
Binary files /dev/null and b/app/src/main/res/drawable-v24/next.png differ
diff --git a/app/src/main/res/drawable-v24/next_new.png b/app/src/main/res/drawable-v24/next_new.png
new file mode 100644
index 0000000..55c3b62
Binary files /dev/null and b/app/src/main/res/drawable-v24/next_new.png differ
diff --git a/app/src/main/res/drawable-v24/night.png b/app/src/main/res/drawable-v24/night.png
new file mode 100644
index 0000000..9ac8fc9
Binary files /dev/null and b/app/src/main/res/drawable-v24/night.png differ
diff --git a/app/src/main/res/drawable-v24/previous.png b/app/src/main/res/drawable-v24/previous.png
new file mode 100644
index 0000000..ecbb39f
Binary files /dev/null and b/app/src/main/res/drawable-v24/previous.png differ
diff --git a/app/src/main/res/drawable-v24/profile_image.png b/app/src/main/res/drawable-v24/profile_image.png
new file mode 100644
index 0000000..c789dfc
Binary files /dev/null and b/app/src/main/res/drawable-v24/profile_image.png differ
diff --git a/app/src/main/res/drawable-v24/right.png b/app/src/main/res/drawable-v24/right.png
new file mode 100644
index 0000000..268744f
Binary files /dev/null and b/app/src/main/res/drawable-v24/right.png differ
diff --git a/app/src/main/res/drawable-v24/rounded_shape.xml b/app/src/main/res/drawable-v24/rounded_shape.xml
new file mode 100644
index 0000000..bc1eed2
--- /dev/null
+++ b/app/src/main/res/drawable-v24/rounded_shape.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-v24/share.png b/app/src/main/res/drawable-v24/share.png
new file mode 100644
index 0000000..7692eea
Binary files /dev/null and b/app/src/main/res/drawable-v24/share.png differ
diff --git a/app/src/main/res/drawable-v24/subscribe.png b/app/src/main/res/drawable-v24/subscribe.png
new file mode 100644
index 0000000..48e9054
Binary files /dev/null and b/app/src/main/res/drawable-v24/subscribe.png differ
diff --git a/app/src/main/res/drawable-v24/success.png b/app/src/main/res/drawable-v24/success.png
new file mode 100644
index 0000000..95cf217
Binary files /dev/null and b/app/src/main/res/drawable-v24/success.png differ
diff --git a/app/src/main/res/drawable-v24/three_dot_menu.png b/app/src/main/res/drawable-v24/three_dot_menu.png
new file mode 100644
index 0000000..a1b6c0b
Binary files /dev/null and b/app/src/main/res/drawable-v24/three_dot_menu.png differ
diff --git a/app/src/main/res/drawable-v24/welcome.png b/app/src/main/res/drawable-v24/welcome.png
new file mode 100644
index 0000000..93c833c
Binary files /dev/null and b/app/src/main/res/drawable-v24/welcome.png differ
diff --git a/app/src/main/res/drawable/back.xml b/app/src/main/res/drawable/back.xml
new file mode 100644
index 0000000..bcc4ebb
--- /dev/null
+++ b/app/src/main/res/drawable/back.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/background_shape.xml b/app/src/main/res/drawable/background_shape.xml
new file mode 100644
index 0000000..5aca057
--- /dev/null
+++ b/app/src/main/res/drawable/background_shape.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/background_shape1.xml b/app/src/main/res/drawable/background_shape1.xml
new file mode 100644
index 0000000..b261564
--- /dev/null
+++ b/app/src/main/res/drawable/background_shape1.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/background_shape2.xml b/app/src/main/res/drawable/background_shape2.xml
new file mode 100644
index 0000000..6bc3d6f
--- /dev/null
+++ b/app/src/main/res/drawable/background_shape2.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/background_shape_blue.xml b/app/src/main/res/drawable/background_shape_blue.xml
new file mode 100644
index 0000000..dfe61f0
--- /dev/null
+++ b/app/src/main/res/drawable/background_shape_blue.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/background_shape_gray.xml b/app/src/main/res/drawable/background_shape_gray.xml
new file mode 100644
index 0000000..a8a3de9
--- /dev/null
+++ b/app/src/main/res/drawable/background_shape_gray.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/background_shape_green.xml b/app/src/main/res/drawable/background_shape_green.xml
new file mode 100644
index 0000000..f038119
--- /dev/null
+++ b/app/src/main/res/drawable/background_shape_green.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/background_shape_square_blue.xml b/app/src/main/res/drawable/background_shape_square_blue.xml
new file mode 100644
index 0000000..1f3fa66
--- /dev/null
+++ b/app/src/main/res/drawable/background_shape_square_blue.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/background_shape_white.xml b/app/src/main/res/drawable/background_shape_white.xml
new file mode 100644
index 0000000..4f242dd
--- /dev/null
+++ b/app/src/main/res/drawable/background_shape_white.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/banner_image1.png b/app/src/main/res/drawable/banner_image1.png
new file mode 100644
index 0000000..ddc870d
Binary files /dev/null and b/app/src/main/res/drawable/banner_image1.png differ
diff --git a/app/src/main/res/drawable/banner_image2.png b/app/src/main/res/drawable/banner_image2.png
new file mode 100644
index 0000000..ddc870d
Binary files /dev/null and b/app/src/main/res/drawable/banner_image2.png differ
diff --git a/app/src/main/res/drawable/home.png b/app/src/main/res/drawable/home.png
new file mode 100644
index 0000000..876ed68
Binary files /dev/null and b/app/src/main/res/drawable/home.png differ
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..07d5da9
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/location.xml b/app/src/main/res/drawable/location.xml
new file mode 100644
index 0000000..1e53e2c
--- /dev/null
+++ b/app/src/main/res/drawable/location.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/notification.png b/app/src/main/res/drawable/notification.png
new file mode 100644
index 0000000..96b3caf
Binary files /dev/null and b/app/src/main/res/drawable/notification.png differ
diff --git a/app/src/main/res/drawable/profile.png b/app/src/main/res/drawable/profile.png
new file mode 100644
index 0000000..4052481
Binary files /dev/null and b/app/src/main/res/drawable/profile.png differ
diff --git a/app/src/main/res/drawable/search.png b/app/src/main/res/drawable/search.png
new file mode 100644
index 0000000..a75718d
Binary files /dev/null and b/app/src/main/res/drawable/search.png differ
diff --git a/app/src/main/res/drawable/side_nav_bar.xml b/app/src/main/res/drawable/side_nav_bar.xml
new file mode 100644
index 0000000..6d81870
--- /dev/null
+++ b/app/src/main/res/drawable/side_nav_bar.xml
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/start.xml b/app/src/main/res/drawable/start.xml
new file mode 100644
index 0000000..82b9e33
--- /dev/null
+++ b/app/src/main/res/drawable/start.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/start_filled.xml b/app/src/main/res/drawable/start_filled.xml
new file mode 100644
index 0000000..380f917
--- /dev/null
+++ b/app/src/main/res/drawable/start_filled.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/layout/activity_appointment_details.xml b/app/src/main/res/layout/activity_appointment_details.xml
new file mode 100644
index 0000000..bc6461f
--- /dev/null
+++ b/app/src/main/res/layout/activity_appointment_details.xml
@@ -0,0 +1,145 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_book_appointment.xml b/app/src/main/res/layout/activity_book_appointment.xml
new file mode 100644
index 0000000..ca3c1ed
--- /dev/null
+++ b/app/src/main/res/layout/activity_book_appointment.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_doctor_list.xml b/app/src/main/res/layout/activity_doctor_list.xml
new file mode 100644
index 0000000..7df03ec
--- /dev/null
+++ b/app/src/main/res/layout/activity_doctor_list.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..ed47c12
--- /dev/null
+++ b/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_successful.xml b/app/src/main/res/layout/activity_successful.xml
new file mode 100644
index 0000000..14900b2
--- /dev/null
+++ b/app/src/main/res/layout/activity_successful.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_welcome.xml b/app/src/main/res/layout/activity_welcome.xml
new file mode 100644
index 0000000..ab7abc7
--- /dev/null
+++ b/app/src/main/res/layout/activity_welcome.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/app_bar_main.xml b/app/src/main/res/layout/app_bar_main.xml
new file mode 100644
index 0000000..312d7e1
--- /dev/null
+++ b/app/src/main/res/layout/app_bar_main.xml
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/app_bar_main_home.xml b/app/src/main/res/layout/app_bar_main_home.xml
new file mode 100644
index 0000000..ee3f86f
--- /dev/null
+++ b/app/src/main/res/layout/app_bar_main_home.xml
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/appointment_activity_header.xml b/app/src/main/res/layout/appointment_activity_header.xml
new file mode 100644
index 0000000..c0762ea
--- /dev/null
+++ b/app/src/main/res/layout/appointment_activity_header.xml
@@ -0,0 +1,146 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/calendar_cell.xml b/app/src/main/res/layout/calendar_cell.xml
new file mode 100644
index 0000000..4d64061
--- /dev/null
+++ b/app/src/main/res/layout/calendar_cell.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/cateory_item.xml b/app/src/main/res/layout/cateory_item.xml
new file mode 100644
index 0000000..308b37a
--- /dev/null
+++ b/app/src/main/res/layout/cateory_item.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/container_layout.xml b/app/src/main/res/layout/container_layout.xml
new file mode 100644
index 0000000..a899f87
--- /dev/null
+++ b/app/src/main/res/layout/container_layout.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/doctor_list_item.xml b/app/src/main/res/layout/doctor_list_item.xml
new file mode 100644
index 0000000..11f649b
--- /dev/null
+++ b/app/src/main/res/layout/doctor_list_item.xml
@@ -0,0 +1,164 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/drawer_header_layout.xml b/app/src/main/res/layout/drawer_header_layout.xml
new file mode 100644
index 0000000..7b7724d
--- /dev/null
+++ b/app/src/main/res/layout/drawer_header_layout.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/drawer_menu_item.xml b/app/src/main/res/layout/drawer_menu_item.xml
new file mode 100644
index 0000000..e36e5ba
--- /dev/null
+++ b/app/src/main/res/layout/drawer_menu_item.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml
new file mode 100644
index 0000000..ee8fb9e
--- /dev/null
+++ b/app/src/main/res/layout/fragment_home.xml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_notification.xml b/app/src/main/res/layout/fragment_notification.xml
new file mode 100644
index 0000000..33f2d02
--- /dev/null
+++ b/app/src/main/res/layout/fragment_notification.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_profile.xml b/app/src/main/res/layout/fragment_profile.xml
new file mode 100644
index 0000000..798225c
--- /dev/null
+++ b/app/src/main/res/layout/fragment_profile.xml
@@ -0,0 +1,334 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml
new file mode 100644
index 0000000..faa78d3
--- /dev/null
+++ b/app/src/main/res/layout/fragment_search.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/notification_item.xml b/app/src/main/res/layout/notification_item.xml
new file mode 100644
index 0000000..7d4f923
--- /dev/null
+++ b/app/src/main/res/layout/notification_item.xml
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/time_item.xml b/app/src/main/res/layout/time_item.xml
new file mode 100644
index 0000000..4cba0d3
--- /dev/null
+++ b/app/src/main/res/layout/time_item.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/viewpager_item.xml b/app/src/main/res/layout/viewpager_item.xml
new file mode 100644
index 0000000..a3fdae0
--- /dev/null
+++ b/app/src/main/res/layout/viewpager_item.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/week_calendar_view.xml b/app/src/main/res/layout/week_calendar_view.xml
new file mode 100644
index 0000000..e8d4974
--- /dev/null
+++ b/app/src/main/res/layout/week_calendar_view.xml
@@ -0,0 +1,180 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/bottom_menu.xml b/app/src/main/res/menu/bottom_menu.xml
new file mode 100644
index 0000000..8fd67cb
--- /dev/null
+++ b/app/src/main/res/menu/bottom_menu.xml
@@ -0,0 +1,28 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..b8c45ed
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..b459f9c
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..aa7759f
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..254027e
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..79484e4
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml
new file mode 100644
index 0000000..ffbad78
--- /dev/null
+++ b/app/src/main/res/navigation/nav_graph.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-night/dimens.xml b/app/src/main/res/values-night/dimens.xml
new file mode 100644
index 0000000..4ab4520
--- /dev/null
+++ b/app/src/main/res/values-night/dimens.xml
@@ -0,0 +1,8 @@
+
+
+ 16dp
+ 16dp
+ 8dp
+ 176dp
+ 16dp
+
\ No newline at end of file
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
new file mode 100644
index 0000000..4b3b92b
--- /dev/null
+++ b/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..7a8ee19
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,21 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #4877df
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
+
+
+ #FFEB3B
+ #E91E63
+
+ #4f5fff
+ #ffb70c
+ #22d562
+ #f2f6fa
+ #B2B7BB
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..955aa30
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,16 @@
+
+ Doctor Care App
+
+ Home Fragment
+ Doctor Care
+
+ Home
+ Home
+ Search
+ Notifications
+ Profile
+ Search Fragment
+ Notification Fragment
+ Profile Fragment
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/style.xml b/app/src/main/res/values/style.xml
new file mode 100644
index 0000000..c314342
--- /dev/null
+++ b/app/src/main/res/values/style.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
new file mode 100644
index 0000000..00ae0a7
--- /dev/null
+++ b/app/src/main/res/values/themes.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/test/java/com/ketub4/mvvmdemowithdi/ExampleUnitTest.kt b/app/src/test/java/com/ketub4/mvvmdemowithdi/ExampleUnitTest.kt
new file mode 100644
index 0000000..735f6bd
--- /dev/null
+++ b/app/src/test/java/com/ketub4/mvvmdemowithdi/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package com.ketub4.mvvmdemowithdi
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..4a38164
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,19 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ repositories {
+ google()
+ mavenCentral()
+ }
+ dependencies {
+ classpath "com.android.tools.build:gradle:7.0.3"
+ classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10'
+ classpath("com.google.dagger:hilt-android-gradle-plugin:2.38.1")
+ classpath 'com.google.gms:google-services:4.3.10'
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..65d0af8
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,22 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
+kapt.use.worker.api=false
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..e708b1c
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..cbd1f7d
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Feb 09 15:05:43 IST 2022
+distributionBase=GRADLE_USER_HOME
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
+distributionPath=wrapper/dists
+zipStorePath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..4f906e0
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/screenshots/1.jpg b/screenshots/1.jpg
new file mode 100644
index 0000000..e0f2921
Binary files /dev/null and b/screenshots/1.jpg differ
diff --git a/screenshots/2.jpg b/screenshots/2.jpg
new file mode 100644
index 0000000..e44ce23
Binary files /dev/null and b/screenshots/2.jpg differ
diff --git a/screenshots/3.jpg b/screenshots/3.jpg
new file mode 100644
index 0000000..f959661
Binary files /dev/null and b/screenshots/3.jpg differ
diff --git a/screenshots/4.jpg b/screenshots/4.jpg
new file mode 100644
index 0000000..1b28b57
Binary files /dev/null and b/screenshots/4.jpg differ
diff --git a/screenshots/5.jpg b/screenshots/5.jpg
new file mode 100644
index 0000000..e4d55a6
Binary files /dev/null and b/screenshots/5.jpg differ
diff --git a/screenshots/6.jpg b/screenshots/6.jpg
new file mode 100644
index 0000000..0d2be30
Binary files /dev/null and b/screenshots/6.jpg differ
diff --git a/screenshots/7.jpg b/screenshots/7.jpg
new file mode 100644
index 0000000..01c516a
Binary files /dev/null and b/screenshots/7.jpg differ
diff --git a/screenshots/8.jpg b/screenshots/8.jpg
new file mode 100644
index 0000000..fba7bd2
Binary files /dev/null and b/screenshots/8.jpg differ
diff --git a/screenshots/9.jpg b/screenshots/9.jpg
new file mode 100644
index 0000000..fff53b7
Binary files /dev/null and b/screenshots/9.jpg differ
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..667f08a
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,10 @@
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ jcenter() // Warning: this repository is going to shut down soon
+ }
+}
+rootProject.name = "MVVMDemoWithDI"
+include ':app'