Przeglądaj źródła

Integrated logout API, created structure for account screen

Khubaib 3 miesięcy temu
rodzic
commit
fb4da484c8

+ 13 - 0
app/src/main/java/com/fastest/pass/account/data/remote/AccountApiService.kt

@@ -0,0 +1,13 @@
+package com.fastest.pass.account.data.remote
+
+import com.fastest.pass.app.WebResponse
+import retrofit2.http.Headers
+import retrofit2.http.POST
+import java.util.Objects
+
+interface AccountApiService {
+
+//    @Headers("Content-Type: application/json")
+    @POST("logout")
+    suspend fun logout() : WebResponse<Objects>
+}

+ 16 - 0
app/src/main/java/com/fastest/pass/account/data/repository/AccountRepositoryImpl.kt

@@ -0,0 +1,16 @@
+package com.fastest.pass.account.data.repository
+
+import com.fastest.pass.account.data.remote.AccountApiService
+import com.fastest.pass.account.domain.repository.AccountRepository
+import com.fastest.pass.app.WebResponse
+import java.util.Objects
+import javax.inject.Inject
+
+class AccountRepositoryImpl @Inject constructor(
+    private val accountApiService: AccountApiService
+) : AccountRepository {
+
+    override suspend fun accountRepository(): WebResponse<Objects> {
+        return accountApiService.logout()
+    }
+}

+ 16 - 0
app/src/main/java/com/fastest/pass/account/di/AccountModule.kt

@@ -1,10 +1,14 @@
 package com.fastest.pass.account.di
 
+import com.fastest.pass.account.data.remote.AccountApiService
+import com.fastest.pass.account.data.repository.AccountRepositoryImpl
+import com.fastest.pass.account.domain.repository.AccountRepository
 import com.fastest.pass.account.utils.AccountNavigation
 import dagger.Module
 import dagger.Provides
 import dagger.hilt.InstallIn
 import dagger.hilt.components.SingletonComponent
+import retrofit2.Retrofit
 import javax.inject.Singleton
 
 @Module
@@ -16,4 +20,16 @@ object AccountModule {
     fun provideNavigation() : AccountNavigation {
         return AccountNavigation()
     }
+
+    @Provides
+    @Singleton
+    fun provideAccountApiService(retrofit: Retrofit) : AccountApiService {
+        return retrofit.create(AccountApiService::class.java)
+    }
+
+    @Provides
+    @Singleton
+    fun provideAccountRepository(accountApiService: AccountApiService) : AccountRepository {
+        return AccountRepositoryImpl(accountApiService)
+    }
 }

+ 8 - 0
app/src/main/java/com/fastest/pass/account/domain/repository/AccountRepository.kt

@@ -0,0 +1,8 @@
+package com.fastest.pass.account.domain.repository
+
+import com.fastest.pass.app.WebResponse
+import java.util.Objects
+
+interface AccountRepository {
+    suspend fun accountRepository() : WebResponse<Objects>
+}

+ 17 - 0
app/src/main/java/com/fastest/pass/account/domain/usecase/AccountUseCase.kt

@@ -0,0 +1,17 @@
+package com.fastest.pass.account.domain.usecase
+
+import com.fastest.pass.account.data.remote.AccountApiService
+import com.fastest.pass.account.domain.repository.AccountRepository
+import com.fastest.pass.app.BaseUseCase
+import com.fastest.pass.app.WebResponse
+import java.util.Objects
+import javax.inject.Inject
+
+class AccountUseCase @Inject constructor(
+    private val accountRepository: AccountRepository
+) : BaseUseCase<String, WebResponse<Objects>>() {
+    override suspend fun execute(params: String): WebResponse<Objects> {
+        return accountRepository.accountRepository()
+    }
+
+}

+ 4 - 4
app/src/main/java/com/fastest/pass/account/presentation/ui/components/AccountScreen.kt

@@ -94,7 +94,8 @@ import kotlin.math.roundToInt
 import kotlin.random.Random
 
 enum class ClickType {
-    OPEN_LOGIN_SCREEN
+    OPEN_LOGIN_SCREEN,
+    LOGOUT_API
 }
 
 @OptIn(ExperimentalMaterial3Api::class)
