diff --git a/data/src/main/java/com/terning/data/dto/response/InternResponseDto.kt b/data/src/main/java/com/terning/data/dto/response/InternResponseDto.kt index 542c29130..3be4e1979 100644 --- a/data/src/main/java/com/terning/data/dto/response/InternResponseDto.kt +++ b/data/src/main/java/com/terning/data/dto/response/InternResponseDto.kt @@ -13,8 +13,8 @@ data class InternResponseDto( val deadline: String, @SerialName("workingPeriod") val workingPeriod: String, - @SerialName("startDate") - val startDate: String, + @SerialName("startYearMonth") + val startYearMonth: String, @SerialName("scrapCount") val scrapCount: Int, @SerialName("viewCount") @@ -33,6 +33,8 @@ data class InternResponseDto( val detail: String, @SerialName("url") val url: String, - @SerialName("scrapId") - val scrapId: Long? = null, + @SerialName("isScrapped") + val isScrapped: Boolean, + @SerialName("color") + val color: String? = null, ) \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/mapper/intern/InternInfoMapper.kt b/data/src/main/java/com/terning/data/mapper/intern/InternInfoMapper.kt index 7e3e8c1e0..9084268eb 100644 --- a/data/src/main/java/com/terning/data/mapper/intern/InternInfoMapper.kt +++ b/data/src/main/java/com/terning/data/mapper/intern/InternInfoMapper.kt @@ -9,7 +9,7 @@ fun InternResponseDto.toInternInfo(): InternInfo = title = title, deadline = deadline, workingPeriod = workingPeriod, - startDate = startDate, + startYearMonth = startYearMonth, scrapCount = scrapCount, viewCount = viewCount, company = company, @@ -19,5 +19,6 @@ fun InternResponseDto.toInternInfo(): InternInfo = jobType = jobType, detail = detail, url = url, - scrapId = scrapId + isScrapped = isScrapped, + color = color, ) \ No newline at end of file diff --git a/domain/src/main/java/com/terning/domain/entity/intern/InternInfo.kt b/domain/src/main/java/com/terning/domain/entity/intern/InternInfo.kt index 77e70f12c..382db6d52 100644 --- a/domain/src/main/java/com/terning/domain/entity/intern/InternInfo.kt +++ b/domain/src/main/java/com/terning/domain/entity/intern/InternInfo.kt @@ -5,7 +5,7 @@ data class InternInfo( val title: String, val deadline: String, val workingPeriod: String, - val startDate: String, + val startYearMonth: String, val scrapCount: Int, val viewCount: Int, val company: String, @@ -15,5 +15,6 @@ data class InternInfo( val jobType: String, val detail: String, val url: String, - val scrapId: Long? = null, + val isScrapped: Boolean, + val color: String? = null, ) \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/intern/InternRoute.kt b/feature/src/main/java/com/terning/feature/intern/InternRoute.kt index ef02c79ed..5dec1e4fc 100644 --- a/feature/src/main/java/com/terning/feature/intern/InternRoute.kt +++ b/feature/src/main/java/com/terning/feature/intern/InternRoute.kt @@ -1,11 +1,13 @@ package com.terning.feature.intern -import android.view.ViewGroup -import android.webkit.WebView +import androidx.browser.customtabs.CustomTabsIntent +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.material3.Text @@ -16,7 +18,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.compose.ui.viewinterop.AndroidView +import androidx.core.net.toUri import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -27,6 +29,7 @@ import com.terning.core.designsystem.theme.CalRed import com.terning.core.designsystem.theme.Grey200 import com.terning.core.designsystem.theme.Grey400 import com.terning.core.designsystem.theme.TerningTheme +import com.terning.core.designsystem.theme.White import com.terning.core.extension.customShadow import com.terning.core.extension.toast import com.terning.core.state.UiState @@ -45,14 +48,12 @@ import java.text.DecimalFormat @Composable fun InternRoute( announcementId: Long = 0, - modifier: Modifier, viewModel: InternViewModel = hiltViewModel(), navController: NavHostController, ) { - val internState by viewModel.internUiState.collectAsStateWithLifecycle() - val context = LocalContext.current val lifecycleOwner = LocalLifecycleOwner.current + val internState by viewModel.internUiState.collectAsStateWithLifecycle(lifecycleOwner) LaunchedEffect(key1 = true) { viewModel.getInternInfo(announcementId) @@ -75,21 +76,25 @@ fun InternRoute( InternScreen( announcementId = announcementId, internUiState = internState, - modifier = modifier, internInfo = (internState.loadState as UiState.Success).data, navController = navController, onDismissCancelDialog = { - viewModel.updateScrapCancelDialogVisibility(false) + with(viewModel) { + updateScrapCancelDialogVisibility(false) + getInternInfo(announcementId) + } + }, + onDismissScrapDialog = { + with(viewModel) { + updateInternDialogVisibility(false) + getInternInfo(announcementId) + } }, - onDismissScrapDialog = { viewModel.updateInternDialogVisibility(false) }, onClickCancelButton = { viewModel.updateScrapCancelDialogVisibility(true) }, onClickScrapButton = { - with(viewModel) { - updateInternshipModel(it) - updateInternDialogVisibility(true) - } + viewModel.updateInternDialogVisibility(true) } ) } @@ -108,12 +113,14 @@ fun InternScreen( onClickCancelButton: (InternInfo) -> Unit, onClickScrapButton: (InternInfo) -> Unit, ) { + val context = LocalContext.current + val decimal = DecimalFormat("#,###") val internInfoList = listOf( stringResource(id = R.string.intern_info_d_day) to internInfo.deadline, stringResource(id = R.string.intern_info_working) to internInfo.workingPeriod, - stringResource(id = R.string.intern_info_start_date) to internInfo.startDate, + stringResource(id = R.string.intern_info_start_date) to internInfo.startYearMonth, ) val qualificationList = listOf( @@ -121,22 +128,18 @@ fun InternScreen( stringResource(id = R.string.intern_info_work) to internInfo.jobType, ) - if (internUiState.showWeb) { - AndroidView( - factory = { - WebView(it).apply { - layoutParams = ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT, - ) - loadUrl(internInfo.url) - } - }, - ) + LaunchedEffect(internUiState.showWeb) { + if (internUiState.showWeb) { + CustomTabsIntent.Builder().build().launchUrl(context, internInfo.url.toUri()) + } } Column( - modifier = modifier.fillMaxHeight(), + modifier = modifier + .statusBarsPadding() + .navigationBarsPadding() + .fillMaxHeight() + .background(White), ) { Column( modifier = Modifier.weight(1f) @@ -200,7 +203,7 @@ fun InternScreen( } } - Spacer(modifier = Modifier.padding(top = 16.dp)) + Spacer(modifier = Modifier.padding(top = 13.dp)) InternPageTitle( modifier = Modifier, @@ -219,7 +222,7 @@ fun InternScreen( } } - Spacer(modifier = Modifier.padding(top = 16.dp)) + Spacer(modifier = Modifier.padding(top = 13.dp)) InternPageTitle( modifier = Modifier, @@ -250,14 +253,15 @@ fun InternScreen( modifier = Modifier, internInfo = internInfo, onScrapClick = { - if (!internUiState.isScrappedState) + if (internInfo.isScrapped) { + onClickCancelButton(internInfo) + } else { onClickScrapButton(internInfo) - else onClickCancelButton(internInfo) + } }, ) - - if (internUiState.scrapDialogVisibility) { + if (internUiState.scrapCancelDialogVisibility) { ScrapCancelDialog( internshipAnnouncementId = announcementId, onDismissRequest = onDismissCancelDialog @@ -265,21 +269,19 @@ fun InternScreen( } if (internUiState.internDialogVisibility) { - internUiState.internshipModel?.let { - ScrapDialog( - title = internUiState.internshipModel.title, - scrapColor = CalRed, - deadline = internUiState.internshipModel.deadline, - startYearMonth = internUiState.internshipModel.startDate, - workingPeriod = internUiState.internshipModel.workingPeriod, - internshipAnnouncementId = announcementId, - companyImage = internUiState.internshipModel.companyImage, - isScrapped = false, - onDismissRequest = onDismissScrapDialog, - onClickChangeColor = { }, - onClickNavigateButton = { } - ) - } + ScrapDialog( + title = internInfo.title, + scrapColor = CalRed, + deadline = internInfo.deadline, + startYearMonth = internInfo.startYearMonth, + workingPeriod = internInfo.workingPeriod, + internshipAnnouncementId = announcementId, + companyImage = internInfo.companyImage, + isScrapped = internInfo.isScrapped, + onDismissRequest = onDismissScrapDialog, + onClickChangeColor = { }, + onClickNavigateButton = { } + ) } } } \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/intern/InternViewModel.kt b/feature/src/main/java/com/terning/feature/intern/InternViewModel.kt index 03c8b5b60..e1f955247 100644 --- a/feature/src/main/java/com/terning/feature/intern/InternViewModel.kt +++ b/feature/src/main/java/com/terning/feature/intern/InternViewModel.kt @@ -3,7 +3,6 @@ package com.terning.feature.intern import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.terning.core.state.UiState -import com.terning.domain.entity.calendar.CalendarScrapDetail import com.terning.domain.entity.intern.InternInfo import com.terning.domain.repository.InternRepository import com.terning.feature.R @@ -32,36 +31,39 @@ class InternViewModel @Inject constructor( viewModelScope.launch { internRepository.getInternInfo(id) .onSuccess { internInfoModel -> - _internUiState.update { currentState -> - currentState.copy(loadState = UiState.Success(internInfoModel)) - } + _internUiState.value = _internUiState.value.copy( + loadState = UiState.Success(internInfoModel) + ) } - .onFailure { + .onFailure { exception: Throwable -> + _internUiState.value = _internUiState.value.copy( + loadState = UiState.Failure(exception.toString()) + ) _sideEffect.emit(InternViewSideEffect.Toast(R.string.server_failure)) } } } - fun updateInternshipModel(scrapDetailModel: InternInfo?) { + fun updateScrapCancelDialogVisibility(visibility: Boolean) { _internUiState.update { currentState -> currentState.copy( - internshipModel = scrapDetailModel + scrapCancelDialogVisibility = visibility, ) } } - fun updateScrapCancelDialogVisibility(visibility: Boolean) { + fun updateInternDialogVisibility(visibility: Boolean) { _internUiState.update { currentState -> currentState.copy( - scrapDialogVisibility = visibility + internDialogVisibility = visibility ) } } - fun updateInternDialogVisibility(visibility: Boolean) { + fun updateInternshipModel(scrapDetailModel: InternInfo?) { _internUiState.update { currentState -> currentState.copy( - internDialogVisibility = visibility + internshipModel = scrapDetailModel ) } } @@ -71,4 +73,4 @@ class InternViewModel @Inject constructor( it.copy(showWeb = show) } } -} \ No newline at end of file +} diff --git a/feature/src/main/java/com/terning/feature/intern/component/InternBottomBar.kt b/feature/src/main/java/com/terning/feature/intern/component/InternBottomBar.kt index 46e7dc7c0..bf5b2f1bf 100644 --- a/feature/src/main/java/com/terning/feature/intern/component/InternBottomBar.kt +++ b/feature/src/main/java/com/terning/feature/intern/component/InternBottomBar.kt @@ -27,6 +27,7 @@ import com.terning.core.extension.noRippleClickable import com.terning.domain.entity.intern.InternInfo import com.terning.feature.R import com.terning.feature.intern.InternViewModel +import com.terning.feature.intern.model.InternUiState @Composable fun InternBottomBar( @@ -35,7 +36,6 @@ fun InternBottomBar( onScrapClick: (InternInfo) -> Unit, viewModel: InternViewModel = hiltViewModel(), ) { - Row( modifier = modifier .fillMaxWidth() @@ -63,20 +63,19 @@ fun InternBottomBar( ) { Icon( painter = painterResource( - id = - if (internInfo.scrapId != null) R.drawable.ic_scrap_true_24 - else R.drawable.ic_scrap_false_24, + id = if (internInfo.isScrapped) { + R.drawable.ic_scrap_true_24 + } else { + R.drawable.ic_scrap_false_24 + } ), contentDescription = null, modifier = modifier - .padding( - bottom = 6.dp - ) + .padding(bottom = 6.dp) .noRippleClickable { onScrapClick(internInfo) }, - tint = if (internInfo.scrapId != null) TerningMain - else Grey350 + tint = if (internInfo.isScrapped) TerningMain else Grey350 ) Text( text = stringResource( @@ -99,4 +98,4 @@ fun InternBottomBar( } } } -} \ No newline at end of file +} diff --git a/feature/src/main/java/com/terning/feature/intern/component/InternInfoRow.kt b/feature/src/main/java/com/terning/feature/intern/component/InternInfoRow.kt index 756b4c097..7b67986be 100644 --- a/feature/src/main/java/com/terning/feature/intern/component/InternInfoRow.kt +++ b/feature/src/main/java/com/terning/feature/intern/component/InternInfoRow.kt @@ -2,9 +2,11 @@ package com.terning.feature.intern.component import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.terning.core.designsystem.theme.Grey400 import com.terning.core.designsystem.theme.Grey500 @@ -13,6 +15,7 @@ import com.terning.core.designsystem.theme.TerningTheme @Composable fun InternInfoRow(title: String, value: String) { Row( + modifier = Modifier.padding(bottom = 3.dp), horizontalArrangement = Arrangement.spacedBy(23.dp, Alignment.Start), verticalAlignment = Alignment.Top, ) { diff --git a/feature/src/main/java/com/terning/feature/intern/model/InternUiState.kt b/feature/src/main/java/com/terning/feature/intern/model/InternUiState.kt index adc01874f..0adb2c489 100644 --- a/feature/src/main/java/com/terning/feature/intern/model/InternUiState.kt +++ b/feature/src/main/java/com/terning/feature/intern/model/InternUiState.kt @@ -9,10 +9,9 @@ data class InternUiState( val loadState: UiState = UiState.Loading, val isColorChange: Boolean = false, val selectedColor: Color = CalRed, - val scrapDialogVisibility: Boolean = false, + val scrapCancelDialogVisibility: Boolean = false, val internDialogVisibility: Boolean = false, val isScrappedState: Boolean = false, val showWeb: Boolean = false, - val scrapId: Long? = null, val internshipModel: InternInfo? = null, ) \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/intern/navigation/InternNavigation.kt b/feature/src/main/java/com/terning/feature/intern/navigation/InternNavigation.kt index 7af39f4c0..7bc5c14c3 100644 --- a/feature/src/main/java/com/terning/feature/intern/navigation/InternNavigation.kt +++ b/feature/src/main/java/com/terning/feature/intern/navigation/InternNavigation.kt @@ -2,9 +2,6 @@ package com.terning.feature.intern.navigation import androidx.compose.animation.EnterTransition import androidx.compose.animation.ExitTransition -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.padding -import androidx.compose.ui.Modifier import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavHostController @@ -27,7 +24,6 @@ fun NavController.navigateIntern( fun NavGraphBuilder.internNavGraph( navHostController: NavHostController, - paddingValues: PaddingValues, ) { composable( exitTransition = { @@ -46,7 +42,6 @@ fun NavGraphBuilder.internNavGraph( val args = it.toRoute() InternRoute( announcementId = args.announcementId, - modifier = Modifier.padding(paddingValues), navController = navHostController ) } diff --git a/feature/src/main/java/com/terning/feature/main/MainScreen.kt b/feature/src/main/java/com/terning/feature/main/MainScreen.kt index ce270cd8e..585768eed 100644 --- a/feature/src/main/java/com/terning/feature/main/MainScreen.kt +++ b/feature/src/main/java/com/terning/feature/main/MainScreen.kt @@ -168,7 +168,6 @@ fun MainScreen( navHostController = navigator.navController ) internNavGraph( - paddingValues = paddingValues, navHostController = navigator.navController ) myPageNavGraph( diff --git a/feature/src/main/java/com/terning/feature/search/search/SearchRoute.kt b/feature/src/main/java/com/terning/feature/search/search/SearchRoute.kt index 1088e226c..84454cd82 100644 --- a/feature/src/main/java/com/terning/feature/search/search/SearchRoute.kt +++ b/feature/src/main/java/com/terning/feature/search/search/SearchRoute.kt @@ -1,5 +1,6 @@ package com.terning.feature.search.search +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -22,6 +23,7 @@ import com.terning.core.designsystem.component.image.TerningImage import com.terning.core.designsystem.component.textfield.SearchTextField import com.terning.core.designsystem.theme.Black import com.terning.core.designsystem.theme.TerningTheme +import com.terning.core.designsystem.theme.White import com.terning.core.extension.noRippleClickable import com.terning.core.state.UiState import com.terning.domain.entity.search.SearchPopularAnnouncement @@ -96,6 +98,7 @@ fun SearchScreen( Column( modifier = modifier .fillMaxSize() + .background(White) ) { TerningImage( painter = com.terning.core.R.drawable.ic_terning_logo_typo, diff --git a/feature/src/main/java/com/terning/feature/search/searchprocess/SearchProcessRoute.kt b/feature/src/main/java/com/terning/feature/search/searchprocess/SearchProcessRoute.kt index 50809694c..09d4ff6b7 100644 --- a/feature/src/main/java/com/terning/feature/search/searchprocess/SearchProcessRoute.kt +++ b/feature/src/main/java/com/terning/feature/search/searchprocess/SearchProcessRoute.kt @@ -1,6 +1,7 @@ package com.terning.feature.search.searchprocess import androidx.compose.foundation.Image +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues @@ -47,6 +48,7 @@ import com.terning.core.designsystem.theme.Grey500 import com.terning.core.designsystem.theme.TerningMain import com.terning.core.designsystem.theme.TerningPointTheme import com.terning.core.designsystem.theme.TerningTheme +import com.terning.core.designsystem.theme.White import com.terning.core.extension.addFocusCleaner import com.terning.core.extension.noRippleClickable import com.terning.core.extension.toast @@ -138,6 +140,7 @@ fun SearchProcessScreen( Column( modifier = modifier .fillMaxSize() + .background(White) .addFocusCleaner(focusManager), ) { BackButtonTopAppBar(