Skip to content

Commit

Permalink
Merge d92d531 into b8aa606
Browse files Browse the repository at this point in the history
  • Loading branch information
muhammedesadcomert authored Sep 11, 2022
2 parents b8aa606 + d92d531 commit 691fdb3
Show file tree
Hide file tree
Showing 28 changed files with 422 additions and 50 deletions.
31 changes: 29 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'androidx.navigation.safeargs.kotlin'
id 'dagger.hilt.android.plugin'
id 'kotlin-kapt'
}

android {
Expand All @@ -12,7 +14,7 @@ android {
minSdk 23
targetSdk 32
versionCode 1
versionName "1.0"
versionName "1.0.1"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand All @@ -33,10 +35,12 @@ android {
buildFeatures {
viewBinding true
}
task printVersionName {
println defaultConfig.versionName
}
}

dependencies {

implementation 'androidx.core:core-ktx:1.8.0'
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.6.1'
Expand All @@ -50,4 +54,27 @@ dependencies {
// Navigation
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"

// Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

// OkHttp
// Define a BOM and its version
implementation platform("com.squareup.okhttp3:okhttp-bom:4.9.3")
// Define any required OkHttp artifacts without version
implementation 'com.squareup.okhttp3:okhttp'
implementation 'com.squareup.okhttp3:logging-interceptor'

// Glide
implementation 'com.github.bumptech.glide:glide:4.13.2'
annotationProcessor 'com.github.bumptech.glide:compiler:4.13.2'

// Hilt
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-compiler:$hilt_version"

// Moshi
implementation "com.squareup.moshi:moshi-kotlin:$moshi_version"
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package com.muhammedesadcomert.shopping

import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4

import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.*
import org.junit.Test
import org.junit.runner.RunWith

import org.junit.Assert.*

/**
* Instrumented test, which will execute on an Android device.
*
Expand All @@ -21,4 +19,4 @@ class ExampleInstrumentedTest {
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.muhammedesadcomert.appnomicase", appContext.packageName)
}
}
}
5 changes: 4 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.muhammedesadcomert.shopping">

<uses-permission android:name="android.permission.INTERNET" />

<application
android:name=".ShoppingApp"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
Expand All @@ -14,7 +17,7 @@
android:theme="@style/Theme.Shopping"
tools:targetApi="31">
<activity
android:name="com.muhammedesadcomert.shopping.MainActivity"
android:name="com.muhammedesadcomert.shopping.ui.MainActivity"
android:exported="true"
android:theme="@style/Theme.Shopping">
<intent-filter>
Expand Down
27 changes: 0 additions & 27 deletions app/src/main/java/com/muhammedesadcomert/shopping/HomeFragment.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.muhammedesadcomert.shopping

import android.app.Application
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class ShoppingApp : Application()
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.muhammedesadcomert.shopping.common.base

import com.muhammedesadcomert.shopping.common.util.Resource
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import retrofit2.HttpException
import retrofit2.Response
import java.io.IOException

abstract class BaseRepository {
suspend fun <T> safeApiCall(apiCall: suspend () -> Response<T>): Resource<T> {
return withContext(Dispatchers.IO) {
try {
val response: Response<T> = apiCall()
if (response.isSuccessful) {
Resource.Success(response.body())
} else {
Resource.Failure(response.message().orEmpty())
}
} catch (e: HttpException) {
Resource.Failure(e.message ?: "Something went wrong!")
} catch (e: IOException) {
Resource.Failure("Please check your internet connection")
} catch (e: Exception) {
Resource.Failure("Something went wrong!")
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.muhammedesadcomert.shopping.common.util

object Constant {
const val BASE_URL = "https://api.shopiroller.com/v2.0/"
const val API_KEY = "xXspnfUxPzOGKNu90bFAjlOTnMLpN8veiixvEFXUw9I="
const val ALIAS_KEY = "AtS1aPFxlIdVLth6ee2SEETlRxk="
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.muhammedesadcomert.shopping.common.util

sealed class Resource<out T> {
data class Success<out T>(val data: T?) : Resource<T>()
data class Failure(val errorMessage: String) : Resource<Nothing>()
object Loading : Resource<Nothing>()
object NONE : Resource<Nothing>()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.muhammedesadcomert.shopping.data.remote

import com.muhammedesadcomert.shopping.ui.home.model.CategoryApiModel
import retrofit2.Response
import retrofit2.http.GET

interface ApiService {
@GET("categories")
suspend fun getCategories(): Response<CategoryApiModel>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.muhammedesadcomert.shopping.data.remote

import com.muhammedesadcomert.shopping.common.util.Constant.ALIAS_KEY
import com.muhammedesadcomert.shopping.common.util.Constant.API_KEY
import okhttp3.Interceptor
import okhttp3.Response

class AuthInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val requestBuilder = with(chain.request().newBuilder()) {
addHeader("Api-Key", API_KEY)
addHeader("Alias-Key", ALIAS_KEY)
build()
}
return chain.proceed(requestBuilder).newBuilder().build()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.muhammedesadcomert.shopping.data.repository

import com.muhammedesadcomert.shopping.common.base.BaseRepository
import com.muhammedesadcomert.shopping.common.util.Resource
import com.muhammedesadcomert.shopping.data.remote.ApiService
import com.muhammedesadcomert.shopping.ui.home.model.CategoryApiModel
import javax.inject.Inject

class ProductRepository @Inject constructor(private val apiService: ApiService) : BaseRepository() {
suspend fun getCategories(): Resource<CategoryApiModel> =
safeApiCall { apiService.getCategories() }
}
42 changes: 42 additions & 0 deletions app/src/main/java/com/muhammedesadcomert/shopping/di/AppModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.muhammedesadcomert.shopping.di

import com.muhammedesadcomert.shopping.common.util.Constant.BASE_URL
import com.muhammedesadcomert.shopping.data.remote.ApiService
import com.muhammedesadcomert.shopping.data.remote.AuthInterceptor
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
@Singleton
fun provideOkHttpClient(authInterceptor: AuthInterceptor) = OkHttpClient.Builder()
.addInterceptor(authInterceptor)
.addInterceptor(
HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.HEADERS)
.setLevel(HttpLoggingInterceptor.Level.BODY)
).build()

@Provides
@Singleton
fun provideRetrofitClient(okHttpClient: OkHttpClient): Retrofit = Retrofit.Builder()
.client(okHttpClient)
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()

@Provides
@Singleton
fun provideApiService(retrofit: Retrofit): ApiService = retrofit.create(ApiService::class.java)

@Provides
fun provideAuthInterceptor() = AuthInterceptor()
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.muhammedesadcomert.shopping
package com.muhammedesadcomert.shopping.ui

import android.os.Bundle
import android.view.Menu
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupActionBarWithNavController
import com.muhammedesadcomert.shopping.R
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MainActivity : AppCompatActivity(R.layout.activity_main) {

private lateinit var navController: NavController
Expand All @@ -32,4 +35,4 @@ class MainActivity : AppCompatActivity(R.layout.activity_main) {
menuInflater.inflate(R.menu.menu, menu)
return super.onCreateOptionsMenu(menu)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.muhammedesadcomert.shopping.ui.home

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.muhammedesadcomert.shopping.databinding.CategoryItemBinding
import com.muhammedesadcomert.shopping.ui.home.CategoryAdapter.CategoryViewHolder
import com.muhammedesadcomert.shopping.ui.home.model.Category

class CategoryAdapter(
private val categories: List<Category>,
private val onItemClicked: (Category) -> Unit,
) : RecyclerView.Adapter<CategoryViewHolder>() {

inner class CategoryViewHolder(private val binding: CategoryItemBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(category: Category) {
with(binding) {
Glide.with(itemView).load(category.icon).into(categoryIcon)
categoryName.text = category.name
}
}
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CategoryViewHolder {
return CategoryViewHolder(
CategoryItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
}

override fun onBindViewHolder(holder: CategoryViewHolder, position: Int) {
val category = categories[position]
holder.bind(category)
holder.itemView.setOnClickListener {
onItemClicked(category)
}
}

override fun getItemCount() = categories.size
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.muhammedesadcomert.shopping.ui.home

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import com.muhammedesadcomert.shopping.databinding.FragmentHomeBinding
import com.muhammedesadcomert.shopping.ui.home.model.Category
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class HomeFragment : Fragment() {

private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!

private val viewModel: HomeViewModel by viewModels()
private lateinit var categories: List<Category>

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
getCategories()
}

private fun getCategories() {
viewModel.categories.observe(viewLifecycleOwner) {
categories = it
initCategoryAdapter()
}
}

private fun initCategoryAdapter() {
val categoryAdapter = CategoryAdapter(categories) { category ->
}

binding.recyclerViewCategories.apply {
adapter = categoryAdapter
setHasFixedSize(true)
}
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
Loading

0 comments on commit 691fdb3

Please sign in to comment.