Skip to content

Commit

Permalink
Merge pull request #160 from boostcampwm-2024/feature/#159-pick-list-…
Browse files Browse the repository at this point in the history
…order

[feature] 픽 목록 정렬 기준 추가
  • Loading branch information
meanjoo authored Dec 25, 2024
2 parents 9a89b6e + 894d002 commit 6fd934e
Show file tree
Hide file tree
Showing 16 changed files with 363 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import com.squirtles.musicroad.map.MapViewModel
import com.squirtles.musicroad.media.PlayerServiceViewModel
import com.squirtles.musicroad.pick.DetailPickScreen
import com.squirtles.musicroad.picklist.PickListScreen
import com.squirtles.musicroad.picklist.PickListType
import com.squirtles.musicroad.profile.ProfileScreen
import com.squirtles.musicroad.setting.SettingNotificationScreen
import com.squirtles.musicroad.setting.SettingProfileScreen
Expand Down Expand Up @@ -54,7 +55,7 @@ fun MainNavGraph(

PickListScreen(
userId = userId,
isFavoritePicks = true,
pickListType = PickListType.FAVORITE,
onBackClick = { navController.navigateUp() },
onItemClick = { pickId -> navigationActions.navigateToPickDetail(pickId) }
)
Expand All @@ -68,7 +69,7 @@ fun MainNavGraph(

PickListScreen(
userId = userId,
isFavoritePicks = false,
pickListType = PickListType.CREATED,
onBackClick = { navController.navigateUp() },
onItemClick = { pickId -> navigationActions.navigateToPickDetail(pickId) }
)
Expand Down
135 changes: 135 additions & 0 deletions app/src/main/java/com/squirtles/musicroad/picklist/OrderBottomSheet.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package com.squirtles.musicroad.picklist

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.displayCutoutPadding
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import com.squirtles.domain.model.Order
import com.squirtles.musicroad.R
import com.squirtles.musicroad.common.Constants.DEFAULT_PADDING
import com.squirtles.musicroad.ui.theme.Dark
import com.squirtles.musicroad.ui.theme.Primary
import com.squirtles.musicroad.ui.theme.White
import kotlinx.coroutines.launch

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun OrderBottomSheet(
isFavoritePicks: Boolean,
currentOrder: Order,
onDismissRequest: () -> Unit,
onOrderClick: (Order) -> Unit,
) {
val sheetState = rememberModalBottomSheetState()
val scope = rememberCoroutineScope()
val orderList = listOf(
stringResource(if (isFavoritePicks) R.string.latest_favorite_order else R.string.latest_create_order) to Order.LATEST,
stringResource(if (isFavoritePicks) R.string.oldest_favorite_order else R.string.oldest_create_order) to Order.OLDEST,
stringResource(R.string.favorite_count_desc) to Order.FAVORITE_DESC,
)

ModalBottomSheet(
onDismissRequest = onDismissRequest,
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.displayCutoutPadding()
.navigationBarsPadding(),
sheetState = sheetState,
containerColor = Dark,
scrimColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.32f),
) {
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
orderList.forEach { (orderText, order) ->
BottomSheetMenu(
text = orderText,
isSelected = currentOrder == order,
) {
scope
.launch {
if (currentOrder != order) {
onOrderClick(order)
}
sheetState.hide()
}
.invokeOnCompletion {
if (!sheetState.isVisible) {
onDismissRequest()
}
}
}
}

HorizontalDivider(color = White)
BottomSheetMenu(
text = stringResource(R.string.close_button_text),
textAlign = TextAlign.Center,
) {
scope
.launch { sheetState.hide() }
.invokeOnCompletion {
if (!sheetState.isVisible) {
onDismissRequest()
}
}
}
}
}
}

@Composable
private fun BottomSheetMenu(
text: String,
textAlign: TextAlign = TextAlign.Start,
isSelected: Boolean = false,
onClick: () -> Unit,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.clickable { onClick() }
.padding(DEFAULT_PADDING),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = text,
modifier = Modifier.weight(1f),
color = if (isSelected) Primary else White,
fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal,
textAlign = textAlign,
)

