Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/implement onboarding board setup api #19

Merged
merged 6 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -166,4 +166,5 @@ google-services.json

# End of https://www.gitignore.io/api/kotlin,androidstudio
/app/keystore
/app/mission-mate-keystore.jks
/app/mission-mate-keystore.jks
/.idea/kotlinc.xml
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -18,4 +20,7 @@ internal abstract class DataModule {

@Binds
abstract fun bindProfileRepository(impl: ProfileRepositoryImpl): ProfileRepository

@Binds
abstract fun bindOnboardingRepository(impl: OnboardingRepositoryImpl): OnboardingRepository
}
Original file line number Diff line number Diff line change
@@ -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<MissionDetailResponse> = handleResult {
onboardingService.createMission(missionRequest)
}
}
Original file line number Diff line number Diff line change
@@ -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<MissionDetailResponse>

}
Original file line number Diff line number Diff line change
@@ -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<NetworkResult<MissionDetailResponse>> = flow {
emit(onboardingRepository.createMission(createMissionRequest))
}
}
Original file line number Diff line number Diff line change
@@ -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<String>,
val boardCount : Int
)
Original file line number Diff line number Diff line change
@@ -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<String>,
val boardCount : Int,
val invitationCode : String
)
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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

/*
* 온보딩 화면에서 사용되는 API
* - 미션 생성
* - 미션 조회 by 초대코드
* - 미션 참여
*/
bywindow marked this conversation as resolved.
Show resolved Hide resolved
interface OnboardingService {
@POST("/api/missions")
suspend fun createMission(
@Body request: CreateMissionRequest
): Response<MissionDetailResponse>
}
2 changes: 2 additions & 0 deletions feature/onboarding/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,6 @@ dependencies {

implementation(project(":core:designsystem"))
implementation(project(":core:navigation"))
implementation(project(":core:domain"))
implementation(project(":core:model"))
}
Original file line number Diff line number Diff line change
@@ -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()
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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 }
Expand Down Expand Up @@ -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()
}
}

}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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()
)
}
Loading
Loading