Skip to content

Commit

Permalink
extract filters column to its own composable
Browse files Browse the repository at this point in the history
  • Loading branch information
ndiritumichael committed Oct 2, 2024
1 parent 54fffd6 commit 11d3798
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 121 deletions.
132 changes: 11 additions & 121 deletions feature/issues/src/main/java/com/devmike/issues/screen/IssuesScreen.kt
Original file line number Diff line number Diff line change
@@ -1,46 +1,35 @@
package com.devmike.issues.screen

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.Button
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilterChip
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
Expand All @@ -50,12 +39,11 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.paging.LoadState
import androidx.paging.PagingData
import androidx.paging.compose.collectAsLazyPagingItems
import com.devmike.domain.helper.IssueState
import com.devmike.domain.models.IssueModel
import com.devmike.domain.models.LabelModel
import com.devmike.issues.screen.components.AssigneesScreen
import com.devmike.issues.screen.components.FiltersScreen
import com.devmike.issues.screen.components.IssueCard
import com.devmike.issues.screen.components.IssueStateChip
import com.devmike.issues.screen.components.LabelsScreen
import com.devmike.issues.screen.components.NoIssuesFoundScreen
import com.devmike.issues.screen.components.SearchTextField
Expand All @@ -77,13 +65,6 @@ fun IssuesScreen(
val selectedAssignes by viewModel.selectedAssignees.collectAsStateWithLifecycle()
val selectedLabels by viewModel.selectedLabels.collectAsStateWithLifecycle()

val showClearChip =
remember(selectedAssignes, selectedLabels) {
derivedStateOf {
selectedAssignes.isNotEmpty() || selectedLabels.isNotEmpty()
}
}.value

val selectedIssueState by viewModel.selectedIssueState.collectAsStateWithLifecycle()

AssigneesScreen(
Expand Down Expand Up @@ -162,104 +143,15 @@ fun IssuesScreen(
),
) {
stickyHeader {
Surface {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth(),
) {
Row(
modifier = Modifier.padding(horizontal = 8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
IssueStateChip(
selectedState = selectedIssueState,
states = IssueState.entries,
onStateSelected = {
viewModel.modifyIssueState(it)
},
)
FilterChip(
selected = selectedLabels.isNotEmpty(),
onClick = { showLabelsDialog = true },
leadingIcon = {
if (selectedLabels.isNotEmpty()) {
Box(
modifier =
Modifier
.background(
MaterialTheme.colorScheme.onPrimary,
CircleShape,
).clip(CircleShape)
.size(15.dp),
) {
Text(
text = "${
selectedLabels.size
}",
modifier =
Modifier
.align(Alignment.Center),
style = MaterialTheme.typography.labelSmall,
)
}
}
},
label = {
Text(
text = "Labels",
)
},
)

FilterChip(
selected = selectedAssignes.isNotEmpty(),
onClick = { showAssigneesDialog = true },
leadingIcon = {
if (selectedAssignes.isNotEmpty()) {
Box(
modifier =
Modifier
.background(
MaterialTheme.colorScheme.onPrimary,
CircleShape,
).clip(CircleShape)
.size(15.dp),
) {
Text(
text = "${
selectedAssignes.size
}",
modifier =
Modifier
.align(Alignment.Center),
style = MaterialTheme.typography.labelSmall,
)
}
}
},
label = {
Text(
text =

"Assignees",
)
},
)

AnimatedVisibility(showClearChip) {
FilterChip(
selected = showClearChip,
onClick = { viewModel.clearFilters() },
label = { Text(text = "Clear Filters") },
)
}
}
HorizontalDivider()
}
}
FiltersScreen(
selectedAssignes = selectedAssignes.map { it.username },
selectedLabels = selectedLabels.map { it.name },
selectedIssueState = selectedIssueState,
showLabelsDialog = { showLabelsDialog = true },
showAssigneesDialog = { showAssigneesDialog = true },
clearFilters = viewModel::clearFilters,
modifyIssueState = viewModel::modifyIssueState,
)
}
items(issues.itemCount) { index ->
val issue = issues[index]
Expand All @@ -282,9 +174,7 @@ fun IssuesScreen(
loadState.refresh is LoadState.Loading -> {
item {
Box(
modifier =
Modifier
.padding(),
modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.Center,
) {
CircularProgressIndicator(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package com.devmike.issues.screen.components

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.FilterChip
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import com.devmike.domain.helper.IssueState

@Composable
fun FiltersScreen(
selectedAssignes: List<String>,
selectedLabels: List<String>,
selectedIssueState: IssueState,
showLabelsDialog: () -> Unit,
showAssigneesDialog: () -> Unit,
clearFilters: () -> Unit,
modifyIssueState: (IssueState) -> Unit,
) {
val showClearChip = selectedAssignes.isNotEmpty() || selectedLabels.isNotEmpty()
Surface {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth(),
) {
Row(
modifier = Modifier.padding(horizontal = 8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
IssueStateChip(
selectedState = selectedIssueState,
states = IssueState.entries,
onStateSelected = modifyIssueState,
)
FilterChip(
selected = selectedLabels.isNotEmpty(),
onClick = showLabelsDialog,
leadingIcon = {
if (selectedLabels.isNotEmpty()) {
Box(
modifier =
Modifier
.background(
MaterialTheme.colorScheme.onPrimary,
CircleShape,
).clip(CircleShape)
.size(15.dp),
) {
Text(
text = "${
selectedLabels.size
}",
modifier =
Modifier
.align(Alignment.Center),
style = MaterialTheme.typography.labelSmall,
)
}
}
},
label = {
Text(
text = "Labels",
)
},
)

FilterChip(
selected = selectedAssignes.isNotEmpty(),
onClick = showAssigneesDialog,
leadingIcon = {
if (selectedAssignes.isNotEmpty()) {
Box(
modifier =
Modifier
.background(
MaterialTheme.colorScheme.onPrimary,
CircleShape,
).clip(CircleShape)
.size(15.dp),
) {
Text(
text = "${
selectedAssignes.size
}",
modifier =
Modifier
.align(Alignment.Center),
style = MaterialTheme.typography.labelSmall,
)
}
}
},
label = {
Text(
text =

"Assignees",
)
},
)

AnimatedVisibility(showClearChip) {
FilterChip(
selected = showClearChip,
onClick = clearFilters,
label = { Text(text = "Clear Filters") },
)
}
}
HorizontalDivider()
}
}
}

0 comments on commit 11d3798

Please sign in to comment.