if (isSelected) {
Icon(
imageVector = Icons.Default.Check,
contentDescription = stringResource(R.string.selected_icon_description),
tint = Primary
)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,30 +1,41 @@
package com.squirtles.musicroad.picklist

import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
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.displayCutoutPadding
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
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.graphics.Brush
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.wear.compose.material.CircularProgressIndicator
import com.squirtles.domain.model.Order
import com.squirtles.musicroad.R
import com.squirtles.musicroad.common.Constants.COLOR_STOPS
import com.squirtles.musicroad.common.Constants.DEFAULT_PADDING
Expand All @@ -37,26 +48,30 @@ import com.squirtles.musicroad.ui.theme.White
@Composable
fun PickListScreen(
userId: String,
isFavoritePicks: Boolean,
pickListType: PickListType,
onBackClick: () -> Unit,
onItemClick: (String) -> Unit,
pickListViewModel: PickListViewModel = hiltViewModel()
) {
val isLandscape = LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE
val uiState by pickListViewModel.pickListUiState.collectAsStateWithLifecycle()
var showOrderBottomSheet by rememberSaveable { mutableStateOf(false) }

LaunchedEffect(Unit) {
if (isFavoritePicks) {
pickListViewModel.fetchFavoritePicks(userId)
} else {
pickListViewModel.fetchMyPicks(userId)
when (pickListType) {
PickListType.FAVORITE -> pickListViewModel.fetchFavoritePicks(userId)
PickListType.CREATED -> pickListViewModel.fetchMyPicks(userId)
}
}

Scaffold(
topBar = {
DefaultTopAppBar(
title = stringResource(
if (isFavoritePicks) R.string.favorite_picks_top_app_bar_title else R.string.my_picks_top_app_bar_title
when (pickListType) {
PickListType.FAVORITE -> R.string.favorite_picks_top_app_bar_title
PickListType.CREATED -> R.string.my_picks_top_app_bar_title
}
),
onBackClick = onBackClick
)
Expand All @@ -67,6 +82,7 @@ fun PickListScreen(
.fillMaxSize()
.background(Brush.verticalGradient(colorStops = COLOR_STOPS))
.padding(innerPadding)
.then(if (isLandscape) Modifier.displayCutoutPadding() else Modifier)
) {
when (uiState) {
PickListUiState.Loading -> {
Expand All @@ -80,6 +96,7 @@ fun PickListScreen(

is PickListUiState.Success -> {
val pickList = (uiState as PickListUiState.Success).pickList
val order = (uiState as PickListUiState.Success).order

Column(
modifier = Modifier.fillMaxSize()
Expand All @@ -96,13 +113,25 @@ fun PickListScreen(
defaultColor = White,
)

Text(
text = stringResource(
if (isFavoritePicks) R.string.latest_favorite_order else R.string.latest_create_order
),
color = White,
style = MaterialTheme.typography.bodyMedium
)
Box(
modifier = Modifier
.wrapContentSize()
.clip(CircleShape)
.clickable { showOrderBottomSheet = true }
) {
Text(
text = getOrderString(
pickListType = pickListType,
order = order
),
modifier = Modifier.padding(
horizontal = DEFAULT_PADDING / 2,
vertical = DEFAULT_PADDING / 4
),
color = White,
style = MaterialTheme.typography.bodyMedium
)
}
}

VerticalSpacer(8)
Expand All @@ -114,7 +143,10 @@ fun PickListScreen(
) {
Text(
text = stringResource(
if (isFavoritePicks) R.string.favorite_picks_empty else R.string.my_picks_empty
when (pickListType) {
PickListType.FAVORITE -> R.string.favorite_picks_empty
PickListType.CREATED -> R.string.my_picks_empty
}
),
color = White,
style = MaterialTheme.typography.titleMedium
Expand All @@ -130,7 +162,7 @@ fun PickListScreen(
) { pick ->
PickItem(
song = pick.song,
createdByOthers = isFavoritePicks,
createdByOthers = pickListType == PickListType.FAVORITE,
createUserName = pick.createdBy.userName,
favoriteCount = pick.favoriteCount,
comment = pick.comment,
Expand All @@ -155,4 +187,38 @@ fun PickListScreen(
}
}
}

if (showOrderBottomSheet) {
OrderBottomSheet(
isFavoritePicks = pickListType == PickListType.FAVORITE,
currentOrder = (uiState as PickListUiState.Success).order,
onDismissRequest = { showOrderBottomSheet = false },
onOrderClick = { order ->
pickListViewModel.setListOrder(pickListType, order)
},
)
}
}

@Composable
private fun getOrderString(pickListType: PickListType, order: Order): String {
return "${
stringResource(
when (order) {
Order.LATEST ->
when (pickListType) {
PickListType.FAVORITE -> R.string.latest_favorite_order
PickListType.CREATED -> R.string.latest_create_order
}
Order.OLDEST ->
when (pickListType) {
PickListType.FAVORITE -> R.string.oldest_favorite_order
PickListType.CREATED -> R.string.oldest_create_order
}
Order.FAVORITE_DESC -> R.string.favorite_count_desc
}
)
}"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.squirtles.musicroad.picklist

enum class PickListType {
FAVORITE, CREATED
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package com.squirtles.musicroad.picklist

import com.squirtles.domain.model.Order
import com.squirtles.domain.model.Pick

sealed class PickListUiState {
data object Loading: PickListUiState()
data class Success(val pickList: List<Pick>) : PickListUiState()
data object Loading : PickListUiState()
data class Success(val pickList: List<Pick>, val order: Order) : PickListUiState()
data object Error : PickListUiState()
}
Loading

0 comments on commit 6fd934e

Please sign in to comment.