diff --git a/.gitignore b/.gitignore
index 9955973..d53cdb2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,15 @@
/.gradle/4.4/fileChanges/last-build.bin
/.gradle/4.10.1/fileChanges/last-build.bin
/.gradle/buildOutputCleanup/outputFiles.bin
+*.iml
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..e7e9d11
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,2 @@
+# Default ignored files
+/workspace.xml
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..681f41a
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ xmlns:android
+
+ ^$
+
+
+
+
+
+
+
+
+ xmlns:.*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*:id
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ .*:name
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ name
+
+ ^$
+
+
+
+
+
+
+
+
+ style
+
+ ^$
+
+
+
+
+
+
+
+
+ .*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*
+
+ http://schemas.android.com/apk/res/android
+
+
+ ANDROID_ATTRIBUTE_ORDER
+
+
+
+
+
+
+ .*
+
+ .*
+
+
+ BY_NAME
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..5cd135a
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..0a801ef
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..f5c6d9e
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 7593dde..dbaadc2 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,6 +1,7 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
+apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 28
@@ -13,6 +14,12 @@ android {
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
+ dataBinding {
+ enabled = true
+ }
+ lintOptions {
+ disable 'GoogleAppIndexingWarning'
+ }
buildTypes {
release {
minifyEnabled false
@@ -38,6 +45,9 @@ repositories {
dependencies {
api fileTree(dir: 'libs', include: ['*.jar'])
api "com.jakewharton:butterknife:$butterknife_version"
+ implementation 'androidx.legacy:legacy-support-v4:1.0.0'
+ implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
+ implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'
kapt "com.jakewharton:butterknife-compiler:$butterknife_version"
api "com.google.dagger:dagger-android-support:$daggerVersion"
@@ -51,15 +61,33 @@ dependencies {
exclude group: 'com.google.code.findbugs'
})
+ testImplementation 'junit:junit:4.12'
api "androidx.appcompat:appcompat:$supportLibraryVersion"
api "androidx.recyclerview:recyclerview:$supportLibraryVersion"
-// api "androidx.legacy:legacy-support-v4:$supportLibraryVersion"
- api 'androidx.constraintlayout:constraintlayout:1.1.3'
+ implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
api 'com.squareup.retrofit2:retrofit:2.6.0'
api 'com.squareup.retrofit2:adapter-rxjava2:2.6.0'
api 'com.squareup.retrofit2:converter-gson:2.3.0'
- api 'com.squareup.picasso:picasso:2.5.2'
- api 'io.reactivex.rxjava2:rxandroid:2.1.1'
+ implementation 'com.squareup.picasso:picasso:2.71828'
- testImplementation 'junit:junit:4.12'
+ implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
+ implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
+ implementation 'io.reactivex.rxjava2:rxjava:2.2.2'
+
+ // UI
+ implementation "com.google.android.material:material:$rootProject.materialVersion"
+
+ // ViewModel Kotlin support
+ implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$rootProject.archLifecycleVersion"
+
+ // Room components
+ implementation "androidx.room:room-runtime:$rootProject.roomVersion"
+ implementation "androidx.room:room-ktx:$rootProject.roomVersion"
+ kapt "androidx.room:room-compiler:$rootProject.roomVersion"
+ androidTestImplementation "androidx.room:room-testing:$rootProject.roomVersion"
+
+ // Koin
+ implementation "org.koin:koin-android:$koin_version"
+ implementation "org.koin:koin-androidx-scope:$koin_version"
+ implementation "org.koin:koin-androidx-viewmodel:$koin_version"
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b687906..ee7d022 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -5,12 +5,12 @@
diff --git a/app/src/main/java/cvdevelopers/githubstalker/Part2.kt b/app/src/main/java/cvdevelopers/githubstalker/Part2.kt
new file mode 100644
index 0000000..6ec8434
--- /dev/null
+++ b/app/src/main/java/cvdevelopers/githubstalker/Part2.kt
@@ -0,0 +1,46 @@
+package cvdevelopers.githubstalker
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import cvdevelopers.takehome.UsersFragment
+import org.koin.android.ext.android.get
+
+// TODO: Rename parameter arguments, choose names that match
+// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
+private const val ARG_PARAM1 = "param1"
+private const val ARG_PARAM2 = "param2"
+
+/**
+ * A simple [Fragment] subclass.
+ * Use the [Part2.newInstance] factory method to
+ * create an instance of this fragment.
+ */
+class Part2 : Fragment() {
+ // TODO: Rename and change types of parameters
+ private var param1: String? = null
+ private var param2: String? = null
+
+ private var mPrimaryKey : String =""
+
+ companion object {
+ fun newInstance() = Part2()
+ }
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ arguments?.let {
+ if(it.containsKey("primary_key"))
+ mPrimaryKey = it.getString("primary_key") ?: "doe"
+
+ }
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ // Inflate the layout for this fragment
+ return inflater.inflate(R.layout.fragment_part2, container, false)
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/Adapter.kt b/app/src/main/java/cvdevelopers/takehome/Adapter.kt
new file mode 100644
index 0000000..f7fd82c
--- /dev/null
+++ b/app/src/main/java/cvdevelopers/takehome/Adapter.kt
@@ -0,0 +1,53 @@
+package cvdevelopers.takehome
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.RecyclerView
+import com.squareup.picasso.Picasso
+import cvdevelopers.githubstalker.R
+import cvdevelopers.takehome.models.Client
+import cvdevelopers.takehome.utils.ItemDiffCallback
+import cvdevelopers.takehome.utils.image.CircleTransformation
+import kotlinx.android.synthetic.main.users.view.*
+
+typealias ClickListener = (Client) -> Unit
+
+class Adapter(private val clickListener: ClickListener) :
+ RecyclerView.Adapter() {
+
+ private var mClient: List = emptyList()
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val view = LayoutInflater.from(parent.context).inflate(
+ R.layout.users, parent, false
+ ) as LinearLayout
+
+ val viewHolder = ViewHolder(view)
+ view.setOnClickListener { clickListener(mClient[viewHolder.adapterPosition]) }
+ return viewHolder
+ }
+
+ override fun getItemCount(): Int = mClient.count()
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(mClient[position])
+ }
+
+ fun updateClient(client: List) {
+ val diffResult = DiffUtil.calculateDiff(ItemDiffCallback(this.mClient, client))
+ this.mClient = client
+ diffResult.dispatchUpdatesTo(this)
+ }
+
+ class ViewHolder(view: ViewGroup) : RecyclerView.ViewHolder(view) {
+ fun bind(client: Client) {
+ val picture = client.picture.medium
+
+ Picasso.get().load(picture).transform(CircleTransformation()).into(itemView.img)
+ itemView.user_first.text = client.name.first
+ itemView.user_last.text = client.name.last
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/LuminaryTakeHomeApplication.kt b/app/src/main/java/cvdevelopers/takehome/LuminaryTakeHomeApplication.kt
deleted file mode 100644
index adce9b7..0000000
--- a/app/src/main/java/cvdevelopers/takehome/LuminaryTakeHomeApplication.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package cvdevelopers.takehome
-
-import android.app.Application
-import cvdevelopers.takehome.dagger.ApplicationComponent
-import cvdevelopers.takehome.dagger.ApplicationModule
-import cvdevelopers.takehome.dagger.DaggerApplicationComponent
-
-class LuminaryTakeHomeApplication : Application() {
-
- val appComponent: ApplicationComponent by lazy {
- DaggerApplicationComponent
- .builder()
- .applicationModule(ApplicationModule(this))
- .build()
- }
-
- override fun onCreate() {
- super.onCreate()
- appComponent.inject(this);
- }
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/MainActivity.kt b/app/src/main/java/cvdevelopers/takehome/MainActivity.kt
index e1c3bb4..a47aaba 100644
--- a/app/src/main/java/cvdevelopers/takehome/MainActivity.kt
+++ b/app/src/main/java/cvdevelopers/takehome/MainActivity.kt
@@ -9,8 +9,13 @@ class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
- (application as LuminaryTakeHomeApplication).appComponent.inject(this)
+ if (savedInstanceState == null) {
+ supportFragmentManager.beginTransaction()
+ .replace(R.id.activity_fragment_container, UsersFragment.newInstance())
+ .addToBackStack(null)
+ .commit()
+ }
}
}
diff --git a/app/src/main/java/cvdevelopers/takehome/UsersFragment.kt b/app/src/main/java/cvdevelopers/takehome/UsersFragment.kt
new file mode 100644
index 0000000..82f2536
--- /dev/null
+++ b/app/src/main/java/cvdevelopers/takehome/UsersFragment.kt
@@ -0,0 +1,88 @@
+package cvdevelopers.takehome
+
+import android.os.Bundle
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.Observer
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.android.material.snackbar.Snackbar
+import cvdevelopers.githubstalker.R
+import cvdevelopers.takehome.models.Client
+import cvdevelopers.takehome.viewmodel.UsersViewModel
+import kotlinx.android.synthetic.main.fragment_users.*
+import org.koin.androidx.viewmodel.ext.android.viewModel
+
+class UsersFragment : Fragment() {
+
+ private val mClickListener: ClickListener = this::onClientClicked
+ private val mViewModel: UsersViewModel by viewModel()
+ private var mAdapter = Adapter(mClickListener)
+ private var mDataSet = emptyList()
+
+ companion object {
+ fun newInstance() = UsersFragment()
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.fragment_users, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ setUpSwipeToRefresh()
+ setupRecyclerView()
+
+ getUsers()
+
+ mViewModel.mUsersList.observe(viewLifecycleOwner, Observer {
+ Log.d("observing::", "observing")
+ renderClients(it)
+ })
+ }
+
+ private fun setUpSwipeToRefresh() {
+ simpleSwipeRefreshLayout.setOnRefreshListener {
+ Toast.makeText(requireContext(), "Swipe detected Fetching users", Toast.LENGTH_SHORT).show()
+ clearDatabase()
+ renderClients(emptyList())
+ getUsers()
+ simpleSwipeRefreshLayout.isRefreshing = false
+ }
+ }
+
+ private fun getUsers() {
+ mViewModel.getUsers()
+ }
+
+ private fun clearDatabase() {
+ mViewModel.clearCache()
+ }
+
+ private fun renderClients(clients: List) {
+ Log.d("rendering clients::", "display client users")
+ loadingIndicator.visibility = View.GONE
+ mDataSet = clients
+ mAdapter.updateClient(clients)
+ recyclerview.visibility = View.VISIBLE
+ }
+
+ private fun setupRecyclerView() {
+ recyclerview.layoutManager = LinearLayoutManager(requireContext())
+ recyclerview.adapter = mAdapter
+ recyclerview.setHasFixedSize(true)
+ }
+
+ private fun onClientClicked(client: Client) {
+ val bundle = Bundle()
+ bundle.putString("primary_key",client.name.last)
+
+ //handle fragment here
+// view?.let { Snackbar.make(it, client.name.first, Snackbar.LENGTH_LONG).show() }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/api/RandomUserApiEndpoint.kt b/app/src/main/java/cvdevelopers/takehome/api/RandomUserApiEndpoint.kt
index 3e4eb8a..7d07e64 100644
--- a/app/src/main/java/cvdevelopers/takehome/api/RandomUserApiEndpoint.kt
+++ b/app/src/main/java/cvdevelopers/takehome/api/RandomUserApiEndpoint.kt
@@ -1,16 +1,15 @@
package cvdevelopers.takehome.api
import cvdevelopers.takehome.models.ApiResponse
-import io.reactivex.Single
import retrofit2.http.GET
import retrofit2.http.Query
interface RandomUserApiEndpoint {
@GET("/api/")
- fun getClient(@Query("page") page: String, @Query("results") results: String = "15"): Single
+ suspend fun getClient(@Query("page") page: String, @Query("results") results: String = "15"): ApiResponse
companion object {
- val SERVER = "https://randomuser.me"
+ const val SERVER = "https://randomuser.me"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/api/RecipeRetrofit.kt b/app/src/main/java/cvdevelopers/takehome/api/RecipeRetrofit.kt
new file mode 100644
index 0000000..057c08e
--- /dev/null
+++ b/app/src/main/java/cvdevelopers/takehome/api/RecipeRetrofit.kt
@@ -0,0 +1,14 @@
+package cvdevelopers.takehome.api
+
+import retrofit2.Retrofit
+import retrofit2.converter.gson.GsonConverterFactory
+
+class RecipeRetrofit {
+
+ companion object {
+ var userApiEndpoint: RandomUserApiEndpoint = Retrofit.Builder()
+ .baseUrl(RandomUserApiEndpoint.SERVER)
+ .addConverterFactory(GsonConverterFactory.create())
+ .build().create(RandomUserApiEndpoint::class.java)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/dagger/ApplicationComponent.kt b/app/src/main/java/cvdevelopers/takehome/dagger/ApplicationComponent.kt
deleted file mode 100644
index 7f4144d..0000000
--- a/app/src/main/java/cvdevelopers/takehome/dagger/ApplicationComponent.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package cvdevelopers.takehome.dagger
-
-import cvdevelopers.takehome.MainActivity
-import cvdevelopers.takehome.LuminaryTakeHomeApplication
-import dagger.Component
-import javax.inject.Singleton
-
-/**
- * Created by CamiloVega on 10/7/17.
- */
-@Singleton
-@Component(modules = arrayOf(ApplicationModule::class, NetworkClientModule::class))
-interface ApplicationComponent {
- fun inject(app: LuminaryTakeHomeApplication)
- fun inject(target: MainActivity)
-}
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/dagger/ApplicationModule.kt b/app/src/main/java/cvdevelopers/takehome/dagger/ApplicationModule.kt
deleted file mode 100644
index 337d977..0000000
--- a/app/src/main/java/cvdevelopers/takehome/dagger/ApplicationModule.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package cvdevelopers.takehome.dagger
-
-import android.app.Application
-import cvdevelopers.takehome.LuminaryTakeHomeApplication
-import dagger.Module
-import dagger.Provides
-import javax.inject.Singleton
-
-@Module
-class ApplicationModule(private val app: LuminaryTakeHomeApplication) {
-
- @Provides
- @Singleton
- fun provideApplication(): Application = app
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/dagger/NetworkClientModule.kt b/app/src/main/java/cvdevelopers/takehome/dagger/NetworkClientModule.kt
deleted file mode 100644
index 47c5ade..0000000
--- a/app/src/main/java/cvdevelopers/takehome/dagger/NetworkClientModule.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package cvdevelopers.takehome.dagger
-
-import com.google.gson.FieldNamingPolicy
-import com.google.gson.Gson
-import com.google.gson.GsonBuilder
-import cvdevelopers.takehome.api.RandomUserApiEndpoint
-import dagger.Module
-import dagger.Provides
-import io.reactivex.schedulers.Schedulers
-import retrofit2.Retrofit
-import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
-import retrofit2.converter.gson.GsonConverterFactory
-import javax.inject.Singleton
-
-@Module
-class NetworkClientModule {
-
- @Provides
- @Singleton
- fun provideGson() = GsonBuilder()
- .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
- .create()
-
- @Provides
- @Singleton
- fun provideRandomUserEndpoint(gson: Gson): RandomUserApiEndpoint = Retrofit.Builder()
- .baseUrl(RandomUserApiEndpoint.SERVER)
- .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
- .addConverterFactory(GsonConverterFactory.create(gson))
- .build().create(RandomUserApiEndpoint::class.java)
-}
diff --git a/app/src/main/java/cvdevelopers/takehome/database/ClientDatabase.kt b/app/src/main/java/cvdevelopers/takehome/database/ClientDatabase.kt
new file mode 100644
index 0000000..0a4d7f6
--- /dev/null
+++ b/app/src/main/java/cvdevelopers/takehome/database/ClientDatabase.kt
@@ -0,0 +1,30 @@
+package cvdevelopers.takehome.database
+
+import android.content.Context
+import androidx.room.Database
+import androidx.room.Room
+import androidx.room.RoomDatabase
+
+@Database(entities = [DatabaseEntity::class], version = 1, exportSchema = false)
+abstract class ClientDatabase : RoomDatabase() {
+
+ abstract fun clientDao(): ClientDictionaryDao
+
+ companion object {
+ private const val mDatabaseName = "client"
+
+ @Volatile
+ private var INSTANCE: ClientDatabase? = null
+
+ fun getDataBase(context: Context): ClientDatabase =
+ INSTANCE ?: synchronized(this) {
+ INSTANCE ?: buildDatabase(context).also { INSTANCE = it }
+ }
+
+ private fun buildDatabase(context: Context) = Room.databaseBuilder(
+ context.applicationContext,
+ ClientDatabase::class.java,
+ mDatabaseName
+ ).build()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/database/ClientDictionaryDao.kt b/app/src/main/java/cvdevelopers/takehome/database/ClientDictionaryDao.kt
new file mode 100644
index 0000000..f96705c
--- /dev/null
+++ b/app/src/main/java/cvdevelopers/takehome/database/ClientDictionaryDao.kt
@@ -0,0 +1,21 @@
+package cvdevelopers.takehome.database
+
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.Query
+
+@Dao
+interface ClientDictionaryDao {
+ @Query("SELECT * FROM DatabaseEntity")
+ suspend fun getClientsByName(): List
+
+ @Query("DELETE FROM DatabaseEntity")
+ suspend fun clearDatabase()
+
+ @Query("SELECT * FROM DatabaseEntity WHERE lastName LIKE :lName")
+ suspend fun getClient(lName: String): DatabaseEntity
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ fun insertWordDefinition(vararg databaseEntity: DatabaseEntity)
+}
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/database/DatabaseEntity.kt b/app/src/main/java/cvdevelopers/takehome/database/DatabaseEntity.kt
new file mode 100644
index 0000000..ed53f3b
--- /dev/null
+++ b/app/src/main/java/cvdevelopers/takehome/database/DatabaseEntity.kt
@@ -0,0 +1,11 @@
+package cvdevelopers.takehome.database
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity
+data class DatabaseEntity(
+ @PrimaryKey val lastName: String,
+ @ColumnInfo(name = "json") val json: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/diKoin/RecipeApplication.kt b/app/src/main/java/cvdevelopers/takehome/diKoin/RecipeApplication.kt
new file mode 100644
index 0000000..5215009
--- /dev/null
+++ b/app/src/main/java/cvdevelopers/takehome/diKoin/RecipeApplication.kt
@@ -0,0 +1,15 @@
+package cvdevelopers.takehome.diKoin
+
+import android.app.Application
+import org.koin.android.ext.koin.androidContext
+import org.koin.core.context.startKoin
+
+class RecipeApplication : Application() {
+ override fun onCreate() {
+ super.onCreate()
+ startKoin {
+ androidContext(this@RecipeApplication)
+ modules(ClientModule)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/diKoin/RecipesModule.kt b/app/src/main/java/cvdevelopers/takehome/diKoin/RecipesModule.kt
new file mode 100644
index 0000000..3d7748a
--- /dev/null
+++ b/app/src/main/java/cvdevelopers/takehome/diKoin/RecipesModule.kt
@@ -0,0 +1,15 @@
+package cvdevelopers.takehome.diKoin
+
+import cvdevelopers.takehome.database.ClientDatabase
+import cvdevelopers.takehome.repository.Repository
+import cvdevelopers.takehome.api.RecipeRetrofit
+import cvdevelopers.takehome.viewmodel.UsersViewModel
+import org.koin.android.ext.koin.androidContext
+import org.koin.androidx.viewmodel.dsl.viewModel
+import org.koin.dsl.module
+
+val ClientModule = module {
+ single { ClientDatabase.getDataBase(androidContext()) }
+ single { Repository(get()) }
+ viewModel { UsersViewModel(get()) }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/models/ApiResponse.kt b/app/src/main/java/cvdevelopers/takehome/models/ApiResponse.kt
index 60edba6..a91ec49 100644
--- a/app/src/main/java/cvdevelopers/takehome/models/ApiResponse.kt
+++ b/app/src/main/java/cvdevelopers/takehome/models/ApiResponse.kt
@@ -1,6 +1,5 @@
package cvdevelopers.takehome.models
-data class ApiResponse (
- val results: List
-){
-}
\ No newline at end of file
+data class ApiResponse(
+ val results: List
+)
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/models/Client.kt b/app/src/main/java/cvdevelopers/takehome/models/Client.kt
index ae3d816..47cf045 100644
--- a/app/src/main/java/cvdevelopers/takehome/models/Client.kt
+++ b/app/src/main/java/cvdevelopers/takehome/models/Client.kt
@@ -1,8 +1,9 @@
package cvdevelopers.takehome.models
data class Client(
- val email: String,
- val id: Id,
- val name: Name,
- val picture: Picture
+ val email: String,
+ val id: Id,
+ val gender: String,
+ val name: Name,
+ val picture: Picture
)
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/models/Id.kt b/app/src/main/java/cvdevelopers/takehome/models/Id.kt
index 0e9e153..70b82c4 100644
--- a/app/src/main/java/cvdevelopers/takehome/models/Id.kt
+++ b/app/src/main/java/cvdevelopers/takehome/models/Id.kt
@@ -1,9 +1,7 @@
package cvdevelopers.takehome.models
-import com.google.gson.annotations.SerializedName
-
data class Id(
- val name: String,
- val value: String
+ val name: String,
+ val value: String
)
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/models/Name.kt b/app/src/main/java/cvdevelopers/takehome/models/Name.kt
index 064fdcc..a688292 100644
--- a/app/src/main/java/cvdevelopers/takehome/models/Name.kt
+++ b/app/src/main/java/cvdevelopers/takehome/models/Name.kt
@@ -1,7 +1,7 @@
package cvdevelopers.takehome.models
data class Name(
- val first: String,
- val last: String,
- val title: String
+ val first: String,
+ val last: String,
+ val title: String
)
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/models/Picture.kt b/app/src/main/java/cvdevelopers/takehome/models/Picture.kt
index f3a4d6e..03e24ea 100644
--- a/app/src/main/java/cvdevelopers/takehome/models/Picture.kt
+++ b/app/src/main/java/cvdevelopers/takehome/models/Picture.kt
@@ -1,7 +1,7 @@
package cvdevelopers.takehome.models
data class Picture(
- val large: String,
- val medium: String,
- val thumbnail: String
+ val large: String,
+ val medium: String,
+ val thumbnail: String
)
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/repository/Repository.kt b/app/src/main/java/cvdevelopers/takehome/repository/Repository.kt
new file mode 100644
index 0000000..fd61d6f
--- /dev/null
+++ b/app/src/main/java/cvdevelopers/takehome/repository/Repository.kt
@@ -0,0 +1,69 @@
+package cvdevelopers.takehome.repository
+
+import android.util.Log
+import cvdevelopers.takehome.database.ClientDatabase
+import cvdevelopers.takehome.database.DatabaseEntity
+import cvdevelopers.takehome.utils.listFromJson
+import cvdevelopers.takehome.utils.listToJson
+import cvdevelopers.takehome.api.RecipeRetrofit
+import cvdevelopers.takehome.models.Client
+import java.util.*
+
+class Repository(private val clientDatabase: ClientDatabase) {
+ private var isRetrofitRequestInProgress = false
+ private var mDataset: List = emptyList()
+
+ suspend fun clearDatabase() {
+ clientDatabase.clientDao().clearDatabase()
+ }
+
+ suspend fun getSearchResults(page: String): List {
+ try {
+ Log.d("getting search::", "ma")
+ mDataset = getClientsFromDatabase(page)
+ } catch (e: Exception) {
+ Log.e("ERROR GETTING DATA ", e.message ?: "")
+ getClientsFromDatabase(page)
+ }
+ return mDataset
+ }
+
+ private suspend fun getClientsFromDatabase(page: String): List {
+ val databaseData = clientDatabase.clientDao().getClientsByName()
+ return if (databaseData.isNotEmpty()) {
+ Log.d("get data from db::", "db is not empty")
+ databaseData[0].run { listFromJson(this.json) }
+ } else {
+ Log.d("db is empty::", "db is empty")
+ getDefinitionsFromServiceCall(page)
+ insertUsersIntoDatabase()
+ mDataset
+ }
+ }
+
+ suspend fun getClientsFromDatabase(clientLName: String): Client {
+ return clientDatabase.clientDao().getClient().json
+
+ }
+
+ private suspend fun getDefinitionsFromServiceCall(page: String) {
+ if (isRetrofitRequestInProgress) return
+ else {
+ isRetrofitRequestInProgress = true
+ Log.d("fetch data from api::", "fetching data")
+ mDataset = RecipeRetrofit.userApiEndpoint.getClient(page).results
+ isRetrofitRequestInProgress = false
+ }
+ }
+
+ private fun insertUsersIntoDatabase() {
+ if (mDataset.isEmpty()) return
+ else {
+ val lastName = mDataset[0].name.last.toLowerCase(Locale.getDefault())
+ val jsonStringData = listToJson(mDataset)
+ Log.d("insert data to db::", "inserting users")
+ clientDatabase.clientDao()
+ .insertWordDefinition(DatabaseEntity(lastName, jsonStringData))
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/utils/GsonUtil.kt b/app/src/main/java/cvdevelopers/takehome/utils/GsonUtil.kt
new file mode 100644
index 0000000..036df8b
--- /dev/null
+++ b/app/src/main/java/cvdevelopers/takehome/utils/GsonUtil.kt
@@ -0,0 +1,13 @@
+package cvdevelopers.takehome.utils
+
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import cvdevelopers.takehome.models.Client
+import java.lang.reflect.Type
+import java.util.ArrayList
+
+val listType: Type = object : TypeToken>() {}.type
+val gson = Gson()
+
+fun listToJson(list: List): String = gson.toJson(list, listType)
+fun listFromJson(string: String): List = gson.fromJson(string, listType)
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/utils/ItemDiffCallback.kt b/app/src/main/java/cvdevelopers/takehome/utils/ItemDiffCallback.kt
new file mode 100644
index 0000000..51894fa
--- /dev/null
+++ b/app/src/main/java/cvdevelopers/takehome/utils/ItemDiffCallback.kt
@@ -0,0 +1,21 @@
+package cvdevelopers.takehome.utils
+
+import androidx.recyclerview.widget.DiffUtil
+import cvdevelopers.takehome.models.Client
+
+class ItemDiffCallback(
+ private val old: List,
+ private val new: List
+) : DiffUtil.Callback() {
+ override fun getOldListSize() = old.size
+
+ override fun getNewListSize() = new.size
+
+ override fun areItemsTheSame(oldIndex: Int, newIndex: Int): Boolean {
+ return old[oldIndex].name == new[newIndex].name
+ }
+
+ override fun areContentsTheSame(oldIndex: Int, newIndex: Int): Boolean {
+ return old[oldIndex] == new[newIndex]
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/viewmodel/UsersViewModel.kt b/app/src/main/java/cvdevelopers/takehome/viewmodel/UsersViewModel.kt
new file mode 100644
index 0000000..a066678
--- /dev/null
+++ b/app/src/main/java/cvdevelopers/takehome/viewmodel/UsersViewModel.kt
@@ -0,0 +1,30 @@
+package cvdevelopers.takehome.viewmodel
+
+import android.util.Log
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import cvdevelopers.takehome.repository.Repository
+import cvdevelopers.takehome.models.Client
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+
+class UsersViewModel(
+ private val repository: Repository
+) : ViewModel() {
+
+ val mUsersList = MutableLiveData>()
+
+ fun getUsers(page: String = "1") = viewModelScope.launch(Dispatchers.IO) {
+ Log.d("get users::", "getting users")
+ mUsersList.postValue(repository.getSearchResults(page))
+ }
+
+ fun clearCache() {
+ viewModelScope.launch(Dispatchers.IO) {
+ repository.clearDatabase()
+ }
+ }
+}
+
+//picture,first, last, gender, email
\ No newline at end of file
diff --git a/app/src/main/java/cvdevelopers/takehome/viewmodel/viewmodel2.kt b/app/src/main/java/cvdevelopers/takehome/viewmodel/viewmodel2.kt
new file mode 100644
index 0000000..c6a770d
--- /dev/null
+++ b/app/src/main/java/cvdevelopers/takehome/viewmodel/viewmodel2.kt
@@ -0,0 +1,23 @@
+package cvdevelopers.takehome.viewmodel
+
+import android.util.Log
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import cvdevelopers.takehome.models.Client
+import cvdevelopers.takehome.repository.Repository
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+
+class viewmodel2( private val repository: Repository
+) : ViewModel() {
+
+
+ val mUsersList = MutableLiveData>()
+
+ fun getUsers(page: String = "1") = viewModelScope.launch(Dispatchers.IO) {
+ Log.d("get users::", "getting users")
+ mUsersList.postValue(repository.getSearchResults(page))
+ }
+
+}
\ 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 f577e9f..e472196 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -13,7 +13,6 @@
+ android:layout_height="wrap_content" />
diff --git a/app/src/main/res/layout/fragment_part2.xml b/app/src/main/res/layout/fragment_part2.xml
new file mode 100644
index 0000000..a04149f
--- /dev/null
+++ b/app/src/main/res/layout/fragment_part2.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_users.xml b/app/src/main/res/layout/fragment_users.xml
new file mode 100644
index 0000000..994e66e
--- /dev/null
+++ b/app/src/main/res/layout/fragment_users.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/users.xml b/app/src/main/res/layout/users.xml
new file mode 100644
index 0000000..08a092b
--- /dev/null
+++ b/app/src/main/res/layout/users.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
\ 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 b8f8350..918322a 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -11,4 +11,9 @@
Fetching User
Search
+ User Image
+ Search By First Name
+ Error Loading Clients
+ First Name
+ Last Name
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index b18e852..954d40c 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -3,6 +3,9 @@