diff --git a/.gitignore b/.gitignore index 231cde62..094710bb 100644 --- a/.gitignore +++ b/.gitignore @@ -166,4 +166,5 @@ google-services.json # End of https://www.gitignore.io/api/kotlin,androidstudio /app/keystore -/app/mission-mate-keystore.jks \ No newline at end of file +/app/mission-mate-keystore.jks +/.idea/kotlinc.xml diff --git a/core/data/src/main/java/com/goalpanzi/mission_mate/core/data/di/DataModule.kt b/core/data/src/main/java/com/goalpanzi/mission_mate/core/data/di/DataModule.kt index cd69468a..caaad2fd 100644 --- a/core/data/src/main/java/com/goalpanzi/mission_mate/core/data/di/DataModule.kt +++ b/core/data/src/main/java/com/goalpanzi/mission_mate/core/data/di/DataModule.kt @@ -1,8 +1,10 @@ package com.goalpanzi.mission_mate.core.data.di import com.goalpanzi.mission_mate.core.data.repository.LoginRepositoryImpl +import com.goalpanzi.mission_mate.core.data.repository.OnboardingRepositoryImpl import com.goalpanzi.mission_mate.core.data.repository.ProfileRepositoryImpl import com.goalpanzi.mission_mate.core.domain.repository.LoginRepository +import com.goalpanzi.mission_mate.core.domain.repository.OnboardingRepository import com.goalpanzi.mission_mate.core.domain.repository.ProfileRepository import dagger.Binds import dagger.Module @@ -18,4 +20,7 @@ internal abstract class DataModule { @Binds abstract fun bindProfileRepository(impl: ProfileRepositoryImpl): ProfileRepository + + @Binds + abstract fun bindOnboardingRepository(impl: OnboardingRepositoryImpl): OnboardingRepository } \ No newline at end of file diff --git a/core/data/src/main/java/com/goalpanzi/mission_mate/core/data/repository/OnboardingRepositoryImpl.kt b/core/data/src/main/java/com/goalpanzi/mission_mate/core/data/repository/OnboardingRepositoryImpl.kt new file mode 100644 index 00000000..97542bc1 --- /dev/null +++ b/core/data/src/main/java/com/goalpanzi/mission_mate/core/data/repository/OnboardingRepositoryImpl.kt @@ -0,0 +1,16 @@ +package com.goalpanzi.mission_mate.core.data.repository + +import com.goalpanzi.mission_mate.core.domain.repository.OnboardingRepository +import com.goalpanzi.mission_mate.core.network.service.OnboardingService +import com.luckyoct.core.model.base.NetworkResult +import com.luckyoct.core.model.request.CreateMissionRequest +import com.luckyoct.core.model.response.MissionDetailResponse +import javax.inject.Inject + +class OnboardingRepositoryImpl @Inject constructor( + private val onboardingService: OnboardingService +) : OnboardingRepository { + override suspend fun createMission(missionRequest: CreateMissionRequest): NetworkResult = handleResult { + onboardingService.createMission(missionRequest) + } +} \ No newline at end of file diff --git a/core/domain/src/main/java/com/goalpanzi/mission_mate/core/domain/repository/OnboardingRepository.kt b/core/domain/src/main/java/com/goalpanzi/mission_mate/core/domain/repository/OnboardingRepository.kt new file mode 100644 index 00000000..dbcdbeb8 --- /dev/null +++ b/core/domain/src/main/java/com/goalpanzi/mission_mate/core/domain/repository/OnboardingRepository.kt @@ -0,0 +1,13 @@ +package com.goalpanzi.mission_mate.core.domain.repository + +import com.goalpanzi.mission_mate.core.network.ResultHandler +import com.luckyoct.core.model.base.NetworkResult +import com.luckyoct.core.model.request.CreateMissionRequest +import com.luckyoct.core.model.response.MissionDetailResponse + +interface OnboardingRepository : ResultHandler { + suspend fun createMission( + missionRequest: CreateMissionRequest + ): NetworkResult + +} \ No newline at end of file diff --git a/core/domain/src/main/java/com/goalpanzi/mission_mate/core/domain/usecase/CreateMissionUseCase.kt b/core/domain/src/main/java/com/goalpanzi/mission_mate/core/domain/usecase/CreateMissionUseCase.kt new file mode 100644 index 00000000..89e3ab37 --- /dev/null +++ b/core/domain/src/main/java/com/goalpanzi/mission_mate/core/domain/usecase/CreateMissionUseCase.kt @@ -0,0 +1,19 @@ +package com.goalpanzi.mission_mate.core.domain.usecase + +import com.goalpanzi.mission_mate.core.domain.repository.OnboardingRepository +import com.luckyoct.core.model.base.NetworkResult +import com.luckyoct.core.model.request.CreateMissionRequest +import com.luckyoct.core.model.response.MissionDetailResponse +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import javax.inject.Inject + +class CreateMissionUseCase @Inject constructor( + private val onboardingRepository: OnboardingRepository +) { + operator fun invoke( + createMissionRequest : CreateMissionRequest + ): Flow> = flow { + emit(onboardingRepository.createMission(createMissionRequest)) + } +} \ No newline at end of file diff --git a/core/model/src/main/java/com/luckyoct/core/model/request/CreateMissionRequest.kt b/core/model/src/main/java/com/luckyoct/core/model/request/CreateMissionRequest.kt new file mode 100644 index 00000000..5d8bacee --- /dev/null +++ b/core/model/src/main/java/com/luckyoct/core/model/request/CreateMissionRequest.kt @@ -0,0 +1,13 @@ +package com.luckyoct.core.model.request + +import kotlinx.serialization.Serializable + +@Serializable +data class CreateMissionRequest( + val description : String, + val missionStartDate : String, + val missionEndDate : String, + val timeOfDay : String, + val missionDays : List, + val boardCount : Int +) \ No newline at end of file diff --git a/core/model/src/main/java/com/luckyoct/core/model/response/MissionDetailResponse.kt b/core/model/src/main/java/com/luckyoct/core/model/response/MissionDetailResponse.kt new file mode 100644 index 00000000..50bd5361 --- /dev/null +++ b/core/model/src/main/java/com/luckyoct/core/model/response/MissionDetailResponse.kt @@ -0,0 +1,16 @@ +package com.luckyoct.core.model.response + +import kotlinx.serialization.Serializable + +@Serializable +data class MissionDetailResponse( + val missionId : Long, + val hostMemberId : Long, + val description : String, + val missionStartDate : String, + val missionEndDate : String, + val timeOfDay : String, + val missionDays : List, + val boardCount : Int, + val invitationCode : String +) \ No newline at end of file diff --git a/core/network/src/main/java/com/goalpanzi/mission_mate/core/network/di/ServiceModule.kt b/core/network/src/main/java/com/goalpanzi/mission_mate/core/network/di/ServiceModule.kt index a6153a67..48d11318 100644 --- a/core/network/src/main/java/com/goalpanzi/mission_mate/core/network/di/ServiceModule.kt +++ b/core/network/src/main/java/com/goalpanzi/mission_mate/core/network/di/ServiceModule.kt @@ -1,6 +1,7 @@ package com.goalpanzi.mission_mate.core.network.di import com.goalpanzi.mission_mate.core.network.service.LoginService +import com.goalpanzi.mission_mate.core.network.service.OnboardingService import com.goalpanzi.mission_mate.core.network.service.ProfileService import dagger.Module import dagger.Provides @@ -24,4 +25,10 @@ object ServiceModule { fun provideProfileService(retrofit: Retrofit): ProfileService { return retrofit.create(ProfileService::class.java) } + + @Provides + @Singleton + fun provideOnboardingService(retrofit: Retrofit): OnboardingService { + return retrofit.create(OnboardingService::class.java) + } } \ No newline at end of file diff --git a/core/network/src/main/java/com/goalpanzi/mission_mate/core/network/service/OnboardingService.kt b/core/network/src/main/java/com/goalpanzi/mission_mate/core/network/service/OnboardingService.kt new file mode 100644 index 00000000..ff94b45c --- /dev/null +++ b/core/network/src/main/java/com/goalpanzi/mission_mate/core/network/service/OnboardingService.kt @@ -0,0 +1,14 @@ +package com.goalpanzi.mission_mate.core.network.service + +import com.luckyoct.core.model.request.CreateMissionRequest +import com.luckyoct.core.model.response.MissionDetailResponse +import retrofit2.Response +import retrofit2.http.Body +import retrofit2.http.POST + +interface OnboardingService { + @POST("/api/missions") + suspend fun createMission( + @Body request: CreateMissionRequest + ): Response +} \ No newline at end of file diff --git a/feature/onboarding/build.gradle.kts b/feature/onboarding/build.gradle.kts index 9e30fb5f..de7ef489 100644 --- a/feature/onboarding/build.gradle.kts +++ b/feature/onboarding/build.gradle.kts @@ -67,4 +67,6 @@ dependencies { implementation(project(":core:designsystem")) implementation(project(":core:navigation")) + implementation(project(":core:domain")) + implementation(project(":core:model")) } \ No newline at end of file diff --git a/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/model/BoardSetupResult.kt b/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/model/BoardSetupResult.kt new file mode 100644 index 00000000..9a4c2d1f --- /dev/null +++ b/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/model/BoardSetupResult.kt @@ -0,0 +1,8 @@ +package com.goalpanzi.mission_mate.feature.onboarding.model + +import com.luckyoct.core.model.response.MissionDetailResponse + +sealed class BoardSetupResult { + data class Success(val data : MissionDetailResponse) : BoardSetupResult() + data class Error(val message : String) : BoardSetupResult() +} \ No newline at end of file diff --git a/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/model/VerificationTimeType.kt b/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/model/VerificationTimeType.kt index f042ca25..71b9ebc0 100644 --- a/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/model/VerificationTimeType.kt +++ b/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/model/VerificationTimeType.kt @@ -6,7 +6,7 @@ import com.goalpanzi.mission_mate.feature.onboarding.R enum class VerificationTimeType( @StringRes val titleId : Int ) { - Am(R.string.onboarding_board_setup_verification_time_input_content_am), - Pm(R.string.onboarding_board_setup_verification_time_input_content_pm), - All(R.string.onboarding_board_setup_verification_time_input_content_all) + MORNING(R.string.onboarding_board_setup_verification_time_input_content_am), + AFTERNOON(R.string.onboarding_board_setup_verification_time_input_content_pm), + EVERYDAY(R.string.onboarding_board_setup_verification_time_input_content_all) } \ No newline at end of file diff --git a/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/screen/boardsetup/BoardSetupScreen.kt b/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/screen/boardsetup/BoardSetupScreen.kt index b5cd31de..2c07a864 100644 --- a/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/screen/boardsetup/BoardSetupScreen.kt +++ b/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/screen/boardsetup/BoardSetupScreen.kt @@ -1,5 +1,6 @@ package com.goalpanzi.mission_mate.feature.onboarding.screen.boardsetup +import android.widget.Toast import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope @@ -13,7 +14,6 @@ import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.rememberPagerState -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -22,6 +22,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.text.font.FontWeight @@ -37,6 +38,7 @@ import com.goalpanzi.mission_mate.core.designsystem.theme.MissionMateTypography import com.goalpanzi.mission_mate.feature.onboarding.R import com.goalpanzi.mission_mate.feature.onboarding.component.BoardSetupNavigationBar import com.goalpanzi.mission_mate.feature.onboarding.component.DatePickerDialog +import com.goalpanzi.mission_mate.feature.onboarding.model.BoardSetupResult import com.goalpanzi.mission_mate.feature.onboarding.model.VerificationTimeType import com.goalpanzi.mission_mate.feature.onboarding.screen.boardsetup.BoardSetupViewModel.Companion.BoardSetupStep import com.goalpanzi.mission_mate.feature.onboarding.util.DateUtils.dateToString @@ -51,6 +53,7 @@ fun BoardSetupRoute( onBackClick: () -> Unit, viewModel: BoardSetupViewModel = hiltViewModel() ) { + val context = LocalContext.current val keyboardController = LocalSoftwareKeyboardController.current val localFocusManager = LocalFocusManager.current val pagerState = rememberPagerState { BoardSetupStep.entries.size } @@ -103,8 +106,16 @@ fun BoardSetupRoute( } LaunchedEffect(key1 = Unit) { - viewModel.setupSuccessEvent.collect { - onSuccess() + viewModel.setupEvent.collect { event -> + when(event){ + is BoardSetupResult.Success -> { + onSuccess() + } + is BoardSetupResult.Error -> { + Toast.makeText(context, event.message,Toast.LENGTH_SHORT).show() + } + } + } } diff --git a/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/screen/boardsetup/BoardSetupSuccessScreen.kt b/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/screen/boardsetup/BoardSetupSuccessScreen.kt index a7441d76..bf90df9c 100644 --- a/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/screen/boardsetup/BoardSetupSuccessScreen.kt +++ b/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/screen/boardsetup/BoardSetupSuccessScreen.kt @@ -1,10 +1,13 @@ package com.goalpanzi.mission_mate.feature.onboarding.screen.boardsetup +import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement 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.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.wrapContentHeight @@ -13,8 +16,10 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.goalpanzi.mission_mate.core.designsystem.component.MissionMateButtonType import com.goalpanzi.mission_mate.core.designsystem.component.MissionMateTextButton @@ -31,49 +36,84 @@ fun BoardSetupSuccessScreen( onClickStart: () -> Unit, modifier: Modifier = Modifier ) { - Column( - modifier = modifier - .fillMaxWidth() - .background(ColorWhite_FFFFFFFF) - .padding(horizontal = 14.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(12.dp) + Box( + modifier = modifier.background(ColorWhite_FFFFFFFF) ) { - Text( - modifier = Modifier.statusBarsPadding().padding(top = 60.dp), - text = stringResource(id = R.string.onboarding_board_setup_success_title), - style = MissionMateTypography.heading_sm_bold, - color = ColorGray2_FF4F505C - ) - - Text( - text = stringResource(id = R.string.onboarding_board_setup_success_description), - style = MissionMateTypography.title_xl_regular, - color = ColorGray3_FF727484, - textAlign = TextAlign.Center - ) - Box( + Image( modifier = Modifier .fillMaxWidth() - .weight(1f), - contentAlignment = Alignment.Center + .wrapContentHeight(), + painter = painterResource(id = com.goalpanzi.mission_mate.core.designsystem.R.drawable.background_jeju), + contentDescription = null, + contentScale = ContentScale.FillWidth + ) + Column( + modifier = modifier + .fillMaxWidth() + .statusBarsPadding() + .navigationBarsPadding() + .padding(horizontal = 14.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(12.dp) ) { - StableImage( + Text( + modifier = Modifier + .statusBarsPadding() + .padding(top = 48.dp), + text = stringResource(id = R.string.onboarding_board_setup_success_title), + style = MissionMateTypography.heading_sm_bold, + color = ColorGray1_FF404249 + ) + + Box( modifier = Modifier + .fillMaxWidth() + .weight(1f), + contentAlignment = Alignment.Center + ) { + StableImage( + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight(), + drawableResId = com.goalpanzi.mission_mate.core.designsystem.R.drawable.image_jeju_success, + contentScale = ContentScale.FillWidth + ) + } + Column( + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = stringResource(id = R.string.onboarding_board_setup_success_description_top), + style = MissionMateTypography.title_xl_bold, + color = ColorGray3_FF727484, + textAlign = TextAlign.Center + ) + Text( + text = stringResource(id = R.string.onboarding_board_setup_success_description_bottom), + style = MissionMateTypography.title_xl_regular, + color = ColorGray3_FF727484, + textAlign = TextAlign.Center + ) + } + MissionMateTextButton( + modifier = Modifier + .padding(bottom = 36.dp, start = 10.dp, end = 10.dp, top = 71.dp) .fillMaxWidth() .wrapContentHeight(), - drawableResId = com.goalpanzi.mission_mate.core.designsystem.R.drawable.image_jeju_success, - contentScale = ContentScale.FillWidth + buttonType = MissionMateButtonType.ACTIVE, + textId = R.string.start, + onClick = onClickStart ) } - MissionMateTextButton( - modifier = Modifier - .padding(vertical = 36.dp, horizontal = 10.dp) - .fillMaxWidth() - .wrapContentHeight(), - buttonType = MissionMateButtonType.ACTIVE, - textId = R.string.start, - onClick = onClickStart - ) } + +} + +@Preview +@Composable +fun PreviewBoardSetupSuccessScreen(){ + BoardSetupSuccessScreen( + onClickStart = {}, + modifier = Modifier.fillMaxSize() + ) } \ No newline at end of file diff --git a/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/screen/boardsetup/BoardSetupViewModel.kt b/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/screen/boardsetup/BoardSetupViewModel.kt index da343c6b..4d3157e1 100644 --- a/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/screen/boardsetup/BoardSetupViewModel.kt +++ b/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/screen/boardsetup/BoardSetupViewModel.kt @@ -6,9 +6,15 @@ import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshotFlow import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.goalpanzi.mission_mate.core.domain.usecase.CreateMissionUseCase +import com.goalpanzi.mission_mate.feature.onboarding.model.BoardSetupResult import com.goalpanzi.mission_mate.feature.onboarding.model.VerificationTimeType +import com.goalpanzi.mission_mate.feature.onboarding.util.DateUtils.filterDatesByDayOfWeek +import com.goalpanzi.mission_mate.feature.onboarding.util.DateUtils.formatLocalDateToString import com.goalpanzi.mission_mate.feature.onboarding.util.DateUtils.isDifferenceTargetDaysOrMore import com.goalpanzi.mission_mate.feature.onboarding.util.DateUtils.longToLocalDate +import com.luckyoct.core.model.base.NetworkResult +import com.luckyoct.core.model.request.CreateMissionRequest import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow @@ -27,11 +33,11 @@ import javax.inject.Inject @HiltViewModel class BoardSetupViewModel @Inject constructor( - + private val createMissionUseCase : CreateMissionUseCase ) : ViewModel() { - private val _setupSuccessEvent = MutableSharedFlow() - val setupSuccessEvent: SharedFlow = _setupSuccessEvent.asSharedFlow() + private val _setupEvent = MutableSharedFlow() + val setupEvent: SharedFlow = _setupEvent.asSharedFlow() private val _currentStep = MutableStateFlow(BoardSetupStep.MISSION) val currentStep: StateFlow = _currentStep.asStateFlow() @@ -104,7 +110,7 @@ class BoardSetupViewModel @Inject constructor( BoardSetupStep.entries[currentStep.value.ordinal + 1] ) } else if (currentStep.value == BoardSetupStep.VERIFICATION_TIME) { - _setupSuccessEvent.emit(Unit) + createMission() } } } @@ -155,6 +161,36 @@ class BoardSetupViewModel @Inject constructor( } } + private suspend fun createMission(){ + val timeOfDay = selectedVerificationTimeType.value?.name + val startDate = startDate.value + val endDate = endDate.value + if(timeOfDay == null || startDate == null || endDate == null){ + _setupEvent.emit(BoardSetupResult.Error("Board Setup is Failed")) + return + } + + createMissionUseCase( + CreateMissionRequest( + description = missionTitle, + missionStartDate = formatLocalDateToString(startDate), + missionEndDate = formatLocalDateToString(endDate), + missionDays = selectedDays.value.map { it.name }, + timeOfDay = timeOfDay, + boardCount = filterDatesByDayOfWeek(startDate, endDate, selectedDays.value) + ) + ).collect { result -> + when(result){ + is NetworkResult.Success -> { + _setupEvent.emit(BoardSetupResult.Success(result.data)) + } + else -> { + _setupEvent.emit(BoardSetupResult.Error("Board Setup is Failed")) + } + } + } + } + private fun getUniqueDaysOfWeekInRange( startDate : LocalDate, endDate: LocalDate diff --git a/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/util/DateUtils.kt b/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/util/DateUtils.kt index e07b230a..76dfe863 100644 --- a/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/util/DateUtils.kt +++ b/feature/onboarding/src/main/java/com/goalpanzi/mission_mate/feature/onboarding/util/DateUtils.kt @@ -3,7 +3,10 @@ package com.goalpanzi.mission_mate.feature.onboarding.util import java.time.DayOfWeek import java.time.Instant import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime import java.time.ZoneId +import java.time.ZoneOffset import java.time.format.DateTimeFormatter import java.time.temporal.ChronoUnit import java.util.Locale @@ -52,4 +55,11 @@ object DateUtils { targetDifferenceDays : Int = 7 ) = ChronoUnit.DAYS.between(startDate, endDate).absoluteValue >= targetDifferenceDays + + fun formatLocalDateToString(date: LocalDate): String { + val dateTime = LocalDateTime.of(date, LocalTime.MIDNIGHT) + + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") + return dateTime.atOffset(ZoneOffset.UTC).format(formatter) + } } \ No newline at end of file diff --git a/feature/onboarding/src/main/res/values/strings.xml b/feature/onboarding/src/main/res/values/strings.xml index e43246be..93ea0501 100644 --- a/feature/onboarding/src/main/res/values/strings.xml +++ b/feature/onboarding/src/main/res/values/strings.xml @@ -9,7 +9,7 @@ LV1. 제주도 미션 설정 - 경쟁인원은\n최소 2명에서 최대 10명입니다! + 경쟁인원은\n최소 2명에서 최대 10명이에요! 최소 2명 최대 10명 미션 @@ -17,7 +17,7 @@ 4~12자 이내로 입력하세요. 기간 및 요일 설정 - 경쟁 기간내 인증 요일로 계산한\n총 인증 횟수는 %s번 입니다! + 경쟁 기간내 인증 요일로 계산한\n총 인증 횟수는 %s번 이에요! 경쟁 기간 인증 요일 @@ -37,7 +37,8 @@ 종일\n00~00시 목표가 완성되었어요! - 꾸준히 미션를 완수해\n세계 곳곳을 경험해봐요! + 이제 시작해볼까요? + 꾸준히 미션를 완수해\n세계 곳곳을 경험해봐요! 다음 완성