Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e4497b9
#79 [RENAME] CalculateTimeFromString 파일 rename
Eonji-sw Apr 4, 2025
0978b37
#79 [MOD] appointmentName 필드 추가
Eonji-sw Apr 4, 2025
cf69dcf
#79 [DEL] 불필요한 파일 제거
Eonji-sw Apr 4, 2025
c92ff89
#79 [FEAT] CalculateTimeFromLocalDate 구현
Eonji-sw Apr 4, 2025
f495fc5
#79 [MOD] onItemClick 로직 변경
Eonji-sw Apr 4, 2025
0810c6a
#79 [MOD] 필드 타입 변경
Eonji-sw Apr 4, 2025
e82fa1a
#79 [MOD] 필드 타입 변경
Eonji-sw Apr 4, 2025
5b82e22
#79 [MOD] 필드 타입 변경
Eonji-sw Apr 4, 2025
4e4956d
#79 [MOD] getOptionDetail 구현
Eonji-sw Apr 4, 2025
203f668
#79 [MOD] getOptionDetail 적용 및 필드 타입 변경
Eonji-sw Apr 4, 2025
4e2b0d1
Merge remote-tracking branch 'origin/develop' into feature/#79-calend…
Eonji-sw Apr 8, 2025
d1c751d
#79 [MOD] ktlint 적용
Eonji-sw Apr 8, 2025
a175893
#79 [MOD] ktlint 적용
Eonji-sw Apr 8, 2025
cdb41b4
#79 [FEAT] getConfirmedDetail, DataErrorDialog 적용
Eonji-sw Apr 8, 2025
8c9cf41
#79 [FEAT] ShowDataErrorDialog 구현
Eonji-sw Apr 8, 2025
e4ebb72
#79 [MOD] ConfirmedDetailEntity appointmentName 필드 추가
Eonji-sw Apr 8, 2025
7046b2c
#79 [MOD] ConfirmedDetailEntity appointmentName 필드 추가
Eonji-sw Apr 8, 2025
3cf55db
#79 [MOD] 시간 형식 변경
Eonji-sw Apr 8, 2025
b8e4f1a
#79 [MOD] 시간 형식 변경
Eonji-sw Apr 8, 2025
90c66c9
#79 [MOD] 시간 형식 변경
Eonji-sw Apr 8, 2025
1863ef4
#79 [MOD] ktlint 적용
Eonji-sw Apr 8, 2025
b14994f
#79 [MOD] ktlint 적용
Eonji-sw Apr 8, 2025
2d64327
#79 [MOD] ktlint 적용, getConfirmedDetail, DataErrorDialog 구현
Eonji-sw Apr 8, 2025
d3ab49b
#79 [MOD] GroupCreate name 조건 추가
Eonji-sw Apr 8, 2025
ab2bfe3
Merge remote-tracking branch 'origin/develop' into feature/#79-calend…
Eonji-sw Apr 9, 2025
e8a49ca
#79 [MOD] fold 적용
Eonji-sw Apr 10, 2025
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
@@ -0,0 +1,16 @@
package com.sopt.core.util.time

import java.time.LocalDate
import java.time.format.TextStyle
import java.util.Locale

