diff --git a/app/build.gradle b/app/build.gradle
index 9c99d98..fb726a4 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,16 +1,18 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
+ id("org.jetbrains.kotlin.kapt")
+ id("org.jetbrains.kotlin.plugin.serialization")
}
android {
namespace 'ru.otus.basicarchitecture'
- compileSdk 33
+ compileSdk 34
defaultConfig {
applicationId "ru.otus.basicarchitecture"
- minSdk 24
- targetSdk 33
+ minSdk 26
+ targetSdk 34
versionCode 1
versionName "1.0"
@@ -24,20 +26,40 @@ android {
}
}
compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+ buildFeatures {
+ viewBinding true
}
kotlinOptions {
- jvmTarget = '1.8'
+ jvmTarget = '17'
+ }
+ kapt {
+ correctErrorTypes true
}
}
dependencies {
+ implementation("com.google.dagger:dagger:2.48.1")
+ kapt("com.google.dagger:dagger-compiler:2.48.1")
- implementation 'androidx.core:core-ktx:1.8.0'
+ implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+ implementation 'androidx.navigation:navigation-fragment-ktx:2.7.6'
+ implementation 'androidx.navigation:navigation-ui-ktx:2.7.6'
+ implementation("com.squareup.okhttp3:okhttp:4.12.0")
+ implementation("com.squareup.retrofit2:retrofit:2.9.0")
+ implementation("com.squareup.retrofit2:converter-gson:2.9.0")
+ implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
+ implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0")
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.6.1")
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.1")
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
+
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1e81fea..e6f0ec2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,8 +1,9 @@
-
+
+ android:exported="true">
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/App.kt b/app/src/main/java/ru/otus/basicarchitecture/App.kt
new file mode 100644
index 0000000..eea3fb6
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/App.kt
@@ -0,0 +1,12 @@
+package ru.otus.basicarchitecture
+
+import android.app.Application
+import ru.otus.basicarchitecture.DI.MainComponent.ApplicationModule
+import ru.otus.basicarchitecture.DI.MainComponent.DaggerMainComponent
+
+class App : Application() {
+ val component by lazy {
+ DaggerMainComponent.builder()
+ .applicationModule(ApplicationModule(this)).build()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Core/Model/Address.kt b/app/src/main/java/ru/otus/basicarchitecture/Core/Model/Address.kt
new file mode 100644
index 0000000..56fc9fe
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Core/Model/Address.kt
@@ -0,0 +1,5 @@
+package ru.otus.basicarchitecture.Core.Model
+
+data class Address(
+ val address: String
+) : BaseModel
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Core/Model/BaseModel.kt b/app/src/main/java/ru/otus/basicarchitecture/Core/Model/BaseModel.kt
new file mode 100644
index 0000000..c6590e7
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Core/Model/BaseModel.kt
@@ -0,0 +1,3 @@
+package ru.otus.basicarchitecture.Core.Model
+
+sealed interface BaseModel
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Core/Model/DTO/Suggestion.kt b/app/src/main/java/ru/otus/basicarchitecture/Core/Model/DTO/Suggestion.kt
new file mode 100644
index 0000000..fb9d809
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Core/Model/DTO/Suggestion.kt
@@ -0,0 +1,22 @@
+package ru.otus.basicarchitecture.Core.Model.DTO
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class SuggestionRequest(
+ @SerialName("query")
+ val query: String
+)
+
+@Serializable
+data class Suggestions(
+ @SerialName("suggestions")
+ val suggestions: List?
+)
+
+@Serializable
+data class Suggestion(
+ @SerialName("value")
+ val value: String?
+)
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Core/Model/Interests.kt b/app/src/main/java/ru/otus/basicarchitecture/Core/Model/Interests.kt
new file mode 100644
index 0000000..c0b7a78
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Core/Model/Interests.kt
@@ -0,0 +1,5 @@
+package ru.otus.basicarchitecture.Core.Model
+
+data class Interests (
+ var interests: String
+) : BaseModel
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Core/Model/Person.kt b/app/src/main/java/ru/otus/basicarchitecture/Core/Model/Person.kt
new file mode 100644
index 0000000..d7ebfc1
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Core/Model/Person.kt
@@ -0,0 +1,22 @@
+package ru.otus.basicarchitecture.Core.Model
+
+import ru.otus.basicarchitecture.DI.FragmentScope
+
+@FragmentScope
+data class Person(
+ var firstName: String,
+ var surName: String,
+ var dateOfBirth: String
+) : BaseModel {
+ companion object {
+ const val defaultValueProperty = ""
+
+ fun defaultPerson(): Person {
+ return Person(
+ defaultValueProperty,
+ defaultValueProperty,
+ defaultValueProperty
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Core/Model/ViewModelFactory.kt b/app/src/main/java/ru/otus/basicarchitecture/Core/Model/ViewModelFactory.kt
new file mode 100644
index 0000000..a47bf1c
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Core/Model/ViewModelFactory.kt
@@ -0,0 +1,13 @@
+package ru.otus.basicarchitecture.Core.Model
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import javax.inject.Inject
+
+class ViewModelFactory @Inject constructor(
+ private val viewModels: @JvmSuppressWildcards Map
+) : ViewModelProvider.Factory {
+ override fun create(modelClass: Class): T {
+ return viewModels[modelClass.simpleName] as T
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Core/Utils/AppConstant.kt b/app/src/main/java/ru/otus/basicarchitecture/Core/Utils/AppConstant.kt
new file mode 100644
index 0000000..9c7b389
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Core/Utils/AppConstant.kt
@@ -0,0 +1,5 @@
+package ru.otus.basicarchitecture.Core.Utils
+
+object AppConstant {
+ const val API_KEY = "463d2f8b8abd97cf30e7ee538d5e6e6f36242b3e"
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Core/Utils/ErrorService.kt b/app/src/main/java/ru/otus/basicarchitecture/Core/Utils/ErrorService.kt
new file mode 100644
index 0000000..5f2858c
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Core/Utils/ErrorService.kt
@@ -0,0 +1,26 @@
+package ru.otus.basicarchitecture.Core.Utils
+
+import android.app.AlertDialog
+import android.app.Dialog
+import android.content.Context
+import android.content.DialogInterface
+import android.text.SpannableString
+import android.widget.Toast
+import ru.otus.basicarchitecture.R
+import javax.inject.Inject
+
+class ErrorService @Inject constructor() {
+ private var context: Context? = null
+ fun show(message: String) {
+ val title = "Ошибка"
+ if (context!= null) {
+ Toast.makeText(context,message ,Toast.LENGTH_SHORT).show();
+
+ }
+
+ }
+
+ fun setContext(context: Context?) {
+ this.context = context
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Core/Utils/Helper.kt b/app/src/main/java/ru/otus/basicarchitecture/Core/Utils/Helper.kt
new file mode 100644
index 0000000..7d62dea
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Core/Utils/Helper.kt
@@ -0,0 +1,5 @@
+package ru.otus.basicarchitecture.Core.Utils
+
+import android.text.Editable
+
+fun String.toEditable(): Editable = Editable.Factory.getInstance().newEditable(this)
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment1/Fragment1SubComponent.kt b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment1/Fragment1SubComponent.kt
new file mode 100644
index 0000000..29dc82f
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment1/Fragment1SubComponent.kt
@@ -0,0 +1,17 @@
+package ru.otus.basicarchitecture.DI.Fragment1
+
+import dagger.Subcomponent
+import ru.otus.basicarchitecture.DI.FragmentComponents.FirstScreen.PersonModule
+import ru.otus.basicarchitecture.DI.FragmentScope
+import ru.otus.basicarchitecture.Ui.Fragment1.Fragment1
+
+@FragmentScope
+@Subcomponent(modules = [PersonModule::class, Fragment1ViewModelModule::class])
+interface Fragment1SubComponent {
+ @Subcomponent.Builder
+ interface Builder {
+ fun build() : Fragment1SubComponent
+ }
+
+ fun inject(fragment1: Fragment1)
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment1/Fragment1ViewModelModule.kt b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment1/Fragment1ViewModelModule.kt
new file mode 100644
index 0000000..2d4e8f4
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment1/Fragment1ViewModelModule.kt
@@ -0,0 +1,18 @@
+package ru.otus.basicarchitecture.DI.Fragment1
+
+import androidx.lifecycle.ViewModel
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.IntoMap
+import dagger.multibindings.StringKey
+import ru.otus.basicarchitecture.Ui.Fragment1.Fragment1ViewModel
+
+@Module
+interface Fragment1ViewModelModule {
+
+ @IntoMap
+ @StringKey("Fragment1ViewModel")
+ @Binds
+ fun bindFirstScreenViewModel(impl: Fragment1ViewModel): ViewModel
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment1/PersonModule.kt b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment1/PersonModule.kt
new file mode 100644
index 0000000..cb27c5b
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment1/PersonModule.kt
@@ -0,0 +1,17 @@
+package ru.otus.basicarchitecture.DI.FragmentComponents.FirstScreen
+
+import dagger.Module
+import dagger.Provides
+import ru.otus.basicarchitecture.Core.Model.Person
+import ru.otus.basicarchitecture.DI.FragmentScope
+
+
+@Module
+class PersonModule {
+ @FragmentScope
+ @Provides
+ fun providePerson(): Person {
+ return Person.defaultPerson()
+ }
+}
+
diff --git a/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment2/AddressModule.kt b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment2/AddressModule.kt
new file mode 100644
index 0000000..931ba35
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment2/AddressModule.kt
@@ -0,0 +1,14 @@
+package ru.otus.basicarchitecture.DI.Fragment2
+import dagger.Module
+import dagger.Provides
+import ru.otus.basicarchitecture.Core.Model.Address
+import ru.otus.basicarchitecture.DI.FragmentScope
+
+@Module
+class AddressModule {
+ @FragmentScope
+ @Provides
+ fun providesAddress(): Address {
+ return Address("")
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment2/Fragment2SubComponent.kt b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment2/Fragment2SubComponent.kt
new file mode 100644
index 0000000..5cfac3f
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment2/Fragment2SubComponent.kt
@@ -0,0 +1,19 @@
+package ru.otus.basicarchitecture.DI.Fragment2
+
+import android.content.Context
+import dagger.BindsInstance
+import dagger.Subcomponent
+import ru.otus.basicarchitecture.DI.FragmentComponents.FirstScreen.PersonModule
+import ru.otus.basicarchitecture.DI.FragmentScope
+import ru.otus.basicarchitecture.Ui.Fragment1.Fragment2
+
+@FragmentScope
+@Subcomponent(modules = [AddressModule::class, Fragment2ViewModelModule::class])
+interface Fragment2SubComponent {
+ @Subcomponent.Builder
+ interface Builder {
+ fun build() : Fragment2SubComponent
+ }
+
+ fun inject(fragment2: Fragment2)
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment2/Fragment2ViewModelModule.kt b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment2/Fragment2ViewModelModule.kt
new file mode 100644
index 0000000..9cbe3ff
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment2/Fragment2ViewModelModule.kt
@@ -0,0 +1,16 @@
+package ru.otus.basicarchitecture.DI.Fragment2
+import androidx.lifecycle.ViewModel
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.IntoMap
+import dagger.multibindings.StringKey
+import ru.otus.basicarchitecture.Ui.Fragment1.Fragment2ViewModel
+
+@Module
+interface Fragment2ViewModelModule {
+ @IntoMap
+ @StringKey("Fragment2ViewModel")
+ @Binds
+ fun bindSecondScreenViewModel(impl: Fragment2ViewModel): ViewModel
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment3/Fragment3SubComponent.kt b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment3/Fragment3SubComponent.kt
new file mode 100644
index 0000000..77c0dd9
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment3/Fragment3SubComponent.kt
@@ -0,0 +1,19 @@
+package ru.otus.basicarchitecture.DI.Fragment3
+
+import dagger.Subcomponent
+import ru.otus.basicarchitecture.DI.FragmentScope
+import ru.otus.basicarchitecture.Ui.Fragment3.Fragment3
+
+@FragmentScope
+@Subcomponent(modules = [Fragment3ViewModelModule::class])
+interface Fragment3SubComponent {
+
+ @Subcomponent.Builder
+ interface Builder {
+ fun build() : Fragment3SubComponent
+ }
+
+ fun inject(fragmentThird: Fragment3)
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment3/Fragment3ViewModelModule.kt b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment3/Fragment3ViewModelModule.kt
new file mode 100644
index 0000000..0e704b9
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment3/Fragment3ViewModelModule.kt
@@ -0,0 +1,18 @@
+package ru.otus.basicarchitecture.DI.Fragment3
+
+import androidx.lifecycle.ViewModel
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.IntoMap
+import dagger.multibindings.StringKey
+import ru.otus.basicarchitecture.Ui.Fragment3.Fragment3ViewModel
+
+@Module
+interface Fragment3ViewModelModule {
+
+ @IntoMap
+ @StringKey("Fragment3ViewModel")
+ @Binds
+ fun bindThirdScreenViewModel(impl: Fragment3ViewModel): ViewModel
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment4/Fragment4SubComponent.kt b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment4/Fragment4SubComponent.kt
new file mode 100644
index 0000000..e86eb8a
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment4/Fragment4SubComponent.kt
@@ -0,0 +1,19 @@
+package ru.otus.basicarchitecture.DI.FragmentComponents.Fragment4
+
+import dagger.Subcomponent
+import ru.otus.basicarchitecture.DI.FragmentScope
+import ru.otus.basicarchitecture.Ui.Fragment4.Fragment4
+
+@FragmentScope
+@Subcomponent(modules = [Fragment4ViewModelModule::class])
+interface Fragment4SubComponent {
+
+
+ @Subcomponent.Builder
+ interface Builder {
+ fun build() : Fragment4SubComponent
+ }
+
+ fun inject(fragment: Fragment4)
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment4/Fragment4ViewModelModule.kt b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment4/Fragment4ViewModelModule.kt
new file mode 100644
index 0000000..3a65868
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/DI/Fragment4/Fragment4ViewModelModule.kt
@@ -0,0 +1,18 @@
+package ru.otus.basicarchitecture.DI.FragmentComponents.Fragment4
+
+import androidx.lifecycle.ViewModel
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.IntoMap
+import dagger.multibindings.StringKey
+import ru.otus.basicarchitecture.Ui.Fragment4.Fragment4ViewModel
+
+
+@Module
+interface Fragment4ViewModelModule {
+
+ @IntoMap
+ @StringKey("Fragment4ViewModel")
+ @Binds
+ fun bindFourthScreenViewModel(impl: Fragment4ViewModel): ViewModel
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/DI/FragmentScope.kt b/app/src/main/java/ru/otus/basicarchitecture/DI/FragmentScope.kt
new file mode 100644
index 0000000..8141879
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/DI/FragmentScope.kt
@@ -0,0 +1,7 @@
+package ru.otus.basicarchitecture.DI
+
+import javax.inject.Scope
+
+@Scope
+@Retention(value = AnnotationRetention.RUNTIME)
+annotation class FragmentScope()
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/DI/MainComponent/ApplicationModule.kt b/app/src/main/java/ru/otus/basicarchitecture/DI/MainComponent/ApplicationModule.kt
new file mode 100644
index 0000000..d803a78
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/DI/MainComponent/ApplicationModule.kt
@@ -0,0 +1,75 @@
+package ru.otus.basicarchitecture.DI.MainComponent
+
+import android.content.Context
+import android.util.Log
+import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
+import dagger.Module
+import dagger.Provides
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.json.Json
+import me.amitshekhar.mvvm.di.ApplicationContext
+import me.amitshekhar.mvvm.di.BaseUrl
+import okhttp3.Interceptor
+import okhttp3.MediaType.Companion.toMediaType
+import okhttp3.OkHttpClient
+import okhttp3.logging.HttpLoggingInterceptor
+import retrofit2.Retrofit
+import retrofit2.converter.gson.GsonConverterFactory
+import ru.otus.basicarchitecture.App
+import ru.otus.basicarchitecture.Core.Utils.AppConstant
+import ru.otus.basicarchitecture.R
+import ru.otus.basicarchitecture.data.NetworkService
+import java.util.concurrent.TimeUnit
+import javax.inject.Singleton
+
+@Module
+class ApplicationModule(private val application: App) {
+
+ @ApplicationContext
+ @Provides
+ fun provideContext(): Context {
+ return application
+ }
+
+ @BaseUrl
+ @Provides
+ fun provideBaseUrl(): String = "http://suggestions.dadata.ru/"
+
+ @Provides
+ @Singleton
+ fun provideNetworkService(
+ @BaseUrl baseUrl: String): NetworkService {
+ val loggingInterceptor = HttpLoggingInterceptor { message ->
+ Log.d("Server", message)
+ }.apply {
+ level = HttpLoggingInterceptor.Level.BODY
+ }
+
+ val token = application.getString(R.string.dadata_api_key)
+ val okHttp = OkHttpClient.Builder()
+ .connectTimeout(60, TimeUnit.SECONDS)
+ .readTimeout(60, TimeUnit.SECONDS)
+ .writeTimeout(60, TimeUnit.SECONDS)
+ .addInterceptor(loggingInterceptor)
+ .addInterceptor(Interceptor { chain ->
+ chain.proceed(
+ chain.request().newBuilder()
+ .header("Content-Type", "application/json")
+ .header("Accept", "application/json")
+ .header(
+ "Authorization",
+ "Token ${token}")
+ .build())
+ })
+ .build()
+ val contentType = "application/json".toMediaType()
+ return Retrofit.Builder()
+ .baseUrl(baseUrl)
+ .client(okHttp)
+ .addConverterFactory(Json{ignoreUnknownKeys = true}.asConverterFactory(contentType))
+ .build()
+ .create(NetworkService::class.java)
+
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/DI/MainComponent/MainComponent.kt b/app/src/main/java/ru/otus/basicarchitecture/DI/MainComponent/MainComponent.kt
new file mode 100644
index 0000000..52987f9
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/DI/MainComponent/MainComponent.kt
@@ -0,0 +1,31 @@
+package ru.otus.basicarchitecture.DI.MainComponent
+
+import android.content.Context
+import dagger.Component
+import me.amitshekhar.mvvm.di.ApplicationContext
+import ru.otus.basicarchitecture.DI.Fragment1.Fragment1SubComponent
+import ru.otus.basicarchitecture.DI.Fragment2.Fragment2SubComponent
+import ru.otus.basicarchitecture.DI.Fragment3.Fragment3SubComponent
+import ru.otus.basicarchitecture.DI.FragmentComponents.Fragment4.Fragment4SubComponent
+import ru.otus.basicarchitecture.Domain.Repository
+import ru.otus.basicarchitecture.data.NetworkService
+import ru.otus.basicarchitecture.data.WizardCache
+import javax.inject.Singleton
+
+@Singleton
+@Component(modules = [WizardCacheModule::class, RepositoryModule::class, ApplicationModule::class])
+interface MainComponent {
+ fun fragment1SubComponent() : Fragment1SubComponent.Builder
+ fun fragment2SubComponent() : Fragment2SubComponent.Builder
+ fun fragment3SubComponent() : Fragment3SubComponent.Builder
+ fun fragment4SubComponent() : Fragment4SubComponent.Builder
+
+ fun wizardCache(): WizardCache
+
+ fun repository(): Repository
+
+ @ApplicationContext
+ fun getContext(): Context
+
+ fun getNetworkService(): NetworkService
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/DI/MainComponent/RepositoryModule.kt b/app/src/main/java/ru/otus/basicarchitecture/DI/MainComponent/RepositoryModule.kt
new file mode 100644
index 0000000..0c5e0df
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/DI/MainComponent/RepositoryModule.kt
@@ -0,0 +1,14 @@
+package ru.otus.basicarchitecture.DI.MainComponent
+
+import dagger.Binds
+import dagger.Module
+import ru.otus.basicarchitecture.data.RepositoryImpl
+import ru.otus.basicarchitecture.Domain.Repository
+import javax.inject.Singleton
+
+@Module
+interface RepositoryModule {
+ @Singleton
+ @Binds
+ fun getRepository(impl: RepositoryImpl) : Repository
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/DI/MainComponent/WizardCacheModule.kt b/app/src/main/java/ru/otus/basicarchitecture/DI/MainComponent/WizardCacheModule.kt
new file mode 100644
index 0000000..c7f2597
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/DI/MainComponent/WizardCacheModule.kt
@@ -0,0 +1,21 @@
+package ru.otus.basicarchitecture.DI.MainComponent
+
+import dagger.Module
+import dagger.Provides
+import ru.otus.basicarchitecture.data.WizardCache
+import javax.inject.Singleton
+
+@Module
+class WizardCacheModule {
+ @Singleton
+ @Provides
+ fun provideWizardCache() : WizardCache{
+ return WizardCache(
+ "",
+ "",
+ "",
+ "",
+ ""
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/DI/qualifiers.kt b/app/src/main/java/ru/otus/basicarchitecture/DI/qualifiers.kt
new file mode 100644
index 0000000..0781c3d
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/DI/qualifiers.kt
@@ -0,0 +1,15 @@
+package me.amitshekhar.mvvm.di
+
+import javax.inject.Qualifier
+
+@Qualifier
+@Retention(AnnotationRetention.BINARY)
+annotation class ApplicationContext
+
+@Qualifier
+@Retention(AnnotationRetention.BINARY)
+annotation class ActivityContext
+
+@Qualifier
+@Retention(AnnotationRetention.BINARY)
+annotation class BaseUrl
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Domain/Data/AddressUseCase.kt b/app/src/main/java/ru/otus/basicarchitecture/Domain/Data/AddressUseCase.kt
new file mode 100644
index 0000000..ca68e78
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Domain/Data/AddressUseCase.kt
@@ -0,0 +1,13 @@
+package ru.otus.basicarchitecture.Domain.Data
+
+import ru.otus.basicarchitecture.Core.Model.Address
+import ru.otus.basicarchitecture.Domain.Repository
+import javax.inject.Inject
+
+class AddressUseCase @Inject constructor(
+ private val repository: Repository
+) {
+ fun setAddress(address: Address){
+ repository.setAddress(address)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Domain/Data/InterestsUseCase.kt b/app/src/main/java/ru/otus/basicarchitecture/Domain/Data/InterestsUseCase.kt
new file mode 100644
index 0000000..b9a20e6
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Domain/Data/InterestsUseCase.kt
@@ -0,0 +1,17 @@
+package ru.otus.basicarchitecture.Domain.Data
+
+import ru.otus.basicarchitecture.Core.Model.Interests
+import ru.otus.basicarchitecture.Domain.Repository
+import javax.inject.Inject
+
+class InterestsUseCase @Inject constructor(
+ private val repository: Repository
+) {
+ fun setInterests(interests: Interests){
+ repository.setInterests(interests)
+ }
+
+ fun getList(): List{
+ return repository.getListInterests()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Domain/Data/PersonUseCase.kt b/app/src/main/java/ru/otus/basicarchitecture/Domain/Data/PersonUseCase.kt
new file mode 100644
index 0000000..6173731
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Domain/Data/PersonUseCase.kt
@@ -0,0 +1,22 @@
+package ru.otus.basicarchitecture.Domain.Data
+
+import ru.otus.basicarchitecture.Core.Model.BaseModel
+import ru.otus.basicarchitecture.Core.Model.Person
+import ru.otus.basicarchitecture.Domain.Repository
+import javax.inject.Inject
+
+class PersonUseCase @Inject constructor(
+ private val repository: Repository
+) {
+ fun setPerson(person: Person) {
+ repository.setPerson(person)
+ }
+
+ fun getList(): List{
+ return repository.getListInterests()
+ }
+
+ fun getPerson(): Map {
+ return repository.getInfoPersonUseCase()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Domain/Repository.kt b/app/src/main/java/ru/otus/basicarchitecture/Domain/Repository.kt
new file mode 100644
index 0000000..0c3d604
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Domain/Repository.kt
@@ -0,0 +1,14 @@
+package ru.otus.basicarchitecture.Domain
+
+import ru.otus.basicarchitecture.Core.Model.Address
+import ru.otus.basicarchitecture.Core.Model.BaseModel
+import ru.otus.basicarchitecture.Core.Model.Interests
+import ru.otus.basicarchitecture.Core.Model.Person
+
+interface Repository {
+ fun setPerson(person: Person)
+ fun getInfoPersonUseCase() : Map
+ fun setAddress(address: Address)
+ fun setInterests(interests: Interests)
+ fun getListInterests(): List
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/MainActivity.kt b/app/src/main/java/ru/otus/basicarchitecture/MainActivity.kt
index 623aba9..ae320ee 100644
--- a/app/src/main/java/ru/otus/basicarchitecture/MainActivity.kt
+++ b/app/src/main/java/ru/otus/basicarchitecture/MainActivity.kt
@@ -1,11 +1,23 @@
package ru.otus.basicarchitecture
-import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import ru.otus.basicarchitecture.Ui.Fragment1.Fragment1
+import ru.otus.basicarchitecture.Ui.Fragment1.Fragment2
+
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
+
+ if(savedInstanceState == null ){
+ val fragment = Fragment2()
+ supportFragmentManager
+ .beginTransaction()
+ .replace(R.id.fragmentContainer, fragment)
+ .addToBackStack(null)
+ .commit()
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Network/Endpoints.kt b/app/src/main/java/ru/otus/basicarchitecture/Network/Endpoints.kt
new file mode 100644
index 0000000..ba1403f
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Network/Endpoints.kt
@@ -0,0 +1,5 @@
+package ru.otus.basicarchitecture.Network
+
+object Endpoints {
+ const val address = "suggestions/api/4_1/rs/suggest/address/"
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Network/NetworkService.kt b/app/src/main/java/ru/otus/basicarchitecture/Network/NetworkService.kt
new file mode 100644
index 0000000..a973b5f
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Network/NetworkService.kt
@@ -0,0 +1,21 @@
+package ru.otus.basicarchitecture.data
+
+
+import retrofit2.Response
+import retrofit2.http.Body
+import retrofit2.http.GET
+import retrofit2.http.Headers
+import retrofit2.http.POST
+import retrofit2.http.Query
+import ru.otus.basicarchitecture.Core.Model.DTO.SuggestionRequest
+import ru.otus.basicarchitecture.Core.Model.DTO.Suggestions
+import ru.otus.basicarchitecture.Core.Model.Person
+import ru.otus.basicarchitecture.Core.Utils.AppConstant
+import ru.otus.basicarchitecture.Network.Endpoints
+import javax.inject.Singleton
+
+@Singleton
+interface NetworkService {
+ @POST(Endpoints.address)
+ suspend fun getAddress(@Body body: SuggestionRequest): Response
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment1/Fragment1.kt b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment1/Fragment1.kt
new file mode 100644
index 0000000..05ed3b2
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment1/Fragment1.kt
@@ -0,0 +1,137 @@
+package ru.otus.basicarchitecture.Ui.Fragment1
+
+import android.app.DatePickerDialog
+import android.content.Context
+import android.os.Bundle
+import android.text.InputType
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.core.content.ContextCompat
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import ru.otus.basicarchitecture.App
+import ru.otus.basicarchitecture.Core.Model.ViewModelFactory
+import ru.otus.basicarchitecture.R
+import ru.otus.basicarchitecture.databinding.Fragment1Binding
+import java.util.Calendar
+import java.util.Locale
+import javax.inject.Inject
+
+class Fragment1: Fragment() {
+ private lateinit var binding: Fragment1Binding
+ @Inject
+ lateinit var viewModelFactory: ViewModelFactory
+ private val MESSAGE_TOAST_INCORRECT_AGE ="Возраст пользователя не может быть меньше 18"
+
+ private val viewModel by lazy {
+ ViewModelProvider(this, viewModelFactory)[Fragment1ViewModel::class.java]
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ binding = Fragment1Binding.inflate(inflater, container, false)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ (requireActivity().application as App).component
+ .fragment1SubComponent()
+ .build()
+ .inject(this)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ setupView()
+ }
+
+ private fun setupView() {
+ binding.birthInputLayout.apply {
+ startIconDrawable = ContextCompat.getDrawable(context, R.drawable.calendar)
+ startIconContentDescription = context.getString(R.string.DateOfBirthHint)
+ }
+ binding.birthEditText.apply {
+ inputType = InputType.TYPE_NULL
+ // isEnabled = false
+ isCursorVisible = false
+ keyListener = null
+
+ onFocusChangeListener = View.OnFocusChangeListener { view, hasFocus ->
+ if (hasFocus) {
+ showDatePicker(view.context)
+ }else{
+ viewModel.validateEmptyValue()
+ }
+ this.clearFocus()
+ }
+
+ }
+ setFocusListener()
+
+ binding.nextButton.let { button ->
+ viewModel.enabledButtonLiveData.observe(viewLifecycleOwner) {
+ button.isEnabled = it
+ }
+ }
+
+ binding.nextButton.setOnClickListener {
+ viewModel.setData(
+ binding.firstNameEditText.text.toString(),
+ binding.surNameEditText.text.toString(),
+ binding.birthEditText.text.toString()
+ ) { openSecondFragment() }
+ }
+ }
+
+
+ private fun setFocusListener(){
+ val lossFocus = View.OnFocusChangeListener{_,hasFocus ->
+ if(!hasFocus){
+ viewModel.validateEmptyValue()
+ }
+ }
+ binding.firstNameEditText.onFocusChangeListener = lossFocus
+ binding.surNameEditText.onFocusChangeListener = lossFocus
+
+ }
+
+ private fun openSecondFragment() {
+ val fragment = Fragment2()
+ parentFragmentManager
+ .beginTransaction()
+ .replace(R.id.fragmentContainer, fragment)
+ .addToBackStack(null)
+ .commit()
+ }
+
+ // возможно надо перенести внутрь ViewModel
+ private fun showDatePicker(context: Context) {
+ val currentDate = Calendar.getInstance()
+ val datePicker = DatePickerDialog(
+ context,
+ { _, year, month, day ->
+ val selectedData =
+ String.format(Locale.getDefault(), "%04d-%02d-%02d", year, month + 1, day)
+ viewModel.validData(day, month, year,
+ { showToast(MESSAGE_TOAST_INCORRECT_AGE, context) }
+ )
+ binding.birthEditText.setText(selectedData)
+ },
+ currentDate.get(Calendar.YEAR),
+ currentDate.get(Calendar.MONTH),
+ currentDate.get(Calendar.DAY_OF_MONTH)
+ )
+ datePicker.show()
+ }
+
+
+
+
+ private fun showToast(message: String, context: Context) {
+ Toast.makeText(context, message, Toast.LENGTH_LONG).show()
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment1/Fragment1ViewModel.kt b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment1/Fragment1ViewModel.kt
new file mode 100644
index 0000000..b73124f
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment1/Fragment1ViewModel.kt
@@ -0,0 +1,75 @@
+package ru.otus.basicarchitecture.Ui.Fragment1
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import ru.otus.basicarchitecture.Core.Model.Person
+import ru.otus.basicarchitecture.Domain.Data.PersonUseCase
+import java.time.LocalDate
+import java.time.format.DateTimeFormatter
+import java.time.temporal.ChronoUnit
+import javax.inject.Inject
+
+class Fragment1ViewModel @Inject constructor(
+ val personUseCase: PersonUseCase
+) : ViewModel() {
+ private val enabledButtonMutableLiveData = MutableLiveData()
+ val enabledButtonLiveData = enabledButtonMutableLiveData
+
+ private var name = DEFFAULT_VALUE
+ private var surName = DEFFAULT_VALUE
+ private var birthDate = DEFFAULT_VALUE
+
+
+ init {
+ enabledButtonMutableLiveData.postValue(false)
+ }
+
+ fun setData(name: String?, surName: String?, birthDate: String?, openFragment: () -> Unit) {
+ this.name = name ?: DEFFAULT_VALUE
+ this.surName = surName ?: DEFFAULT_VALUE
+ this.birthDate = birthDate ?: DEFFAULT_VALUE
+ if(validateEmptyValue()){
+ val person = Person(this.name, this.surName, this.birthDate)
+ personUseCase.setPerson(person)
+ openFragment.invoke()
+ }
+ }
+
+ fun validateEmptyValue(): Boolean {
+ return if (name.isEmpty() || surName.isEmpty() || birthDate.isEmpty()) {
+ enabledButtonMutableLiveData.postValue(false)
+ false
+ } else {
+ enabledButtonMutableLiveData.postValue(true)
+ true
+ }
+ }
+
+ fun validData(day: Int, month: Int, year: Int, showToast: () -> Unit) {
+ val correctAge = 18
+ val currentDate = LocalDate.now()
+ val monthText = if (month < 9) "0${month + 1}" else "${month + 1}"
+ val dayText = if (day<10) "0${day+1}" else "$day"
+ val selectedDateValue = LocalDate.parse("$year-$monthText-$dayText", DateTimeFormatter.ISO_DATE)
+ val diff = ChronoUnit.YEARS.between(selectedDateValue, currentDate)
+ if (diff < correctAge) {
+ setupFalseButton(showToast)
+ } else {
+ enabledButtonLiveData.postValue(true)
+ }
+ }
+
+ private fun setupFalseButton(showToast: () -> Unit) {
+ enabledButtonMutableLiveData.postValue(false)
+ showToast.invoke()
+ }
+
+ fun enabledButton(){
+ enabledButtonMutableLiveData.postValue(true)
+ }
+
+
+ companion object {
+ private val DEFFAULT_VALUE = ""
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment2/Fragment2.kt b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment2/Fragment2.kt
new file mode 100644
index 0000000..eff81fd
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment2/Fragment2.kt
@@ -0,0 +1,123 @@
+package ru.otus.basicarchitecture.Ui.Fragment1
+
+import android.os.Bundle
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.core.widget.doAfterTextChanged
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import ru.otus.basicarchitecture.App
+import ru.otus.basicarchitecture.Core.Model.DTO.Suggestion
+import ru.otus.basicarchitecture.Core.Model.ViewModelFactory
+import ru.otus.basicarchitecture.Core.Utils.toEditable
+import ru.otus.basicarchitecture.R
+import ru.otus.basicarchitecture.Ui.Fragment2.Fragment2Adapter
+import ru.otus.basicarchitecture.Ui.Fragment2.OnItemClickListener
+import ru.otus.basicarchitecture.Ui.Fragment3.Fragment3
+import ru.otus.basicarchitecture.databinding.Fragment2Binding
+import javax.inject.Inject
+
+class Fragment2: Fragment() {
+ private lateinit var binding: Fragment2Binding
+ @Inject
+ lateinit var viewModelFactory: ViewModelFactory
+ lateinit var adapter: Fragment2Adapter
+
+ private val viewModel by lazy {
+ ViewModelProvider(this, viewModelFactory)[Fragment2ViewModel::class.java]
+ }
+
+
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ binding = Fragment2Binding.inflate(inflater, container, false)
+ return binding.root
+ }
+
+
+ override fun onResume() {
+ super.onResume()
+ setupView()
+ }
+
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ (requireActivity().application as App).component
+ .fragment2SubComponent()
+ .build()
+ .inject(this)
+
+ viewModel.errorService.setContext(requireContext())
+ setupView()
+ }
+
+ private fun setupView() {
+ binding.nextButton.let { button ->
+ setListeners()
+ viewModel.enabledButtonLiveData.observe(viewLifecycleOwner) {
+ button.isEnabled = it
+ }
+ }
+
+
+ binding.addressField.doAfterTextChanged {
+ val context = requireContext()
+ viewModel.loadSuggestions(input = it.toString())
+ }
+
+ viewModel.suggestionsLiveData.observe(viewLifecycleOwner) {
+ Log.d("Server", "Size=" + it.size.toString())
+ adapter.addList(it)
+ }
+
+ viewModel.showProgress.observe(viewLifecycleOwner) {
+ if(it) {
+ binding.progressBar.visibility = View.VISIBLE
+ } else {
+ binding.progressBar.visibility = View.GONE
+ }
+ }
+
+ configureRecycler()
+ setFocusListener()
+ }
+
+ fun configureRecycler() {
+ adapter = Fragment2Adapter(listener = object : OnItemClickListener {
+ override fun onItemClick(item: Suggestion?) {
+ item?.value?.let { viewModel.setQuery(it) }
+ binding.addressField.text = item?.value?.toEditable()
+ }
+ })
+ binding.recyclerAddress.adapter = adapter
+ }
+
+ private fun setListeners() {
+ binding.nextButton.setOnClickListener {
+ viewModel.setData(
+ binding.addressField.text.toString()
+ ) { openFragment() }
+ }
+ }
+
+
+ private fun openFragment() {
+ val fragment = Fragment3()
+ parentFragmentManager
+ .beginTransaction()
+ .replace(R.id.fragmentContainer, fragment)
+ .addToBackStack(null)
+ .commit()
+ }
+
+ private fun setFocusListener() {
+ val lossFocus = View.OnFocusChangeListener { _, hasFocus ->
+ if (hasFocus) viewModel.buttonEnabled()
+ }
+
+ binding.addressField.onFocusChangeListener = lossFocus
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment2/Fragment2Adapter.kt b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment2/Fragment2Adapter.kt
new file mode 100644
index 0000000..e7aff06
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment2/Fragment2Adapter.kt
@@ -0,0 +1,49 @@
+package ru.otus.basicarchitecture.Ui.Fragment2
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import ru.otus.basicarchitecture.Core.Model.DTO.Suggestion
+import ru.otus.basicarchitecture.databinding.AddressLayoutBinding
+
+
+interface OnItemClickListener {
+ fun onItemClick(item: Suggestion?)
+}
+
+class Fragment2Adapter(private val listener: OnItemClickListener): RecyclerView.Adapter() {
+ private var items: MutableList = mutableListOf()
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AddressItemViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ val binding = AddressLayoutBinding.inflate(inflater, parent, false)
+ return AddressItemViewHolder(binding)
+ }
+
+ override fun onBindViewHolder(holder: AddressItemViewHolder, position: Int) {
+ holder.bind(items[position])
+ holder.itemView.setOnClickListener {
+ listener.onItemClick(items[position])
+ }
+ }
+
+ override fun getItemCount(): Int {
+ return items.size
+ }
+
+ fun setList(list: List) {
+ items.clear()
+ addList(list)
+ }
+
+ fun addList(list: List) {
+ items.addAll(list)
+ notifyDataSetChanged()
+ }
+
+ inner class AddressItemViewHolder(private val binding: AddressLayoutBinding) : RecyclerView.ViewHolder(binding.root) {
+ fun bind(item: Suggestion) {
+ binding.name.text = item.value
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment2/Fragment2ViewModel.kt b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment2/Fragment2ViewModel.kt
new file mode 100644
index 0000000..2ed62d0
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment2/Fragment2ViewModel.kt
@@ -0,0 +1,109 @@
+package ru.otus.basicarchitecture.Ui.Fragment1
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import ru.otus.basicarchitecture.Core.Model.Address
+import ru.otus.basicarchitecture.Domain.Data.AddressUseCase
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import retrofit2.http.Query
+import ru.otus.basicarchitecture.Core.Model.DTO.Suggestion
+import ru.otus.basicarchitecture.Core.Utils.ErrorService
+import ru.otus.basicarchitecture.data.AddressImpl
+import javax.inject.Inject
+
+class Fragment2ViewModel @Inject constructor (
+ private val addressUseCase: AddressUseCase,
+ private val repository: AddressImpl,
+ public val errorService: ErrorService
+) : ViewModel() {
+
+ private var prevQuery = ""
+ private val enabledButtonMutableLiveData = MutableLiveData()
+ val enabledButtonLiveData = enabledButtonMutableLiveData
+
+ private val mSuggestionsMutableLiveData = MutableLiveData>()
+ val suggestionsLiveData = mSuggestionsMutableLiveData
+
+ private val mShowProgress = MutableLiveData()
+ val showProgress = mShowProgress
+
+
+ private val UNKNOWN_VALUE = ""
+ private var country: String = UNKNOWN_VALUE
+ private var city: String = UNKNOWN_VALUE
+ private var address: String = UNKNOWN_VALUE
+
+ private var loadingSuggestionsTask: Job = Job()
+
+
+ init {
+ enabledButtonMutableLiveData.postValue(true)
+ }
+
+ fun setData(address: String?, openFragment: () -> Unit){
+ this.address = address ?: UNKNOWN_VALUE
+ if(validateEmptyValue(this.address)) {
+ val addres = Address(this.address)
+ addressUseCase.setAddress(addres)
+ openFragment.invoke()
+ }
+ }
+
+ fun validateEmptyValue(address: String): Boolean {
+ return if (address.isEmpty()) {
+ enabledButtonMutableLiveData.postValue(false)
+ false
+ } else {
+ enabledButtonMutableLiveData.postValue(true)
+ true
+ }
+ }
+
+ fun buttonEnabled(){
+ enabledButtonMutableLiveData.postValue(true)
+ }
+
+
+ fun loadSuggestions(input: String) {
+ if (input == prevQuery) {
+ return
+ }
+ prevQuery = input
+
+ loadingSuggestionsTask.cancel()
+ mShowProgress.value = true
+ loadingSuggestionsTask = viewModelScope.launch {
+ delay(2000)
+ try {
+ withContext(Dispatchers.IO) { repository.getSuggestions(input) }
+ .takeIf { it.isSuccess }
+ ?.let {
+ mShowProgress.value = false
+ mSuggestionsMutableLiveData.value =
+ it.getOrNull()
+ ?.suggestions
+ ?.filter { s -> s.value != input }
+ ?.mapNotNull { s -> s.value?.let { v -> Suggestion(v) } }
+ ?: emptyList()
+ } ?: let {
+ mShowProgress.value = false
+ errorService.show("Ошибка загрузки")
+
+ }
+ } catch (t: Throwable) {
+ mShowProgress.value = false
+
+ }
+ }
+ }
+
+ fun setQuery(query: String) {
+ prevQuery = query
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment3/Fragment3.kt b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment3/Fragment3.kt
new file mode 100644
index 0000000..463ac13
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment3/Fragment3.kt
@@ -0,0 +1,82 @@
+package ru.otus.basicarchitecture.Ui.Fragment3
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import androidx.recyclerview.widget.GridLayoutManager
+import ru.otus.basicarchitecture.App
+import ru.otus.basicarchitecture.Core.Model.ViewModelFactory
+import ru.otus.basicarchitecture.R
+import ru.otus.basicarchitecture.Ui.Fragment4.Fragment4
+import ru.otus.basicarchitecture.databinding.Fragment3Binding
+import javax.inject.Inject
+
+class Fragment3: Fragment() {
+ private lateinit var binding: Fragment3Binding
+ @Inject
+ lateinit var viewModelFactory: ViewModelFactory
+
+ private lateinit var adapter: InterestsAdapter
+
+ private val viewModel by lazy {
+ ViewModelProvider(this, viewModelFactory)[Fragment3ViewModel::class.java]
+ }
+
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ binding = Fragment3Binding.inflate(inflater, container, false)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ (requireActivity().application as App).component
+ .fragment3SubComponent()
+ .build()
+ .inject(this)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ view?.let { setupRV(it) }
+ setupView()
+
+
+ }
+
+ fun setupView() {
+ binding.nextButton.setOnClickListener {
+ viewModel.setData {
+ openFourthFragment()
+ }
+ }
+
+ viewModel.listInterestsLD.observe(viewLifecycleOwner) {
+ adapter.interestsList = it
+ }
+ }
+
+ private fun openFourthFragment() {
+ val fragment = Fragment4()
+ parentFragmentManager
+ .beginTransaction()
+ .replace(R.id.fragmentContainer, fragment)
+ .addToBackStack(null)
+ .commit()
+ }
+
+ private fun setupRV(view: View) {
+ adapter = InterestsAdapter()
+ val layoutManager = GridLayoutManager(view.context,3)
+ binding.recyclerView.adapter = adapter
+ binding.recyclerView.layoutManager = layoutManager
+
+ adapter.onClickListener = {
+ viewModel.changeEnabledState(it)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment3/Fragment3ViewModel.kt b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment3/Fragment3ViewModel.kt
new file mode 100644
index 0000000..8efa961
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment3/Fragment3ViewModel.kt
@@ -0,0 +1,61 @@
+package ru.otus.basicarchitecture.Ui.Fragment3
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import ru.otus.basicarchitecture.Core.Model.Interests
+import ru.otus.basicarchitecture.Domain.Data.InterestsUseCase
+import ru.otus.basicarchitecture.presentation.Fragment3.ModelInterestsForView
+import javax.inject.Inject
+
+class Fragment3ViewModel @Inject constructor(
+ private val interestsUseCase: InterestsUseCase
+) : ViewModel() {
+
+ private val saveInterests = mutableListOf()
+
+ private val mutableListAllInterests = sortedSetOf(
+ { o1, o2 -> o1.id.compareTo(o2.id) }
+ )
+ private val _listInterestsLD = MutableLiveData>()
+
+ val listInterestsLD: LiveData> = _listInterestsLD
+
+ init {
+ val aa = interestsUseCase.getList()
+ for (a in aa.indices) {
+ val model = ModelInterestsForView(a, aa[a], false)
+ mutableListAllInterests.add(model)
+ }
+ _listInterestsLD.postValue(mutableListAllInterests.toList())
+ }
+
+ fun setData(openFragment: () -> Unit){
+
+ val list = mutableListOf()
+ saveInterests.forEach {
+ list.add(it.interests)
+ }
+ interestsUseCase.setInterests(
+ Interests(list.joinToString())
+ )
+ openFragment.invoke()
+ }
+
+ fun changeEnabledState(model: ModelInterestsForView) {
+ val newModel = model.copy(enabled = !model.enabled)
+ mutableListAllInterests.remove(model)
+ mutableListAllInterests.add(newModel)
+ if(newModel.enabled){
+ saveInterests.add(newModel)
+ }else{
+ saveInterests.remove(newModel)
+ }
+ updateList()
+ }
+
+ private fun updateList() {
+ _listInterestsLD.postValue(mutableListAllInterests.toList())
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment3/InterestsAdapter.kt b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment3/InterestsAdapter.kt
new file mode 100644
index 0000000..7cc9927
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment3/InterestsAdapter.kt
@@ -0,0 +1,55 @@
+package ru.otus.basicarchitecture.Ui.Fragment3
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.RecyclerView
+import ru.otus.basicarchitecture.R
+import ru.otus.basicarchitecture.presentation.Fragment3.InterestsDiffUtil
+import ru.otus.basicarchitecture.presentation.Fragment3.InterestsViewHolder
+import ru.otus.basicarchitecture.presentation.Fragment3.ModelInterestsForView
+
+class InterestsAdapter: RecyclerView.Adapter() {
+
+ var onClickListener: ((ModelInterestsForView) -> Unit)? = null
+
+ var interestsList = listOf()
+ set(value){
+ val callback = InterestsDiffUtil(interestsList, value)
+ val diffResult = DiffUtil.calculateDiff(callback)
+ diffResult.dispatchUpdatesTo(this)
+ field = value
+ }
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): InterestsViewHolder {
+
+ val layout = when (viewType) {
+ DISABLED_VIEW -> R.layout.interests_disabled
+ ENABLED_VIEW -> R.layout.interests_enabled
+ else -> throw RuntimeException("Unknown view type: $viewType")
+ }
+ val view = LayoutInflater.from(parent.context).inflate(layout, parent, false)
+ return InterestsViewHolder(view)
+ }
+
+ override fun onBindViewHolder(holder: InterestsViewHolder, position: Int) {
+ val item = interestsList[position]
+ holder.view.setOnClickListener {
+ onClickListener?.invoke(item)
+ }
+ holder.textView.text = item.interests
+ }
+ override fun getItemViewType(position: Int): Int {
+ val item = interestsList[position]
+ return if (item.enabled) ENABLED_VIEW else DISABLED_VIEW
+ }
+
+ override fun getItemCount(): Int {
+ return interestsList.size
+ }
+
+ companion object {
+ val ENABLED_VIEW = 100
+ val DISABLED_VIEW = 101
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment3/InterestsDiffUtil.kt b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment3/InterestsDiffUtil.kt
new file mode 100644
index 0000000..a56f0e6
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment3/InterestsDiffUtil.kt
@@ -0,0 +1,25 @@
+package ru.otus.basicarchitecture.presentation.Fragment3
+
+import androidx.recyclerview.widget.DiffUtil
+
+class InterestsDiffUtil(
+ private val oldList: List,
+ private val newList: List,
+) : DiffUtil.Callback() {
+ override fun getOldListSize(): Int {
+ return oldList.size
+ }
+
+ override fun getNewListSize(): Int {
+ return newList.size
+ }
+
+ override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
+ return oldList[oldItemPosition].id == newList[newItemPosition].id
+ }
+
+ override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
+ return oldList[oldItemPosition] == newList[newItemPosition]
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment3/InterestsViewHolder.kt b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment3/InterestsViewHolder.kt
new file mode 100644
index 0000000..f29c1a1
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment3/InterestsViewHolder.kt
@@ -0,0 +1,10 @@
+package ru.otus.basicarchitecture.presentation.Fragment3
+
+import android.view.View
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import ru.otus.basicarchitecture.R
+
+class InterestsViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
+ val textView = view.findViewById(R.id.textInterests)
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment3/ModelInterestsForView.kt b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment3/ModelInterestsForView.kt
new file mode 100644
index 0000000..26b18b8
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment3/ModelInterestsForView.kt
@@ -0,0 +1,20 @@
+package ru.otus.basicarchitecture.presentation.Fragment3
+
+import ru.otus.basicarchitecture.Core.Model.Interests
+
+data class ModelInterestsForView(
+ var id: Int,
+ val interests: String,
+ var enabled: Boolean
+){
+
+ companion object {
+ fun toDomain(modelView: ModelInterestsForView): Interests {
+ return Interests(modelView.interests)
+ }
+
+ fun toModel(id: Int, interests: Interests): ModelInterestsForView {
+ return ModelInterestsForView(id, interests.interests, false)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment4/Fragment4.kt b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment4/Fragment4.kt
new file mode 100644
index 0000000..511a71e
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment4/Fragment4.kt
@@ -0,0 +1,66 @@
+package ru.otus.basicarchitecture.Ui.Fragment4
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import androidx.recyclerview.widget.RecyclerView
+import androidx.recyclerview.widget.StaggeredGridLayoutManager
+import ru.otus.basicarchitecture.App
+import ru.otus.basicarchitecture.Core.Model.ViewModelFactory
+import ru.otus.basicarchitecture.R
+import ru.otus.basicarchitecture.databinding.Fragment3Binding
+import ru.otus.basicarchitecture.databinding.Fragment4Binding
+
+import javax.inject.Inject
+
+class Fragment4: Fragment() {
+ private lateinit var binding: Fragment4Binding
+
+ @Inject
+ lateinit var viewModelFactory: ViewModelFactory
+
+
+ private val viewModel by lazy{
+ ViewModelProvider(this, viewModelFactory)[Fragment4ViewModel::class.java]
+ }
+
+ private var adapter = Fragment4Adapter()
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ binding = Fragment4Binding.inflate(inflater, container, false)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ (requireActivity().application as App).component
+ .fragment4SubComponent()
+ .build()
+ .inject(this)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ setupView()
+ }
+
+ private fun setupView(){
+ binding.Name.text = viewModel.fragment4Model.name
+ binding.Surname.text = viewModel.fragment4Model.surName
+ binding.DateOfBirth.text = viewModel.fragment4Model.birthDate
+ binding.Address.text = viewModel.fragment4Model.fullAddress
+ adapter.listInterestsInfo = viewModel.fragment4Model.interests
+
+ val spanCount = 2
+ val orientation = StaggeredGridLayoutManager.VERTICAL
+ val layoutManager = StaggeredGridLayoutManager(spanCount, orientation)
+
+ binding.recyclerView4.layoutManager = layoutManager
+ binding.recyclerView4.adapter = adapter
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment4/Fragment4Adapter.kt b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment4/Fragment4Adapter.kt
new file mode 100644
index 0000000..18b5f81
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment4/Fragment4Adapter.kt
@@ -0,0 +1,31 @@
+package ru.otus.basicarchitecture.Ui.Fragment4
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import ru.otus.basicarchitecture.R
+import ru.otus.basicarchitecture.presentation.Fragment3.InterestsViewHolder
+
+
+class Fragment4Adapter : RecyclerView.Adapter() {
+
+ var listInterestsInfo: List = listOf()
+ set(value) {
+ field = value
+ notifyDataSetChanged()
+ }
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): InterestsViewHolder {
+ val layout = R.layout.interests_disabled
+ val view = LayoutInflater.from(parent.context).inflate(layout, parent,false)
+ return InterestsViewHolder(view)
+ }
+
+ override fun getItemCount(): Int {
+ return listInterestsInfo.size
+ }
+
+ override fun onBindViewHolder(holder: InterestsViewHolder, position: Int) {
+ val item = listInterestsInfo[position]
+ holder.textView.text = item
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment4/Fragment4Model.kt b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment4/Fragment4Model.kt
new file mode 100644
index 0000000..dadcf6b
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment4/Fragment4Model.kt
@@ -0,0 +1,9 @@
+package ru.otus.basicarchitecture.Ui.Fragment4
+
+data class Fragment4Model(
+ val name: String,
+ val surName: String,
+ val birthDate: String,
+ val fullAddress: String,
+ val interests: List
+)
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment4/Fragment4ViewModel.kt b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment4/Fragment4ViewModel.kt
new file mode 100644
index 0000000..27d66d4
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/Ui/Fragment4/Fragment4ViewModel.kt
@@ -0,0 +1,30 @@
+package ru.otus.basicarchitecture.Ui.Fragment4
+
+import androidx.lifecycle.ViewModel
+import ru.otus.basicarchitecture.Core.Model.Address
+import ru.otus.basicarchitecture.Core.Model.Interests
+import ru.otus.basicarchitecture.Core.Model.Person
+import ru.otus.basicarchitecture.Domain.Data.PersonUseCase
+import ru.otus.basicarchitecture.Ui.Fragment4.Fragment4Model
+import javax.inject.Inject
+
+class Fragment4ViewModel @Inject constructor(
+ info: PersonUseCase
+) : ViewModel() {
+
+ val fragment4Model: Fragment4Model
+
+ init {
+ val information = info.getPerson()
+ val person = information["person"] as Person
+ val address = information["address"] as Address
+ val interest = information["interests"] as Interests
+ fragment4Model = Fragment4Model(
+ person.firstName,
+ person.surName,
+ person.dateOfBirth,
+ address.address,
+ interest.interests.split(",")
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/data/AddressImpl.kt b/app/src/main/java/ru/otus/basicarchitecture/data/AddressImpl.kt
new file mode 100644
index 0000000..00ec059
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/data/AddressImpl.kt
@@ -0,0 +1,21 @@
+package ru.otus.basicarchitecture.data
+
+import retrofit2.Response
+import ru.otus.basicarchitecture.Core.Model.DTO.SuggestionRequest
+import java.io.IOException
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class AddressImpl @Inject constructor(private val networkService: NetworkService) {
+
+ suspend fun getSuggestions(input: String) = networkCall {
+ networkService.getAddress(SuggestionRequest(input))
+ }
+
+ suspend inline fun networkCall(crossinline block: suspend () -> Response): Result =
+ runCatching {
+ block().body() ?: throw IOException("Network error")
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/data/RepositoryImpl.kt b/app/src/main/java/ru/otus/basicarchitecture/data/RepositoryImpl.kt
new file mode 100644
index 0000000..5f7b038
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/data/RepositoryImpl.kt
@@ -0,0 +1,91 @@
+package ru.otus.basicarchitecture.data
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import ru.otus.basicarchitecture.Core.Model.Address
+import ru.otus.basicarchitecture.Core.Model.BaseModel
+import ru.otus.basicarchitecture.Core.Model.Interests
+import ru.otus.basicarchitecture.Core.Model.Person
+import ru.otus.basicarchitecture.Domain.Repository
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class RepositoryImpl @Inject constructor(
+ private val wizardCache: WizardCache
+) : Repository {
+
+
+ private val listInterests = listOf(
+ "Йога и медитация",
+ "Игры настольные",
+ "Пение в караоке",
+ "Реставрация старинной мебели",
+ "Занятия танцами",
+ "Развитие навыков программирования",
+ "Садоводство и уход за растениями",
+ "Фотография архитектурных сооружений",
+ "Шитье и создание одежды",
+ "Философия и обсуждение философских вопросов",
+ "Развитие навыков игры на музыкальных инструментах",
+ "Прослушивание подкастов о науке",
+ "Рукоделие и создание поделок",
+ "Экстримальные виды спорта: парашютный спорт, сноубординг, скейтбординг"
+ )
+
+
+
+
+ private val mutableLiveDataWizardCache = MutableLiveData()
+
+ val liveDataWizardCache: LiveData = mutableLiveDataWizardCache
+
+
+
+ override fun setPerson(person: Person) {
+ wizardCache.firstName = person.firstName
+ wizardCache.surName = person.surName
+ wizardCache.dateOfBirth = person.firstName
+ updateWizardCache()
+ }
+
+ override fun setAddress(address: Address) {
+ wizardCache.address = address.address
+ updateWizardCache()
+ }
+
+ private fun updateWizardCache() {
+ mutableLiveDataWizardCache.postValue(wizardCache)
+ }
+
+ override fun getListInterests(): List = listInterests
+
+ override fun setInterests(interests: Interests) {
+ wizardCache.interests = interests.interests
+ updateWizardCache()
+ }
+
+ override fun getInfoPersonUseCase(): Map {
+ val person = Person(
+ wizardCache.firstName,
+ wizardCache.surName,
+ wizardCache.dateOfBirth
+ )
+
+ val address = Address(
+ wizardCache.address
+ )
+
+ val interests = Interests(
+ wizardCache.interests
+ )
+
+
+ return mapOf(
+ "person" to person,
+ "address" to address,
+ "interests" to interests
+ )
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/otus/basicarchitecture/data/WizardCache.kt b/app/src/main/java/ru/otus/basicarchitecture/data/WizardCache.kt
new file mode 100644
index 0000000..4db9cfc
--- /dev/null
+++ b/app/src/main/java/ru/otus/basicarchitecture/data/WizardCache.kt
@@ -0,0 +1,19 @@
+package ru.otus.basicarchitecture.data
+
+
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+data class WizardCache(
+ //person
+ var firstName: String,
+ var surName: String,
+ var dateOfBirth: String,
+
+ //address
+ var address: String,
+
+ //interests
+ var interests: String
+)
\ No newline at end of file
diff --git a/app/src/main/res/drawable/background_state_button.xml b/app/src/main/res/drawable/background_state_button.xml
new file mode 100644
index 0000000..4ababae
--- /dev/null
+++ b/app/src/main/res/drawable/background_state_button.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/button_selector.xml b/app/src/main/res/drawable/button_selector.xml
new file mode 100644
index 0000000..132c26d
--- /dev/null
+++ b/app/src/main/res/drawable/button_selector.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/calendar.xml b/app/src/main/res/drawable/calendar.xml
new file mode 100644
index 0000000..0083b28
--- /dev/null
+++ b/app/src/main/res/drawable/calendar.xml
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/form_text_view_for_rv.xml b/app/src/main/res/drawable/form_text_view_for_rv.xml
new file mode 100644
index 0000000..c01d672
--- /dev/null
+++ b/app/src/main/res/drawable/form_text_view_for_rv.xml
@@ -0,0 +1,10 @@
+
+
+ -
+
+
+
+
+
+
\ 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
index 0b15a20..d242c41 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -6,4 +6,9 @@
android:layout_height="match_parent"
tools:context=".MainActivity">
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/address_layout.xml b/app/src/main/res/layout/address_layout.xml
new file mode 100644
index 0000000..01da18c
--- /dev/null
+++ b/app/src/main/res/layout/address_layout.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment1.xml b/app/src/main/res/layout/fragment1.xml
new file mode 100644
index 0000000..e39657a
--- /dev/null
+++ b/app/src/main/res/layout/fragment1.xml
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment2.xml b/app/src/main/res/layout/fragment2.xml
new file mode 100644
index 0000000..e1c5b93
--- /dev/null
+++ b/app/src/main/res/layout/fragment2.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment3.xml b/app/src/main/res/layout/fragment3.xml
new file mode 100644
index 0000000..f424320
--- /dev/null
+++ b/app/src/main/res/layout/fragment3.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment4.xml b/app/src/main/res/layout/fragment4.xml
new file mode 100644
index 0000000..4a7e317
--- /dev/null
+++ b/app/src/main/res/layout/fragment4.xml
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/interests_disabled.xml b/app/src/main/res/layout/interests_disabled.xml
new file mode 100644
index 0000000..9295816
--- /dev/null
+++ b/app/src/main/res/layout/interests_disabled.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/interests_enabled.xml b/app/src/main/res/layout/interests_enabled.xml
new file mode 100644
index 0000000..171e2ab
--- /dev/null
+++ b/app/src/main/res/layout/interests_enabled.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index f8c6127..330f2f8 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -7,4 +7,5 @@
#FF018786
#FF000000
#FFFFFFFF
+ #008DED
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f26b6d3..127f65d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,3 +1,12 @@
BasicArchitecture
+ Next
+ Name
+ Date of Birth
+ Surname
+ Date
+ country
+ city
+ Address
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index c84cccf..df06faa 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,4 +3,5 @@ plugins {
id 'com.android.application' version '8.0.0' apply false
id 'com.android.library' version '8.0.0' apply false
id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
+ id("org.jetbrains.kotlin.plugin.serialization") version "1.9.0" apply false
}
\ No newline at end of file