Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[UI#146] 홈 뷰 / 다이얼로그 구현 #153

Merged
merged 5 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ fun InternItemWithShadow(
dateDeadline: String,
workingPeriod: String,
isScrapped: Boolean,
onScrapButtonClicked: (Long) -> Unit = {}
) {
Box(
modifier = modifier
Expand All @@ -40,7 +41,8 @@ fun InternItemWithShadow(
title = title,
dateDeadline = dateDeadline,
workingPeriod = workingPeriod,
isScraped = isScrapped
isScraped = isScrapped,
onScrapButtonClicked = onScrapButtonClicked
)
}
}
1 change: 1 addition & 0 deletions core/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
<string name="dialog_scrap_cancel_button">스크랩 취소하기</string>
<string name="dialog_scrap_mine">내가 스크랩한 관심 공고에요!</string>
<string name="dialog_scrap_move_to_intern">공고 상세 정보 보러가기</string>
<string name="dialog_today_deadline">오늘 마감되는 공고예요!</string>

<!--Intern-->
<string name="intern_info_d_day">서류 마감</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,34 @@ import kotlinx.serialization.Serializable

@Serializable
data class HomeRecommendInternResponseDto(
@SerialName("scrapId")
val scrapId: Long?,
@SerialName("intershipAnnouncementId")
val internshipAnnouncementId: Long,
@SerialName("title")
val title: String,
@SerialName("dDay")
val dDay: String,
@SerialName("deadline")
val deadline: String,
@SerialName("workingPeriod")
val workingPeriod: String,
@SerialName("startYearMonth")
val startYearMonth: String,
@SerialName("companyImage")
val companyImage: String,
@SerialName("isScrapped")
val isScrapped: Boolean,
) {
fun toRecommendInternEntity(): HomeRecommendInternModel =
HomeRecommendInternModel(
scrapId = this.scrapId,
internshipAnnouncementId = this.internshipAnnouncementId,
title = this.title,
dDay = this.dDay,
deadline = deadline,
workingPeriod = this.workingPeriod,
startYearMonth = this.startYearMonth,
companyImage = this.companyImage,
isScrapped = this.isScrapped,
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.terning.domain.entity.response

data class HomeRecommendInternModel(
val scrapId: Long?,
val internshipAnnouncementId: Long,
val title: String,
val dDay: String,
val deadline: String,
val workingPeriod: String,
val startYearMonth: String,
val companyImage: String,
val isScrapped: Boolean,
)
85 changes: 80 additions & 5 deletions feature/src/main/java/com/terning/feature/home/home/HomeRoute.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import androidx.navigation.NavHostController
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.terning.core.designsystem.component.bottomsheet.SortingBottomSheet
import com.terning.core.designsystem.component.button.SortingButton
import com.terning.core.designsystem.component.dialog.ScrapCancelDialogContent
import com.terning.core.designsystem.component.dialog.TerningBasicDialog
import com.terning.core.designsystem.component.item.InternItemWithShadow
import com.terning.core.designsystem.component.topappbar.LogoTopAppBar
import com.terning.core.designsystem.theme.Black
Expand All @@ -52,8 +54,10 @@ import com.terning.feature.home.changefilter.navigation.navigateChangeFilter
import com.terning.feature.home.home.component.HomeFilteringEmptyIntern
import com.terning.feature.home.home.component.HomeFilteringScreen
import com.terning.feature.home.home.component.HomeRecommendEmptyIntern
import com.terning.feature.home.home.component.HomeRecommendInternDialog
import com.terning.feature.home.home.component.HomeTodayEmptyWithImg
import com.terning.feature.home.home.component.HomeTodayIntern
import com.terning.feature.home.home.model.HomeDialogState
import com.terning.feature.home.home.navigation.navigateHome
import com.terning.feature.intern.navigation.navigateIntern

Expand Down Expand Up @@ -87,6 +91,7 @@ fun HomeRoute(
val homeRecommendInternState by viewModel.homeRecommendInternState.collectAsStateWithLifecycle()
val homeFilteringState by viewModel.homeFilteringState.collectAsStateWithLifecycle()
val homeUserState by viewModel.homeUserState.collectAsStateWithLifecycle()
val homeDialogState by viewModel.homeDialogState.collectAsStateWithLifecycle()

LaunchedEffect(viewModel.homeSideEffect, lifecycleOwner) {
viewModel.homeSideEffect.flowWithLifecycle(lifecycle = lifecycleOwner.lifecycle)
Expand Down Expand Up @@ -146,6 +151,7 @@ fun HomeRoute(
homeFilteringInfo = homeFilteringInfo,
homeTodayInternList = homeTodayInternList,
recommendInternList = homeRecommendInternList,
homeDialogState = homeDialogState,
onChangeFilterClick = { navController.navigateChangeFilter() },
navController = navController
)
Expand All @@ -159,11 +165,13 @@ fun HomeScreen(
homeFilteringInfo: HomeFilteringInfoModel,
homeTodayInternList: List<HomeTodayInternModel>,
recommendInternList: List<HomeRecommendInternModel>,
homeDialogState: HomeDialogState,
onChangeFilterClick: () -> Unit,
viewModel: HomeViewModel = hiltViewModel(),
navController: NavHostController,
) {
var sheetState by remember { mutableStateOf(false) }
var scrapId by remember { mutableStateOf(-1) }

if (sheetState) {
SortingBottomSheet(
Expand Down Expand Up @@ -199,7 +207,11 @@ fun HomeScreen(
.padding(bottom = 16.dp)
) {
ShowMainTitleWithName(homeUserName)
ShowTodayIntern(homeTodayInternList = homeTodayInternList)
ShowTodayIntern(
homeTodayInternList = homeTodayInternList,
homeDialogState = homeDialogState,
navigateToDetail = { navController.navigateIntern(announcementId = it) }
)
}
}
stickyHeader {
Expand Down Expand Up @@ -239,7 +251,12 @@ fun HomeScreen(
items(recommendInternList.size) { index ->
RecommendInternItem(
navController = navController,
intern = recommendInternList[index]
intern = recommendInternList[index],
onScrapButtonClicked = {
viewModel.updateScrapDialogVisible(true)
viewModel.updateIsToday(false)
scrapId = index
}
)
}
}
Expand All @@ -256,13 +273,62 @@ fun HomeScreen(
}
}
}

if (homeDialogState.isScrapDialogVisible && !homeDialogState.isToday) {
TerningBasicDialog(
onDismissRequest = { viewModel.updateScrapDialogVisible(false) },
content = {
if (recommendInternList[scrapId].scrapId != null) {
ScrapCancelDialogContent(
onClickScrapCancel = {
viewModel.updateScrapDialogVisible(false)
viewModel.deleteScrap(
recommendInternList[scrapId].scrapId ?: -1,
)
if(homeDialogState.isScrappedState) {
viewModel.getRecommendInternsData(
currentSortBy.value,
homeFilteringInfo.startYear ?: viewModel.currentYear,
homeFilteringInfo.startMonth ?: viewModel.currentMonth,
)
viewModel.updateScrapped(false)
}
}
)
} else {
with(recommendInternList[scrapId]) {
HomeRecommendInternDialog(
internInfoList = listOf(
stringResource(id = R.string.intern_info_d_day) to deadline,
stringResource(id = R.string.intern_info_working) to workingPeriod,
stringResource(id = R.string.intern_info_start_date) to startYearMonth,
),
clickAction = {
viewModel.updateScrapDialogVisible(false)
if(homeDialogState.isScrappedState) {
viewModel.getRecommendInternsData(
currentSortBy.value,
homeFilteringInfo.startYear ?: viewModel.currentYear,
homeFilteringInfo.startMonth ?: viewModel.currentMonth,
)
viewModel.updateScrapped(false)
}
},
homeRecommendInternModel = this,
)
}
}
}
)
}
}


@Composable
private fun RecommendInternItem(
navController: NavHostController,
intern: HomeRecommendInternModel,
onScrapButtonClicked: (Long) -> Unit,
) {
InternItemWithShadow(
modifier = Modifier
Expand All @@ -278,7 +344,8 @@ private fun RecommendInternItem(
workingPeriod = intern.workingPeriod,
isScrapped = intern.isScrapped,
shadowRadius = 5.dp,
shadowWidth = 1.dp
shadowWidth = 1.dp,
onScrapButtonClicked = onScrapButtonClicked,
)
}

Expand All @@ -299,11 +366,19 @@ private fun ShowMainTitleWithName(userName: String) {
}

@Composable
private fun ShowTodayIntern(homeTodayInternList: List<HomeTodayInternModel>) {
private fun ShowTodayIntern(
homeTodayInternList: List<HomeTodayInternModel>,
homeDialogState: HomeDialogState,
navigateToDetail: (Long) -> Unit,
) {
if (homeTodayInternList.isEmpty()) {
HomeTodayEmptyWithImg()
} else {
HomeTodayIntern(internList = homeTodayInternList)
HomeTodayIntern(
internList = homeTodayInternList,
homeDialogState = homeDialogState,
navigateToDetail = { navigateToDetail(it) },
)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
package com.terning.feature.home.home

import androidx.compose.ui.graphics.Color
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.terning.core.state.UiState
import com.terning.domain.entity.request.ChangeFilteringRequestModel
import com.terning.domain.entity.request.ScrapRequestModel
import com.terning.domain.entity.response.HomeFilteringInfoModel
import com.terning.domain.entity.response.HomeRecommendInternModel
import com.terning.domain.entity.response.HomeTodayInternModel
import com.terning.domain.repository.HomeRepository
import com.terning.domain.repository.MyPageRepository
import com.terning.domain.repository.ScrapRepository
import com.terning.feature.R
import com.terning.feature.home.home.model.HomeDialogState
import com.terning.feature.home.home.model.SortBy
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import java.util.Calendar
import javax.inject.Inject
Expand All @@ -24,6 +29,7 @@ import javax.inject.Inject
class HomeViewModel @Inject constructor(
private val homeRepository: HomeRepository,
private val myPageRepository: MyPageRepository,
private val scrapRepository: ScrapRepository,
) : ViewModel() {
val currentYear = Calendar.getInstance().get(Calendar.YEAR)
val currentMonth = Calendar.getInstance().get(Calendar.MONTH)
Expand All @@ -49,6 +55,10 @@ class HomeViewModel @Inject constructor(
private val _homeUserState = MutableStateFlow<UiState<String>>(UiState.Loading)
val homeUserState get() = _homeUserState.asStateFlow()

private val _homeDialogState: MutableStateFlow<HomeDialogState> =
MutableStateFlow(HomeDialogState())
val homeDialogState get() = _homeDialogState.asStateFlow()

init {
getProfile()
getFilteringInfo()
Expand Down Expand Up @@ -112,4 +122,74 @@ class HomeViewModel @Inject constructor(
}
}
}

fun postScrap(
internshipAnnouncementId: Long,
colorIndex: Int,
) {
viewModelScope.launch {
scrapRepository.postScrap(
ScrapRequestModel(
id = internshipAnnouncementId,
color = colorIndex,
)
).onSuccess {
updateScrapDialogVisible(visible = false)
updateScrapped(scrapped = true)
getHomeTodayInternList()
}.onFailure {
_homeSideEffect.emit(HomeSideEffect.ShowToast(R.string.server_failure))
}
}
}

fun deleteScrap(scrapId: Long) {
viewModelScope.launch {
scrapRepository.deleteScrap(
ScrapRequestModel(id = scrapId)
).onSuccess {
updateScrapDialogVisible(visible = false)
updateScrapped(scrapped = true)
getHomeTodayInternList()
}.onFailure {
_homeSideEffect.emit(HomeSideEffect.ShowToast(R.string.server_failure))
}
}
}

fun updateSelectColor(newColor: Color) {
_homeDialogState.update {
it.copy(selectedColor = newColor)
}
}

fun updateScrapDialogVisible(visible: Boolean) {
_homeDialogState.update {
it.copy(isScrapDialogVisible = visible)
}
}

fun updateScrapped(scrapped: Boolean) {
_homeDialogState.update {
it.copy(isScrappedState = scrapped)
}
}

fun updatePaletteOpen(open: Boolean) {
_homeDialogState.update {
it.copy(isPaletteOpen = open)
}
}

fun updateColorChange(change: Boolean) {
_homeDialogState.update {
it.copy(isColorChange = change)
}
}

fun updateIsToday(change: Boolean) {
_homeDialogState.update {
it.copy(isToday = change)
}
}
}
Loading
Loading