diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 09a8ea8..50ec747 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -20,11 +20,6 @@
android:label="@string/app_name"
android:theme="@style/Theme.Meongmory">
-
-
-
-
-
-}
\ No newline at end of file
diff --git a/data/src/main/java/com/meongmoryteam/data/datasource/FoodDataSourceImpl.kt b/data/src/main/java/com/meongmoryteam/data/datasource/FoodDataSourceImpl.kt
deleted file mode 100644
index e29a4ff..0000000
--- a/data/src/main/java/com/meongmoryteam/data/datasource/FoodDataSourceImpl.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.meongmoryteam.data.datasource
-
-import com.meongmoryteam.data.model.WeekFoodResponse
-import com.meongmoryteam.data.service.ExampleApi
-import javax.inject.Inject
-
-class FoodDataSourceImpl @Inject constructor(
- private val exampleApi: ExampleApi
-) : FoodDataSource {
- override suspend fun weekGetFoodArea(s: String): Result {
- return runCatching { exampleApi.weekGetFoodArea(s) }
- }
-}
\ No newline at end of file
diff --git a/data/src/main/java/com/meongmoryteam/data/datasource/login/LoginDataSource.kt b/data/src/main/java/com/meongmoryteam/data/datasource/login/LoginDataSource.kt
new file mode 100644
index 0000000..63fa73e
--- /dev/null
+++ b/data/src/main/java/com/meongmoryteam/data/datasource/login/LoginDataSource.kt
@@ -0,0 +1,11 @@
+package com.meongmoryteam.data.datasource.login
+
+import com.meongmoryteam.data.model.response.login.GetSmsSendResponse
+import com.meongmoryteam.data.model.request.login.SmsSendRequest
+import com.meongmoryteam.data.model.request.login.SmsValidateRequest
+import com.meongmoryteam.data.model.response.login.PostSmsValidateResponse
+
+interface LoginDataSource {
+ suspend fun getSmsSend(smsSendRequest: SmsSendRequest): Result
+ suspend fun postSmsValidate(smsValidateRequest: SmsValidateRequest): Result
+}
\ No newline at end of file
diff --git a/data/src/main/java/com/meongmoryteam/data/datasource/login/LoginDataSourceImpl.kt b/data/src/main/java/com/meongmoryteam/data/datasource/login/LoginDataSourceImpl.kt
new file mode 100644
index 0000000..cdba355
--- /dev/null
+++ b/data/src/main/java/com/meongmoryteam/data/datasource/login/LoginDataSourceImpl.kt
@@ -0,0 +1,21 @@
+package com.meongmoryteam.data.datasource.login
+
+import com.meongmoryteam.data.model.response.login.GetSmsSendResponse
+import com.meongmoryteam.data.model.request.login.SmsSendRequest
+import com.meongmoryteam.data.model.request.login.SmsValidateRequest
+import com.meongmoryteam.data.model.response.login.PostSmsValidateResponse
+import com.meongmoryteam.data.service.login.LoginApi
+import javax.inject.Inject
+
+class LoginDataSourceImpl @Inject constructor(
+ private val loginApi: LoginApi
+): LoginDataSource {
+
+ override suspend fun getSmsSend(smsSendRequest: SmsSendRequest): Result {
+ return runCatching { loginApi.getSmsSend(smsSendRequest) }
+ }
+
+ override suspend fun postSmsValidate(smsValidateRequest: SmsValidateRequest): Result {
+ return runCatching { loginApi.postSmsValidate(smsValidateRequest) }
+ }
+}
\ No newline at end of file
diff --git a/data/src/main/java/com/meongmoryteam/data/model/GetWeekFood.kt b/data/src/main/java/com/meongmoryteam/data/model/GetWeekFood.kt
deleted file mode 100644
index 9550d5d..0000000
--- a/data/src/main/java/com/meongmoryteam/data/model/GetWeekFood.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.meongmoryteam.data.model
-
-import com.meongmoryteam.domain.model.ResponseWeekFoodEntity
-import kotlinx.serialization.Serializable
-
-@Serializable
-data class WeekFoodResponse(
- val success : Boolean,
- val message : String,
- val localDateTime : String,
- val httpStatus : String,
- val httpCode : Int,
- val data : List,
-) {
- @Serializable
- data class WeekFoodResult(
- val mealId: Int,
- val toDay: String,
- val mealType : String,
- val statusType : String,
- val meals : List
- )
-}
-
-fun WeekFoodResponse.toWeekFoodEntity(): ResponseWeekFoodEntity {
- val weekFoodResultEntityList = this.data.map { result ->
- ResponseWeekFoodEntity.WeekFoodResultEntity(
- mealId = result.mealId,
- toDay = result.toDay,
- mealType = result.mealType,
- statusType = result.statusType,
- meals = result.meals
- )
- }
-
- return ResponseWeekFoodEntity(
- success = this.success,
- message = this.message,
- localDateTime = this.localDateTime,
- httpStatus = this.httpStatus,
- httpCode = this.httpCode,
- data = weekFoodResultEntityList
- )
-}
\ No newline at end of file
diff --git a/data/src/main/java/com/meongmoryteam/data/model/request/login/SmsSendRequest.kt b/data/src/main/java/com/meongmoryteam/data/model/request/login/SmsSendRequest.kt
new file mode 100644
index 0000000..419f3d1
--- /dev/null
+++ b/data/src/main/java/com/meongmoryteam/data/model/request/login/SmsSendRequest.kt
@@ -0,0 +1,15 @@
+package com.meongmoryteam.data.model.request.login
+
+import com.meongmoryteam.domain.model.reqeust.login.SmsSendRequestEntity
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class SmsSendRequest(
+ val phone: String
+)
+
+fun SmsSendRequestEntity.toSmsSendRequest(): SmsSendRequest {
+ return SmsSendRequest(
+ phone = this.phone
+ )
+}
\ No newline at end of file
diff --git a/data/src/main/java/com/meongmoryteam/data/model/request/login/SmsValidateRequest.kt b/data/src/main/java/com/meongmoryteam/data/model/request/login/SmsValidateRequest.kt
new file mode 100644
index 0000000..d614d5c
--- /dev/null
+++ b/data/src/main/java/com/meongmoryteam/data/model/request/login/SmsValidateRequest.kt
@@ -0,0 +1,17 @@
+package com.meongmoryteam.data.model.request.login
+
+import com.meongmoryteam.domain.model.reqeust.login.SmsValidateRequestEntity
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class SmsValidateRequest(
+ val code: String,
+ val phone: String
+)
+
+fun SmsValidateRequestEntity.toSmsValidateRequest(): SmsValidateRequest {
+ return SmsValidateRequest(
+ code = this.code,
+ phone = this.phone
+ )
+}
diff --git a/data/src/main/java/com/meongmoryteam/data/model/response/login/GetSmsSendResponse.kt b/data/src/main/java/com/meongmoryteam/data/model/response/login/GetSmsSendResponse.kt
new file mode 100644
index 0000000..9a29098
--- /dev/null
+++ b/data/src/main/java/com/meongmoryteam/data/model/response/login/GetSmsSendResponse.kt
@@ -0,0 +1,31 @@
+package com.meongmoryteam.data.model.response.login
+
+import com.meongmoryteam.domain.model.response.login.GetSmsSendData
+import com.meongmoryteam.domain.model.response.login.GetSmsSendEntity
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class GetSmsSendResponse(
+ val status: Int,
+ val code: String,
+ val message: String,
+ val data: Data,
+)
+
+@Serializable
+data class Data(
+ val value: String,
+ val message: String?
+)
+
+fun GetSmsSendResponse.toGetSmsSendEntity(): GetSmsSendEntity {
+ return GetSmsSendEntity(
+ status = this.status,
+ code = this.code,
+ message = this.message,
+ getSmsSendData = GetSmsSendData(
+ value = this.data.value,
+ message = this.data.message
+ )
+ )
+}
\ No newline at end of file
diff --git a/data/src/main/java/com/meongmoryteam/data/model/response/login/PostSmsValidateResponse.kt b/data/src/main/java/com/meongmoryteam/data/model/response/login/PostSmsValidateResponse.kt
new file mode 100644
index 0000000..4cd688f
--- /dev/null
+++ b/data/src/main/java/com/meongmoryteam/data/model/response/login/PostSmsValidateResponse.kt
@@ -0,0 +1,21 @@
+package com.meongmoryteam.data.model.response.login
+
+import com.meongmoryteam.domain.model.response.login.PostSmsValidateEntity
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class PostSmsValidateResponse(
+ val status: Int,
+ val code: String,
+ val message: String,
+ val data: Boolean
+)
+
+fun PostSmsValidateResponse.toPostSmsValidateEntity(): PostSmsValidateEntity {
+ return PostSmsValidateEntity(
+ status = this.status,
+ code = this.code,
+ message = this.message,
+ data = this.data
+ )
+}
\ No newline at end of file
diff --git a/data/src/main/java/com/meongmoryteam/data/repository/FoodRepositoryImpl.kt b/data/src/main/java/com/meongmoryteam/data/repository/FoodRepositoryImpl.kt
deleted file mode 100644
index c00ed79..0000000
--- a/data/src/main/java/com/meongmoryteam/data/repository/FoodRepositoryImpl.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.meongmoryteam.data.repository
-
-import com.meongmoryteam.data.datasource.FoodDataSource
-import com.meongmoryteam.data.model.toWeekFoodEntity
-import com.meongmoryteam.domain.model.ResponseWeekFoodEntity
-import com.meongmoryteam.domain.repository.FoodRepository
-import javax.inject.Inject
-
-class FoodRepositoryImpl @Inject constructor(
- private val foodDataSource: FoodDataSource
-) : FoodRepository {
-
- override suspend fun weekFood(area: String): Result {
- return foodDataSource.weekGetFoodArea(area).map { it.toWeekFoodEntity() }
- }
-}
\ No newline at end of file
diff --git a/data/src/main/java/com/meongmoryteam/data/repository/login/LoginRepositoryImpl.kt b/data/src/main/java/com/meongmoryteam/data/repository/login/LoginRepositoryImpl.kt
new file mode 100644
index 0000000..9d180fb
--- /dev/null
+++ b/data/src/main/java/com/meongmoryteam/data/repository/login/LoginRepositoryImpl.kt
@@ -0,0 +1,26 @@
+package com.meongmoryteam.data.repository.login
+
+import com.meongmoryteam.data.datasource.login.LoginDataSource
+import com.meongmoryteam.data.model.response.login.toGetSmsSendEntity
+import com.meongmoryteam.data.model.request.login.toSmsSendRequest
+import com.meongmoryteam.data.model.request.login.toSmsValidateRequest
+import com.meongmoryteam.data.model.response.login.toPostSmsValidateEntity
+import com.meongmoryteam.domain.model.response.login.GetSmsSendEntity
+import com.meongmoryteam.domain.model.reqeust.login.SmsSendRequestEntity
+import com.meongmoryteam.domain.model.reqeust.login.SmsValidateRequestEntity
+import com.meongmoryteam.domain.model.response.login.PostSmsValidateEntity
+import com.meongmoryteam.domain.repository.login.LoginRepository
+import javax.inject.Inject
+
+class LoginRepositoryImpl @Inject constructor(
+ private val loginDataSource: LoginDataSource
+) : LoginRepository {
+
+ override suspend fun getSmsSend(smsSendRequestEntity: SmsSendRequestEntity): Result {
+ return loginDataSource.getSmsSend(smsSendRequestEntity.toSmsSendRequest()).map { it.toGetSmsSendEntity() }
+ }
+
+ override suspend fun postSmsValidate(smsValidateRequestEntity: SmsValidateRequestEntity): Result {
+ return loginDataSource.postSmsValidate(smsValidateRequestEntity.toSmsValidateRequest()).map { it.toPostSmsValidateEntity() }
+ }
+}
\ No newline at end of file
diff --git a/data/src/main/java/com/meongmoryteam/data/service/ExampleApi.kt b/data/src/main/java/com/meongmoryteam/data/service/ExampleApi.kt
deleted file mode 100644
index 198ea75..0000000
--- a/data/src/main/java/com/meongmoryteam/data/service/ExampleApi.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.meongmoryteam.data.service
-
-import com.meongmoryteam.data.model.WeekFoodResponse
-import retrofit2.http.GET
-import retrofit2.http.Path
-
-interface ExampleApi {
-
- @GET("/api/v2/meals/week/{area}")
- suspend fun weekGetFoodArea(
- @Path("area") area: String
- ): WeekFoodResponse
-}
\ No newline at end of file
diff --git a/data/src/main/java/com/meongmoryteam/data/service/login/LoginApi.kt b/data/src/main/java/com/meongmoryteam/data/service/login/LoginApi.kt
new file mode 100644
index 0000000..3da3c79
--- /dev/null
+++ b/data/src/main/java/com/meongmoryteam/data/service/login/LoginApi.kt
@@ -0,0 +1,21 @@
+package com.meongmoryteam.data.service.login
+
+import com.meongmoryteam.data.model.response.login.GetSmsSendResponse
+import com.meongmoryteam.data.model.request.login.SmsSendRequest
+import com.meongmoryteam.data.model.request.login.SmsValidateRequest
+import com.meongmoryteam.data.model.response.login.PostSmsValidateResponse
+import retrofit2.http.Body
+import retrofit2.http.POST
+
+interface LoginApi {
+
+ @POST("sms/send")
+ suspend fun getSmsSend(
+ @Body smsSendRequest: SmsSendRequest
+ ): GetSmsSendResponse
+
+ @POST("sms/validate")
+ suspend fun postSmsValidate(
+ @Body smsValidateRequest: SmsValidateRequest
+ ): PostSmsValidateResponse
+}
\ No newline at end of file
diff --git a/domain/src/main/java/com/meongmoryteam/domain/model/ResponseWeekFoodEntity.kt b/domain/src/main/java/com/meongmoryteam/domain/model/ResponseWeekFoodEntity.kt
deleted file mode 100644
index 1001d5a..0000000
--- a/domain/src/main/java/com/meongmoryteam/domain/model/ResponseWeekFoodEntity.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.meongmoryteam.domain.model
-
-data class ResponseWeekFoodEntity(
- val success : Boolean,
- val message : String,
- val localDateTime : String,
- val httpStatus : String,
- val httpCode : Int,
- val data : List,
-){
- data class WeekFoodResultEntity(
- val mealId: Int,
- val toDay: String,
- val mealType : String,
- val statusType : String,
- val meals : List
- )
-}
diff --git a/domain/src/main/java/com/meongmoryteam/domain/model/reqeust/login/SmsSendRequestEntity.kt b/domain/src/main/java/com/meongmoryteam/domain/model/reqeust/login/SmsSendRequestEntity.kt
new file mode 100644
index 0000000..0c56f78
--- /dev/null
+++ b/domain/src/main/java/com/meongmoryteam/domain/model/reqeust/login/SmsSendRequestEntity.kt
@@ -0,0 +1,5 @@
+package com.meongmoryteam.domain.model.reqeust.login
+
+data class SmsSendRequestEntity(
+ val phone: String
+)
diff --git a/domain/src/main/java/com/meongmoryteam/domain/model/reqeust/login/SmsValidateRequestEntity.kt b/domain/src/main/java/com/meongmoryteam/domain/model/reqeust/login/SmsValidateRequestEntity.kt
new file mode 100644
index 0000000..0a6b7e8
--- /dev/null
+++ b/domain/src/main/java/com/meongmoryteam/domain/model/reqeust/login/SmsValidateRequestEntity.kt
@@ -0,0 +1,6 @@
+package com.meongmoryteam.domain.model.reqeust.login
+
+data class SmsValidateRequestEntity(
+ val code: String,
+ val phone: String
+)
diff --git a/domain/src/main/java/com/meongmoryteam/domain/model/response/login/GetSmsSendEntity.kt b/domain/src/main/java/com/meongmoryteam/domain/model/response/login/GetSmsSendEntity.kt
new file mode 100644
index 0000000..0d493e5
--- /dev/null
+++ b/domain/src/main/java/com/meongmoryteam/domain/model/response/login/GetSmsSendEntity.kt
@@ -0,0 +1,14 @@
+package com.meongmoryteam.domain.model.response.login
+
+data class GetSmsSendEntity(
+ val status: Int,
+ val code: String,
+ val message: String,
+ val getSmsSendData: GetSmsSendData,
+)
+
+data class GetSmsSendData(
+ val value: String,
+ val message: String?
+)
+
diff --git a/domain/src/main/java/com/meongmoryteam/domain/model/response/login/PostSmsValidateEntity.kt b/domain/src/main/java/com/meongmoryteam/domain/model/response/login/PostSmsValidateEntity.kt
new file mode 100644
index 0000000..8a964c0
--- /dev/null
+++ b/domain/src/main/java/com/meongmoryteam/domain/model/response/login/PostSmsValidateEntity.kt
@@ -0,0 +1,8 @@
+package com.meongmoryteam.domain.model.response.login
+
+data class PostSmsValidateEntity(
+ val status: Int,
+ val code: String,
+ val message: String,
+ val data: Boolean,
+)
diff --git a/domain/src/main/java/com/meongmoryteam/domain/repository/FoodRepository.kt b/domain/src/main/java/com/meongmoryteam/domain/repository/FoodRepository.kt
deleted file mode 100644
index 4f7627b..0000000
--- a/domain/src/main/java/com/meongmoryteam/domain/repository/FoodRepository.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.meongmoryteam.domain.repository
-
-import com.meongmoryteam.domain.model.ResponseWeekFoodEntity
-
-interface FoodRepository {
- suspend fun weekFood(area: String): Result
-}
\ No newline at end of file
diff --git a/domain/src/main/java/com/meongmoryteam/domain/repository/login/LoginRepository.kt b/domain/src/main/java/com/meongmoryteam/domain/repository/login/LoginRepository.kt
new file mode 100644
index 0000000..8cdfcc3
--- /dev/null
+++ b/domain/src/main/java/com/meongmoryteam/domain/repository/login/LoginRepository.kt
@@ -0,0 +1,11 @@
+package com.meongmoryteam.domain.repository.login
+
+import com.meongmoryteam.domain.model.response.login.GetSmsSendEntity
+import com.meongmoryteam.domain.model.reqeust.login.SmsSendRequestEntity
+import com.meongmoryteam.domain.model.reqeust.login.SmsValidateRequestEntity
+import com.meongmoryteam.domain.model.response.login.PostSmsValidateEntity
+
+interface LoginRepository {
+ suspend fun getSmsSend(smsSendRequestEntity: SmsSendRequestEntity): Result
+ suspend fun postSmsValidate(smsValidateRequestEntity: SmsValidateRequestEntity): Result
+}
\ No newline at end of file
diff --git a/domain/src/main/java/com/meongmoryteam/domain/usecase/GetWeekFoodUseCase.kt b/domain/src/main/java/com/meongmoryteam/domain/usecase/GetWeekFoodUseCase.kt
deleted file mode 100644
index 346b03b..0000000
--- a/domain/src/main/java/com/meongmoryteam/domain/usecase/GetWeekFoodUseCase.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.meongmoryteam.domain.usecase
-
-import com.meongmoryteam.domain.repository.FoodRepository
-import javax.inject.Inject
-
-class GetWeekFoodUseCase @Inject constructor(
- private val foodRepository: FoodRepository
-) {
- suspend operator fun invoke(s : String) = foodRepository.weekFood(s)
-}
\ No newline at end of file
diff --git a/domain/src/main/java/com/meongmoryteam/domain/usecase/login/GetSmsSendUseCase.kt b/domain/src/main/java/com/meongmoryteam/domain/usecase/login/GetSmsSendUseCase.kt
new file mode 100644
index 0000000..f95e691
--- /dev/null
+++ b/domain/src/main/java/com/meongmoryteam/domain/usecase/login/GetSmsSendUseCase.kt
@@ -0,0 +1,11 @@
+package com.meongmoryteam.domain.usecase.login
+
+import com.meongmoryteam.domain.model.reqeust.login.SmsSendRequestEntity
+import com.meongmoryteam.domain.repository.login.LoginRepository
+import javax.inject.Inject
+
+class GetSmsSendUseCase @Inject constructor(
+ private val loginRepository: LoginRepository
+) {
+ suspend operator fun invoke(smsSendRequestEntity: SmsSendRequestEntity) = loginRepository.getSmsSend(smsSendRequestEntity)
+}
\ No newline at end of file
diff --git a/domain/src/main/java/com/meongmoryteam/domain/usecase/login/PostSmsValidateUseCase.kt b/domain/src/main/java/com/meongmoryteam/domain/usecase/login/PostSmsValidateUseCase.kt
new file mode 100644
index 0000000..606a3a1
--- /dev/null
+++ b/domain/src/main/java/com/meongmoryteam/domain/usecase/login/PostSmsValidateUseCase.kt
@@ -0,0 +1,12 @@
+package com.meongmoryteam.domain.usecase.login
+
+import com.meongmoryteam.domain.model.reqeust.login.SmsValidateRequestEntity
+import com.meongmoryteam.domain.repository.login.LoginRepository
+import javax.inject.Inject
+
+class PostSmsValidateUseCase @Inject constructor(
+ private val loginRepository: LoginRepository
+) {
+ suspend operator fun invoke(smsValidateRequestEntity: SmsValidateRequestEntity)
+ = loginRepository.postSmsValidate(smsValidateRequestEntity)
+}
\ No newline at end of file
diff --git a/presentation/src/main/java/com/meongmoryteam/presentation/ExampleFoodState.kt b/presentation/src/main/java/com/meongmoryteam/presentation/ExampleFoodState.kt
deleted file mode 100644
index 02f34fa..0000000
--- a/presentation/src/main/java/com/meongmoryteam/presentation/ExampleFoodState.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.meongmoryteam.presentation
-
-import com.meongmoryteam.domain.model.ResponseWeekFoodEntity
-
-sealed class ExampleFoodState {
- object UnInitialized : ExampleFoodState()
-
- object Loading : ExampleFoodState()
-
- data class SuccessWeekFoodGetData(val getWeekFoodData: ResponseWeekFoodEntity) : ExampleFoodState()
-
- data class Error(val errorCode: Throwable) : ExampleFoodState()
-}
\ No newline at end of file
diff --git a/presentation/src/main/java/com/meongmoryteam/presentation/MainViewModel.kt b/presentation/src/main/java/com/meongmoryteam/presentation/MainViewModel.kt
deleted file mode 100644
index 1fc7896..0000000
--- a/presentation/src/main/java/com/meongmoryteam/presentation/MainViewModel.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.meongmoryteam.presentation
-
-import androidx.lifecycle.ViewModel
-import androidx.lifecycle.viewModelScope
-import com.meongmoryteam.domain.usecase.GetWeekFoodUseCase
-import dagger.hilt.android.lifecycle.HiltViewModel
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.launch
-import javax.inject.Inject
-
-@HiltViewModel
-class ExampleViewModel @Inject constructor(
- private val getWeekFoodUseCase: GetWeekFoodUseCase
-) : ViewModel() {
-
- private val _weekGetFoodArea = MutableStateFlow(ExampleFoodState.UnInitialized)
- val weekGetFoodArea: StateFlow = _weekGetFoodArea.asStateFlow()
-
- fun getWeekFood(area: String) {
- viewModelScope.launch {
- getWeekFoodUseCase(area).onSuccess {
- _weekGetFoodArea.emit(ExampleFoodState.SuccessWeekFoodGetData(it))
- }.onFailure {
- _weekGetFoodArea.emit(ExampleFoodState.Error(it))
- }
- }
- }
-}
\ No newline at end of file
diff --git a/presentation/src/main/java/com/meongmoryteam/presentation/base/CommonText.kt b/presentation/src/main/java/com/meongmoryteam/presentation/base/CommonText.kt
index 005fecd..4629355 100644
--- a/presentation/src/main/java/com/meongmoryteam/presentation/base/CommonText.kt
+++ b/presentation/src/main/java/com/meongmoryteam/presentation/base/CommonText.kt
@@ -53,7 +53,8 @@ fun TextButtonComponent(
style: TextStyle,
width: Float = 1f,
modifier: Modifier = Modifier,
- onClick: () -> Unit
+ enabled: Boolean = true,
+ onClick: () -> Unit,
) {
TextButton(
onClick = onClick,
@@ -63,6 +64,7 @@ fun TextButtonComponent(
.height(50.dp)
.padding(vertical = 5.dp),
colors = colors,
+ enabled = enabled
)
{
Text(
diff --git a/presentation/src/main/java/com/meongmoryteam/presentation/ui/login/LoginActivity.kt b/presentation/src/main/java/com/meongmoryteam/presentation/ui/login/LoginActivity.kt
index ae5ba92..83357f7 100644
--- a/presentation/src/main/java/com/meongmoryteam/presentation/ui/login/LoginActivity.kt
+++ b/presentation/src/main/java/com/meongmoryteam/presentation/ui/login/LoginActivity.kt
@@ -19,7 +19,7 @@ class LoginActivity : ComponentActivity() {
private fun setUnivSelectScreen() {
setContent {
MeongmoryTheme {
-
+ LoginScreen()
}
}
}
diff --git a/presentation/src/main/java/com/meongmoryteam/presentation/ui/login/LoginContract.kt b/presentation/src/main/java/com/meongmoryteam/presentation/ui/login/LoginContract.kt
new file mode 100644
index 0000000..c8c0c8a
--- /dev/null
+++ b/presentation/src/main/java/com/meongmoryteam/presentation/ui/login/LoginContract.kt
@@ -0,0 +1,31 @@
+package com.meongmoryteam.presentation.ui.login
+
+import com.meongmoryteam.presentation.base.LoadState
+import com.meongmoryteam.presentation.base.ViewEvent
+import com.meongmoryteam.presentation.base.ViewSideEffect
+import com.meongmoryteam.presentation.base.ViewState
+import com.meongmoryteam.presentation.ui.register_dog.RegisterDogContract
+
+class LoginContract {
+ data class LoginState(
+ val getSmsSendLoadState: LoadState = LoadState.SUCCESS,
+ val phoneNumber: String = "",
+ val certificationNumber: String = "",
+ val getCertificationNumber: String = "",
+ val isCertification: Boolean = false,
+ ): ViewState
+
+ sealed class LoginEvent : ViewEvent {
+ object GetCertificationButtonClicked : LoginEvent()
+ object PostCertificationButtonClicked : LoginEvent()
+ object ToTermScreenButtonClicked : LoginEvent()
+ data class OnPhoneChanged(val phoneNumber: String) : LoginEvent()
+ data class OnCertificationNumberChanged(val certificationNumber: String) : LoginEvent()
+ }
+
+ sealed class LoginEffect : ViewSideEffect {
+ object MoveToTerm: LoginEffect()
+ object SuccessCertification: LoginEffect()
+ object FailCertification: LoginEffect()
+ }
+}
\ No newline at end of file
diff --git a/presentation/src/main/java/com/meongmoryteam/presentation/ui/login/LoginScreen.kt b/presentation/src/main/java/com/meongmoryteam/presentation/ui/login/LoginScreen.kt
new file mode 100644
index 0000000..58de1f6
--- /dev/null
+++ b/presentation/src/main/java/com/meongmoryteam/presentation/ui/login/LoginScreen.kt
@@ -0,0 +1,221 @@
+package com.meongmoryteam.presentation.ui.login
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.text.KeyboardOptions
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Snackbar
+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.rememberCoroutineScope
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.PlatformTextStyle
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.input.KeyboardType
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.hilt.navigation.compose.hiltViewModel
+import com.meongmoryteam.presentation.R
+import com.meongmoryteam.presentation.base.TextButtonComponent
+import com.meongmoryteam.presentation.base.TextFieldComponent
+import com.meongmoryteam.presentation.ui.theme.ButtonContent
+import com.meongmoryteam.presentation.ui.theme.DarkGrey
+import com.meongmoryteam.presentation.ui.theme.LightGrey
+import com.meongmoryteam.presentation.ui.theme.NotoSansKR
+import com.meongmoryteam.presentation.ui.theme.Orange
+import com.meongmoryteam.presentation.ui.theme.Typography
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.launch
+
+@Composable
+fun LoginScreen(
+ loginViewModel: LoginViewModel = hiltViewModel(),
+) {
+ val loginViewState by loginViewModel.viewState.collectAsState()
+
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .background(Color.White)
+ ) {
+ LoginPhoneCertTitle()
+ LoginPhoneTextField()
+ Spacer(modifier = Modifier.weight(1f))
+ TextButtonComponent(
+ text = stringResource(R.string.login_phone_login_next_button),
+ colors = if (!loginViewState.isCertification) {
+ ButtonDefaults.textButtonColors(LightGrey)
+ } else {
+ ButtonDefaults.textButtonColors(Orange)
+ },
+ style = TextStyle(
+ fontFamily = NotoSansKR,
+ fontWeight = FontWeight.W500,
+ fontSize = 15.sp,
+ lineHeight = 20.sp,
+ color = ButtonContent,
+ platformStyle = PlatformTextStyle(includeFontPadding = false)
+ ),
+ enabled = loginViewState.isCertification,
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(50.dp)
+ .padding(horizontal = 16.dp),
+ ) {
+
+ }
+ }
+
+ LaunchedEffect(key1 = loginViewModel.effect) {
+ loginViewModel.effect.collect { effect ->
+ when (effect) {
+ is LoginContract.LoginEffect.MoveToTerm -> {
+
+ }
+ is LoginContract.LoginEffect.FailCertification -> {
+ /*
+ 인증 실패 스낵바 기획 논의
+ */
+ }
+ is LoginContract.LoginEffect.SuccessCertification -> {
+ /*
+ 인증 성공 스낵바 기획 논의
+ */
+ }
+ }
+ }
+ }
+}
+
+@Composable
+fun LoginPhoneCertTitle() {
+ Icon(
+ modifier = Modifier.padding(12.dp),
+ painter = painterResource(R.drawable.ic_left_btn),
+ contentDescription = stringResource(R.string.login_back_button),
+ )
+ Spacer(modifier = Modifier.padding(30.dp))
+
+ Text(
+ modifier = Modifier.padding(start = 16.dp),
+ text = stringResource(R.string.login_phone_screen_title),
+ fontSize = 20.sp,
+ color = Color.Black,
+ fontWeight = FontWeight.SemiBold
+ )
+ Spacer(modifier = Modifier.padding(6.dp))
+
+ Text(
+ modifier = Modifier.padding(start = 16.dp),
+ text = stringResource(R.string.login_phone_screen_sub_title),
+ color = DarkGrey,
+ style = Typography.titleSmall
+ )
+ Spacer(modifier = Modifier.padding(32.dp))
+}
+
+@Composable
+fun LoginPhoneTextField(
+ loginViewModel: LoginViewModel = hiltViewModel(),
+) {
+ val loginViewState by loginViewModel.viewState.collectAsState()
+
+ Text(
+ modifier = Modifier.padding(start = 16.dp),
+ text = stringResource(R.string.login_phone),
+ color = DarkGrey,
+ style = Typography.titleSmall
+ )
+ Spacer(modifier = Modifier.padding(10.dp))
+
+ TextFieldComponent(
+ name = loginViewState.phoneNumber,
+ placeholder = stringResource(R.string.login_phone_text_field_hint),
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(37.dp)
+ .padding(horizontal = 16.dp),
+ onValueChange = { loginViewModel.setEvent(LoginContract.LoginEvent.OnPhoneChanged(it.trim())) },
+ keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
+ )
+ Spacer(modifier = Modifier.padding(6.dp))
+
+ TextButtonComponent(
+ text = stringResource(R.string.login_phone_get_certification_button),
+ colors = if (loginViewState.phoneNumber.length != 11) {
+ ButtonDefaults.textButtonColors(LightGrey)
+ } else {
+ ButtonDefaults.textButtonColors(Orange)
+ },
+ style = TextStyle(
+ fontFamily = NotoSansKR,
+ fontWeight = FontWeight.W500,
+ fontSize = 15.sp,
+ lineHeight = 20.sp,
+ color = ButtonContent,
+ platformStyle = PlatformTextStyle(includeFontPadding = false)
+ ),
+ enabled = loginViewState.phoneNumber.length == 11,
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 16.dp),
+ ) {
+ loginViewModel.setEvent(LoginContract.LoginEvent.GetCertificationButtonClicked)
+ }
+ Spacer(modifier = Modifier.padding(20.dp))
+
+ TextFieldComponent(
+ name = loginViewState.certificationNumber,
+ placeholder = stringResource(R.string.login_certification_text_field_hint),
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(37.dp)
+ .padding(horizontal = 16.dp),
+ onValueChange = { loginViewModel.setEvent(LoginContract.LoginEvent.OnCertificationNumberChanged(it)) },
+ keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
+ )
+ Spacer(modifier = Modifier.padding(6.dp))
+
+ TextButtonComponent(
+ text = stringResource(R.string.login_phone_post_certification_button),
+ colors = if (loginViewState.certificationNumber.length != 5) {
+ ButtonDefaults.textButtonColors(LightGrey)
+ } else {
+ ButtonDefaults.textButtonColors(Orange)
+ },
+ style = TextStyle(
+ fontFamily = NotoSansKR,
+ fontWeight = FontWeight.W500,
+ fontSize = 15.sp,
+ lineHeight = 20.sp,
+ color = ButtonContent,
+ platformStyle = PlatformTextStyle(includeFontPadding = false)
+ ),
+ enabled = loginViewState.certificationNumber.length == 5,
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 16.dp),
+ ) {
+ loginViewModel.setEvent(LoginContract.LoginEvent.PostCertificationButtonClicked)
+ }
+}
+
+@Preview
+@Composable
+fun LoginScreenPreview() {
+ LoginScreen()
+}
\ No newline at end of file
diff --git a/presentation/src/main/java/com/meongmoryteam/presentation/ui/login/LoginViewModel.kt b/presentation/src/main/java/com/meongmoryteam/presentation/ui/login/LoginViewModel.kt
new file mode 100644
index 0000000..218b5f2
--- /dev/null
+++ b/presentation/src/main/java/com/meongmoryteam/presentation/ui/login/LoginViewModel.kt
@@ -0,0 +1,93 @@
+package com.meongmoryteam.presentation.ui.login
+
+import androidx.lifecycle.viewModelScope
+import com.meongmoryteam.domain.model.reqeust.login.SmsSendRequestEntity
+import com.meongmoryteam.domain.model.reqeust.login.SmsValidateRequestEntity
+import com.meongmoryteam.domain.usecase.login.GetSmsSendUseCase
+import com.meongmoryteam.domain.usecase.login.PostSmsValidateUseCase
+import com.meongmoryteam.presentation.base.BaseViewModel
+import com.meongmoryteam.presentation.base.LoadState
+import com.meongmoryteam.presentation.ui.login.LoginContract.LoginEffect
+import com.meongmoryteam.presentation.ui.login.LoginContract.LoginEvent
+import com.meongmoryteam.presentation.ui.login.LoginContract.LoginState
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+@HiltViewModel
+class LoginViewModel @Inject constructor(
+ private val getSmsSendUseCase: GetSmsSendUseCase,
+ private val postSmsSendUseCase: PostSmsValidateUseCase
+): BaseViewModel(
+ LoginState()
+) {
+ override fun handleEvents(event: LoginEvent) {
+ when(event) {
+ is LoginEvent.GetCertificationButtonClicked -> {
+ updateState { copy(getSmsSendLoadState = LoadState.LOADING) }
+ getSmsSend()
+ }
+ is LoginEvent.PostCertificationButtonClicked -> {
+ postSmsSend()
+ }
+ is LoginEvent.ToTermScreenButtonClicked -> {
+ sendEffect({ LoginEffect.MoveToTerm })
+ }
+ is LoginEvent.OnPhoneChanged -> reflectUpdateState(phoneNumber = event.phoneNumber)
+ is LoginEvent.OnCertificationNumberChanged -> reflectUpdateState(certificationNumber = event.certificationNumber)
+ }
+ }
+
+ private fun getSmsSend() {
+ val smsSendRequest = SmsSendRequestEntity(
+ viewState.value.phoneNumber
+ )
+ viewModelScope.launch {
+ getSmsSendUseCase(smsSendRequest).onSuccess {
+ updateState {
+ copy(
+ getSmsSendLoadState = LoadState.SUCCESS,
+ getCertificationNumber = it.getSmsSendData.value
+ )
+ }
+ }.onFailure {
+ updateState {
+ copy(
+ getSmsSendLoadState = LoadState.ERROR,
+ )
+ }
+ }
+ }
+ }
+
+ private fun postSmsSend() {
+ val smsValidRequest = SmsValidateRequestEntity(
+ viewState.value.certificationNumber,
+ viewState.value.phoneNumber
+ )
+ viewModelScope.launch {
+ postSmsSendUseCase(smsValidRequest).onSuccess {
+ updateState {
+ copy(
+ isCertification = true
+ )
+ }
+ sendEffect({ LoginEffect.SuccessCertification })
+ }.onFailure {
+ sendEffect({ LoginEffect.FailCertification })
+ }
+ }
+ }
+
+ private fun reflectUpdateState(
+ phoneNumber: String = viewState.value.phoneNumber,
+ certificationNumber: String = viewState.value.certificationNumber
+ ) {
+ updateState {
+ copy(
+ phoneNumber = phoneNumber,
+ certificationNumber = certificationNumber
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml
index 04b8e52..b2d5d21 100644
--- a/presentation/src/main/res/values/strings.xml
+++ b/presentation/src/main/res/values/strings.xml
@@ -102,5 +102,16 @@
휴대폰 번호로 시작하기
펫다이어리 로고
전화
+ 로그인 화면 닫기 버튼
+ 안녕하세요!\n휴대폰 번호로 로그인 해주세요!
+ 휴대폰 번호는 안전하게 보관되어\n이웃에게 공개되지 않아요.
+ 휴대폰 번호
+ -없이 숫자만 입력
+ 인증번호 받기
+ 인증번호 입력
+ 인증 요청
+ 다음
+
+ 네트워크 에러가 발생하였습니다.
\ No newline at end of file