Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,11 @@ object DateTimeFormatter {

fun LocalTime.toIsoTimeString(): String = "${hour.pad2()}:${minute.pad2()}:${second.pad2()}"

/**
* @param: date 선택된 날짜
* @param: time 선택된 시간
* @return: LocalDate, LocalTime을 조합한 ISO8601 문자열
* */
Comment thread
dogmania marked this conversation as resolved.
fun formatIsoDateTime(
date: LocalDate,
time: LocalTime,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,14 @@ class ScheduleRepositoryImpl(
)
}

override suspend fun deleteScheduleAppResult(scheduleId: Long): AppResult<Unit> =
safeApiCall {
networkClient.requestOrThrow<Unit>(
method = HttpMethod.DELETE,
path = "/schedules/$scheduleId",
)
}

/**
* Local
* */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ interface ScheduleRepository {
isEnabled: Boolean,
): AppResult<Unit>

suspend fun deleteScheduleAppResult(scheduleId: Long): AppResult<Unit>

/**
* Local
* */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ sealed interface CalendarIntent : Intent {

data class DeleteHistory(
val scheduleId: Long,
val isPast: Boolean,
) : CalendarIntent
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.ondot.calendar.contract

import androidx.lifecycle.viewModelScope
import com.dh.ondot.presentation.ui.theme.ERROR_GET_SCHEDULE_LIST
import com.dh.ondot.presentation.ui.theme.SUCCESS_DELETE_SCHEDULE
import com.ondot.domain.model.enums.AlarmType
import com.ondot.domain.model.enums.MapProvider
import com.ondot.domain.model.enums.ToastType
Expand Down Expand Up @@ -101,7 +102,13 @@ class CalendarViewModel(
observeMapProvider()
}

is CalendarIntent.DeleteHistory -> deleteHistory(intent.scheduleId)
is CalendarIntent.DeleteHistory -> {
if (intent.isPast) {
deleteHistory(intent.scheduleId)
} else {
deleteSchedule(intent.scheduleId)
}
}
}
}

Expand Down Expand Up @@ -373,6 +380,71 @@ class CalendarViewModel(
)
}

// --------------------------------------------일정 삭제------------------------------------------------

private fun deleteSchedule(scheduleId: Long) {
val selectedDate = currentState.selectedDate
val previousSchedules = currentState.selectedDateSchedules
val previousItems = currentState.selectedDateScheduleItems
val previousSchedulesByDate = currentState.schedulesByDate

Comment thread
dogmania marked this conversation as resolved.
val targetSchedule =
previousSchedules.firstOrNull { it.scheduleId == scheduleId }
?: run {
logger.e { "일정을 찾을 수 없습니다. $scheduleId" }
return
}

val updatedSchedules = previousSchedules.filter { it.scheduleId != scheduleId }
val updatedItems = previousItems.filter { it.scheduleId != scheduleId }

val previousMarkers = previousSchedulesByDate[selectedDate].orEmpty()
val updatedMarkers = previousMarkers.filter { it.scheduleId != scheduleId }

val updatedSchedulesByDate =
previousSchedulesByDate.toMutableMap().apply {
if (updatedMarkers.isEmpty()) {
remove(selectedDate)
} else {
this[selectedDate] = updatedMarkers
}
}

cancelScheduleAlarms(targetSchedule)

reduce {
copy(
selectedDateSchedules = updatedSchedules,
selectedDateScheduleItems = updatedItems,
schedulesByDate = updatedSchedulesByDate,
)
}

launchResult(
block = { scheduleRepository.deleteScheduleAppResult(scheduleId) },
onSuccess = {
emitEffect(CalendarSideEffect.ShowToast(SUCCESS_DELETE_SCHEDULE, ToastType.INFO))
},
onError = {
applySchedules(
date = selectedDate,
schedules = previousSchedules,
)

reduce {
copy(
schedulesByDate = previousSchedulesByDate,
)
}

applyAlarmLocally(
schedule = targetSchedule,
enabled = targetSchedule.hasActiveAlarm,
)
},
)
}

/**--------------------------------------------기타 유틸-----------------------------------------------*/

private fun prepInfo(schedule: Schedule) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ fun CalendarRoute(
onMoveToNextMonth = { viewModel.dispatch(CalendarIntent.MoveToNextMonth) },
onToggleAlarm = { scheduleId, enabled -> viewModel.dispatch(CalendarIntent.ToggleAlarm(scheduleId, enabled)) },
onAddSchedule = navigateToCreateGeneralSchedule,
onDelete = { viewModel.dispatch(CalendarIntent.DeleteHistory(it)) },
onDelete = { id, isPast -> viewModel.dispatch(CalendarIntent.DeleteHistory(id, isPast)) },
)
}

