Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion core/data/src/main/java/com/mifos/core/data/di/DataModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import com.mifos.core.data.repository.PathTrackingRepository
import com.mifos.core.data.repository.PinPointClientRepository
import com.mifos.core.data.repository.ReportCategoryRepository
import com.mifos.core.data.repository.ReportDetailRepository
import com.mifos.core.data.repository.SearchRepository
import com.mifos.core.data.repository_imp.ActivateRepositoryImp
import com.mifos.core.data.repository_imp.CenterDetailsRepositoryImp
import com.mifos.core.data.repository_imp.CenterListRepositoryImp
Expand All @@ -43,6 +44,7 @@ import com.mifos.core.data.repository_imp.PathTrackingRepositoryImp
import com.mifos.core.data.repository_imp.PinPointClientRepositoryImp
import com.mifos.core.data.repository_imp.ReportCategoryRepositoryImp
import com.mifos.core.data.repository_imp.ReportDetailRepositoryImp
import com.mifos.core.data.repository_imp.SearchRepositoryImp
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
Expand All @@ -63,6 +65,9 @@ abstract class DataModule {
groupsListRepositoryImpl: GroupsListRepositoryImpl
): GroupsListRepository

@Binds
internal abstract fun provideSearchRepository(repository: SearchRepositoryImp): SearchRepository

@Binds
internal abstract fun provideGroupDetailsRepository(impl: GroupDetailsRepositoryImp): GroupDetailsRepository

