diff --git a/core/src/main/java/com/terning/core/designsystem/component/topappbar/CalendarTopAppBar.kt b/core/src/main/java/com/terning/core/designsystem/component/topappbar/CalendarTopAppBar.kt index dc0089100..70fdab3eb 100644 --- a/core/src/main/java/com/terning/core/designsystem/component/topappbar/CalendarTopAppBar.kt +++ b/core/src/main/java/com/terning/core/designsystem/component/topappbar/CalendarTopAppBar.kt @@ -40,10 +40,8 @@ fun CalendarTopAppBar( .fillMaxWidth() .background(color = Color.White) .padding( - top = 23.dp, - bottom = 22.dp, - start = 22.dp, - end = 22.dp + vertical = 20.dp, + horizontal = 21.dp ) ) { Row( diff --git a/core/src/main/java/com/terning/core/extension/Modifier.kt b/core/src/main/java/com/terning/core/extension/Modifier.kt index 789d198b5..86f9aa963 100644 --- a/core/src/main/java/com/terning/core/extension/Modifier.kt +++ b/core/src/main/java/com/terning/core/extension/Modifier.kt @@ -6,11 +6,15 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.composed import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.focus.FocusManager +import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Paint import androidx.compose.ui.graphics.drawscope.drawIntoCanvas @@ -88,3 +92,31 @@ fun Modifier.customShadow( } } } + +@SuppressLint("ModifierFactoryUnreferencedReceiver", "ReturnFromAwaitPointerEventScope") +fun Modifier.swipableVertically( + setHideComponent: () -> Unit +) = composed { + var initialTouchPosition by remember { mutableStateOf(null) } + pointerInput(Unit) { + awaitPointerEventScope { + while (true) { + val event = awaitPointerEvent() + val position = event.changes.first().position + + if (event.changes.first().pressed) { + if (initialTouchPosition == null) { + initialTouchPosition = position + } else { + val deltaY = initialTouchPosition?.let { position.y - it.y } + if (deltaY != null && deltaY > 300f) { + setHideComponent() + } + } + } else { + initialTouchPosition = null + } + } + } + } +} diff --git a/data/src/main/java/com/terning/data/datasource/ScrapDataSource.kt b/data/src/main/java/com/terning/data/datasource/ScrapDataSource.kt index c8ee6ff14..ecab3bd13 100644 --- a/data/src/main/java/com/terning/data/datasource/ScrapDataSource.kt +++ b/data/src/main/java/com/terning/data/datasource/ScrapDataSource.kt @@ -1,7 +1,7 @@ package com.terning.data.datasource import com.terning.data.dto.NonDataBaseResponse -import com.terning.domain.entity.CalendarScrapRequest +import com.terning.domain.entity.calendar.CalendarScrapRequest interface ScrapDataSource { suspend fun postScrap( diff --git a/data/src/main/java/com/terning/data/datasourceimpl/ScrapDataSourceImpl.kt b/data/src/main/java/com/terning/data/datasourceimpl/ScrapDataSourceImpl.kt index 46eb24351..fee3ddcc4 100644 --- a/data/src/main/java/com/terning/data/datasourceimpl/ScrapDataSourceImpl.kt +++ b/data/src/main/java/com/terning/data/datasourceimpl/ScrapDataSourceImpl.kt @@ -4,7 +4,7 @@ import com.terning.data.datasource.ScrapDataSource import com.terning.data.dto.NonDataBaseResponse import com.terning.data.dto.request.ScrapColorRequestDto import com.terning.data.service.ScrapService -import com.terning.domain.entity.CalendarScrapRequest +import com.terning.domain.entity.calendar.CalendarScrapRequest import javax.inject.Inject class ScrapDataSourceImpl @Inject constructor( diff --git a/data/src/main/java/com/terning/data/dto/response/CalendarDayListResponseDto.kt b/data/src/main/java/com/terning/data/dto/response/CalendarDayListResponseDto.kt index 3382b4863..d2e897972 100644 --- a/data/src/main/java/com/terning/data/dto/response/CalendarDayListResponseDto.kt +++ b/data/src/main/java/com/terning/data/dto/response/CalendarDayListResponseDto.kt @@ -1,27 +1,26 @@ package com.terning.data.dto.response -import com.terning.domain.entity.CalendarScrapDetail import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable data class CalendarDayListResponseDto( - @SerialName("scrapId") - val scrapId: Long, @SerialName("internshipAnnouncementId") val internshipAnnouncementId: Long, @SerialName("title") val title: String, @SerialName("dDay") val dDay: String, + @SerialName("deadline") + val deadline: String, @SerialName("workingPeriod") val workingPeriod: String, @SerialName("color") val color: String, @SerialName("companyImage") val companyImage: String, - @SerialName("startYear") - val startYear: Int, - @SerialName("startMonth") - val startMonth: Int + @SerialName("startYearMonth") + val startYearMonth: String, + @SerialName("isScrapped") + val isScrapped: Boolean ) \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/dto/response/CalendarMonthListResponseDto.kt b/data/src/main/java/com/terning/data/dto/response/CalendarMonthListResponseDto.kt index 227887e51..35c2e45aa 100644 --- a/data/src/main/java/com/terning/data/dto/response/CalendarMonthListResponseDto.kt +++ b/data/src/main/java/com/terning/data/dto/response/CalendarMonthListResponseDto.kt @@ -1,6 +1,5 @@ package com.terning.data.dto.response -import com.terning.domain.entity.CalendarScrapDetail import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -8,28 +7,28 @@ import kotlinx.serialization.Serializable data class CalendarMonthListResponseDto( @SerialName("deadline") val deadline: String, - @SerialName("scraps") - val scraps: List + @SerialName("announcements") + val announcements: List ) { @Serializable - data class Scrap( - @SerialName("scrapId") - val scrapId: Long, + data class Announcement( @SerialName("internshipAnnouncementId") val internshipAnnouncementId: Long, - @SerialName("title") - val title: String, + @SerialName("companyImage") + val companyImage: String, @SerialName("dDay") val dDay: String, + @SerialName("title") + val title: String, @SerialName("workingPeriod") val workingPeriod: String, + @SerialName("isScrapped") + val isScrapped: Boolean, @SerialName("color") val color: String, - @SerialName("companyImage") - val companyImage: String, - @SerialName("startYear") - val startYear: Int, - @SerialName("startMonth") - val startMonth: Int + @SerialName("deadline") + val deadline: String, + @SerialName("startYearMonth") + val startYearMonth: String, ) } \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/dto/response/CalendarMonthResponseDto.kt b/data/src/main/java/com/terning/data/dto/response/CalendarMonthResponseDto.kt index 35df9d9eb..fcf9b9e95 100644 --- a/data/src/main/java/com/terning/data/dto/response/CalendarMonthResponseDto.kt +++ b/data/src/main/java/com/terning/data/dto/response/CalendarMonthResponseDto.kt @@ -1,6 +1,5 @@ package com.terning.data.dto.response -import com.terning.domain.entity.CalendarScrap import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/data/src/main/java/com/terning/data/mapper/CalendarScrapDetailListMapper.kt b/data/src/main/java/com/terning/data/mapper/CalendarScrapDetailListMapper.kt index 377d0e08d..a6701e8bb 100644 --- a/data/src/main/java/com/terning/data/mapper/CalendarScrapDetailListMapper.kt +++ b/data/src/main/java/com/terning/data/mapper/CalendarScrapDetailListMapper.kt @@ -1,19 +1,18 @@ package com.terning.data.mapper import com.terning.data.dto.response.CalendarMonthListResponseDto -import com.terning.domain.entity.CalendarScrapDetail +import com.terning.domain.entity.calendar.CalendarScrapDetail -fun CalendarMonthListResponseDto.toCalendarScrapDetailList(): List = scraps.map { scrap -> +fun CalendarMonthListResponseDto.toCalendarScrapDetailList(): List = announcements.map { announcement -> CalendarScrapDetail( - scrapId = scrap.scrapId, - internshipAnnouncementId = scrap.internshipAnnouncementId, - title = scrap.title, - dDay = scrap.dDay, - workingPeriod = scrap.workingPeriod, - color = scrap.color, - companyImage = scrap.companyImage, - startYear = scrap.startYear, - startMonth = scrap.startMonth, - deadLine = deadline + internshipAnnouncementId = announcement.internshipAnnouncementId, + title = announcement.title, + dDay = announcement.dDay, + workingPeriod = announcement.workingPeriod, + color = announcement.color, + companyImage = announcement.companyImage, + startYearMonth = announcement.startYearMonth, + deadline = announcement.deadline, + isScrapped = announcement.isScrapped ) } \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/mapper/CalendarScrapDetailMapper.kt b/data/src/main/java/com/terning/data/mapper/CalendarScrapDetailMapper.kt index ee71280b0..e2280c2ce 100644 --- a/data/src/main/java/com/terning/data/mapper/CalendarScrapDetailMapper.kt +++ b/data/src/main/java/com/terning/data/mapper/CalendarScrapDetailMapper.kt @@ -1,18 +1,17 @@ package com.terning.data.mapper import com.terning.data.dto.response.CalendarDayListResponseDto -import com.terning.domain.entity.CalendarScrapDetail +import com.terning.domain.entity.calendar.CalendarScrapDetail fun CalendarDayListResponseDto.toCalendarScrapDetail() = CalendarScrapDetail( - scrapId = scrapId, internshipAnnouncementId = internshipAnnouncementId, title = title, dDay = dDay, workingPeriod = workingPeriod, color = color, companyImage = companyImage, - startYear = startYear, - startMonth = startMonth, - deadLine = "" + startYearMonth = startYearMonth, + deadline = deadline, + isScrapped = isScrapped ) diff --git a/data/src/main/java/com/terning/data/mapper/CalendarScrapMapper.kt b/data/src/main/java/com/terning/data/mapper/CalendarScrapMapper.kt index a70241fc3..9d92714e7 100644 --- a/data/src/main/java/com/terning/data/mapper/CalendarScrapMapper.kt +++ b/data/src/main/java/com/terning/data/mapper/CalendarScrapMapper.kt @@ -1,7 +1,7 @@ package com.terning.data.mapper import com.terning.data.dto.response.CalendarMonthResponseDto -import com.terning.domain.entity.CalendarScrap +import com.terning.domain.entity.calendar.CalendarScrap fun CalendarMonthResponseDto.toCalendarScrapList(): List = scraps.map { scrap -> CalendarScrap( diff --git a/data/src/main/java/com/terning/data/repositoryimpl/CalendarRepositoryImpl.kt b/data/src/main/java/com/terning/data/repositoryimpl/CalendarRepositoryImpl.kt index e3da56ef1..ad1c64648 100644 --- a/data/src/main/java/com/terning/data/repositoryimpl/CalendarRepositoryImpl.kt +++ b/data/src/main/java/com/terning/data/repositoryimpl/CalendarRepositoryImpl.kt @@ -7,8 +7,8 @@ import com.terning.data.dto.request.CalendarMonthRequestDto import com.terning.data.mapper.toCalendarScrapDetail import com.terning.data.mapper.toCalendarScrapDetailList import com.terning.data.mapper.toCalendarScrapList -import com.terning.domain.entity.CalendarScrapDetail -import com.terning.domain.entity.CalendarScrap +import com.terning.domain.entity.calendar.CalendarScrapDetail +import com.terning.domain.entity.calendar.CalendarScrap import com.terning.domain.repository.CalendarRepository import java.time.LocalDate import java.time.format.DateTimeFormatter @@ -50,7 +50,7 @@ class CalendarRepositoryImpl @Inject constructor( val scrapModelMapByDeadLine = result.flatMap { dto -> dto.toCalendarScrapDetailList() - }.groupBy { it.deadLine } + }.groupBy { it.deadline } scrapModelMapByDeadLine } diff --git a/data/src/main/java/com/terning/data/repositoryimpl/ScrapRepositoryImpl.kt b/data/src/main/java/com/terning/data/repositoryimpl/ScrapRepositoryImpl.kt index 90976c267..ba532fe90 100644 --- a/data/src/main/java/com/terning/data/repositoryimpl/ScrapRepositoryImpl.kt +++ b/data/src/main/java/com/terning/data/repositoryimpl/ScrapRepositoryImpl.kt @@ -1,7 +1,7 @@ package com.terning.data.repositoryimpl import com.terning.data.datasource.ScrapDataSource -import com.terning.domain.entity.CalendarScrapRequest +import com.terning.domain.entity.calendar.CalendarScrapRequest import com.terning.domain.repository.ScrapRepository import javax.inject.Inject diff --git a/domain/src/main/java/com/terning/domain/entity/CalendarScrap.kt b/domain/src/main/java/com/terning/domain/entity/calendar/CalendarScrap.kt similarity index 77% rename from domain/src/main/java/com/terning/domain/entity/CalendarScrap.kt rename to domain/src/main/java/com/terning/domain/entity/calendar/CalendarScrap.kt index 524c21e2f..da23207aa 100644 --- a/domain/src/main/java/com/terning/domain/entity/CalendarScrap.kt +++ b/domain/src/main/java/com/terning/domain/entity/calendar/CalendarScrap.kt @@ -1,4 +1,4 @@ -package com.terning.domain.entity +package com.terning.domain.entity.calendar data class CalendarScrap( val scrapId: Long, diff --git a/domain/src/main/java/com/terning/domain/entity/CalendarScrapDetail.kt b/domain/src/main/java/com/terning/domain/entity/calendar/CalendarScrapDetail.kt similarity index 54% rename from domain/src/main/java/com/terning/domain/entity/CalendarScrapDetail.kt rename to domain/src/main/java/com/terning/domain/entity/calendar/CalendarScrapDetail.kt index 5148a4e49..a4729ffc6 100644 --- a/domain/src/main/java/com/terning/domain/entity/CalendarScrapDetail.kt +++ b/domain/src/main/java/com/terning/domain/entity/calendar/CalendarScrapDetail.kt @@ -1,15 +1,13 @@ -package com.terning.domain.entity +package com.terning.domain.entity.calendar data class CalendarScrapDetail( - val scrapId: Long, val internshipAnnouncementId: Long, val title: String, val dDay: String, val workingPeriod: String, + val deadline: String, val color: String, val companyImage: String, - val startYear: Int, - val startMonth: Int, - val deadLine: String, - val isScrapped: Boolean = true + val startYearMonth: String, + val isScrapped: Boolean ) diff --git a/domain/src/main/java/com/terning/domain/entity/CalendarScrapRequest.kt b/domain/src/main/java/com/terning/domain/entity/calendar/CalendarScrapRequest.kt similarity index 64% rename from domain/src/main/java/com/terning/domain/entity/CalendarScrapRequest.kt rename to domain/src/main/java/com/terning/domain/entity/calendar/CalendarScrapRequest.kt index f87ad429f..8b4d047d2 100644 --- a/domain/src/main/java/com/terning/domain/entity/CalendarScrapRequest.kt +++ b/domain/src/main/java/com/terning/domain/entity/calendar/CalendarScrapRequest.kt @@ -1,4 +1,4 @@ -package com.terning.domain.entity +package com.terning.domain.entity.calendar data class CalendarScrapRequest( val id: Long, diff --git a/domain/src/main/java/com/terning/domain/repository/CalendarRepository.kt b/domain/src/main/java/com/terning/domain/repository/CalendarRepository.kt index 148f062ad..f9b57a318 100644 --- a/domain/src/main/java/com/terning/domain/repository/CalendarRepository.kt +++ b/domain/src/main/java/com/terning/domain/repository/CalendarRepository.kt @@ -1,7 +1,7 @@ package com.terning.domain.repository -import com.terning.domain.entity.CalendarScrapDetail -import com.terning.domain.entity.CalendarScrap +import com.terning.domain.entity.calendar.CalendarScrapDetail +import com.terning.domain.entity.calendar.CalendarScrap import java.time.LocalDate interface CalendarRepository{ diff --git a/domain/src/main/java/com/terning/domain/repository/ScrapRepository.kt b/domain/src/main/java/com/terning/domain/repository/ScrapRepository.kt index 5cf835208..99631d73a 100644 --- a/domain/src/main/java/com/terning/domain/repository/ScrapRepository.kt +++ b/domain/src/main/java/com/terning/domain/repository/ScrapRepository.kt @@ -1,6 +1,6 @@ package com.terning.domain.repository -import com.terning.domain.entity.CalendarScrapRequest +import com.terning.domain.entity.calendar.CalendarScrapRequest interface ScrapRepository { suspend fun postScrap(calendarScrapRequest: CalendarScrapRequest): Result diff --git a/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt b/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt index 37b56da48..d173cbd4b 100644 --- a/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt +++ b/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt @@ -1,6 +1,5 @@ package com.terning.feature.calendar.calendar -import androidx.activity.compose.BackHandler import androidx.compose.animation.slideInHorizontally import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutHorizontally @@ -39,31 +38,26 @@ import java.time.LocalDate @Composable fun CalendarRoute( - navigateUp: () -> Unit, navigateToAnnouncement: (Long) -> Unit, + modifier: Modifier = Modifier, viewModel: CalendarViewModel = hiltViewModel() ) { val lifecycleOwner = LocalLifecycleOwner.current val uiState by viewModel.uiState.collectAsStateWithLifecycle(lifecycleOwner = lifecycleOwner) - BackHandler { - if (uiState.isWeekEnabled) { - viewModel.updateSelectedDate(uiState.selectedDate) - } else if (uiState.isListEnabled) { - viewModel.updateListVisibility(false) - } else { - navigateUp() - } - } - CalendarScreen( + modifier = modifier, uiState = uiState, navigateToAnnouncement = navigateToAnnouncement, updateSelectedDate = viewModel::updateSelectedDate, updatePage = viewModel::updatePage, + disableListVisibility = { viewModel.updateListVisibility(false) }, + disableWeekVisibility = { viewModel.updateSelectedDate(uiState.selectedDate) }, onClickListButton = { viewModel.updateListVisibility(!uiState.isListEnabled) - if (uiState.isWeekEnabled) { viewModel.updateWeekVisibility(false) } + if (uiState.isWeekEnabled) { + viewModel.updateWeekVisibility(false) + } } ) } @@ -73,6 +67,8 @@ private fun CalendarScreen( uiState: CalendarUiState, navigateToAnnouncement: (Long) -> Unit, updateSelectedDate: (LocalDate) -> Unit, + disableListVisibility: () -> Unit, + disableWeekVisibility: () -> Unit, updatePage: (Int) -> Unit, onClickListButton: () -> Unit, modifier: Modifier = Modifier, @@ -91,24 +87,22 @@ private fun CalendarScreen( } } - Scaffold( + Column( modifier = modifier, - topBar = { - CalendarTopAppBar( - date = getYearMonthByPage(uiState.currentPage), - isListExpanded = uiState.isListEnabled, - isWeekExpanded = uiState.isWeekEnabled, - onListButtonClicked = onClickListButton, - onMonthNavigationButtonClicked = { direction -> - coroutineScope.launch { - listState.animateScrollToItem( - index = listState.firstVisibleItemIndex + direction, - ) - } + ){ + CalendarTopAppBar( + date = getYearMonthByPage(uiState.currentPage), + isListExpanded = uiState.isListEnabled, + isWeekExpanded = uiState.isWeekEnabled, + onListButtonClicked = onClickListButton, + onMonthNavigationButtonClicked = { direction -> + coroutineScope.launch { + listState.animateScrollToItem( + index = listState.firstVisibleItemIndex + direction, + ) } - ) - } - ) { paddingValues -> + } + ) ScreenTransition( targetState = !uiState.isListEnabled, transitionOne = slideInHorizontally { fullWidth -> -fullWidth } togetherWith @@ -119,7 +113,6 @@ private fun CalendarScreen( Column( modifier = Modifier .fillMaxSize() - .padding(top = paddingValues.calculateTopPadding()) ) { WeekDaysHeader() @@ -150,6 +143,7 @@ private fun CalendarScreen( calendarUiState = uiState, modifier = Modifier .fillMaxSize(), + navigateUp = disableWeekVisibility, navigateToAnnouncement = navigateToAnnouncement, updateSelectedDate = updateSelectedDate ) @@ -162,9 +156,9 @@ private fun CalendarScreen( listState = listState, pages = uiState.calendarModel.pageCount, navigateToAnnouncement = navigateToAnnouncement, + navigateUp = disableListVisibility, modifier = Modifier .fillMaxSize() - .padding(top = paddingValues.calculateTopPadding()) ) }, ) diff --git a/feature/src/main/java/com/terning/feature/calendar/calendar/navigation/CalendarNavigation.kt b/feature/src/main/java/com/terning/feature/calendar/calendar/navigation/CalendarNavigation.kt index 7f06fac41..7aa5db891 100644 --- a/feature/src/main/java/com/terning/feature/calendar/calendar/navigation/CalendarNavigation.kt +++ b/feature/src/main/java/com/terning/feature/calendar/calendar/navigation/CalendarNavigation.kt @@ -2,6 +2,9 @@ package com.terning.feature.calendar.calendar.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.NavOptions @@ -20,7 +23,8 @@ fun NavController.navigateCalendar(navOptions: NavOptions? = null) { } fun NavGraphBuilder.calendarNavGraph( - navHostController: NavController + navHostController: NavController, + paddingValues: PaddingValues ) { composable( exitTransition = { @@ -37,7 +41,7 @@ fun NavGraphBuilder.calendarNavGraph( } ) { CalendarRoute( - navigateUp = navHostController::navigateUp, + modifier = Modifier.padding(paddingValues), navigateToAnnouncement = navHostController::navigateIntern ) } diff --git a/feature/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt b/feature/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt index 91f31fd01..6e145abbc 100644 --- a/feature/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt +++ b/feature/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt @@ -1,12 +1,13 @@ package com.terning.feature.calendar.list +import androidx.activity.compose.BackHandler +import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListState @@ -20,6 +21,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp @@ -28,16 +30,15 @@ import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.flowWithLifecycle import com.terning.core.designsystem.theme.Back -import com.terning.core.designsystem.theme.Grey200 +import com.terning.core.designsystem.theme.Black 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.getDateAsMapString import com.terning.core.extension.getFullDateStringInKorean import com.terning.core.extension.isListNotEmpty import com.terning.core.extension.toast import com.terning.core.state.UiState -import com.terning.domain.entity.CalendarScrapDetail +import com.terning.domain.entity.calendar.CalendarScrapDetail import com.terning.feature.R import com.terning.feature.calendar.calendar.model.CalendarDefaults.flingBehavior import com.terning.feature.calendar.calendar.model.CalendarModel.Companion.getLocalDateByPage @@ -53,6 +54,7 @@ fun CalendarListRoute( pages: Int, listState: LazyListState, modifier: Modifier = Modifier, + navigateUp: () -> Unit, navigateToAnnouncement: (Long) -> Unit, viewModel: CalendarListViewModel = hiltViewModel() ) { @@ -80,6 +82,10 @@ fun CalendarListRoute( } } + BackHandler { + navigateUp() + } + CalendarListScreen( pages = pages, listState = listState, @@ -99,7 +105,7 @@ fun CalendarListRoute( }, onClickScrapButton = { scrapId -> with(viewModel){ - updateScrapId(scrapId) + updateAnnouncementId(scrapId) updateScrapCancelDialogVisibility(true) } }, @@ -145,8 +151,7 @@ private fun CalendarListScreen( .background(Back) ) { when (uiState.loadState) { - UiState.Loading -> {} - UiState.Empty -> { + UiState.Loading -> { item { Box( modifier = Modifier.fillMaxSize(), @@ -156,7 +161,7 @@ private fun CalendarListScreen( modifier = Modifier .padding(top = 42.dp) .fillMaxWidth(), - text = stringResource(id = R.string.calendar_empty_scrap), + text = stringResource(id = R.string.calendar_text_friday), textAlign = TextAlign.Center, style = TerningTheme.typography.body5, color = Grey400 @@ -164,30 +169,42 @@ private fun CalendarListScreen( } } } + UiState.Empty -> { + item { + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + CalendarListEmpty() + } + } + } is UiState.Failure -> {} is UiState.Success -> { + val scrapMap = uiState.loadState.data items(getDate.lengthOfMonth()) { day -> - val scrapMap = uiState.loadState.data - val currentDate = - LocalDate.of(getDate.year, getDate.monthValue, day + 1) - val dateIndex = currentDate.getDateAsMapString() + val currentDate = LocalDate.of(getDate.year, getDate.monthValue, day + 1) + val dateInKorean = currentDate.getFullDateStringInKorean() + + if (scrapMap[dateInKorean].isListNotEmpty()) { + Text( + text = dateInKorean, + style = TerningTheme.typography.title5, + color = Black, + modifier = Modifier + .padding(start = 24.dp, top = 16.dp, bottom = 15.dp) + ) - if (scrapMap[dateIndex].isListNotEmpty()) { CalendarScrapList( selectedDate = currentDate, - scrapList = scrapMap[dateIndex].orEmpty(), + scrapList = scrapMap[dateInKorean].orEmpty(), onScrapButtonClicked = onClickScrapButton, onInternshipClicked = onClickInternship, - isFromList = true - ) - - Spacer( + isFromList = true, modifier = Modifier - .padding(top = 4.dp) .fillMaxWidth() - .height(4.dp) - .background(Grey200) + .padding(horizontal = 24.dp) ) } } @@ -199,9 +216,9 @@ private fun CalendarListScreen( } if (uiState.scrapDialogVisibility) { - uiState.scrapId?.run { + uiState.internshipAnnouncementId?.run { ScrapCancelDialog( - scrapId = this, + internshipAnnouncementId = this, onDismissRequest = onDismissCancelDialog ) } @@ -218,10 +235,8 @@ private fun CalendarListScreen( title = uiState.internshipModel.title, scrapColor = scrapColor, deadline = uiState.currentDate.getFullDateStringInKorean(), - startYear = uiState.internshipModel.startYear, - startMonth = uiState.internshipModel.startMonth, + startYearMonth = uiState.internshipModel.startYearMonth, workingPeriod = uiState.internshipModel.workingPeriod, - scrapId = uiState.internshipModel.scrapId, internshipAnnouncementId = uiState.internshipModel.internshipAnnouncementId, companyImage = uiState.internshipModel.companyImage, isScrapped = true, @@ -233,4 +248,26 @@ private fun CalendarListScreen( } } +@Composable +private fun CalendarListEmpty( + modifier: Modifier = Modifier +) { + Image( + painter = painterResource( + id = R.drawable.ic_terning_calendar_empty + ), + contentDescription = "", + modifier = modifier.padding(top = 20.dp, bottom = 4.dp) + ) + + Text( + modifier = modifier + .fillMaxWidth(), + text = stringResource(id = R.string.calendar_empty_scrap), + textAlign = TextAlign.Center, + style = TerningTheme.typography.body5, + color = Grey400 + ) +} + diff --git a/feature/src/main/java/com/terning/feature/calendar/list/CalendarListViewModel.kt b/feature/src/main/java/com/terning/feature/calendar/list/CalendarListViewModel.kt index cfd4f7876..6491ae47a 100644 --- a/feature/src/main/java/com/terning/feature/calendar/list/CalendarListViewModel.kt +++ b/feature/src/main/java/com/terning/feature/calendar/list/CalendarListViewModel.kt @@ -3,7 +3,7 @@ package com.terning.feature.calendar.list import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.terning.core.state.UiState -import com.terning.domain.entity.CalendarScrapDetail +import com.terning.domain.entity.calendar.CalendarScrapDetail import com.terning.domain.repository.CalendarRepository import com.terning.feature.R import com.terning.feature.calendar.list.model.CalendarListUiState @@ -15,7 +15,6 @@ import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import java.time.LocalDate import javax.inject.Inject @@ -45,10 +44,10 @@ class CalendarListViewModel @Inject constructor( } } - fun updateScrapId(scrapId: Long? = null) { + fun updateAnnouncementId(announcementId: Long? = null) { _uiState.update { currentState -> currentState.copy( - scrapId = scrapId + internshipAnnouncementId = announcementId ) } } @@ -71,29 +70,28 @@ class CalendarListViewModel @Inject constructor( fun getScrapMonthList( date: LocalDate - ) = viewModelScope.launch { - withContext(Dispatchers.IO) { - calendarRepository.getScrapMonthList( - year = _uiState.value.currentDate.year, - month = _uiState.value.currentDate.monthValue - ) - }.fold( - onSuccess = { - _uiState.update { currentState -> - currentState.copy( - loadState = if (it.isNotEmpty()) UiState.Success(it) else UiState.Empty - ) - } - }, - onFailure = { - _uiState.update { currentState -> - currentState.copy( - loadState = UiState.Failure(it.message.toString()) - ) + ) = viewModelScope.launch(Dispatchers.IO) { + calendarRepository.getScrapMonthList( + year = date.year, + month = date.monthValue + ) + .fold( + onSuccess = { + _uiState.update { currentState -> + currentState.copy( + loadState = if (it.isNotEmpty()) UiState.Success(it) else UiState.Empty + ) + } + }, + onFailure = { + _uiState.update { currentState -> + currentState.copy( + loadState = UiState.Failure(it.message.toString()) + ) + } + _sideEffect.emit(CalendarListSideEffect.ShowToast(R.string.server_failure)) } - _sideEffect.emit(CalendarListSideEffect.ShowToast(R.string.server_failure)) - } - ) + ) } -} \ No newline at end of file +} diff --git a/feature/src/main/java/com/terning/feature/calendar/list/component/CalendarScrap.kt b/feature/src/main/java/com/terning/feature/calendar/list/component/CalendarScrap.kt index aa38a573a..8349ac8fb 100644 --- a/feature/src/main/java/com/terning/feature/calendar/list/component/CalendarScrap.kt +++ b/feature/src/main/java/com/terning/feature/calendar/list/component/CalendarScrap.kt @@ -7,7 +7,7 @@ import androidx.compose.ui.unit.dp import com.terning.core.designsystem.component.item.InternItem import com.terning.core.designsystem.component.item.ScrapBox import com.terning.core.extension.noRippleClickable -import com.terning.domain.entity.CalendarScrapDetail +import com.terning.domain.entity.calendar.CalendarScrapDetail @Composable fun CalendarScrap( @@ -25,8 +25,8 @@ fun CalendarScrap( elevation = 1.dp, ) { InternItem( - scrapId = scrap.scrapId, - imageUrl = scrap.companyImage.orEmpty(), + scrapId = scrap.internshipAnnouncementId, + imageUrl = scrap.companyImage, title = scrap.title, dateDeadline = scrap.dDay, workingPeriod = scrap.workingPeriod, diff --git a/feature/src/main/java/com/terning/feature/calendar/list/component/CalendarScrapList.kt b/feature/src/main/java/com/terning/feature/calendar/list/component/CalendarScrapList.kt index d8e48179b..a2ff8bb49 100644 --- a/feature/src/main/java/com/terning/feature/calendar/list/component/CalendarScrapList.kt +++ b/feature/src/main/java/com/terning/feature/calendar/list/component/CalendarScrapList.kt @@ -15,7 +15,7 @@ import com.terning.core.designsystem.theme.Black import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.extension.getDateStringInKorean import com.terning.core.extension.isListNotEmpty -import com.terning.domain.entity.CalendarScrapDetail +import com.terning.domain.entity.calendar.CalendarScrapDetail import java.time.LocalDate @Composable @@ -28,26 +28,13 @@ internal fun CalendarScrapList( isFromList: Boolean = false ) { val scrollState = rememberScrollState() - val topModifier = if (!isFromList) { - Modifier - .fillMaxWidth() - .padding(horizontal = 24.dp) - .verticalScroll(scrollState) - } else { - Modifier - .fillMaxWidth() - .padding(horizontal = 24.dp) - } - - if (scrapList.isListNotEmpty()) { - Text( - text = selectedDate.getDateStringInKorean(), - style = TerningTheme.typography.title5, - color = Black, - modifier = Modifier - .padding(start = 24.dp, top = 16.dp, bottom = 15.dp) - ) - } + val topModifier = modifier.then( + if (!isFromList) { + Modifier.verticalScroll(scrollState) + } else { + Modifier + } + ) Column( modifier = topModifier @@ -59,7 +46,7 @@ internal fun CalendarScrapList( onInternshipClicked = onInternshipClicked ) Spacer( - modifier = Modifier.height(12.dp) + modifier = Modifier.height(if(scrap == scrapList.last()) 16.dp else 12.dp) ) } } diff --git a/feature/src/main/java/com/terning/feature/calendar/list/model/CalendarListUiState.kt b/feature/src/main/java/com/terning/feature/calendar/list/model/CalendarListUiState.kt index 6377463d7..1e7fb236f 100644 --- a/feature/src/main/java/com/terning/feature/calendar/list/model/CalendarListUiState.kt +++ b/feature/src/main/java/com/terning/feature/calendar/list/model/CalendarListUiState.kt @@ -1,7 +1,7 @@ package com.terning.feature.calendar.list.model import com.terning.core.state.UiState -import com.terning.domain.entity.CalendarScrapDetail +import com.terning.domain.entity.calendar.CalendarScrapDetail import java.time.LocalDate data class CalendarListUiState( @@ -9,6 +9,6 @@ data class CalendarListUiState( val currentDate: LocalDate = LocalDate.now(), val scrapDialogVisibility: Boolean = false, val internDialogVisibility: Boolean = false, - val scrapId: Long? = null, + val internshipAnnouncementId: Long? = null, val internshipModel: CalendarScrapDetail? = null ) \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt b/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt index 609769fff..5ebbabdd4 100644 --- a/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt +++ b/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt @@ -14,7 +14,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.flowWithLifecycle import com.terning.core.extension.toast import com.terning.core.state.UiState -import com.terning.domain.entity.CalendarScrap +import com.terning.domain.entity.calendar.CalendarScrap import com.terning.feature.calendar.calendar.model.CalendarDefaults.flingBehavior import com.terning.feature.calendar.calendar.model.CalendarModel.Companion.getLocalDateByPage import com.terning.feature.calendar.month.model.MonthModel diff --git a/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthViewModel.kt b/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthViewModel.kt index 0f17cecd7..fbcd6dcb1 100644 --- a/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthViewModel.kt +++ b/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthViewModel.kt @@ -14,7 +14,6 @@ import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import javax.inject.Inject @HiltViewModel @@ -29,20 +28,19 @@ class CalendarMonthViewModel @Inject constructor( fun getScrapMonth( year: Int, month: Int - ) = viewModelScope.launch { - withContext(Dispatchers.IO) { - calendarRepository.getScrapMonth(year, month) - }.fold( - onSuccess = { - _uiState.update { currentState -> - currentState.copy( - loadState = UiState.Success(it) - ) + ) = viewModelScope.launch(Dispatchers.IO) { + calendarRepository.getScrapMonth(year, month) + .fold( + onSuccess = { + _uiState.update { currentState -> + currentState.copy( + loadState = UiState.Success(it) + ) + } + }, + onFailure = { + _sideEffect.emit(CalendarMonthSideEffect.ShowToast(R.string.server_failure)) } - }, - onFailure = { - _sideEffect.emit(CalendarMonthSideEffect.ShowToast(R.string.server_failure)) - } - ) + ) } } \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/calendar/month/component/CalendarMonth.kt b/feature/src/main/java/com/terning/feature/calendar/month/component/CalendarMonth.kt index 2abffd608..7a6ee8ef6 100644 --- a/feature/src/main/java/com/terning/feature/calendar/month/component/CalendarMonth.kt +++ b/feature/src/main/java/com/terning/feature/calendar/month/component/CalendarMonth.kt @@ -16,7 +16,7 @@ import com.terning.core.designsystem.theme.TerningPointTheme import com.terning.core.extension.getDateAsMapString import com.terning.core.extension.isToday import com.terning.core.extension.noRippleClickable -import com.terning.domain.entity.CalendarScrap +import com.terning.domain.entity.calendar.CalendarScrap import com.terning.feature.calendar.calendar.component.CalendarDay import com.terning.feature.calendar.month.model.MonthModel import java.time.LocalDate @@ -63,6 +63,7 @@ internal fun CalendarMonth( if (!day.isOutDate) { val index = day.date.getDateAsMapString() CalendarMonthScrap( + weekCount = month.size, scrapLists = scrapMap[index].orEmpty(), modifier = Modifier.fillMaxWidth() ) diff --git a/feature/src/main/java/com/terning/feature/calendar/month/component/CalendarMonthScrap.kt b/feature/src/main/java/com/terning/feature/calendar/month/component/CalendarMonthScrap.kt index ba27ba799..f20ca1b91 100644 --- a/feature/src/main/java/com/terning/feature/calendar/month/component/CalendarMonthScrap.kt +++ b/feature/src/main/java/com/terning/feature/calendar/month/component/CalendarMonthScrap.kt @@ -16,20 +16,24 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.designsystem.theme.White -import com.terning.domain.entity.CalendarScrap +import com.terning.domain.entity.calendar.CalendarScrap import com.terning.feature.R -private const val MAX_SCRAP_COUNT = 3 +private const val SCRAP_COUNT_WEEK_SIX = 3 +private const val SCRAP_COUNT_WEEK_FIVE = 4 @Composable internal fun CalendarMonthScrap( + weekCount: Int, modifier: Modifier = Modifier, scrapLists: List ) { + val scrapCount = if(weekCount == 5) SCRAP_COUNT_WEEK_FIVE else SCRAP_COUNT_WEEK_SIX + LazyColumn( modifier = modifier ) { - items(scrapLists.subList(0, MAX_SCRAP_COUNT.coerceAtMost(scrapLists.size))) { scrap -> + items(scrapLists.subList(0, scrapCount.coerceAtMost(scrapLists.size))) { scrap -> Text( text = scrap.title, style = TerningTheme.typography.button5, @@ -49,11 +53,11 @@ internal fun CalendarMonthScrap( } item { - if (scrapLists.size > MAX_SCRAP_COUNT) { + if (scrapLists.size > scrapCount) { Text( - text = stringResource(id = R.string.calendar_scrap_overflow, (scrapLists.size - MAX_SCRAP_COUNT)), + text = stringResource(id = R.string.calendar_scrap_overflow, (scrapLists.size - scrapCount)), style = TerningTheme.typography.detail4, - textAlign = TextAlign.Center, + textAlign = TextAlign.End, modifier = Modifier.fillMaxWidth() ) } diff --git a/feature/src/main/java/com/terning/feature/calendar/month/model/CalendarMonthUiState.kt b/feature/src/main/java/com/terning/feature/calendar/month/model/CalendarMonthUiState.kt index 9734222ee..89e0f0f45 100644 --- a/feature/src/main/java/com/terning/feature/calendar/month/model/CalendarMonthUiState.kt +++ b/feature/src/main/java/com/terning/feature/calendar/month/model/CalendarMonthUiState.kt @@ -1,7 +1,7 @@ package com.terning.feature.calendar.month.model import com.terning.core.state.UiState -import com.terning.domain.entity.CalendarScrap +import com.terning.domain.entity.calendar.CalendarScrap data class CalendarMonthUiState( val loadState: UiState>> = UiState.Loading diff --git a/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt b/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt index a994b1916..ca882549f 100644 --- a/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt +++ b/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt @@ -1,9 +1,9 @@ package com.terning.feature.calendar.week +import androidx.activity.compose.BackHandler +import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape @@ -18,10 +18,9 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow -import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color -import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp @@ -30,13 +29,16 @@ import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.flowWithLifecycle import com.terning.core.designsystem.theme.Back +import com.terning.core.designsystem.theme.Black 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.getDateStringInKorean import com.terning.core.extension.getFullDateStringInKorean +import com.terning.core.extension.swipableVertically import com.terning.core.extension.toast import com.terning.core.state.UiState -import com.terning.domain.entity.CalendarScrapDetail +import com.terning.domain.entity.calendar.CalendarScrapDetail import com.terning.feature.R import com.terning.feature.calendar.calendar.model.CalendarUiState import com.terning.feature.calendar.list.component.CalendarScrapList @@ -52,6 +54,7 @@ fun CalendarWeekRoute( calendarUiState: CalendarUiState, navigateToAnnouncement: (Long) -> Unit, updateSelectedDate: (LocalDate) -> Unit, + navigateUp: () -> Unit, modifier: Modifier = Modifier, viewModel: CalendarWeekViewModel = hiltViewModel() ) { @@ -76,6 +79,10 @@ fun CalendarWeekRoute( viewModel.getScrapWeekList(selectedDate = uiState.selectedDate) } + BackHandler { + navigateUp() + } + CalendarWeekScreen( modifier = modifier, uiState = uiState, @@ -95,7 +102,7 @@ fun CalendarWeekRoute( onClickChangeColor = { viewModel.getScrapWeekList(uiState.selectedDate) }, onClickScrapButton = { scrapId -> with(viewModel) { - updateScrapId(scrapId) + updateInternshipAnnouncementId(scrapId) updateScrapCancelDialogVisibility(true) } }, @@ -121,43 +128,22 @@ private fun CalendarWeekScreen( navigateToAnnouncement: (Long) -> Unit, modifier: Modifier = Modifier ) { - var initialTouchPosition by remember { mutableStateOf(null) } - var hideComponent by remember { mutableStateOf(false) } + var swiped by remember { mutableStateOf(false) } - LaunchedEffect(hideComponent) { - if (hideComponent) { + LaunchedEffect(swiped) { + if (swiped) { updateSelectedDate(selectedDate) } } - val swipeModifier = Modifier.pointerInput(Unit) { - awaitPointerEventScope { - while (true) { - val event = awaitPointerEvent() - val position = event.changes.first().position - - if (event.changes.first().pressed) { - if (initialTouchPosition == null) { - initialTouchPosition = position - } else { - val deltaY = initialTouchPosition?.let { position.y - it.y } - if (deltaY != null && deltaY > 300f) { - hideComponent = true - } - } - } else { - initialTouchPosition = null - } - } - } - } - Column( modifier = modifier - .background(Back) + .background(Back), + horizontalAlignment = Alignment.CenterHorizontally ) { Card( - modifier = swipeModifier + modifier = Modifier + .swipableVertically { swiped = true } .shadow( shape = RoundedCornerShape(bottomStart = 20.dp, bottomEnd = 20.dp), elevation = 1.dp @@ -174,13 +160,25 @@ private fun CalendarWeekScreen( ) } + Text( + text = selectedDate.getDateStringInKorean(), + style = TerningTheme.typography.title5, + color = Black, + modifier = Modifier + .fillMaxWidth() + .padding(start = 24.dp, top = 16.dp, bottom = 15.dp) + ) + when (uiState.loadState) { is UiState.Loading -> {} is UiState.Empty -> { CalendarWeekEmpty() } - is UiState.Failure -> {} + is UiState.Failure -> { + CalendarWeekEmpty() + } + is UiState.Success -> { CalendarWeekSuccess( scrapList = uiState.loadState.data.toImmutableList(), @@ -193,9 +191,9 @@ private fun CalendarWeekScreen( } if (uiState.scrapDialogVisibility) { - uiState.scrapId?.run { + uiState.internshipAnnouncementId?.run { ScrapCancelDialog( - scrapId = this, + internshipAnnouncementId = this, onDismissRequest = onDismissCancelDialog ) } @@ -212,10 +210,8 @@ private fun CalendarWeekScreen( title = uiState.internshipModel.title, scrapColor = scrapColor, deadline = uiState.selectedDate.getFullDateStringInKorean(), - startYear = uiState.internshipModel.startYear, - startMonth = uiState.internshipModel.startMonth, + startYearMonth = uiState.internshipModel.startYearMonth, workingPeriod = uiState.internshipModel.workingPeriod, - scrapId = uiState.internshipModel.scrapId, internshipAnnouncementId = uiState.internshipModel.internshipAnnouncementId, companyImage = uiState.internshipModel.companyImage, isScrapped = true, @@ -231,20 +227,22 @@ private fun CalendarWeekScreen( private fun CalendarWeekEmpty( modifier: Modifier = Modifier ) { - Box( - modifier = modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) { - Text( - modifier = Modifier - .padding(top = 42.dp) - .fillMaxWidth(), - text = stringResource(id = R.string.calendar_empty_scrap), - textAlign = TextAlign.Center, - style = TerningTheme.typography.body5, - color = Grey400 - ) - } + Image( + painter = painterResource( + id = R.drawable.ic_terning_calendar_empty + ), + contentDescription = "", + modifier = modifier.padding(top = 20.dp, bottom = 4.dp) + ) + + Text( + modifier = modifier + .fillMaxWidth(), + text = stringResource(id = R.string.calendar_empty_scrap), + textAlign = TextAlign.Center, + style = TerningTheme.typography.body5, + color = Grey400 + ) } @Composable @@ -258,7 +256,9 @@ private fun CalendarWeekSuccess( selectedDate = selectedDate, scrapList = scrapList, onScrapButtonClicked = onScrapButtonClicked, - onInternshipClicked = onInternshipClicked + onInternshipClicked = onInternshipClicked, + modifier = Modifier + .padding(horizontal = 24.dp) ) } diff --git a/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekViewModel.kt b/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekViewModel.kt index 8374a610b..0ebe403c3 100644 --- a/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekViewModel.kt +++ b/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekViewModel.kt @@ -3,7 +3,7 @@ package com.terning.feature.calendar.week import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.terning.core.state.UiState -import com.terning.domain.entity.CalendarScrapDetail +import com.terning.domain.entity.calendar.CalendarScrapDetail import com.terning.domain.repository.CalendarRepository import com.terning.feature.R import com.terning.feature.calendar.week.model.CalendarWeekUiState @@ -15,7 +15,6 @@ import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import java.time.LocalDate import javax.inject.Inject @@ -45,10 +44,10 @@ class CalendarWeekViewModel @Inject constructor( } } - fun updateScrapId(scrapId: Long? = null) { + fun updateInternshipAnnouncementId(internshipAnnouncementId: Long? = null) { _uiState.update { currentState -> currentState.copy( - scrapId = scrapId + internshipAnnouncementId = internshipAnnouncementId ) } } @@ -69,26 +68,25 @@ class CalendarWeekViewModel @Inject constructor( } } - fun getScrapWeekList(selectedDate: LocalDate) = viewModelScope.launch { - withContext(Dispatchers.IO) { - calendarRepository.getScrapDayList(selectedDate) - }.fold( - onSuccess = { - _uiState.update { currentState -> - currentState.copy( - loadState = if (it.isNotEmpty()) UiState.Success(it) else UiState.Empty - ) - } - }, - onFailure = { - _uiState.update { currentState -> - currentState.copy( - loadState = UiState.Failure(it.message.toString()) - ) + fun getScrapWeekList(selectedDate: LocalDate) = viewModelScope.launch(Dispatchers.IO) { + calendarRepository.getScrapDayList(selectedDate) + .fold( + onSuccess = { + _uiState.update { currentState -> + currentState.copy( + loadState = if (it.isNotEmpty()) UiState.Success(it) else UiState.Empty + ) + } + }, + onFailure = { + _uiState.update { currentState -> + currentState.copy( + loadState = UiState.Failure(it.message.toString()) + ) + } + _sideEffect.emit(CalendarWeekSideEffect.ShowToast(R.string.server_failure)) } - _sideEffect.emit(CalendarWeekSideEffect.ShowToast(R.string.server_failure)) - } - ) + ) } } \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/calendar/week/model/CalendarWeekUiState.kt b/feature/src/main/java/com/terning/feature/calendar/week/model/CalendarWeekUiState.kt index b878bbb2f..08932e1e7 100644 --- a/feature/src/main/java/com/terning/feature/calendar/week/model/CalendarWeekUiState.kt +++ b/feature/src/main/java/com/terning/feature/calendar/week/model/CalendarWeekUiState.kt @@ -1,7 +1,7 @@ package com.terning.feature.calendar.week.model import com.terning.core.state.UiState -import com.terning.domain.entity.CalendarScrapDetail +import com.terning.domain.entity.calendar.CalendarScrapDetail import java.time.LocalDate data class CalendarWeekUiState( @@ -9,6 +9,6 @@ data class CalendarWeekUiState( val selectedDate: LocalDate = LocalDate.now(), val scrapDialogVisibility: Boolean = false, val internDialogVisibility: Boolean = false, - val scrapId: Long? = null, + val internshipAnnouncementId: Long? = null, val internshipModel: CalendarScrapDetail? = null ) \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/dialog/cancel/ScrapCancelDialog.kt b/feature/src/main/java/com/terning/feature/dialog/cancel/ScrapCancelDialog.kt index 3e3c8fd77..9700fa9e4 100644 --- a/feature/src/main/java/com/terning/feature/dialog/cancel/ScrapCancelDialog.kt +++ b/feature/src/main/java/com/terning/feature/dialog/cancel/ScrapCancelDialog.kt @@ -31,7 +31,7 @@ import com.terning.feature.R @Composable fun ScrapCancelDialog( - scrapId: Long, + internshipAnnouncementId: Long, onDismissRequest: (Boolean) -> Unit, viewModel: ScrapCancelViewModel = hiltViewModel() ) { @@ -53,7 +53,7 @@ fun ScrapCancelDialog( ScrapCancelScreen( onDismissRequest = { onDismissRequest(false) }, - onClickScrapCancel = { viewModel.deleteScrap(scrapId) } + onClickScrapCancel = { viewModel.deleteScrap(internshipAnnouncementId) } ) } diff --git a/feature/src/main/java/com/terning/feature/dialog/cancel/ScrapCancelViewModel.kt b/feature/src/main/java/com/terning/feature/dialog/cancel/ScrapCancelViewModel.kt index 0cf47d3a2..2353d2077 100644 --- a/feature/src/main/java/com/terning/feature/dialog/cancel/ScrapCancelViewModel.kt +++ b/feature/src/main/java/com/terning/feature/dialog/cancel/ScrapCancelViewModel.kt @@ -2,7 +2,7 @@ package com.terning.feature.dialog.cancel import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.terning.domain.entity.CalendarScrapRequest +import com.terning.domain.entity.calendar.CalendarScrapRequest import com.terning.domain.repository.ScrapRepository import com.terning.feature.R import dagger.hilt.android.lifecycle.HiltViewModel diff --git a/feature/src/main/java/com/terning/feature/dialog/detail/ScrapDialog.kt b/feature/src/main/java/com/terning/feature/dialog/detail/ScrapDialog.kt index e160aea7a..57ab067dc 100644 --- a/feature/src/main/java/com/terning/feature/dialog/detail/ScrapDialog.kt +++ b/feature/src/main/java/com/terning/feature/dialog/detail/ScrapDialog.kt @@ -59,10 +59,8 @@ fun ScrapDialog( title: String, scrapColor: Color, deadline: String, - startYear: Int, - startMonth: Int, + startYearMonth: String, workingPeriod: String, - scrapId: Long, internshipAnnouncementId: Long, companyImage: String, isScrapped: Boolean, @@ -108,8 +106,7 @@ fun ScrapDialog( ScrapDialogScreen( title = title, deadline = deadline, - startYear = startYear, - startMonth = startMonth, + startYearMonth = startYearMonth, workingPeriod = workingPeriod, isScrapped = isScrapped, companyImage = companyImage, @@ -119,7 +116,7 @@ fun ScrapDialog( onClickColorButton = viewModel::changeSelectedColor, onClickColorChangeButton = { if(uiState.isColorChanged) - viewModel.patchScrap(scrapId = scrapId, color = uiState.selectedColorType) + viewModel.patchScrap(scrapId = internshipAnnouncementId, color = uiState.selectedColorType) }, onClickNavigateButton = viewModel::navigateToDetail, onClickScrapButton = { @@ -134,8 +131,7 @@ fun ScrapDialog( private fun ScrapDialogScreen( title: String, deadline: String, - startYear: Int, - startMonth: Int, + startYearMonth: String, workingPeriod: String, isScrapped: Boolean, companyImage: String, @@ -252,7 +248,7 @@ private fun ScrapDialogScreen( ) InternInfoRow( title = stringResource(id = R.string.intern_info_start_date), - value = "${startYear}년 ${startMonth}월" + value = startYearMonth ) } } @@ -327,8 +323,7 @@ private fun ScrapDialogPreview() { ScrapDialogScreen( title = "터닝 하반기 채용터닝 하반기 채용터닝 하반기 채용터닝터닝 하반기 채용터닝터닝 하반기 채용터닝터닝 하반기 채용터닝터닝 하반기 채용터닝터닝 하반기 채용터닝 하반기 채용터닝 하반기 채용터닝 하반기 채용터닝 하반기 채용터닝 하반기 채용터닝 하반기 채용", deadline = "2024/09/07", - startYear = 2024, - startMonth = 11, + startYearMonth = "2024년 11월", workingPeriod = "2개월", companyImage = "", isScrapped = false, diff --git a/feature/src/main/java/com/terning/feature/dialog/detail/ScrapDialogViewModel.kt b/feature/src/main/java/com/terning/feature/dialog/detail/ScrapDialogViewModel.kt index 3f08e2e4b..b74b3e27c 100644 --- a/feature/src/main/java/com/terning/feature/dialog/detail/ScrapDialogViewModel.kt +++ b/feature/src/main/java/com/terning/feature/dialog/detail/ScrapDialogViewModel.kt @@ -14,7 +14,7 @@ import com.terning.core.designsystem.theme.CalPurple import com.terning.core.designsystem.theme.CalRed import com.terning.core.designsystem.theme.CalYellow import com.terning.core.type.ColorType -import com.terning.domain.entity.CalendarScrapRequest +import com.terning.domain.entity.calendar.CalendarScrapRequest import com.terning.domain.repository.ScrapRepository import com.terning.feature.R import com.terning.feature.dialog.detail.state.ScrapDialogUiState diff --git a/feature/src/main/java/com/terning/feature/home/home/HomeViewModel.kt b/feature/src/main/java/com/terning/feature/home/home/HomeViewModel.kt index 96c958fe1..3269ce21f 100644 --- a/feature/src/main/java/com/terning/feature/home/home/HomeViewModel.kt +++ b/feature/src/main/java/com/terning/feature/home/home/HomeViewModel.kt @@ -5,7 +5,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.terning.core.designsystem.theme.CalRed import com.terning.core.state.UiState -import com.terning.domain.entity.CalendarScrapRequest +import com.terning.domain.entity.calendar.CalendarScrapRequest import com.terning.domain.entity.request.ChangeFilteringRequestModel import com.terning.domain.repository.HomeRepository import com.terning.domain.repository.MyPageRepository 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 7322223a9..460e980b6 100644 --- a/feature/src/main/java/com/terning/feature/intern/InternViewModel.kt +++ b/feature/src/main/java/com/terning/feature/intern/InternViewModel.kt @@ -4,7 +4,7 @@ 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.CalendarScrapRequest +import com.terning.domain.entity.calendar.CalendarScrapRequest import com.terning.domain.repository.InternRepository import com.terning.domain.repository.ScrapRepository import com.terning.feature.R 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 516f63bf1..f851101a2 100644 --- a/feature/src/main/java/com/terning/feature/main/MainScreen.kt +++ b/feature/src/main/java/com/terning/feature/main/MainScreen.kt @@ -128,7 +128,9 @@ fun MainScreen( paddingValues = paddingValues, navHostController = navigator.navController ) - calendarNavGraph(navHostController = navigator.navController) + calendarNavGraph( + paddingValues = paddingValues, + navHostController = navigator.navController) searchNavGraph(navHostController = navigator.navController) signInNavGraph( paddingValues = paddingValues, diff --git a/feature/src/main/java/com/terning/feature/search/searchprocess/SearchProcessViewModel.kt b/feature/src/main/java/com/terning/feature/search/searchprocess/SearchProcessViewModel.kt index a36b01dcd..8f8028280 100644 --- a/feature/src/main/java/com/terning/feature/search/searchprocess/SearchProcessViewModel.kt +++ b/feature/src/main/java/com/terning/feature/search/searchprocess/SearchProcessViewModel.kt @@ -3,7 +3,7 @@ package com.terning.feature.search.searchprocess import androidx.compose.ui.graphics.Color import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.terning.domain.entity.CalendarScrapRequest +import com.terning.domain.entity.calendar.CalendarScrapRequest import com.terning.domain.entity.search.SearchResult import com.terning.domain.repository.ScrapRepository import com.terning.domain.repository.SearchRepository diff --git a/feature/src/main/res/drawable/ic_terning_calendar_empty.xml b/feature/src/main/res/drawable/ic_terning_calendar_empty.xml new file mode 100644 index 000000000..9f1e706fa --- /dev/null +++ b/feature/src/main/res/drawable/ic_terning_calendar_empty.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +