Skip to content

Commit

Permalink
Merge pull request #89 from everymeals/feature/school_auth_screen
Browse files Browse the repository at this point in the history
[Feature/school_auth_screen]: 인증 이메일 API 연동 작업
  • Loading branch information
kez-lab authored Dec 21, 2023
2 parents 45d8094 + 5846566 commit c862b4a
Show file tree
Hide file tree
Showing 16 changed files with 261 additions and 53 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.everymeal.data.datasource.auth

import com.everymeal.domain.model.auth.Email
import com.everymeal.domain.model.auth.EmailAuthToken

interface AuthRemoteDataSource {
suspend fun postEmail(email: Email): Result<String>
suspend fun postEmail(email: Email): Result<EmailAuthToken>
suspend fun verifyToken(emailAuthToken: String, emailAuthValue: String): Result<Boolean>
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
package com.everymeal.data.datasource.auth

import com.everymeal.data.model.auth.EmailResponse
import com.everymeal.data.model.auth.toEmail
import com.everymeal.data.model.auth.toEmailAuthToken
import com.everymeal.data.model.auth.toEmailRequest
import com.everymeal.data.model.unwrapData
import com.everymeal.data.service.auth.AuthApi
import com.everymeal.domain.model.auth.Email
import com.everymeal.domain.model.auth.EmailAuthToken
import javax.inject.Inject

class AuthRemoteRemoteDataSourceImpl @Inject constructor(
private val authApi: AuthApi
) : AuthRemoteDataSource {

override suspend fun postEmail(email: Email): Result<String> = runCatching {
authApi.postEmail(email.toEmailRequest())
}.unwrapData()
override suspend fun postEmail(email: Email): Result<EmailAuthToken> = runCatching {
authApi.postEmail(email.toEmailRequest()).data.toEmailAuthToken()
}

override suspend fun verifyToken(emailAuthToken: String, emailAuthValue: String) = runCatching {
authApi.verifyToken(emailAuthToken, emailAuthValue).data
}
}
14 changes: 14 additions & 0 deletions data/src/main/java/com/everymeal/data/model/auth/EmailResponse.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.everymeal.data.model.auth

import com.everymeal.domain.model.auth.EmailAuthToken
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class EmailResponse(
@SerialName("emailAuthToken") val emailAuthToken: String,
)

fun EmailResponse.toEmailAuthToken(): EmailAuthToken =
EmailAuthToken(emailAuthToken = emailAuthToken)

Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,21 @@ package com.everymeal.data.repository

import com.everymeal.data.datasource.auth.AuthRemoteDataSource
import com.everymeal.domain.model.auth.Email
import com.everymeal.domain.model.auth.EmailAuthToken
import com.everymeal.domain.repository.auth.AuthRepository
import javax.inject.Inject

class DefaultAuthRepository @Inject constructor(
private val authRemoteDataSource: AuthRemoteDataSource
) : AuthRepository {
override suspend fun postEmail(email: Email): Result<String> {
override suspend fun postEmail(email: Email): Result<EmailAuthToken> {
return authRemoteDataSource.postEmail(email)
}

override suspend fun verifyToken(
emailAuthToken: String,
emailAuthValue: String
): Result<Boolean> {
return authRemoteDataSource.verifyToken(emailAuthToken, emailAuthValue)
}
}
14 changes: 13 additions & 1 deletion data/src/main/java/com/everymeal/data/service/auth/AuthApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,21 @@ package com.everymeal.data.service.auth

import com.everymeal.data.model.BaseResponse
import com.everymeal.data.model.auth.EmailRequest
import com.everymeal.data.model.auth.EmailResponse
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Query

interface AuthApi {
@POST("/api/v1/users/email")
suspend fun postEmail(emailRequest: EmailRequest): BaseResponse<String>
suspend fun postEmail(
@Body emailRequest: EmailRequest
): BaseResponse<EmailResponse>

@GET("/api/v1/users/email/verify")
suspend fun verifyToken(
@Query("emailAuthToken") emailAuthToken: String,
@Query("emailAuthValue") emailAuthValue: String
): BaseResponse<Boolean>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.everymeal.domain.model.auth

data class EmailAuthToken(
val emailAuthToken: String
)
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.everymeal.domain.repository.auth

import com.everymeal.domain.model.auth.Email
import com.everymeal.domain.model.auth.EmailAuthToken

interface AuthRepository {
suspend fun postEmail(email: Email): Result<String>
suspend fun postEmail(email: Email): Result<EmailAuthToken>
suspend fun verifyToken(emailAuthToken: String, emailAuthValue: String): Result<Boolean>

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.everymeal.domain.usecase.auth

import com.everymeal.domain.model.auth.Email
import com.everymeal.domain.model.auth.EmailAuthToken
import com.everymeal.domain.repository.auth.AuthRepository
import javax.inject.Inject

Expand All @@ -9,7 +10,7 @@ class PostEmailUseCase @Inject constructor(
) {
suspend operator fun invoke(
email: Email
): Result<String> {
): Result<EmailAuthToken> {
return authRepository.postEmail(email)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.everymeal.domain.usecase.auth

import com.everymeal.domain.repository.auth.AuthRepository
import javax.inject.Inject

class VerifyTokenUseCase @Inject constructor(
private val authRepository: AuthRepository
) {
suspend operator fun invoke(
emailAuthToken: String,
emailAuthValue: String
): Result<Boolean> {
return authRepository.verifyToken(emailAuthToken, emailAuthValue)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ enum class EveryMealRoute(val route: String) {
MY_PAGE("my-page"),
DETAIL_LIST("detail-list"),
DETAIL_RESTAURANT("detail-restaurant"),
}
SCHOOL_AUTH("school-auth"),
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,23 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import com.everymeal.presentation.ui.bottom.BottomNavigation
import com.everymeal.presentation.ui.bottom.EveryMealBottomNavigation
import com.everymeal.presentation.ui.bottom.EveryMealRoute
import com.everymeal.presentation.ui.bottom.navigateBottomNavigationScreen
import com.everymeal.presentation.ui.detail.DetailListScreen
import com.everymeal.presentation.ui.home.HomeScreen
import com.everymeal.presentation.ui.mypage.MyPageScreen
import com.everymeal.presentation.ui.restaurant.DetailRestaurantScreen
import com.everymeal.presentation.ui.signup.school.SchoolAuthScreen
import com.everymeal.presentation.ui.univfood.UnivFoodScreen
import com.everymeal.presentation.ui.whatfood.WhatFoodScreen

const val DETAIL_SCREEN_TYPE = "detailScreenType"

@Composable
fun MainScreen(
navController: NavHostController = rememberNavController(),
Expand Down Expand Up @@ -62,7 +61,7 @@ fun MainScreen(
navController.navigate(EveryMealRoute.DETAIL_LIST.route.plus("/$detailScreenType"))
},
onDetailRestaurantClick = {
navController.navigate(EveryMealRoute.DETAIL_RESTAURANT.route)
navController.navigate(EveryMealRoute.SCHOOL_AUTH.route)
}
)
}
Expand All @@ -75,7 +74,7 @@ fun MainScreen(
composable(route = EveryMealRoute.MY_PAGE.route) {
MyPageScreen()
}
composable(route = EveryMealRoute.DETAIL_LIST.route.plus("/{$DETAIL_SCREEN_TYPE}"),) {
composable(route = EveryMealRoute.DETAIL_LIST.route.plus("/{$DETAIL_SCREEN_TYPE}")) {
val detailScreenType = it.arguments?.getString(DETAIL_SCREEN_TYPE) ?: ""
DetailListScreen(
title = detailScreenType,
Expand All @@ -85,6 +84,13 @@ fun MainScreen(
composable(route = EveryMealRoute.DETAIL_RESTAURANT.route) {
DetailRestaurantScreen()
}
composable(route = EveryMealRoute.SCHOOL_AUTH.route) {
SchoolAuthScreen(
onSuccessEmailVerification = {
navController.popBackStack()
}
)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.everymeal.presentation.ui.signup.school

import android.util.Log
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
Expand All @@ -8,19 +9,20 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.everymeal.presentation.R
import com.everymeal.presentation.components.EveryMealConditionAgreeDialog
import com.everymeal.presentation.components.EveryMealConditionAgreeDialogItem
import com.everymeal.presentation.ui.signup.school.email.EmailTokenVerifyScreen
import com.everymeal.presentation.ui.signup.school.email.SchoolAuthPostEmailScreen
import com.everymeal.presentation.ui.theme.EveryMealTypography

Expand All @@ -32,9 +34,26 @@ enum class SchoolAuthScreenType {
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SchoolAuthScreen(
viewModel: SchoolAuthViewModel = hiltViewModel()
viewModel: SchoolAuthViewModel = hiltViewModel(),
onSuccessEmailVerification: () -> Unit,
) {
val viewState by viewModel.viewState.collectAsState()
LaunchedEffect(key1 = viewModel.effect) {
viewModel.effect.collect { effect ->
when (effect) {
is SchoolContract.Effect.Error -> {
Log.e(
"SchoolAuthScreen",
"code: ${effect.code.toString()} message: ${effect.message}"
)
}

is SchoolContract.Effect.SuccessEmailVerification -> {
onSuccessEmailVerification()
}
}
}
}
Scaffold(
topBar = {
CenterAlignedTopAppBar(
Expand Down Expand Up @@ -75,17 +94,17 @@ private fun EmailAuthBottomSheet(viewModel: SchoolAuthViewModel) {
mutableStateListOf(
EveryMealConditionAgreeDialogItem(
title = "[필수] 이용 약관 동의",
isAgreed = true,
isAgreed = false,
isEssential = true,
),
EveryMealConditionAgreeDialogItem(
title = "[필수] 개인정보 수집 및 이용 동의",
isAgreed = true,
isAgreed = false,
isEssential = true,
),
EveryMealConditionAgreeDialogItem(
title = "[선택] 마케팅 정보 수집 동의",
isAgreed = true,
isAgreed = false,
)
)
}
Expand All @@ -97,6 +116,12 @@ private fun EmailAuthBottomSheet(viewModel: SchoolAuthViewModel) {
},
onNextButtonClicked = {
if (conditionItems.filter { it.isEssential }.any { it.isAgreed }) {
Log.d(
"TAG",
"EmailAuthBottomSheet: ${
conditionItems.filter { it.isEssential }.any { it.isAgreed }
}"
)
viewModel.setEvent(SchoolContract.Event.OnPostEmail)
}
},
Expand All @@ -111,16 +136,22 @@ fun SchoolAuthContent(
viewModel: SchoolAuthViewModel,
state: SchoolContract.State
) {
SchoolAuthPostEmailScreen(
modifier = modifier,
viewModel = viewModel,
state = state,
)
}
when (state.schoolAuthScreenType) {
SchoolAuthScreenType.POST_EMAIL -> {
SchoolAuthPostEmailScreen(
modifier = modifier,
viewModel = viewModel,
state = state,
)
}

SchoolAuthScreenType.VERIFY_TOKEN -> {
EmailTokenVerifyScreen(
modifier = modifier,
state = state,
viewModel = viewModel
)
}
}

@Preview
@Composable
fun SchoolAuthScreenPreview() {
SchoolAuthScreen()
}
Loading

0 comments on commit c862b4a

Please sign in to comment.