Expand All @@ -97,7 +97,7 @@ private fun CalendarScreen(
onMoveToNextMonth: () -> Unit,
onToggleAlarm: (Long, Boolean) -> Unit,
onAddSchedule: () -> Unit,
onDelete: (Long) -> Unit,
onDelete: (Long, Boolean) -> Unit,
) {
val scope = rememberCoroutineScope()
val sheetState = rememberCalendarSheetState()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ fun CalendarBottomSheet(
schedules: List<CalendarScheduleItemUiModel>,
togglingScheduleIds: Set<Long> = emptySet(),
onToggleAlarm: (Long, Boolean) -> Unit = { _, _ -> },
onDelete: (Long) -> Unit = {},
onDelete: (Long, Boolean) -> Unit = { _, _ -> },
) {
Surface(
modifier = modifier,
Expand Down Expand Up @@ -123,7 +123,7 @@ fun CalendarBottomSheet(
schedules.forEach { item ->
SwipeableDeleteItem(
enabled = item.isPast,
onDelete = { onDelete(item.scheduleId) },
onDelete = { onDelete(item.scheduleId, item.isPast) },
) {
CalendarScheduleListItem(
item = item,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ fun CalendarDay(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(3.dp),
) {
cell.markers.take(2).forEach { marker ->
cell.markers.take(3).forEach { marker ->
ScheduleChip(
text = marker.title,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class EditScheduleViewModel(

@OptIn(ExperimentalTime::class)
fun saveSchedule() {
// 새로 설정된 약속 날짜, 시간을 조합한 Iso8601 문자열
val newDate =
DateTimeFormatter.formatIsoDateTime(
date =
Expand All @@ -82,7 +83,8 @@ class EditScheduleViewModel(
.map { it + 1 },
)

if (!newSchedule.preparationAlarm.enabled) cancelAlarm(newSchedule.preparationAlarm.alarmId)
// 변경된 데이터가 있을 수 있으므로 기존 알람 취소
cancelAlarms()
Comment thread
dogmania marked this conversation as resolved.

viewModelScope.launch {
scheduleRepository.editSchedule(uiState.value.scheduleId, newSchedule).collect {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.dh.ondot.presentation.ui.theme.ANDROID
import com.dh.ondot.presentation.ui.theme.CREATE_SCHEDULE
import com.dh.ondot.presentation.ui.theme.GENERAL_SCHEDULE_BOTTOM_SHEET_MATERIAL
import com.dh.ondot.presentation.ui.theme.GENERAL_SCHEDULE_BOTTOM_SHEET_MEDICINE
import com.dh.ondot.presentation.ui.theme.GENERAL_SCHEDULE_BOTTOM_SHEET_TITLE
import com.dh.ondot.presentation.ui.theme.OnDotTypo
import com.dh.ondot.presentation.ui.theme.WORD_CONFIRM
Expand All @@ -50,15 +49,13 @@ import com.ondot.designsystem.components.AlarmInfoItem
import com.ondot.designsystem.components.DateTimeInfoBar
import com.ondot.designsystem.components.OnDotBottomSheet
import com.ondot.designsystem.components.OnDotButton
import com.ondot.designsystem.components.OnDotCheckBox
import com.ondot.designsystem.components.OnDotText
import com.ondot.designsystem.components.RoundedTextField
import com.ondot.designsystem.components.RouteInputSection
import com.ondot.designsystem.components.TopBar
import com.ondot.designsystem.getPlatform
import com.ondot.designsystem.theme.OnDotColor.GradientGreenTop
import com.ondot.designsystem.theme.OnDotColor.Gray0
import com.ondot.designsystem.theme.OnDotColor.Gray200
import com.ondot.designsystem.theme.OnDotColor.Gray600
import com.ondot.designsystem.theme.OnDotColor.Gray800
import com.ondot.designsystem.theme.OnDotColor.Gray900
Expand Down Expand Up @@ -230,27 +227,6 @@ private fun BottomSheetContent(onCreateSchedule: (Boolean, String) -> Unit) {

Spacer(modifier = Modifier.height(20.dp))

Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
) {
OnDotCheckBox(
isChecked = isMedicineChecked,
onCheckedChange = { isMedicineChecked = !isMedicineChecked },
)

Spacer(modifier = Modifier.width(8.dp))

OnDotText(
text = GENERAL_SCHEDULE_BOTTOM_SHEET_MEDICINE,
style = OnDotTextStyle.BodyLargeR1,
color = Gray200,
modifier = Modifier.clickable { isMedicineChecked = !isMedicineChecked },
)
}

Spacer(modifier = Modifier.height(16.dp))

RoundedTextField(
value = input,
onValueChange = { input = it },
Expand Down
Loading