Expand Down Expand Up @@ -92,7 +97,7 @@ abstract class DataModule {

@Binds
internal abstract fun bindPinpointRepository(impl: PinPointClientRepositoryImp): PinPointClientRepository

@Binds
internal abstract fun bindActivateRepository(impl: ActivateRepositoryImp): ActivateRepository

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package com.mifos.mifosxdroid.online.search
package com.mifos.core.data.repository

import com.mifos.core.objects.SearchedEntity
import rx.Observable
import kotlinx.coroutines.flow.Flow

/**
* Created by Aditya Gupta on 06/08/23.
*/
interface SearchRepository {

fun searchResources(
suspend fun searchResources(
query: String?,
resources: String?,
exactMatch: Boolean?
): Observable<List<SearchedEntity>>
): Flow<List<SearchedEntity>>

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.mifos.core.data.repository_imp

import com.mifos.core.common.network.Dispatcher
import com.mifos.core.common.network.MifosDispatchers
import com.mifos.core.data.repository.SearchRepository
import com.mifos.core.network.datamanager.DataManagerSearch
import com.mifos.core.objects.SearchedEntity
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import javax.inject.Inject

/**
* Created by Aditya Gupta on 06/08/23.
*/
class SearchRepositoryImp @Inject constructor(
private val dataManagerSearch: DataManagerSearch,
@Dispatcher(MifosDispatchers.IO)
private val ioDispatcher: CoroutineDispatcher,
) : SearchRepository {

override suspend fun searchResources(
query: String?,
resources: String?,
exactMatch: Boolean?
): Flow<List<SearchedEntity>> = flow {
val result = dataManagerSearch.searchResources(query, resources, exactMatch)
emit(result)
}.flowOn(ioDispatcher)
.distinctUntilChanged()
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.mifos.core.designsystem.theme.BluePrimary
Expand Down Expand Up @@ -142,6 +143,8 @@ fun MifosOutlinedTextField(
Text(
text = label,
style = MaterialTheme.typography.labelMedium,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
},
leadingIcon = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ fun MifosPagingAppendProgress() {

@Composable
fun MifosCircularProgress(
contentDesc: String = "loadingIndicator"
modifier: Modifier = Modifier,
contentDesc: String = "loadingIndicator",
) {
Box(
modifier = Modifier
modifier = modifier
.fillMaxSize()
.semantics { contentDescription = contentDesc },
contentAlignment = Alignment.Center
Expand All @@ -60,5 +61,4 @@ fun MifosCircularProgress(
color = DarkGray
)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
package com.mifos.core.designsystem.component

import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FabPosition
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
Expand All @@ -12,8 +14,11 @@ import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.contentColorFor
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontStyle
Expand Down Expand Up @@ -77,7 +82,34 @@ fun MifosScaffold(
snackbarHost = { snackbarHostState?.let { SnackbarHost(it) } },
containerColor = White,
bottomBar = bottomBar,
floatingActionButton = floatingActionButton
floatingActionButton = floatingActionButton,
) { padding ->
content(padding)
}
}

@Composable
fun MifosScaffold(
modifier: Modifier = Modifier,
topBar: @Composable () -> Unit = {},
bottomBar: @Composable () -> Unit = {},
floatingActionButton: @Composable () -> Unit = {},
snackbarHostState: SnackbarHostState = remember { SnackbarHostState() },
floatingActionButtonPosition: FabPosition = FabPosition.End,
containerColor: Color = Color.White,
contentColor: Color = contentColorFor(containerColor),
content: @Composable (PaddingValues) -> Unit
) {
Scaffold(
modifier = modifier,
topBar = topBar,
floatingActionButton = floatingActionButton,
floatingActionButtonPosition = floatingActionButtonPosition,
snackbarHost = { SnackbarHost(snackbarHostState) },
bottomBar = bottomBar,
containerColor = containerColor,
contentColor = contentColor,
contentWindowInsets = WindowInsets(0, 0, 0, 0)
) { padding ->
content(padding)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import javax.inject.Singleton
*/
@Singleton
class DataManagerSearch @Inject constructor(private val baseApiManager: BaseApiManager) {
fun searchResources(
suspend fun searchResources(
query: String?, resources: String?,
exactMatch: Boolean?
): Observable<List<SearchedEntity>> {
): List<SearchedEntity> {
return baseApiManager.searchApi.searchResources(query, resources, exactMatch)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import rx.Observable
*/
interface SearchService {
@GET(APIEndPoint.SEARCH)
fun searchResources(
suspend fun searchResources(
@Query("query") clientName: String?,
@Query("resource") resources: String?,
@Query("exactMatch") exactMatch: Boolean?
): Observable<List<SearchedEntity>>
): List<SearchedEntity>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.mifos.core.testing.repository

import com.mifos.core.data.repository.SearchRepository
import com.mifos.core.objects.SearchedEntity
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.update
import org.jetbrains.annotations.TestOnly

class TestSearchRepository: SearchRepository {

private val sampleResults = MutableStateFlow(emptyList<SearchedEntity>())

override suspend fun searchResources(
query: String?,
resources: String?,
exactMatch: Boolean?
): Flow<List<SearchedEntity>> {
return sampleResults.map { list ->
when {
query.isNullOrBlank() && resources.isNullOrBlank() -> emptyList()
else -> {
list.asSequence().filter { entity ->
(resources.isNullOrBlank() || entity.entityType.equals(resources, ignoreCase = true)) &&
(query.isNullOrBlank() || when {
exactMatch == true -> entity.entityName.equals(query, ignoreCase = true) ||
entity.entityAccountNo.equals(query, ignoreCase = true) || entity.parentName.equals(query, true)

else -> entity.entityName?.contains(query, ignoreCase = true) == true ||
entity.entityAccountNo?.contains(query, ignoreCase = true) == true ||
entity.parentName?.contains(query, true) == true
})
}.toList()
}
}
}
}

@TestOnly
fun addSampleResults(results: List<SearchedEntity>) {
sampleResults.update { results }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package com.mifos.core.ui.components

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp

enum class FabType {
CLIENT, CENTER, GROUP
}

sealed class FabButtonState {
data object Collapsed : FabButtonState()

data object Expand : FabButtonState()

fun isExpanded() = this == Expand

fun toggleValue() = if (isExpanded()) {
Collapsed
} else {
Expand
}
}

data class FabButton(
val fabType: FabType,
val iconRes: Int,
)

@Composable
fun FabItem(
modifier: Modifier = Modifier,
fabButton: FabButton,
onFabClick: (FabType) -> Unit
) {
FloatingActionButton(
onClick = {
onFabClick(fabButton.fabType)
},
modifier = modifier
.size(48.dp)
) {
Icon(
painter = painterResource(id = fabButton.iconRes),
contentDescription = fabButton.fabType.name
)
}
}

@Composable
fun MultiFloatingActionButton(
modifier: Modifier = Modifier,
fabButtons: List<FabButton>,
fabButtonState: FabButtonState,
onFabButtonStateChange: (FabButtonState) -> Unit,
onFabClick: (FabType) -> Unit,
) {
val rotation by animateFloatAsState(
if (fabButtonState.isExpanded())
45f
else
0f, label = "mainFabRotation"
)

Column(
modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally
) {
AnimatedVisibility(
visible = fabButtonState.isExpanded(),
enter = fadeIn() + expandVertically(),
exit = fadeOut() + shrinkVertically()
) {
Column {
fabButtons.forEach {
FabItem(
fabButton = it,
onFabClick = onFabClick
)
Spacer(modifier = Modifier.height(24.dp))
}
}
}

FloatingActionButton(
onClick = {
onFabButtonStateChange(fabButtonState.toggleValue())
},
modifier = Modifier
.rotate(rotation)
) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = "mainFabIcon"
)
}
}
}
Loading