class CalculateTimeFromLocalDate {
// ex) 1월 1일 (월)
fun formatLocalDateWithDay(localDate: LocalDate): String {
val month = localDate.monthValue
val day = localDate.dayOfMonth
val dayOfWeek = localDate.dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.KOREAN)

return "${month}${day}일 ($dayOfWeek)"
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.sopt.core.util
package com.sopt.core.util.time

import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.time.format.TextStyle
import java.util.Locale

class CalculateTime {
class CalculateTimeFromString {
// ex) 09/07
fun extractFullDateWithSlash(dateTime: String): String {
return parseDateTime(dateTime).toLocalDate().format(DateTimeFormatter.ofPattern("MM/dd"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import androidx.compose.ui.graphics.Color
import com.sopt.core.designsystem.theme.NoostakTheme
import com.sopt.core.type.AvailabilityLevel
import com.sopt.core.type.CellType
import com.sopt.core.util.CalculateTime
import com.sopt.core.util.time.CalculateTimeFromString
import com.sopt.domain.entity.AppointmentMembersInfoEntity
import com.sopt.domain.entity.TimeEntity

Expand Down Expand Up @@ -138,8 +138,8 @@ class TimeTable {
}

private fun formatDateTimeToCustomFormat(dateTime: String): String {
val dayOfWeek = CalculateTime().extractDayOfWeek(dateTime)
val date = CalculateTime().extractDateWithSlash(dateTime)
val dayOfWeek = CalculateTimeFromString().extractDayOfWeek(dateTime)
val date = CalculateTimeFromString().extractDateWithSlash(dateTime)
return "$dayOfWeek\n$date"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.sopt.domain.entity.IdentityEntity

fun ResponseGetOptionDetailDto.toAppointmentDetailEntity() = AppointmentDetailEntity(
myIdentity = myInfo?.toIdentityEntity() ?: IdentityEntity("unavailable", -1, "나"),
appointmentName = appointmentName,
date = appointmentTime.date,
startTime = appointmentTime.startTime,
endTime = appointmentTime.endTime,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ fun ResponseGetGroupConfirmedDetailDto.toConfirmedDetailEntity() = ConfirmedDeta
position = myInfo.position,
name = myInfo.name
),
appointmentName = appointmentName,
date = appointmentTime.date,
startTime = appointmentTime.startTime,
endTime = appointmentTime.endTime,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ package com.sopt.domain.entity

data class AppointmentDetailEntity(
val myIdentity: IdentityEntity,
val date: String,
val startTime: String,
val endTime: String,
val category: String,
val availableMembersCount: Int,
val appointmentName: String = "",
val date: String = "",
val startTime: String = "",
val endTime: String = "",
val category: String = "",
val availableMembersCount: Int = 0,
val availableMembers: List<String>,
val unavailableMembersCount: Int,
val unavailableMembersCount: Int = 0,
val unavailableMembers: List<String>
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.sopt.domain.entity

data class ConfirmedDetailEntity(
val myIdentity: IdentityEntity,
val appointmentName: String = "",
val date: String,
val startTime: String,
val endTime: String,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.sopt.domain.entity

import java.time.LocalDate

data class ScheduleEntity(
val groupId: Long = -1,
val date: String, // M월 D일 (E) - ex) 1월 13일 (월)
val date: LocalDate,
val scheduleList: List<CalendarAppointmentEntity>
)
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ import com.sopt.core.designsystem.theme.NoostakAndroidTheme
import com.sopt.core.designsystem.theme.NoostakTheme
import com.sopt.core.extension.showIf
import com.sopt.core.state.UiState
import com.sopt.core.util.CalculateTime
import com.sopt.core.util.RearrangeList
import com.sopt.core.util.time.CalculateTimeFromString
import com.sopt.domain.entity.AppointmentDetailEntity
import com.sopt.domain.entity.IdentityEntity
import com.sopt.presentation.R
Expand Down Expand Up @@ -104,7 +104,7 @@ fun AppointmentConfirmRoute(
)
}

else -> {}
else -> Unit
}

if (showErrorDialog.first) {
Expand All @@ -131,7 +131,7 @@ fun AppointmentConfirmScreen(
onConfirmButtonClick: (Long) -> Unit,
data: AppointmentDetailEntity
) {
val calculateTime = CalculateTime()
val calculateTime = CalculateTimeFromString()
val date = calculateTime.extractDateWithKorean(data.date)
val dayOfWeek = calculateTime.extractDayOfWeekWithBraces(data.date)
val startHour = calculateTime.extractHourWithZero(data.startTime)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ import com.sopt.core.designsystem.theme.NoostakAndroidTheme
import com.sopt.core.designsystem.theme.NoostakTheme
import com.sopt.core.extension.noRippleClickable
import com.sopt.core.extension.showIf
import com.sopt.core.util.CalculateTime
import com.sopt.core.util.RearrangeList
import com.sopt.core.util.time.CalculateTimeFromString
import com.sopt.domain.entity.IdentityEntity
import com.sopt.domain.entity.OptionEntity
import com.sopt.domain.entity.RecommendationPriorityEntity
Expand Down Expand Up @@ -114,7 +114,7 @@ fun RecommendationItem(
}
}
val (isLiked, likes) = likeState
val calculateTime = CalculateTime()
val calculateTime = CalculateTimeFromString()
val date = calculateTime.extractDateWithKorean(data.date)
val dayOfWeek = calculateTime.extractDayOfWeekWithBraces(data.date)
val startHour = calculateTime.extractHourWithZero(data.startTime)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.sopt.presentation.calendar

import android.annotation.SuppressLint
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
Expand All @@ -17,7 +18,10 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
Expand All @@ -32,15 +36,20 @@ import androidx.navigation.compose.rememberNavController
import com.sopt.core.designsystem.component.bottomsheet.NoostakBottomSheet
import com.sopt.core.designsystem.component.calendar.WeekDaysHeader
import com.sopt.core.designsystem.component.calendar.YearMonthHeader
import com.sopt.core.designsystem.component.dialog.NoostakDialog
import com.sopt.core.designsystem.component.topappbar.NoostakLogoAppBar
import com.sopt.core.designsystem.screen.NoostakLoadingScreen
import com.sopt.core.designsystem.theme.NoostakAndroidTheme
import com.sopt.core.designsystem.theme.NoostakTheme
import com.sopt.core.extension.getYearMonthByPage
import com.sopt.core.extension.initialPage
import com.sopt.core.extension.pageCount
import com.sopt.core.state.UiState
import com.sopt.core.type.DialogType
import com.sopt.domain.entity.CalendarAppointmentEntity
import com.sopt.domain.entity.CalendarSchedule
import com.sopt.domain.entity.GroupEntity
import com.sopt.domain.entity.ScheduleEntity
import com.sopt.presentation.R
import com.sopt.presentation.calendar.component.CalendarFloatingActionDialog
import com.sopt.presentation.calendar.component.CalendarGroup
Expand All @@ -49,6 +58,7 @@ import com.sopt.presentation.calendar.component.bottomsheet.ScheduleListScreen
import java.time.LocalDate
import java.time.YearMonth

@SuppressLint("StateFlowValueCalledInComposition")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CalendarRoute(
Expand All @@ -58,10 +68,14 @@ fun CalendarRoute(
navigateToGroupEnter: () -> Unit,
navigateToAppointmentCreate: (Long) -> Unit
) {
val navController = rememberNavController()

val getGroupsState by calendarViewModel.getGroupsState.collectAsStateWithLifecycle()
val getConfirmedDetailState by calendarViewModel.getConfirmedDetailState.collectAsStateWithLifecycle()

val showAddDialog by calendarViewModel.showAddDialog.collectAsStateWithLifecycle()
val showBottomSheet by calendarViewModel.showBottomSheet.collectAsStateWithLifecycle()
val navController = rememberNavController()
val showDataErrorDialog by calendarViewModel.showDataErrorDialog.collectAsStateWithLifecycle()

val scheduleMap by calendarViewModel.scheduleMap.collectAsStateWithLifecycle()

Expand All @@ -72,6 +86,9 @@ fun CalendarRoute(

val currentYearMonth by remember { derivedStateOf { getYearMonthByPage(pagerState.currentPage) } }

var clickDate by remember { mutableStateOf<LocalDate?>(null) }
var clickAppointmentId by remember { mutableLongStateOf(-1) }

LaunchedEffect(pagerState) {
snapshotFlow { pagerState.currentPage }
.collect { page ->
Expand All @@ -85,15 +102,31 @@ fun CalendarRoute(
is CalendarSideEffect.NavigateToGroupCreate -> navigateToGroupCreate()
is CalendarSideEffect.NavigateToGroupEnter -> navigateToGroupEnter()
is CalendarSideEffect.NavigateToAppointmentCreate -> navigateToAppointmentCreate(
calendarViewModel.getSelectedScheduleEntity().groupId
calendarViewModel.selectedGroupId.value ?: -1
)

is CalendarSideEffect.ShowAddDialog -> calendarViewModel.showAddDialog(true)
is CalendarSideEffect.ShowBottomSheet -> calendarViewModel.showBottomSheet(true)
is CalendarSideEffect.ShowDataErrorDialog -> calendarViewModel.showDataErrorDialog(
true
)
}
}
}

if (showDataErrorDialog) {
NoostakDialog(
dialogType = DialogType.DATA_FAILURE,
onClick = {
calendarViewModel.getConfirmedDetail(clickAppointmentId)
},
onDismissRequest = {
calendarViewModel.showDataErrorDialog(false)
navController.popBackStack()
}
)
}

if (showAddDialog) {
CalendarFloatingActionDialog(
onClick = { calendarViewModel.showAddDialog(false) },
Expand All @@ -117,30 +150,47 @@ fun CalendarRoute(
},
content = {
NavHost(navController, startDestination = SCHEDULE_LIST) {
composable(SCHEDULE_LIST) { backStackEntry ->
ScheduleListScreen(
data = calendarViewModel.getSelectedScheduleEntity(),
onItemClick = { schedule ->
backStackEntry.savedStateHandle[SCHEDULE] =
schedule.id // 바꿔야 함
navController.navigate(SCHEDULE_DETAIL)
},
onCreateAppointmentBtnClick = {
calendarViewModel.navigateToAppointmentCreate()
calendarViewModel.showBottomSheet(false)
}
)
composable(SCHEDULE_LIST) {
clickDate?.let { date ->
ScheduleListScreen(
data = ScheduleEntity(
groupId = calendarViewModel.selectedGroupId.value ?: -1,
date = date,
scheduleList = calendarViewModel.selectedDayAppointments.value.map {
CalendarAppointmentEntity(
id = it.id,
name = it.name,
category = it.category,
startTime = it.startTime,
endTime = it.endTime,
duration = it.duration,
date = it.date
)
}
),
onItemClick = { id ->
clickAppointmentId = id
calendarViewModel.getConfirmedDetail(clickAppointmentId)
navController.navigate(SCHEDULE_DETAIL)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: 빈 화면 위에 다이얼로그 뜨는 것보다 그룹 아이템이 보이는 상태에서 뜨는게 나을 것같아서 이렇게 수정해주쇼!!

Suggested change
navController.navigate(SCHEDULE_DETAIL)
when (getConfirmedDetailState) {
is UiState.Success -> {
navController.navigate(SCHEDULE_DETAIL)
}
else -> Unit
}

},
onCreateAppointmentBtnClick = {
calendarViewModel.navigateToAppointmentCreate()
calendarViewModel.showBottomSheet(false)
}
)
}
}
composable(SCHEDULE_DETAIL) {
val schedule =
navController.previousBackStackEntry?.savedStateHandle?.get<Long>(
SCHEDULE
)
schedule?.let { id ->
ScheduleDetailScreen(
data = calendarViewModel.mockScheduleDetail,
onBackBtnClick = { navController.popBackStack() }
)
when (getConfirmedDetailState) {
is UiState.Loading -> NoostakLoadingScreen()
is UiState.Success -> {
ScheduleDetailScreen(
data = (getConfirmedDetailState as UiState.Success).data,
onBackBtnClick = { navController.popBackStack() }
)
}

else -> Unit
}
}
}
Expand All @@ -157,6 +207,7 @@ fun CalendarRoute(
showAddDialog = showAddDialog,
onAddBtnClick = { calendarViewModel.showAddDialog(true) },
onItemClick = { clickedDate ->
clickDate = clickedDate
calendarViewModel.onDayClicked(clickedDate)
},
onGroupClick = { groupId ->
Expand Down Expand Up @@ -236,7 +287,6 @@ private fun CalendarContent(
}
}

const val SCHEDULE = "schedule"
const val SCHEDULE_LIST = "schedule_list"
const val SCHEDULE_DETAIL = "schedule_detail"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ sealed interface CalendarSideEffect {
data object NavigateToAppointmentCreate : CalendarSideEffect
data class ShowAddDialog(val show: Boolean) : CalendarSideEffect
data object ShowBottomSheet : CalendarSideEffect
data object ShowDataErrorDialog : CalendarSideEffect
}
Loading