Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
44b9b9d
Merge remote-tracking branch 'origin/feat/#26-calendar-view' into fea…
nhyeonii Jan 13, 2026
545f04b
[REF/#45] BaseResponse 서버 명세 맞춰 수정
nhyeonii Jan 13, 2026
cf2fe10
[FEAT/#45] CalendarMonthlyDto 구현
nhyeonii Jan 13, 2026
3678005
[FEAT/#45] CalendarMonthlyModel 구현
nhyeonii Jan 13, 2026
81e24fa
[FEAT/#45] CalendarSerivce 구현
nhyeonii Jan 13, 2026
d177a31
[DEL/#45] git keep 삭제
nhyeonii Jan 13, 2026
363dde1
[FEAT/#45] CalendarDataSource 구현
nhyeonii Jan 13, 2026
fce0c02
[FEAT/#45] CalendarMonthlyResponseModel 구현
nhyeonii Jan 13, 2026
20b678f
[FEAT/#45] CalendarRepository 구현
nhyeonii Jan 13, 2026
be7f19a
[FEAT/#45] CalendarService 구현
nhyeonii Jan 13, 2026
dae6b8c
[FEAT/#45] DataSourceModule 구현
nhyeonii Jan 13, 2026
cf391bd
[FEAT/#45] datasource, repository, service module 구현
nhyeonii Jan 13, 2026
b22ffad
[FEAT/#45] CalendarDaily 관련 DTO 구현
nhyeonii Jan 13, 2026
ecbab52
[FEAT/#45] CalendarDailyResponseModel 구현
nhyeonii Jan 13, 2026
f3736ec
[FEAT/#45] CalendarDataSource 구현
nhyeonii Jan 13, 2026
b849b04
[FEAT/#45] CalendarService 구현
nhyeonii Jan 13, 2026
c3a1eaa
[FEAT/#45] CalendarRepository 구현
nhyeonii Jan 13, 2026
e36dec5
[FEAT/#45] Calendar getCalendarDaily 뷰모델 연결
nhyeonii Jan 13, 2026
49b54e9
[CHORE/#45] Lint format
nhyeonii Jan 13, 2026
c8a3332
[REF/#45] CalendarMonthly api non - null로
nhyeonii Jan 14, 2026
04b095c
[FEAT/#45] CalendarDownTImeResponseDto 구현
nhyeonii Jan 14, 2026
7226ed5
[FEAT/#45] CalendarDownTimeResponse DTO, Model 구현
nhyeonii Jan 14, 2026
0133395
[FEAT/#45] CalendarDownTimeDataSource 구현
nhyeonii Jan 14, 2026
f3d1341
[FEAT/#45] CalendarDownTimeRepository 구현
nhyeonii Jan 14, 2026
c074b72
[FEAT/#45] CalendarService 구현
nhyeonii Jan 14, 2026
eed2dc1
[FEAT/#45] Calendar ViewModel api 연결
nhyeonii Jan 14, 2026
b184832
[REF/#45] procedureCountByDate non - null 적용
nhyeonii Jan 14, 2026
87fb189
[FEAT/#45] 뷰모델 로직 수정
nhyeonii Jan 14, 2026
7d7add4
[CHORE/#45] Lint format
nhyeonii Jan 14, 2026
7b7ec49
[FEAT/#51] 이전, 이후 달 선택 시 1일로 선택
nhyeonii Jan 14, 2026
f81ac76
[REF/#45] CalendarDownTimeDto 서버 규격 맞춰 수정
nhyeonii Jan 14, 2026
6905929
[REF/#45] downTimeDuration non - null 수정
nhyeonii Jan 14, 2026
9e2114d
[REF/#45] CalendarViewModel 로직 수정
nhyeonii Jan 14, 2026
bb09f2a
[REF/#45] loadMonthly Calendar 중복 호출 문제 해결
nhyeonii Jan 14, 2026
c998029
[REF/#45] 시술 카드 화면 깜빡임 개선
nhyeonii Jan 15, 2026
2a0358a
[CHORE/#45] 엔드포인트 수정
nhyeonii Jan 15, 2026
0a0b921
[REF/#45] 이벤트 클릭 조건 수정
nhyeonii Jan 15, 2026
7339e27
[REF/#45] 이벤트 클릭 조건 수정
nhyeonii Jan 15, 2026
72fc82b
Merge remote-tracking branch 'origin/develop' into feat/#45-calendar-…
nhyeonii Jan 15, 2026
30c8d3a
[CHORE/#45] Lint format
nhyeonii Jan 15, 2026
99bf2c8
[FEAT/#45] 월별 데이터 캐싱 구현
nhyeonii Jan 16, 2026
0983606
[FEAT/#45] 달별, 일별 데이터 캐싱
nhyeonii Jan 16, 2026
33409be
[REF/#45] sohee6989 리뷰 반영
nhyeonii Jan 16, 2026
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
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import kotlinx.serialization.Serializable
@Serializable
data class BaseResponse<T>(
@SerialName("code")
val code: Int,
val code: String,
Comment thread
nhyeonii marked this conversation as resolved.
@SerialName("message")
val message: String,
@SerialName("data")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.cherrish.android.core.util

import java.time.DayOfWeek
import java.time.LocalDateTime

fun DayOfWeek.daysUntil(other: DayOfWeek) = (other.value - value + 7) % 7

fun formatProcedureDay(scheduledAt: String): String {
val dateTime = LocalDateTime.parse(scheduledAt)
val month = dateTime.month.value
val day = dateTime.dayOfMonth
val dayOfWeek = dateTime.dayOfWeek.toKoreanName()
return "${month}월 ${day}일 $dayOfWeek"
}

fun DayOfWeek.toKoreanName(): String = when (this) {
DayOfWeek.MONDAY -> "월요일"
DayOfWeek.TUESDAY -> "화요일"
DayOfWeek.WEDNESDAY -> "수요일"
DayOfWeek.THURSDAY -> "목요일"
DayOfWeek.FRIDAY -> "금요일"
DayOfWeek.SATURDAY -> "토요일"
DayOfWeek.SUNDAY -> "일요일"
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.cherrish.android.data.di

import com.cherrish.android.data.remote.datasource.DummyDataSource
import com.cherrish.android.data.remote.datasourceimpl.DummyDataSourceImpl
import com.cherrish.android.data.remote.datasource.CalendarDataSource
import com.cherrish.android.data.remote.datasourceimpl.CalendarDataSourceImpl
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
Expand All @@ -13,7 +13,7 @@ import javax.inject.Singleton
abstract class DataSourceModule {
@Binds
@Singleton
abstract fun bindDummyDataSource(
dummyDataSourceImpl: DummyDataSourceImpl
): DummyDataSource
abstract fun bindCalendarDataSource(
calendarDataSourceImpl: CalendarDataSourceImpl
): CalendarDataSource
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.cherrish.android.data.di

import com.cherrish.android.data.repository.DummyRepository
import com.cherrish.android.data.repositoryimpl.DummyRepositoryImpl
import com.cherrish.android.data.repository.CalendarRepository
import com.cherrish.android.data.repositoryimpl.CalendarRepositoryImpl
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
Expand All @@ -13,7 +13,7 @@ import javax.inject.Singleton
abstract class RepositoryModule {
@Binds
@Singleton
abstract fun bindDummyRepository(
dummyRepositoryImpl: DummyRepositoryImpl
): DummyRepository
abstract fun bindCalendarRepository(
calendarRepositoryImpl: CalendarRepositoryImpl
): CalendarRepository
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.cherrish.android.data.di

import com.cherrish.android.data.remote.service.DummyService
import com.cherrish.android.data.remote.service.CalendarService
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand All @@ -13,7 +13,7 @@ import retrofit2.Retrofit
object ServiceModule {
@Provides
@Singleton
fun provideDummyService(
fun provideCalendarService(
retrofit: Retrofit
): DummyService = retrofit.create(DummyService::class.java)
): CalendarService = retrofit.create(CalendarService::class.java)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.cherrish.android.data.model

import com.cherrish.android.data.remote.dto.response.CalendarDailyResponseDto
import com.cherrish.android.data.remote.dto.response.EventDto

data class CalendarDailyResponseModel(
val eventCount: Int,
val events: List<EventModel>
)

data class EventModel(
val type: String,
val userProcedureId: Long,
val procedureId: Long,
val name: String,
val scheduledAt: String,
val downtimeDays: Int
)

fun CalendarDailyResponseDto.toModel() = CalendarDailyResponseModel(
eventCount = this.eventCount,
events = this.events.map { it.toModel() }
)

fun EventDto.toModel() = EventModel(
type = this.type,
userProcedureId = this.userProcedureId,
procedureId = this.procedureId,
name = this.name,
scheduledAt = this.scheduledAt,
downtimeDays = this.downtimeDays
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.cherrish.android.data.model

import com.cherrish.android.data.remote.dto.response.CalendarDownTimeResponseDto

data class CalendarDownTimeResponseModel(
val userProcedureId: Long,
val scheduledAt: String,
val downtimeDays: Int,
val sensitiveDays: List<String>,
val cautionDays: List<String>,
val recoveryDays: List<String>
)

fun CalendarDownTimeResponseDto.toModel() = CalendarDownTimeResponseModel(
userProcedureId = this.userProcedureId,
scheduledAt = this.scheduledAt,
downtimeDays = this.downtimeDays,
sensitiveDays = this.sensitiveDays,
cautionDays = this.cautionDays,
recoveryDays = this.recoveryDays
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.cherrish.android.data.model

import com.cherrish.android.data.remote.dto.request.CalendarMonthlyRequestDto

data class CalendarMonthlyRequestModel(
val year: Int,
val month: Int
)

fun CalendarMonthlyRequestModel.toDto() = CalendarMonthlyRequestDto(
year = this.year,
month = this.month
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.cherrish.android.data.model

import com.cherrish.android.data.remote.dto.response.CalendarMonthlyResponseDto

data class CalendarMonthlyResponseModel(
val dailyProcedureCounts: Map<Int, Long>
)

fun CalendarMonthlyResponseDto.toModel() = CalendarMonthlyResponseModel(
dailyProcedureCounts = this.dailyProcedureCounts
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.cherrish.android.data.remote.datasource

import com.cherrish.android.core.network.BaseResponse
import com.cherrish.android.data.remote.dto.response.CalendarDailyResponseDto
import com.cherrish.android.data.remote.dto.response.CalendarDownTimeResponseDto
import com.cherrish.android.data.remote.dto.response.CalendarMonthlyResponseDto

interface CalendarDataSource {
suspend fun getCalendarMonthly(year: Int, month: Int): BaseResponse<CalendarMonthlyResponseDto>
suspend fun getCalendarDaily(date: String): BaseResponse<CalendarDailyResponseDto>
suspend fun getCalendarEventDowntime(id: Long): BaseResponse<CalendarDownTimeResponseDto>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.cherrish.android.data.remote.datasourceimpl

import com.cherrish.android.core.network.BaseResponse
import com.cherrish.android.data.remote.datasource.CalendarDataSource
import com.cherrish.android.data.remote.dto.response.CalendarDailyResponseDto
import com.cherrish.android.data.remote.dto.response.CalendarDownTimeResponseDto
import com.cherrish.android.data.remote.dto.response.CalendarMonthlyResponseDto
import com.cherrish.android.data.remote.service.CalendarService
import javax.inject.Inject

class CalendarDataSourceImpl @Inject constructor(
private val calendarService: CalendarService
) : CalendarDataSource {
override suspend fun getCalendarMonthly(
year: Int,
month: Int
): BaseResponse<CalendarMonthlyResponseDto> =
calendarService.getCalendarMonthly(year = year, month = month)

override suspend fun getCalendarDaily(
date: String
): BaseResponse<CalendarDailyResponseDto> =
calendarService.getCalendarDaily(date = date)

override suspend fun getCalendarEventDowntime(
id: Long
): BaseResponse<CalendarDownTimeResponseDto> =
calendarService.getCalendarEventDowntime(id = id)
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.cherrish.android.data.remote.dto.request

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class CalendarDailyRequestDto(
@SerialName("date")
val date: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.cherrish.android.data.remote.dto.request

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class CalendarMonthlyRequestDto(
@SerialName("year")
val year: Int,
@SerialName("month")
val month: Int
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.cherrish.android.data.remote.dto.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class CalendarDailyResponseDto(
@SerialName("eventCount")
val eventCount: Int,
@SerialName("events")
val events: List<EventDto>
)

@Serializable
data class EventDto(
@SerialName("type")
val type: String,
@SerialName("userProcedureId")
val userProcedureId: Long,
@SerialName("procedureId")
val procedureId: Long,
@SerialName("name")
val name: String,
@SerialName("scheduledAt")
val scheduledAt: String,
@SerialName("downtimeDays")
val downtimeDays: Int
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.cherrish.android.data.remote.dto.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class CalendarDownTimeResponseDto(
@SerialName("userProcedureId")
val userProcedureId: Long,
@SerialName("scheduledAt")
val scheduledAt: String,
@SerialName("downtimeDays")
val downtimeDays: Int,
@SerialName("sensitiveDays")
val sensitiveDays: List<String>,
@SerialName("cautionDays")
val cautionDays: List<String>,
@SerialName("recoveryDays")
val recoveryDays: List<String>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.cherrish.android.data.remote.dto.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class CalendarMonthlyResponseDto(
@SerialName("dailyProcedureCounts")
val dailyProcedureCounts: Map<Int, Long>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.cherrish.android.data.remote.service

import com.cherrish.android.core.network.BaseResponse
import com.cherrish.android.data.remote.dto.response.CalendarDailyResponseDto
import com.cherrish.android.data.remote.dto.response.CalendarDownTimeResponseDto
import com.cherrish.android.data.remote.dto.response.CalendarMonthlyResponseDto
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Query

interface CalendarService {
@GET("api/calendar/monthly")
suspend fun getCalendarMonthly(
@Query("year") year: Int,
@Query("month") month: Int
): BaseResponse<CalendarMonthlyResponseDto>

@GET("api/calendar/daily")
suspend fun getCalendarDaily(
@Query("date") date: String
): BaseResponse<CalendarDailyResponseDto>

@GET("api/calendar/events/{id}/downtime")
suspend fun getCalendarEventDowntime(
@Path("id") id: Long
): BaseResponse<CalendarDownTimeResponseDto>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.cherrish.android.data.repository

import com.cherrish.android.data.model.CalendarDailyResponseModel
import com.cherrish.android.data.model.CalendarDownTimeResponseModel
import com.cherrish.android.data.model.CalendarMonthlyResponseModel

interface CalendarRepository {
suspend fun getCalendarMonthly(
year: Int,
month: Int
): Result<CalendarMonthlyResponseModel>

suspend fun getCalendarDaily(
date: String
): Result<CalendarDailyResponseModel>

suspend fun getCalendarEventDowntime(
id: Long
): Result<CalendarDownTimeResponseModel>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.cherrish.android.data.repositoryimpl

import com.cherrish.android.core.util.suspendRunCatching
import com.cherrish.android.data.model.CalendarDailyResponseModel
import com.cherrish.android.data.model.CalendarDownTimeResponseModel
import com.cherrish.android.data.model.CalendarMonthlyResponseModel
import com.cherrish.android.data.model.toModel
import com.cherrish.android.data.remote.datasource.CalendarDataSource
import com.cherrish.android.data.repository.CalendarRepository
import javax.inject.Inject

class CalendarRepositoryImpl @Inject constructor(
private val calendarDataSource: CalendarDataSource
) : CalendarRepository {
override suspend fun getCalendarMonthly(
year: Int,
month: Int
): Result<CalendarMonthlyResponseModel> =
suspendRunCatching {
calendarDataSource.getCalendarMonthly(year = year, month = month).data!!.toModel()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: (단순 궁금) data!! 사용은 NullPointerException 위험이 있다는데 괜찮은가용~/!?!?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

data!! 사용 시 NPE 가능성은 잇지용 ~~ 다만 앱 크래시는 안 나고, 에러 흐름은 통제할 수 잇어 이런식으로 사용했엉요 ! 해당 API는 스펙상 성공 응답일 경우 data가 항상 내려오도록 보장되어 있고 null인 경우는 서버 계약 위반 또는 비정상 응답으로 판단하고 있답니닿ㅎㅎㅎ 그래서 suspendRunCatching을 통해 실패로 감싸 상위 레이어에서 공통 에러 처리하도록 의도햇어요 !! 그냥 runCatching이 아니라 suspendRunCatching util 함수를 사용하는 이유랍니도 !

}

override suspend fun getCalendarDaily(date: String): Result<CalendarDailyResponseModel> =
suspendRunCatching {
calendarDataSource.getCalendarDaily(date = date).data!!.toModel()
}

override suspend fun getCalendarEventDowntime(id: Long): Result<CalendarDownTimeResponseModel> =
suspendRunCatching {
calendarDataSource.getCalendarEventDowntime(id = id).data!!.toModel()
}
Comment thread
nhyeonii marked this conversation as resolved.
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ fun CalendarRoute(
CalendarScreen(
uiState = state.data,
paddingValues = paddingValues,
onMonthChange = viewModel::onMonthChanged,
onMonthChange = viewModel::onMonthChange,
onDateClick = viewModel::onDateClick,
onEventClick = viewModel::onEventClick,
onAddButtonClick = { /*TODO: 시술 선택 플로우로 이동*/ }
Expand Down
Loading