Skip to content

Commit

Permalink
Merge pull request #7 from mughalasim/feature/member-type
Browse files Browse the repository at this point in the history
Version 12.0 - Added member type support with 3 types Admin, Supervisor and Member with different permissions determined in use cases
  • Loading branch information
mughalasim authored Jul 11, 2024
2 parents 933bf73 + 86d6070 commit 135444c
Show file tree
Hide file tree
Showing 36 changed files with 411 additions and 173 deletions.
3 changes: 1 addition & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ android {

setConfigVariable(variableName = "CURRENCY_CODE", variableSource = "CURRENCY_CODE")
setConfigVariable(variableName = "API_BASE_URL", variableSource = "API_BASE_URL")
setConfigVariable(variableName = "ADMIN_LIVE", variableSource = "ADMIN_LIVE")
setConfigVariable(variableName = "ADMIN_STAGING", variableSource = "ADMIN_STAGING")
setConfigVariable(variableName = "PATH_USER_IMAGES", variableSource = "PATH_USER_IMAGES")
setConfigVariable(variableName = "PATH_PAYMENT", variableSource = "PATH_PAYMENT")
Expand Down Expand Up @@ -109,7 +108,7 @@ android {
detekt {
toolVersion = libs.versions.detekt.get()
config.setFrom(rootProject.file("detekt.yml"))
buildUponDefaultConfig = true
buildUponDefaultConfig = false
}

packaging {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ val repositoryModule =
module {
single<AuthRepository> {
AuthRepositoryImp(
adminEmails = listOf(BuildConfig.ADMIN_LIVE, BuildConfig.ADMIN_STAGING),
pathUser = BuildConfig.PATH_USER,
logger = get()
)
}
Expand Down
10 changes: 5 additions & 5 deletions app/src/main/kotlin/com/ndemi/garden/gym/di/ViewModelModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,25 @@ import org.koin.dsl.module
val viewModelModule =
module {

viewModel { MainScreenViewModel(get(), get()) }
viewModel { MainScreenViewModel(get(), get(), get()) }

viewModel { LoginScreenViewModel(get(), get(), get()) }

viewModel { ProfileScreenViewModel(get(), get(), get(), get(), get(), get()) }

viewModel { AttendanceScreenViewModel(get(), get()) }

viewModel { PaymentsScreenViewModel(get(), get(), get()) }
viewModel { PaymentsScreenViewModel(get(), get(), get(), get()) }

viewModel { PaymentAddScreenViewModel(get(), get(), get()) }

viewModel { LiveAttendanceScreenViewModel(get(), get()) }

viewModel { MembersScreenViewModel(get(), get(), get()) }
viewModel { MembersScreenViewModel(get(), get(), get(), get()) }

viewModel { MemberEditScreenViewModel(get(), get(), get(), get()) }
viewModel { MemberEditScreenViewModel(get(), get(), get(), get(), get()) }

viewModel { MembersAttendancesScreenViewModel(get(), get(), get()) }
viewModel { MembersAttendancesScreenViewModel(get(), get(), get(), get()) }

viewModel { RegisterScreenViewModel(get(), get(), get(), get()) }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class NavigationServiceImp(

override fun setNavController(navController: NavController) {
this.navController = navController
val initialRoute = Route.getInitialRoute(authUseCase.isAuthenticated(), authUseCase.isAdmin())
val initialRoute = Route.getInitialRoute(authUseCase.isAuthenticated(), authUseCase.isNotMember())
this.initialRoute = initialRoute
}

Expand Down Expand Up @@ -56,7 +56,7 @@ class NavigationServiceImp(

override fun getCurrentRoute(): Route =
navController.currentDestination?.route?.toRoute() ?:
Route.getInitialRoute(authUseCase.isAuthenticated(), authUseCase.isAdmin())
Route.getInitialRoute(authUseCase.isAuthenticated(), authUseCase.isNotMember())

override fun getInitialRoute(): Route = initialRoute
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ fun LoginScreen(
initial = UiState.Waiting
)

if (uiState.value is UiState.Success){
viewModel.navigateLogInSuccess()
}
// if (uiState.value is UiState.Success){
// viewModel.navigateLogInSuccess()
// }

Column(
modifier = Modifier
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.ndemi.garden.gym.ui.screens.main

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.ImageShader
import androidx.compose.ui.graphics.ShaderBrush
import androidx.compose.ui.graphics.TileMode
import androidx.compose.ui.res.imageResource
import androidx.navigation.NavHostController
import com.ndemi.garden.gym.R
import com.ndemi.garden.gym.navigation.NavigationHost
import com.ndemi.garden.gym.navigation.NavigationService
import com.ndemi.garden.gym.ui.theme.AppTheme
import com.ndemi.garden.gym.ui.theme.padding_screen
import com.ndemi.garden.gym.ui.widgets.BottomNavItem
import com.ndemi.garden.gym.ui.widgets.BottomNavigationWidget


@Composable
fun MainDetailsScreen(
isAuthenticated: Boolean,
isAdmin: Boolean,
navController: NavHostController,
navigationService: NavigationService,
){
Scaffold(
topBar = {},
bottomBar = {
val bottomNavItems = if (isAuthenticated) {
if (isAdmin) {
BottomNavItem.getAdminBottomItems()
} else {
BottomNavItem.getMemberBottomItems()
}
} else {
BottomNavItem.getLoginBottomItems()
}
BottomNavigationWidget(
navController,
bottomNavItems
)
},
) { innerPadding ->
val image = ImageBitmap.imageResource(R.drawable.bg_pattern)
val brush = remember(image) { ShaderBrush(ImageShader(image, TileMode.Repeated, TileMode.Repeated)) }
Column(
modifier =
Modifier
.padding(innerPadding)
.fillMaxSize()
.background(AppTheme.colors.backgroundScreen)
.background(brush, alpha = 0.05f),
verticalArrangement = Arrangement.spacedBy(padding_screen),
) {
NavigationHost(
navController = navController,
navigationService = navigationService,
)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,30 +1,11 @@
package com.ndemi.garden.gym.ui.screens.main

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.ImageShader
import androidx.compose.ui.graphics.ShaderBrush
import androidx.compose.ui.graphics.TileMode
import androidx.compose.ui.res.imageResource
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.compose.runtime.livedata.observeAsState
import androidx.navigation.compose.rememberNavController
import com.ndemi.garden.gym.R
import com.ndemi.garden.gym.navigation.NavigationHost
import com.ndemi.garden.gym.navigation.Route
import com.ndemi.garden.gym.navigation.Route.Companion.toRoute
import com.ndemi.garden.gym.ui.theme.AppTheme
import com.ndemi.garden.gym.ui.theme.padding_screen
import com.ndemi.garden.gym.ui.widgets.BottomNavItem
import com.ndemi.garden.gym.ui.widgets.BottomNavigationWidget
import com.ndemi.garden.gym.ui.widgets.LoadingScreenWidget
import com.ndemi.garden.gym.ui.widgets.WarningWidget
import cv.domain.entities.MemberType
import org.koin.androidx.compose.koinViewModel

@Composable
Expand All @@ -33,45 +14,48 @@ fun MainScreen(
) {
val navController = rememberNavController()
viewModel.setNavController(navController)
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route?.toRoute()
val authState = viewModel.authState.observeAsState()

Scaffold(
topBar = {},
bottomBar = {
val bottomNavItems = when (currentRoute) {
Route.LoginScreen -> BottomNavItem.getLoginBottomItems()
else -> {
if (viewModel.isAuthenticated() && viewModel.isAdmin()){
BottomNavItem.getAdminBottomItems()
} else if (viewModel.isAuthenticated()){
BottomNavItem.getMemberBottomItems()
} else {
BottomNavItem.getLoginBottomItems()
}
when(authState.value){
MainScreenViewModel.AuthState.Authorised -> {
val data = viewModel.loggedInMember.observeAsState()
when(val response = data.value){

is MainScreenViewModel.UiState.Error -> {
WarningWidget(title = response.message)
}

MainScreenViewModel.UiState.Loading -> {
LoadingScreenWidget()
}

is MainScreenViewModel.UiState.Success -> {
MainDetailsScreen(
isAuthenticated = true,
isAdmin = response.member.memberType != MemberType.MEMBER,
navController = navController,
navigationService = viewModel.getNavigationService()
)
}

null -> {
LoadingScreenWidget()
}
}
BottomNavigationWidget(
navController,
bottomNavItems
)
},
) { innerPadding ->
val image = ImageBitmap.imageResource(R.drawable.bg_pattern)
val brush = remember(image) { ShaderBrush(ImageShader(image, TileMode.Repeated, TileMode.Repeated)) }
Column(
modifier =
Modifier
.padding(innerPadding)
.fillMaxSize()
.background(AppTheme.colors.backgroundScreen)
.background(brush, alpha = 0.05f),
verticalArrangement = Arrangement.spacedBy(padding_screen),
) {
NavigationHost(
}

MainScreenViewModel.AuthState.UnAuthorised -> {
MainDetailsScreen(
isAuthenticated = false,
isAdmin = false,
navController = navController,
navigationService = viewModel.getNavigationService(),
navigationService = viewModel.getNavigationService()
)
}

null -> {
LoadingScreenWidget()
}
}
}

Original file line number Diff line number Diff line change
@@ -1,20 +1,67 @@
package com.ndemi.garden.gym.ui.screens.main

import androidx.compose.runtime.Immutable
import androidx.lifecycle.ViewModel
import androidx.lifecycle.liveData
import androidx.navigation.NavHostController
import com.ndemi.garden.gym.navigation.NavigationService
import com.ndemi.garden.gym.ui.utils.ErrorCodeConverter
import cv.domain.DomainResult
import cv.domain.entities.MemberEntity
import cv.domain.usecase.AuthUseCase
import kotlinx.coroutines.Dispatchers

class MainScreenViewModel(
private val navigationService: NavigationService,
private val authUseCase: AuthUseCase,
private val errorCodeConverter: ErrorCodeConverter,
) : ViewModel() {
fun setNavController(navController: NavHostController) =
navigationService.setNavController(navController)

fun getNavigationService(): NavigationService = navigationService

fun isAuthenticated() = authUseCase.isAuthenticated()
val authState = liveData(Dispatchers.IO) {
emit(AuthState.UnAuthorised)
authUseCase.getAuthState().collect{
when(it){
is DomainResult.Success ->
emit(AuthState.Authorised)

fun isAdmin() = authUseCase.isAdmin()
is DomainResult.Error ->
emit(AuthState.UnAuthorised)
}
}

}

val loggedInMember = liveData(Dispatchers.IO) {
emit(UiState.Loading)
authUseCase.getLoggedInUser().collect {

when (it) {
is DomainResult.Success ->
emit(UiState.Success(it.data))

is DomainResult.Error ->
emit(UiState.Error(errorCodeConverter.getMessage(it.error)))
}
}
}

@Immutable
sealed interface AuthState {
data object Authorised : AuthState

data object UnAuthorised : AuthState
}

@Immutable
sealed interface UiState {
data object Loading : UiState

data class Error(val message: String) : UiState

data class Success(val member: MemberEntity) : UiState
}
}
Loading

0 comments on commit 135444c

Please sign in to comment.