diff --git a/app/src/main/java/com/poti/android/core/designsystem/component/navigation/PotiHeaderPage.kt b/app/src/main/java/com/poti/android/core/designsystem/component/navigation/PotiHeaderPage.kt index 06f496fc..4ce936d6 100644 --- a/app/src/main/java/com/poti/android/core/designsystem/component/navigation/PotiHeaderPage.kt +++ b/app/src/main/java/com/poti/android/core/designsystem/component/navigation/PotiHeaderPage.kt @@ -61,7 +61,7 @@ fun PotiHeaderPage( subTitle?.let { Text( text = subTitle, - style = PotiTheme.typography.caption10m.copy( + style = PotiTheme.typography.caption12m.copy( lineHeight = 1.35.em, ), color = PotiTheme.colors.gray700, diff --git a/app/src/main/java/com/poti/android/core/designsystem/component/navigation/PotiHeaderPrimary.kt b/app/src/main/java/com/poti/android/core/designsystem/component/navigation/PotiHeaderPrimary.kt index f3c16d3b..c6b2f267 100644 --- a/app/src/main/java/com/poti/android/core/designsystem/component/navigation/PotiHeaderPrimary.kt +++ b/app/src/main/java/com/poti/android/core/designsystem/component/navigation/PotiHeaderPrimary.kt @@ -46,7 +46,7 @@ fun PotiHeaderPrimary( ) } else { Icon( - imageVector = ImageVector.vectorResource(R.drawable.ic_logo), + imageVector = ImageVector.vectorResource(R.drawable.ic_poti_logo), contentDescription = null, tint = Color.Unspecified, ) diff --git a/app/src/main/java/com/poti/android/data/mapper/home/GoodsCategoryMapper.kt b/app/src/main/java/com/poti/android/data/mapper/home/GoodsCategoryMapper.kt index 36f3e9e9..4dfd2602 100644 --- a/app/src/main/java/com/poti/android/data/mapper/home/GoodsCategoryMapper.kt +++ b/app/src/main/java/com/poti/android/data/mapper/home/GoodsCategoryMapper.kt @@ -2,11 +2,11 @@ package com.poti.android.data.mapper.home import com.poti.android.data.remote.dto.response.home.GoodsCategoryResponseDto import com.poti.android.data.remote.dto.response.home.GroupItemDto -import com.poti.android.domain.model.party.GoodsCategory import com.poti.android.domain.model.party.GroupItem +import com.poti.android.domain.model.party.ProductCategory -fun GoodsCategoryResponseDto.toDomain(): GoodsCategory = - GoodsCategory( +fun GoodsCategoryResponseDto.toDomain(): ProductCategory = + ProductCategory( nickname = nickname, mainArtist = mainArtist, mainArtistId = mainArtistId, diff --git a/app/src/main/java/com/poti/android/data/mapper/home/HomeMapper.kt b/app/src/main/java/com/poti/android/data/mapper/home/HomeMapper.kt index 3c6b8a10..bc3d4796 100644 --- a/app/src/main/java/com/poti/android/data/mapper/home/HomeMapper.kt +++ b/app/src/main/java/com/poti/android/data/mapper/home/HomeMapper.kt @@ -10,8 +10,8 @@ import com.poti.android.domain.model.home.HomeContent fun HomeResponseDto.toDomain(): HomeContent = HomeContent( nickname = nickname, - mainArtist = mainArtist.orEmpty(), - mainArtistId = mainArtistId ?: 0L, + mainArtist = mainArtist, + mainArtistId = mainArtistId, myGroupItems = myGroupItems.orEmpty().map { it.toDomain() }, otherGroupItems = otherGroupItems.map { it.toDomain() }, banners = banners.map { it.toDomain() }, @@ -20,7 +20,7 @@ fun HomeResponseDto.toDomain(): HomeContent = HomeContent( fun MyGroupItemDto.toDomain(): GroupItem = GroupItem( postTitle = postTitle.orEmpty(), artist = artist.orEmpty(), - artistId = artistId ?: 0L, + artistId = artistId ?: 0, postImage = postImage.orEmpty(), postCount = postCount ?: 0, tag = tag.orEmpty(), @@ -29,7 +29,7 @@ fun MyGroupItemDto.toDomain(): GroupItem = GroupItem( fun OtherGroupItemDto.toDomain(): GroupItem = GroupItem( postTitle = postTitle, artist = artist, - artistId = artistId ?: 0L, + artistId = artistId ?: 0, postImage = postImage.orEmpty(), postCount = postCount, tag = tag, diff --git a/app/src/main/java/com/poti/android/data/mapper/party/ProductPartyListMapper.kt b/app/src/main/java/com/poti/android/data/mapper/party/ProductPartyListMapper.kt index 5c991292..3701b6e7 100644 --- a/app/src/main/java/com/poti/android/data/mapper/party/ProductPartyListMapper.kt +++ b/app/src/main/java/com/poti/android/data/mapper/party/ProductPartyListMapper.kt @@ -16,7 +16,7 @@ private fun PartyDto.toDomain(): PartySummary = PartySummary( partyId = potId, price = price, - goodsImageUrl = thumbnailUrl.orEmpty(), + productImageUrl = thumbnailUrl.orEmpty(), currentCount = currentCount, totalCount = totalCount, availableMembers = availableMembers, diff --git a/app/src/main/java/com/poti/android/data/mapper/user/MyPageMapper.kt b/app/src/main/java/com/poti/android/data/mapper/user/MyPageMapper.kt index 2367ef9a..7253d159 100644 --- a/app/src/main/java/com/poti/android/data/mapper/user/MyPageMapper.kt +++ b/app/src/main/java/com/poti/android/data/mapper/user/MyPageMapper.kt @@ -1,9 +1,6 @@ package com.poti.android.data.mapper.user import com.poti.android.data.remote.dto.response.user.MyPageResponseDto -import com.poti.android.data.remote.dto.response.user.ParticipationSummaryDto -import com.poti.android.data.remote.dto.response.user.RecruitSummaryDto -import com.poti.android.domain.model.user.HistorySummary import com.poti.android.domain.model.user.UserMyPage import java.lang.String.format import java.util.Locale @@ -21,17 +18,3 @@ fun MyPageResponseDto.toDomain(): UserMyPage = participationSummary = participationSummary.toDomain(), recruitSummary = recruitSummary.toDomain(), ) - -fun ParticipationSummaryDto.toDomain(): HistorySummary = - HistorySummary( - total = total, - inProgress = inProgress, - completed = completed, - ) - -fun RecruitSummaryDto.toDomain(): HistorySummary = - HistorySummary( - total = total, - inProgress = inProgress, - completed = completed, - ) diff --git a/app/src/main/java/com/poti/android/data/mapper/ProfileMapper.kt b/app/src/main/java/com/poti/android/data/mapper/user/ProfileMapper.kt similarity index 81% rename from app/src/main/java/com/poti/android/data/mapper/ProfileMapper.kt rename to app/src/main/java/com/poti/android/data/mapper/user/ProfileMapper.kt index bcaf06bb..068fe280 100644 --- a/app/src/main/java/com/poti/android/data/mapper/ProfileMapper.kt +++ b/app/src/main/java/com/poti/android/data/mapper/user/ProfileMapper.kt @@ -1,7 +1,7 @@ -package com.poti.android.data.mapper +package com.poti.android.data.mapper.user import com.poti.android.data.remote.dto.response.user.ProfileResponseDto -import com.poti.android.data.remote.dto.response.user.RecruitSummaryDto +import com.poti.android.data.remote.dto.response.user.ProfileSummaryDto import com.poti.android.domain.model.user.HistorySummary import com.poti.android.domain.model.user.UserProfile @@ -18,7 +18,7 @@ fun ProfileResponseDto.toDomain(): UserProfile = recruitSummary = recruitSummary.toDomain(), ) -fun RecruitSummaryDto.toDomain(): HistorySummary = +fun ProfileSummaryDto.toDomain(): HistorySummary = HistorySummary( total = total, inProgress = inProgress, diff --git a/app/src/main/java/com/poti/android/data/remote/dto/request/user/OnboardingRequestDto.kt b/app/src/main/java/com/poti/android/data/remote/dto/request/user/OnboardingRequestDto.kt index a041a363..14a0c596 100644 --- a/app/src/main/java/com/poti/android/data/remote/dto/request/user/OnboardingRequestDto.kt +++ b/app/src/main/java/com/poti/android/data/remote/dto/request/user/OnboardingRequestDto.kt @@ -8,5 +8,5 @@ data class OnboardingRequestDto( @SerialName("nickname") val nickname: String, @SerialName("favoriteArtistId") - val favoriteArtistId: Long, + val favoriteArtistId: Long?, ) diff --git a/app/src/main/java/com/poti/android/data/remote/dto/response/user/MyPageResponseDto.kt b/app/src/main/java/com/poti/android/data/remote/dto/response/user/MyPageResponseDto.kt index dd0608bd..ecc0076f 100644 --- a/app/src/main/java/com/poti/android/data/remote/dto/response/user/MyPageResponseDto.kt +++ b/app/src/main/java/com/poti/android/data/remote/dto/response/user/MyPageResponseDto.kt @@ -24,7 +24,7 @@ data class MyPageResponseDto( @SerialName("favoriteArtistName") val favoriteArtistName: String?, @SerialName("participationSummary") - val participationSummary: ParticipationSummaryDto, + val participationSummary: ProfileSummaryDto, @SerialName("recruitSummary") - val recruitSummary: RecruitSummaryDto, + val recruitSummary: ProfileSummaryDto, ) diff --git a/app/src/main/java/com/poti/android/data/remote/dto/response/user/OnboardingResponseDto.kt b/app/src/main/java/com/poti/android/data/remote/dto/response/user/OnboardingResponseDto.kt index ceb2eaeb..ea45ed66 100644 --- a/app/src/main/java/com/poti/android/data/remote/dto/response/user/OnboardingResponseDto.kt +++ b/app/src/main/java/com/poti/android/data/remote/dto/response/user/OnboardingResponseDto.kt @@ -6,7 +6,7 @@ import kotlinx.serialization.Serializable @Serializable data class OnboardingResponseDto( @SerialName("nickname") - val nickname: String, + val nickname: String?, @SerialName("favoriteArtistId") - val favoriteArtistId: Long, + val favoriteArtistId: Long?, ) diff --git a/app/src/main/java/com/poti/android/data/remote/dto/response/user/ProfileResponseDto.kt b/app/src/main/java/com/poti/android/data/remote/dto/response/user/ProfileResponseDto.kt index 7bf34d49..263b41a5 100644 --- a/app/src/main/java/com/poti/android/data/remote/dto/response/user/ProfileResponseDto.kt +++ b/app/src/main/java/com/poti/android/data/remote/dto/response/user/ProfileResponseDto.kt @@ -22,5 +22,5 @@ data class ProfileResponseDto( @SerialName("hasFavoriteArtist") val hasFavoriteArtist: Boolean, @SerialName("recruitSummary") - val recruitSummary: RecruitSummaryDto, + val recruitSummary: ProfileSummaryDto, ) diff --git a/app/src/main/java/com/poti/android/data/remote/dto/response/user/ProfileSummaryDto.kt b/app/src/main/java/com/poti/android/data/remote/dto/response/user/ProfileSummaryDto.kt index d62b3ca6..77f56a58 100644 --- a/app/src/main/java/com/poti/android/data/remote/dto/response/user/ProfileSummaryDto.kt +++ b/app/src/main/java/com/poti/android/data/remote/dto/response/user/ProfileSummaryDto.kt @@ -4,17 +4,7 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable -data class ParticipationSummaryDto( - @SerialName("total") - val total: Int, - @SerialName("inProgress") - val inProgress: Int, - @SerialName("completed") - val completed: Int, -) - -@Serializable -data class RecruitSummaryDto( +data class ProfileSummaryDto( @SerialName("total") val total: Int, @SerialName("inProgress") diff --git a/app/src/main/java/com/poti/android/data/repository/HomeRepositoryImpl.kt b/app/src/main/java/com/poti/android/data/repository/HomeRepositoryImpl.kt index 3799d951..06701a22 100644 --- a/app/src/main/java/com/poti/android/data/repository/HomeRepositoryImpl.kt +++ b/app/src/main/java/com/poti/android/data/repository/HomeRepositoryImpl.kt @@ -5,7 +5,7 @@ import com.poti.android.core.network.util.HttpResponseHandler import com.poti.android.data.mapper.home.toDomain import com.poti.android.data.remote.datasource.HomeRemoteDataSource import com.poti.android.domain.model.home.HomeContent -import com.poti.android.domain.model.party.GoodsCategory +import com.poti.android.domain.model.party.ProductCategory import com.poti.android.domain.repository.HomeRepository import javax.inject.Inject @@ -25,7 +25,7 @@ class HomeRepositoryImpl @Inject constructor( size: Int?, sort: String?, artistId: Long?, - ): Result = httpResponseHandler.safeApiCall { + ): Result = httpResponseHandler.safeApiCall { homeRemoteDataSource.getGoodsCategoryList( page = page, size = size, diff --git a/app/src/main/java/com/poti/android/data/repository/UserRepositoryImpl.kt b/app/src/main/java/com/poti/android/data/repository/UserRepositoryImpl.kt index 0590adf8..639ce817 100644 --- a/app/src/main/java/com/poti/android/data/repository/UserRepositoryImpl.kt +++ b/app/src/main/java/com/poti/android/data/repository/UserRepositoryImpl.kt @@ -2,8 +2,6 @@ package com.poti.android.data.repository import com.poti.android.core.network.model.handleApiResponse import com.poti.android.core.network.util.HttpResponseHandler -import com.poti.android.data.mapper.artist.toDomain -import com.poti.android.data.mapper.toDomain import com.poti.android.data.mapper.user.toDomain import com.poti.android.data.remote.datasource.UserRemoteDataSource import com.poti.android.data.remote.dto.request.user.NicknameDuplicateRequestDto @@ -19,13 +17,15 @@ class UserRepositoryImpl @Inject constructor( ) : UserRepository { override suspend fun patchOnboarding( nickname: String, - favoriteArtistId: Long, + favoriteArtistId: Long?, ): Result = httpResponseHandler.safeApiCall { val requestDto = OnboardingRequestDto( nickname = nickname, favoriteArtistId = favoriteArtistId, ) userRemoteDataSource.patchOnboarding(onboardingRequest = requestDto) + .handleApiResponse() + .getOrThrow() } override suspend fun postNicknameDuplicate(nickname: String): Result = diff --git a/app/src/main/java/com/poti/android/domain/model/home/HomeContent.kt b/app/src/main/java/com/poti/android/domain/model/home/HomeContent.kt index a8395e0d..700121d0 100644 --- a/app/src/main/java/com/poti/android/domain/model/home/HomeContent.kt +++ b/app/src/main/java/com/poti/android/domain/model/home/HomeContent.kt @@ -1,12 +1,12 @@ package com.poti.android.domain.model.home data class HomeContent( - val nickname: String = "", - val mainArtist: String = "", - val mainArtistId: Long = 0L, - val myGroupItems: List = emptyList(), - val otherGroupItems: List = emptyList(), - val banners: List = emptyList(), + val nickname: String, + val mainArtist: String?, + val mainArtistId: Long?, + val myGroupItems: List, + val otherGroupItems: List, + val banners: List, ) data class GroupItem( diff --git a/app/src/main/java/com/poti/android/domain/model/party/GoodsCategory.kt b/app/src/main/java/com/poti/android/domain/model/party/ProductCategory.kt similarity index 93% rename from app/src/main/java/com/poti/android/domain/model/party/GoodsCategory.kt rename to app/src/main/java/com/poti/android/domain/model/party/ProductCategory.kt index 0c1d7edd..60aa35e0 100644 --- a/app/src/main/java/com/poti/android/domain/model/party/GoodsCategory.kt +++ b/app/src/main/java/com/poti/android/domain/model/party/ProductCategory.kt @@ -1,6 +1,6 @@ package com.poti.android.domain.model.party -data class GoodsCategory( +data class ProductCategory( val nickname: String, val mainArtist: String?, val mainArtistId: Long?, diff --git a/app/src/main/java/com/poti/android/domain/model/party/ProductPartyList.kt b/app/src/main/java/com/poti/android/domain/model/party/ProductPartyList.kt index 6c1102e4..13e59a2c 100644 --- a/app/src/main/java/com/poti/android/domain/model/party/ProductPartyList.kt +++ b/app/src/main/java/com/poti/android/domain/model/party/ProductPartyList.kt @@ -9,7 +9,7 @@ data class ProductPartyList( data class PartySummary( val partyId: Long, val price: Int, - val goodsImageUrl: String, + val productImageUrl: String, val currentCount: Int, val totalCount: Int, val availableMembers: List, diff --git a/app/src/main/java/com/poti/android/domain/repository/HomeRepository.kt b/app/src/main/java/com/poti/android/domain/repository/HomeRepository.kt index 0ec2b93c..e00aacad 100644 --- a/app/src/main/java/com/poti/android/domain/repository/HomeRepository.kt +++ b/app/src/main/java/com/poti/android/domain/repository/HomeRepository.kt @@ -1,7 +1,7 @@ package com.poti.android.domain.repository import com.poti.android.domain.model.home.HomeContent -import com.poti.android.domain.model.party.GoodsCategory +import com.poti.android.domain.model.party.ProductCategory interface HomeRepository { suspend fun getHomeContent(): Result @@ -11,5 +11,5 @@ interface HomeRepository { size: Int? = null, sort: String? = null, artistId: Long? = null, - ): Result + ): Result } diff --git a/app/src/main/java/com/poti/android/domain/repository/UserRepository.kt b/app/src/main/java/com/poti/android/domain/repository/UserRepository.kt index 26097940..f6e0621a 100644 --- a/app/src/main/java/com/poti/android/domain/repository/UserRepository.kt +++ b/app/src/main/java/com/poti/android/domain/repository/UserRepository.kt @@ -6,7 +6,7 @@ import com.poti.android.domain.model.user.UserProfile interface UserRepository { suspend fun patchOnboarding( nickname: String, - favoriteArtistId: Long, + favoriteArtistId: Long?, ): Result suspend fun postNicknameDuplicate( diff --git a/app/src/main/java/com/poti/android/presentation/history/list/HistoryListScreen.kt b/app/src/main/java/com/poti/android/presentation/history/list/HistoryListScreen.kt index c5e2ea1b..3e1c2fe8 100644 --- a/app/src/main/java/com/poti/android/presentation/history/list/HistoryListScreen.kt +++ b/app/src/main/java/com/poti/android/presentation/history/list/HistoryListScreen.kt @@ -4,6 +4,7 @@ import androidx.compose.foundation.gestures.detectHorizontalDragGestures import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -18,6 +19,8 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.compose.LifecycleEventEffect import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.poti.android.core.common.state.ApiState import com.poti.android.core.common.util.HandleSideEffects @@ -49,6 +52,10 @@ fun HistoryListRoute( ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() + LifecycleEventEffect(Lifecycle.Event.ON_RESUME) { + viewModel.processIntent(HistoryListUiIntent.OnResume) + } + HandleSideEffects(viewModel.sideEffect) { effect -> when (effect) { HistoryListUiEffect.NavigateBack -> onPopBackStack() @@ -82,6 +89,7 @@ private fun HistoryListScreen( ) { Scaffold( modifier = modifier, + contentWindowInsets = WindowInsets(), topBar = { PotiHeaderPage( onNavigationClick = onBackClick, diff --git a/app/src/main/java/com/poti/android/presentation/history/list/HistoryListViewModel.kt b/app/src/main/java/com/poti/android/presentation/history/list/HistoryListViewModel.kt index c92bac17..d4b74cb5 100644 --- a/app/src/main/java/com/poti/android/presentation/history/list/HistoryListViewModel.kt +++ b/app/src/main/java/com/poti/android/presentation/history/list/HistoryListViewModel.kt @@ -12,6 +12,7 @@ import com.poti.android.domain.repository.ParticipationRepository import com.poti.android.domain.repository.PartyRepository import com.poti.android.domain.type.HistoryListType import com.poti.android.presentation.history.list.model.HistoryListUiEffect +import com.poti.android.presentation.history.list.model.HistoryListUiEffect.* import com.poti.android.presentation.history.list.model.HistoryListUiIntent import com.poti.android.presentation.history.list.model.HistoryListUiState import com.poti.android.presentation.history.list.model.HistoryMode @@ -41,11 +42,12 @@ class HistoryListViewModel @Inject constructor( is HistoryListUiIntent.OnTabSelected -> selectTab(intent.tab) is HistoryListUiIntent.OnCardClick -> { if (uiState.value.mode == HistoryMode.RECRUIT) { - sendEffect(HistoryListUiEffect.NavigateToRecruiterDetail(intent.id)) + sendEffect(NavigateToRecruiterDetail(intent.id)) } else { - sendEffect(HistoryListUiEffect.NavigateToParticipantDetail(intent.id)) + sendEffect(NavigateToParticipantDetail(intent.id)) } } + HistoryListUiIntent.OnResume -> loadUserHistoryList() } } @@ -117,7 +119,7 @@ class HistoryListViewModel @Inject constructor( historyListType = listStatus, partyStatus = item.postStatus, ) - }, + }.distinctBy { it.id }, ) updateState { diff --git a/app/src/main/java/com/poti/android/presentation/history/list/model/Contracts.kt b/app/src/main/java/com/poti/android/presentation/history/list/model/Contracts.kt index 10401982..5138a375 100644 --- a/app/src/main/java/com/poti/android/presentation/history/list/model/Contracts.kt +++ b/app/src/main/java/com/poti/android/presentation/history/list/model/Contracts.kt @@ -11,7 +11,7 @@ import com.poti.android.domain.model.history.HistoryListContent data class HistoryListUiState( val historyListLoadState: ApiState = ApiState.Init, - val mode: HistoryMode = HistoryMode.RECRUIT, + val mode: HistoryMode = HistoryMode.PARTICIPATION, val selectedTab: PotiHeaderTabType = PotiHeaderTabType.ONGOING, ) : UiState { val titleRes = when (mode) { @@ -52,6 +52,8 @@ sealed interface HistoryListUiIntent : UiIntent { data class OnTabSelected(val tab: PotiHeaderTabType) : HistoryListUiIntent data class OnCardClick(val id: Long) : HistoryListUiIntent + + data object OnResume : HistoryListUiIntent } sealed interface HistoryListUiEffect : UiEffect { diff --git a/app/src/main/java/com/poti/android/presentation/history/manage/ParticipantManageScreen.kt b/app/src/main/java/com/poti/android/presentation/history/manage/ParticipantManageScreen.kt index 4f23db1c..04a32f33 100644 --- a/app/src/main/java/com/poti/android/presentation/history/manage/ParticipantManageScreen.kt +++ b/app/src/main/java/com/poti/android/presentation/history/manage/ParticipantManageScreen.kt @@ -12,6 +12,8 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.compose.LifecycleEventEffect import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.poti.android.R import com.poti.android.core.common.extension.onSuccess @@ -39,6 +41,10 @@ fun ParticipantManageRoute( ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() + LifecycleEventEffect(Lifecycle.Event.ON_RESUME) { + viewModel.processIntent(ParticipantManageUiIntent.OnResume) + } + HandleSideEffects(viewModel.sideEffect) { effect -> when (effect) { ParticipantManageUiEffect.NavigateBack -> popBackStack() diff --git a/app/src/main/java/com/poti/android/presentation/history/manage/ParticipantManageViewModel.kt b/app/src/main/java/com/poti/android/presentation/history/manage/ParticipantManageViewModel.kt index d8e14f15..a31d5f36 100644 --- a/app/src/main/java/com/poti/android/presentation/history/manage/ParticipantManageViewModel.kt +++ b/app/src/main/java/com/poti/android/presentation/history/manage/ParticipantManageViewModel.kt @@ -9,6 +9,7 @@ import com.poti.android.domain.repository.DeliveryRepository import com.poti.android.domain.repository.PartyRepository import com.poti.android.domain.repository.PaymentRepository import com.poti.android.presentation.history.manage.model.ManageModalState +import com.poti.android.presentation.history.manage.model.ManageModalState.* import com.poti.android.presentation.history.manage.model.ParticipantManageUiEffect import com.poti.android.presentation.history.manage.model.ParticipantManageUiIntent import com.poti.android.presentation.history.manage.model.ParticipantManageUiState @@ -38,14 +39,15 @@ class ParticipantManageViewModel @Inject constructor( when (intent) { ParticipantManageUiIntent.OnBackClick -> sendEffect(ParticipantManageUiEffect.NavigateBack) is ParticipantManageUiIntent.OnDepositConfirmClick -> updateState { - copy(activeModal = ManageModalState.DepositConfirm(intent.participantId)) + copy(activeModal = DepositConfirm(intent.participantId)) } is ParticipantManageUiIntent.OnDeliveryInputClick -> updateState { - copy(activeModal = ManageModalState.DeliveryInput(intent.participantId)) + copy(activeModal = DeliveryInput(intent.participantId)) } ParticipantManageUiIntent.OnDepositModalDismiss -> updateState { copy(activeModal = ManageModalState.None) } is ParticipantManageUiIntent.OnDepositModalConfirm -> confirmDeposit(intent.participantId) is ParticipantManageUiIntent.RegisterDelivery -> registerDelivery(intent.participantId, intent.deliveryMethod, intent.trackingNumber) + ParticipantManageUiIntent.OnResume -> loadParticipantManageDetail() } } diff --git a/app/src/main/java/com/poti/android/presentation/history/manage/component/HistoryParticipantDetail.kt b/app/src/main/java/com/poti/android/presentation/history/manage/component/HistoryParticipantDetail.kt index 84f0b1d6..120636bb 100644 --- a/app/src/main/java/com/poti/android/presentation/history/manage/component/HistoryParticipantDetail.kt +++ b/app/src/main/java/com/poti/android/presentation/history/manage/component/HistoryParticipantDetail.kt @@ -103,7 +103,7 @@ fun HistoryParticipantDetail( itemOptionText = participant.shippingName, priceText = stringResource( R.string.history_participant_detail_won_unit_format, - participant.shippingPrice, + participant.shippingPrice.toMoneyString(), ), sizeType = PotiListOptionPriceSize.SMALL, ) diff --git a/app/src/main/java/com/poti/android/presentation/history/manage/model/Contracts.kt b/app/src/main/java/com/poti/android/presentation/history/manage/model/Contracts.kt index 360a4d3e..cc1413d0 100644 --- a/app/src/main/java/com/poti/android/presentation/history/manage/model/Contracts.kt +++ b/app/src/main/java/com/poti/android/presentation/history/manage/model/Contracts.kt @@ -34,6 +34,8 @@ sealed interface ParticipantManageUiIntent : UiIntent { val deliveryMethod: String, val trackingNumber: String, ) : ParticipantManageUiIntent + + data object OnResume : ParticipantManageUiIntent } sealed interface ParticipantManageUiEffect : UiEffect { diff --git a/app/src/main/java/com/poti/android/presentation/history/participant/ParticipantViewModel.kt b/app/src/main/java/com/poti/android/presentation/history/participant/ParticipantViewModel.kt index 676c4527..e89d52b2 100644 --- a/app/src/main/java/com/poti/android/presentation/history/participant/ParticipantViewModel.kt +++ b/app/src/main/java/com/poti/android/presentation/history/participant/ParticipantViewModel.kt @@ -31,12 +31,12 @@ class ParticipantViewModel @Inject constructor( private val participantId: Long = savedStateHandle.toRoute().participantId init { - getParticipantDetail(participantId) + getParticipantDetail() } override fun processIntent(intent: ParticipantDetailUiIntent) { when (intent) { - is ParticipantDetailUiIntent.LoadDetail -> getParticipantDetail(intent.recruitId) + is ParticipantDetailUiIntent.LoadDetail -> getParticipantDetail() ParticipantDetailUiIntent.OnBackClick -> sendEffect(ParticipantDetailUiEffect.NavigateBack) is ParticipantDetailUiIntent.OnPartyDetailClick -> sendEffect(ParticipantDetailUiEffect.NavigateToPartyDetail(intent.partyId)) ParticipantDetailUiIntent.OnDepositCompleteClick -> updateState { copy(overlayState = ParticipantDetailOverlayState.DepositBottomSheet) } @@ -49,7 +49,7 @@ class ParticipantViewModel @Inject constructor( } } - private fun getParticipantDetail(participantId: Long) = launchScope { + private fun getParticipantDetail() = launchScope { if (uiState.value.participantDetailState !is ApiState.Success) { updateState { copy(participantDetailState = ApiState.Loading) } } @@ -82,7 +82,7 @@ class ParticipantViewModel @Inject constructor( Timber.d("fail: ${error.message}") } - getParticipantDetail(participantId) + getParticipantDetail() updateState { copy(overlayState = ParticipantDetailOverlayState.None) } } @@ -90,7 +90,7 @@ class ParticipantViewModel @Inject constructor( participantRepository.patchDeliveryConfirm(participantId) .onSuccess { leaderUser -> Timber.d("success: confirmDelivery") - getParticipantDetail(participantId) + getParticipantDetail() userRepository.getUserProfile(leaderUser) .onSuccess { leader -> @@ -123,7 +123,7 @@ class ParticipantViewModel @Inject constructor( .onSuccess { result -> Timber.d("success: $result") updateState { copy(overlayState = ParticipantDetailOverlayState.None) } - getParticipantDetail(participantId) + getParticipantDetail() }.onFailure { error -> Timber.e(error, "submit review failed") } diff --git a/app/src/main/java/com/poti/android/presentation/history/recruiter/RecruiterDetailScreen.kt b/app/src/main/java/com/poti/android/presentation/history/recruiter/RecruiterDetailScreen.kt index 583c1d6f..51dc2c0b 100644 --- a/app/src/main/java/com/poti/android/presentation/history/recruiter/RecruiterDetailScreen.kt +++ b/app/src/main/java/com/poti/android/presentation/history/recruiter/RecruiterDetailScreen.kt @@ -14,6 +14,8 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.compose.LifecycleEventEffect import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.poti.android.R import com.poti.android.core.common.extension.onSuccess @@ -43,6 +45,10 @@ fun RecruiterDetailRoute( ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() + LifecycleEventEffect(Lifecycle.Event.ON_RESUME) { + viewModel.processIntent(RecruiterDetailUiIntent.OnResume) + } + HandleSideEffects(viewModel.sideEffect) { effect -> when (effect) { RecruiterDetailUiEffect.NavigateBack -> onPopBackStack() diff --git a/app/src/main/java/com/poti/android/presentation/history/recruiter/RecruiterViewModel.kt b/app/src/main/java/com/poti/android/presentation/history/recruiter/RecruiterViewModel.kt index 44d9bdf4..52979d2f 100644 --- a/app/src/main/java/com/poti/android/presentation/history/recruiter/RecruiterViewModel.kt +++ b/app/src/main/java/com/poti/android/presentation/history/recruiter/RecruiterViewModel.kt @@ -7,6 +7,7 @@ import com.poti.android.core.common.state.ApiState import com.poti.android.domain.repository.PartyRepository import com.poti.android.presentation.history.navigation.HistoryRoute import com.poti.android.presentation.history.recruiter.model.RecruiterDetailUiEffect +import com.poti.android.presentation.history.recruiter.model.RecruiterDetailUiEffect.* import com.poti.android.presentation.history.recruiter.model.RecruiterDetailUiIntent import com.poti.android.presentation.history.recruiter.model.RecruiterDetailUiState import com.poti.android.presentation.history.recruiter.model.toUiModel @@ -23,22 +24,19 @@ class RecruiterViewModel @Inject constructor( private val recruitId: Long = savedStateHandle.toRoute().recruitId init { - if (recruitId != -1L) { - getRecruiterDetail(recruitId) - } else { - updateState { copy(recruiterDetailState = ApiState.Init) } - } + getRecruiterDetail() } override fun processIntent(intent: RecruiterDetailUiIntent) { when (intent) { is RecruiterDetailUiIntent.BackButtonClicked -> sendEffect(RecruiterDetailUiEffect.NavigateBack) - is RecruiterDetailUiIntent.PartyCardClicked -> sendEffect(RecruiterDetailUiEffect.NavigateToPartyDetail(recruitId)) - is RecruiterDetailUiIntent.ParticipantSectionClicked -> sendEffect(RecruiterDetailUiEffect.NavigateToParticipantList(recruitId)) + is RecruiterDetailUiIntent.PartyCardClicked -> sendEffect(NavigateToPartyDetail(recruitId)) + is RecruiterDetailUiIntent.ParticipantSectionClicked -> sendEffect(NavigateToParticipantList(recruitId)) + RecruiterDetailUiIntent.OnResume -> getRecruiterDetail() } } - private fun getRecruiterDetail(recruitId: Long) = launchScope { + private fun getRecruiterDetail() = launchScope { partyRepository.getRecruitDetail(recruitId) .onSuccess { updateState { diff --git a/app/src/main/java/com/poti/android/presentation/history/recruiter/model/Contracts.kt b/app/src/main/java/com/poti/android/presentation/history/recruiter/model/Contracts.kt index b98099d5..a9aeb578 100644 --- a/app/src/main/java/com/poti/android/presentation/history/recruiter/model/Contracts.kt +++ b/app/src/main/java/com/poti/android/presentation/history/recruiter/model/Contracts.kt @@ -10,11 +10,13 @@ data class RecruiterDetailUiState( ) : UiState sealed interface RecruiterDetailUiIntent : UiIntent { - object BackButtonClicked : RecruiterDetailUiIntent + data object BackButtonClicked : RecruiterDetailUiIntent - object PartyCardClicked : RecruiterDetailUiIntent + data object PartyCardClicked : RecruiterDetailUiIntent - object ParticipantSectionClicked : RecruiterDetailUiIntent + data object ParticipantSectionClicked : RecruiterDetailUiIntent + + data object OnResume : RecruiterDetailUiIntent } sealed interface RecruiterDetailUiEffect : UiEffect { diff --git a/app/src/main/java/com/poti/android/presentation/main/MainBottomBar.kt b/app/src/main/java/com/poti/android/presentation/main/MainBottomBar.kt index af6e6671..bc36ad1e 100644 --- a/app/src/main/java/com/poti/android/presentation/main/MainBottomBar.kt +++ b/app/src/main/java/com/poti/android/presentation/main/MainBottomBar.kt @@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.selection.selectable @@ -48,7 +49,8 @@ fun MainBottomBar( .fillMaxWidth() .background(PotiTheme.colors.white) .topRoundedBorder(1.dp, PotiTheme.colors.gray300, 20.dp) - .padding(16.dp), + .padding(16.dp) + .navigationBarsPadding(), horizontalArrangement = Arrangement.SpaceBetween, ) { MainTab.entries.forEach { tab -> diff --git a/app/src/main/java/com/poti/android/presentation/main/MainScreen.kt b/app/src/main/java/com/poti/android/presentation/main/MainScreen.kt index 3a0b9dac..60706026 100644 --- a/app/src/main/java/com/poti/android/presentation/main/MainScreen.kt +++ b/app/src/main/java/com/poti/android/presentation/main/MainScreen.kt @@ -1,7 +1,6 @@ package com.poti.android.presentation.main import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -19,7 +18,6 @@ fun MainScreen( visible = navigator.shouldShowBottomBar(), currentTab = navigator.currentTab, onTabSelected = { navigator.navigate(it) }, - modifier = Modifier.navigationBarsPadding(), ) }, ) { innerPadding -> diff --git a/app/src/main/java/com/poti/android/presentation/main/MainTab.kt b/app/src/main/java/com/poti/android/presentation/main/MainTab.kt index 7aac5f56..d005d718 100644 --- a/app/src/main/java/com/poti/android/presentation/main/MainTab.kt +++ b/app/src/main/java/com/poti/android/presentation/main/MainTab.kt @@ -18,7 +18,7 @@ enum class MainTab( label = R.string.bottom_nav_home, route = HomeRoute.Home, ), - MY_PARTY( + HISTORY( iconResId = R.drawable.ic_history, label = R.string.bottom_nav_history, route = HistoryRoute.HistoryList(), diff --git a/app/src/main/java/com/poti/android/presentation/onboarding/OnboardingViewModel.kt b/app/src/main/java/com/poti/android/presentation/onboarding/OnboardingViewModel.kt index 453c9df7..a90de259 100644 --- a/app/src/main/java/com/poti/android/presentation/onboarding/OnboardingViewModel.kt +++ b/app/src/main/java/com/poti/android/presentation/onboarding/OnboardingViewModel.kt @@ -131,7 +131,9 @@ class OnboardingViewModel @Inject constructor( } } - private fun handleSkipClick() { + private fun handleSkipClick() = launchScope { + userRepository.patchOnboarding(uiState.value.nickname, null) + .onSuccess { } updateState { copy( selectedArtistId = null, diff --git a/app/src/main/java/com/poti/android/presentation/party/PartyNavigation.kt b/app/src/main/java/com/poti/android/presentation/party/PartyNavigation.kt index 18336a85..a7a00bfd 100644 --- a/app/src/main/java/com/poti/android/presentation/party/PartyNavigation.kt +++ b/app/src/main/java/com/poti/android/presentation/party/PartyNavigation.kt @@ -7,9 +7,9 @@ import androidx.navigation.navigation import com.poti.android.core.navigation.Route import com.poti.android.presentation.party.create.navigation.partyCreateNavGraph import com.poti.android.presentation.party.detail.navigation.partyDetailNavGraph -import com.poti.android.presentation.party.goodsfilter.navigation.goodsFilterNavGraph import com.poti.android.presentation.party.home.navigation.HomeRoute import com.poti.android.presentation.party.home.navigation.homeNavGraph +import com.poti.android.presentation.party.product.navigation.productNavGraph import kotlinx.serialization.Serializable @Serializable @@ -26,7 +26,7 @@ fun NavGraphBuilder.partyNavGraph( paddingValues = paddingValues, navController = navController, ) - goodsFilterNavGraph( + productNavGraph( paddingValues = paddingValues, navController = navController, onPopBackStack = navController::popBackStack, diff --git a/app/src/main/java/com/poti/android/presentation/party/create/PartyArtistSelectScreen.kt b/app/src/main/java/com/poti/android/presentation/party/create/PartyArtistSelectScreen.kt index 1e57c2df..3a1708d9 100644 --- a/app/src/main/java/com/poti/android/presentation/party/create/PartyArtistSelectScreen.kt +++ b/app/src/main/java/com/poti/android/presentation/party/create/PartyArtistSelectScreen.kt @@ -1,6 +1,7 @@ package com.poti.android.presentation.party.create import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -64,6 +65,7 @@ private fun PartyArtistSelectScreen( ) { Scaffold( modifier = modifier, + contentWindowInsets = WindowInsets(), topBar = { PotiHeaderPage( onNavigationClick = onPopBackStack, diff --git a/app/src/main/java/com/poti/android/presentation/party/detail/component/ParticipantGuidelines.kt b/app/src/main/java/com/poti/android/presentation/party/detail/component/ParticipantGuidelines.kt index 26104c8a..75644f83 100644 --- a/app/src/main/java/com/poti/android/presentation/party/detail/component/ParticipantGuidelines.kt +++ b/app/src/main/java/com/poti/android/presentation/party/detail/component/ParticipantGuidelines.kt @@ -28,7 +28,7 @@ fun ParticipantGuidelines( Text( text = text, style = PotiTheme.typography.caption12m, - color = PotiTheme.colors.gray800, + color = PotiTheme.colors.gray700, ) } } diff --git a/app/src/main/java/com/poti/android/presentation/party/detail/model/Contracts.kt b/app/src/main/java/com/poti/android/presentation/party/detail/model/Contracts.kt index c2edcea6..5d922a60 100644 --- a/app/src/main/java/com/poti/android/presentation/party/detail/model/Contracts.kt +++ b/app/src/main/java/com/poti/android/presentation/party/detail/model/Contracts.kt @@ -4,6 +4,7 @@ import com.poti.android.core.base.UiEffect import com.poti.android.core.base.UiIntent import com.poti.android.core.base.UiState import com.poti.android.core.common.extension.getSuccessDataOrNull +import com.poti.android.core.common.extension.toMoneyString import com.poti.android.core.common.state.ApiState import com.poti.android.core.designsystem.component.field.FieldMenuItem import com.poti.android.domain.model.party.PartyDetail @@ -51,7 +52,7 @@ data class PartyDetailUiState( get() { val memberPriceSum = selectedMembers.sumOf { it.price?.replace(",", "")?.toIntOrNull() ?: 0 } val deliveryPrice = selectedDelivery?.price?.replace(",", "")?.toIntOrNull() ?: 0 - return (memberPriceSum + deliveryPrice).toString() + return (memberPriceSum + deliveryPrice).toMoneyString() } val isBottomSheetButtonEnable: Boolean diff --git a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/GoodsCategoryScreen.kt b/app/src/main/java/com/poti/android/presentation/party/goodsfilter/GoodsCategoryScreen.kt deleted file mode 100644 index 8824f479..00000000 --- a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/GoodsCategoryScreen.kt +++ /dev/null @@ -1,172 +0,0 @@ -package com.poti.android.presentation.party.goodsfilter - -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.wrapContentWidth -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.Scaffold -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.poti.android.R -import com.poti.android.core.common.extension.onSuccess -import com.poti.android.core.common.util.HandleSideEffects -import com.poti.android.core.common.util.screenWidthDp -import com.poti.android.core.designsystem.component.button.PotiFloatingButton -import com.poti.android.core.designsystem.component.button.PotiSmallButton -import com.poti.android.core.designsystem.component.navigation.PotiHeaderPage -import com.poti.android.core.designsystem.theme.PotiTheme -import com.poti.android.domain.model.party.GoodsCategory -import com.poti.android.presentation.party.goodsfilter.component.GoodsSortBottomSheet -import com.poti.android.presentation.party.goodsfilter.model.GoodsCategoryUiEffect -import com.poti.android.presentation.party.goodsfilter.model.GoodsCategoryUiIntent -import com.poti.android.presentation.party.goodsfilter.model.GoodsSortType -import com.poti.android.presentation.party.home.component.GoodsLargeCard - -@Composable -fun GoodsCategoryRoute( - artistId: Long, - onPopBackStack: () -> Unit, - onNavigateToPartyCreate: (Long?) -> Unit, - onNavigateToGoodsPartyList: (Long, String) -> Unit, - modifier: Modifier = Modifier, - viewModel: GoodsCategoryViewModel = hiltViewModel(), -) { - val uiState by viewModel.uiState.collectAsStateWithLifecycle() - - HandleSideEffects(viewModel.sideEffect) { effect -> - when (effect) { - GoodsCategoryUiEffect.NavigateBack -> onPopBackStack() - is GoodsCategoryUiEffect.NavigateToPartyCreate -> onNavigateToPartyCreate(artistId) - is GoodsCategoryUiEffect.NavigateToGoodsPartyList -> onNavigateToGoodsPartyList(artistId, effect.title) - } - } - - uiState.goodsCategoryLoadState.onSuccess { goodsCategory -> - GoodsCategoryScreen( - goodsCategory = goodsCategory, - selectedSortType = uiState.selectedSortType, - isSortBottomSheetVisible = uiState.isSortBottomSheetVisible, - onBackClick = { - viewModel.processIntent(GoodsCategoryUiIntent.OnBackClick) - }, - onFloatingClick = { - viewModel.processIntent(GoodsCategoryUiIntent.OnFloatingClick) - }, - onSortFilterClick = { - viewModel.processIntent(GoodsCategoryUiIntent.OnSortFilterClick) - }, - onSortSelect = { - viewModel.processIntent(GoodsCategoryUiIntent.OnSortSelected(it)) - }, - onSortDismiss = { - viewModel.processIntent(GoodsCategoryUiIntent.OnSortDismiss) - }, - onCardClick = { artistId, title -> - viewModel.processIntent(GoodsCategoryUiIntent.OnCardClick(artistId, title)) - }, - modifier = modifier, - ) - } -} - -@Composable -private fun GoodsCategoryScreen( - goodsCategory: GoodsCategory, - selectedSortType: GoodsSortType, - isSortBottomSheetVisible: Boolean, - onBackClick: () -> Unit, - onFloatingClick: () -> Unit, - onSortFilterClick: () -> Unit, - onSortSelect: (GoodsSortType) -> Unit, - onSortDismiss: () -> Unit, - onCardClick: (Long, String) -> Unit, - modifier: Modifier = Modifier, -) { - if (isSortBottomSheetVisible) { - GoodsSortBottomSheet( - selectedSortType = selectedSortType, - onSelect = onSortSelect, - onDismissRequest = onSortDismiss, - ) - } - - Scaffold( - modifier = modifier, - containerColor = PotiTheme.colors.white, - topBar = { - PotiHeaderPage( - onNavigationClick = onBackClick, - title = stringResource(R.string.home_recommend_goods, goodsCategory.nickname), - ) - }, - floatingActionButton = { - PotiFloatingButton( - onClick = onFloatingClick, // TODO: 아티스트 입력 상태로 등록 화면 이동; 아티스트 아이디, 아티스트 이름 - ) - }, - ) { innerPadding -> - LazyColumn( - modifier = Modifier - .fillMaxWidth() - .padding(innerPadding), - contentPadding = PaddingValues(horizontal = screenWidthDp(16.dp)), - ) { - item { - PotiSmallButton( - text = stringResource(selectedSortType.displayRes), - onClick = onSortFilterClick, - modifier = Modifier - .fillMaxWidth() - .wrapContentWidth(Alignment.End), - ) - } - - items(goodsCategory.groupItems) { groupItem -> - GoodsLargeCard( - imageUrl = groupItem.postImage, - artist = groupItem.artist, - title = groupItem.postTitle, - partyCount = groupItem.postCount, - tag = groupItem.tag, - onClick = { id, title -> onCardClick(id, title) }, - modifier = Modifier - .fillMaxWidth() - .padding(bottom = 16.dp), - artistId = groupItem.artistId, - ) - } - item { - Spacer(Modifier.height(80.dp)) - } - } - } -} - -@Preview(showBackground = true) -@Composable -private fun GoodsCategoryScreenPreview() { - PotiTheme { - GoodsCategoryScreen( - goodsCategory = dummyGoodsCategory, - selectedSortType = GoodsSortType.LATEST, - isSortBottomSheetVisible = false, - onBackClick = {}, - onFloatingClick = {}, - onSortFilterClick = {}, - onSortSelect = {}, - onSortDismiss = {}, - onCardClick = { _, _ -> }, - ) - } -} diff --git a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/GoodsCategoryViewModel.kt b/app/src/main/java/com/poti/android/presentation/party/goodsfilter/GoodsCategoryViewModel.kt deleted file mode 100644 index 1dcfe36c..00000000 --- a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/GoodsCategoryViewModel.kt +++ /dev/null @@ -1,72 +0,0 @@ -package com.poti.android.presentation.party.goodsfilter - -import androidx.lifecycle.SavedStateHandle -import com.poti.android.core.base.BaseViewModel -import com.poti.android.core.common.state.ApiState -import com.poti.android.domain.repository.HomeRepository -import com.poti.android.presentation.party.goodsfilter.model.GoodsCategoryUiEffect -import com.poti.android.presentation.party.goodsfilter.model.GoodsCategoryUiIntent -import com.poti.android.presentation.party.goodsfilter.model.GoodsCategoryUiState -import com.poti.android.presentation.party.goodsfilter.model.GoodsSortType -import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject - -@HiltViewModel -class GoodsCategoryViewModel @Inject constructor( - private val homeRepository: HomeRepository, - savedStateHandle: SavedStateHandle, -) : - BaseViewModel( - initialState = GoodsCategoryUiState(), - ) { - private val artistId: Long = checkNotNull(savedStateHandle["artistId"]) - - override fun processIntent(intent: GoodsCategoryUiIntent) { - when (intent) { - GoodsCategoryUiIntent.OnBackClick -> sendEffect(GoodsCategoryUiEffect.NavigateBack) - GoodsCategoryUiIntent.OnFloatingClick -> sendEffect(GoodsCategoryUiEffect.NavigateToPartyCreate) - GoodsCategoryUiIntent.OnSortFilterClick -> updateState { copy(isSortBottomSheetVisible = true) } - is GoodsCategoryUiIntent.OnSortSelected -> { - updateState { - copy( - selectedSortType = intent.sortType, - isSortBottomSheetVisible = false, - ) - } - loadGoodsCategoryList(intent.sortType) - } - GoodsCategoryUiIntent.OnSortDismiss -> updateState { copy(isSortBottomSheetVisible = false) } - is GoodsCategoryUiIntent.OnCardClick -> sendEffect(GoodsCategoryUiEffect.NavigateToGoodsPartyList(intent.artistId, intent.title)) - } - } - - init { - loadGoodsCategoryList() - } - - private fun loadGoodsCategoryList(sortType: GoodsSortType = uiState.value.selectedSortType) = - launchScope { - updateState { copy(goodsCategoryLoadState = ApiState.Loading) } - - homeRepository.getGoodsCategoryList( - page = 0, - size = 10, - sort = sortType.name, - artistId = artistId, - ) - .onSuccess { goodsCategory -> - updateState { - copy(goodsCategoryLoadState = ApiState.Success(goodsCategory)) - } - } - .onFailure { throwable -> - updateState { - copy( - goodsCategoryLoadState = ApiState.Failure( - throwable.message ?: "Failed to load goods category", - ), - ) - } - } - } - } diff --git a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/GoodsFilteredPartyListScreen.kt b/app/src/main/java/com/poti/android/presentation/party/goodsfilter/GoodsFilteredPartyListScreen.kt deleted file mode 100644 index b9a9969f..00000000 --- a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/GoodsFilteredPartyListScreen.kt +++ /dev/null @@ -1,230 +0,0 @@ -package com.poti.android.presentation.party.goodsfilter - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.Scaffold -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.poti.android.R -import com.poti.android.core.common.extension.getSuccessDataOrNull -import com.poti.android.core.common.util.HandleSideEffects -import com.poti.android.core.common.util.screenWidthDp -import com.poti.android.core.designsystem.component.bottomsheet.MemberSelectBottomSheet -import com.poti.android.core.designsystem.component.button.PotiFloatingButton -import com.poti.android.core.designsystem.component.button.PotiSmallButton -import com.poti.android.core.designsystem.component.navigation.PotiHeaderPage -import com.poti.android.core.designsystem.theme.PotiTheme -import com.poti.android.domain.model.party.PartySummary -import com.poti.android.domain.model.party.ProductPartyList -import com.poti.android.presentation.party.goodsfilter.component.FilteredSortBottomSheet -import com.poti.android.presentation.party.goodsfilter.component.PartyCard -import com.poti.android.presentation.party.goodsfilter.model.FilteredSortType -import com.poti.android.presentation.party.goodsfilter.model.GoodsFilterUiEffect -import com.poti.android.presentation.party.goodsfilter.model.GoodsFilterUiIntent -import com.poti.android.presentation.party.goodsfilter.model.membersText -import com.poti.android.presentation.party.goodsfilter.model.priceText -import com.poti.android.presentation.party.goodsfilter.model.ratingText - -@Composable -fun GoodsFilteredPartyListRoute( - artistId: Long, - onPopBackStack: () -> Unit, - onNavigateToPartyCreate: (Long, String, String) -> Unit, - onNavigateToPartyDetail: (Long) -> Unit, - modifier: Modifier = Modifier, - viewModel: GoodsFilterViewModel = hiltViewModel(), -) { - val uiState by viewModel.uiState.collectAsStateWithLifecycle() - - HandleSideEffects(viewModel.sideEffect) { effect -> - when (effect) { - GoodsFilterUiEffect.NavigateBack -> onPopBackStack() - is GoodsFilterUiEffect.NavigateToPartyCreate -> onNavigateToPartyCreate(artistId, effect.artistName, effect.productName) - is GoodsFilterUiEffect.NavigateToPartyDetail -> onNavigateToPartyDetail(effect.partyId) - } - } - - if (uiState.isMemberFilterBottomSheetVisible) { - MemberSelectBottomSheet( - title = R.string.goods_filter_member_select_label, - onDismiss = { viewModel.processIntent(GoodsFilterUiIntent.CloseMemberFilterBottomSheet) }, - mainBtnText = R.string.action_button_done, - onMainBtnClick = { viewModel.processIntent(GoodsFilterUiIntent.OnMemberFilterDone) }, - mainEnabled = uiState.isMemberBottomSheetToucehd, - subBtnText = R.string.action_button_refresh, - onSubBtnClick = { viewModel.processIntent(GoodsFilterUiIntent.OnMemberFilterRefresh) }, - subEnabled = true, - members = uiState.allMemberNames, - selectedIndices = uiState.bottomSheetSelectedMembersIdices, - onMemberClick = { viewModel.processIntent(GoodsFilterUiIntent.OnMemberSelect(it)) }, - autoCloseSubBtn = false, - ) - } - - if (uiState.isSortFilterBottomSheetVisible) { - FilteredSortBottomSheet( - selectedSortType = uiState.goodsPartySortType, - onSelect = { viewModel.processIntent(GoodsFilterUiIntent.OnSortSelect(it)) }, - onDismissRequest = { viewModel.processIntent(GoodsFilterUiIntent.CloseSortFilterBottomSheet) }, - ) - } - - GoodsFilteredPartyListScreen( - productPartyListInfo = uiState.productPartyListInfo.getSuccessDataOrNull() ?: ProductPartyList( - partyTitle = uiState.cachedTitle, - artistName = uiState.cachedSubTitle, - partySummaries = emptyList(), - ), - partySortType = uiState.goodsPartySortType, - memberFilterText = uiState.memberFilterText, - onBackClick = { - viewModel.processIntent(GoodsFilterUiIntent.OnBackClick) - }, - onFloatingClick = { - viewModel.processIntent(GoodsFilterUiIntent.OnFloatingClick) - }, - onMemberFilterClick = { - viewModel.processIntent(GoodsFilterUiIntent.OnMemberFilterClick) - }, - onSortFilterClick = { - viewModel.processIntent(GoodsFilterUiIntent.OnSortFilterClick) - }, - onCardClick = { potId -> - viewModel.processIntent(GoodsFilterUiIntent.OnPartyClick(potId)) - }, - modifier = modifier, - ) -} - -@Composable -private fun GoodsFilteredPartyListScreen( - productPartyListInfo: ProductPartyList, - partySortType: FilteredSortType, - memberFilterText: String, - onBackClick: () -> Unit, - onFloatingClick: () -> Unit, - onMemberFilterClick: () -> Unit, - onSortFilterClick: () -> Unit, - onCardClick: (Long) -> Unit, - modifier: Modifier = Modifier, -) { - Scaffold( - modifier = modifier, - containerColor = PotiTheme.colors.white, - contentWindowInsets = WindowInsets(0), - topBar = { - PotiHeaderPage( - onNavigationClick = onBackClick, - title = productPartyListInfo.partyTitle, - subTitle = productPartyListInfo.artistName, - ) - }, - floatingActionButton = { - PotiFloatingButton( - onClick = onFloatingClick, // TODO: [예림] 등록 화면(PartyCreateScreen)에 (아티스트 + 굿즈명) 넘겨주기 - ) - }, - ) { innerPadding -> - LazyColumn( - modifier = Modifier - .fillMaxWidth() - .padding(innerPadding), - contentPadding = PaddingValues(horizontal = screenWidthDp(16.dp)), - ) { - item { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - ) { - PotiSmallButton( - text = memberFilterText, - onClick = onMemberFilterClick, - ) - - PotiSmallButton( - text = stringResource(partySortType.displayRes), - onClick = onSortFilterClick, - ) - } - } - - items(productPartyListInfo.partySummaries) { party -> - PartyCard( - potId = party.partyId, - profileImageUrl = party.profileImageUrl ?: "", - nickname = party.nickname, - rating = party.ratingText(), - imageUrl = party.goodsImageUrl, - members = party.membersText(), - price = party.priceText(), - currentCount = party.currentCount, - totalCount = party.totalCount, - onClick = onCardClick, - modifier = Modifier - .fillMaxWidth() - .padding(bottom = 16.dp), - ) - } - - item { - Spacer(Modifier.height(80.dp)) - } - } - } -} - -@Preview -@Composable -private fun GoodsFilteredPartyListScreenPreveiw() { - GoodsFilteredPartyListScreen( - productPartyListInfo = ProductPartyList( - partyTitle = "헤더 타이틀", - artistName = "서브타이틀", - partySummaries = listOf( - PartySummary( - partyId = 1, - price = 1000, - goodsImageUrl = "", - currentCount = 5, - totalCount = 7, - availableMembers = listOf("원영", "유진", "이서"), - profileImageUrl = "", - nickname = "닉네임", - rating = 1.2, - ), - PartySummary( - partyId = 1, - price = 8000, - goodsImageUrl = "", - currentCount = 6, - totalCount = 6, - availableMembers = listOf("원영", "유진"), - profileImageUrl = "", - nickname = "닉네임", - rating = 1.2, - ), - ), - ), - partySortType = FilteredSortType.DEADLINE, - memberFilterText = "", - onBackClick = {}, - onFloatingClick = {}, - onMemberFilterClick = {}, - onSortFilterClick = {}, - onCardClick = {}, - ) -} diff --git a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/model/GoodsCategoryUiState.kt b/app/src/main/java/com/poti/android/presentation/party/goodsfilter/model/GoodsCategoryUiState.kt deleted file mode 100644 index 1e92324a..00000000 --- a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/model/GoodsCategoryUiState.kt +++ /dev/null @@ -1,51 +0,0 @@ -package com.poti.android.presentation.party.goodsfilter.model - -import androidx.annotation.StringRes -import com.poti.android.R -import com.poti.android.core.base.UiEffect -import com.poti.android.core.base.UiIntent -import com.poti.android.core.base.UiState -import com.poti.android.core.common.state.ApiState -import com.poti.android.domain.model.party.GoodsCategory - -enum class GoodsSortType( - val request: String, - @StringRes val displayRes: Int, -) { - LATEST( - request = "LATEST", - displayRes = R.string.goods_filter_sort_latest, - ), - HOT( - request = "HOT", - displayRes = R.string.goods_filter_sort_hot, - ), -} - -data class GoodsCategoryUiState( - val goodsCategoryLoadState: ApiState = ApiState.Loading, - val isSortBottomSheetVisible: Boolean = false, - val selectedSortType: GoodsSortType = GoodsSortType.LATEST, -) : UiState - -sealed interface GoodsCategoryUiIntent : UiIntent { - data object OnBackClick : GoodsCategoryUiIntent - - data object OnFloatingClick : GoodsCategoryUiIntent - - data object OnSortFilterClick : GoodsCategoryUiIntent - - data class OnSortSelected(val sortType: GoodsSortType) : GoodsCategoryUiIntent - - data object OnSortDismiss : GoodsCategoryUiIntent - - data class OnCardClick(val artistId: Long, val title: String) : GoodsCategoryUiIntent -} - -sealed interface GoodsCategoryUiEffect : UiEffect { - data object NavigateBack : GoodsCategoryUiEffect - - data object NavigateToPartyCreate : GoodsCategoryUiEffect - - data class NavigateToGoodsPartyList(val artistId: Long, val title: String) : GoodsCategoryUiEffect -} diff --git a/app/src/main/java/com/poti/android/presentation/party/home/DummyHomeData.kt b/app/src/main/java/com/poti/android/presentation/party/home/DummyHomeData.kt new file mode 100644 index 00000000..9b933fab --- /dev/null +++ b/app/src/main/java/com/poti/android/presentation/party/home/DummyHomeData.kt @@ -0,0 +1,30 @@ +package com.poti.android.presentation.party.home + +import com.poti.android.domain.model.home.GroupItem + +val fakeMyGroupItems = listOf( + GroupItem( + postTitle = "2026 시즌 콘서트 후드", + artist = "아이유", + artistId = 0L, + postImage = "", + postCount = 3, + tag = "인기", + ), + GroupItem( + postTitle = "공식 응원봉 Ver.2", + artist = "아이유", + artistId = 0L, + postImage = "", + postCount = 12, + tag = "NEW", + ), + GroupItem( + postTitle = "월드투어 포토북", + artist = "아이유", + artistId = 0L, + postImage = "", + postCount = 7, + tag = "", + ), +) diff --git a/app/src/main/java/com/poti/android/presentation/party/home/HomeScreen.kt b/app/src/main/java/com/poti/android/presentation/party/home/HomeScreen.kt index d9b822b0..091514ab 100644 --- a/app/src/main/java/com/poti/android/presentation/party/home/HomeScreen.kt +++ b/app/src/main/java/com/poti/android/presentation/party/home/HomeScreen.kt @@ -26,46 +26,17 @@ import com.poti.android.core.designsystem.component.button.PotiFloatingButton import com.poti.android.core.designsystem.component.navigation.PotiHeaderPrimary import com.poti.android.core.designsystem.theme.PotiTheme import com.poti.android.domain.model.home.Banner -import com.poti.android.domain.model.home.GroupItem import com.poti.android.domain.model.home.HomeContent import com.poti.android.presentation.party.home.component.HomeBannerSection import com.poti.android.presentation.party.home.component.HomeGoodsSection import com.poti.android.presentation.party.home.model.HomeUiEffect import com.poti.android.presentation.party.home.model.HomeUiIntent -val fakeMyGroupItems = listOf( - GroupItem( - postTitle = "2026 시즌 콘서트 후드", - artist = "아이유", - artistId = 0L, - postImage = "", - postCount = 3, - tag = "인기", - ), - GroupItem( - postTitle = "공식 응원봉 Ver.2", - artist = "아이유", - artistId = 0L, - postImage = "", - postCount = 12, - tag = "NEW", - ), - GroupItem( - postTitle = "월드투어 포토북", - artist = "아이유", - artistId = 0L, - postImage = "", - postCount = 7, - tag = "", - ), -) - @Composable fun HomeRoute( onNavigateToPartyCreate: () -> Unit, - onNavigateToPartyDetail: (Long) -> Unit, onNavigateToGoodsPartyList: (Long, String) -> Unit, - onNavigateToGoodsCategory: (Long) -> Unit, + onNavigateToProductCategory: (Long?, Boolean) -> Unit, modifier: Modifier = Modifier, viewModel: HomeViewModel = hiltViewModel(), ) { @@ -74,9 +45,9 @@ fun HomeRoute( HandleSideEffects(viewModel.sideEffect) { effect -> when (effect) { HomeUiEffect.NavigateToPartyCreate -> onNavigateToPartyCreate() - is HomeUiEffect.NavigateToPartyDetail -> onNavigateToPartyDetail(effect.postId) is HomeUiEffect.NavigateToGoodsPartyList -> onNavigateToGoodsPartyList(effect.artistId, effect.title) - is HomeUiEffect.NavigateToGoodsCategory -> onNavigateToGoodsCategory(effect.artistId) + is HomeUiEffect.NavigateToMyArtistCategory -> onNavigateToProductCategory(effect.artistId, true) + HomeUiEffect.NavigateToOtherProductCategory -> onNavigateToProductCategory(null, false) } } @@ -84,15 +55,9 @@ fun HomeRoute( HomeScreen( homeContent = homeContent, onFloatingClick = { viewModel.processIntent(HomeUiIntent.OnFloatingClick) }, - onBannerClick = { postId -> - viewModel.processIntent(HomeUiIntent.OnBannerClick(postId)) - }, - onMoreClick = { artistId -> - viewModel.processIntent(HomeUiIntent.OnMoreClick(artistId)) - }, - onCardClick = { artistId, title -> - viewModel.processIntent(HomeUiIntent.OnCardClick(artistId, title)) - }, + onMyArtistCategoryClick = { artistId -> viewModel.processIntent(HomeUiIntent.OnMyArtistCategoryClick(artistId)) }, + onOtherProductCategoryClick = { viewModel.processIntent(HomeUiIntent.OnOtherProductCategoryClick) }, + onProductCardClick = { artistId, title -> viewModel.processIntent(HomeUiIntent.OnProductCardClick(artistId, title)) }, modifier = modifier, ) } @@ -102,9 +67,9 @@ fun HomeRoute( private fun HomeScreen( homeContent: HomeContent, onFloatingClick: () -> Unit, - onBannerClick: (Long) -> Unit, - onMoreClick: (Long) -> Unit, - onCardClick: (Long, String) -> Unit, + onMyArtistCategoryClick: (Long?) -> Unit, + onOtherProductCategoryClick: (Long?) -> Unit, + onProductCardClick: (Long, String) -> Unit, modifier: Modifier = Modifier, ) { val scrollState = rememberScrollState() @@ -128,7 +93,7 @@ private fun HomeScreen( ) { HomeBannerSection( banners = homeContent.banners, - onBannerClick = onBannerClick, + onBannerClick = {}, modifier = Modifier .padding(top = screenHeightDp(16.dp)) .padding(horizontal = screenWidthDp(16.dp)), @@ -141,8 +106,8 @@ private fun HomeScreen( title = R.string.home_recommend_goods, nickname = homeContent.nickname, groupItems = homeContent.myGroupItems, - onMoreClick = onMoreClick, - onCardClick = onCardClick, + onMoreClick = onMyArtistCategoryClick, + onCardClick = onProductCardClick, ) Spacer(modifier = Modifier.height(28.dp)) @@ -152,8 +117,8 @@ private fun HomeScreen( title = R.string.home_other_goods, nickname = homeContent.nickname, groupItems = homeContent.otherGroupItems, - onMoreClick = onMoreClick, - onCardClick = onCardClick, + onMoreClick = onOtherProductCategoryClick, + onCardClick = onProductCardClick, ) } } @@ -184,11 +149,13 @@ private fun HomeScreenPreview() { ), myGroupItems = fakeMyGroupItems, otherGroupItems = fakeMyGroupItems, + mainArtist = null, + mainArtistId = null, ), onFloatingClick = { }, - onBannerClick = { }, - onMoreClick = { }, - onCardClick = { _, _ -> }, + onMyArtistCategoryClick = { }, + onOtherProductCategoryClick = {}, + onProductCardClick = { _, _ -> }, ) } } diff --git a/app/src/main/java/com/poti/android/presentation/party/home/HomeViewModel.kt b/app/src/main/java/com/poti/android/presentation/party/home/HomeViewModel.kt index dc8cff44..2a905dc0 100644 --- a/app/src/main/java/com/poti/android/presentation/party/home/HomeViewModel.kt +++ b/app/src/main/java/com/poti/android/presentation/party/home/HomeViewModel.kt @@ -4,6 +4,7 @@ import com.poti.android.core.base.BaseViewModel import com.poti.android.core.common.state.ApiState import com.poti.android.domain.repository.HomeRepository import com.poti.android.presentation.party.home.model.HomeUiEffect +import com.poti.android.presentation.party.home.model.HomeUiEffect.* import com.poti.android.presentation.party.home.model.HomeUiIntent import com.poti.android.presentation.party.home.model.HomeUiState import dagger.hilt.android.lifecycle.HiltViewModel @@ -17,11 +18,11 @@ class HomeViewModel @Inject constructor( ) { override fun processIntent(intent: HomeUiIntent) { when (intent) { - HomeUiIntent.OnFloatingClick -> sendEffect(HomeUiEffect.NavigateToPartyCreate) - is HomeUiIntent.OnBannerClick -> sendEffect(HomeUiEffect.NavigateToPartyDetail(intent.postId)) - is HomeUiIntent.OnMoreClick -> sendEffect(HomeUiEffect.NavigateToGoodsCategory(intent.artistId)) - is HomeUiIntent.OnCardClick -> sendEffect(HomeUiEffect.NavigateToGoodsPartyList(intent.artistId, intent.title)) + HomeUiIntent.OnFloatingClick -> sendEffect(NavigateToPartyCreate) + is HomeUiIntent.OnMyArtistCategoryClick -> sendEffect(NavigateToMyArtistCategory(intent.artistId)) + is HomeUiIntent.OnProductCardClick -> sendEffect(NavigateToGoodsPartyList(intent.artistId, intent.title)) HomeUiIntent.LoadHomeContent -> loadHomeContent() + HomeUiIntent.OnOtherProductCategoryClick -> sendEffect(NavigateToOtherProductCategory) } } diff --git a/app/src/main/java/com/poti/android/presentation/party/home/component/GoodsLargeCard.kt b/app/src/main/java/com/poti/android/presentation/party/home/component/GoodsLargeCard.kt index 01935a17..5c1471ec 100644 --- a/app/src/main/java/com/poti/android/presentation/party/home/component/GoodsLargeCard.kt +++ b/app/src/main/java/com/poti/android/presentation/party/home/component/GoodsLargeCard.kt @@ -75,7 +75,7 @@ fun GoodsLargeCard( if (!tag.isNullOrBlank()) { PotiSecondaryTag( text = tag, - sizeType = PotiTagSize.SMALL, + sizeType = PotiTagSize.LARGE, modifier = Modifier .align(Alignment.TopStart) .padding(12.dp), @@ -103,7 +103,7 @@ fun GoodsLargeCard( color = PotiTheme.colors.gray800, overflow = TextOverflow.Ellipsis, maxLines = 1, - style = PotiTheme.typography.caption12m, + style = PotiTheme.typography.body14m, ) Text( @@ -113,7 +113,7 @@ fun GoodsLargeCard( overflow = TextOverflow.Ellipsis, maxLines = 2, minLines = 2, - style = PotiTheme.typography.body14m, + style = PotiTheme.typography.body16m, ) } diff --git a/app/src/main/java/com/poti/android/presentation/party/home/component/HomeGoodsSection.kt b/app/src/main/java/com/poti/android/presentation/party/home/component/HomeGoodsSection.kt index dee28f94..745e6f96 100644 --- a/app/src/main/java/com/poti/android/presentation/party/home/component/HomeGoodsSection.kt +++ b/app/src/main/java/com/poti/android/presentation/party/home/component/HomeGoodsSection.kt @@ -25,11 +25,11 @@ import com.poti.android.presentation.party.home.fakeMyGroupItems @Composable fun HomeGoodsSection( - artistId: Long, + artistId: Long?, @StringRes title: Int, nickname: String, groupItems: List, - onMoreClick: (Long) -> Unit, + onMoreClick: (Long?) -> Unit, onCardClick: (Long, String) -> Unit, modifier: Modifier = Modifier, ) { diff --git a/app/src/main/java/com/poti/android/presentation/party/home/model/Contracts.kt b/app/src/main/java/com/poti/android/presentation/party/home/model/Contracts.kt index 98ac1825..ad1ca943 100644 --- a/app/src/main/java/com/poti/android/presentation/party/home/model/Contracts.kt +++ b/app/src/main/java/com/poti/android/presentation/party/home/model/Contracts.kt @@ -8,15 +8,14 @@ import com.poti.android.domain.model.home.HomeContent data class HomeUiState( val homeContentLoadState: ApiState = ApiState.Loading, - val homeContent: HomeContent = HomeContent(), ) : UiState sealed interface HomeUiIntent : UiIntent { - data class OnBannerClick(val postId: Long) : HomeUiIntent + data class OnMyArtistCategoryClick(val artistId: Long?) : HomeUiIntent - data class OnMoreClick(val artistId: Long) : HomeUiIntent + data class OnProductCardClick(val artistId: Long, val title: String) : HomeUiIntent - data class OnCardClick(val artistId: Long, val title: String) : HomeUiIntent + data object OnOtherProductCategoryClick : HomeUiIntent data object OnFloatingClick : HomeUiIntent @@ -26,9 +25,9 @@ sealed interface HomeUiIntent : UiIntent { sealed interface HomeUiEffect : UiEffect { data object NavigateToPartyCreate : HomeUiEffect - data class NavigateToPartyDetail(val postId: Long) : HomeUiEffect + data class NavigateToMyArtistCategory(val artistId: Long?) : HomeUiEffect - data class NavigateToGoodsCategory(val artistId: Long) : HomeUiEffect + data object NavigateToOtherProductCategory : HomeUiEffect data class NavigateToGoodsPartyList(val artistId: Long, val title: String) : HomeUiEffect } diff --git a/app/src/main/java/com/poti/android/presentation/party/home/navigation/HomeNavigation.kt b/app/src/main/java/com/poti/android/presentation/party/home/navigation/HomeNavigation.kt index aeecff2a..0e4fd6fb 100644 --- a/app/src/main/java/com/poti/android/presentation/party/home/navigation/HomeNavigation.kt +++ b/app/src/main/java/com/poti/android/presentation/party/home/navigation/HomeNavigation.kt @@ -8,10 +8,9 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable import com.poti.android.core.navigation.Route import com.poti.android.presentation.party.create.navigation.navigateToPartyCreate -import com.poti.android.presentation.party.detail.navigation.navigateToPartyDetail -import com.poti.android.presentation.party.goodsfilter.navigation.navigateToGoodsCategory -import com.poti.android.presentation.party.goodsfilter.navigation.navigateToGoodsPartyList import com.poti.android.presentation.party.home.HomeRoute +import com.poti.android.presentation.party.product.navigation.navigateToProductCategory +import com.poti.android.presentation.party.product.navigation.navigateToProductPartyList import kotlinx.serialization.Serializable sealed interface HomeRoute : Route { @@ -26,9 +25,8 @@ fun NavGraphBuilder.homeNavGraph( composable { HomeRoute( onNavigateToPartyCreate = navController::navigateToPartyCreate, - onNavigateToPartyDetail = navController::navigateToPartyDetail, - onNavigateToGoodsPartyList = navController::navigateToGoodsPartyList, - onNavigateToGoodsCategory = navController::navigateToGoodsCategory, + onNavigateToGoodsPartyList = navController::navigateToProductPartyList, + onNavigateToProductCategory = navController::navigateToProductCategory, modifier = Modifier.padding(paddingValues), ) } diff --git a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/DummyGoodsCategory.kt b/app/src/main/java/com/poti/android/presentation/party/product/DummyGoodsCategory.kt similarity index 87% rename from app/src/main/java/com/poti/android/presentation/party/goodsfilter/DummyGoodsCategory.kt rename to app/src/main/java/com/poti/android/presentation/party/product/DummyGoodsCategory.kt index fe2a721e..9c17f072 100644 --- a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/DummyGoodsCategory.kt +++ b/app/src/main/java/com/poti/android/presentation/party/product/DummyGoodsCategory.kt @@ -1,9 +1,9 @@ -package com.poti.android.presentation.party.goodsfilter +package com.poti.android.presentation.party.product -import com.poti.android.domain.model.party.GoodsCategory import com.poti.android.domain.model.party.GroupItem +import com.poti.android.domain.model.party.ProductCategory -val dummyGoodsCategory = GoodsCategory( +val dummyProductCategory = ProductCategory( nickname = "포티", mainArtist = "아이브", mainArtistId = 1L, diff --git a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/DummyPotsDate.kt b/app/src/main/java/com/poti/android/presentation/party/product/DummyPotsDate.kt similarity index 88% rename from app/src/main/java/com/poti/android/presentation/party/goodsfilter/DummyPotsDate.kt rename to app/src/main/java/com/poti/android/presentation/party/product/DummyPotsDate.kt index 7cec2ba7..54673f5d 100644 --- a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/DummyPotsDate.kt +++ b/app/src/main/java/com/poti/android/presentation/party/product/DummyPotsDate.kt @@ -1,4 +1,4 @@ -package com.poti.android.presentation.party.goodsfilter +package com.poti.android.presentation.party.product import com.poti.android.domain.model.party.PartySummary import com.poti.android.domain.model.party.ProductPartyList @@ -10,7 +10,7 @@ val dummyProductPartyList = ProductPartyList( PartySummary( partyId = 1L, price = 21300, - goodsImageUrl = "", + productImageUrl = "", currentCount = 3, totalCount = 5, availableMembers = listOf("원영", "유진"), @@ -21,7 +21,7 @@ val dummyProductPartyList = ProductPartyList( PartySummary( partyId = 2L, price = 21300, - goodsImageUrl = "", + productImageUrl = "", currentCount = 6, totalCount = 6, availableMembers = listOf("원영", "유진"), @@ -32,7 +32,7 @@ val dummyProductPartyList = ProductPartyList( PartySummary( partyId = 3L, price = 21300, - goodsImageUrl = "", + productImageUrl = "", currentCount = 1, totalCount = 4, availableMembers = listOf("원영", "유진"), diff --git a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/model/Extension.kt b/app/src/main/java/com/poti/android/presentation/party/product/Extension.kt similarity index 92% rename from app/src/main/java/com/poti/android/presentation/party/goodsfilter/model/Extension.kt rename to app/src/main/java/com/poti/android/presentation/party/product/Extension.kt index bff20a38..65a9e862 100644 --- a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/model/Extension.kt +++ b/app/src/main/java/com/poti/android/presentation/party/product/Extension.kt @@ -1,4 +1,4 @@ -package com.poti.android.presentation.party.goodsfilter.model +package com.poti.android.presentation.party.product import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource diff --git a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/component/FilteredSortBottomSheet.kt b/app/src/main/java/com/poti/android/presentation/party/product/component/FilteredSortBottomSheet.kt similarity index 85% rename from app/src/main/java/com/poti/android/presentation/party/goodsfilter/component/FilteredSortBottomSheet.kt rename to app/src/main/java/com/poti/android/presentation/party/product/component/FilteredSortBottomSheet.kt index 4f2a7814..f5b44d8b 100644 --- a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/component/FilteredSortBottomSheet.kt +++ b/app/src/main/java/com/poti/android/presentation/party/product/component/FilteredSortBottomSheet.kt @@ -1,4 +1,4 @@ -package com.poti.android.presentation.party.goodsfilter.component +package com.poti.android.presentation.party.product.component import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3Api @@ -12,19 +12,19 @@ import androidx.compose.ui.unit.dp import com.poti.android.core.common.util.screenWidthDp import com.poti.android.core.designsystem.component.bottomsheet.PotiBottomSheet import com.poti.android.core.designsystem.component.display.PotiListRadio -import com.poti.android.presentation.party.goodsfilter.model.FilteredSortType +import com.poti.android.presentation.party.product.partylist.model.PartySortType import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @Composable fun FilteredSortBottomSheet( - selectedSortType: FilteredSortType, - onSelect: (FilteredSortType) -> Unit, + selectedSortType: PartySortType, + onSelect: (PartySortType) -> Unit, onDismissRequest: () -> Unit, modifier: Modifier = Modifier, ) { - val sortTypes = remember { FilteredSortType.entries.toList() } + val sortTypes = remember { PartySortType.entries.toList() } val options = remember { sortTypes.map { it.displayRes }.toImmutableList() diff --git a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/component/GoodsSortBottomSheet.kt b/app/src/main/java/com/poti/android/presentation/party/product/component/GoodsSortBottomSheet.kt similarity index 86% rename from app/src/main/java/com/poti/android/presentation/party/goodsfilter/component/GoodsSortBottomSheet.kt rename to app/src/main/java/com/poti/android/presentation/party/product/component/GoodsSortBottomSheet.kt index 5d49d74b..bce922e5 100644 --- a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/component/GoodsSortBottomSheet.kt +++ b/app/src/main/java/com/poti/android/presentation/party/product/component/GoodsSortBottomSheet.kt @@ -1,4 +1,4 @@ -package com.poti.android.presentation.party.goodsfilter.component +package com.poti.android.presentation.party.product.component import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3Api @@ -16,19 +16,19 @@ import androidx.compose.ui.unit.dp import com.poti.android.core.common.util.screenWidthDp import com.poti.android.core.designsystem.component.bottomsheet.PotiBottomSheet import com.poti.android.core.designsystem.component.display.PotiListRadio -import com.poti.android.presentation.party.goodsfilter.model.GoodsSortType +import com.poti.android.presentation.party.product.productcategory.model.ProductSortType import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @Composable fun GoodsSortBottomSheet( - selectedSortType: GoodsSortType, - onSelect: (GoodsSortType) -> Unit, + selectedSortType: ProductSortType, + onSelect: (ProductSortType) -> Unit, onDismissRequest: () -> Unit, modifier: Modifier = Modifier, ) { - val sortTypes = remember { GoodsSortType.entries.toList() } + val sortTypes = remember { ProductSortType.entries.toList() } val options = remember { sortTypes.map { it.displayRes }.toImmutableList() @@ -64,7 +64,7 @@ fun GoodsSortBottomSheet( @Composable private fun GoodsSortBottomSheetPreview() { var show by remember { mutableStateOf(true) } - var selected by remember { mutableStateOf(GoodsSortType.LATEST) } + var selected by remember { mutableStateOf(ProductSortType.LATEST) } if (show) { GoodsSortBottomSheet( diff --git a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/component/PartyCard.kt b/app/src/main/java/com/poti/android/presentation/party/product/component/PartyCard.kt similarity index 99% rename from app/src/main/java/com/poti/android/presentation/party/goodsfilter/component/PartyCard.kt rename to app/src/main/java/com/poti/android/presentation/party/product/component/PartyCard.kt index e645ea9b..7a506841 100644 --- a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/component/PartyCard.kt +++ b/app/src/main/java/com/poti/android/presentation/party/product/component/PartyCard.kt @@ -1,4 +1,4 @@ -package com.poti.android.presentation.party.goodsfilter.component +package com.poti.android.presentation.party.product.component import androidx.compose.foundation.background import androidx.compose.foundation.border diff --git a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/navigation/GoodsNavigation.kt b/app/src/main/java/com/poti/android/presentation/party/product/navigation/ProductNavigation.kt similarity index 52% rename from app/src/main/java/com/poti/android/presentation/party/goodsfilter/navigation/GoodsNavigation.kt rename to app/src/main/java/com/poti/android/presentation/party/product/navigation/ProductNavigation.kt index 9fb7d499..9a4cbcc3 100644 --- a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/navigation/GoodsNavigation.kt +++ b/app/src/main/java/com/poti/android/presentation/party/product/navigation/ProductNavigation.kt @@ -1,4 +1,4 @@ -package com.poti.android.presentation.party.goodsfilter.navigation +package com.poti.android.presentation.party.product.navigation import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.padding @@ -10,61 +10,57 @@ import androidx.navigation.toRoute import com.poti.android.core.navigation.Route import com.poti.android.presentation.party.create.navigation.navigateToPartyCreate import com.poti.android.presentation.party.detail.navigation.navigateToPartyDetail -import com.poti.android.presentation.party.goodsfilter.GoodsCategoryRoute -import com.poti.android.presentation.party.goodsfilter.GoodsFilteredPartyListRoute +import com.poti.android.presentation.party.product.partylist.ProductPartyListRoute +import com.poti.android.presentation.party.product.productcategory.ProductCategoryRoute import kotlinx.serialization.Serializable -sealed interface GoodsRoute : Route { +sealed interface ProductRoute : Route { @Serializable - data object GoodsList : GoodsRoute - - @Serializable - data class GoodsPartyList( + data class ProductPartyList( val artistId: Long, val title: String, - ) : GoodsRoute + ) : ProductRoute @Serializable - data class GoodsCategory( - val artistId: Long, - ) : GoodsRoute + data class ProductCategory( + val artistId: Long? = null, + val isMyArtist: Boolean, + ) : ProductRoute } -fun NavController.navigateToGoodsList() { - navigate(GoodsRoute.GoodsList) -} - -fun NavController.navigateToGoodsPartyList( +fun NavController.navigateToProductPartyList( artistId: Long, title: String, ) { - navigate(GoodsRoute.GoodsPartyList(artistId, title)) + navigate(ProductRoute.ProductPartyList(artistId, title)) } -fun NavController.navigateToGoodsCategory(artistId: Long) { - navigate(GoodsRoute.GoodsCategory(artistId)) +fun NavController.navigateToProductCategory( + artistId: Long?, + isMyArtist: Boolean, +) { + navigate(ProductRoute.ProductCategory(artistId, isMyArtist)) } -fun NavGraphBuilder.goodsFilterNavGraph( +fun NavGraphBuilder.productNavGraph( paddingValues: PaddingValues, navController: NavController, onPopBackStack: () -> Unit, ) { - composable { backStackEntry -> - val artistId = backStackEntry.toRoute().artistId - - GoodsCategoryRoute( + composable { backStackEntry -> + val artistId = backStackEntry.toRoute().artistId + ProductCategoryRoute( artistId = artistId, onPopBackStack = navController::popBackStack, onNavigateToPartyCreate = navController::navigateToPartyCreate, - onNavigateToGoodsPartyList = navController::navigateToGoodsPartyList, + onNavigateToProductPartyList = navController::navigateToProductPartyList, modifier = Modifier.padding(paddingValues), ) } - composable { backStackEntry -> - val artistId = backStackEntry.toRoute().artistId + composable { backStackEntry -> + val artistId = backStackEntry.toRoute().artistId - GoodsFilteredPartyListRoute( + ProductPartyListRoute( artistId = artistId, onPopBackStack = onPopBackStack, onNavigateToPartyCreate = navController::navigateToPartyCreate, diff --git a/app/src/main/java/com/poti/android/presentation/party/product/partylist/ProductPartyListScreen.kt b/app/src/main/java/com/poti/android/presentation/party/product/partylist/ProductPartyListScreen.kt new file mode 100644 index 00000000..71bde5ad --- /dev/null +++ b/app/src/main/java/com/poti/android/presentation/party/product/partylist/ProductPartyListScreen.kt @@ -0,0 +1,221 @@ +package com.poti.android.presentation.party.product.partylist + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.poti.android.R +import com.poti.android.core.common.extension.getSuccessDataOrNull +import com.poti.android.core.common.util.HandleSideEffects +import com.poti.android.core.common.util.screenHeightDp +import com.poti.android.core.common.util.screenWidthDp +import com.poti.android.core.designsystem.component.bottomsheet.MemberSelectBottomSheet +import com.poti.android.core.designsystem.component.button.PotiFloatingButton +import com.poti.android.core.designsystem.component.button.PotiSmallButton +import com.poti.android.core.designsystem.component.navigation.PotiHeaderPage +import com.poti.android.domain.model.party.PartySummary +import com.poti.android.domain.model.party.ProductPartyList +import com.poti.android.presentation.party.product.component.FilteredSortBottomSheet +import com.poti.android.presentation.party.product.component.PartyCard +import com.poti.android.presentation.party.product.membersText +import com.poti.android.presentation.party.product.partylist.model.PartySortType +import com.poti.android.presentation.party.product.partylist.model.ProductPartyListUiEffect +import com.poti.android.presentation.party.product.partylist.model.ProductPartyListUiIntent +import com.poti.android.presentation.party.product.priceText +import com.poti.android.presentation.party.product.ratingText + +@Composable +fun ProductPartyListRoute( + artistId: Long, + onPopBackStack: () -> Unit, + onNavigateToPartyCreate: (Long, String, String) -> Unit, + onNavigateToPartyDetail: (Long) -> Unit, + modifier: Modifier = Modifier, + viewModel: ProductPartyListViewModel = hiltViewModel(), +) { + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + + HandleSideEffects(viewModel.sideEffect) { effect -> + when (effect) { + ProductPartyListUiEffect.NavigateBack -> onPopBackStack() + is ProductPartyListUiEffect.NavigateToPartyCreate -> onNavigateToPartyCreate(artistId, effect.artistName, effect.productName) + is ProductPartyListUiEffect.NavigateToPartyDetail -> onNavigateToPartyDetail(effect.partyId) + } + } + + if (uiState.isMemberFilterBottomSheetVisible) { + MemberSelectBottomSheet( + title = R.string.goods_filter_member_select_label, + onDismiss = { viewModel.processIntent(ProductPartyListUiIntent.CloseMemberFilterBottomSheet) }, + mainBtnText = R.string.action_button_done, + onMainBtnClick = { viewModel.processIntent(ProductPartyListUiIntent.OnMemberFilterDone) }, + mainEnabled = uiState.isMemberBottomSheetToucehd, + subBtnText = R.string.action_button_refresh, + onSubBtnClick = { viewModel.processIntent(ProductPartyListUiIntent.OnMemberFilterRefresh) }, + subEnabled = true, + members = uiState.allMemberNames, + selectedIndices = uiState.bottomSheetSelectedMembersIdices, + onMemberClick = { viewModel.processIntent(ProductPartyListUiIntent.OnMemberSelect(it)) }, + autoCloseSubBtn = false, + ) + } + + if (uiState.isSortFilterBottomSheetVisible) { + FilteredSortBottomSheet( + selectedSortType = uiState.partySortType, + onSelect = { viewModel.processIntent(ProductPartyListUiIntent.OnSortSelect(it)) }, + onDismissRequest = { viewModel.processIntent(ProductPartyListUiIntent.CloseSortFilterBottomSheet) }, + ) + } + + ProductPartyListScreen( + productPartyListInfo = uiState.productPartyListInfo.getSuccessDataOrNull() ?: ProductPartyList( + partyTitle = uiState.cachedTitle, + artistName = uiState.cachedSubTitle, + partySummaries = emptyList(), + ), + partySortType = uiState.partySortType, + memberFilterText = uiState.memberFilterText, + onBackClick = { viewModel.processIntent(ProductPartyListUiIntent.OnBackClick) }, + onFloatingClick = { viewModel.processIntent(ProductPartyListUiIntent.OnFloatingClick) }, + onMemberFilterClick = { viewModel.processIntent(ProductPartyListUiIntent.OnMemberFilterClick) }, + onSortFilterClick = { viewModel.processIntent(ProductPartyListUiIntent.OnSortFilterClick) }, + onCardClick = { potId -> viewModel.processIntent(ProductPartyListUiIntent.OnPartyClick(potId)) }, + modifier = modifier, + ) +} + +@Composable +private fun ProductPartyListScreen( + productPartyListInfo: ProductPartyList, + partySortType: PartySortType, + memberFilterText: String, + onBackClick: () -> Unit, + onFloatingClick: () -> Unit, + onMemberFilterClick: () -> Unit, + onSortFilterClick: () -> Unit, + onCardClick: (Long) -> Unit, + modifier: Modifier = Modifier, +) { + Box( + modifier = modifier, + ) { + Column { + PotiHeaderPage( + onNavigationClick = onBackClick, + title = productPartyListInfo.partyTitle, + subTitle = productPartyListInfo.artistName, + ) + + LazyColumn( + modifier = Modifier.fillMaxWidth(), + contentPadding = PaddingValues( + start = screenWidthDp(16.dp), + end = screenWidthDp(16.dp), + bottom = 76.dp, + ), + ) { + item { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + ) { + PotiSmallButton( + text = memberFilterText, + onClick = onMemberFilterClick, + ) + + PotiSmallButton( + text = stringResource(partySortType.displayRes), + onClick = onSortFilterClick, + ) + } + } + + items(productPartyListInfo.partySummaries) { party -> + PartyCard( + potId = party.partyId, + profileImageUrl = party.profileImageUrl ?: "", + nickname = party.nickname, + rating = party.ratingText(), + imageUrl = party.productImageUrl, + members = party.membersText(), + price = party.priceText(), + currentCount = party.currentCount, + totalCount = party.totalCount, + onClick = onCardClick, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 16.dp), + ) + } + } + } + + PotiFloatingButton( + onClick = onFloatingClick, + modifier = Modifier + .align(Alignment.BottomEnd) + .padding( + end = screenWidthDp(20.dp), + bottom = screenHeightDp(12.dp), + ), + ) + } +} + +@Preview +@Composable +private fun ProductPartyListScreenPreveiw() { + ProductPartyListScreen( + productPartyListInfo = ProductPartyList( + partyTitle = "헤더 타이틀", + artistName = "서브타이틀", + partySummaries = listOf( + PartySummary( + partyId = 1, + price = 1000, + productImageUrl = "", + currentCount = 5, + totalCount = 7, + availableMembers = listOf("원영", "유진", "이서"), + profileImageUrl = "", + nickname = "닉네임", + rating = 1.2, + ), + PartySummary( + partyId = 1, + price = 8000, + productImageUrl = "", + currentCount = 6, + totalCount = 6, + availableMembers = listOf("원영", "유진"), + profileImageUrl = "", + nickname = "닉네임", + rating = 1.2, + ), + ), + ), + partySortType = PartySortType.DEADLINE, + memberFilterText = "", + onBackClick = {}, + onFloatingClick = {}, + onMemberFilterClick = {}, + onSortFilterClick = {}, + onCardClick = {}, + ) +} diff --git a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/GoodsFilterViewModel.kt b/app/src/main/java/com/poti/android/presentation/party/product/partylist/ProductPartyListViewModel.kt similarity index 67% rename from app/src/main/java/com/poti/android/presentation/party/goodsfilter/GoodsFilterViewModel.kt rename to app/src/main/java/com/poti/android/presentation/party/product/partylist/ProductPartyListViewModel.kt index 246d611e..70e4eaa6 100644 --- a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/GoodsFilterViewModel.kt +++ b/app/src/main/java/com/poti/android/presentation/party/product/partylist/ProductPartyListViewModel.kt @@ -1,4 +1,4 @@ -package com.poti.android.presentation.party.goodsfilter +package com.poti.android.presentation.party.product.partylist import androidx.lifecycle.SavedStateHandle import androidx.navigation.toRoute @@ -6,67 +6,67 @@ import com.poti.android.core.base.BaseViewModel import com.poti.android.core.common.state.ApiState import com.poti.android.domain.repository.ArtistRepository import com.poti.android.domain.repository.PartyRepository -import com.poti.android.presentation.party.goodsfilter.model.GoodsFilterUiEffect -import com.poti.android.presentation.party.goodsfilter.model.GoodsFilterUiIntent -import com.poti.android.presentation.party.goodsfilter.model.GoodsFilterUiState -import com.poti.android.presentation.party.goodsfilter.navigation.GoodsRoute.GoodsPartyList +import com.poti.android.presentation.party.product.navigation.ProductRoute +import com.poti.android.presentation.party.product.partylist.model.ProductPartyListUiEffect +import com.poti.android.presentation.party.product.partylist.model.ProductPartyListUiIntent +import com.poti.android.presentation.party.product.partylist.model.ProductPartyListUiState import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel -class GoodsFilterViewModel @Inject constructor( +class ProductPartyListViewModel @Inject constructor( private val artistRepository: ArtistRepository, private val partyRepository: PartyRepository, savedStateHandle: SavedStateHandle, -) : BaseViewModel( - initialState = GoodsFilterUiState(), +) : BaseViewModel( + initialState = ProductPartyListUiState(), ) { - private val artistId: Long = savedStateHandle.toRoute().artistId - private val title: String = savedStateHandle.toRoute().title + private val artistId: Long = savedStateHandle.toRoute().artistId + private val title: String = savedStateHandle.toRoute().title init { fetchArtistMembers() loadPartyList() } - override fun processIntent(intent: GoodsFilterUiIntent) { + override fun processIntent(intent: ProductPartyListUiIntent) { when (intent) { - GoodsFilterUiIntent.LoadGoodsPots -> loadPartyList() - GoodsFilterUiIntent.OnBackClick -> sendEffect(GoodsFilterUiEffect.NavigateBack) - GoodsFilterUiIntent.OnFloatingClick -> sendEffect( - GoodsFilterUiEffect.NavigateToPartyCreate( + ProductPartyListUiIntent.LoadProductPartyList -> loadPartyList() + ProductPartyListUiIntent.OnBackClick -> sendEffect(ProductPartyListUiEffect.NavigateBack) + ProductPartyListUiIntent.OnFloatingClick -> sendEffect( + ProductPartyListUiEffect.NavigateToPartyCreate( artistName = uiState.value.cachedSubTitle, productName = title, ), ) - is GoodsFilterUiIntent.OnPartyClick -> sendEffect(GoodsFilterUiEffect.NavigateToPartyDetail(intent.partyId)) - GoodsFilterUiIntent.OnMemberFilterClick -> { + is ProductPartyListUiIntent.OnPartyClick -> sendEffect(ProductPartyListUiEffect.NavigateToPartyDetail(intent.partyId)) + ProductPartyListUiIntent.OnMemberFilterClick -> { refreshMemberSelectBottomSheet() updateState { copy(isMemberFilterBottomSheetVisible = true) } } - is GoodsFilterUiIntent.OnMemberSelect -> { + is ProductPartyListUiIntent.OnMemberSelect -> { onBottomSheetMemberChanged(intent.index) } - GoodsFilterUiIntent.OnSortFilterClick -> { + ProductPartyListUiIntent.OnSortFilterClick -> { updateState { copy(isSortFilterBottomSheetVisible = true) } } - GoodsFilterUiIntent.CloseSortFilterBottomSheet -> { + ProductPartyListUiIntent.CloseSortFilterBottomSheet -> { updateState { copy(isSortFilterBottomSheetVisible = false) } } - is GoodsFilterUiIntent.OnSortSelect -> { - updateState { copy(goodsPartySortType = intent.sort, isSortFilterBottomSheetVisible = false) } + is ProductPartyListUiIntent.OnSortSelect -> { + updateState { copy(partySortType = intent.sort, isSortFilterBottomSheetVisible = false) } loadPartyList() } - GoodsFilterUiIntent.CloseMemberFilterBottomSheet -> updateState { copy(isMemberFilterBottomSheetVisible = false) } + ProductPartyListUiIntent.CloseMemberFilterBottomSheet -> updateState { copy(isMemberFilterBottomSheetVisible = false) } - GoodsFilterUiIntent.OnMemberFilterDone -> saveSelectedMember() + ProductPartyListUiIntent.OnMemberFilterDone -> saveSelectedMember() - GoodsFilterUiIntent.OnMemberFilterRefresh -> { + ProductPartyListUiIntent.OnMemberFilterRefresh -> { if (uiState.value.bottomSheetSelectedMembersIdices.isNotEmpty()) { clearSelectedMembers() } @@ -76,7 +76,7 @@ class GoodsFilterViewModel @Inject constructor( private fun loadPartyList() = launchScope { val currentState = uiState.value - val sort = currentState.goodsPartySortType.request + val sort = currentState.partySortType.request val memberIds = if (currentState.selectedMembers.isNotEmpty()) { currentState.selectedMembers.map { it.memberId } } else { @@ -87,7 +87,7 @@ class GoodsFilterViewModel @Inject constructor( partyRepository.getProductPartyList( page = 0, - size = 10, + size = 100, title = title, artistId = artistId, sort = sort, diff --git a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/model/GoodsFilteredContracts.kt b/app/src/main/java/com/poti/android/presentation/party/product/partylist/model/Contracts.kt similarity index 50% rename from app/src/main/java/com/poti/android/presentation/party/goodsfilter/model/GoodsFilteredContracts.kt rename to app/src/main/java/com/poti/android/presentation/party/product/partylist/model/Contracts.kt index b8a144c1..3e2b5b85 100644 --- a/app/src/main/java/com/poti/android/presentation/party/goodsfilter/model/GoodsFilteredContracts.kt +++ b/app/src/main/java/com/poti/android/presentation/party/product/partylist/model/Contracts.kt @@ -1,6 +1,5 @@ -package com.poti.android.presentation.party.goodsfilter.model +package com.poti.android.presentation.party.product.partylist.model -import androidx.annotation.StringRes import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import com.poti.android.R @@ -11,23 +10,14 @@ import com.poti.android.core.common.state.ApiState import com.poti.android.domain.model.artist.Member import com.poti.android.domain.model.party.ProductPartyList -enum class FilteredSortType( - val request: String, - @StringRes val displayRes: Int, -) { - LATEST("LATEST", R.string.goods_filter_sort_latest), - DEADLINE("DEADLINE", R.string.goods_filter_sort_deadline), - RATING("RATING", R.string.goods_filter_sort_rating), -} - -data class GoodsFilterUiState( +data class ProductPartyListUiState( val productPartyListInfo: ApiState = ApiState.Loading, val cachedTitle: String = "", val cachedSubTitle: String = "", val membersLoadState: ApiState> = ApiState.Loading, val displayMembers: List = emptyList(), val selectedMembers: List = emptyList(), - val goodsPartySortType: FilteredSortType = FilteredSortType.DEADLINE, + val partySortType: PartySortType = PartySortType.DEADLINE, val isMemberFilterBottomSheetVisible: Boolean = false, val isSortFilterBottomSheetVisible: Boolean = false, val bottomSheetSelectedMembersIdices: Set = setOf(), @@ -39,21 +29,21 @@ data class GoodsFilterUiState( val memberFilterText: String @Composable get() = when { selectedMembers.isEmpty() -> - stringResource(R.string.goods_filter_member_select) + stringResource(R.string.party_filter_member_select) selectedMembers.size == 1 -> selectedMembers[0].name selectedMembers.size == 2 -> stringResource( - R.string.goods_filter_member_two_format, + R.string.party_filter_member_two_format, selectedMembers[0].name, selectedMembers[1].name, ) else -> stringResource( - R.string.goods_filter_member_more_format, + R.string.party_filter_member_more_format, selectedMembers[0].name, selectedMembers[1].name, selectedMembers.size - 2, @@ -61,36 +51,36 @@ data class GoodsFilterUiState( } } -sealed interface GoodsFilterUiIntent : UiIntent { - data object LoadGoodsPots : GoodsFilterUiIntent +sealed interface ProductPartyListUiIntent : UiIntent { + data object LoadProductPartyList : ProductPartyListUiIntent - data object OnBackClick : GoodsFilterUiIntent + data object OnBackClick : ProductPartyListUiIntent - data object OnFloatingClick : GoodsFilterUiIntent + data object OnFloatingClick : ProductPartyListUiIntent - data class OnPartyClick(val partyId: Long) : GoodsFilterUiIntent + data class OnPartyClick(val partyId: Long) : ProductPartyListUiIntent - data object OnMemberFilterClick : GoodsFilterUiIntent + data object OnMemberFilterClick : ProductPartyListUiIntent - data class OnMemberSelect(val index: Int) : GoodsFilterUiIntent + data class OnMemberSelect(val index: Int) : ProductPartyListUiIntent - data object OnSortFilterClick : GoodsFilterUiIntent + data object OnSortFilterClick : ProductPartyListUiIntent - data class OnSortSelect(val sort: FilteredSortType) : GoodsFilterUiIntent + data class OnSortSelect(val sort: PartySortType) : ProductPartyListUiIntent - data object CloseMemberFilterBottomSheet : GoodsFilterUiIntent + data object CloseMemberFilterBottomSheet : ProductPartyListUiIntent - data object CloseSortFilterBottomSheet : GoodsFilterUiIntent + data object CloseSortFilterBottomSheet : ProductPartyListUiIntent - data object OnMemberFilterDone : GoodsFilterUiIntent + data object OnMemberFilterDone : ProductPartyListUiIntent - data object OnMemberFilterRefresh : GoodsFilterUiIntent + data object OnMemberFilterRefresh : ProductPartyListUiIntent } -sealed interface GoodsFilterUiEffect : UiEffect { - data object NavigateBack : GoodsFilterUiEffect +sealed interface ProductPartyListUiEffect : UiEffect { + data object NavigateBack : ProductPartyListUiEffect - data class NavigateToPartyCreate(val artistName: String, val productName: String) : GoodsFilterUiEffect + data class NavigateToPartyCreate(val artistName: String, val productName: String) : ProductPartyListUiEffect - data class NavigateToPartyDetail(val partyId: Long) : GoodsFilterUiEffect + data class NavigateToPartyDetail(val partyId: Long) : ProductPartyListUiEffect } diff --git a/app/src/main/java/com/poti/android/presentation/party/product/partylist/model/PartySortType.kt b/app/src/main/java/com/poti/android/presentation/party/product/partylist/model/PartySortType.kt new file mode 100644 index 00000000..3278621a --- /dev/null +++ b/app/src/main/java/com/poti/android/presentation/party/product/partylist/model/PartySortType.kt @@ -0,0 +1,13 @@ +package com.poti.android.presentation.party.product.partylist.model + +import androidx.annotation.StringRes +import com.poti.android.R + +enum class PartySortType( + val request: String, + @StringRes val displayRes: Int, +) { + LATEST("LATEST", R.string.party_filter_sort_latest), + DEADLINE("DEADLINE", R.string.party_filter_sort_deadline), + RATING("RATING", R.string.party_filter_sort_rating), +} diff --git a/app/src/main/java/com/poti/android/presentation/party/product/productcategory/ProductCategoryScreen.kt b/app/src/main/java/com/poti/android/presentation/party/product/productcategory/ProductCategoryScreen.kt new file mode 100644 index 00000000..0dd4703d --- /dev/null +++ b/app/src/main/java/com/poti/android/presentation/party/product/productcategory/ProductCategoryScreen.kt @@ -0,0 +1,168 @@ +package com.poti.android.presentation.party.product.productcategory + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.poti.android.R +import com.poti.android.core.common.extension.onSuccess +import com.poti.android.core.common.util.HandleSideEffects +import com.poti.android.core.common.util.screenHeightDp +import com.poti.android.core.common.util.screenWidthDp +import com.poti.android.core.designsystem.component.button.PotiFloatingButton +import com.poti.android.core.designsystem.component.button.PotiSmallButton +import com.poti.android.core.designsystem.component.navigation.PotiHeaderPage +import com.poti.android.core.designsystem.theme.PotiTheme +import com.poti.android.domain.model.party.ProductCategory +import com.poti.android.presentation.party.home.component.GoodsLargeCard +import com.poti.android.presentation.party.product.component.GoodsSortBottomSheet +import com.poti.android.presentation.party.product.dummyProductCategory +import com.poti.android.presentation.party.product.productcategory.model.ProductCategoryUiEffect +import com.poti.android.presentation.party.product.productcategory.model.ProductCategoryUiIntent +import com.poti.android.presentation.party.product.productcategory.model.ProductSortType + +@Composable +fun ProductCategoryRoute( + artistId: Long?, + onPopBackStack: () -> Unit, + onNavigateToPartyCreate: (Long?) -> Unit, + onNavigateToProductPartyList: (Long, String) -> Unit, + modifier: Modifier = Modifier, + viewModel: ProductCategoryViewModel = hiltViewModel(), +) { + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + + HandleSideEffects(viewModel.sideEffect) { effect -> + when (effect) { + ProductCategoryUiEffect.NavigateBack -> onPopBackStack() + is ProductCategoryUiEffect.NavigateToPartyCreate -> onNavigateToPartyCreate(artistId) + is ProductCategoryUiEffect.NavigateToProductPartyList -> onNavigateToProductPartyList(effect.artistId, effect.title) + } + } + + uiState.productCategoryLoadState.onSuccess { goodsCategory -> + ProductCategoryScreen( + title = if (viewModel.isMyArtist) stringResource(R.string.home_recommend_goods, goodsCategory.nickname) else stringResource(R.string.home_other_goods), + productCategory = goodsCategory, + selectedSortType = uiState.selectedSortType, + isSortBottomSheetVisible = uiState.isSortBottomSheetVisible, + onBackClick = { viewModel.processIntent(ProductCategoryUiIntent.OnBackClick) }, + onFloatingClick = { viewModel.processIntent(ProductCategoryUiIntent.OnFloatingClick) }, + onSortFilterClick = { viewModel.processIntent(ProductCategoryUiIntent.OnSortFilterClick) }, + onSortSelect = { viewModel.processIntent(ProductCategoryUiIntent.OnSortSelected(it)) }, + onSortDismiss = { viewModel.processIntent(ProductCategoryUiIntent.OnSortDismiss) }, + onCardClick = { artistId, title -> viewModel.processIntent(ProductCategoryUiIntent.OnCardClick(artistId, title)) }, + modifier = modifier, + ) + } +} + +@Composable +private fun ProductCategoryScreen( + title: String, + productCategory: ProductCategory, + selectedSortType: ProductSortType, + isSortBottomSheetVisible: Boolean, + onBackClick: () -> Unit, + onFloatingClick: () -> Unit, + onSortFilterClick: () -> Unit, + onSortSelect: (ProductSortType) -> Unit, + onSortDismiss: () -> Unit, + onCardClick: (Long, String) -> Unit, + modifier: Modifier = Modifier, +) { + if (isSortBottomSheetVisible) { + GoodsSortBottomSheet( + selectedSortType = selectedSortType, + onSelect = onSortSelect, + onDismissRequest = onSortDismiss, + ) + } + + Box( + modifier = modifier, + ) { + Column { + PotiHeaderPage( + onNavigationClick = onBackClick, + title = title, + ) + + LazyColumn( + modifier = Modifier.fillMaxWidth(), + contentPadding = PaddingValues( + start = screenWidthDp(16.dp), + end = screenWidthDp(16.dp), + bottom = 76.dp, + ), + ) { + item { + PotiSmallButton( + text = stringResource(selectedSortType.displayRes), + onClick = onSortFilterClick, + modifier = Modifier + .fillMaxWidth() + .wrapContentWidth(Alignment.End), + ) + } + + items(productCategory.groupItems) { groupItem -> + GoodsLargeCard( + imageUrl = groupItem.postImage, + artist = groupItem.artist, + title = groupItem.postTitle, + partyCount = groupItem.postCount, + tag = groupItem.tag, + onClick = { id, title -> onCardClick(groupItem.artistId, groupItem.postTitle) }, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 16.dp), + artistId = groupItem.artistId, + ) + } + } + } + + PotiFloatingButton( + onClick = onFloatingClick, + modifier = Modifier + .align(Alignment.BottomEnd) + .padding( + end = screenWidthDp(20.dp), + bottom = screenHeightDp(12.dp), + ), + ) + } +} + +@Preview(showBackground = true) +@Composable +private fun ProductCategoryScreenPreview() { + PotiTheme { + ProductCategoryScreen( + title = "", + productCategory = dummyProductCategory, + selectedSortType = ProductSortType.LATEST, + isSortBottomSheetVisible = false, + onBackClick = {}, + onFloatingClick = {}, + onSortFilterClick = {}, + onSortSelect = {}, + onSortDismiss = {}, + onCardClick = { _, _ -> }, + ) + } +} diff --git a/app/src/main/java/com/poti/android/presentation/party/product/productcategory/ProductCategoryViewModel.kt b/app/src/main/java/com/poti/android/presentation/party/product/productcategory/ProductCategoryViewModel.kt new file mode 100644 index 00000000..738461df --- /dev/null +++ b/app/src/main/java/com/poti/android/presentation/party/product/productcategory/ProductCategoryViewModel.kt @@ -0,0 +1,77 @@ +package com.poti.android.presentation.party.product.productcategory + +import androidx.lifecycle.SavedStateHandle +import androidx.navigation.toRoute +import com.poti.android.core.base.BaseViewModel +import com.poti.android.core.common.state.ApiState +import com.poti.android.domain.repository.HomeRepository +import com.poti.android.presentation.party.product.navigation.ProductRoute.ProductCategory +import com.poti.android.presentation.party.product.productcategory.model.ProductCategoryUiEffect +import com.poti.android.presentation.party.product.productcategory.model.ProductCategoryUiIntent +import com.poti.android.presentation.party.product.productcategory.model.ProductCategoryUiState +import com.poti.android.presentation.party.product.productcategory.model.ProductSortType +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class ProductCategoryViewModel @Inject constructor( + private val homeRepository: HomeRepository, + savedStateHandle: SavedStateHandle, +) : + BaseViewModel( + initialState = ProductCategoryUiState(), + ) { + private val args = savedStateHandle.toRoute() + private val artistId: Long? = args.artistId + val isMyArtist: Boolean = args.isMyArtist + + override fun processIntent(intent: ProductCategoryUiIntent) { + when (intent) { + ProductCategoryUiIntent.OnBackClick -> sendEffect(ProductCategoryUiEffect.NavigateBack) + ProductCategoryUiIntent.OnFloatingClick -> sendEffect(ProductCategoryUiEffect.NavigateToPartyCreate) + ProductCategoryUiIntent.OnSortFilterClick -> updateState { copy(isSortBottomSheetVisible = true) } + is ProductCategoryUiIntent.OnSortSelected -> { + updateState { + copy( + selectedSortType = intent.sortType, + isSortBottomSheetVisible = false, + ) + } + loadGoodsCategoryList(intent.sortType) + } + + ProductCategoryUiIntent.OnSortDismiss -> updateState { copy(isSortBottomSheetVisible = false) } + is ProductCategoryUiIntent.OnCardClick -> sendEffect(ProductCategoryUiEffect.NavigateToProductPartyList(intent.artistId, intent.title)) + } + } + + init { + loadGoodsCategoryList() + } + + private fun loadGoodsCategoryList(sortType: ProductSortType = uiState.value.selectedSortType) = + launchScope { + updateState { copy(productCategoryLoadState = ApiState.Loading) } + + homeRepository.getGoodsCategoryList( + page = 0, + size = 100, + sort = sortType.name, + artistId = artistId, + ) + .onSuccess { goodsCategory -> + updateState { + copy(productCategoryLoadState = ApiState.Success(goodsCategory)) + } + } + .onFailure { throwable -> + updateState { + copy( + productCategoryLoadState = ApiState.Failure( + throwable.message ?: "Failed to load goods category", + ), + ) + } + } + } + } diff --git a/app/src/main/java/com/poti/android/presentation/party/product/productcategory/model/Contracts.kt b/app/src/main/java/com/poti/android/presentation/party/product/productcategory/model/Contracts.kt new file mode 100644 index 00000000..1546887a --- /dev/null +++ b/app/src/main/java/com/poti/android/presentation/party/product/productcategory/model/Contracts.kt @@ -0,0 +1,35 @@ +package com.poti.android.presentation.party.product.productcategory.model + +import com.poti.android.core.base.UiEffect +import com.poti.android.core.base.UiIntent +import com.poti.android.core.base.UiState +import com.poti.android.core.common.state.ApiState +import com.poti.android.domain.model.party.ProductCategory + +data class ProductCategoryUiState( + val productCategoryLoadState: ApiState = ApiState.Loading, + val isSortBottomSheetVisible: Boolean = false, + val selectedSortType: ProductSortType = ProductSortType.LATEST, +) : UiState + +sealed interface ProductCategoryUiIntent : UiIntent { + data object OnBackClick : ProductCategoryUiIntent + + data object OnFloatingClick : ProductCategoryUiIntent + + data object OnSortFilterClick : ProductCategoryUiIntent + + data class OnSortSelected(val sortType: ProductSortType) : ProductCategoryUiIntent + + data object OnSortDismiss : ProductCategoryUiIntent + + data class OnCardClick(val artistId: Long, val title: String) : ProductCategoryUiIntent +} + +sealed interface ProductCategoryUiEffect : UiEffect { + data object NavigateBack : ProductCategoryUiEffect + + data object NavigateToPartyCreate : ProductCategoryUiEffect + + data class NavigateToProductPartyList(val artistId: Long, val title: String) : ProductCategoryUiEffect +} diff --git a/app/src/main/java/com/poti/android/presentation/party/product/productcategory/model/ProductSortType.kt b/app/src/main/java/com/poti/android/presentation/party/product/productcategory/model/ProductSortType.kt new file mode 100644 index 00000000..b7e14a97 --- /dev/null +++ b/app/src/main/java/com/poti/android/presentation/party/product/productcategory/model/ProductSortType.kt @@ -0,0 +1,18 @@ +package com.poti.android.presentation.party.product.productcategory.model + +import androidx.annotation.StringRes +import com.poti.android.R + +enum class ProductSortType( + val request: String, + @StringRes val displayRes: Int, +) { + LATEST( + request = "LATEST", + displayRes = R.string.party_filter_sort_latest, + ), + HOT( + request = "HOT", + displayRes = R.string.party_filter_sort_hot, + ), +} diff --git a/app/src/main/java/com/poti/android/presentation/user/mypage/MyPageScreen.kt b/app/src/main/java/com/poti/android/presentation/user/mypage/MyPageScreen.kt index 396983cf..f4888482 100644 --- a/app/src/main/java/com/poti/android/presentation/user/mypage/MyPageScreen.kt +++ b/app/src/main/java/com/poti/android/presentation/user/mypage/MyPageScreen.kt @@ -38,7 +38,6 @@ import com.poti.android.presentation.user.mypage.model.MyPageUiIntent @Composable fun MyPageRoute( - onNavigateToArtist: () -> Unit, onNavigateToHistoryList: (HistoryMode, HistorySummaryType) -> Unit, modifier: Modifier = Modifier, viewModel: MyPageViewModel = hiltViewModel(), @@ -47,8 +46,6 @@ fun MyPageRoute( HandleSideEffects(viewModel.sideEffect) { effect -> when (effect) { - MyPageUiEffect.NavigateToArtist -> onNavigateToArtist() - is MyPageUiEffect.NavigateToHistoryList -> { onNavigateToHistoryList(effect.mode, effect.tab) } @@ -58,7 +55,7 @@ fun MyPageRoute( uiState.userMyPageLoadState.onSuccess { userMyPage -> MyPageScreen( userMyPage = userMyPage, - onArtistClick = { viewModel.processIntent(MyPageUiIntent.OnArtistClick) }, // TODO: [예림] 선택 최애 없을 때만 이동 + onArtistClick = { }, onHistoryClick = { mode, type -> viewModel.processIntent( MyPageUiIntent.OnHistoryClick(mode, type), diff --git a/app/src/main/java/com/poti/android/presentation/user/mypage/MyPageViewModel.kt b/app/src/main/java/com/poti/android/presentation/user/mypage/MyPageViewModel.kt index 8cd0f827..282f3c51 100644 --- a/app/src/main/java/com/poti/android/presentation/user/mypage/MyPageViewModel.kt +++ b/app/src/main/java/com/poti/android/presentation/user/mypage/MyPageViewModel.kt @@ -17,8 +17,6 @@ class MyPageViewModel @Inject constructor( ) { override fun processIntent(intent: MyPageUiIntent) { when (intent) { - MyPageUiIntent.OnArtistClick -> sendEffect(MyPageUiEffect.NavigateToArtist) - is MyPageUiIntent.OnHistoryClick -> { sendEffect( MyPageUiEffect.NavigateToHistoryList( diff --git a/app/src/main/java/com/poti/android/presentation/user/mypage/model/Contracts.kt b/app/src/main/java/com/poti/android/presentation/user/mypage/model/Contracts.kt index 7f378825..18be2994 100644 --- a/app/src/main/java/com/poti/android/presentation/user/mypage/model/Contracts.kt +++ b/app/src/main/java/com/poti/android/presentation/user/mypage/model/Contracts.kt @@ -13,8 +13,6 @@ data class MyPageUiState( ) : UiState sealed interface MyPageUiIntent : UiIntent { - data object OnArtistClick : MyPageUiIntent - data class OnHistoryClick( val mode: HistoryMode, val tab: HistorySummaryType, @@ -22,8 +20,6 @@ sealed interface MyPageUiIntent : UiIntent { } sealed interface MyPageUiEffect : UiEffect { - data object NavigateToArtist : MyPageUiEffect - data class NavigateToHistoryList( val mode: HistoryMode, val tab: HistorySummaryType, diff --git a/app/src/main/java/com/poti/android/presentation/user/mypage/navigation/MyPageNavigation.kt b/app/src/main/java/com/poti/android/presentation/user/mypage/navigation/MyPageNavigation.kt index ee769036..2ba1faf7 100644 --- a/app/src/main/java/com/poti/android/presentation/user/mypage/navigation/MyPageNavigation.kt +++ b/app/src/main/java/com/poti/android/presentation/user/mypage/navigation/MyPageNavigation.kt @@ -8,7 +8,6 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable import com.poti.android.core.navigation.Route import com.poti.android.presentation.history.navigation.navigateToHistoryList -import com.poti.android.presentation.onboarding.navigation.navigateToOnboardingArtist import com.poti.android.presentation.user.mypage.MyPageRoute import kotlinx.serialization.Serializable @@ -27,7 +26,6 @@ fun NavGraphBuilder.myPageNavGraph( ) { composable { MyPageRoute( - onNavigateToArtist = navController::navigateToOnboardingArtist, onNavigateToHistoryList = navController::navigateToHistoryList, modifier = Modifier.padding(paddingValues), ) diff --git a/app/src/main/res/drawable/ic_logo.xml b/app/src/main/res/drawable/ic_logo.xml deleted file mode 100644 index 8a112c10..00000000 --- a/app/src/main/res/drawable/ic_logo.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - diff --git a/app/src/main/res/drawable/ic_poti_logo.xml b/app/src/main/res/drawable/ic_poti_logo.xml index 8a112c10..0f539d5a 100644 --- a/app/src/main/res/drawable/ic_poti_logo.xml +++ b/app/src/main/res/drawable/ic_poti_logo.xml @@ -7,27 +7,7 @@ - - - - - - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 03959f89..988a44a8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -230,15 +230,15 @@ 다른 굿즈 구경하기 더보기 - - 최신순 - 인기순 + + 최신순 + 인기순 랜덤순 - 마감임박순 - 평점순 - 멤버 선택 - %1$s, %2$s - %1$s, %2$s 외 %3$d명 + 마감임박순 + 평점순 + 멤버 선택 + %1$s, %2$s + %1$s, %2$s 외 %3$d명 %1$s원~ %.1f  |