@@ -183,8 +184,7 @@ fun AccountScreen(clickType: (ClickType) -> Unit) {
                     title = stringResource(id = R.string.logout),
                     desc = stringResource(id = R.string.sure_logout_account),
                     onCancel = { isLoggedOut = false },
-                    clickType = {
-                        clickType ->
+                    clickType = { clickType ->
                         clickType(clickType)
                     }
                     )
@@ -375,7 +375,7 @@ fun BoxScope.LogoutDialog(
                 Button(
                     onClick = {
                         Log.d("test_button", "Logout Yes")
-                        clickType.invoke(ClickType.OPEN_LOGIN_SCREEN)
+                        clickType.invoke(ClickType.LOGOUT_API)
                         onCancel.invoke()
                     },
                     modifier = Modifier

+ 17 - 0
app/src/main/java/com/fastest/pass/account/presentation/ui/fragment/AccountFragment.kt

@@ -20,6 +20,8 @@ import com.fastest.pass.account.presentation.ui.components.ClickType
 import com.fastest.pass.account.presentation.viewmodels.AccountViewModel
 import com.fastest.pass.account.utils.AccountNavigation
 import com.fastest.pass.account.utils.AccountRoute
+import com.fastest.pass.app.GenericLoader
+import com.fastest.pass.helpers.BasePreferenceHelper
 import com.fastest.pass.ui.theme.FastestPassTheme
 import dagger.hilt.android.AndroidEntryPoint
 import javax.inject.Inject
@@ -31,6 +33,8 @@ class AccountFragment : BaseFragment() {
 
     @Inject
     lateinit var navigation: AccountNavigation
+    @Inject
+    lateinit var basePreferenceHelper: BasePreferenceHelper
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -53,13 +57,26 @@ class AccountFragment : BaseFragment() {
                                 .background(colorResource(id = R.color.home_background_color))
                                 .padding(paddingValues.calculateBottomPadding())
                         ) {
+                            val logoutResponse = viewmodel.logoutResponse.value
+
+                            if (logoutResponse.response?.status == true) {
+                                basePreferenceHelper.setLoggedInState(false)
+                                basePreferenceHelper.clearAllData()
+                                viewmodel.navigateTo(AccountRoute.OpenLoginScreen)
+                            }
+
                             AccountScreen { clickType ->
                                 when (clickType) {
                                     ClickType.OPEN_LOGIN_SCREEN -> {
                                         viewmodel.navigateTo(AccountRoute.OpenLoginScreen)
                                     }
+                                    ClickType.LOGOUT_API -> {
+                                        viewmodel.logout()
+                                    }
                                 }
                             }
+
+                            GenericLoader(loader = logoutResponse.isLoading)
                         }
                     }
                 }

+ 39 - 1
app/src/main/java/com/fastest/pass/account/presentation/viewmodels/AccountViewModel.kt

@@ -1,14 +1,52 @@
 package com.fastest.pass.account.presentation.viewmodels
 
+import android.util.Log
+import androidx.compose.runtime.State
+import androidx.compose.runtime.mutableStateOf
 import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.fastest.pass.account.domain.usecase.AccountUseCase
 import com.fastest.pass.account.utils.AccountRoute
+import com.fastest.pass.app.Result
+import com.fastest.pass.app.UIState
+import com.fastest.pass.app.WebResponse
+import dagger.hilt.android.lifecycle.HiltViewModel
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.launch
+import java.util.Objects
+import javax.inject.Inject
 
-class AccountViewModel : ViewModel() {
+@HiltViewModel
+class AccountViewModel @Inject constructor(
+    private val accountUseCase: AccountUseCase
+) : ViewModel() {
 
     private val _router = MutableStateFlow<AccountRoute>(AccountRoute.OpenNoneScreen)
     val router: MutableStateFlow<AccountRoute> = _router
 
+    private var _logoutResponse = mutableStateOf(UIState<WebResponse<Objects>>())
+    val logoutResponse: State<UIState<WebResponse<Objects>>> = _logoutResponse
+
+    fun logout() {
+        viewModelScope.launch {
+            Log.d("logout_api", "logout()")
+            accountUseCase("") { result ->
+                Log.d("logout_api", "result = $result")
+                when (result) {
+                    is Result.Loading -> {
+                        _logoutResponse.value = UIState(true)
+                    }
+                    is Result.Success -> {
+                        _logoutResponse.value = UIState(false, result.data)
+                    }
+                    is Result.Failure -> {
+                        _logoutResponse.value = UIState(false)
+                    }
+                }
+            }
+        }
+    }
+
     fun navigateTo(accountRoute: AccountRoute) {
         _router.value = accountRoute
     }

+ 9 - 2
app/src/main/java/com/fastest/pass/app/AppModule.kt

@@ -20,15 +20,22 @@ object AppModule {
 
     // Provide the Base URL here
     private const val BASE_URL = "https://api.fastestpass.com/v1/"
-
+    private const val KEY_HEADER_AUTHORIZATION: String = "Authorization"
 
     @Provides
     @Singleton
-    fun provideOkHttpClient(): OkHttpClient {
+    fun provideOkHttpClient(basePreferenceHelper: BasePreferenceHelper): OkHttpClient {
         return OkHttpClient.Builder()
             .connectTimeout(120, TimeUnit.SECONDS)
             .readTimeout(120, TimeUnit.SECONDS)
             .addInterceptor(HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY })
+            .addInterceptor { chain ->
+                val token = basePreferenceHelper.getToken()
+                val request = chain.request().newBuilder()
+                    .addHeader(KEY_HEADER_AUTHORIZATION, "Bearer $token")
+                    .build()
+                chain.proceed(request)
+            }
             .build()
     }
 

+ 10 - 0
app/src/main/java/com/fastest/pass/helpers/BasePreferenceHelper.kt

@@ -6,6 +6,7 @@ class BasePreferenceHelper(private val context: Context) : PreferencesHelper() {
 
     fun clearAllData() {
         removePreference(context, KEY_FILENAME, KEY_ISLOGGEDIN)
+        removePreference(context, KEY_FILENAME, KEY_BEARER_TOKEN)
     }
 
     fun getLoggedInState(): Boolean {
@@ -16,8 +17,17 @@ class BasePreferenceHelper(private val context: Context) : PreferencesHelper() {
         putBooleanPreference(context, KEY_FILENAME, KEY_ISLOGGEDIN, state)
     }
 
+    fun saveToken(token: String) {
+        putStringPreference(context, KEY_FILENAME, KEY_BEARER_TOKEN, token)
+    }
+
+    fun getToken(): String? {
+        return getStringPreference(context, KEY_FILENAME, KEY_BEARER_TOKEN)
+    }
+
     companion object {
         private const val KEY_FILENAME = "file_fastestpass"
         private const val KEY_ISLOGGEDIN = "key_isloggedin"
+        private const val KEY_BEARER_TOKEN = "key_bearer_token"
     }
 }

+ 2 - 2
app/src/main/java/com/fastest/pass/login/data/model/LoginResponse.kt

@@ -1,7 +1,7 @@
 package com.fastest.pass.login.data.model
 
 data class LoginResponse(
-    val id: Boolean,
-    val firstname: String,
+    val userInfo: UserInfo,
+    val token: String
 )
 

+ 7 - 0
app/src/main/java/com/fastest/pass/login/data/model/UserInfo.kt

@@ -0,0 +1,7 @@
+package com.fastest.pass.login.data.model
+
+data class UserInfo(
+    val id: Int,
+    val name: String,
+    val email: String
+)

+ 1 - 0
app/src/main/java/com/fastest/pass/login/presentation/ui/LoginFragment.kt

@@ -64,6 +64,7 @@ class LoginFragment : BaseFragment() {
 
                             loginResponse.response?.data?.let {
                                 basePreferenceHelper.setLoggedInState(true)
+                                basePreferenceHelper.saveToken(it.token)
                                 viewmodel.navigateTo(LoginRoute.OpenDashBoardScreen)
                             }