diff --git a/app/src/main/java/com/texthip/thip/data/di/ServiceModule.kt b/app/src/main/java/com/texthip/thip/data/di/ServiceModule.kt index 3308a37c..ea3fc9e0 100644 --- a/app/src/main/java/com/texthip/thip/data/di/ServiceModule.kt +++ b/app/src/main/java/com/texthip/thip/data/di/ServiceModule.kt @@ -1,12 +1,18 @@ package com.texthip.thip.data.di +import com.texthip.thip.data.service.RoomsService import dagger.Module +import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import retrofit2.Retrofit +import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) object ServiceModule { -// @Provides -// @Singleton + @Provides + @Singleton + fun providesRoomsService(retrofit: Retrofit): RoomsService = + retrofit.create(RoomsService::class.java) } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/data/model/rooms/response/RoomsPlayingResponse.kt b/app/src/main/java/com/texthip/thip/data/model/rooms/response/RoomsPlayingResponse.kt new file mode 100644 index 00000000..978c97fc --- /dev/null +++ b/app/src/main/java/com/texthip/thip/data/model/rooms/response/RoomsPlayingResponse.kt @@ -0,0 +1,37 @@ +package com.texthip.thip.data.model.rooms.response + +import kotlinx.serialization.Serializable + +@Serializable +data class RoomsPlayingResponse( + val isHost: Boolean, + val roomId: Int, + val roomName: String, + val roomImageUrl: String, + val isPublic: Boolean, + val progressStartDate: String, + val progressEndDate: String, + val category: String, + val roomDescription: String, + val memberCount: Int, + val recruitCount: Int, + val isbn: String, + val bookTitle: String, + val authorName: String, + val currentPage: Int, + val userPercentage: Double, + val currentVotes: List +) + +@Serializable +data class CurrentVote( + val content: String, + val page: Int, + val isOverview: Boolean, + val voteItems: List +) + +@Serializable +data class VoteItem( + val itemName: String +) \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/data/model/rooms/response/RoomsUsersResponse.kt b/app/src/main/java/com/texthip/thip/data/model/rooms/response/RoomsUsersResponse.kt new file mode 100644 index 00000000..604d8062 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/data/model/rooms/response/RoomsUsersResponse.kt @@ -0,0 +1,17 @@ +package com.texthip.thip.data.model.rooms.response + +import kotlinx.serialization.Serializable + +@Serializable +data class RoomsUsersResponse( + val userList: List +) + +@Serializable +data class UserList( + val userId: Int, + val nickname: String, + val imageUrl: String, + val alias: String, + val followerCount: Int, +) \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/data/repository/RoomsRepository.kt b/app/src/main/java/com/texthip/thip/data/repository/RoomsRepository.kt new file mode 100644 index 00000000..141a40ed --- /dev/null +++ b/app/src/main/java/com/texthip/thip/data/repository/RoomsRepository.kt @@ -0,0 +1,27 @@ +package com.texthip.thip.data.repository + +import com.texthip.thip.data.model.base.handleBaseResponse +import com.texthip.thip.data.service.RoomsService +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class RoomsRepository @Inject constructor( + private val roomsService: RoomsService, +) { + suspend fun getRoomsPlaying( + roomId: Int + ) = runCatching { + roomsService.getRoomsPlaying( + roomId = roomId + ).handleBaseResponse().getOrThrow() + } + + suspend fun getRoomsUsers( + roomId: Int + ) = runCatching { + roomsService.getRoomsUsers( + roomId = roomId + ).handleBaseResponse().getOrThrow() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/data/service/RoomsService.kt b/app/src/main/java/com/texthip/thip/data/service/RoomsService.kt new file mode 100644 index 00000000..d493c456 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/data/service/RoomsService.kt @@ -0,0 +1,19 @@ +package com.texthip.thip.data.service + +import com.texthip.thip.data.model.base.BaseResponse +import com.texthip.thip.data.model.rooms.response.RoomsPlayingResponse +import com.texthip.thip.data.model.rooms.response.RoomsUsersResponse +import retrofit2.http.GET +import retrofit2.http.Path + +interface RoomsService { + @GET("rooms/{roomId}/playing") + suspend fun getRoomsPlaying( + @Path("roomId") roomId: Int + ): BaseResponse + + @GET("rooms/{roomId}/users") + suspend fun getRoomsUsers( + @Path("roomId") roomId: Int + ): BaseResponse +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/common/buttons/ActionBookButton.kt b/app/src/main/java/com/texthip/thip/ui/common/buttons/ActionBookButton.kt index fd5ebe2f..f2bc6b1b 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/buttons/ActionBookButton.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/buttons/ActionBookButton.kt @@ -32,7 +32,7 @@ fun ActionBookButton( ) { Box( modifier = Modifier - .background(color = colors.DarkGrey, shape = RoundedCornerShape(12.dp)) + .background(color = colors.DarkGrey02, shape = RoundedCornerShape(12.dp)) .clickable { onClick() } diff --git a/app/src/main/java/com/texthip/thip/ui/common/cards/CardNote.kt b/app/src/main/java/com/texthip/thip/ui/common/cards/CardNote.kt index 132fb173..018263bd 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/cards/CardNote.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/cards/CardNote.kt @@ -27,7 +27,7 @@ import com.texthip.thip.ui.theme.ThipTheme.typography @Composable fun CardNote( currentPage: Int, - percentage: Int, + percentage: Double, onClick: () -> Unit = { } ) { Column( @@ -85,7 +85,7 @@ fun CardNote( ) { Box( modifier = Modifier - .fillMaxWidth(fraction = percentage / 100f) + .fillMaxWidth(fraction = (percentage / 100f).toFloat()) .fillMaxHeight() .background(color = colors.Purple, shape = RoundedCornerShape(12.dp)) ) @@ -98,7 +98,7 @@ fun CardNote( private fun CardNotePreview() { CardNote( currentPage = 50, - percentage = 30, + percentage = 30.0, onClick = { } ) } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt b/app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt index 7795853e..9002c2cb 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -22,16 +23,15 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.texthip.thip.R -import com.texthip.thip.ui.common.buttons.GroupVoteButton -import com.texthip.thip.ui.group.room.mock.VoteData -import com.texthip.thip.ui.group.room.mock.mockVoteData +import com.texthip.thip.data.model.rooms.response.CurrentVote +import com.texthip.thip.data.model.rooms.response.VoteItem import com.texthip.thip.ui.theme.ThipTheme.colors import com.texthip.thip.ui.theme.ThipTheme.typography @Composable fun CardVote( - voteData: List, - onVoteClick: (VoteData) -> Unit = {} + voteData: List, + onVoteClick: (CurrentVote) -> Unit = {} ) { val pageCount = voteData.size val pagerState = rememberPagerState(pageCount = { pageCount }) @@ -70,7 +70,6 @@ fun CardVote( modifier = Modifier.fillMaxWidth() ) { page -> val vote = voteData[page] - val voteItems = vote.voteItems.take(3) // 최대 3개만 Column( modifier = Modifier @@ -80,35 +79,58 @@ fun CardVote( verticalArrangement = Arrangement.spacedBy(10.dp) ) { Text( - text = vote.description, + text = vote.content, style = typography.info_m500_s12, color = colors.White, ) - GroupVoteButton( - voteItems = voteItems, - selectedIndex = null, // 표시용이므로 선택 없음 - hasVoted = false, // 투표 상태 없음 - onOptionSelected = { onVoteClick(vote) } // 어떤 항목을 눌러도 이동 - ) + vote.voteItems.forEachIndexed { index, item -> + Box( + modifier = Modifier + .fillMaxWidth() + .background( + color = colors.DarkGrey, + shape = RoundedCornerShape(12.dp) + ) + .height(44.dp) + ) { + Row( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 12.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Text( +// text = "${index + 1}. ${item.itemName}", + text = stringResource( + R.string.numbering, + index + 1, + item.itemName + ), + color = colors.White, + style = typography.feedcopy_r400_s14_h20 + ) + } + } + } } } + } - Row( - Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - repeat(pageCount) { iteration -> - val color = - if (pagerState.currentPage == iteration) colors.White else colors.Grey02 - Box( - modifier = Modifier - .padding(horizontal = 12.dp) - .background(color, CircleShape) - .size(4.dp) - ) - } + Row( + Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + repeat(pageCount) { iteration -> + val color = + if (pagerState.currentPage == iteration) colors.White else colors.Grey02 + Box( + modifier = Modifier + .padding(horizontal = 12.dp) + .background(color, CircleShape) + .size(4.dp) + ) } } } @@ -123,7 +145,28 @@ private fun CardVotePreview() { .padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { - CardVote(voteData = mockVoteData) - CardVote(voteData = emptyList()) + CardVote( + voteData = listOf( + CurrentVote( + content = "3연에 나오는 심장은 무엇을 의미하는 걸까요?", + page = 12, + isOverview = false, + voteItems = listOf( + VoteItem("사랑"), + VoteItem("희생"), + VoteItem("고통"), + ) + ), + CurrentVote( + content = "가장 인상 깊었던 구절은 무엇인가요?", + page = 25, + isOverview = false, + voteItems = listOf( + VoteItem("1연 1행"), + VoteItem("2연 3행"), + ) + ) + ) + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt b/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt index 132889d2..e0d8efd6 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt @@ -1,10 +1,7 @@ package com.texthip.thip.ui.common.header -import androidx.compose.foundation.Image -import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -19,13 +16,12 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import coil.compose.AsyncImage import com.texthip.thip.R -import com.texthip.thip.ui.theme.Grey import com.texthip.thip.ui.theme.ThipTheme import com.texthip.thip.ui.theme.ThipTheme.colors import com.texthip.thip.ui.theme.ThipTheme.typography @@ -33,7 +29,7 @@ import com.texthip.thip.ui.theme.ThipTheme.typography @Composable fun ProfileBar( modifier: Modifier = Modifier, - profileImage: Painter?, + profileImage: String, topText: String, bottomText: String, bottomTextColor: Color = colors.NeonGreen, // todo: 서버에서 색 보내주는걸로 받기? @@ -48,22 +44,13 @@ fun ProfileBar( .clickable { onClick() }, verticalAlignment = Alignment.CenterVertically ) { - if (profileImage != null) { - Image( - painter = profileImage, - contentDescription = "프로필 이미지", - modifier = Modifier - .size(36.dp) - .clip(CircleShape) - ) - } else { - Box( - modifier = Modifier - .size(36.dp) - .clip(CircleShape) - .background(Grey) - ) - } + AsyncImage( + model = profileImage, + contentDescription = "프로필 이미지", + modifier = Modifier + .size(36.dp) + .clip(CircleShape) + ) Spacer(modifier = Modifier.width(8.dp)) Column( modifier = Modifier.weight(1f), @@ -119,14 +106,14 @@ fun PreviewProfileBar() { ThipTheme { Column { ProfileBar( - profileImage = null, + profileImage = "문학_image", topText = "user.01", bottomText = stringResource(R.string.influencer), showSubscriberInfo = true, subscriberCount = 77 ) ProfileBar( - profileImage = null, + profileImage = "문학_image", topText = "user.04", bottomText = stringResource(R.string.influencer), showSubscriberInfo = false, diff --git a/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBarFeed.kt b/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBarFeed.kt index b74bb4d2..03690bd2 100644 --- a/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBarFeed.kt +++ b/app/src/main/java/com/texthip/thip/ui/common/header/ProfileBarFeed.kt @@ -88,7 +88,7 @@ fun ProfileBarFeedPreview() { profileImage = null, nickname = "user.01", genreName = "칭호칭호", - genreColor = colors.Orange, + genreColor = colors.SocialScience, date = "2025.01.12" ) } diff --git a/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedCommentScreen.kt b/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedCommentScreen.kt index 0ff1b2b3..cdf7c34d 100644 --- a/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedCommentScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedCommentScreen.kt @@ -48,6 +48,8 @@ import com.texthip.thip.ui.common.forms.CommentTextField import com.texthip.thip.ui.common.header.ProfileBar import com.texthip.thip.ui.common.modal.DialogPopup import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar +import com.texthip.thip.ui.group.note.component.CommentItem +import com.texthip.thip.ui.group.note.component.ReplyItem import com.texthip.thip.ui.feed.component.ImageViewerModal import com.texthip.thip.ui.feed.mock.FeedItemType import com.texthip.thip.ui.group.note.component.CommentItem @@ -65,6 +67,8 @@ import com.texthip.thip.ui.group.note.mock.ReplyItem as FeedReplyItem fun FeedCommentScreen( modifier: Modifier = Modifier, feedItem: FeedItem, + bookImage: Painter? = null, + profileImage: String, feedType: FeedItemType, profileImage: Painter? = null, currentUserId: Int, @@ -531,6 +535,11 @@ private fun FeedCommentScreenPrev() { R.drawable.bookcover_sample, R.drawable.bookcover_sample ), + bookImage = painterResource(R.drawable.bookcover_sample), + profileImage = "https://example.com/image1.jpg", + onLikeClick = {}, + onCommentInputChange = {}, + onSendClick = {}, tags = listOf("에세이", "문학", "힐링") ) val commentList = remember { mutableStateListOf() } diff --git a/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt b/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt index d896e9b9..1cd2268a 100644 --- a/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt @@ -19,7 +19,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -43,8 +42,8 @@ import com.texthip.thip.ui.theme.ThipTheme.typography @Composable fun FeedScreen( navController: NavController? = null, - nickname: String, - userRole: String, + nickname: String = "", + userRole: String = "", feeds: List = emptyList(), totalFeedCount: Int = 0, selectedTabIndex: Int = 0, @@ -61,49 +60,49 @@ fun FeedScreen( profileImageUrl = "https://example.com/image1.jpg", nickname = "abcabcabcabc", role = "문학가", - roleColor = colors.Orange + roleColor = colors.SocialScience ), MySubscriptionData( profileImageUrl = "https://example.com/image.jpg", nickname = "aaaaaaa", role = "작가", - roleColor = colors.Orange + roleColor = colors.SocialScience ), MySubscriptionData( profileImageUrl = "https://example.com/image1.jpg", nickname = "abcabcabcabc", role = "문학가", - roleColor = colors.Orange + roleColor = colors.SocialScience ), MySubscriptionData( profileImageUrl = "https://example.com/image.jpg", nickname = "aaaaaaa", role = "작가", - roleColor = colors.Orange + roleColor = colors.SocialScience ), MySubscriptionData( profileImageUrl = "https://example.com/image1.jpg", nickname = "abcabcabcabc", role = "문학가", - roleColor = colors.Orange + roleColor = colors.SocialScience ), MySubscriptionData( profileImageUrl = "https://example.com/image.jpg", nickname = "aaaaaaa", role = "작가", - roleColor = colors.Orange + roleColor = colors.SocialScience ), MySubscriptionData( profileImageUrl = "https://example.com/image1.jpg", nickname = "abcabcabcabc", role = "문학가", - roleColor = colors.Orange + roleColor = colors.SocialScience ), MySubscriptionData( profileImageUrl = "https://example.com/image.jpg", nickname = "aaaaaaa", role = "작가", - roleColor = colors.Orange + roleColor = colors.SocialScience ) ) Box(modifier = Modifier.fillMaxSize()) { diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentItem.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentItem.kt index 6672518a..8a5de977 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentItem.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/CommentItem.kt @@ -43,7 +43,7 @@ fun CommentItem( profileImage = painterResource(R.drawable.character_literature), nickname = data.nickName, genreName = data.genreName, - genreColor = colors.Orange, + genreColor = colors.SocialScience, date = data.postDate ) diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/ReplyItem.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/ReplyItem.kt index 3849a853..29b5ec69 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/component/ReplyItem.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/ReplyItem.kt @@ -54,7 +54,7 @@ fun ReplyItem( profileImage = painterResource(R.drawable.character_literature), nickname = data.nickName, genreName = data.genreName, - genreColor = colors.Orange, + genreColor = colors.SocialScience, date = data.postDate ) diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt index 85e2b952..1363f3e0 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/TextCommentCard.kt @@ -13,7 +13,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.blur import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -49,7 +48,7 @@ fun TextCommentCard( ) { ProfileBar( modifier = Modifier.padding(0.dp), - profileImage = painterResource(R.drawable.character_literature), + profileImage = "https://example.com/image1.jpg", topText = data.nickName, bottomText = data.page.toString() + stringResource(R.string.page), bottomTextColor = colors.Purple, diff --git a/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt b/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt index 60def258..1662f38f 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/note/component/VoteCommentCard.kt @@ -13,7 +13,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.blur import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -54,7 +53,7 @@ fun VoteCommentCard( verticalArrangement = Arrangement.spacedBy(8.dp) ) { ProfileBar( - profileImage = painterResource(R.drawable.character_literature), + profileImage = "https://example.com/image1.jpg", topText = data.nickName, bottomText = data.page.toString() + stringResource(R.string.page), bottomTextColor = colors.Purple, diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomBody.kt b/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomBody.kt index 9d8a2600..ecfbf519 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomBody.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomBody.kt @@ -9,30 +9,34 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.texthip.thip.R +import com.texthip.thip.data.model.rooms.response.CurrentVote +import com.texthip.thip.data.model.rooms.response.VoteItem import com.texthip.thip.ui.common.buttons.ActionBookButton import com.texthip.thip.ui.common.cards.CardChat import com.texthip.thip.ui.common.cards.CardNote import com.texthip.thip.ui.common.cards.CardVote -import com.texthip.thip.ui.group.room.mock.GroupRoomBodyData -import com.texthip.thip.ui.group.room.mock.mockVoteData @Composable fun GroupRoomBody( modifier: Modifier = Modifier, - data: GroupRoomBodyData + bookTitle: String, + authorName: String, + currentPage: Int, + userPercentage: Double, + currentVotes: List ) { Column( modifier = modifier.padding(horizontal = 20.dp), verticalArrangement = Arrangement.spacedBy(20.dp) ) { ActionBookButton( - bookTitle = data.bookTitle, - bookAuthor = data.bookAuthor + bookTitle = bookTitle, + bookAuthor = authorName ) {} CardNote( - currentPage = data.currentPage, - percentage = data.percentage, + currentPage = currentPage, + percentage = userPercentage ) {} CardChat( @@ -41,7 +45,7 @@ fun GroupRoomBody( ) {} CardVote( - voteData = data.voteList + voteData = currentVotes ) } } @@ -50,12 +54,30 @@ fun GroupRoomBody( @Composable private fun GroupRoomBodyPreview() { GroupRoomBody( - data = GroupRoomBodyData( - bookTitle = "호르몬 체인지", - bookAuthor = "최정화", - currentPage = 100, - percentage = 50, - voteList = mockVoteData + bookTitle = "책 제목", + authorName = "저자 이름", + currentPage = 100, + userPercentage = 50.0, + currentVotes = listOf( + CurrentVote( + content = "3연에 나오는 심장은 무엇을 의미하는 걸까요?", + page = 12, + isOverview = false, + voteItems = listOf( + VoteItem("사랑"), + VoteItem("희생"), + VoteItem("고통"), + ) + ), + CurrentVote( + content = "가장 인상 깊었던 구절은 무엇인가요?", + page = 25, + isOverview = false, + voteItems = listOf( + VoteItem("1연 1행"), + VoteItem("2연 3행"), + ) + ) ) ) } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomHeader.kt b/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomHeader.kt index 5cf61e14..faed3109 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomHeader.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomHeader.kt @@ -1,6 +1,7 @@ package com.texthip.thip.ui.group.room.component import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -23,14 +24,25 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.texthip.thip.R -import com.texthip.thip.ui.group.room.mock.GroupRoomHeaderData import com.texthip.thip.ui.theme.ThipTheme.colors import com.texthip.thip.ui.theme.ThipTheme.typography +import com.texthip.thip.utils.type.GenreColor @Composable fun GroupRoomHeader( - data: GroupRoomHeaderData + roomName: String, + roomDescription: String, + isPublic: Boolean, + progressStartDate: String, + progressEndDate: String, + memberCount: Int, + category: String, + color: String = "RED", // TODO: 서버에서 색상 추가해주면 수정, + onNavigateToMates: () -> Unit = { } ) { + val categoryColorEnum = GenreColor.fromString(color) + val categoryColor = categoryColorEnum.colorProvider() + Column( modifier = Modifier.padding(horizontal = 20.dp) ) { @@ -39,12 +51,12 @@ fun GroupRoomHeader( verticalAlignment = Alignment.CenterVertically, ) { Text( - text = data.groupRoomName, + text = roomName, style = typography.bigtitle_b700_s22_h24, color = colors.White ) - if (data.isPrivate) { + if (!isPublic) { Icon( painter = painterResource(R.drawable.ic_lock), contentDescription = "Lock Icon", @@ -65,7 +77,7 @@ fun GroupRoomHeader( Spacer(Modifier.height(4.dp)) Text( - text = data.introductionContent, + text = roomDescription, style = typography.copy_r400_s12_h20, color = colors.White ) @@ -94,13 +106,19 @@ fun GroupRoomHeader( } Spacer(Modifier.height(12.dp)) Text( - text = data.period, + text = stringResource( + R.string.group_room_period, + progressStartDate, + progressEndDate + ), style = typography.timedate_r400_s11, color = colors.White ) } - Column { + Column( + modifier = Modifier.clickable { onNavigateToMates() } + ) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, @@ -134,7 +152,7 @@ fun GroupRoomHeader( } Spacer(Modifier.height(12.dp)) Text( - text = stringResource(R.string.participate_num, data.participantCount), + text = stringResource(R.string.participate_num, memberCount), style = typography.menu_sb600_s12, color = colors.White ) @@ -156,9 +174,9 @@ fun GroupRoomHeader( modifier = Modifier.padding(end = 4.dp) ) Text( - text = data.genre, + text = category, style = typography.info_m500_s12, - color = colors.Orange // TODO: 장르에 맞는 색으로 변경 + color = categoryColor ) } } @@ -169,13 +187,12 @@ fun GroupRoomHeader( @Composable private fun GroupRoomHeaderPreview() { GroupRoomHeader( - data = GroupRoomHeaderData( - groupRoomName = "호르몬 체인지 완독하는 방", - introductionContent = "‘시집만 읽는 사람들’ 3월 모임입니다. 이번 달 모임방은 심장보다 단단한 토마토 한 알 완독합니다.", - isPrivate = true, - period = "2023.10.01 ~ 2023.10.31", - participantCount = 22, - genre = "문학" - ) + roomName = "호르몬 체인지 완독하는 방", + roomDescription = "‘시집만 읽는 사람들’ 3월 모임입니다. 이번 달 모임방은 심장보다 단단한 토마토 한 알 완독합니다.", + isPublic = true, + progressStartDate = "2023.10.01", + progressEndDate = "2023.10.31", + memberCount = 22, + category = "문학" ) } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomMatesList.kt b/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomMatesList.kt index cb522094..0188acd7 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomMatesList.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomMatesList.kt @@ -9,13 +9,15 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.texthip.thip.data.model.rooms.response.RoomsUsersResponse +import com.texthip.thip.data.model.rooms.response.UserList import com.texthip.thip.ui.common.header.ProfileBar -import com.texthip.thip.ui.group.room.mock.GroupRoomMateData import com.texthip.thip.ui.theme.ThipTheme.colors @Composable fun GroupRoomMatesList( - members: List + members: RoomsUsersResponse, + onUserClick: (Int) -> Unit = {} ) { Column( verticalArrangement = Arrangement.spacedBy(16.dp), @@ -23,17 +25,19 @@ fun GroupRoomMatesList( .fillMaxWidth() .padding(20.dp) ) { - members.forEachIndexed { index, member -> + val userList = members.userList + userList.forEachIndexed { index, member -> ProfileBar( - profileImage = member.profileImageUrl, + profileImage = member.imageUrl, topText = member.nickname, - bottomText = member.role, - bottomTextColor = member.roleColor, + bottomText = member.alias, +// bottomTextColor = member.aliasColor, + bottomTextColor = colors.ScienceIt, // TODO: 서버에서 보내주는 색상으로 수정 showSubscriberInfo = true, - subscriberCount = member.subscriberCount - ) {} + subscriberCount = member.followerCount + ) { onUserClick(member.userId) } - if (index != members.lastIndex) { + if (index != userList.lastIndex) { HorizontalDivider( color = colors.DarkGrey02, thickness = 1.dp @@ -47,35 +51,24 @@ fun GroupRoomMatesList( @Composable private fun GroupRoomMatesListPreview() { GroupRoomMatesList( - members = listOf( - GroupRoomMateData( - profileImageUrl = null, - nickname = "Thiper", - role = "칭호칭호", - roleColor = colors.Yellow, - subscriberCount = 100 - ), - GroupRoomMateData( - profileImageUrl = null, - nickname = "thipthip", - role = "공식 인플루언서", - roleColor = colors.NeonGreen, - subscriberCount = 50 - ), - GroupRoomMateData( - profileImageUrl = null, - nickname = "Thiper", - role = "칭호칭호", - roleColor = colors.Yellow, - subscriberCount = 100 - ), - GroupRoomMateData( - profileImageUrl = null, - nickname = "thip01", - role = "작가", - roleColor = colors.NeonGreen, - subscriberCount = 100 - ), - ) + members = + RoomsUsersResponse( + listOf( + UserList( + userId = 1, + nickname = "김희용", + alias = "문학가", + imageUrl = "https://example.com/image1.jpg", + followerCount = 100 + ), + UserList( + userId = 2, + nickname = "노성준", + alias = "문학가", + imageUrl = "https://example.com/image1.jpg", + followerCount = 100 + ), + ) + ) ) } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/mock/GroupRoomBodyData.kt b/app/src/main/java/com/texthip/thip/ui/group/room/mock/GroupRoomBodyData.kt deleted file mode 100644 index 6bce72ba..00000000 --- a/app/src/main/java/com/texthip/thip/ui/group/room/mock/GroupRoomBodyData.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.texthip.thip.ui.group.room.mock - -data class GroupRoomBodyData( - val bookTitle: String, - val bookAuthor: String, - val currentPage: Int, - val percentage: Int, - val voteList: List -) diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/mock/GroupRoomHeaderData.kt b/app/src/main/java/com/texthip/thip/ui/group/room/mock/GroupRoomHeaderData.kt deleted file mode 100644 index 71d9b579..00000000 --- a/app/src/main/java/com/texthip/thip/ui/group/room/mock/GroupRoomHeaderData.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.texthip.thip.ui.group.room.mock - -data class GroupRoomHeaderData( - val groupRoomName: String, - val isPrivate: Boolean, - val introductionContent: String, - val period: String, - val participantCount: Int, - val genre: String -) diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/mock/GroupRoomMateData.kt b/app/src/main/java/com/texthip/thip/ui/group/room/mock/GroupRoomMateData.kt deleted file mode 100644 index 5af77a32..00000000 --- a/app/src/main/java/com/texthip/thip/ui/group/room/mock/GroupRoomMateData.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.texthip.thip.ui.group.room.mock - -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.painter.Painter - -data class GroupRoomMateData( - val profileImageUrl: Painter? = null, - val nickname: String, - val role: String, - val roleColor: Color, - val subscriberCount: Int, -) \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/mock/VoteData.kt b/app/src/main/java/com/texthip/thip/ui/group/room/mock/VoteData.kt deleted file mode 100644 index acff9b1a..00000000 --- a/app/src/main/java/com/texthip/thip/ui/group/room/mock/VoteData.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.texthip.thip.ui.group.room.mock - -import com.texthip.thip.ui.group.note.mock.VoteItem - -data class VoteData( - val description: String, - val voteItems: List -) - -val mockVoteData = listOf( - VoteData( - description = "투표 내용입니다...", - voteItems = listOf( - VoteItem(1, "김땡땡", 50, false), - VoteItem(2, "이땡땡", 10, false), -// VoteItem(3, "박땡땡", 20, false), -// VoteItem(4, "최땡땡", 15, false), -// VoteItem(5, "정땡땡", 5, false) - ) - ), - VoteData( - description = "옆으로 넘긴 다른 투표 01", - voteItems = listOf( - VoteItem(1, "어쩌구", 25, false), - VoteItem(2, "저쩌구", 45, false), - VoteItem(3, "삼번", 20, false), - VoteItem(4, "사번", 10, false) - ) - ), - VoteData( - description = "옆으로 넘긴 다른 투표 02", - voteItems = listOf( - VoteItem(1, "투표 제목과 항목 버튼이 가로 스크롤되고", 40, false), - VoteItem(2, "아래 캐러셀 닷은", 35, false), - VoteItem(3, "위치 그대로, 강조점만 바뀌도록.", 25, false) - ) - ) -) \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomMatesScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomMatesScreen.kt index ae189a1c..a511d0a7 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomMatesScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomMatesScreen.kt @@ -1,25 +1,76 @@ package com.texthip.thip.ui.group.room.screen +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.height import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +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.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.texthip.thip.R +import com.texthip.thip.data.model.rooms.response.RoomsUsersResponse +import com.texthip.thip.data.model.rooms.response.UserList import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar import com.texthip.thip.ui.group.room.component.GroupRoomMatesList -import com.texthip.thip.ui.group.room.mock.GroupRoomMateData +import com.texthip.thip.ui.group.room.viewmodel.GroupRoomMatesUiState +import com.texthip.thip.ui.group.room.viewmodel.GroupRoomMatesViewModel import com.texthip.thip.ui.theme.ThipTheme import com.texthip.thip.ui.theme.ThipTheme.colors @Composable -fun GroupRoomMatesScreen() { +fun GroupRoomMatesScreen( + roomId: Int, + onBackClick: () -> Unit = {}, + onUserClick: (Int) -> Unit = {}, + viewModel: GroupRoomMatesViewModel = hiltViewModel() +) { + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + + // 화면이 처음 그려질 때 데이터 로딩 실행 + LaunchedEffect(key1 = Unit) { + viewModel.fetchUsers(roomId) + } + + // UI 상태에 따라 다른 화면을 보여줌 + when (val state = uiState) { + is GroupRoomMatesUiState.Loading -> { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + CircularProgressIndicator() + } + } + + is GroupRoomMatesUiState.Success -> { + // 성공 시, 실제 데이터를 화면에 표시 + GroupRoomMatesContent( + data = state.users, + onBackClick = onBackClick, + onUserClick = onUserClick + ) + } + + is GroupRoomMatesUiState.Error -> { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + Text(text = state.message, color = colors.White) // TODO: 에러 메시지 스타일링 + } + } + } +} + +@Composable +fun GroupRoomMatesContent( + data: RoomsUsersResponse, + onBackClick: () -> Unit = {}, + onUserClick: (Int) -> Unit = {}, +) { val scrollState = rememberScrollState() Column( @@ -28,100 +79,15 @@ fun GroupRoomMatesScreen() { ) { DefaultTopAppBar( title = stringResource(R.string.group_room_mates), - onLeftClick = {}, + onLeftClick = onBackClick, ) Column( modifier = Modifier .verticalScroll(scrollState) ) { - Spacer(Modifier.height(40.dp)) GroupRoomMatesList( - members = listOf( - GroupRoomMateData( - profileImageUrl = null, - nickname = "Thiper", - role = "칭호칭호", - roleColor = colors.Yellow, - subscriberCount = 100 - ), - GroupRoomMateData( - profileImageUrl = null, - nickname = "thipthip", - role = "공식 인플루언서", - roleColor = colors.NeonGreen, - subscriberCount = 50 - ), - GroupRoomMateData( - profileImageUrl = null, - nickname = "Thiper", - role = "칭호칭호", - roleColor = colors.Yellow, - subscriberCount = 100 - ), - GroupRoomMateData( - profileImageUrl = null, - nickname = "thip01", - role = "작가", - roleColor = colors.NeonGreen, - subscriberCount = 100 - ), - GroupRoomMateData( - profileImageUrl = null, - nickname = "Thiper", - role = "칭호칭호", - roleColor = colors.Yellow, - subscriberCount = 100 - ), - GroupRoomMateData( - profileImageUrl = null, - nickname = "thipthip", - role = "공식 인플루언서", - roleColor = colors.NeonGreen, - subscriberCount = 50 - ), - GroupRoomMateData( - profileImageUrl = null, - nickname = "Thiper", - role = "칭호칭호", - roleColor = colors.Yellow, - subscriberCount = 100 - ), - GroupRoomMateData( - profileImageUrl = null, - nickname = "thip01", - role = "작가", - roleColor = colors.NeonGreen, - subscriberCount = 100 - ), - GroupRoomMateData( - profileImageUrl = null, - nickname = "Thiper", - role = "칭호칭호", - roleColor = colors.Yellow, - subscriberCount = 100 - ), - GroupRoomMateData( - profileImageUrl = null, - nickname = "thipthip", - role = "공식 인플루언서", - roleColor = colors.NeonGreen, - subscriberCount = 50 - ), - GroupRoomMateData( - profileImageUrl = null, - nickname = "Thiper", - role = "칭호칭호", - roleColor = colors.Yellow, - subscriberCount = 100 - ), - GroupRoomMateData( - profileImageUrl = null, - nickname = "thip01", - role = "작가", - roleColor = colors.NeonGreen, - subscriberCount = 100 - ), - ) + members = data, + onUserClick = onUserClick, ) } } @@ -131,6 +97,27 @@ fun GroupRoomMatesScreen() { @Composable private fun GroupRoomMatesScreenPreview() { ThipTheme { - GroupRoomMatesScreen() + GroupRoomMatesContent( + data = RoomsUsersResponse( + listOf( + UserList( + userId = 1, + nickname = "김희용", + alias = "문학가", + imageUrl = "https://example.com/image1.jpg", + followerCount = 100 + ), + UserList( + userId = 2, + nickname = "노성준", + alias = "문학가", + imageUrl = "https://example.com/image1.jpg", + followerCount = 100 + ), + ) + ), + onBackClick = {}, + onUserClick = {} + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomRecruitScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomRecruitScreen.kt index 4ff90801..6d385dda 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomRecruitScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomRecruitScreen.kt @@ -279,7 +279,7 @@ fun GroupRoomRecruitScreen( Text( text = detail.genre, style = typography.info_m500_s12, - color = colors.genreColor + color = colors.SocialScience ) } } diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt b/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt index bd97b6d2..9a40056b 100644 --- a/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt @@ -1,6 +1,7 @@ package com.texthip.thip.ui.group.room.screen -import androidx.compose.foundation.Image +import com.texthip.thip.data.model.rooms.response.RoomsPlayingResponse +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -10,8 +11,11 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -19,28 +23,73 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.blur +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import coil.compose.AsyncImage import com.texthip.thip.R import com.texthip.thip.ui.common.bottomsheet.MenuBottomSheet import com.texthip.thip.ui.common.modal.DialogPopup import com.texthip.thip.ui.common.topappbar.GradationTopAppBar import com.texthip.thip.ui.group.room.component.GroupRoomBody import com.texthip.thip.ui.group.room.component.GroupRoomHeader -import com.texthip.thip.ui.group.room.mock.GroupRoomBodyData -import com.texthip.thip.ui.group.room.mock.GroupRoomHeaderData import com.texthip.thip.ui.group.room.mock.MenuBottomSheetItem -import com.texthip.thip.ui.group.room.mock.mockVoteData +import com.texthip.thip.ui.group.room.viewmodel.GroupRoomUiState +import com.texthip.thip.ui.group.room.viewmodel.GroupRoomViewModel import com.texthip.thip.ui.theme.ThipTheme import com.texthip.thip.ui.theme.ThipTheme.colors +import com.texthip.thip.utils.type.GenreBackgroundImage -@OptIn(ExperimentalMaterial3Api::class) @Composable fun GroupRoomScreen( - onBackClick: () -> Unit = {} + roomId: Int, + onBackClick: () -> Unit = {}, + onNavigateToMates: () -> Unit = {}, + viewModel: GroupRoomViewModel = hiltViewModel() +) { + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + + // 화면이 처음 그려질 때 데이터 로딩 실행 + LaunchedEffect(key1 = Unit) { + viewModel.fetchRoomsPlaying(roomId) + } + + // UI 상태에 따라 다른 화면을 보여줌 + when (val state = uiState) { + is GroupRoomUiState.Loading -> { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + CircularProgressIndicator() + } + } + + is GroupRoomUiState.Success -> { + // 성공 시, 실제 데이터를 화면에 표시 + GroupRoomContent( + roomDetails = state.roomsPlaying, + onBackClick = onBackClick, + onNavigateToMates = onNavigateToMates + ) + } + + is GroupRoomUiState.Error -> { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + Text(text = state.message, color = colors.White) // TODO: 에러 메시지 스타일링 + } + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun GroupRoomContent( + roomDetails: RoomsPlayingResponse, + onBackClick: () -> Unit = {}, + onNavigateToMates: () -> Unit = {} ) { val scrollState = rememberScrollState() @@ -48,7 +97,18 @@ fun GroupRoomScreen( var isLeaveDialogVisible by remember { mutableStateOf(false) } var isDeleteDialogVisible by remember { mutableStateOf(false) } - val isOwner = false // 서버에서 받아오기 + val isOwner = roomDetails.isHost + + val imageModel = remember(roomDetails.roomImageUrl) { + // 서버에서 받은 문자열이 "_image"로 끝나면 Enum에서 로컬 리소스를 찾음 + if (roomDetails.roomImageUrl.endsWith("_image")) { + GenreBackgroundImage.fromServerValue(roomDetails.roomImageUrl).imageResId + } + // 그렇지 않으면 URL로 그대로 사용 + else { + roomDetails.roomImageUrl + } + } Box( if (isBottomSheetVisible || isLeaveDialogVisible || isDeleteDialogVisible) { @@ -60,41 +120,57 @@ fun GroupRoomScreen( } ) { Box(modifier = Modifier.verticalScroll(scrollState)) { - Image( - painter = painterResource(R.drawable.img_group_room), - contentDescription = null, - contentScale = ContentScale.Crop, + Box( modifier = Modifier .fillMaxWidth() - .height(360.dp) - ) + .height(336.dp) + ) { + AsyncImage( + model = imageModel, + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier.fillMaxSize() + ) + + Box( + modifier = Modifier + .fillMaxSize() + .background( + brush = Brush.verticalGradient( + colorStops = arrayOf( + 0.0594f to Color.Transparent, + 0.94f to colors.Black + ) + ) + ) + ) + } Column( modifier = Modifier .fillMaxWidth() - .padding(top = 76.dp, bottom = 20.dp) + .padding(top = 70.dp, bottom = 20.dp) ) { GroupRoomHeader( - data = GroupRoomHeaderData( - groupRoomName = "호르몬 체인지 완독하는 방", - introductionContent = "‘시집만 읽는 사람들’ 3월 모임입니다. 이번 달 모임방은 심장보다 단단한 토마토 한 알 완독합니다.", - isPrivate = true, - period = "2023.10.01 ~ 2023.10.31", - participantCount = 22, - genre = "문학" - ) - ) + roomName = roomDetails.roomName, + roomDescription = roomDetails.roomDescription, + isPublic = roomDetails.isPublic, + progressStartDate = roomDetails.progressStartDate, + progressEndDate = roomDetails.progressEndDate, + memberCount = roomDetails.memberCount, + category = roomDetails.category + ) { + onNavigateToMates() + } Spacer(Modifier.height(30.dp)) GroupRoomBody( - data = GroupRoomBodyData( - bookTitle = "호르몬 체인지", - bookAuthor = "최정화", - currentPage = 100, - percentage = 50, - voteList = mockVoteData - ) + bookTitle = roomDetails.bookTitle, + authorName = roomDetails.authorName, + currentPage = roomDetails.currentPage, + userPercentage = roomDetails.userPercentage, + currentVotes = roomDetails.currentVotes ) } } @@ -182,6 +258,27 @@ fun GroupRoomScreen( @Composable private fun GroupRoomScreenPreview() { ThipTheme { - GroupRoomScreen() + GroupRoomContent( + roomDetails = RoomsPlayingResponse( + isHost = true, + roomId = 1, + roomName = "호르몬 체인지 완독하는 방", + roomImageUrl = "문학_image", + isPublic = false, + progressStartDate = "2023.10.01", + progressEndDate = "2023.10.31", + category = "문학", + roomDescription = "‘시집만 읽는 사람들’ 3월 모임입니다.", + memberCount = 22, + recruitCount = 30, + isbn = "12345", + bookTitle = "호르몬 체인지", + authorName = "최정화", + currentPage = 100, + userPercentage = 5.0, + currentVotes = emptyList() + ), + onBackClick = {} + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/viewmodel/GroupRoomMatesViewModel.kt b/app/src/main/java/com/texthip/thip/ui/group/room/viewmodel/GroupRoomMatesViewModel.kt new file mode 100644 index 00000000..77e4179a --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/group/room/viewmodel/GroupRoomMatesViewModel.kt @@ -0,0 +1,44 @@ +package com.texthip.thip.ui.group.room.viewmodel + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.texthip.thip.data.model.rooms.response.RoomsUsersResponse +import com.texthip.thip.data.repository.RoomsRepository +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +sealed interface GroupRoomMatesUiState { + data object Loading : GroupRoomMatesUiState + data class Success(val users: RoomsUsersResponse) : GroupRoomMatesUiState + data class Error(val message: String) : GroupRoomMatesUiState +} + +@HiltViewModel +class GroupRoomMatesViewModel @Inject constructor( + private val roomsRepository: RoomsRepository +) : ViewModel() { + + private val _uiState = MutableStateFlow(GroupRoomMatesUiState.Loading) + val uiState = _uiState.asStateFlow() + + fun fetchUsers(roomId: Int) { + viewModelScope.launch { + _uiState.value = GroupRoomMatesUiState.Loading + + roomsRepository.getRoomsUsers(roomId = roomId) + .onSuccess { users -> + if (users != null) { + _uiState.value = GroupRoomMatesUiState.Success(users) + } + } + .onFailure { throwable -> + _uiState.value = GroupRoomMatesUiState.Error( + throwable.message ?: "알 수 없는 오류가 발생했습니다." + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/group/room/viewmodel/GroupRoomViewModel.kt b/app/src/main/java/com/texthip/thip/ui/group/room/viewmodel/GroupRoomViewModel.kt new file mode 100644 index 00000000..3fa2d3b3 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/ui/group/room/viewmodel/GroupRoomViewModel.kt @@ -0,0 +1,44 @@ +package com.texthip.thip.ui.group.room.viewmodel + +import com.texthip.thip.data.model.rooms.response.RoomsPlayingResponse +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.texthip.thip.data.repository.RoomsRepository +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +sealed interface GroupRoomUiState { + data object Loading : GroupRoomUiState // 로딩 중 + data class Success(val roomsPlaying: RoomsPlayingResponse) : GroupRoomUiState // 성공 + data class Error(val message: String) : GroupRoomUiState // 실패 +} + +@HiltViewModel +class GroupRoomViewModel @Inject constructor( + private val roomsRepository: RoomsRepository +) : ViewModel() { + private val _uiState = MutableStateFlow(GroupRoomUiState.Loading) + val uiState = _uiState.asStateFlow() + + fun fetchRoomsPlaying(roomId: Int) { + // ViewModel의 생명주기와 연결된 코루틴 스코프에서 실행 + viewModelScope.launch { + _uiState.value = GroupRoomUiState.Loading + + roomsRepository.getRoomsPlaying(roomId = roomId) + .onSuccess { roomsPlaying -> + if (roomsPlaying != null) { + _uiState.value = GroupRoomUiState.Success(roomsPlaying) + } + } + .onFailure { throwable -> + _uiState.value = GroupRoomUiState.Error( + throwable.message ?: "알 수 없는 오류가 발생했습니다." + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/mypage/component/RoleCard.kt b/app/src/main/java/com/texthip/thip/ui/mypage/component/RoleCard.kt index 4779eb62..5e1ea662 100644 --- a/app/src/main/java/com/texthip/thip/ui/mypage/component/RoleCard.kt +++ b/app/src/main/java/com/texthip/thip/ui/mypage/component/RoleCard.kt @@ -32,7 +32,7 @@ import androidx.compose.ui.unit.dp import com.texthip.thip.R import com.texthip.thip.ui.theme.DarkGrey import com.texthip.thip.ui.theme.NeonGreen -import com.texthip.thip.ui.theme.Pink +import com.texthip.thip.ui.theme.Art import com.texthip.thip.ui.theme.ThipTheme import com.texthip.thip.ui.theme.ThipTheme.colors import com.texthip.thip.ui.theme.ThipTheme.typography @@ -125,7 +125,7 @@ fun RoleCardPreview() { role = "예술가", imageResId = R.drawable.character_art, genreColor = White, - roleColor = Pink, + roleColor = Art, selected = selected2, onClick = { selected2 = !selected2 } ) diff --git a/app/src/main/java/com/texthip/thip/ui/mypage/component/SavedFeedCard.kt b/app/src/main/java/com/texthip/thip/ui/mypage/component/SavedFeedCard.kt index 21324213..fbda07d5 100644 --- a/app/src/main/java/com/texthip/thip/ui/mypage/component/SavedFeedCard.kt +++ b/app/src/main/java/com/texthip/thip/ui/mypage/component/SavedFeedCard.kt @@ -50,7 +50,7 @@ fun SavedFeedCard( .padding(20.dp) ) { ProfileBar( - profileImage = profileImage, + profileImage = "https://example.com/image1.jpg", topText = feedItem.userName, bottomText = feedItem.userRole, showSubscriberInfo = false, diff --git a/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageEditScreen.kt b/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageEditScreen.kt index df9c0228..e4d5b5d6 100644 --- a/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageEditScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageEditScreen.kt @@ -38,31 +38,31 @@ fun EditProfileScreen() { stringResource(R.string.literature), stringResource(R.string.literary_person), R.drawable.character_literature, - colors.NeonGreen + colors.Literature ), RoleItem( stringResource(R.string.science_it), stringResource(R.string.scientist), R.drawable.character_science, - colors.Lavendar + colors.ScienceIt ), RoleItem( stringResource(R.string.social_science), stringResource(R.string.sociologist), R.drawable.character_sociology, - colors.Orange + colors.SocialScience ), RoleItem( stringResource(R.string.art), stringResource(R.string.artist), R.drawable.character_art, - colors.Pink + colors.Art ), RoleItem( stringResource(R.string.humanities), stringResource(R.string.philosopher), R.drawable.character_humanities, - colors.Skyblue + colors.Humanities ) ) Column( diff --git a/app/src/main/java/com/texthip/thip/ui/navigator/extensions/GroupNavigationExtensions.kt b/app/src/main/java/com/texthip/thip/ui/navigator/extensions/GroupNavigationExtensions.kt index 48fc3ddb..2a6151ca 100644 --- a/app/src/main/java/com/texthip/thip/ui/navigator/extensions/GroupNavigationExtensions.kt +++ b/app/src/main/java/com/texthip/thip/ui/navigator/extensions/GroupNavigationExtensions.kt @@ -55,4 +55,7 @@ fun NavHostController.navigateToGroupRoom(roomId: Int) { navigate(GroupRoutes.Room(roomId)) } - +// 독서메이트 화면으로 이동 +fun NavHostController.navigateToGroupRoomMates(roomId: Int) { + navigate(GroupRoutes.RoomMates(roomId)) +} diff --git a/app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt b/app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt index 0c8adce7..e6693f61 100644 --- a/app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt +++ b/app/src/main/java/com/texthip/thip/ui/navigator/navigations/GroupNavigation.kt @@ -12,25 +12,27 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.NavHostController import androidx.navigation.compose.composable import androidx.navigation.toRoute -import com.texthip.thip.ui.group.viewmodel.GroupViewModel import com.texthip.thip.ui.group.makeroom.screen.GroupMakeRoomScreen import com.texthip.thip.ui.group.makeroom.viewmodel.GroupMakeRoomViewModel import com.texthip.thip.ui.group.myroom.mock.GroupBottomButtonType import com.texthip.thip.ui.group.myroom.mock.GroupRoomData import com.texthip.thip.ui.group.myroom.screen.GroupMyScreen +import com.texthip.thip.ui.group.room.screen.GroupRoomMatesScreen import com.texthip.thip.ui.group.room.screen.GroupRoomRecruitScreen import com.texthip.thip.ui.group.room.screen.GroupRoomScreen import com.texthip.thip.ui.group.screen.GroupDoneScreen import com.texthip.thip.ui.group.screen.GroupScreen import com.texthip.thip.ui.group.search.screen.GroupSearchScreen +import com.texthip.thip.ui.group.viewmodel.GroupViewModel import com.texthip.thip.ui.navigator.extensions.navigateToAlarm import com.texthip.thip.ui.navigator.extensions.navigateToGroupDone import com.texthip.thip.ui.navigator.extensions.navigateToGroupMakeRoom import com.texthip.thip.ui.navigator.extensions.navigateToGroupMy import com.texthip.thip.ui.navigator.extensions.navigateToGroupRecruit -import com.texthip.thip.ui.navigator.extensions.navigateToRecommendedGroupRecruit import com.texthip.thip.ui.navigator.extensions.navigateToGroupRoom +import com.texthip.thip.ui.navigator.extensions.navigateToGroupRoomMates import com.texthip.thip.ui.navigator.extensions.navigateToGroupSearch +import com.texthip.thip.ui.navigator.extensions.navigateToRecommendedGroupRecruit import com.texthip.thip.ui.navigator.routes.GroupRoutes import com.texthip.thip.ui.navigator.routes.MainTabRoutes @@ -226,6 +228,7 @@ fun NavGraphBuilder.groupNavigation( composable { backStackEntry -> val route = backStackEntry.toRoute() val roomId = route.roomId + val parentEntry = remember(navController) { try { navController.getBackStackEntry(MainTabRoutes.Group) @@ -238,21 +241,33 @@ fun NavGraphBuilder.groupNavigation( } else { viewModel() } - - // suspend 함수를 위한 LaunchedEffect 사용 - var roomDetail by remember { mutableStateOf(null) } - LaunchedEffect(roomId) { - roomDetail = groupViewModel.getRoomDetail(roomId) - } - - roomDetail?.let { - GroupRoomScreen( - onBackClick = { - navigateBack() - } - ) - } ?: run { - // 로딩 중이거나 데이터를 찾을 수 없는 경우 - } + + GroupRoomScreen( +// roomId = roomId, + roomId = 1, + onBackClick = { + navigateBack() + }, + onNavigateToMates = { + navController.navigateToGroupRoomMates(roomId) + }, + ) + } + + // Group Room Mates 화면 + composable { backStackEntry -> + val route = backStackEntry.toRoute() + val roomId = route.roomId + + GroupRoomMatesScreen( +// roomId = roomId, + roomId = 1, + onBackClick = { + navigateBack() + }, + onUserClick = { + // 네비게이션 로직 (예: 유저 프로필로 이동) + } + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/navigator/routes/GroupRoutes.kt b/app/src/main/java/com/texthip/thip/ui/navigator/routes/GroupRoutes.kt index 7c327d3c..533bf084 100644 --- a/app/src/main/java/com/texthip/thip/ui/navigator/routes/GroupRoutes.kt +++ b/app/src/main/java/com/texthip/thip/ui/navigator/routes/GroupRoutes.kt @@ -21,4 +21,7 @@ sealed class GroupRoutes : Routes() { @Serializable data class Room(val roomId: Int) : GroupRoutes() + + @Serializable + data class RoomMates(val roomId: Int) : GroupRoutes() } \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/ui/signin/screen/SignupGenreScreen.kt b/app/src/main/java/com/texthip/thip/ui/signin/screen/SignupGenreScreen.kt index 7b1233bf..26efed99 100644 --- a/app/src/main/java/com/texthip/thip/ui/signin/screen/SignupGenreScreen.kt +++ b/app/src/main/java/com/texthip/thip/ui/signin/screen/SignupGenreScreen.kt @@ -40,31 +40,31 @@ fun SignupGenreScreen() { stringResource(R.string.literature), stringResource(R.string.literary_person), R.drawable.character_literature, - colors.NeonGreen + colors.Literature ), RoleItem( stringResource(R.string.science_it), stringResource(R.string.scientist), R.drawable.character_science, - colors.Lavendar + colors.ScienceIt ), RoleItem( stringResource(R.string.social_science), stringResource(R.string.sociologist), R.drawable.character_sociology, - colors.Orange + colors.SocialScience ), RoleItem( stringResource(R.string.art), stringResource(R.string.artist), R.drawable.character_art, - colors.Pink + colors.Art ), RoleItem( stringResource(R.string.humanities), stringResource(R.string.philosopher), R.drawable.character_humanities, - colors.Skyblue + colors.Humanities ) ) diff --git a/app/src/main/java/com/texthip/thip/ui/theme/Color.kt b/app/src/main/java/com/texthip/thip/ui/theme/Color.kt index 1fe1ebe9..89d77798 100644 --- a/app/src/main/java/com/texthip/thip/ui/theme/Color.kt +++ b/app/src/main/java/com/texthip/thip/ui/theme/Color.kt @@ -13,16 +13,16 @@ val NeonGreen50 = Color(0x80A7FFB4) val Red = Color(0xFFFF9496) -val Mint = Color(0xFFA0F8E8) -val MintSub = Color(0xFF4FD9C0) -val Orange = Color(0xFFFDB770) -val OrangeSub = Color(0xFFFF8B17) -val genreColor = Color(0xFFB5B35D) -val Skyblue = Color(0xFFA1D5FF) -val SkyblueSub = Color(0xFF6DB5EE) -val Pink = Color(0xFFFF8BAC) -val Lavendar = Color(0xFFC8A5FF) -val LavendaSub = Color(0xFFA76FFF) +val Literature = Color(0xFFA0F8E8) +val LiteratureSub = Color(0xFF4FD9C0) +val SocialScience = Color(0xFFFDB770) +val SocialScienceSub = Color(0xFFFF8B17) +val Humanities = Color(0xFFA1D5FF) +val HumanitiesSub = Color(0xFF6DB5EE) +val Art = Color(0xFFFF8BAC) +val ArtSub = Color(0xFFFB5A88) +val ScienceIt = Color(0xFFC8A5FF) +val ScienceItSub = Color(0xFFA76FFF) val Yellow = Color(0xFFFFECA7) val KakaoYellow = Color(0xFFFEE500) @@ -56,16 +56,16 @@ data class ThipColors( val NeonGreen: Color, val NeonGreen50: Color, val Red: Color, - val Mint: Color, - val MintSub: Color, - val Orange: Color, - val OrangeSub: Color, - val genreColor: Color, - val Skyblue: Color, - val SkyblueSub: Color, - val Pink: Color, - val Lavendar: Color, - val LavendaSub: Color, + val Literature: Color, + val LiteratureSub: Color, + val SocialScience: Color, + val SocialScienceSub: Color, + val Humanities: Color, + val HumanitiesSub: Color, + val Art: Color, + val ArtSub: Color, + val ScienceIt: Color, + val ScienceItSub: Color, val Yellow: Color, val KakaoYellow: Color, val PureWhite: Color, @@ -95,16 +95,16 @@ val defaultThipColors = ThipColors( NeonGreen = NeonGreen, NeonGreen50 = NeonGreen50, Red = Red, - Mint = Mint, - MintSub = MintSub, - Orange = Orange, - OrangeSub = OrangeSub, - genreColor = genreColor, - Skyblue = Skyblue, - SkyblueSub = SkyblueSub, - Pink = Pink, - Lavendar = Lavendar, - LavendaSub = LavendaSub, + Literature = Literature, + LiteratureSub = LiteratureSub, + SocialScience = SocialScience, + SocialScienceSub = SocialScienceSub, + Humanities = Humanities, + HumanitiesSub = HumanitiesSub, + Art = Art, + ArtSub = ArtSub, + ScienceIt = ScienceIt, + ScienceItSub = ScienceItSub, Yellow = Yellow, KakaoYellow = KakaoYellow, PureWhite = PureWhite, diff --git a/app/src/main/java/com/texthip/thip/utils/type/GenreBackgroundImage.kt b/app/src/main/java/com/texthip/thip/utils/type/GenreBackgroundImage.kt new file mode 100644 index 00000000..2ffc9501 --- /dev/null +++ b/app/src/main/java/com/texthip/thip/utils/type/GenreBackgroundImage.kt @@ -0,0 +1,22 @@ +package com.texthip.thip.utils.type + +import androidx.annotation.DrawableRes +import com.texthip.thip.R + +enum class GenreBackgroundImage( + val genreName: String, + @DrawableRes val imageResId: Int +) { + LITERATURE("문학", R.drawable.img_literature), + HUMANITIES("인문학", R.drawable.img_humanities), + SCIENCE("과학•IT", R.drawable.img_science_it), + SOCIAL_SCIENCE("사회과학", R.drawable.img_social_science), + ART("예술", R.drawable.img_art); + + companion object { + fun fromServerValue(serverValue: String?): GenreBackgroundImage { + val genreNameFromServer = serverValue?.substringBefore("_") ?: return GenreBackgroundImage.LITERATURE + return entries.find { it.genreName == genreNameFromServer } ?: GenreBackgroundImage.LITERATURE + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/texthip/thip/utils/type/GenreColor.kt b/app/src/main/java/com/texthip/thip/utils/type/GenreColor.kt new file mode 100644 index 00000000..fa97df0e --- /dev/null +++ b/app/src/main/java/com/texthip/thip/utils/type/GenreColor.kt @@ -0,0 +1,23 @@ +package com.texthip.thip.utils.type + +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color +import com.texthip.thip.ui.theme.ThipTheme.colors + +enum class GenreColor( + val colorProvider: @Composable () -> Color +) { + RED({ colors.Art }), + BLUE({ colors.Humanities }), + GREEN({ colors.Literature }), + YELLOW({ colors.SocialScience }), + PURPLE({ colors.ScienceIt }); + + + companion object { + fun fromString(colorString: String?): GenreColor { + return entries.find { it.name.equals(colorString, ignoreCase = true) } + ?: RED + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/img_art.png b/app/src/main/res/drawable/img_art.png new file mode 100644 index 00000000..0a800ce2 Binary files /dev/null and b/app/src/main/res/drawable/img_art.png differ diff --git a/app/src/main/res/drawable/img_humanities.png b/app/src/main/res/drawable/img_humanities.png new file mode 100644 index 00000000..a05474b7 Binary files /dev/null and b/app/src/main/res/drawable/img_humanities.png differ diff --git a/app/src/main/res/drawable/img_literature.png b/app/src/main/res/drawable/img_literature.png new file mode 100644 index 00000000..93f18ebe Binary files /dev/null and b/app/src/main/res/drawable/img_literature.png differ diff --git a/app/src/main/res/drawable/img_science_it.png b/app/src/main/res/drawable/img_science_it.png new file mode 100644 index 00000000..611822f0 Binary files /dev/null and b/app/src/main/res/drawable/img_science_it.png differ diff --git a/app/src/main/res/drawable/img_social_science.png b/app/src/main/res/drawable/img_social_science.png new file mode 100644 index 00000000..1608038d Binary files /dev/null and b/app/src/main/res/drawable/img_social_science.png differ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4f70ba19..33dcceb3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -176,6 +176,7 @@ 신고하기 아직 대화가 없어요 첫번째 한마디를 남겨보세요! + %d. %s ~