diff --git a/.gitignore b/.gitignore index ec9cfba01..3c5e3b0b9 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,5 @@ core/designsystem/build/outputs/aar/ core/model/build/outputs/aar/ core/designsystem/build/tmp/kotlin-classes/debug/META-INF core/designsystem/build/tmp -core/designsystem/build/kotlin/compileReleaseKotlin/ \ No newline at end of file +core/designsystem/build/kotlin/compileReleaseKotlin/ +core/model/build/kotlin compileReleaseKotlin/ \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0efbc6b82..46cc891df 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,4 +1,5 @@ import com.kusitms.connectdog.Configuration +import org.jetbrains.kotlin.konan.properties.Properties @Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed plugins { @@ -24,6 +25,13 @@ android { vectorDrawables { useSupportLibrary = true } + + val localProperties = Properties() + val localPropertiesFile = rootProject.file("local.properties") + if (localPropertiesFile.exists()) { localPropertiesFile.inputStream().use { localProperties.load(it) } } + + val kakaoAppKey: String = localProperties.getProperty("kakao_app_key") ?: "" + manifestPlaceholders["KAKAO_APP_KEY"] = kakaoAppKey } buildTypes { @@ -43,7 +51,9 @@ android { kotlinOptions { jvmTarget = "17" } - + buildFeatures { + buildConfig = true + } packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3141c2a6c..8f88bf606 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,7 +18,7 @@ tools:targetApi="33"> + android:value="${KAKAO_APP_KEY}" /> + android:scheme="kakao${KAKAO_APP_KEY}" /> diff --git a/core/data/build.gradle.kts b/core/data/build.gradle.kts index 29b949ee8..80c307d03 100644 --- a/core/data/build.gradle.kts +++ b/core/data/build.gradle.kts @@ -1,4 +1,5 @@ import com.kusitms.connectdog.Configuration +import org.jetbrains.kotlin.konan.properties.Properties @Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed plugins { @@ -16,6 +17,14 @@ android { defaultConfig { minSdk = Configuration.minSdk + val localProperties = Properties() + val localPropertiesFile = rootProject.file("local.properties") + if (localPropertiesFile.exists()) { localPropertiesFile.inputStream().use { localProperties.load(it) } } + + val baseUrl: String = localProperties.getProperty("BASE_URL") ?: "" + + buildConfigField("String", "BASE_URL", "\"$baseUrl\"") + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") } @@ -36,15 +45,21 @@ android { kotlinOptions { jvmTarget = "17" } + buildFeatures { + buildConfig = true + } } dependencies { + implementation(projects.domain) implementation(project(":core:model")) implementation(project(":core:util")) kapt(libs.hilt.compiler) implementation(libs.hilt.android) + implementation(libs.kotlinx.coroutines.core) + implementation(libs.retrofit.core) implementation(libs.retrofit.kotlin.serialization) implementation(libs.retrofit.converter.moshi) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/ApiService.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/ApiService.kt index fed0d091b..d8078a559 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/ApiService.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/ApiService.kt @@ -1,18 +1,9 @@ package com.kusitms.connectdog.core.data.api import com.kusitms.connectdog.core.data.api.model.AdditionalAuthBody -import com.kusitms.connectdog.core.data.api.model.AuthDto -import com.kusitms.connectdog.core.data.api.model.EmailDto import com.kusitms.connectdog.core.data.api.model.FcmTokenRequestBody -import com.kusitms.connectdog.core.data.api.model.IsDuplicateNicknameResponse -import com.kusitms.connectdog.core.data.api.model.IsDuplicatePhoneNumberBody -import com.kusitms.connectdog.core.data.api.model.IsDuplicatePhoneNumberResponse -import com.kusitms.connectdog.core.data.api.model.LoginResponseItem import com.kusitms.connectdog.core.data.api.model.MyInfoResponseItem -import com.kusitms.connectdog.core.data.api.model.NormalLoginBody -import com.kusitms.connectdog.core.data.api.model.PhoneDto import com.kusitms.connectdog.core.data.api.model.Response -import com.kusitms.connectdog.core.data.api.model.SocialLoginBody import com.kusitms.connectdog.core.data.api.model.VolunteerResponse import com.kusitms.connectdog.core.data.api.model.intermediator.IntermediatorInfoResponseItem import com.kusitms.connectdog.core.data.api.model.volunteer.AnnouncementHomeResponseItem @@ -24,18 +15,25 @@ import com.kusitms.connectdog.core.data.api.model.volunteer.ApplyBody import com.kusitms.connectdog.core.data.api.model.volunteer.BadgeResponse import com.kusitms.connectdog.core.data.api.model.volunteer.BasicInformationResponse import com.kusitms.connectdog.core.data.api.model.volunteer.BookmarkResponseItem -import com.kusitms.connectdog.core.data.api.model.volunteer.EmailAuthDto -import com.kusitms.connectdog.core.data.api.model.volunteer.EmailCertificationBody -import com.kusitms.connectdog.core.data.api.model.volunteer.IsDuplicateNicknameBody -import com.kusitms.connectdog.core.data.api.model.volunteer.NormalVolunteerSignUpBody import com.kusitms.connectdog.core.data.api.model.volunteer.NoticeDetailResponseItem import com.kusitms.connectdog.core.data.api.model.volunteer.PasswordCheckResponse import com.kusitms.connectdog.core.data.api.model.volunteer.PasswordDto import com.kusitms.connectdog.core.data.api.model.volunteer.ReviewDetailResponse import com.kusitms.connectdog.core.data.api.model.volunteer.ReviewDetailWithId -import com.kusitms.connectdog.core.data.api.model.volunteer.SocialVolunteerSignUpBody import com.kusitms.connectdog.core.data.api.model.volunteer.UserInfoResponse import com.kusitms.connectdog.core.data.api.model.volunteer.VolunteerAccountInfo +import com.kusitms.connectdog.core.model.auth.AuthCodeWithAccessToken +import com.kusitms.connectdog.core.model.auth.Email +import com.kusitms.connectdog.core.model.auth.EmailAuthCode +import com.kusitms.connectdog.core.model.auth.Phone +import com.kusitms.connectdog.core.model.auth.PhoneNumberDuplication +import com.kusitms.connectdog.core.model.login.LoginResult +import com.kusitms.connectdog.core.model.login.NormalLogin +import com.kusitms.connectdog.core.model.login.SocialLogin +import com.kusitms.connectdog.core.model.signup.IsDuplicated +import com.kusitms.connectdog.core.model.signup.Nickname +import com.kusitms.connectdog.core.model.signup.NormalVolunteerDetail +import com.kusitms.connectdog.core.model.signup.SocialVolunteerDetail import okhttp3.MultipartBody import okhttp3.RequestBody import retrofit2.http.Body @@ -83,28 +81,28 @@ internal interface ApiService { */ @POST("/volunteers/nickname/isDuplicated") suspend fun postNickname( - @Body nickname: IsDuplicateNicknameBody - ): IsDuplicateNicknameResponse + @Body body: Nickname + ): IsDuplicated @POST("/volunteers/sign-up/email") - suspend fun postEmail( - @Body emailCertificationBody: EmailCertificationBody - ): AuthDto + suspend fun getEmailAuthCode( + @Body body: Email + ): EmailAuthCode @POST("/volunteers/sign-up") suspend fun postNormalVolunteerSignUp( - @Body normalVolunteerSignUpBody: NormalVolunteerSignUpBody + @Body body: NormalVolunteerDetail ) @PATCH("/volunteers/sign-up/social") suspend fun postSocialVolunteerSignUp( - @Body socialVolunteerSignUpBody: SocialVolunteerSignUpBody + @Body socialVolunteerSignUpBody: SocialVolunteerDetail ) @POST("/volunteers/phone/isDuplicated") - suspend fun getIsDuplicatePhoneNumber( - @Body isDuplicatePhoneNumberBody: IsDuplicatePhoneNumberBody - ): IsDuplicatePhoneNumberResponse + suspend fun getPhoneNumberDuplication( + @Body body: Phone + ): PhoneNumberDuplication /** * 봉사관리 @@ -147,25 +145,19 @@ internal interface ApiService { */ @Headers("Content-Type: application/json") @POST("/volunteers/login") - suspend fun postLoginData( - @Body loginBody: NormalLoginBody - ): LoginResponseItem - - @Headers("Content-Type: application/json") - @POST("/intermediaries/login") - suspend fun postIntermediatorLoginData( - @Body loginBody: NormalLoginBody - ): LoginResponseItem + suspend fun normalLogin( + @Body loginBody: NormalLogin + ): LoginResult @POST("/volunteers/login/social") suspend fun postSocialLoginData( - @Body socialLoginBody: SocialLoginBody - ): LoginResponseItem + @Body socialLoginBody: SocialLogin + ): LoginResult @POST("/volunteers/search/send-email") suspend fun volunteerPasswordSearchAuth( - @Body body: EmailDto - ): EmailAuthDto + @Body body: Email + ): AuthCodeWithAccessToken /**s * 이동봉사자 > 마이페이지 @@ -284,7 +276,7 @@ internal interface ApiService { suspend fun getVolunteerAccountInfo(): VolunteerAccountInfo @POST("/volunteers/search/email") - suspend fun volunteerEmailSearch( - @Body body: PhoneDto - ): EmailDto + suspend fun searchVolunteerEmail( + @Body body: Phone + ): Email } diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/InterApiService.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/InterApiService.kt index 335501855..071669646 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/InterApiService.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/InterApiService.kt @@ -1,13 +1,8 @@ package com.kusitms.connectdog.core.data.api -import com.kusitms.connectdog.core.data.api.model.EmailDto import com.kusitms.connectdog.core.data.api.model.FcmTokenRequestBody -import com.kusitms.connectdog.core.data.api.model.IsDuplicatePhoneNumberBody -import com.kusitms.connectdog.core.data.api.model.IsDuplicatePhoneNumberResponse -import com.kusitms.connectdog.core.data.api.model.PhoneDto import com.kusitms.connectdog.core.data.api.model.Response import com.kusitms.connectdog.core.data.api.model.VolunteerResponse -import com.kusitms.connectdog.core.data.api.model.intermediator.DuplicateDto import com.kusitms.connectdog.core.data.api.model.intermediator.InterAnnouncementDetailResponse import com.kusitms.connectdog.core.data.api.model.intermediator.InterApplicationCompletedResponseItem import com.kusitms.connectdog.core.data.api.model.intermediator.InterApplicationInProgressResponseItem @@ -17,16 +12,23 @@ import com.kusitms.connectdog.core.data.api.model.intermediator.InterProfileFind import com.kusitms.connectdog.core.data.api.model.intermediator.InterProfileInfoResponse import com.kusitms.connectdog.core.data.api.model.intermediator.IntermediatorAccountInfo import com.kusitms.connectdog.core.data.api.model.intermediator.IntermediatorProfileInfoResponseItem -import com.kusitms.connectdog.core.data.api.model.intermediator.NameDto -import com.kusitms.connectdog.core.data.api.model.volunteer.EmailAuthDto import com.kusitms.connectdog.core.data.api.model.volunteer.PasswordCheckResponse import com.kusitms.connectdog.core.data.api.model.volunteer.PasswordDto import com.kusitms.connectdog.core.data.api.model.volunteer.ReviewDetailResponse +import com.kusitms.connectdog.core.model.auth.AuthCodeWithAccessToken +import com.kusitms.connectdog.core.model.auth.Email +import com.kusitms.connectdog.core.model.auth.Phone +import com.kusitms.connectdog.core.model.auth.PhoneNumberDuplication +import com.kusitms.connectdog.core.model.login.LoginResult +import com.kusitms.connectdog.core.model.login.NormalLogin +import com.kusitms.connectdog.core.model.signup.IsDuplicated +import com.kusitms.connectdog.core.model.signup.Name import okhttp3.MultipartBody import okhttp3.RequestBody import retrofit2.http.Body import retrofit2.http.DELETE import retrofit2.http.GET +import retrofit2.http.Headers import retrofit2.http.Multipart import retrofit2.http.PATCH import retrofit2.http.POST @@ -36,6 +38,15 @@ import retrofit2.http.Query internal interface InterApiService { + /** + * 로그인 + */ + @Headers("Content-Type: application/json") + @POST("/intermediaries/login") + suspend fun normalLogin( + @Body body: NormalLogin + ): LoginResult + /** * 회원가입 */ @@ -47,14 +58,14 @@ internal interface InterApiService { ) @POST("/intermediaries/phone/isDuplicated") - suspend fun getIsDuplicatePhoneNumber( - @Body body: IsDuplicatePhoneNumberBody - ): IsDuplicatePhoneNumberResponse + suspend fun getPhoneNumberDuplication( + @Body body: Phone + ): PhoneNumberDuplication @POST("/intermediaries/name/isDuplicated") suspend fun checkIsDuplicateName( - @Body body: NameDto - ): DuplicateDto + @Body body: Name + ): IsDuplicated @POST("/intermediaries/password/check") suspend fun checkInterPassword( @@ -158,9 +169,9 @@ internal interface InterApiService { suspend fun patchNotification() @POST("/intermediaries/search/send-email") - suspend fun interPasswordSearchAuth( - @Body body: EmailDto - ): EmailAuthDto + suspend fun emailAuthForPasswordReset( + @Body body: Email + ): AuthCodeWithAccessToken @Multipart @POST("/intermediaries/posts") @@ -176,7 +187,7 @@ internal interface InterApiService { suspend fun interWithdraw() @POST("/intermediaries/search/email") - suspend fun interEmailSearch( - @Body body: PhoneDto - ): EmailDto + suspend fun searchIntermediatorEmail( + @Body body: Phone + ): Email } diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/AuthDto.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/AuthDto.kt deleted file mode 100644 index 33dd3cf4d..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/AuthDto.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model - -data class AuthDto( - val authCode: String -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/EmailDto.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/EmailDto.kt deleted file mode 100644 index dabd831b0..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/EmailDto.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model - -data class EmailDto( - val email: String -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicateNicknameResponse.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicateNicknameResponse.kt deleted file mode 100644 index 287e07d7a..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicateNicknameResponse.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model - -data class IsDuplicateNicknameResponse( - val isDuplicated: Boolean -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicatePhoneNumberBody.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicatePhoneNumberBody.kt deleted file mode 100644 index 2c9411856..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicatePhoneNumberBody.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model - -data class IsDuplicatePhoneNumberBody( - val phone: String -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicatePhoneNumberResponse.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicatePhoneNumberResponse.kt deleted file mode 100644 index c942be00a..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/IsDuplicatePhoneNumberResponse.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model - -data class IsDuplicatePhoneNumberResponse( - val isDuplicated: Boolean, - val socialType: String?, - val email: String? -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/NormalLoginBody.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/NormalLoginBody.kt deleted file mode 100644 index 8678e3a27..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/NormalLoginBody.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model - -data class NormalLoginBody( - val email: String, - val password: String -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/PhoneDto.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/PhoneDto.kt deleted file mode 100644 index c2b160711..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/PhoneDto.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model - -data class PhoneDto( - val phone: String -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/SocialLoginBody.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/SocialLoginBody.kt deleted file mode 100644 index 3f7554a54..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/SocialLoginBody.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model - -data class SocialLoginBody( - val accessToken: String, - val provider: String -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/EmailAuthDto.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/EmailAuthDto.kt deleted file mode 100644 index 98a19d223..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/EmailAuthDto.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model.volunteer - -data class EmailAuthDto( - val authCode: String, - val accessToken: String -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/EmailCertificationBody.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/EmailCertificationBody.kt deleted file mode 100644 index 3473527f6..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/EmailCertificationBody.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.kusitms.connectdog.core.data.api.model.volunteer - -data class EmailCertificationBody( - val email: String -) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/di/ApiModule.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/di/ApiModule.kt index eab102c32..177d162c2 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/di/ApiModule.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/di/ApiModule.kt @@ -1,16 +1,15 @@ package com.kusitms.connectdog.core.data.di -import android.content.Context import android.util.Log +import com.kusitms.connectdog.core.data.BuildConfig import com.kusitms.connectdog.core.data.api.ApiService import com.kusitms.connectdog.core.data.api.InterApiService -import com.kusitms.connectdog.core.data.repository.DataStoreRepository +import com.kusitms.connectdog.domain.repository.DataStoreRepository import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import dagger.Module import dagger.Provides import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking @@ -31,12 +30,10 @@ private const val TAG = "API Module" @Module @InstallIn(SingletonComponent::class) internal object ApiModule { - private const val BASE_URL = "https://dev-api.pawwithu.site/" - @Provides fun provideNetworkInterceptor(dataStoreRepository: DataStoreRepository): Interceptor = Interceptor { chain -> val request = chain.request() - val jwt = runBlocking { dataStoreRepository.accessTokenFlow.first().toString() } + val jwt = runBlocking { dataStoreRepository.getAccessToken().first().toString() } Log.d(TAG, "AccessToken: $jwt") @@ -57,12 +54,6 @@ internal object ApiModule { } } - @Provides - @Singleton - fun provideDataStoreRepository(@ApplicationContext context: Context): DataStoreRepository { - return DataStoreRepository(context) - } - @Provides @Singleton fun provideOkhttpClient(interceptor: Interceptor): OkHttpClient { @@ -93,7 +84,7 @@ internal object ApiModule { moshi: Moshi ): ApiService { return Retrofit.Builder() - .baseUrl(BASE_URL) + .baseUrl(BuildConfig.BASE_URL) .addConverterFactory(MoshiConverterFactory.create(moshi)) .client(okHttpClient).build() .create(ApiService::class.java) @@ -106,7 +97,7 @@ internal object ApiModule { moshi: Moshi ): InterApiService { return Retrofit.Builder() - .baseUrl(BASE_URL) + .baseUrl(BuildConfig.BASE_URL) .addConverterFactory(MoshiConverterFactory.create(moshi)) .client(okHttpClient).build() .create(InterApiService::class.java) @@ -114,8 +105,5 @@ internal object ApiModule { @Provides @Singleton - fun provideJson(): Json = - Json { - ignoreUnknownKeys = true - } + fun provideJson(): Json = Json { ignoreUnknownKeys = true } } diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/di/DataStoreModule.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/di/DataStoreModule.kt new file mode 100644 index 000000000..74b651068 --- /dev/null +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/di/DataStoreModule.kt @@ -0,0 +1,21 @@ +package com.kusitms.connectdog.core.data.di + +import android.content.Context +import com.kusitms.connectdog.core.data.repository.DataStoreRepositoryImpl +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@InstallIn(SingletonComponent::class) +@Module +internal object DataStoreModule { + @Provides + @Singleton + fun provideDataStoreRepository(@ApplicationContext context: Context): DataStoreRepository { + return DataStoreRepositoryImpl(context) + } +} \ No newline at end of file diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/di/VolunteerDataModule.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/di/VolunteerDataModule.kt index 0d13f0ac5..a53183919 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/di/VolunteerDataModule.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/di/VolunteerDataModule.kt @@ -4,18 +4,20 @@ import com.kusitms.connectdog.core.data.api.ApiService import com.kusitms.connectdog.core.data.api.InterApiService import com.kusitms.connectdog.core.data.repository.ApplyRepository import com.kusitms.connectdog.core.data.repository.ApplyRepositoryImpl +import com.kusitms.connectdog.core.data.repository.AuthRepositoryImpl import com.kusitms.connectdog.core.data.repository.DetailRepository import com.kusitms.connectdog.core.data.repository.DetailRepositoryImpl import com.kusitms.connectdog.core.data.repository.HomeRepository import com.kusitms.connectdog.core.data.repository.HomeRepositoryImpl -import com.kusitms.connectdog.core.data.repository.LoginRepository import com.kusitms.connectdog.core.data.repository.LoginRepositoryImpl import com.kusitms.connectdog.core.data.repository.ManagementRepository import com.kusitms.connectdog.core.data.repository.ManagementRepositoryImpl import com.kusitms.connectdog.core.data.repository.MyPageRepository import com.kusitms.connectdog.core.data.repository.MyPageRepositoryImpl -import com.kusitms.connectdog.core.data.repository.SignUpRepository import com.kusitms.connectdog.core.data.repository.SignUpRepositoryImpl +import com.kusitms.connectdog.domain.repository.AuthRepository +import com.kusitms.connectdog.domain.repository.LoginRepository +import com.kusitms.connectdog.domain.repository.SignUpRepository import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -26,6 +28,24 @@ import javax.inject.Singleton @Module internal class VolunteerDataModule { + @Provides + @Singleton + fun provideLoginRepository( + apiService: ApiService, + intermediatorApi: InterApiService + ): LoginRepository { + return LoginRepositoryImpl(apiService, intermediatorApi) + } + + @Provides + @Singleton + fun provideAuthRepository( + apiService: ApiService, + intermediatorApi: InterApiService + ): AuthRepository { + return AuthRepositoryImpl(apiService, intermediatorApi) + } + @Provides @Singleton fun provideSignUpRepository( @@ -37,11 +57,11 @@ internal class VolunteerDataModule { @Provides @Singleton - fun provideLoginRepository( - apiService: ApiService, + fun provideTestRepository( + volunteerApi: ApiService, intermediatorApi: InterApiService - ): LoginRepository { - return LoginRepositoryImpl(apiService, intermediatorApi) + ): com.kusitms.connectdog.core.data.repository.SignUpRepository { + return SignUpRepositoryImpl(volunteerApi, intermediatorApi) } @Provides diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/AuthRepositoryImpl.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/AuthRepositoryImpl.kt new file mode 100644 index 000000000..07fa07699 --- /dev/null +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/AuthRepositoryImpl.kt @@ -0,0 +1,65 @@ +package com.kusitms.connectdog.core.data.repository + +import com.kusitms.connectdog.core.data.api.ApiService +import com.kusitms.connectdog.core.data.api.InterApiService +import com.kusitms.connectdog.core.model.auth.Email +import com.kusitms.connectdog.core.model.auth.Phone +import com.kusitms.connectdog.core.model.auth.AuthCodeWithAccessToken +import com.kusitms.connectdog.core.model.auth.EmailAuthCode +import com.kusitms.connectdog.core.model.auth.PhoneNumberDuplication +import com.kusitms.connectdog.domain.repository.AuthRepository +import javax.inject.Inject + +internal class AuthRepositoryImpl @Inject constructor( + private val volunteerApi: ApiService, + private val intermediatorApi: InterApiService +) : AuthRepository { + override suspend fun getEmailAuthCode( + email: String + ): Result = runCatching { + val body = Email(email) + return@runCatching volunteerApi.getEmailAuthCode(body) + } + + override suspend fun searchVolunteerEmail( + phone: String + ): Result = runCatching { + val body = Phone(phone = phone) + return@runCatching volunteerApi.searchVolunteerEmail(body) + } + + override suspend fun searchIntermediatorEmail( + phone: String + ): Result = runCatching { + val body = Phone(phone = phone) + return@runCatching intermediatorApi.searchIntermediatorEmail(body) + } + + override suspend fun emailAuthForVolunteerPasswordReset( + email: String + ): Result = runCatching { + val body = Email(email = email) + return@runCatching volunteerApi.volunteerPasswordSearchAuth(body) + } + + override suspend fun emailAuthForIntermediatorPasswordReset( + email: String + ): Result = runCatching { + val body = Email(email = email) + return@runCatching intermediatorApi.emailAuthForPasswordReset(body) + } + + override suspend fun getVolunteerPhoneNumberDuplication( + phone: String + ): Result = runCatching { + val body = Phone(phone = phone) + return@runCatching volunteerApi.getPhoneNumberDuplication(body) + } + + override suspend fun getIntermediatorPhoneNumberDuplication( + phone: String + ): Result = runCatching { + val body = Phone(phone = phone) + return@runCatching intermediatorApi.getPhoneNumberDuplication(body) + } +} \ No newline at end of file diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/DataStoreRepository.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/DataStoreRepository.kt deleted file mode 100644 index 5c29f7b87..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/DataStoreRepository.kt +++ /dev/null @@ -1,106 +0,0 @@ -package com.kusitms.connectdog.core.data.repository - -import android.content.Context -import androidx.datastore.core.DataStore -import androidx.datastore.preferences.core.Preferences -import androidx.datastore.preferences.core.edit -import androidx.datastore.preferences.core.stringPreferencesKey -import androidx.datastore.preferences.preferencesDataStore -import com.kusitms.connectdog.core.util.AppMode -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.android.scopes.ActivityRetainedScoped -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.map -import javax.inject.Inject - -private val Context.dataStore: DataStore by preferencesDataStore(name = "TokenDataStore") - -@ActivityRetainedScoped -class DataStoreRepository @Inject constructor( - @ApplicationContext private val context: Context -) { - private object PreferenceKeys { - val accessToken = stringPreferencesKey("access_token") - val refreshToken = stringPreferencesKey("refresh_token") - val socialToken = stringPreferencesKey("social_token") - val fcmToken = stringPreferencesKey("fcm_token") - val appMode = stringPreferencesKey("app_mode") - val socialProvider = stringPreferencesKey("social_provider") - } - - suspend fun saveSocialToken(accessToken: String) { - context.dataStore.edit { preferences -> - preferences[PreferenceKeys.socialToken] = accessToken - } - } - - suspend fun saveAccessToken(accessToken: String) { - context.dataStore.edit { preferences -> - preferences[PreferenceKeys.accessToken] = accessToken - } - } - - suspend fun deleteAccessToken() { - context.dataStore.edit { preferences -> - preferences.remove(PreferenceKeys.accessToken) - } - } - - suspend fun saveRefreshToken(refreshToken: String) { - context.dataStore.edit { preferences -> - preferences[PreferenceKeys.refreshToken] = refreshToken - } - } - - suspend fun saveAppMode(appMode: AppMode) { - context.dataStore.edit { preferences -> - preferences[PreferenceKeys.appMode] = appMode.name - } - } - - suspend fun saveFcmToken(fcmToken: String) { - context.dataStore.edit { preferences -> - preferences[PreferenceKeys.fcmToken] = fcmToken - } - } - - suspend fun saveSocialProvider(provider: String) { - context.dataStore.edit { preferences -> - preferences[PreferenceKeys.socialProvider] = provider - } - } - - val accessTokenFlow: Flow = context.dataStore.data - .map { preferences -> - preferences[PreferenceKeys.accessToken] - } - - val appModeFlow: Flow = context.dataStore.data - .map { preferences -> - AppMode.valueOf(preferences[PreferenceKeys.appMode].toString()) - } - .catch { - emit(AppMode.LOGIN) - } - - val refreshTokenFlow: Flow = context.dataStore.data - .map { preferences -> - preferences[PreferenceKeys.accessToken] - } - - val fcmTokenFlow: Flow = context.dataStore.data - .map { preferences -> - preferences[PreferenceKeys.fcmToken] - } - - val socialTokenFlow: Flow = context.dataStore.data - .map { preferences -> - preferences[PreferenceKeys.socialToken] - } - - val socialProviderFlow: Flow = context.dataStore.data - .map { preferences -> - preferences[PreferenceKeys.socialProvider] - } -} diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/DataStoreRepositoryImpl.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/DataStoreRepositoryImpl.kt new file mode 100644 index 000000000..681a66a1b --- /dev/null +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/DataStoreRepositoryImpl.kt @@ -0,0 +1,102 @@ +package com.kusitms.connectdog.core.data.repository + +import android.content.Context +import android.util.Log +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.stringPreferencesKey +import androidx.datastore.preferences.preferencesDataStore +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import com.kusitms.connectdog.domain.usecase.login.AppMode +import com.kusitms.connectdog.domain.usecase.login.SocialLoginProvider +import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.map +import javax.inject.Inject + +object PreferenceKeys { + val accessToken = stringPreferencesKey("access_token") + val refreshToken = stringPreferencesKey("refresh_token") + val socialToken = stringPreferencesKey("social_token") + val fcmToken = stringPreferencesKey("fcm_token") + val appMode = stringPreferencesKey("app_mode") + val socialProvider = stringPreferencesKey("social_provider") +} + +private val Context.dataStore: DataStore by preferencesDataStore(name = "ConnectDogDataStore") + +class DataStoreRepositoryImpl @Inject constructor( + @ApplicationContext private val context: Context +) : DataStoreRepository { + override suspend fun updateAccessToken(accessToken: String) { + context.dataStore.edit { preferences -> + preferences[PreferenceKeys.accessToken] = accessToken + } + } + + override suspend fun updateRefreshToken(refreshToken: String) { + context.dataStore.edit { preferences -> + preferences[PreferenceKeys.accessToken] = refreshToken + } + } + + override suspend fun updateAppMode(appMode: AppMode) { + context.dataStore.edit { preferences -> + preferences[PreferenceKeys.appMode] = appMode.toString() + } + } + + override suspend fun updateFcmToken(fcmToken: String) { + context.dataStore.edit { preferences -> + preferences[PreferenceKeys.fcmToken] = fcmToken + } + } + + override suspend fun updateSocialToken(token: String) { + context.dataStore.edit { preferences -> + preferences[PreferenceKeys.socialToken] = token + } + } + + override suspend fun updateSocialLoginProvider(provider: SocialLoginProvider) { + context.dataStore.edit { preferences -> + preferences[PreferenceKeys.socialProvider] = provider.toString() + } + } + + override suspend fun getFcmToken(): Flow = context.dataStore.data.map { preferences -> + preferences[PreferenceKeys.fcmToken] + } + + override suspend fun getRefreshToken(): Flow = context.dataStore.data.map { preferences -> + preferences[PreferenceKeys.refreshToken] + } + + override suspend fun getAccessToken(): Flow = context.dataStore.data.map { preferences -> + preferences[PreferenceKeys.accessToken] + } + + override suspend fun getAppMode(): Flow = context.dataStore.data + .map { preferences -> + AppMode.valueOf(preferences[PreferenceKeys.appMode].toString()) + } + .catch { + emit(AppMode.LOGIN) + } + + override suspend fun getSocialToken(): Flow = context.dataStore.data.map { preferences -> + preferences[PreferenceKeys.socialToken] + } + + override suspend fun getSocialLoginProvider(): Flow { + TODO("Not yet implemented") + } + + override suspend fun deleteAccessToken() { + context.dataStore.edit { preferences -> + preferences[PreferenceKeys.fcmToken] = "" + } + } +} \ No newline at end of file diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/LoginRepository.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/LoginRepository.kt deleted file mode 100644 index 13a7416c6..000000000 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/LoginRepository.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.kusitms.connectdog.core.data.repository - -import com.kusitms.connectdog.core.data.api.model.EmailDto -import com.kusitms.connectdog.core.data.api.model.LoginResponseItem -import com.kusitms.connectdog.core.data.api.model.NormalLoginBody -import com.kusitms.connectdog.core.data.api.model.SocialLoginBody -import com.kusitms.connectdog.core.data.api.model.volunteer.EmailAuthDto - -interface LoginRepository { - suspend fun postLoginData( - loginBody: NormalLoginBody - ): LoginResponseItem - - suspend fun postSocialLoginData( - socialLoginBody: SocialLoginBody - ): LoginResponseItem - - suspend fun postIntermediatorLoginData( - loginBody: NormalLoginBody - ): LoginResponseItem - - suspend fun volunteerEmailSearch(phone: String): EmailDto - - suspend fun interEmailSearch(phone: String): EmailDto - - suspend fun volunteerPasswordSearchAuth(email: String): EmailAuthDto - - suspend fun interPasswordSearchAuth(email: String): EmailAuthDto - - suspend fun logout() -} diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/LoginRepositoryImpl.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/LoginRepositoryImpl.kt index c32491a3c..6be9774d5 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/LoginRepositoryImpl.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/LoginRepositoryImpl.kt @@ -2,59 +2,41 @@ package com.kusitms.connectdog.core.data.repository import com.kusitms.connectdog.core.data.api.ApiService import com.kusitms.connectdog.core.data.api.InterApiService -import com.kusitms.connectdog.core.data.api.model.EmailDto -import com.kusitms.connectdog.core.data.api.model.LoginResponseItem -import com.kusitms.connectdog.core.data.api.model.NormalLoginBody -import com.kusitms.connectdog.core.data.api.model.PhoneDto -import com.kusitms.connectdog.core.data.api.model.SocialLoginBody -import com.kusitms.connectdog.core.data.api.model.volunteer.EmailAuthDto +import com.kusitms.connectdog.core.model.login.LoginResult +import com.kusitms.connectdog.core.model.login.NormalLogin +import com.kusitms.connectdog.core.model.login.SocialLogin +import com.kusitms.connectdog.domain.repository.LoginRepository import javax.inject.Inject internal class LoginRepositoryImpl @Inject constructor( - private val api: ApiService, - private val interApi: InterApiService + private val volunteerApi: ApiService, + private val intermediatorApi: InterApiService ) : LoginRepository { - override suspend fun postLoginData( - loginBody: NormalLoginBody - ): LoginResponseItem { - return api.postLoginData( - loginBody - ) + override suspend fun volunteerNormalLogin( + email: String, + password: String + ): Result = runCatching { + val body = NormalLogin(email, password) + return@runCatching volunteerApi.normalLogin(body) } - override suspend fun postSocialLoginData( - socialLoginBody: SocialLoginBody - ): LoginResponseItem { - return api.postSocialLoginData( - socialLoginBody - ) + override suspend fun intermediatorNormalLogin( + email: String, + password: String + ): Result = runCatching { + val body = NormalLogin(email, password) + return@runCatching intermediatorApi.normalLogin(body) } - override suspend fun postIntermediatorLoginData(loginBody: NormalLoginBody): LoginResponseItem { - return api.postIntermediatorLoginData(loginBody) + override suspend fun socialLogin( + accessToken: String, + provider: String + ): Result = runCatching{ + val body = SocialLogin(accessToken, provider) + return@runCatching volunteerApi.postSocialLoginData(body) } - override suspend fun volunteerEmailSearch(phone: String): EmailDto { - val body = PhoneDto(phone = phone) - return api.volunteerEmailSearch(body) - } - - override suspend fun interEmailSearch(phone: String): EmailDto { - val body = PhoneDto(phone = phone) - return interApi.interEmailSearch(body) - } - - override suspend fun volunteerPasswordSearchAuth(email: String): EmailAuthDto { - val body = EmailDto(email = email) - return api.volunteerPasswordSearchAuth(body) - } - - override suspend fun interPasswordSearchAuth(email: String): EmailAuthDto { - val body = EmailDto(email = email) - return interApi.interPasswordSearchAuth(body) - } - - override suspend fun logout() { - return api.logout() + override suspend fun logout() = runCatching { + return@runCatching volunteerApi.logout() } } diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/MyPageRepository.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/MyPageRepository.kt index 424bfc5f9..ea986c287 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/MyPageRepository.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/MyPageRepository.kt @@ -1,20 +1,20 @@ package com.kusitms.connectdog.core.data.repository -import com.kusitms.connectdog.core.data.api.model.IsDuplicateNicknameResponse import com.kusitms.connectdog.core.data.api.model.MyInfoResponseItem import com.kusitms.connectdog.core.data.api.model.intermediator.IntermediatorAccountInfo import com.kusitms.connectdog.core.data.api.model.volunteer.BadgeResponse import com.kusitms.connectdog.core.data.api.model.volunteer.BookmarkResponseItem -import com.kusitms.connectdog.core.data.api.model.volunteer.IsDuplicateNicknameBody import com.kusitms.connectdog.core.data.api.model.volunteer.UserInfoResponse import com.kusitms.connectdog.core.data.api.model.volunteer.VolunteerAccountInfo +import com.kusitms.connectdog.core.model.signup.IsDuplicated +import com.kusitms.connectdog.core.model.signup.Nickname interface MyPageRepository { suspend fun getMyInfo(): MyInfoResponseItem suspend fun getUserInfo(): UserInfoResponse suspend fun getBadge(): List suspend fun getBookmarkData(): List - suspend fun postNickname(nickname: IsDuplicateNicknameBody): IsDuplicateNicknameResponse + suspend fun postNickname(nickname: Nickname): IsDuplicated suspend fun updateUserInfo(userInfo: UserInfoResponse) suspend fun updateNotification() suspend fun getVolunteerAccountInfo(): VolunteerAccountInfo diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/MyPageRepositoryImpl.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/MyPageRepositoryImpl.kt index 0c11391ac..57d033f1e 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/MyPageRepositoryImpl.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/MyPageRepositoryImpl.kt @@ -2,14 +2,14 @@ package com.kusitms.connectdog.core.data.repository import com.kusitms.connectdog.core.data.api.ApiService import com.kusitms.connectdog.core.data.api.InterApiService -import com.kusitms.connectdog.core.data.api.model.IsDuplicateNicknameResponse import com.kusitms.connectdog.core.data.api.model.MyInfoResponseItem import com.kusitms.connectdog.core.data.api.model.intermediator.IntermediatorAccountInfo import com.kusitms.connectdog.core.data.api.model.volunteer.BadgeResponse import com.kusitms.connectdog.core.data.api.model.volunteer.BookmarkResponseItem -import com.kusitms.connectdog.core.data.api.model.volunteer.IsDuplicateNicknameBody import com.kusitms.connectdog.core.data.api.model.volunteer.UserInfoResponse import com.kusitms.connectdog.core.data.api.model.volunteer.VolunteerAccountInfo +import com.kusitms.connectdog.core.model.signup.IsDuplicated +import com.kusitms.connectdog.core.model.signup.Nickname import javax.inject.Inject internal class MyPageRepositoryImpl @Inject constructor( @@ -32,7 +32,7 @@ internal class MyPageRepositoryImpl @Inject constructor( return api.getBookmarkData() } - override suspend fun postNickname(nickname: IsDuplicateNicknameBody): IsDuplicateNicknameResponse { + override suspend fun postNickname(nickname: Nickname): IsDuplicated { return api.postNickname(nickname) } diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/SignUpRepository.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/SignUpRepository.kt index f7cad69a1..aa05293e5 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/SignUpRepository.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/SignUpRepository.kt @@ -1,28 +1,8 @@ package com.kusitms.connectdog.core.data.repository -import com.kusitms.connectdog.core.data.api.model.AuthDto -import com.kusitms.connectdog.core.data.api.model.IsDuplicateNicknameResponse -import com.kusitms.connectdog.core.data.api.model.IsDuplicatePhoneNumberBody -import com.kusitms.connectdog.core.data.api.model.IsDuplicatePhoneNumberResponse -import com.kusitms.connectdog.core.data.api.model.intermediator.DuplicateDto -import com.kusitms.connectdog.core.data.api.model.intermediator.IntermediatorSignUpBody -import com.kusitms.connectdog.core.data.api.model.intermediator.NameDto -import com.kusitms.connectdog.core.data.api.model.volunteer.EmailCertificationBody -import com.kusitms.connectdog.core.data.api.model.volunteer.IsDuplicateNicknameBody -import com.kusitms.connectdog.core.data.api.model.volunteer.NormalVolunteerSignUpBody import com.kusitms.connectdog.core.data.api.model.volunteer.PasswordCheckResponse -import com.kusitms.connectdog.core.data.api.model.volunteer.SocialVolunteerSignUpBody -import java.io.File interface SignUpRepository { - suspend fun postNickname(nickname: IsDuplicateNicknameBody): IsDuplicateNicknameResponse - suspend fun postEmail(email: EmailCertificationBody): AuthDto - suspend fun postNormalVolunteerSignUp(signUp: NormalVolunteerSignUpBody) - suspend fun postSocialVolunteerSignUp(signUp: SocialVolunteerSignUpBody) - suspend fun postIntermediatorSignUp(signUp: IntermediatorSignUpBody, file: File) - suspend fun getVolunteerPhoneNumberDuplicated(body: IsDuplicatePhoneNumberBody): IsDuplicatePhoneNumberResponse - suspend fun getInterMediatorPhoneNumberDuplicated(body: IsDuplicatePhoneNumberBody): IsDuplicatePhoneNumberResponse - suspend fun isDuplicateInterNickName(body: NameDto): DuplicateDto suspend fun checkVolunteerPassword(password: String): PasswordCheckResponse suspend fun checkInterPassword(password: String): PasswordCheckResponse suspend fun changeVolunteerPassword(password: String) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/SignUpRepositoryImpl.kt b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/SignUpRepositoryImpl.kt index 7d86c8b93..fdf8e5201 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/SignUpRepositoryImpl.kt +++ b/core/data/src/main/java/com/kusitms/connectdog/core/data/repository/SignUpRepositoryImpl.kt @@ -1,89 +1,125 @@ package com.kusitms.connectdog.core.data.repository -import com.google.gson.Gson import com.kusitms.connectdog.core.data.api.ApiService import com.kusitms.connectdog.core.data.api.InterApiService -import com.kusitms.connectdog.core.data.api.model.AuthDto -import com.kusitms.connectdog.core.data.api.model.IsDuplicateNicknameResponse -import com.kusitms.connectdog.core.data.api.model.IsDuplicatePhoneNumberBody -import com.kusitms.connectdog.core.data.api.model.IsDuplicatePhoneNumberResponse -import com.kusitms.connectdog.core.data.api.model.intermediator.DuplicateDto -import com.kusitms.connectdog.core.data.api.model.intermediator.IntermediatorSignUpBody -import com.kusitms.connectdog.core.data.api.model.intermediator.NameDto -import com.kusitms.connectdog.core.data.api.model.volunteer.EmailCertificationBody -import com.kusitms.connectdog.core.data.api.model.volunteer.IsDuplicateNicknameBody -import com.kusitms.connectdog.core.data.api.model.volunteer.NormalVolunteerSignUpBody import com.kusitms.connectdog.core.data.api.model.volunteer.PasswordCheckResponse -import com.kusitms.connectdog.core.data.api.model.volunteer.PasswordDto -import com.kusitms.connectdog.core.data.api.model.volunteer.SocialVolunteerSignUpBody -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody -import java.io.File +import com.kusitms.connectdog.core.model.signup.IsDuplicated +import com.kusitms.connectdog.core.model.signup.Name +import com.kusitms.connectdog.core.model.signup.Nickname +import com.kusitms.connectdog.core.model.signup.NormalVolunteerDetail +import com.kusitms.connectdog.core.model.signup.SocialVolunteerDetail +import com.kusitms.connectdog.domain.repository.SignUpRepository import javax.inject.Inject internal class SignUpRepositoryImpl @Inject constructor( private val volunteerApi: ApiService, private val intermediatorApi: InterApiService -) : SignUpRepository { - override suspend fun postNickname(nickname: IsDuplicateNicknameBody): IsDuplicateNicknameResponse { - return volunteerApi.postNickname(nickname) +) : SignUpRepository, com.kusitms.connectdog.core.data.repository.SignUpRepository { + override suspend fun getVolunteerNicknameDuplication( + nickname: String + ): Result = runCatching { + val body = Nickname(nickname) + return@runCatching volunteerApi.postNickname(body) } - override suspend fun postEmail(email: EmailCertificationBody): AuthDto { - return volunteerApi.postEmail(email) + override suspend fun getIntermediatorNicknameDuplication( + name: String + ): Result = runCatching { + val body = Name(name) + return@runCatching intermediatorApi.checkIsDuplicateName(body) } - override suspend fun postNormalVolunteerSignUp(signUp: NormalVolunteerSignUpBody) { - volunteerApi.postNormalVolunteerSignUp(signUp) - } - - override suspend fun postSocialVolunteerSignUp(signUp: SocialVolunteerSignUpBody) { - return volunteerApi.postSocialVolunteerSignUp(signUp) - } - - override suspend fun postIntermediatorSignUp(signUp: IntermediatorSignUpBody, image: File) { - val jsonBody = RequestBody.create( - "application/json; charset=utf-8".toMediaTypeOrNull(), - Gson().toJson(signUp) + override suspend fun initNormalVolunteerSignUp( + email: String, + password: String, + nickname: String, + profileImageNum: Int, + isOptionAgr: Boolean, + phone: String, + name: String + ): Result = runCatching { + val body = NormalVolunteerDetail( + email = email, + password = password, + nickname = nickname, + profileImageNum = profileImageNum, + isOptionAgr = isOptionAgr, + phone = phone, + name = name ) - - val fileBody = RequestBody.create("multipart/form-data".toMediaTypeOrNull(), image) - - val file = MultipartBody.Part.createFormData("profileImage", image.name, fileBody) - - return intermediatorApi.intermediatorSignUp(jsonBody, file) - } - - override suspend fun getVolunteerPhoneNumberDuplicated(body: IsDuplicatePhoneNumberBody): IsDuplicatePhoneNumberResponse { - return volunteerApi.getIsDuplicatePhoneNumber(body) + volunteerApi.postNormalVolunteerSignUp(body) } - override suspend fun getInterMediatorPhoneNumberDuplicated(body: IsDuplicatePhoneNumberBody): IsDuplicatePhoneNumberResponse { - return intermediatorApi.getIsDuplicatePhoneNumber(body) + override suspend fun initSocialVolunteerSignUp( + nickname: String, + profileImageNum: Int, + isOptionAgr: Boolean, + phone: String, + name: String + ): Result = runCatching { + val body = SocialVolunteerDetail( + nickname = nickname, + profileImageNum = profileImageNum, + isOptionAgr = isOptionAgr, + phone = phone, + name = name + ) + return@runCatching volunteerApi.postSocialVolunteerSignUp(body) } - override suspend fun isDuplicateInterNickName(body: NameDto): DuplicateDto { - return intermediatorApi.checkIsDuplicateName(body) - } +// override suspend fun postIntermediatorSignUp(signUp: IntermediatorSignUpBody, image: File) { +// val jsonBody = RequestBody.create( +// "application/json; charset=utf-8".toMediaTypeOrNull(), +// Gson().toJson(signUp) +// ) +// +// val fileBody = RequestBody.create("multipart/form-data".toMediaTypeOrNull(), image) +// val file = MultipartBody.Part.createFormData("profileImage", image.name, fileBody) +// +// return intermediatorApi.intermediatorSignUp(jsonBody, file) +// } +// +// override suspend fun getVolunteerPhoneNumberDuplicated(body: IsDuplicatePhoneNumberBody): IsDuplicatePhoneNumberResponse { +// return volunteerApi.getIsDuplicatePhoneNumber(body) +// } +// +// override suspend fun getInterMediatorPhoneNumberDuplicated(body: IsDuplicatePhoneNumberBody): IsDuplicatePhoneNumberResponse { +// return intermediatorApi.getIsDuplicatePhoneNumber(body) +// } +// +// override suspend fun checkVolunteerPassword(password: String): PasswordCheckResponse { +// val body = PasswordDto(password) +// return volunteerApi.checkVolunteerPassword(body) +// } +// +// override suspend fun checkInterPassword(password: String): PasswordCheckResponse { +// val body = PasswordDto(password) +// return intermediatorApi.checkInterPassword(body) +// } +// +// override suspend fun changeVolunteerPassword(password: String) { +// val body = PasswordDto(password) +// volunteerApi.changeVolunteerPassword(body) +// } +// +// override suspend fun changeInterPassword(password: String) { +// val body = PasswordDto(password) +// intermediatorApi.changeInterPassword(body) +// } override suspend fun checkVolunteerPassword(password: String): PasswordCheckResponse { - val body = PasswordDto(password) - return volunteerApi.checkVolunteerPassword(body) + TODO("Not yet implemented") } override suspend fun checkInterPassword(password: String): PasswordCheckResponse { - val body = PasswordDto(password) - return intermediatorApi.checkInterPassword(body) + TODO("Not yet implemented") } override suspend fun changeVolunteerPassword(password: String) { - val body = PasswordDto(password) - volunteerApi.changeVolunteerPassword(body) + TODO("Not yet implemented") } override suspend fun changeInterPassword(password: String) { - val body = PasswordDto(password) - intermediatorApi.changeInterPassword(body) + TODO("Not yet implemented") } } diff --git a/core/designsystem/build/generated/source/buildConfig/debug/com/kusitms/connectdog/core/designsystem/BuildConfig.java b/core/designsystem/build/generated/source/buildConfig/debug/com/kusitms/connectdog/core/designsystem/BuildConfig.java new file mode 100644 index 000000000..5fb8a9d0e --- /dev/null +++ b/core/designsystem/build/generated/source/buildConfig/debug/com/kusitms/connectdog/core/designsystem/BuildConfig.java @@ -0,0 +1,10 @@ +/** + * Automatically generated file. DO NOT MODIFY + */ +package com.kusitms.connectdog.core.designsystem; + +public final class BuildConfig { + public static final boolean DEBUG = Boolean.parseBoolean("true"); + public static final String LIBRARY_PACKAGE_NAME = "com.kusitms.connectdog.core.designsystem"; + public static final String BUILD_TYPE = "debug"; +} diff --git a/core/designsystem/build/generated/source/buildConfig/release/com/kusitms/connectdog/core/designsystem/BuildConfig.java b/core/designsystem/build/generated/source/buildConfig/release/com/kusitms/connectdog/core/designsystem/BuildConfig.java new file mode 100644 index 000000000..37f0ec558 --- /dev/null +++ b/core/designsystem/build/generated/source/buildConfig/release/com/kusitms/connectdog/core/designsystem/BuildConfig.java @@ -0,0 +1,10 @@ +/** + * Automatically generated file. DO NOT MODIFY + */ +package com.kusitms.connectdog.core.designsystem; + +public final class BuildConfig { + public static final boolean DEBUG = false; + public static final String LIBRARY_PACKAGE_NAME = "com.kusitms.connectdog.core.designsystem"; + public static final String BUILD_TYPE = "release"; +} diff --git a/core/designsystem/build/reports/ktlint/ktlintKotlinScriptFormat/ktlintKotlinScriptFormat.txt b/core/designsystem/build/reports/ktlint/ktlintKotlinScriptFormat/ktlintKotlinScriptFormat.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/ActionRow.kt b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/ActionRow.kt new file mode 100644 index 000000000..932f80cae --- /dev/null +++ b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/ActionRow.kt @@ -0,0 +1,40 @@ +package com.kusitms.connectdog.core.designsystem.component + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.kusitms.connectdog.core.designsystem.theme.Gray2 + +@Composable +fun ActionRow( + vararg items: Pair Unit> +) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + items.forEachIndexed { index, item -> + Text( + modifier = Modifier.clickable { item.second() }, + text = item.first, + fontSize = 12.sp, + color = Gray2 + ) + if (index != items.lastIndex) { + Text( + modifier = Modifier.padding(horizontal = 16.dp), + text = "|", + fontSize = 12.sp, + color = Gray2 + ) + } + } + } +} \ No newline at end of file diff --git a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/Banner.kt b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/Banner.kt index 6ae0bed2f..bf02d0901 100644 --- a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/Banner.kt +++ b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/Banner.kt @@ -2,6 +2,7 @@ package com.kusitms.connectdog.core.designsystem.component import android.widget.Toast import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row @@ -14,6 +15,7 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource @@ -24,6 +26,7 @@ import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.kusitms.connectdog.core.designsystem.R +import com.kusitms.connectdog.core.designsystem.theme.Gray5 import com.kusitms.connectdog.core.designsystem.theme.PetOrange @Composable @@ -34,8 +37,11 @@ fun BannerGuideline( Row( modifier = Modifier + .padding(horizontal = 20.dp) + .padding(vertical = 12.dp) .fillMaxWidth() .defaultMinSize(minHeight = 84.dp) + .clip(RoundedCornerShape(12.dp)) .background(MaterialTheme.colorScheme.primary) .padding(horizontal = 20.dp), verticalAlignment = Alignment.CenterVertically, diff --git a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/CheckBox.kt b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/CheckBox.kt new file mode 100644 index 000000000..aa46874d0 --- /dev/null +++ b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/CheckBox.kt @@ -0,0 +1,78 @@ +package com.kusitms.connectdog.core.designsystem.component + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.kusitms.connectdog.core.designsystem.R +import com.kusitms.connectdog.core.designsystem.theme.Gray1 +import com.kusitms.connectdog.core.designsystem.theme.Gray2 +import com.kusitms.connectdog.core.designsystem.theme.Gray4 +import com.kusitms.connectdog.core.designsystem.theme.PetOrange + +@Composable +fun CheckBox( + text: String, + checked: Boolean, + onClick: () -> Unit, + hasDetail: Boolean, + onDetailClick: () -> Unit = {} +) { + var isChecked by remember { mutableStateOf(checked) } + if (checked != isChecked) isChecked = checked + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp) + .clickable { + onClick() + isChecked = !isChecked + }, + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + painter = painterResource(id = R.drawable.ic_checked), + contentDescription = null, + tint = if (isChecked) PetOrange else Gray4, + modifier = Modifier.size(24.dp) + ) + Spacer(modifier = Modifier.width(12.dp)) + Text( + text = text, + fontSize = 14.sp, + fontWeight = FontWeight.Medium, + color = if (isChecked) Color.Black else Gray2 + ) + Spacer(modifier = Modifier.weight(1f)) + if (hasDetail) { + Text( + modifier = Modifier.clickable { onDetailClick() }, + text = "보기", + style = TextStyle(textDecoration = TextDecoration.Underline), + fontSize = 14.sp, + fontWeight = FontWeight.Medium, + color = if (isChecked) Gray1 else Gray2, + ) + } + } +} diff --git a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/Line.kt b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/Line.kt new file mode 100644 index 000000000..981fa6d84 --- /dev/null +++ b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/Line.kt @@ -0,0 +1,31 @@ +package com.kusitms.connectdog.core.designsystem.component + +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp + +@Composable +fun HorizontalLine( + height: Int, + color: Color +) { + Canvas( + modifier = Modifier + .fillMaxWidth() + .height(height.dp) + .padding(horizontal = 20.dp) + ) { + drawLine( + color = color, + start = Offset(0f, 0f), + end = Offset(size.width, 0f), + strokeWidth = 1f + ) + } +} \ No newline at end of file diff --git a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/SearchBar.kt b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/SearchBar.kt new file mode 100644 index 000000000..d886bf4df --- /dev/null +++ b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/SearchBar.kt @@ -0,0 +1,82 @@ +package com.kusitms.connectdog.core.designsystem.component + +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Search +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.withStyle +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.kusitms.connectdog.core.designsystem.R +import com.kusitms.connectdog.core.designsystem.theme.Gray1 +import com.kusitms.connectdog.core.designsystem.theme.Gray3 +import com.kusitms.connectdog.core.designsystem.theme.Gray5 + +@Composable +fun SearchBar( + onClick: () -> Unit, +) { + Row( + modifier = Modifier + .padding(horizontal = 20.dp) + .padding(vertical = 12.dp) + .fillMaxWidth() + .border( + width = 1.dp, + color = Gray5, + shape = RoundedCornerShape(90.dp) + ) + .clickable { onClick() }, + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + modifier = Modifier + .padding(start = 20.dp) + .size(24.dp), + imageVector = Icons.Filled.Search, + tint = Gray3, + contentDescription = "Navigate to Search" + ) + Spacer(modifier = Modifier.width(5.dp)) + Text( + modifier = Modifier.padding(vertical = 10.dp), + text = buildAnnotatedString { + withStyle( + SpanStyle( + color = Gray1, + fontSize = 12.sp, + fontWeight = FontWeight.Medium + ) + ) { + append(stringResource(id = R.string.search_bar_title)) + } + withStyle( + SpanStyle( + color = Gray3, + fontSize = 10.sp, + fontWeight = FontWeight.Medium + ) + ) { + append(stringResource(id = R.string.search_bar_subtitle)) + } + }, + lineHeight = 15.sp + ) + } +} \ No newline at end of file diff --git a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/TopAppBar.kt b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/TopAppBar.kt index 02a86c0e2..1f39a61cd 100644 --- a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/TopAppBar.kt +++ b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/component/TopAppBar.kt @@ -100,9 +100,11 @@ fun ConnectDogTopAppBar( } } - Row(modifier = Modifier.align(Alignment.CenterEnd)) { - actionButtons() - } + Row( + modifier = Modifier.align(Alignment.CenterEnd), + content = { actionButtons() } + ) + if (titleRes != null) { Text( text = stringResource(id = titleRes), diff --git a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/theme/Color.kt b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/theme/Color.kt index 4898a1844..8e3ef6fc8 100644 --- a/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/theme/Color.kt +++ b/core/designsystem/src/main/java/com/kusitms/connectdog/core/designsystem/theme/Color.kt @@ -23,6 +23,9 @@ val Gray7 = Color(0xFFF5F5F5) val Gray8 = Color(0xFFFAFAFA) val Gray9 = Color(0xFFAEAEAE) val Gray10 = Color(0xFF969696) +val Gray60 = Color(0XFF878787) +val Gray80 = Color(0XFF5F5F5F) +val Gray100 = Color(0XFF242424) val Brown1 = Color(0xFF5B3816) val Brown1_5 = Color(0xFFDDD7D1) diff --git a/core/designsystem/src/main/res/values/strings.xml b/core/designsystem/src/main/res/values/strings.xml index f7c58638a..b81cdcf97 100644 --- a/core/designsystem/src/main/res/values/strings.xml +++ b/core/designsystem/src/main/res/values/strings.xml @@ -1,7 +1,5 @@ - 227799f94d3661c7d84b79daba3b0eaa - 일정 모집자명 @@ -55,4 +53,8 @@ 봉사 건을 완료 처리 하시겠습니까? 봉사가 모두 종료되었나요?\n완료 처리 시 봉사자에게도\n완료 푸시 알림이 전송됩니다. 완료 + + + 딱 맞는 이동봉사를 찾아보세요!\n + 출발지·도착지·일정 \ No newline at end of file diff --git a/core/model/build.gradle.kts b/core/model/build.gradle.kts index 35f9740d4..1d739c52b 100644 --- a/core/model/build.gradle.kts +++ b/core/model/build.gradle.kts @@ -1,24 +1,10 @@ -import com.kusitms.connectdog.Configuration - @Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed plugins { - alias(libs.plugins.com.android.library) - alias(libs.plugins.org.jetbrains.kotlin.android) - alias(libs.plugins.ktlint) + id("java-library") + alias(libs.plugins.org.jetbrains.kotlin.jvm) } -android { - namespace = "com.kusitms.connectdog.core.model" - compileSdk = Configuration.compileSdk - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - kotlinOptions { - jvmTarget = "1.8" - } -} - -dependencies { -} +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} \ No newline at end of file diff --git a/core/model/build/classes/kotlin/main/META-INF/model.kotlin_module b/core/model/build/classes/kotlin/main/META-INF/model.kotlin_module new file mode 100644 index 000000000..3aa63618c Binary files /dev/null and b/core/model/build/classes/kotlin/main/META-INF/model.kotlin_module differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Announcement.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Announcement.class new file mode 100644 index 000000000..1e35850eb Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Announcement.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/AnnouncementHome$Companion.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/AnnouncementHome$Companion.class new file mode 100644 index 000000000..c8faa7226 Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/AnnouncementHome$Companion.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/AnnouncementHome.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/AnnouncementHome.class new file mode 100644 index 000000000..41a874269 Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/AnnouncementHome.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Application.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Application.class new file mode 100644 index 000000000..a5e7b3fb5 Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Application.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/ConnectDogResult.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/ConnectDogResult.class new file mode 100644 index 000000000..ac0caf2af Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/ConnectDogResult.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Loading.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Loading.class new file mode 100644 index 000000000..d5e24a1c7 Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Loading.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Success.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Success.class new file mode 100644 index 000000000..168eadde5 Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Success.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Yet.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Yet.class new file mode 100644 index 000000000..9f49c8bfb Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Yet.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState.class new file mode 100644 index 000000000..72eeb88ac Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Example$Grade.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Example$Grade.class new file mode 100644 index 000000000..04a599912 Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Example$Grade.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Example.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Example.class new file mode 100644 index 000000000..19ad1b7df Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Example.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/InterApplication.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/InterApplication.class new file mode 100644 index 000000000..e902aa861 Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/InterApplication.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/IntermediatorManage.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/IntermediatorManage.class new file mode 100644 index 000000000..3db929422 Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/IntermediatorManage.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Recent.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Recent.class new file mode 100644 index 000000000..091fbdfce Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Recent.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Review.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Review.class new file mode 100644 index 000000000..fa56387a0 Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Review.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Volunteer.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Volunteer.class new file mode 100644 index 000000000..11135f888 Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Volunteer.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/AuthCodeWithAccessToken.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/AuthCodeWithAccessToken.class new file mode 100644 index 000000000..426b4ae61 Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/AuthCodeWithAccessToken.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/Email.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/Email.class new file mode 100644 index 000000000..ede7fbecd Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/Email.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/EmailAuthCode.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/EmailAuthCode.class new file mode 100644 index 000000000..83d28a418 Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/EmailAuthCode.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/Phone.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/Phone.class new file mode 100644 index 000000000..6e7d6ee1f Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/Phone.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/PhoneNumberDuplication.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/PhoneNumberDuplication.class new file mode 100644 index 000000000..e4c752ab4 Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/PhoneNumberDuplication.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/LoginResult.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/LoginResult.class new file mode 100644 index 000000000..292f57aad Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/LoginResult.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/NormalLogin.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/NormalLogin.class new file mode 100644 index 000000000..8129b374e Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/NormalLogin.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/SocialLogin.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/SocialLogin.class new file mode 100644 index 000000000..7c1696357 Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/SocialLogin.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/IsDuplicated.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/IsDuplicated.class new file mode 100644 index 000000000..b2547f04b Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/IsDuplicated.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/Name.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/Name.class new file mode 100644 index 000000000..31625ffe4 Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/Name.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/Nickname.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/Nickname.class new file mode 100644 index 000000000..87e38acf3 Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/Nickname.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/NormalVolunteerDetail.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/NormalVolunteerDetail.class new file mode 100644 index 000000000..6bb57833e Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/NormalVolunteerDetail.class differ diff --git a/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/SocialVolunteerDetail.class b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/SocialVolunteerDetail.class new file mode 100644 index 000000000..e75db1acd Binary files /dev/null and b/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/SocialVolunteerDetail.class differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab similarity index 91% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab index 2b9d16218..af59e3f83 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream new file mode 100644 index 000000000..f81060006 Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len new file mode 100644 index 000000000..8effc88fc Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len new file mode 100644 index 000000000..6a294aa5b Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at new file mode 100644 index 000000000..76e776467 Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i similarity index 95% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i index cbc49165b..57ca44890 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab similarity index 90% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab index c3ca54408..b982fe693 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream similarity index 79% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream index ffd66dee1..34a22a011 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len new file mode 100644 index 000000000..ed0c78127 Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len new file mode 100644 index 000000000..fa4322445 Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at new file mode 100644 index 000000000..9f08f43af Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i similarity index 97% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i index 7838bdec6..17b47beb7 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab similarity index 90% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab index d726bf7a8..430bfd301 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream similarity index 79% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream index ffd66dee1..34a22a011 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len new file mode 100644 index 000000000..ed0c78127 Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len new file mode 100644 index 000000000..fa4322445 Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at new file mode 100644 index 000000000..c9dd2196f Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i similarity index 97% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i index 7838bdec6..17b47beb7 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab similarity index 90% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab index d726bf7a8..f49073638 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream similarity index 79% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream index 4192ff2c4..02cd99cb1 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len new file mode 100644 index 000000000..ed0c78127 Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len new file mode 100644 index 000000000..fa4322445 Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at new file mode 100644 index 000000000..c9dd2196f Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i similarity index 97% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i index 4535b7ad5..65f534089 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab similarity index 90% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab index 0ff08ef63..d2a3d164f 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream similarity index 79% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream index 5723d61ce..65c119a2c 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len new file mode 100644 index 000000000..6f9277755 Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len new file mode 100644 index 000000000..575d13208 Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at similarity index 57% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at index a5a4ee1d7..fbac1fb25 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i similarity index 96% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i index b55ca3082..8ec266e88 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab similarity index 92% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab index 4c6ad8378..fae2fbfe1 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream similarity index 68% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream index e3a14c307..729477221 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len new file mode 100644 index 000000000..8effc88fc Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len new file mode 100644 index 000000000..6a294aa5b Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at new file mode 100644 index 000000000..a98c4f7bc Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i similarity index 97% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i index b927fa49f..c2555187b 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab similarity index 98% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab index 808c74939..a55140b89 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/counters.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/counters.tab new file mode 100644 index 000000000..1911a39b6 --- /dev/null +++ b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/counters.tab @@ -0,0 +1,2 @@ +25 +0 \ No newline at end of file diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab similarity index 92% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab index f5ab49026..780441c2e 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream similarity index 68% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream index e3a14c307..729477221 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len new file mode 100644 index 000000000..8effc88fc Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len new file mode 100644 index 000000000..6a294aa5b Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at similarity index 57% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at index afce831e8..ae69ecd25 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i similarity index 97% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i index d18cf546b..eafbf6baf 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab similarity index 91% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab index bfc127c57..248e43db6 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream similarity index 98% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream index b73411eda..9a5059973 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len new file mode 100644 index 000000000..1df5122b7 Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len new file mode 100644 index 000000000..42df8b93f Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at new file mode 100644 index 000000000..d5feb11f6 Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i similarity index 99% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i index fd274018e..ea39692f9 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab similarity index 78% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab index 5d1798fe6..766bd3702 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream similarity index 84% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream index eeb177d51..7cb7ce1cd 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len new file mode 100644 index 000000000..7b4ddda50 Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.len new file mode 100644 index 000000000..4e534439e Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.len differ diff --git a/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at new file mode 100644 index 000000000..cb8b4f3df Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab_i b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab_i similarity index 85% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab_i rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab_i index 42142a0ba..34e4b2131 100644 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab_i and b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab_i differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len b/core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len similarity index 100% rename from core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len rename to core/model/build/kotlin/compileKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len diff --git a/core/model/build/kotlin/compileKotlin/cacheable/last-build.bin b/core/model/build/kotlin/compileKotlin/cacheable/last-build.bin new file mode 100644 index 000000000..94bc580e1 Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/cacheable/last-build.bin differ diff --git a/core/model/build/kotlin/compileKotlin/local-state/build-history.bin b/core/model/build/kotlin/compileKotlin/local-state/build-history.bin new file mode 100644 index 000000000..498de9818 Binary files /dev/null and b/core/model/build/kotlin/compileKotlin/local-state/build-history.bin differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream deleted file mode 100644 index 39a98da47..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len deleted file mode 100644 index d668d29e3..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len deleted file mode 100644 index a54135646..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at deleted file mode 100644 index 8694ee8ce..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len deleted file mode 100644 index 3e5b6a53b..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len deleted file mode 100644 index cf8a30a1c..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at deleted file mode 100644 index ac65f4acd..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len deleted file mode 100644 index 3e5b6a53b..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len deleted file mode 100644 index cf8a30a1c..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at deleted file mode 100644 index 5cf06f957..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len deleted file mode 100644 index 3e5b6a53b..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len deleted file mode 100644 index cf8a30a1c..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at deleted file mode 100644 index 5cf06f957..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len deleted file mode 100644 index c1727f81f..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len deleted file mode 100644 index 9911af505..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len deleted file mode 100644 index d668d29e3..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len deleted file mode 100644 index a54135646..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at deleted file mode 100644 index 25a7dcc9d..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/counters.tab b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/counters.tab deleted file mode 100644 index 920202f82..000000000 --- a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/counters.tab +++ /dev/null @@ -1,2 +0,0 @@ -11 -0 \ No newline at end of file diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len deleted file mode 100644 index d668d29e3..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len deleted file mode 100644 index a54135646..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len deleted file mode 100644 index 296694d3c..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len deleted file mode 100644 index a54135646..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at deleted file mode 100644 index f49494259..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len deleted file mode 100644 index b67c22714..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.len b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.len deleted file mode 100644 index b4da13181..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.len and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at b/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at deleted file mode 100644 index 8bd51fcfa..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/cacheable/last-build.bin b/core/model/build/kotlin/compileReleaseKotlin/cacheable/last-build.bin deleted file mode 100644 index e20e1387b..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/cacheable/last-build.bin and /dev/null differ diff --git a/core/model/build/kotlin/compileReleaseKotlin/local-state/build-history.bin b/core/model/build/kotlin/compileReleaseKotlin/local-state/build-history.bin deleted file mode 100644 index fadb9450b..000000000 Binary files a/core/model/build/kotlin/compileReleaseKotlin/local-state/build-history.bin and /dev/null differ diff --git a/core/model/build/kotlin/modeljar-classes.txt b/core/model/build/kotlin/modeljar-classes.txt new file mode 100644 index 000000000..af6b32e85 --- /dev/null +++ b/core/model/build/kotlin/modeljar-classes.txt @@ -0,0 +1 @@ +/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Announcement.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/AnnouncementHome$Companion.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/AnnouncementHome.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Application.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/ConnectDogResult.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Loading.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Success.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState$Yet.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/DataUiState.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Example$Grade.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Example.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/InterApplication.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/IntermediatorManage.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Recent.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Review.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/Volunteer.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/AuthCodeWithAccessToken.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/Email.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/EmailAuthCode.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/Phone.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/auth/PhoneNumberDuplication.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/LoginResult.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/NormalLogin.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/login/SocialLogin.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/IsDuplicated.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/Name.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/Nickname.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/NormalVolunteerDetail.class:/Users/kangseunggu/Desktop/ConnectDog-AOS/core/model/build/classes/kotlin/main/com/kusitms/connectdog/core/model/signup/SocialVolunteerDetail.class \ No newline at end of file diff --git a/core/model/build/libs/model.jar b/core/model/build/libs/model.jar new file mode 100644 index 000000000..a073bc6a1 Binary files /dev/null and b/core/model/build/libs/model.jar differ diff --git a/core/model/build/reports/ktlint/ktlintKotlinScriptFormat/ktlintKotlinScriptFormat.txt b/core/model/build/reports/ktlint/ktlintKotlinScriptFormat/ktlintKotlinScriptFormat.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/core/model/build/reports/ktlint/ktlintMainSourceSetFormat/ktlintMainSourceSetFormat.txt b/core/model/build/reports/ktlint/ktlintMainSourceSetFormat/ktlintMainSourceSetFormat.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/AnnouncementHome.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/AnnouncementHome.kt index 832df94df..2cf4fe7ea 100644 --- a/core/model/src/main/java/com/kusitms/connectdog/core/model/AnnouncementHome.kt +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/AnnouncementHome.kt @@ -7,4 +7,15 @@ data class AnnouncementHome( val postId: Int, val dogName: String, val pickUpTime: String -) +) { + companion object { + fun loading() = AnnouncementHome( + imageUrl = "", + location = "이동봉사 위치", + date = "YY.mm.dd(요일)", + postId = -1, + dogName = "", + pickUpTime = "" + ) + } +} diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/AuthCodeWithAccessToken.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/AuthCodeWithAccessToken.kt new file mode 100644 index 000000000..31dc7af29 --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/AuthCodeWithAccessToken.kt @@ -0,0 +1,6 @@ +package com.kusitms.connectdog.core.model.auth + +data class AuthCodeWithAccessToken( + val authCode: String, + val accessToken: String +) diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/Email.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/Email.kt new file mode 100644 index 000000000..064699b06 --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/Email.kt @@ -0,0 +1,5 @@ +package com.kusitms.connectdog.core.model.auth + +data class Email( + val email: String +) diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/EmailAuthCode.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/EmailAuthCode.kt new file mode 100644 index 000000000..04d98c3e8 --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/EmailAuthCode.kt @@ -0,0 +1,5 @@ +package com.kusitms.connectdog.core.model.auth + +data class EmailAuthCode( + val authCode: String +) diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/Phone.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/Phone.kt new file mode 100644 index 000000000..64223e00e --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/Phone.kt @@ -0,0 +1,5 @@ +package com.kusitms.connectdog.core.model.auth + +data class Phone( + val phone: String +) diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/PhoneNumberDuplication.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/PhoneNumberDuplication.kt new file mode 100644 index 000000000..62d544830 --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/auth/PhoneNumberDuplication.kt @@ -0,0 +1,7 @@ +package com.kusitms.connectdog.core.model.auth + +data class PhoneNumberDuplication( + val isDuplicated: Boolean, + val socialType: String?, + val email: String? +) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/LoginResponseItem.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/login/LoginResult.kt similarity index 51% rename from core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/LoginResponseItem.kt rename to core/model/src/main/java/com/kusitms/connectdog/core/model/login/LoginResult.kt index 81e0364c3..500b1798c 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/LoginResponseItem.kt +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/login/LoginResult.kt @@ -1,6 +1,6 @@ -package com.kusitms.connectdog.core.data.api.model +package com.kusitms.connectdog.core.model.login -data class LoginResponseItem( +data class LoginResult( val accessToken: String, val refreshToken: String, val roleName: String diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/login/NormalLogin.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/login/NormalLogin.kt new file mode 100644 index 000000000..69b0c2a9d --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/login/NormalLogin.kt @@ -0,0 +1,6 @@ +package com.kusitms.connectdog.core.model.login + +data class NormalLogin( + val email: String, + val password: String +) diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/login/SocialLogin.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/login/SocialLogin.kt new file mode 100644 index 000000000..459c63dd7 --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/login/SocialLogin.kt @@ -0,0 +1,6 @@ +package com.kusitms.connectdog.core.model.login + +data class SocialLogin( + val accessToken: String, + val provider: String +) diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/IsDuplicated.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/IsDuplicated.kt new file mode 100644 index 000000000..b58fad5a6 --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/IsDuplicated.kt @@ -0,0 +1,5 @@ +package com.kusitms.connectdog.core.model.signup + +data class IsDuplicated( + val isDuplicated: Boolean +) diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/Name.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/Name.kt new file mode 100644 index 000000000..62b06c51a --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/Name.kt @@ -0,0 +1,5 @@ +package com.kusitms.connectdog.core.model.signup + +data class Name( + val name: String +) \ No newline at end of file diff --git a/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/Nickname.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/Nickname.kt new file mode 100644 index 000000000..e67ebdb44 --- /dev/null +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/Nickname.kt @@ -0,0 +1,5 @@ +package com.kusitms.connectdog.core.model.signup + +data class Nickname( + val nickname: String +) diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/NormalVolunteerSignUpBody.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/NormalVolunteerDetail.kt similarity index 65% rename from core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/NormalVolunteerSignUpBody.kt rename to core/model/src/main/java/com/kusitms/connectdog/core/model/signup/NormalVolunteerDetail.kt index 9911b7c0e..878e24e48 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/NormalVolunteerSignUpBody.kt +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/NormalVolunteerDetail.kt @@ -1,6 +1,6 @@ -package com.kusitms.connectdog.core.data.api.model.volunteer +package com.kusitms.connectdog.core.model.signup -data class NormalVolunteerSignUpBody( +data class NormalVolunteerDetail( val email: String, val password: String, val nickname: String, diff --git a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/SocialVolunteerSignUpBody.kt b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/SocialVolunteerDetail.kt similarity index 58% rename from core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/SocialVolunteerSignUpBody.kt rename to core/model/src/main/java/com/kusitms/connectdog/core/model/signup/SocialVolunteerDetail.kt index 47a6d5a10..a8ad32489 100644 --- a/core/data/src/main/java/com/kusitms/connectdog/core/data/api/model/volunteer/SocialVolunteerSignUpBody.kt +++ b/core/model/src/main/java/com/kusitms/connectdog/core/model/signup/SocialVolunteerDetail.kt @@ -1,6 +1,6 @@ -package com.kusitms.connectdog.core.data.api.model.volunteer +package com.kusitms.connectdog.core.model.signup -data class SocialVolunteerSignUpBody( +data class SocialVolunteerDetail( val nickname: String, val profileImageNum: Int, val isOptionAgr: Boolean = true, diff --git a/core/util/src/main/java/com/kusitms/connectdog/core/util/Constants.kt b/core/util/src/main/java/com/kusitms/connectdog/core/util/Constants.kt index 8835173b3..f44f19fb4 100644 --- a/core/util/src/main/java/com/kusitms/connectdog/core/util/Constants.kt +++ b/core/util/src/main/java/com/kusitms/connectdog/core/util/Constants.kt @@ -1,18 +1,20 @@ package com.kusitms.connectdog.core.util -enum class AppMode { - LOGIN, - VOLUNTEER, - INTERMEDIATOR -} +import androidx.annotation.DrawableRes -enum class UserType { - SOCIAL_VOLUNTEER, - NORMAL_VOLUNTEER, - INTERMEDIATOR +enum class UserType( + @DrawableRes val topBarTitleRes: Int, +) { + SOCIAL_VOLUNTEER(R.string.volunteer_signup), + NORMAL_VOLUNTEER(R.string.volunteer_signup), + INTERMEDIATOR(R.string.intermediator_signup) } enum class SocialType { GUEST, VOLUNTEER +} + +enum class AccountType { + EMAIL, PASSWORD } \ No newline at end of file diff --git a/core/util/src/main/res/values/string.xml b/core/util/src/main/res/values/string.xml new file mode 100644 index 000000000..e03158634 --- /dev/null +++ b/core/util/src/main/res/values/string.xml @@ -0,0 +1,5 @@ + + + 이동봉사자 회원가입 + 이동봉사 모집자 회원가입 + \ No newline at end of file diff --git a/data/src/main/java/com/kusitms/connectdog/data/model/remote/request/NormalLoginDto.kt b/data/src/main/java/com/kusitms/connectdog/data/model/remote/request/NormalLoginDto.kt deleted file mode 100644 index ce8dc8496..000000000 --- a/data/src/main/java/com/kusitms/connectdog/data/model/remote/request/NormalLoginDto.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.kusitms.connectdog.data.model.remote.request - -data class NormalLoginDto( - val email: String, - val password: String -) diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts index 7afdbc404..61b8c213b 100644 --- a/domain/build.gradle.kts +++ b/domain/build.gradle.kts @@ -5,6 +5,13 @@ plugins { } java { - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +dependencies { + implementation(projects.core.model) + + implementation(libs.kotlinx.coroutines.core) + implementation(libs.javax.inject) } \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/repository/AuthRepository.kt b/domain/src/main/java/com/kusitms/connectdog/domain/repository/AuthRepository.kt new file mode 100644 index 000000000..c9e7edbbe --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/repository/AuthRepository.kt @@ -0,0 +1,19 @@ +package com.kusitms.connectdog.domain.repository + +import com.kusitms.connectdog.core.model.auth.AuthCodeWithAccessToken +import com.kusitms.connectdog.core.model.auth.Email +import com.kusitms.connectdog.core.model.auth.EmailAuthCode +import com.kusitms.connectdog.core.model.auth.PhoneNumberDuplication + + +interface AuthRepository { + suspend fun getEmailAuthCode(email: String): Result + suspend fun searchVolunteerEmail(phone: String): Result + suspend fun searchIntermediatorEmail(phone: String): Result + + suspend fun emailAuthForVolunteerPasswordReset(email: String): Result + suspend fun emailAuthForIntermediatorPasswordReset(email: String): Result + + suspend fun getVolunteerPhoneNumberDuplication(phone: String): Result + suspend fun getIntermediatorPhoneNumberDuplication(phone: String): Result +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/repository/DataStoreRepository.kt b/domain/src/main/java/com/kusitms/connectdog/domain/repository/DataStoreRepository.kt new file mode 100644 index 000000000..556836fc4 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/repository/DataStoreRepository.kt @@ -0,0 +1,23 @@ +package com.kusitms.connectdog.domain.repository + +import com.kusitms.connectdog.domain.usecase.login.AppMode +import com.kusitms.connectdog.domain.usecase.login.SocialLoginProvider +import kotlinx.coroutines.flow.Flow + +interface DataStoreRepository { + suspend fun updateAccessToken(accessToken: String) + suspend fun updateRefreshToken(refreshToken: String) + suspend fun updateAppMode(appMode: AppMode) + suspend fun updateFcmToken(fcmToken: String) + suspend fun updateSocialToken(token: String) + suspend fun updateSocialLoginProvider(provider: SocialLoginProvider) + + suspend fun getAccessToken(): Flow + suspend fun getRefreshToken(): Flow + suspend fun getFcmToken(): Flow + suspend fun getAppMode(): Flow + suspend fun getSocialToken(): Flow + suspend fun getSocialLoginProvider(): Flow + + suspend fun deleteAccessToken() +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/repository/LoginRepository.kt b/domain/src/main/java/com/kusitms/connectdog/domain/repository/LoginRepository.kt new file mode 100644 index 000000000..a12904072 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/repository/LoginRepository.kt @@ -0,0 +1,22 @@ +package com.kusitms.connectdog.domain.repository + +import com.kusitms.connectdog.core.model.login.LoginResult + +interface LoginRepository { + suspend fun volunteerNormalLogin( + email: String, + password: String + ): Result + + suspend fun socialLogin( + accessToken: String, + provider: String + ): Result + + suspend fun intermediatorNormalLogin( + email: String, + password: String + ): Result + + suspend fun logout(): Result +} diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/repository/SignUpRepository.kt b/domain/src/main/java/com/kusitms/connectdog/domain/repository/SignUpRepository.kt new file mode 100644 index 000000000..bba542245 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/repository/SignUpRepository.kt @@ -0,0 +1,26 @@ +package com.kusitms.connectdog.domain.repository + +import com.kusitms.connectdog.core.model.signup.IsDuplicated + +interface SignUpRepository { + suspend fun getVolunteerNicknameDuplication(nickname: String): Result + suspend fun getIntermediatorNicknameDuplication(nickname: String): Result + + suspend fun initNormalVolunteerSignUp( + email: String, + password: String, + nickname: String, + profileImageNum: Int, + isOptionAgr: Boolean = true, + phone: String, + name: String + ): Result + + suspend fun initSocialVolunteerSignUp( + nickname: String, + profileImageNum: Int, + isOptionAgr: Boolean = true, + phone: String, + name: String + ): Result +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/GetAppModeUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/GetAppModeUseCase.kt new file mode 100644 index 000000000..2d00c8dc2 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/GetAppModeUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetAppModeUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke() = repository.getAppMode() +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/GetFcmTokenUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/GetFcmTokenUseCase.kt new file mode 100644 index 000000000..b3dc3d2af --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/GetFcmTokenUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetFcmTokenUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke() = repository.getFcmToken() +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/UpdateFcmTokenUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/UpdateFcmTokenUseCase.kt new file mode 100644 index 000000000..325ec5cd9 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/UpdateFcmTokenUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class UpdateFcmTokenUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke(fcmToken: String) = repository.updateFcmToken(fcmToken) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/EmailAuthForIntermediatorPasswordResetUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/EmailAuthForIntermediatorPasswordResetUseCase.kt new file mode 100644 index 000000000..b08536f73 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/EmailAuthForIntermediatorPasswordResetUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.auth + +import com.kusitms.connectdog.domain.repository.AuthRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class EmailAuthForIntermediatorPasswordResetUseCase @Inject constructor( + val repository: AuthRepository +) { + suspend operator fun invoke(email: String) = repository.emailAuthForIntermediatorPasswordReset(email) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/EmailAuthForVolunteerPassowordResetUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/EmailAuthForVolunteerPassowordResetUseCase.kt new file mode 100644 index 000000000..0e1d039b3 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/EmailAuthForVolunteerPassowordResetUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.auth + +import com.kusitms.connectdog.domain.repository.AuthRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class EmailAuthForVolunteerPasswordResetUseCase @Inject constructor( + val repository: AuthRepository +) { + suspend operator fun invoke(email: String) = repository.emailAuthForVolunteerPasswordReset(email) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetEmailAuthCodeUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetEmailAuthCodeUseCase.kt new file mode 100644 index 000000000..32fdfeb17 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetEmailAuthCodeUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.auth + +import com.kusitms.connectdog.domain.repository.AuthRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetEmailAuthCodeUseCase @Inject constructor( + val repository: AuthRepository +) { + suspend operator fun invoke(email: String) = repository.getEmailAuthCode(email) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetIntermediatorPhoneNumberDuplicationUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetIntermediatorPhoneNumberDuplicationUseCase.kt new file mode 100644 index 000000000..3ab598a16 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetIntermediatorPhoneNumberDuplicationUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.auth + +import com.kusitms.connectdog.domain.repository.AuthRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetIntermediatorPhoneNumberDuplicationUseCase @Inject constructor( + val repository: AuthRepository +) { + suspend operator fun invoke(phone: String) = repository.getIntermediatorPhoneNumberDuplication(phone) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetVolunteerPhoneNumberDuplicationUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetVolunteerPhoneNumberDuplicationUseCase.kt new file mode 100644 index 000000000..017a0fe3e --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/GetVolunteerPhoneNumberDuplicationUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.auth + +import com.kusitms.connectdog.domain.repository.AuthRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetVolunteerPhoneNumberDuplicationUseCase @Inject constructor( + val repository: AuthRepository +) { + suspend operator fun invoke(phone: String) = repository.getVolunteerPhoneNumberDuplication(phone) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/SearchIntermediatorEmailUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/SearchIntermediatorEmailUseCase.kt new file mode 100644 index 000000000..235f1f81b --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/SearchIntermediatorEmailUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.auth + +import com.kusitms.connectdog.domain.repository.AuthRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class SearchIntermediatorEmailUseCase @Inject constructor( + val repository: AuthRepository +) { + suspend operator fun invoke(phone: String) = repository.searchIntermediatorEmail(phone) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/SearchVolunteerEmailUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/SearchVolunteerEmailUseCase.kt new file mode 100644 index 000000000..4fbd29486 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/auth/SearchVolunteerEmailUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.auth + +import com.kusitms.connectdog.domain.repository.AuthRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class SearchVolunteerEmailUseCase @Inject constructor( + val repository: AuthRepository +) { + suspend operator fun invoke(phone: String) = repository.searchVolunteerEmail(phone) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/DeleteAccessTokenUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/DeleteAccessTokenUseCase.kt new file mode 100644 index 000000000..47ab7ab99 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/DeleteAccessTokenUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class DeleteAccessTokenUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke() = repository.deleteAccessToken() +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/IntermediatorLoginUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/IntermediatorLoginUseCase.kt new file mode 100644 index 000000000..00bf11ac0 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/IntermediatorLoginUseCase.kt @@ -0,0 +1,15 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.LoginRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class IntermediatorLoginUseCase @Inject constructor( + val repository: LoginRepository +) { + suspend operator fun invoke( + email: String, + password: String + ) = repository.intermediatorNormalLogin(email, password) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/LogoutUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/LogoutUseCase.kt new file mode 100644 index 000000000..1ff46c68f --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/LogoutUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.LoginRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class LogoutUseCase @Inject constructor( + val repository: LoginRepository +) { + suspend operator fun invoke() = repository.logout() +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/SocialLoginUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/SocialLoginUseCase.kt new file mode 100644 index 000000000..56f6a6c9d --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/SocialLoginUseCase.kt @@ -0,0 +1,15 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.LoginRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class SocialLoginUseCase @Inject constructor( + val repository: LoginRepository +) { + suspend operator fun invoke( + accessToken: String, + provider: String + ) = repository.socialLogin(accessToken, provider) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateAccessTokenUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateAccessTokenUseCase.kt new file mode 100644 index 000000000..dee3a01d7 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateAccessTokenUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class UpdateAccessTokenUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke(accessToken: String) = repository.updateAccessToken(accessToken) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateAppModeUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateAppModeUseCase.kt new file mode 100644 index 000000000..9e2235977 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateAppModeUseCase.kt @@ -0,0 +1,18 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +enum class AppMode { + LOGIN, + VOLUNTEER, + INTERMEDIATOR +} + +@Singleton +class UpdateAppModeUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke(appMode: AppMode) = repository.updateAppMode(appMode) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateRefreshTokenUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateRefreshTokenUseCase.kt new file mode 100644 index 000000000..9509c7d9f --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateRefreshTokenUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class UpdateRefreshTokenUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke(refreshToken: String) = repository.updateRefreshToken(refreshToken) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateSocialProviderUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateSocialProviderUseCase.kt new file mode 100644 index 000000000..aa68bb5a8 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateSocialProviderUseCase.kt @@ -0,0 +1,16 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +enum class SocialLoginProvider { + KAKAO, NAVER +} + +@Singleton +class UpdateSocialProviderUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke(provider: SocialLoginProvider) = repository.updateSocialLoginProvider(provider) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateSocialTokenUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateSocialTokenUseCase.kt new file mode 100644 index 000000000..0ef69fd00 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/UpdateSocialTokenUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class UpdateSocialTokenUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke(token: String) = repository.updateSocialToken(token) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/VolunteerLoginUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/VolunteerLoginUseCase.kt new file mode 100644 index 000000000..1d7723c15 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/login/VolunteerLoginUseCase.kt @@ -0,0 +1,15 @@ +package com.kusitms.connectdog.domain.usecase.login + +import com.kusitms.connectdog.domain.repository.LoginRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class VolunteerLoginUseCase @Inject constructor( + val repository: LoginRepository +) { + suspend operator fun invoke( + email: String, + password: String + ) = repository.volunteerNormalLogin(email, password) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetIntermediatorNameDuplication.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetIntermediatorNameDuplication.kt new file mode 100644 index 000000000..5829ea14c --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetIntermediatorNameDuplication.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.signup + +import com.kusitms.connectdog.domain.repository.SignUpRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetIntermediatorNameDuplication @Inject constructor( + val repository: SignUpRepository +) { + suspend operator fun invoke(name: String) = repository.getIntermediatorNicknameDuplication(name) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetSocialProviderUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetSocialProviderUseCase.kt new file mode 100644 index 000000000..05250ee68 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetSocialProviderUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.signup + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetSocialProviderUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke() = repository.getSocialLoginProvider() +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetSocialTokenUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetSocialTokenUseCase.kt new file mode 100644 index 000000000..5810aa490 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetSocialTokenUseCase.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.signup + +import com.kusitms.connectdog.domain.repository.DataStoreRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetSocialTokenUseCase @Inject constructor( + val repository: DataStoreRepository +) { + suspend operator fun invoke() = repository.getSocialToken() +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetVolunteerNicknameDuplication.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetVolunteerNicknameDuplication.kt new file mode 100644 index 000000000..3831db639 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/GetVolunteerNicknameDuplication.kt @@ -0,0 +1,12 @@ +package com.kusitms.connectdog.domain.usecase.signup + +import com.kusitms.connectdog.domain.repository.SignUpRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GetVolunteerNicknameDuplication @Inject constructor( + val repository: SignUpRepository +) { + suspend operator fun invoke(nickname: String) = repository.getVolunteerNicknameDuplication(nickname) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/InitNormalVolunteerSignUpUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/InitNormalVolunteerSignUpUseCase.kt new file mode 100644 index 000000000..bc6a96e50 --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/InitNormalVolunteerSignUpUseCase.kt @@ -0,0 +1,28 @@ +package com.kusitms.connectdog.domain.usecase.signup + +import com.kusitms.connectdog.domain.repository.SignUpRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class InitNormalVolunteerSignUpUseCase @Inject constructor( + val repository: SignUpRepository +) { + suspend operator fun invoke( + email: String, + password: String, + nickname: String, + profileImageNum: Int, + isOptionAgr: Boolean = true, + phone: String, + name: String + ) = repository.initNormalVolunteerSignUp( + email = email, + password = password, + nickname = nickname, + profileImageNum = profileImageNum, + isOptionAgr = isOptionAgr, + phone = phone, + name = name + ) +} \ No newline at end of file diff --git a/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/InitSocialVolunteerSignUpUseCase.kt b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/InitSocialVolunteerSignUpUseCase.kt new file mode 100644 index 000000000..7a6bcc20c --- /dev/null +++ b/domain/src/main/java/com/kusitms/connectdog/domain/usecase/signup/InitSocialVolunteerSignUpUseCase.kt @@ -0,0 +1,28 @@ +package com.kusitms.connectdog.domain.usecase.signup + +import com.kusitms.connectdog.domain.repository.SignUpRepository +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class InitSocialVolunteerSignUpUseCase @Inject constructor( + val repository: SignUpRepository +) { + suspend operator fun invoke( + email: String, + password: String, + nickname: String, + profileImageNum: Int, + isOptionAgr: Boolean = true, + phone: String, + name: String + ) = repository.initNormalVolunteerSignUp( + email = email, + password = password, + nickname = nickname, + profileImageNum = profileImageNum, + isOptionAgr = isOptionAgr, + phone = phone, + name = name + ) +} \ No newline at end of file diff --git a/feature/home/build.gradle.kts b/feature/home/build.gradle.kts index 27f91e5c9..f3436e00e 100644 --- a/feature/home/build.gradle.kts +++ b/feature/home/build.gradle.kts @@ -46,7 +46,7 @@ android { } dependencies { - + implementation(projects.domain) implementation(project(":core:model")) implementation(project(":core:data")) implementation(project(":core:designsystem")) diff --git a/feature/home/src/main/java/com/kusitms/connectdog/feature/home/HomeViewModel.kt b/feature/home/src/main/java/com/kusitms/connectdog/feature/home/HomeViewModel.kt index 0c2a29df0..cac60d7d6 100644 --- a/feature/home/src/main/java/com/kusitms/connectdog/feature/home/HomeViewModel.kt +++ b/feature/home/src/main/java/com/kusitms/connectdog/feature/home/HomeViewModel.kt @@ -4,8 +4,8 @@ import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.kusitms.connectdog.core.data.api.model.FcmTokenRequestBody -import com.kusitms.connectdog.core.data.repository.DataStoreRepository import com.kusitms.connectdog.core.data.repository.HomeRepository +import com.kusitms.connectdog.domain.usecase.GetFcmTokenUseCase import com.kusitms.connectdog.feature.home.state.AnnouncementUiState import com.kusitms.connectdog.feature.home.state.ReviewUiState import dagger.hilt.android.lifecycle.HiltViewModel @@ -14,7 +14,6 @@ import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn @@ -24,14 +23,12 @@ import javax.inject.Inject private val TAG = "HomeViewModel" @HiltViewModel -class HomeViewModel -@Inject -constructor( +class HomeViewModel @Inject constructor( private val homeRepository: HomeRepository, - private val dataStoreRepository: DataStoreRepository + private val getFcmTokenUseCase: GetFcmTokenUseCase, ) : ViewModel() { init { - postFcmToken() +// postFcmToken() } private val _errorFlow = MutableSharedFlow() @@ -94,11 +91,8 @@ constructor( ) private fun postFcmToken() = viewModelScope.launch { - val token = dataStoreRepository.fcmTokenFlow.first() - try { - token?.let { homeRepository.postFcmToken(FcmTokenRequestBody(it)) } - } catch (e: Exception) { - Log.d("fcm post", e.message.toString()) + getFcmTokenUseCase().collect { + it?.let { homeRepository.postFcmToken(FcmTokenRequestBody(it)) } } } } diff --git a/feature/home/src/main/java/com/kusitms/connectdog/feature/home/screen/HomeScreen.kt b/feature/home/src/main/java/com/kusitms/connectdog/feature/home/screen/HomeScreen.kt index 875cad7db..848dcf6c4 100644 --- a/feature/home/src/main/java/com/kusitms/connectdog/feature/home/screen/HomeScreen.kt +++ b/feature/home/src/main/java/com/kusitms/connectdog/feature/home/screen/HomeScreen.kt @@ -1,13 +1,10 @@ package com.kusitms.connectdog.feature.home.screen +import android.annotation.SuppressLint import androidx.activity.compose.BackHandler import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -23,47 +20,37 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.outlined.Notifications -import androidx.compose.material3.Divider -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton -import androidx.compose.material3.LocalMinimumInteractiveComponentEnforcement import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.ColorPainter -import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.SpanStyle -import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.withStyle -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 androidx.lifecycle.compose.collectAsStateWithLifecycle import com.kusitms.connectdog.core.designsystem.component.BannerGuideline import com.kusitms.connectdog.core.designsystem.component.ConnectDogReview +import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar import com.kusitms.connectdog.core.designsystem.component.NetworkImage import com.kusitms.connectdog.core.designsystem.component.ReviewType +import com.kusitms.connectdog.core.designsystem.component.SearchBar +import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType import com.kusitms.connectdog.core.designsystem.component.text.TextWithIcon -import com.kusitms.connectdog.core.designsystem.theme.ConnectDogTheme -import com.kusitms.connectdog.core.designsystem.theme.Gray1 import com.kusitms.connectdog.core.designsystem.theme.Gray2 import com.kusitms.connectdog.core.designsystem.theme.Gray3 -import com.kusitms.connectdog.core.designsystem.theme.Gray5 import com.kusitms.connectdog.core.model.AnnouncementHome import com.kusitms.connectdog.core.model.Review import com.kusitms.connectdog.feature.home.HomeViewModel @@ -95,29 +82,24 @@ internal fun HomeRoute( viewModel.errorFlow.collectLatest { throwable -> onShowErrorSnackBar(throwable) } } - Column( - modifier = Modifier.fillMaxSize() - ) { - TopAppBar( - onClickSearch = onNavigateToFilterSearch, - onNotificationClick = onNavigateToNotification - ) - HomeScreen( - announcementUiState = announcementUiState, - reviewUiState = reviewUiState, - onNavigateToSearch = onNavigateToSearch, - onNavigateToReview = onNavigateToReview, - onNavigateToDetail = onNavigateToDetail, - onNavigateToGuide = onNavigateToGuide, - onNavigateToReviewDetail = onNavigateToReviewDetail - ) - } + HomeScreen( + announcementUiState = announcementUiState, + reviewUiState = reviewUiState, + onNavigateToFilterSearch = onNavigateToFilterSearch, + onNavigateToSearch = onNavigateToSearch, + onNavigateToReview = onNavigateToReview, + onNavigateToDetail = onNavigateToDetail, + onNavigateToGuide = onNavigateToGuide, + onNavigateToReviewDetail = onNavigateToReviewDetail + ) } +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable private fun HomeScreen( announcementUiState: AnnouncementUiState, reviewUiState: ReviewUiState, + onNavigateToFilterSearch: () -> Unit, onNavigateToSearch: () -> Unit, onNavigateToReview: () -> Unit, onNavigateToDetail: (Long) -> Unit, @@ -125,195 +107,40 @@ private fun HomeScreen( onNavigateToReviewDetail: (Long) -> Unit ) { val scrollState = rememberScrollState() - Column( - modifier = Modifier - .verticalScroll(scrollState) - .fillMaxSize() - ) { - BannerGuideline(onNavigateToGuide) - MoveContent(onClick = { onNavigateToSearch() }, titleRes = R.string.home_navigate_search) - AnnouncementContent(announcementUiState, onClick = onNavigateToDetail) - MoveContent(onClick = { onNavigateToReview() }, titleRes = R.string.home_navigate_review) - ReviewContent(uiState = reviewUiState, onClick = onNavigateToReviewDetail) - Spacer(modifier = Modifier.height(90.dp)) - } -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun TopAppBar( - onClickSearch: () -> Unit, - onNotificationClick: () -> Unit -) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(start = 20.dp, end = 20.dp, top = 16.dp, bottom = 16.dp), - verticalAlignment = Alignment.CenterVertically - ) { - SearchBar( - onClick = onClickSearch, - modifier = Modifier.weight(1f) - ) - Spacer(modifier = Modifier.width(20.dp)) - CompositionLocalProvider(LocalMinimumInteractiveComponentEnforcement provides false) { - IconButton( - onClick = onNotificationClick, - modifier = Modifier.size(24.dp) - ) { - Icon( - imageVector = Icons.Outlined.Notifications, - contentDescription = "Navigate to Search" - ) - } - } - } -} -@Composable -private fun SearchBar( - onClick: () -> Unit, - modifier: Modifier -) { - Box( - modifier = modifier - .height(50.dp) - .border( - width = 1.dp, - color = Gray5, - shape = RoundedCornerShape(90.dp) - ) - .clickable { onClick() }, - contentAlignment = Alignment.CenterStart - ) { - Icon( - modifier = Modifier - .padding(start = 20.dp) - .size(24.dp), - imageVector = Icons.Filled.Search, - tint = Gray3, - contentDescription = "Navigate to Search" - ) - Text( - modifier = Modifier.padding(start = 52.dp), - text = buildAnnotatedString { - withStyle( - SpanStyle( - color = Gray1, - fontSize = 12.sp, - fontWeight = FontWeight.Medium - ) - ) { - append(stringResource(id = R.string.search_bar_title_1)) + Scaffold( + topBar = { + ConnectDogTopAppBar( + titleRes = null, + navigationType = TopAppBarNavigationType.HOME, + actionButtons = { + IconButton(onClick = {}) { + Icon( + imageVector = Icons.Outlined.Notifications, + contentDescription = "Navigate to Search", + modifier = Modifier.clickable { } + ) + } } - withStyle( - SpanStyle( - color = Gray3, - fontSize = 10.sp, - fontWeight = FontWeight.Medium - ) - ) { - append(stringResource(id = R.string.search_bar_title_2)) - } - }, - lineHeight = 15.sp - ) - } -} - -@Composable -private fun StatisticBanner(modifier: Modifier) { - Column(horizontalAlignment = Alignment.End, modifier = modifier) { - Row( - modifier = Modifier.padding(end = 10.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - painter = painterResource(id = R.drawable.ic_info), - contentDescription = "info icon", - modifier = Modifier.padding(2.dp), - tint = Gray3 - ) - Text( - text = stringResource(id = R.string.home_counting_guide), - style = MaterialTheme.typography.labelMedium, - color = Gray3 ) } - Spacer(modifier = Modifier.size(6.dp)) - Box( + ) { + Column( modifier = Modifier - .fillMaxWidth() - .background( - color = MaterialTheme.colorScheme.primaryContainer, - shape = RoundedCornerShape(12.dp) - ) + .verticalScroll(scrollState) + .fillMaxSize() + .padding(top = 48.dp, bottom = 90.dp) ) { - Divider( - color = MaterialTheme.colorScheme.onPrimary, - modifier = Modifier - .height(80.dp) - .width(1.dp) - .align(Alignment.Center) - ) - Row( - horizontalArrangement = Arrangement.SpaceEvenly, - verticalAlignment = Alignment.Bottom, - modifier = Modifier - .height(80.dp) - .fillMaxWidth() - ) { - StatisticInfoItem( - modifier = Modifier.weight(1f), - number = "105", - descriptionRes = R.string.home_need_move_description, - painter = painterResource(id = R.drawable.img_man_dog) - ) - StatisticInfoItem( - modifier = Modifier.weight(1f), - number = "22", - descriptionRes = R.string.home_moved_description, - painter = painterResource(id = R.drawable.img_woman) - ) - } + SearchBar(onClick = onNavigateToFilterSearch) + BannerGuideline(onNavigateToGuide) + MoveContent(onClick = { onNavigateToSearch() }, titleRes = R.string.home_navigate_search) + AnnouncementContent(announcementUiState, onClick = onNavigateToDetail) + MoveContent(onClick = { onNavigateToReview() }, titleRes = R.string.home_navigate_review) + ReviewContent(uiState = reviewUiState, onClick = onNavigateToReviewDetail) } } } -@Composable -private fun StatisticInfoItem( - modifier: Modifier = Modifier, - number: String = "0", - descriptionRes: Int, - painter: Painter -) { - Row { - Column(horizontalAlignment = Alignment.Start) { - Row(verticalAlignment = Alignment.CenterVertically) { - Text( - text = number, - style = MaterialTheme.typography.titleSmall, - fontSize = 20.sp, - color = MaterialTheme.colorScheme.onSurface - ) - Text( - text = stringResource(id = R.string.home_dog_unit), - style = MaterialTheme.typography.labelMedium, - fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.onSurface, - modifier = Modifier.padding(start = 2.dp) - ) - } - Text( - text = stringResource(id = descriptionRes), - style = MaterialTheme.typography.labelMedium, - fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.onSurface - ) - } - Image(painter = painter, contentDescription = "mandog") - } -} @Composable fun MoveContent( @@ -334,7 +161,7 @@ fun MoveContent( ) IconButton(onClick = { onClick() }) { Icon( - painter = painterResource(id = com.kusitms.connectdog.core.designsystem.R.drawable.ic_right_arrow), + painter = painterResource(id = R.drawable.ic_right_arrow), contentDescription = "move to another screen", modifier = Modifier.size(24.dp), tint = Gray2 @@ -405,9 +232,7 @@ fun AnnouncementLoading( modifier: Modifier, arrangement: Arrangement.Horizontal ) { - val list = List(4) { - AnnouncementHome("", "이동봉사 위치", "YY.mm.dd(요일)", -1, "", "") - } + val list = List(4) { AnnouncementHome.loading() } LazyRow(horizontalArrangement = arrangement, modifier = modifier) { items(list) { AnnouncementCardContent(announcementHome = it, onClick = {}) @@ -509,22 +334,3 @@ private fun ReviewCardContent( ConnectDogReview(review = review, modifier = Modifier.width(272.dp), type = ReviewType.HOME) } } - -@Preview -@Composable -private fun HomeScreenPreview() { - ConnectDogTheme { - Column(modifier = Modifier.background(Color.White)) { - TopAppBar(onClickSearch = {}, onNotificationClick = {}) - HomeScreen( - announcementUiState = AnnouncementUiState.Empty, - reviewUiState = ReviewUiState.Empty, - {}, - {}, - {}, - {}, - {} - ) - } - } -} diff --git a/feature/home/src/main/res/values/string.xml b/feature/home/src/main/res/values/string.xml index 4f9e04082..2773f2773 100644 --- a/feature/home/src/main/res/values/string.xml +++ b/feature/home/src/main/res/values/string.xml @@ -43,8 +43,6 @@ 이동했어요! 지금 필요한 이동봉사 공고 생생한 이동봉사 후기 - 딱 맞는 이동봉사를 찾아보세요!\n - 출발지·도착지·일정 이동봉사 후기 diff --git a/feature/intermediator/build.gradle.kts b/feature/intermediator/build.gradle.kts index 19f2de1f9..569104159 100644 --- a/feature/intermediator/build.gradle.kts +++ b/feature/intermediator/build.gradle.kts @@ -46,7 +46,7 @@ android { } dependencies { - + implementation(projects.domain) implementation(project(":core:model")) implementation(project(":core:data")) implementation(project(":core:designsystem")) diff --git a/feature/intermediator/src/main/java/com/kusitms/connectdog/feature/intermediator/viewmodel/InterHomeViewModel.kt b/feature/intermediator/src/main/java/com/kusitms/connectdog/feature/intermediator/viewmodel/InterHomeViewModel.kt index 9e9dba5d2..7cc10eadb 100644 --- a/feature/intermediator/src/main/java/com/kusitms/connectdog/feature/intermediator/viewmodel/InterHomeViewModel.kt +++ b/feature/intermediator/src/main/java/com/kusitms/connectdog/feature/intermediator/viewmodel/InterHomeViewModel.kt @@ -4,7 +4,6 @@ import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.kusitms.connectdog.core.data.api.model.FcmTokenRequestBody -import com.kusitms.connectdog.core.data.repository.DataStoreRepository import com.kusitms.connectdog.core.data.repository.InterManagementRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow @@ -15,12 +14,12 @@ import javax.inject.Inject @HiltViewModel class InterHomeViewModel @Inject constructor( - private val dataStoreRepository: DataStoreRepository, +// private val dataStoreRepository: DataStoreRepository, private val repository: InterManagementRepository ) : ViewModel() { - init { - postFcmToken() - } +// init { +// postFcmToken() +// } private val _profileImage = MutableStateFlow("") val profileImage: StateFlow get() = _profileImage @@ -67,11 +66,11 @@ class InterHomeViewModel @Inject constructor( } private fun postFcmToken() = viewModelScope.launch { - val token = dataStoreRepository.fcmTokenFlow.first() - try { - token?.let { repository.postFcmToken(FcmTokenRequestBody(it)) } - } catch (e: Exception) { - Log.d("fcm post", e.message.toString()) - } +// val token = dataStoreRepository.fcmTokenFlow.first() +// try { +// token?.let { repository.postFcmToken(FcmTokenRequestBody(it)) } +// } catch (e: Exception) { +// Log.d("fcm post", e.message.toString()) +// } } } diff --git a/feature/login/build.gradle.kts b/feature/login/build.gradle.kts index 945feb1e5..e1f0491ef 100644 --- a/feature/login/build.gradle.kts +++ b/feature/login/build.gradle.kts @@ -1,3 +1,6 @@ +import org.jetbrains.kotlin.konan.properties.Properties +import com.kusitms.connectdog.Configuration + @Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed plugins { alias(libs.plugins.com.android.library) @@ -9,10 +12,20 @@ plugins { android { namespace = "com.kusitms.connectdog.feature.login" - compileSdk = 33 + compileSdk = Configuration.minSdk defaultConfig { - minSdk = 30 + minSdk = Configuration.minSdk + + val localProperties = Properties() + val localPropertiesFile = rootProject.file("local.properties") + if (localPropertiesFile.exists()) { localPropertiesFile.inputStream().use { localProperties.load(it) } } + + val naverClientId: String = localProperties.getProperty("NAVER_CLIENT_ID") ?: "" + val naverClientSecret: String = localProperties.getProperty("NAVER_CLIENT_SECRET") ?: "" + + buildConfigField("String", "NAVER_CLIENT_ID", "\"$naverClientId\"") + buildConfigField("String", "NAVER_CLIENT_SECRET", "\"$naverClientSecret\"") testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") @@ -37,6 +50,7 @@ android { buildFeatures { compose = true + buildConfig = true } composeOptions { kotlinCompilerExtensionVersion = "1.4.3" @@ -44,13 +58,13 @@ android { } dependencies { - - implementation(project(":core:designsystem")) - implementation(project(":core:util")) + implementation(projects.domain) + implementation(projects.core.model) + implementation(projects.core.designsystem) + implementation(projects.core.util) + implementation(projects.core.data) implementation(libs.androidx.core.splashscreen) - implementation(project(mapOf("path" to ":core:data"))) - kapt(libs.hilt.compiler) implementation(libs.hilt.android) @@ -81,6 +95,4 @@ dependencies { implementation(libs.kakao.oauth) implementation(libs.naver.oauth) - - implementation(libs.androidx.junit.ktx) } diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/LoginNavigation.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/navigation/LoginNavigation.kt similarity index 72% rename from feature/login/src/main/java/com/kusitms/connectdog/feature/login/LoginNavigation.kt rename to feature/login/src/main/java/com/kusitms/connectdog/feature/login/navigation/LoginNavigation.kt index d94e15894..ab068e802 100644 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/LoginNavigation.kt +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/navigation/LoginNavigation.kt @@ -1,20 +1,22 @@ -package com.kusitms.connectdog.feature.login +package com.kusitms.connectdog.feature.login.navigation import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavType import androidx.navigation.compose.composable import androidx.navigation.navArgument +import com.kusitms.connectdog.core.util.AccountType import com.kusitms.connectdog.core.util.UserType import com.kusitms.connectdog.feature.login.screen.EmailSearchResultScreen import com.kusitms.connectdog.feature.login.screen.EmailSearchScreen import com.kusitms.connectdog.feature.login.screen.LoginRoute import com.kusitms.connectdog.feature.login.screen.NormalLoginScreen -import com.kusitms.connectdog.feature.login.screen.PasswordSearchAuthScreen -import com.kusitms.connectdog.feature.login.screen.PasswordSearchScreen +import com.kusitms.connectdog.feature.login.screen.EmailAuthForPasswordResetScreen +import com.kusitms.connectdog.feature.login.screen.NoAccountScreen +import com.kusitms.connectdog.feature.login.screen.PasswordResetScreen fun NavController.navigateToLoginRoute() { - navigate(LoginRoute.route) { + navigate(LoginRoute.ROUTE) { popUpTo(graph.id) { inclusive = true } @@ -22,11 +24,11 @@ fun NavController.navigateToLoginRoute() { } fun NavController.navigateNormalLogin(userType: UserType) { - navigate("${LoginRoute.normal_login}/$userType") + navigate("${LoginRoute.NORMAL_LOGIN}/$userType") } fun NavController.navigateEmailSearch(userType: UserType) { - navigate("${LoginRoute.email_search}/$userType") + navigate("${LoginRoute.EMAIL_SEARCH}/$userType") } fun NavController.navigateEmailSearchComplete(email: String) { @@ -38,7 +40,11 @@ fun NavController.navigatePasswordSearchAuth(userType: UserType) { } fun NavController.navigatePasswordSearch(userType: UserType) { - navigate("${LoginRoute.password_search}/$userType") + navigate("${LoginRoute.PASSWORD_SEARCH}/$userType") +} + +fun NavController.navigateToNoAccount(accountType: AccountType) { + navigate("${LoginRoute.NO_ACCOUNT}/$accountType") } fun NavGraphBuilder.loginNavGraph( @@ -55,9 +61,10 @@ fun NavGraphBuilder.loginNavGraph( onNavigateToPasswordSearchAuth: (UserType) -> Unit, onNavigateToLoginRoute: () -> Unit, onSendMessage: (String) -> Unit, - onVerifyCode: (String, (Boolean) -> Unit) -> Unit + onVerifyCode: (String, (Boolean) -> Unit) -> Unit, + onNavigateToNoAccount: (AccountType) -> Unit ) { - composable(route = LoginRoute.route) { + composable(route = LoginRoute.ROUTE) { LoginRoute( finish, onNavigateToNormalLogin, @@ -70,7 +77,7 @@ fun NavGraphBuilder.loginNavGraph( } composable( - route = "${LoginRoute.normal_login}/{type}", + route = "${LoginRoute.NORMAL_LOGIN}/{type}", arguments = listOf( navArgument("type") { type = NavType.EnumType(UserType::class.java) @@ -79,17 +86,15 @@ fun NavGraphBuilder.loginNavGraph( ) { NormalLoginScreen( onBackClick = onBackClick, - userType = it.arguments!!.getSerializable("type") as UserType, onNavigateToSignUp = onNavigateToSignup, onNavigateToVolunteerHome = onNavigateToVolunteer, - onNavigateToIntermediatorHome = onNavigateToIntermediatorHome, onNavigateToEmailSearch = onNavigateToEmailSearch, onNavigateToPasswordSearch = onNavigateToPasswordSearchAuth ) } composable( - route = "${LoginRoute.email_search}/{type}", + route = "${LoginRoute.EMAIL_SEARCH}/{type}", arguments = listOf( navArgument("type") { type = NavType.EnumType(UserType::class.java) @@ -122,14 +127,14 @@ fun NavGraphBuilder.loginNavGraph( } composable( - route = "${LoginRoute.password_search}/{type}", + route = "${LoginRoute.PASSWORD_SEARCH}/{type}", arguments = listOf( navArgument("type") { type = NavType.EnumType(UserType::class.java) } ) ) { - PasswordSearchScreen( + PasswordResetScreen( onBackClick = onBackClick, userType = it.arguments!!.getSerializable("type") as UserType, imeHeight = imeHeight, @@ -145,20 +150,36 @@ fun NavGraphBuilder.loginNavGraph( } ) ) { - PasswordSearchAuthScreen( + EmailAuthForPasswordResetScreen( onBackClick = onBackClick, imeHeight = imeHeight, onNavigateToPasswordSearch = onNavigateToPasswordSearch, - userType = it.arguments!!.getSerializable("type") as UserType + onNavigateToNoAccount = onNavigateToNoAccount, + userType = it.arguments!!.getSerializable("type") as UserType, + ) + } + + composable( + route = "${LoginRoute.NO_ACCOUNT}/{accountType}", + arguments = listOf( + navArgument("accountType") { + type = NavType.EnumType(AccountType::class.java) + } + ) + ) { + NoAccountScreen( + accountType = it.arguments!!.getSerializable("accountType") as AccountType, + onNavigateToLoginRoute = onNavigateToLoginRoute ) } } object LoginRoute { - const val route = "login" - const val normal_login = "normal_login" - const val email_search = "email_search" - const val password_search = "password_search" + const val ROUTE = "login" + const val NORMAL_LOGIN = "normal_login" + const val EMAIL_SEARCH = "email_search" + const val PASSWORD_SEARCH = "password_search" const val email_search_complete = "email_search_complete" const val password_search_auth = "password_search_auth" + const val NO_ACCOUNT = "no_account" } diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/PasswordSearchAuthScreen.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailAuthForPasswordResetScreen.kt similarity index 57% rename from feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/PasswordSearchAuthScreen.kt rename to feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailAuthForPasswordResetScreen.kt index 0f549f390..39f818a5d 100644 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/PasswordSearchAuthScreen.kt +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailAuthForPasswordResetScreen.kt @@ -11,11 +11,9 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardType @@ -23,21 +21,23 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import com.kusitms.connectdog.core.designsystem.component.ConnectDogBottomButton -import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextFieldWithButton +import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType -import com.kusitms.connectdog.core.designsystem.theme.Gray5 -import com.kusitms.connectdog.core.designsystem.theme.PetOrange -import com.kusitms.connectdog.core.designsystem.theme.Red1 +import com.kusitms.connectdog.core.util.AccountType import com.kusitms.connectdog.core.util.UserType import com.kusitms.connectdog.feature.login.R -import com.kusitms.connectdog.feature.login.viewmodel.PasswordSearchAuthViewModel +import com.kusitms.connectdog.feature.login.state.EmailAuthForPasswordResetSideEffect +import com.kusitms.connectdog.feature.login.viewmodel.EmailAuthForPasswordResetViewModel +import org.orbitmvi.orbit.compose.collectAsState +import org.orbitmvi.orbit.compose.collectSideEffect @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable -fun PasswordSearchAuthScreen( +fun EmailAuthForPasswordResetScreen( onBackClick: () -> Unit, onNavigateToPasswordSearch: (UserType) -> Unit, + onNavigateToNoAccount: (AccountType) -> Unit, imeHeight: Int, userType: UserType ) { @@ -53,6 +53,7 @@ fun PasswordSearchAuthScreen( Content( imeHeight = imeHeight, onNavigateToPasswordSearch = onNavigateToPasswordSearch, + onNavigateToNoAccount = onNavigateToNoAccount, userType = userType ) } @@ -62,15 +63,21 @@ fun PasswordSearchAuthScreen( private fun Content( imeHeight: Int, onNavigateToPasswordSearch: (UserType) -> Unit, + onNavigateToNoAccount: (AccountType) -> Unit, userType: UserType, - viewModel: PasswordSearchAuthViewModel = hiltViewModel() + viewModel: EmailAuthForPasswordResetViewModel = hiltViewModel() ) { val focusManager = LocalFocusManager.current val interactionSource = remember { MutableInteractionSource() } - val context = LocalContext.current - val isValidEmail by viewModel.isValidEmail.collectAsState() - val isEmailVerified by viewModel.isEmailVerified.collectAsState() - val isEmailError by viewModel.isEmailError.collectAsState() + + val uiState by viewModel.collectAsState() + + viewModel.collectSideEffect { + when(it) { + EmailAuthForPasswordResetSideEffect.NavigateToFail -> onNavigateToNoAccount(AccountType.PASSWORD) + EmailAuthForPasswordResetSideEffect.NavigateToPasswordReset -> onNavigateToPasswordSearch(userType) + } + } Column( modifier = Modifier @@ -78,7 +85,7 @@ private fun Content( .padding(top = 80.dp, bottom = 24.dp) .padding(horizontal = 20.dp) .clickable( - onClick = { focusManager.clearFocus() }, + onClick = focusManager::clearFocus, indication = null, interactionSource = interactionSource ) @@ -90,43 +97,29 @@ private fun Content( lineHeight = 28.sp ) Spacer(modifier = Modifier.height(40.dp)) - ConnectDogTextFieldWithButton( - text = viewModel.email, - width = 62, - height = 27, - textFieldLabel = "이메일", + ConnectDogTextField( + text = uiState.email, + label = "이메일", placeholder = "이메일 입력", - buttonLabel = "인증 요청", - isError = (isValidEmail ?: false) || (isEmailError == true), - onTextChanged = { - viewModel.updateEmail(it) - viewModel.updateEmailValidity() - }, - borderColor = if (isValidEmail == false) PetOrange else Gray5, - onClick = { viewModel.postEmail(context, userType) }, - padding = 5 + onTextChanged = viewModel::onEmailChanged, ) Spacer(modifier = Modifier.height(12.dp)) - ConnectDogTextFieldWithButton( - text = viewModel.certificationNumber, - width = 62, - height = 27, - textFieldLabel = "인증 번호", - placeholder = "숫자 6자리", - buttonLabel = "인증 확인", - keyboardType = KeyboardType.Text, - onTextChanged = { viewModel.updateCertificationNumber(it) }, - borderColor = if (viewModel.isEmailVerified.value == true) PetOrange else if (viewModel.isEmailVerified.value == false) Red1 else Gray5, - onClick = { viewModel.checkCertificationNumber(context) }, - padding = 5, - isError = isEmailVerified == false - ) + if(uiState.isSendAuthCode) { + ConnectDogTextField( + text = uiState.inputAuthCode, + label = "인증 번호", + placeholder = "숫자 6자리", + keyboardType = KeyboardType.Text, + onTextChanged = viewModel::onInputAuthCodeChanged, + isError = uiState.isAuthCodeError + ) + } Spacer(modifier = Modifier.weight(1f)) ConnectDogBottomButton( - onClick = { onNavigateToPasswordSearch(userType) }, - content = "인증 완료", - enabled = isEmailVerified == true + onClick = { viewModel.onNextButtonClick(userType) }, + content = uiState.bottomButtonText, + enabled = uiState.enableNext ) - Spacer(modifier = Modifier.height(imeHeight.dp)) + Spacer(modifier = Modifier.height((imeHeight+32).dp)) } } diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailSearchResultScreen.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailSearchResultScreen.kt index ae2bde448..4e7f06e9b 100644 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailSearchResultScreen.kt +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailSearchResultScreen.kt @@ -28,7 +28,7 @@ import com.kusitms.connectdog.feature.login.R @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable -internal fun EmailSearchResultScreen( +fun EmailSearchResultScreen( onBackClick: () -> Unit, email: String, navigateToLoginRoute: () -> Unit diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailSearchScreen.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailSearchScreen.kt index 8debff384..2f671f1f2 100644 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailSearchScreen.kt +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/EmailSearchScreen.kt @@ -1,34 +1,40 @@ package com.kusitms.connectdog.feature.login.screen import android.annotation.SuppressLint -import android.widget.Toast +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row 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.layout.width 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.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import com.kusitms.connectdog.core.designsystem.component.ConnectDogBottomButton -import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextFieldWithButton +import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType +import com.kusitms.connectdog.core.designsystem.theme.Gray60 +import com.kusitms.connectdog.core.designsystem.theme.Gray80 +import com.kusitms.connectdog.core.designsystem.theme.Red1 import com.kusitms.connectdog.core.util.UserType import com.kusitms.connectdog.feature.login.R -import com.kusitms.connectdog.feature.login.viewmodel.SearchViewModel +import com.kusitms.connectdog.feature.login.state.EmailSearchSideEffect +import com.kusitms.connectdog.feature.login.viewmodel.EmailSearchViewModel +import org.orbitmvi.orbit.compose.collectAsState +import org.orbitmvi.orbit.compose.collectSideEffect @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable @@ -39,7 +45,7 @@ fun EmailSearchScreen( onSendMessageClick: (String) -> Unit, onVerifyCodeClick: (String, (Boolean) -> Unit) -> Unit, userType: UserType, - viewModel: SearchViewModel = hiltViewModel() + viewModel: EmailSearchViewModel = hiltViewModel() ) { Scaffold( topBar = { @@ -68,15 +74,15 @@ private fun Content( onSendMessageClick: (String) -> Unit, onVerifyCodeClick: (String, (Boolean) -> Unit) -> Unit, userType: UserType, - viewModel: SearchViewModel + viewModel: EmailSearchViewModel ) { - val context = LocalContext.current - val isSendNumber by remember { viewModel.isSendNumber }.collectAsState() - val isCertified by remember { viewModel.isCertified }.collectAsState() + val uiState by viewModel.collectAsState() - LaunchedEffect(key1 = viewModel) { - viewModel.findEmail.collect { - it?.let { navigateToCompleteScreen(it) } + viewModel.collectSideEffect { sideEffect -> + when(sideEffect) { + is EmailSearchSideEffect.NavigateToEmailSearchResult -> { + uiState.email?.let { navigateToCompleteScreen(it) } + } } } @@ -87,68 +93,66 @@ private fun Content( ) { Spacer(modifier = Modifier.height(80.dp)) Text( - text = "휴대폰 번호 인증을\n진행해주세요", + text = stringResource(id = R.string.email_auth_title), fontSize = 20.sp, fontWeight = FontWeight.Bold, lineHeight = 25.sp ) Spacer(modifier = Modifier.height(40.dp)) - ConnectDogTextFieldWithButton( - text = viewModel.phoneNumber, - width = 62, - height = 27, - textFieldLabel = "휴대폰 번호", + ConnectDogTextField( + text = uiState.phoneNumber, + label = stringResource(id = R.string.phone_number), keyboardType = KeyboardType.Number, placeholder = "- 빼고 입력", - buttonLabel = "인증 요청", - onTextChanged = { if (it.length <= 11) viewModel.updatePhoneNumber(it) }, - onClick = { - if (viewModel.phoneNumber.isEmpty()) { - Toast.makeText(context, "휴대폰 번호를 입력해주세요", Toast.LENGTH_SHORT).show() - } else if (viewModel.phoneNumber.length == 11) { - onSendMessageClick(viewModel.phoneNumber) - Toast.makeText(context, "인증번호를 전송하였습니다.", Toast.LENGTH_SHORT).show() - viewModel.updateIsSendNumber(true) - } else { - Toast.makeText(context, "올바른 휴대폰 번호를 입력해주세요", Toast.LENGTH_SHORT).show() - } - }, - padding = 5 + onTextChanged = viewModel::onPhoneNumberChanged, ) Spacer(modifier = Modifier.height(12.dp)) - ConnectDogTextFieldWithButton( - text = viewModel.certificationNumber, - width = 62, - height = 27, - textFieldLabel = "인증번호", - keyboardType = KeyboardType.Number, - placeholder = "인증번호 6자리", - buttonLabel = "인증 확인", - onTextChanged = { if (it.length <= 6) viewModel.updateCertificationNumber(it) }, - onClick = { - if (!isSendNumber) { - Toast.makeText(context, "먼저 인증번호를 전송해주세요", Toast.LENGTH_SHORT).show() - } else { - if (viewModel.certificationNumber.isEmpty()) { - Toast.makeText(context, "인증 번호를 입력해주세요", Toast.LENGTH_SHORT).show() - } else if (viewModel.certificationNumber.length == 6) { - onVerifyCodeClick(it) { viewModel.updateIsCertified(it) } - } else { - Toast.makeText(context, "인증 번호는 6자리로 입력해주세요", Toast.LENGTH_SHORT).show() - } - } - }, - padding = 5 - ) + if(uiState.isSendAuthCode) { + ConnectDogTextField( + text = uiState.authCode, + label = "인증번호", + keyboardType = KeyboardType.Number, + placeholder = "인증번호 6자리", + onTextChanged = viewModel::onAuthCodeChanged, + isError = (uiState.isAuthCodeError == true) + ) + if(uiState.isAuthCodeError == true) { + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = "올바른 인증번호를 입력해주세요", + fontSize = 10.sp, + color = Red1 + ) + } + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 12.dp), + horizontalArrangement = Arrangement.Center + ) { + Text( + text = "인증번호가 오지 않는다면?", + color = Gray60, + fontSize = 12.sp + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + modifier = Modifier.clickable { }, + text = "재발송", + fontSize = 12.sp, + color = Gray80, + fontWeight = FontWeight.SemiBold + ) + } + } Spacer(modifier = Modifier.weight(1f)) ConnectDogBottomButton( - content = "다음", - enabled = isCertified, - onClick = { viewModel.test(userType = userType, context = context) }, - modifier = - Modifier + modifier = Modifier .fillMaxWidth() - .height(56.dp) + .height(56.dp), + content = uiState.bottomButtonText, + enabled = uiState.enableNext, + onClick = { viewModel.onNextClick(userType, onSendMessageClick, onVerifyCodeClick) }, ) Spacer(modifier = Modifier.height((imeHeight + 32).dp)) } diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/LoginScreen.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/LoginScreen.kt index 6a34c0c59..3c4f246a7 100644 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/LoginScreen.kt +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/LoginScreen.kt @@ -15,14 +15,12 @@ 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.layout.width +import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Tab import androidx.compose.material3.TabRow 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.remember import androidx.compose.runtime.rememberCoroutineScope @@ -41,6 +39,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import com.google.accompanist.pager.ExperimentalPagerApi import com.google.accompanist.pager.HorizontalPager import com.google.accompanist.pager.rememberPagerState +import com.kusitms.connectdog.core.designsystem.component.ActionRow import com.kusitms.connectdog.core.designsystem.component.ConnectDogIconBottomButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogNormalButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField @@ -49,12 +48,14 @@ import com.kusitms.connectdog.core.designsystem.theme.Gray2 import com.kusitms.connectdog.core.designsystem.theme.KAKAO import com.kusitms.connectdog.core.designsystem.theme.NAVER import com.kusitms.connectdog.core.designsystem.theme.PetOrange -import com.kusitms.connectdog.core.util.SocialType import com.kusitms.connectdog.core.util.UserType import com.kusitms.connectdog.feature.login.R +import com.kusitms.connectdog.feature.login.state.LoginSideEffect import com.kusitms.connectdog.feature.login.viewmodel.LoginViewModel -import com.kusitms.connectdog.feature.login.viewmodel.Provider import kotlinx.coroutines.launch +import org.orbitmvi.orbit.compose.collectAsState +import org.orbitmvi.orbit.compose.collectSideEffect +import com.kusitms.connectdog.core.designsystem.R.drawable as DR @Composable internal fun LoginRoute( @@ -94,7 +95,7 @@ fun LoginScreen( modifier = Modifier .fillMaxSize() .clickable( - onClick = { focusManager.clearFocus() }, + onClick = focusManager::clearFocus, indication = null, interactionSource = interactionSource ) @@ -115,11 +116,11 @@ fun LoginScreen( ) Spacer(modifier = Modifier.weight(1f)) Image( - painter = painterResource(id = com.kusitms.connectdog.core.designsystem.R.drawable.ic_main), - contentDescription = null, modifier = Modifier .fillMaxWidth() - .aspectRatio(1f) + .aspectRatio(1f), + painter = painterResource(id = DR.ic_main), + contentDescription = null, ) } } @@ -135,9 +136,7 @@ private fun LoginContent( onNavigateToPasswordSearch: (UserType) -> Unit ) { val pages = listOf("이동봉사자 회원", "이동봉사 모집자 회원") - Column( - modifier = Modifier.height(340.dp) - ) { + Column { val pagerState = rememberPagerState() val coroutineScope = rememberCoroutineScope() @@ -146,8 +145,8 @@ private fun LoginContent( .height(37.dp) .fillMaxWidth(0.5f) .padding( - start = if (pagerState.currentPage == 0) 0.dp else 10.dp, - end = if (pagerState.currentPage == 0) 10.dp else 0.dp + start = if (pagerState.currentPage == 0) 0.dp else 33.dp, + end = if (pagerState.currentPage == 0) 33.dp else 0.dp ) .align(if (pagerState.currentPage == 0) Alignment.End else Alignment.Start) ) { @@ -160,8 +159,7 @@ private fun LoginContent( } TabRow( - modifier = Modifier - .padding(start = 10.dp, end = 10.dp), + modifier = Modifier.padding(horizontal = 10.dp), selectedTabIndex = pagerState.currentPage ) { pages.forEachIndexed { index, title -> @@ -177,17 +175,15 @@ private fun LoginContent( ) }, selected = pagerState.currentPage == index, - onClick = { - coroutineScope.launch { - pagerState.scrollToPage(index) - } - } + onClick = { coroutineScope.launch { pagerState.scrollToPage(index) } } ) } } + HorizontalPager( + modifier = Modifier.height(400.dp), count = pages.size, - state = pagerState + state = pagerState, ) { when (it) { 0 -> Volunteer( @@ -213,33 +209,32 @@ private fun Volunteer( onNavigateToSignup: (UserType) -> Unit, onNavigateToVolunteerHome: () -> Unit, viewModel: LoginViewModel = hiltViewModel() -) { +) { val context = LocalContext.current - val socialType by viewModel.socialType.collectAsState() - socialType?.let { - when (it) { - SocialType.VOLUNTEER -> onNavigateToVolunteerHome() - SocialType.GUEST -> onNavigateToSignup(UserType.SOCIAL_VOLUNTEER) + viewModel.collectSideEffect { sideEffect -> + when (sideEffect) { + is LoginSideEffect.NavigateToHome -> onNavigateToVolunteerHome() + is LoginSideEffect.NavigateToSignUp -> onNavigateToSignup(UserType.SOCIAL_VOLUNTEER) } } Column( - horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier .fillMaxHeight() - .padding(top = 32.dp) + .padding(top = 25.dp), + horizontalAlignment = Alignment.CenterHorizontally, ) { Spacer(modifier = Modifier.height(20.dp)) ConnectDogIconBottomButton( - iconId = R.drawable.ic_kakao, - contentDescription = "kakao login", - onClick = { viewModel.initSocialLogin(Provider.KAKAO, context) }, - content = stringResource(id = R.string.kakao_login), modifier = Modifier .fillMaxWidth() .padding(horizontal = 20.dp), color = KAKAO, + iconId = R.drawable.ic_kakao, + contentDescription = "kakao login", + onClick = { viewModel.initKakaoLogin(context) }, + content = stringResource(id = R.string.kakao_login), textColor = Color(0xFF373737) ) Spacer(modifier = Modifier.height(10.dp)) @@ -250,11 +245,14 @@ private fun Volunteer( color = NAVER, iconId = R.drawable.ic_naver, contentDescription = "naver login", - onClick = { viewModel.initSocialLogin(Provider.NAVER, context) }, + onClick = { viewModel.initNaverLogin(context) }, content = stringResource(id = R.string.naver_login) ) Spacer(modifier = Modifier.height(30.dp)) - SignUpOrLogin(onNavigateToSignup, onNavigateToNormalLogin, UserType.NORMAL_VOLUNTEER) + ActionRow( + stringResource(id = R.string.email_signup) to { onNavigateToSignup(UserType.NORMAL_VOLUNTEER) }, + stringResource(id = R.string.email_login) to { onNavigateToNormalLogin(UserType.NORMAL_VOLUNTEER) } + ) } } @@ -266,11 +264,12 @@ private fun Intermediator( onNavigateToPasswordSearch: (UserType) -> Unit, viewModel: LoginViewModel = hiltViewModel() ) { - val isLoginSuccessful by viewModel.isLoginSuccessful.collectAsState() + val uiState by viewModel.collectAsState() - LaunchedEffect(key1 = viewModel) { - viewModel.isLoginSuccessful.collect { - if (it == true) { onNavigateToIntermediatorHome() } + viewModel.collectSideEffect { + when(it) { + is LoginSideEffect.NavigateToHome -> onNavigateToIntermediatorHome() + is LoginSideEffect.NavigateToSignUp -> null } } @@ -278,70 +277,38 @@ private fun Intermediator( verticalArrangement = Arrangement.Top, horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier - .padding(top = 32.dp, start = 20.dp, end = 20.dp) .fillMaxHeight() + .padding(top = 25.dp) + .padding(horizontal = 20.dp) ) { ConnectDogTextField( - text = viewModel.email, - label = "이메일", - placeholder = "이메일 입력", + text = uiState.email, + label = stringResource(id = R.string.email), + placeholder = stringResource(id = R.string.input_email), keyboardType = KeyboardType.Text, - onTextChanged = { viewModel.updateEmail(it) }, - isError = (isLoginSuccessful == false) + onTextChanged = viewModel::onEmailChanged, + isError = (uiState.isLoginSuccessful == false) ) Spacer(modifier = Modifier.height(12.dp)) ConnectDogTextField( - text = viewModel.password, - label = "비밀번호", - placeholder = "비밀번호 입력", + text = uiState.password, + label = stringResource(id = R.string.password), + placeholder = stringResource(id = R.string.input_password), keyboardType = KeyboardType.Password, - onTextChanged = { viewModel.updatePassword(it) }, - isError = (isLoginSuccessful == false) + onTextChanged = viewModel::onPasswordChanged, + isError = (uiState.isLoginSuccessful == false) ) Spacer(modifier = Modifier.height(12.dp)) ConnectDogNormalButton( - modifier = Modifier - .fillMaxWidth(), + modifier = Modifier.fillMaxWidth(), content = stringResource(id = R.string.login), - onClick = { - viewModel.initIntermediatorLogin() - } + onClick = viewModel::initIntermediatorLogin ) Spacer(modifier = Modifier.height(30.dp)) - AccountFind( - onNavigateToSignup = onNavigateToSignup, - onNavigateToEmailSearch = { onNavigateToEmailSearch(UserType.INTERMEDIATOR) }, - onNavigateToPasswordSearch = { onNavigateToPasswordSearch(UserType.INTERMEDIATOR) }, - userType = UserType.INTERMEDIATOR - ) - } -} - -@Composable -private fun SignUpOrLogin( - onNavigateToSignup: (UserType) -> Unit, - onNavigateToNormalLogin: (UserType) -> Unit, - userType: UserType -) { - Row { - Text( - modifier = Modifier.clickable { onNavigateToSignup(userType) }, - text = "이메일로 회원가입", - fontSize = 12.sp, - color = Gray2 - ) - Spacer(modifier = Modifier.width(16.dp)) - Text( - text = "|", - fontSize = 12.sp, - color = Gray2 - ) - Spacer(modifier = Modifier.width(16.dp)) - Text( - modifier = Modifier.clickable { onNavigateToNormalLogin(userType) }, - text = "이메일 로그인", - fontSize = 12.sp, - color = Gray2 + ActionRow( + stringResource(id = R.string.email_signup) to { onNavigateToSignup(UserType.INTERMEDIATOR) }, + stringResource(id = R.string.email_search) to { onNavigateToEmailSearch(UserType.INTERMEDIATOR) }, + stringResource(id = R.string.password_search) to { onNavigateToPasswordSearch(UserType.INTERMEDIATOR) } ) } } diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/NoAccountScreen.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/NoAccountScreen.kt new file mode 100644 index 000000000..509f37a34 --- /dev/null +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/NoAccountScreen.kt @@ -0,0 +1,57 @@ +package com.kusitms.connectdog.feature.login.screen + +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.kusitms.connectdog.core.designsystem.component.ConnectDogBottomButton +import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar +import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType +import com.kusitms.connectdog.core.designsystem.theme.Gray100 +import com.kusitms.connectdog.core.designsystem.theme.Gray60 +import com.kusitms.connectdog.core.util.AccountType +import com.kusitms.connectdog.feature.login.R + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Composable +fun NoAccountScreen( + accountType: AccountType, + onNavigateToLoginRoute: () -> Unit, +) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 20.dp) + .padding(vertical = 32.dp), + ) { + Spacer(modifier = Modifier.height(48.dp)) + Text( + text = stringResource(id = R.string.no_account_title), + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + color = Gray100 + ) + Spacer(modifier = Modifier.height(12.dp)) + Text( + text = stringResource(id = R.string.no_account_subtitle), + fontSize = 15.sp, + fontWeight = FontWeight.Normal, + color = Gray60 + ) + Spacer(modifier = Modifier.weight(1f)) + ConnectDogBottomButton( + content = "처음으로 돌아가기", + onClick = onNavigateToLoginRoute + ) + } +} \ No newline at end of file diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/NormalLoginScreen.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/NormalLoginScreen.kt index 728995ed1..c86a4b302 100644 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/NormalLoginScreen.kt +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/NormalLoginScreen.kt @@ -4,70 +4,59 @@ import android.annotation.SuppressLint import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.aspectRatio 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.layout.width import androidx.compose.material3.MaterialTheme 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.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel -import com.kusitms.connectdog.core.designsystem.R +import com.kusitms.connectdog.core.designsystem.R as DR +import com.kusitms.connectdog.core.designsystem.component.ActionRow import com.kusitms.connectdog.core.designsystem.component.ConnectDogErrorCard import com.kusitms.connectdog.core.designsystem.component.ConnectDogNormalButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType -import com.kusitms.connectdog.core.designsystem.theme.Gray2 import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.feature.login.R +import com.kusitms.connectdog.feature.login.state.LoginSideEffect import com.kusitms.connectdog.feature.login.viewmodel.LoginViewModel - -private const val TAG = "EmailLoginScreen" +import org.orbitmvi.orbit.compose.collectAsState +import org.orbitmvi.orbit.compose.collectSideEffect @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable internal fun NormalLoginScreen( - userType: UserType, onBackClick: () -> Unit, onNavigateToSignUp: (UserType) -> Unit, onNavigateToVolunteerHome: () -> Unit, - onNavigateToIntermediatorHome: () -> Unit, onNavigateToEmailSearch: (UserType) -> Unit, onNavigateToPasswordSearch: (UserType) -> Unit, viewModel: LoginViewModel = hiltViewModel() ) { val focusManager = LocalFocusManager.current val interactionSource = remember { MutableInteractionSource() } - val isLoginSuccessful by viewModel.isLoginSuccessful.collectAsState() - LaunchedEffect(key1 = viewModel) { - viewModel.isLoginSuccessful.collect { - if (it == true) { - when (userType) { - UserType.INTERMEDIATOR -> onNavigateToIntermediatorHome() - else -> onNavigateToVolunteerHome() - } - } + viewModel.collectSideEffect { + when (it) { + is LoginSideEffect.NavigateToHome -> onNavigateToVolunteerHome() + is LoginSideEffect.NavigateToSignUp -> null } } @@ -80,11 +69,7 @@ internal fun NormalLoginScreen( ), topBar = { ConnectDogTopAppBar( - titleRes = when (userType) { - UserType.SOCIAL_VOLUNTEER -> R.string.volunteer_login - UserType.NORMAL_VOLUNTEER -> R.string.volunteer_login - UserType.INTERMEDIATOR -> R.string.intermediator_login - }, + titleRes = DR.string.volunteer_login, navigationType = TopAppBarNavigationType.BACK, navigationIconContentDescription = "Navigation icon", onNavigationClick = onBackClick @@ -96,8 +81,6 @@ internal fun NormalLoginScreen( onNavigateToSignUp = onNavigateToSignUp, onNavigateToEmailSearch = onNavigateToEmailSearch, onNavigateToPasswordSearch = onNavigateToPasswordSearch, - userType = userType, - isLoginSuccessful = isLoginSuccessful ) } } @@ -108,9 +91,9 @@ private fun Content( onNavigateToSignUp: (UserType) -> Unit, onNavigateToEmailSearch: (UserType) -> Unit, onNavigateToPasswordSearch: (UserType) -> Unit, - userType: UserType, - isLoginSuccessful: Boolean? ) { + val uiState by viewModel.collectAsState() + Column( modifier = Modifier .fillMaxSize() @@ -122,54 +105,57 @@ private fun Content( .padding(horizontal = 20.dp) ) { ConnectDogTextField( - text = viewModel.email, - label = "이메일", - placeholder = "이메일 입력", + text = uiState.email, + label = stringResource(id = R.string.email), + placeholder = stringResource(id = R.string.email), keyboardType = KeyboardType.Text, - onTextChanged = { viewModel.updateEmail(it) }, - isError = isLoginSuccessful?.let { !it } ?: run { false } + onTextChanged = viewModel::onEmailChanged, + isError = uiState.isLoginSuccessful?.let { !it } ?: run { false } ) Spacer(modifier = Modifier.height(12.dp)) ConnectDogTextField( - text = viewModel.password, - label = "비밀번호", - placeholder = "비밀번호 입력", + text = uiState.password, + label = stringResource(id = R.string.password), + placeholder = stringResource(id = R.string.input_password), keyboardType = KeyboardType.Password, - onTextChanged = { viewModel.updatePassword(it) }, - isError = isLoginSuccessful?.let { !it } ?: run { false } + onTextChanged = viewModel::onPasswordChanged, + isError = uiState.isLoginSuccessful?.let { !it } ?: run { false } ) Spacer(modifier = Modifier.height(12.dp)) ConnectDogNormalButton( - content = "로그인", + content = stringResource(id = R.string.login), color = MaterialTheme.colorScheme.primary, - onClick = { viewModel.initVolunteerLogin() }, + onClick = viewModel::initVolunteerLogin, modifier = Modifier .fillMaxWidth() .height(56.dp) ) Spacer(modifier = Modifier.height(30.dp)) - AccountFind( - onNavigateToSignup = onNavigateToSignUp, - onNavigateToEmailSearch = onNavigateToEmailSearch, - onNavigateToPasswordSearch = onNavigateToPasswordSearch, - userType = userType + ActionRow( + stringResource(id = R.string.email_signup) to { onNavigateToSignUp(UserType.NORMAL_VOLUNTEER) }, + stringResource(id = R.string.email_search) to { onNavigateToEmailSearch(UserType.NORMAL_VOLUNTEER) }, + stringResource(id = R.string.password_search) to { + onNavigateToPasswordSearch( + UserType.NORMAL_VOLUNTEER + ) + } ) } Spacer(modifier = Modifier.height(30.dp)) Box( modifier = Modifier.fillMaxSize() ) { - if (isLoginSuccessful?.let { !it } ?: run { false }) { + if (uiState.isLoginSuccessful?.let { !it } ?: run { false }) { ConnectDogErrorCard( modifier = Modifier .zIndex(1f) .align(Alignment.TopCenter) .padding(horizontal = 20.dp), - errorMessage = R.string.login_error + errorMessage = DR.string.login_error ) } Image( - painter = painterResource(id = R.drawable.ic_main_large), + painter = painterResource(id = DR.drawable.ic_main_large), contentDescription = null, modifier = Modifier .fillMaxWidth() @@ -179,49 +165,3 @@ private fun Content( } } } - -@Composable -fun AccountFind( - onNavigateToSignup: (UserType) -> Unit, - onNavigateToEmailSearch: (UserType) -> Unit, - onNavigateToPasswordSearch: (UserType) -> Unit, - userType: UserType -) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - Text( - modifier = Modifier.clickable { onNavigateToSignup(userType) }, - text = "이메일로 회원가입", - fontSize = 12.sp, - color = Gray2 - ) - Spacer(modifier = Modifier.width(16.dp)) - Text( - text = "|", - fontSize = 12.sp, - color = Gray2 - ) - Spacer(modifier = Modifier.width(16.dp)) - Text( - modifier = Modifier.clickable { onNavigateToEmailSearch(UserType.NORMAL_VOLUNTEER) }, - text = "이메일 찾기", - fontSize = 12.sp, - color = Gray2 - ) - Spacer(modifier = Modifier.width(16.dp)) - Text( - text = "|", - fontSize = 12.sp, - color = Gray2 - ) - Spacer(modifier = Modifier.width(16.dp)) - Text( - modifier = Modifier.clickable { onNavigateToPasswordSearch(UserType.NORMAL_VOLUNTEER) }, - text = "비밀번호 찾기", - fontSize = 12.sp, - color = Gray2 - ) - } -} diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/PasswordSearchScreen.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/PasswordResetScreen.kt similarity index 96% rename from feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/PasswordSearchScreen.kt rename to feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/PasswordResetScreen.kt index 9b3a3f3da..1c21c7634 100644 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/PasswordSearchScreen.kt +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/screen/PasswordResetScreen.kt @@ -30,11 +30,11 @@ import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationTyp import com.kusitms.connectdog.core.designsystem.theme.Gray3 import com.kusitms.connectdog.core.util.UserType import com.kusitms.connectdog.feature.login.R -import com.kusitms.connectdog.feature.login.viewmodel.PasswordSearchViewModel +import com.kusitms.connectdog.feature.login.viewmodel.PasswordResetViewModel @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable -fun PasswordSearchScreen( +fun PasswordResetScreen( onBackClick: () -> Unit, imeHeight: Int, navigateToLoginRoute: () -> Unit, @@ -60,7 +60,7 @@ fun PasswordSearchScreen( @Composable private fun Content( imeHeight: Int, - viewModel: PasswordSearchViewModel = hiltViewModel(), + viewModel: PasswordResetViewModel = hiltViewModel(), navigateToLoginRoute: () -> Unit, userType: UserType ) { diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/EmailAuthForPasswordResetUiState.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/EmailAuthForPasswordResetUiState.kt new file mode 100644 index 000000000..f0693f5a6 --- /dev/null +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/EmailAuthForPasswordResetUiState.kt @@ -0,0 +1,36 @@ +package com.kusitms.connectdog.feature.login.state + +import com.kusitms.connectdog.core.util.emptyString + +data class EmailAuthForPasswordResetUiState( + val email: String, + val inputAuthCode: String, + val authCode: String, + val isSendAuthCode: Boolean, + val isValidEmail: Boolean, + val isEmailError: Boolean, + val accessToken: String, + val bottomButtonText: String, + val enableNext: Boolean, + val isAuthCodeError: Boolean, +) { + companion object { + fun empty() = EmailAuthForPasswordResetUiState( + email = emptyString(), + inputAuthCode = emptyString(), + authCode = emptyString(), + accessToken = emptyString(), + isSendAuthCode = false, + isValidEmail = false, + bottomButtonText = "인증 요청", + enableNext = false, + isEmailError = false, + isAuthCodeError = false, + ) + } +} + +sealed class EmailAuthForPasswordResetSideEffect { + object NavigateToFail: EmailAuthForPasswordResetSideEffect() + object NavigateToPasswordReset: EmailAuthForPasswordResetSideEffect() +} \ No newline at end of file diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/EmailSearchUiState.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/EmailSearchUiState.kt new file mode 100644 index 000000000..f35b5ea23 --- /dev/null +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/EmailSearchUiState.kt @@ -0,0 +1,29 @@ +package com.kusitms.connectdog.feature.login.state + +import com.kusitms.connectdog.core.util.emptyString + +data class EmailSearchUiState( + val phoneNumber: String, + val isSendAuthCode: Boolean, + val authCode: String, + val email: String?, + val enableNext: Boolean, + val bottomButtonText: String, + val isAuthCodeError: Boolean? +) { + companion object { + fun empty() = EmailSearchUiState( + phoneNumber = emptyString(), + authCode = emptyString(), + isSendAuthCode = false, + email = null, + enableNext = false, + bottomButtonText = "인증 요청", + isAuthCodeError = null + ) + } +} + +sealed class EmailSearchSideEffect { + object NavigateToEmailSearchResult: EmailSearchSideEffect() +} \ No newline at end of file diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/LoginUiState.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/LoginUiState.kt new file mode 100644 index 000000000..b0579c688 --- /dev/null +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/LoginUiState.kt @@ -0,0 +1,28 @@ +package com.kusitms.connectdog.feature.login.state + +import com.kusitms.connectdog.core.util.SocialType +import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.core.util.emptyString + +data class LoginUiState( + val email: String, + val password: String, + val isLoginSuccessful: Boolean?, + val socialType: SocialType?, + val socialToken: String +) { + companion object { + fun empty() = LoginUiState( + email = emptyString(), + password = emptyString(), + isLoginSuccessful = null, + socialType = null, + socialToken = emptyString() + ) + } +} + +sealed class LoginSideEffect { + object NavigateToHome: LoginSideEffect() + data class NavigateToSignUp(val userType: UserType): LoginSideEffect() +} \ No newline at end of file diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/PasswordResetUiState.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/PasswordResetUiState.kt new file mode 100644 index 000000000..57235515c --- /dev/null +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/state/PasswordResetUiState.kt @@ -0,0 +1,19 @@ +package com.kusitms.connectdog.feature.login.state + +import com.kusitms.connectdog.core.util.emptyString + +data class PasswordResetUiState( + val password: String, + val passwordCheck: String, + val isValidPassword: Boolean? +) { + companion object { + fun empty() = PasswordResetUiState( + password = emptyString(), + passwordCheck = emptyString(), + isValidPassword = null + ) + } +} + +sealed class PasswordResetSideEffect \ No newline at end of file diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/EmailAuthForPasswordResetViewModel.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/EmailAuthForPasswordResetViewModel.kt new file mode 100644 index 000000000..d54ae0436 --- /dev/null +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/EmailAuthForPasswordResetViewModel.kt @@ -0,0 +1,93 @@ +package com.kusitms.connectdog.feature.login.viewmodel + +import android.util.Patterns +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.domain.usecase.auth.EmailAuthForIntermediatorPasswordResetUseCase +import com.kusitms.connectdog.domain.usecase.auth.EmailAuthForVolunteerPasswordResetUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateAccessTokenUseCase +import com.kusitms.connectdog.feature.login.state.EmailAuthForPasswordResetSideEffect +import com.kusitms.connectdog.feature.login.state.EmailAuthForPasswordResetUiState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import org.orbitmvi.orbit.Container +import org.orbitmvi.orbit.ContainerHost +import org.orbitmvi.orbit.syntax.simple.intent +import org.orbitmvi.orbit.syntax.simple.postSideEffect +import org.orbitmvi.orbit.syntax.simple.reduce +import org.orbitmvi.orbit.viewmodel.container +import javax.inject.Inject + +@HiltViewModel +class EmailAuthForPasswordResetViewModel @Inject constructor( + private val emailAuthForVolunteerPasswordResetUseCase: EmailAuthForVolunteerPasswordResetUseCase, + private val emailAuthForIntermediatorPasswordResetUseCase: EmailAuthForIntermediatorPasswordResetUseCase, + private val updateAccessTokenUseCase: UpdateAccessTokenUseCase +) : ContainerHost, + ViewModel() { + override val container: Container = + container(EmailAuthForPasswordResetUiState.empty()) + private val state: EmailAuthForPasswordResetUiState + get() = container.stateFlow.value + + fun onEmailChanged(email: String) { + intent { reduce { state.copy(email = email) } } + checkValidEmail() + enableNextButton() + } + + fun onInputAuthCodeChanged(inputAuthCode: String) { + if (inputAuthCode.length <= 8) intent { reduce { state.copy(inputAuthCode = inputAuthCode) } } + enableNextButton() + } + + fun onNextButtonClick(userType: UserType) { + if(!state.isSendAuthCode) { + sendAuthCode(userType) + intent { reduce { state.copy(enableNext = false) } } + intent { reduce { state.copy(bottomButtonText = "인증 확인") } } + } else if(state.inputAuthCode != state.authCode){ + intent { reduce { state.copy(isAuthCodeError = true) } } + } else { + intent { postSideEffect(EmailAuthForPasswordResetSideEffect.NavigateToPasswordReset) } + } + } + + private fun sendAuthCode(userType: UserType) = when (userType) { + UserType.INTERMEDIATOR -> getIntermediatorEmailAuthCode() + else -> getVolunteerEmailAuthCode() + } + + private fun getVolunteerEmailAuthCode() = viewModelScope.launch { + emailAuthForVolunteerPasswordResetUseCase(state.email).onSuccess { + intent { reduce { state.copy(authCode = it.authCode, isSendAuthCode = true) } } + updateAccessTokenUseCase(it.accessToken) + }.onFailure { + intent { postSideEffect(EmailAuthForPasswordResetSideEffect.NavigateToFail) } + } + } + + private fun getIntermediatorEmailAuthCode() = viewModelScope.launch { + emailAuthForIntermediatorPasswordResetUseCase(state.email).onSuccess { + intent { reduce { state.copy(authCode = it.authCode, isSendAuthCode = true) } } + updateAccessTokenUseCase(it.accessToken) + }.onFailure { + intent { postSideEffect(EmailAuthForPasswordResetSideEffect.NavigateToFail) } + } + } + + private fun enableNextButton() = intent { + if (!state.isSendAuthCode && state.isValidEmail) { + reduce { state.copy(enableNext = true) } + } else if(state.isSendAuthCode && state.inputAuthCode.length == 8) { + reduce { state.copy(enableNext = true) } + } else { + reduce { state.copy(enableNext = false) } + } + } + + private fun checkValidEmail() = intent { + reduce { state.copy(isValidEmail = Patterns.EMAIL_ADDRESS.matcher(state.email).matches()) } + } +} diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/EmailSearchViewModel.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/EmailSearchViewModel.kt new file mode 100644 index 000000000..697c547e3 --- /dev/null +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/EmailSearchViewModel.kt @@ -0,0 +1,91 @@ +package com.kusitms.connectdog.feature.login.viewmodel + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.domain.usecase.auth.SearchIntermediatorEmailUseCase +import com.kusitms.connectdog.domain.usecase.auth.SearchVolunteerEmailUseCase +import com.kusitms.connectdog.feature.login.state.EmailSearchSideEffect +import com.kusitms.connectdog.feature.login.state.EmailSearchUiState +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import org.orbitmvi.orbit.Container +import org.orbitmvi.orbit.ContainerHost +import org.orbitmvi.orbit.syntax.simple.intent +import org.orbitmvi.orbit.syntax.simple.postSideEffect +import org.orbitmvi.orbit.syntax.simple.reduce +import org.orbitmvi.orbit.viewmodel.container +import javax.inject.Inject + +@HiltViewModel +class EmailSearchViewModel @Inject constructor( + private val searchVolunteerEmailUseCase: SearchVolunteerEmailUseCase, + private val searchIntermediatorEmailUseCase: SearchIntermediatorEmailUseCase +): ContainerHost, ViewModel() { + override val container: Container = container(EmailSearchUiState.empty()) + private val state: EmailSearchUiState + get() = container.stateFlow.value + + fun onPhoneNumberChanged(phoneNumber: String) = intent { + if (phoneNumber.length <= 11) reduce { state.copy(phoneNumber = phoneNumber) } + enableNextButton() + } + + fun onAuthCodeChanged(authCode: String) = intent { + if (authCode.length <= 6) reduce { state.copy(authCode = authCode) } + enableNextButton() + } + + private fun enableNextButton() = intent { + if(!state.isSendAuthCode && state.phoneNumber.length == 11) { + reduce { state.copy(enableNext = true) } + } else if(state.isSendAuthCode && state.authCode.length == 6) { + reduce { state.copy(enableNext = true) } + } else { + reduce { state.copy(enableNext = false) } + } + } + + fun onNextClick( + userType: UserType, + onSendMessageClick: (String) -> Unit, + onVerifyCodeClick: (String, (Boolean) -> Unit) -> Unit, + ) { + if(!state.isSendAuthCode) { + updateBottomButtonText() + onSendMessageClick(state.phoneNumber) + disableNextButton() + intent { reduce { state.copy(isSendAuthCode = true) } } + } else { + onVerifyCodeClick(state.authCode) { + if(it) intent { + when(userType) { + UserType.INTERMEDIATOR -> searchIntermediatorEmail() + else -> searchVolunteerEmail() + } + postSideEffect(EmailSearchSideEffect.NavigateToEmailSearchResult) + } + else intent { reduce { state.copy(isAuthCodeError = true) } } + } + } + } + + private fun updateBottomButtonText() = intent { reduce { state.copy(bottomButtonText = "인증 확인" ) } } + private fun disableNextButton() = intent { reduce { state.copy(enableNext = false) } } + + private fun searchIntermediatorEmail() = viewModelScope.launch { + searchIntermediatorEmailUseCase(state.phoneNumber).onSuccess { + intent { reduce { state.copy(email = it.email) } } + }.onFailure { + + } + } + + private fun searchVolunteerEmail() = viewModelScope.launch { + searchVolunteerEmailUseCase(state.phoneNumber).onSuccess { + intent { reduce { state.copy(email = it.email) } } + }.onFailure { + + } + } +} diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/LoginViewModel.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/LoginViewModel.kt index 78fe65816..f779fb737 100644 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/LoginViewModel.kt +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/LoginViewModel.kt @@ -1,207 +1,144 @@ package com.kusitms.connectdog.feature.login.viewmodel import android.content.Context -import android.util.Log -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.kakao.sdk.auth.model.OAuthToken import com.kakao.sdk.common.model.ClientError import com.kakao.sdk.common.model.ClientErrorCause import com.kakao.sdk.user.UserApiClient -import com.kusitms.connectdog.core.data.api.model.NormalLoginBody -import com.kusitms.connectdog.core.data.api.model.SocialLoginBody -import com.kusitms.connectdog.core.data.repository.DataStoreRepository -import com.kusitms.connectdog.core.data.repository.LoginRepository -import com.kusitms.connectdog.core.util.AppMode -import com.kusitms.connectdog.core.util.SocialType +import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.domain.usecase.login.AppMode +import com.kusitms.connectdog.domain.usecase.login.IntermediatorLoginUseCase +import com.kusitms.connectdog.domain.usecase.login.SocialLoginProvider +import com.kusitms.connectdog.domain.usecase.login.SocialLoginUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateAccessTokenUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateAppModeUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateRefreshTokenUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateSocialProviderUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateSocialTokenUseCase +import com.kusitms.connectdog.domain.usecase.login.VolunteerLoginUseCase +import com.kusitms.connectdog.feature.login.BuildConfig +import com.kusitms.connectdog.feature.login.state.LoginSideEffect +import com.kusitms.connectdog.feature.login.state.LoginUiState import com.navercorp.nid.NaverIdLoginSDK import com.navercorp.nid.oauth.NidOAuthLogin import com.navercorp.nid.oauth.OAuthLoginCallback import com.navercorp.nid.profile.NidProfileCallback import com.navercorp.nid.profile.data.NidProfileResponse import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch +import org.orbitmvi.orbit.Container +import org.orbitmvi.orbit.ContainerHost +import org.orbitmvi.orbit.syntax.simple.intent +import org.orbitmvi.orbit.syntax.simple.postSideEffect +import org.orbitmvi.orbit.syntax.simple.reduce +import org.orbitmvi.orbit.viewmodel.container import javax.inject.Inject -enum class Provider { - KAKAO, NAVER -} - -private const val TAG = "LoginViewModel" - @HiltViewModel class LoginViewModel @Inject constructor( - private val loginRepository: LoginRepository, - private val dataStoreRepository: DataStoreRepository -) : ViewModel() { - private val _isLoginSuccessful: MutableStateFlow = MutableStateFlow(null) - val isLoginSuccessful: StateFlow - get() = _isLoginSuccessful - - private val _socialType: MutableStateFlow = MutableStateFlow(null) - val socialType: StateFlow - get() = _socialType - - private val _email: MutableState = mutableStateOf("") - val email: String - get() = _email.value - - private val _password: MutableState = mutableStateOf("") - val password: String - get() = _password.value - - private val _accessToken: MutableStateFlow = MutableStateFlow(null) - - fun updateEmail(email: String) { - _email.value = email - } - - fun updatePassword(password: String) { - _password.value = password - } - - fun initVolunteerLogin() { - val body = NormalLoginBody(_email.value, _password.value) - viewModelScope.launch { - try { - val response = loginRepository.postLoginData(body) - dataStoreRepository.saveAccessToken(response.accessToken) - dataStoreRepository.saveRefreshToken(response.refreshToken) - dataStoreRepository.saveAppMode(AppMode.VOLUNTEER) - _isLoginSuccessful.value = true - Log.d(TAG, isLoginSuccessful.toString()) - Log.d(TAG, dataStoreRepository.accessTokenFlow.first().toString()) - } catch (e: Exception) { - _isLoginSuccessful.value = false - Log.d(TAG, e.message.toString()) + private val volunteerLoginUseCase: VolunteerLoginUseCase, + private val intermediatorLoginUseCase: IntermediatorLoginUseCase, + private val socialLoginUseCase: SocialLoginUseCase, + private val updateAccessTokenUseCase: UpdateAccessTokenUseCase, + private val updateRefreshTokenUseCase: UpdateRefreshTokenUseCase, + private val updateAppModeUseCase: UpdateAppModeUseCase, + private val updateSocialTokenUseCase: UpdateSocialTokenUseCase, + private val updateSocialProviderUseCase: UpdateSocialProviderUseCase, +) : ContainerHost, ViewModel() { + override val container: Container = container(LoginUiState.empty()) + private val state: LoginUiState + get() = container.stateFlow.value + + fun onEmailChanged(email: String) = intent { reduce { state.copy(email = email) } } + fun onPasswordChanged(password: String) = intent { reduce { state.copy(password = password) } } + + fun initVolunteerLogin() = viewModelScope.launch { + volunteerLoginUseCase( + email = state.email, + password = state.password + ).onSuccess { + updateAccessTokenUseCase(it.accessToken) + updateRefreshTokenUseCase(it.refreshToken) + updateAppModeUseCase(AppMode.VOLUNTEER) + intent { + reduce { state.copy(isLoginSuccessful = true) } + postSideEffect(LoginSideEffect.NavigateToHome) } + }.onFailure { + intent { reduce { state.copy(isLoginSuccessful = false) } } } } - fun initIntermediatorLogin() { - val body = NormalLoginBody(_email.value, _password.value) - viewModelScope.launch { - try { - val response = loginRepository.postIntermediatorLoginData(body) - _isLoginSuccessful.value = true - dataStoreRepository.saveAccessToken(response.accessToken) - dataStoreRepository.saveRefreshToken(response.refreshToken) - dataStoreRepository.saveAppMode(AppMode.INTERMEDIATOR) - } catch (e: Exception) { - _isLoginSuccessful.value = false - Log.d(TAG, e.message.toString()) + fun initIntermediatorLogin() = viewModelScope.launch { + intermediatorLoginUseCase( + email = state.email, + password = state.password + ).onSuccess { + intent { + reduce { state.copy(isLoginSuccessful = true) } + postSideEffect(LoginSideEffect.NavigateToHome) } + updateAccessTokenUseCase(it.accessToken) + updateRefreshTokenUseCase(it.refreshToken) + updateAppModeUseCase(AppMode.INTERMEDIATOR) + }.onFailure { + intent { reduce { state.copy(isLoginSuccessful = false) } } } } - fun initSocialLogin(provider: Provider, context: Context) { - when (provider) { - Provider.NAVER -> initNaverLogin(context) - Provider.KAKAO -> initKakaoLogin(context) - } - - viewModelScope.launch { - try { - _accessToken.collect { - if (it == null) return@collect - val body = SocialLoginBody(accessToken = it, provider = provider.toString()) - val response = loginRepository.postSocialLoginData(body) - dataStoreRepository.saveAccessToken(response.accessToken) - dataStoreRepository.saveRefreshToken(response.refreshToken) - dataStoreRepository.saveSocialToken(it) - dataStoreRepository.saveSocialProvider(provider.toString()) - when (response.roleName) { - "GUEST" -> _socialType.emit(SocialType.GUEST) - "AUTH_VOLUNTEER" -> { - _socialType.emit(SocialType.VOLUNTEER) - dataStoreRepository.saveAppMode(AppMode.VOLUNTEER) - } - } - Log.d(TAG, response.toString()) + private fun initSocialLogin(provider: SocialLoginProvider, token: String) = viewModelScope.launch { + socialLoginUseCase( + accessToken = token, + provider = provider.toString() + ).onSuccess { + updateAccessTokenUseCase(it.accessToken) + updateRefreshTokenUseCase(it.refreshToken) + when(it.roleName) { + "GUEST" -> intent { postSideEffect(LoginSideEffect.NavigateToSignUp(UserType.SOCIAL_VOLUNTEER)) } + "AUTH_VOLUNTEER" -> { + intent { postSideEffect(LoginSideEffect.NavigateToHome) } + updateAppModeUseCase(AppMode.VOLUNTEER) } - } catch (e: Exception) { - Log.d(TAG, e.message.toString()) } } } - private fun initNaverLogin(context: Context) { - NaverIdLoginSDK.initialize(context, "rWBuAHxm0vihdivNGAZI", "8Sfw75g883", "connectdog") - NaverIdLoginSDK.authenticate(context, naverLoginCallback) - } - private val naverLoginCallback = object : OAuthLoginCallback { override fun onSuccess() { NidOAuthLogin().callProfileApi(object : NidProfileCallback { override fun onSuccess(result: NidProfileResponse) { - Log.d("tszq", "succesa") - _accessToken.value = NaverIdLoginSDK.getAccessToken().toString() - } - - override fun onError(errorCode: Int, message: String) { - Log.e("login", message) + initSocialLogin(SocialLoginProvider.NAVER, NaverIdLoginSDK.getAccessToken().toString()) } - override fun onFailure(httpStatus: Int, message: String) { - Log.e("login", message) - } + override fun onError(errorCode: Int, message: String) {} + override fun onFailure(httpStatus: Int, message: String) {} }) } + override fun onError(errorCode: Int, message: String) {} + override fun onFailure(httpStatus: Int, message: String) {} + } - override fun onError(errorCode: Int, message: String) { - Log.e("login", message) - } - - override fun onFailure(httpStatus: Int, message: String) { - Log.e("login", message) + private val kakaoLoginCallback: (OAuthToken?, Throwable?) -> Unit = { token, error -> + if (token != null && error != null) { + initSocialLogin(SocialLoginProvider.KAKAO, token.accessToken) } } - private fun initKakaoLogin(context: Context) { - val kakaoLoginCallback: (OAuthToken?, Throwable?) -> Unit = { token, error -> - if (error != null) { - Log.e("Kakao Login", "카카오계정으로 로그인 실패", error) - } else if (token != null) { - Log.i("Kakao Login", "카카오계정으로 로그인 성공 ${token.accessToken}") - _accessToken.value = token.accessToken - - UserApiClient.instance.me { user, error -> - if (error != null) { - Log.e("Kakao Login", "사용자 정보 요청 실패", error) - } else if (user != null) { - } - } - } - } + fun initNaverLogin(context: Context) { + NaverIdLoginSDK.initialize(context, BuildConfig.NAVER_CLIENT_ID, BuildConfig.NAVER_CLIENT_SECRET, "connectdog") + NaverIdLoginSDK.authenticate(context, naverLoginCallback) + } + fun initKakaoLogin(context: Context) { if (UserApiClient.instance.isKakaoTalkLoginAvailable(context)) { UserApiClient.instance.loginWithKakaoTalk(context) { token, error -> - if (error != null) { - Log.e("Kakao Login", "카카오톡으로 로그인 실패", error) - - if (error is ClientError && error.reason == ClientErrorCause.Cancelled) { - return@loginWithKakaoTalk - } - - UserApiClient.instance.loginWithKakaoAccount( - context, - callback = kakaoLoginCallback - ) - } else if (token != null) { - Log.i("Kakao Login", "카카오 로그인 성공 ${token.accessToken}") - _accessToken.value = token.accessToken - - UserApiClient.instance.me { user, error -> - if (error != null) { - Log.e("Kakao Login", "사용자 정보 요청 실패", error) - } else if (user != null) { - } - } + if (error != null && token != null) { + initSocialLogin(SocialLoginProvider.KAKAO, token.accessToken) + } else if (error is ClientError && error.reason == ClientErrorCause.Cancelled) { + UserApiClient.instance.loginWithKakaoAccount(context, callback = kakaoLoginCallback) + return@loginWithKakaoTalk } } } else { diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordSearchViewModel.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordResetViewModel.kt similarity index 77% rename from feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordSearchViewModel.kt rename to feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordResetViewModel.kt index 844d9cd9b..8576e5690 100644 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordSearchViewModel.kt +++ b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordResetViewModel.kt @@ -5,16 +5,25 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.kusitms.connectdog.core.data.repository.SignUpRepository import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.feature.login.state.PasswordResetSideEffect +import com.kusitms.connectdog.feature.login.state.PasswordResetUiState import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch +import org.orbitmvi.orbit.Container +import org.orbitmvi.orbit.ContainerHost +import org.orbitmvi.orbit.viewmodel.container import javax.inject.Inject @HiltViewModel -class PasswordSearchViewModel @Inject constructor( +class PasswordResetViewModel @Inject constructor( private val repository: SignUpRepository -) : ViewModel() { +): ContainerHost, ViewModel() { + override val container: Container = container(PasswordResetUiState.empty()) + private val state: PasswordResetUiState + get() = container.stateFlow.value + private var _password = mutableStateOf("") val password: String get() = _password.value diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordSearchAuthViewModel.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordSearchAuthViewModel.kt deleted file mode 100644 index 2fa5528b9..000000000 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/PasswordSearchAuthViewModel.kt +++ /dev/null @@ -1,105 +0,0 @@ -package com.kusitms.connectdog.feature.login.viewmodel - -import android.content.Context -import android.widget.Toast -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.kusitms.connectdog.core.data.repository.DataStoreRepository -import com.kusitms.connectdog.core.data.repository.LoginRepository -import com.kusitms.connectdog.core.util.UserType -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch -import javax.inject.Inject - -@HiltViewModel -class PasswordSearchAuthViewModel @Inject constructor( - private val repository: LoginRepository, - private val dataStoreRepository: DataStoreRepository -) : ViewModel() { - private var postNumber: String = "" - - private val _isEmailVerified: MutableStateFlow = MutableStateFlow(null) - val isEmailVerified: StateFlow - get() = _isEmailVerified - - private val _isEmailError: MutableStateFlow = MutableStateFlow(null) - val isEmailError: StateFlow - get() = _isEmailError - - private val _isValidEmail: MutableStateFlow = MutableStateFlow(null) - val isValidEmail: StateFlow - get() = _isValidEmail - - private val _email: MutableState = mutableStateOf("") - val email: String - get() = _email.value - - private val _certificationNumber: MutableState = mutableStateOf("") - val certificationNumber: String - get() = _certificationNumber.value - - private val accessToken = MutableStateFlow(null) - - fun updateEmail(email: String) { - _email.value = email - } - - fun updateCertificationNumber(certificationNumber: String) { - _certificationNumber.value = certificationNumber - } - - fun updateEmailValidity() { - _isValidEmail.value = !android.util.Patterns.EMAIL_ADDRESS.matcher(_email.value).matches() - } - - fun updateEmailVerify(value: Boolean) { - _isEmailVerified.value = value - } - - fun postEmail(context: Context, userType: UserType) = viewModelScope.launch { - if (_email.value.isEmpty()) { - Toast.makeText(context, "이메일을 입력해주세요", Toast.LENGTH_SHORT).show() - return@launch - } - if (isValidEmail.value == true) { - Toast.makeText(context, "유효한 이메일을 입력해주세요", Toast.LENGTH_SHORT).show() - return@launch - } - - try { - val response = when (userType) { - UserType.INTERMEDIATOR -> repository.interPasswordSearchAuth(_email.value) - else -> repository.volunteerPasswordSearchAuth(_email.value) - } - Toast.makeText(context, "이메일을 전송했습니다", Toast.LENGTH_SHORT).show() - _isEmailError.value = false - postNumber = response.authCode - accessToken.value = response.accessToken - } catch (e: Exception) { - val text = when (userType) { - UserType.INTERMEDIATOR -> "해당 이동봉사 모집자를 찾을 수 없습니다." - else -> "해당 봉사자를 찾을 수 없습니다." - } - _isEmailError.value = true - Toast.makeText(context, text, Toast.LENGTH_SHORT).show() - } - } - - fun checkCertificationNumber(context: Context) = viewModelScope.launch { - if (_certificationNumber.value.isEmpty()) { - Toast.makeText(context, "인증번호를 입력해주세요", Toast.LENGTH_SHORT).show() - } else { - _isEmailVerified.value = _certificationNumber.value == postNumber - if (_isEmailVerified.value == true) { - accessToken.value?.let { dataStoreRepository.saveAccessToken(it) } - Toast.makeText(context, "인증이 완료되었습니다", Toast.LENGTH_SHORT).show() - } else if (_isEmailVerified.value == false) { - Toast.makeText(context, "인증에 실패하였습니다", Toast.LENGTH_SHORT).show() - } - } - } -} diff --git a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/SearchViewModel.kt b/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/SearchViewModel.kt deleted file mode 100644 index 10fef30ae..000000000 --- a/feature/login/src/main/java/com/kusitms/connectdog/feature/login/viewmodel/SearchViewModel.kt +++ /dev/null @@ -1,77 +0,0 @@ -package com.kusitms.connectdog.feature.login.viewmodel - -import android.content.Context -import android.widget.Toast -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.kusitms.connectdog.core.data.repository.LoginRepository -import com.kusitms.connectdog.core.util.UserType -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch -import javax.inject.Inject - -@HiltViewModel -class SearchViewModel @Inject constructor( - private val repository: LoginRepository -) : ViewModel() { - private val _phoneNumber: MutableState = mutableStateOf("") - val phoneNumber: String - get() = _phoneNumber.value - - private val _certificationNumber: MutableState = mutableStateOf("") - val certificationNumber: String - get() = _certificationNumber.value - - private val _isSendNumber: MutableStateFlow = MutableStateFlow(false) - val isSendNumber: StateFlow = _isSendNumber - - private val _isCertified: MutableStateFlow = MutableStateFlow(false) - val isCertified: StateFlow = _isCertified - - private val _findEmail = MutableStateFlow(null) - val findEmail: StateFlow - get() = _findEmail - - fun updateCertificationNumber(value: String) { - _certificationNumber.value = value - } - - fun updatePhoneNumber(value: String) { - _phoneNumber.value = value - } - - fun updateIsSendNumber(value: Boolean) { - _isSendNumber.value = value - } - - fun updateIsCertified(isCertified: Boolean) { - _isCertified.value = isCertified - } - - fun test(userType: UserType, context: Context) = viewModelScope.launch { - try { - when (userType) { - UserType.INTERMEDIATOR -> { - val response = repository.interEmailSearch(_phoneNumber.value) - _findEmail.value = response.email - } - - UserType.NORMAL_VOLUNTEER -> { - val response = repository.volunteerEmailSearch(_phoneNumber.value) - _findEmail.value = response.email - } - - else -> {} - } - } catch (e: Exception) { - when (userType) { - UserType.INTERMEDIATOR -> Toast.makeText(context, "해당 해당 이동봉사 모집자를 찾을 수 없습니다.", Toast.LENGTH_SHORT).show() - else -> Toast.makeText(context, "해당 이동봉사자를 찾을 수 없습니다.", Toast.LENGTH_SHORT).show() - } - } - } -} diff --git a/feature/login/src/main/res/values/strings.xml b/feature/login/src/main/res/values/strings.xml index f3431d9a3..ee1f3361c 100644 --- a/feature/login/src/main/res/values/strings.xml +++ b/feature/login/src/main/res/values/strings.xml @@ -1,5 +1,14 @@ + 이메일 + 비밀번호 + + 이메일 입력 + 비밀번호 입력 + + 이메일로 회원가입 + 이메일 로그인\ + 네이버로 3초 만에 시작하기 카카오로 3초 만에 시작하기 코넥독 계정으로 회원가입하기 @@ -10,4 +19,13 @@ 비밀번호 찾기 로그인에 사용할\n비밀번호를 입력해 주세요 + + + 이메일 인증을\n진행해주세요 + 휴대폰 번호 + + + + 입력하신 번호로 가입한 계정이\n존재하지 않습니다 + 정보가 일치하는 계정이 존재하지 않습니다. \ No newline at end of file diff --git a/feature/main/build.gradle.kts b/feature/main/build.gradle.kts index d46d2787b..85412dd83 100644 --- a/feature/main/build.gradle.kts +++ b/feature/main/build.gradle.kts @@ -37,7 +37,6 @@ android { kotlinOptions { jvmTarget = "17" } - buildFeatures { compose = true } @@ -47,7 +46,7 @@ android { } dependencies { - + implementation(projects.domain) // Navigation을 위해 모든 feature 의존성 추가 필요 implementation(project(":feature:login")) implementation(project(":feature:signup")) @@ -90,9 +89,9 @@ dependencies { implementation(libs.androidx.compose.material3) implementation(libs.kotlinx.collection.imuutable) - - // test - implementation(libs.androidx.junit.ktx) + implementation(libs.orbit.core) + implementation(libs.orbit.compose) + implementation(libs.orbit.viewmodel) } kapt { diff --git a/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainActivity.kt b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainActivity.kt index 5521e4aeb..713cccabb 100644 --- a/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainActivity.kt +++ b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainActivity.kt @@ -31,20 +31,14 @@ import com.google.firebase.auth.PhoneAuthCredential import com.google.firebase.auth.PhoneAuthOptions import com.google.firebase.auth.PhoneAuthProvider import com.google.firebase.messaging.FirebaseMessaging -import com.kusitms.connectdog.core.data.repository.DataStoreRepository import com.kusitms.connectdog.core.designsystem.theme.ConnectDogTheme +import com.kusitms.connectdog.domain.usecase.login.AppMode import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import org.orbitmvi.orbit.compose.collectAsState import java.util.concurrent.TimeUnit -import javax.inject.Inject @AndroidEntryPoint class MainActivity : ComponentActivity() { - @Inject - lateinit var dataStore: DataStoreRepository private lateinit var auth: FirebaseAuth private lateinit var verificationId: String private var imeHeight by mutableIntStateOf(0) @@ -60,11 +54,10 @@ class MainActivity : ComponentActivity() { installSplashScreen() imeListener() - lifecycleScope.launch { - val appMode = withContext(Dispatchers.IO) { - dataStore.appModeFlow.first() - } - setContent { + + setContent { + val uiState by viewModel.collectAsState() + uiState.appMode?.let { appMode -> val navigator: MainNavigator = rememberMainNavigator(mode = appMode) ConnectDogTheme { MainScreen( @@ -137,7 +130,6 @@ class MainActivity : ComponentActivity() { val updatedHeight = if (imeHeight - sysBarInsets.bottom < 0) 0 else imeHeight - sysBarInsets.bottom - Log.d("saqa", updatedHeight.toString()) return insets } } diff --git a/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainNavigator.kt b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainNavigator.kt index 7552e6709..049b5de21 100644 --- a/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainNavigator.kt +++ b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainNavigator.kt @@ -8,8 +8,9 @@ import androidx.navigation.NavHostController import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navOptions -import com.kusitms.connectdog.core.util.AppMode +import com.kusitms.connectdog.core.util.AccountType import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.domain.usecase.login.AppMode import com.kusitms.connectdog.feature.home.model.Filter import com.kusitms.connectdog.feature.home.navigation.HomeRoute import com.kusitms.connectdog.feature.home.navigation.navigateApply @@ -32,13 +33,14 @@ import com.kusitms.connectdog.feature.intermediator.navigation.navigateToCreateA import com.kusitms.connectdog.feature.intermediator.navigation.navigateToCreateComplete import com.kusitms.connectdog.feature.intermediator.navigation.navigateToCreateDog import com.kusitms.connectdog.feature.intermediator.navigation.navigateToInterProfileEdit -import com.kusitms.connectdog.feature.login.LoginRoute -import com.kusitms.connectdog.feature.login.navigateEmailSearch -import com.kusitms.connectdog.feature.login.navigateEmailSearchComplete -import com.kusitms.connectdog.feature.login.navigateNormalLogin -import com.kusitms.connectdog.feature.login.navigatePasswordSearch -import com.kusitms.connectdog.feature.login.navigatePasswordSearchAuth -import com.kusitms.connectdog.feature.login.navigateToLoginRoute +import com.kusitms.connectdog.feature.login.navigation.LoginRoute +import com.kusitms.connectdog.feature.login.navigation.navigateEmailSearch +import com.kusitms.connectdog.feature.login.navigation.navigateEmailSearchComplete +import com.kusitms.connectdog.feature.login.navigation.navigateNormalLogin +import com.kusitms.connectdog.feature.login.navigation.navigatePasswordSearch +import com.kusitms.connectdog.feature.login.navigation.navigatePasswordSearchAuth +import com.kusitms.connectdog.feature.login.navigation.navigateToLoginRoute +import com.kusitms.connectdog.feature.login.navigation.navigateToNoAccount import com.kusitms.connectdog.feature.management.navigation.navigateCheckReview import com.kusitms.connectdog.feature.management.navigation.navigateCreateReview import com.kusitms.connectdog.feature.management.navigation.navigateManagement @@ -71,7 +73,7 @@ internal class MainNavigator( val startDestination = when (mode) { AppMode.VOLUNTEER -> MainTab.HOME.route AppMode.INTERMEDIATOR -> IntermediatorRoute.route - AppMode.LOGIN -> LoginRoute.route + AppMode.LOGIN -> LoginRoute.ROUTE } val currentTab: MainTab? @@ -106,16 +108,17 @@ internal class MainNavigator( fun navigatePasswordSearchAuth(userType: UserType) = navController.navigatePasswordSearchAuth(userType) fun onLogoutClick() = navController.navigateToLoginRoute() fun navigatePasswordSearch(userType: UserType) = navController.navigatePasswordSearch(userType) + fun navigateNoAccount(accountType: AccountType) = navController.navigateToNoAccount(accountType) // signup navigator - fun navigateVolunteerProfile(userType: UserType) = navController.navigateToVolunteerProfile(userType) + fun navigateVolunteerProfile() = navController.navigateToVolunteerProfile() fun navigateIntermediatorProfile() = navController.navigateToIntermediatorProfile() - fun navigateRegisterEmail(userType: UserType) = navController.navigateRegisterEmail(userType) - fun navigateRegisterPassword(userType: UserType) = navController.navigateRegisterPassword(userType) + fun navigateRegisterEmail() = navController.navigateRegisterEmail() + fun navigateRegisterPassword() = navController.navigateRegisterPassword() fun navigateSelectProfileImage() = navController.navigateSelectProfileImage() - fun navigateCompleteSignUp(userType: UserType) = navController.navigateCompleteSignUp(userType) + fun navigateCompleteSignUp() = navController.navigateCompleteSignUp() fun navigateIntermediatorInformation() = navController.navigateIntermediatorInformation() - fun navigateCertification(userType: UserType) = navController.navigateToCertification(userType) + fun navigateCertification() = navController.navigateToCertification() // volunteer navigator fun navigateHome() = navigate(MainTab.HOME) @@ -176,7 +179,4 @@ internal class MainNavigator( internal fun rememberMainNavigator( navController: NavHostController = rememberNavController(), mode: AppMode -): MainNavigator = - remember(navController) { - MainNavigator(navController, mode) - } +): MainNavigator = remember(navController) { MainNavigator(navController, mode) } diff --git a/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainScreen.kt b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainScreen.kt index 214a250c5..5a821f94c 100644 --- a/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainScreen.kt +++ b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainScreen.kt @@ -1,6 +1,8 @@ package com.kusitms.connectdog.feature.main import android.net.Uri +import android.os.Build +import androidx.annotation.RequiresApi import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut @@ -12,7 +14,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.size -import androidx.compose.material3.Divider +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.NavigationBar @@ -31,20 +33,19 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.compose.NavHost import com.google.gson.Gson import com.kusitms.connectdog.core.designsystem.theme.ConnectDogTheme -import com.kusitms.connectdog.core.util.AppMode import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.domain.usecase.login.AppMode import com.kusitms.connectdog.feature.home.navigation.homeNavGraph import com.kusitms.connectdog.feature.intermediator.navigation.intermediatorNavGraph import com.kusitms.connectdog.feature.intermediator.viewmodel.CreateApplicationViewModel -import com.kusitms.connectdog.feature.login.loginNavGraph +import com.kusitms.connectdog.feature.login.navigation.loginNavGraph import com.kusitms.connectdog.feature.management.navigation.managementNavGraph import com.kusitms.connectdog.feature.mypage.navigation.mypageNavGraph import com.kusitms.connectdog.feature.mypage.viewmodel.EditProfileViewModel import com.kusitms.connectdog.signup.navigation.signUpGraph -import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel -import com.kusitms.connectdog.signup.viewmodel.VolunteerProfileViewModel import kotlinx.collections.immutable.toPersistentList +@RequiresApi(Build.VERSION_CODES.TIRAMISU) @Composable internal fun MainScreen( mode: AppMode, @@ -55,18 +56,18 @@ internal fun MainScreen( openWebBrowser: (String) -> Unit, imeHeight: Int ) { - val profileViewModel: VolunteerProfileViewModel = hiltViewModel() - val signUpViewModel: SignUpViewModel = hiltViewModel() val editProfileViewModel: EditProfileViewModel = hiltViewModel() val createApplicationViewModel: CreateApplicationViewModel = hiltViewModel() Scaffold( content = { Box( - modifier = - Modifier + modifier = Modifier .fillMaxSize() - .background(MaterialTheme.colorScheme.onPrimary, shape = RectangleShape) + .background( + color = MaterialTheme.colorScheme.onPrimary, + shape = RectangleShape + ) ) { NavHost( navController = navigator.navController, @@ -86,23 +87,23 @@ internal fun MainScreen( onNavigateToPasswordSearchAuth = navigator::navigatePasswordSearchAuth, onSendMessage = { sendVerificationCode(it) }, onVerifyCode = { code, callback -> verifyCode(code) { callback(it) } }, - onNavigateToLoginRoute = navigator::onLogoutClick + onNavigateToLoginRoute = navigator::onLogoutClick, + onNavigateToNoAccount = navigator::navigateNoAccount ) signUpGraph( + navController = navigator.navController, onBackClick = navigator::popBackStackIfNotHome, - navigateToVolunteerProfile = { navigator.navigateVolunteerProfile(it) }, - navigateToIntermediatorInformation = { navigator.navigateIntermediatorInformation() }, - navigateToIntermediatorProfile = { navigator.navigateIntermediatorProfile() }, - navigateToRegisterEmail = { navigator.navigateRegisterEmail(it) }, - navigateToRegisterPassword = { navigator.navigateRegisterPassword(it) }, + navigateToVolunteerProfile = navigator::navigateVolunteerProfile, + navigateToIntermediatorInformation = navigator::navigateIntermediatorInformation, + navigateToIntermediatorProfile = navigator::navigateIntermediatorProfile, + navigateToRegisterEmail = navigator::navigateRegisterEmail, + navigateToRegisterPassword = navigator::navigateRegisterPassword, navigateToSelectProfileImage = { navigator.navigateSelectProfileImage() }, - navigateToCompleteSignUp = { navigator.navigateCompleteSignUp(it) }, - navigateToVolunteer = { navigator.navigateHome() }, - navigateToIntermediator = { navigator.navigateIntermediatorHome() }, + navigateToCompleteSignUp = navigator::navigateCompleteSignUp, + navigateToVolunteerHome = navigator::navigateHome, + navigateToIntermediatorHome = navigator::navigateIntermediatorHome, imeHeight = imeHeight, - signUpViewModel = signUpViewModel, - profileViewModel = profileViewModel, - navigateToCertification = { navigator.navigateCertification(it) }, + navigateToCertification = navigator::navigateCertification, onSendMessage = { sendVerificationCode(it) }, onVerifyCode = { code, callback -> verifyCode(code) { callback(it) } }, navigateToLogin = { navigator.onLogoutClick() }, @@ -190,7 +191,7 @@ internal fun MainScreen( Column( modifier = Modifier.height(68.dp) ) { - Divider(thickness = 1.dp, color = MaterialTheme.colorScheme.outline) + HorizontalDivider(thickness = 1.dp, color = MaterialTheme.colorScheme.outline) NavigationBar( containerColor = Color.Transparent, modifier = Modifier.background(Color.White) @@ -226,15 +227,10 @@ private fun NavigationIcon( selected: Boolean ) { Icon( + modifier = Modifier.size(24.dp), painter = painterResource(id = tab.iconResId), contentDescription = tab.contentDescription, - tint = - if (selected) { - MaterialTheme.colorScheme.primary - } else { - MaterialTheme.colorScheme.onSurface - }, - modifier = Modifier.size(24.dp) + tint = if (selected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurface, ) } diff --git a/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainUiState.kt b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainUiState.kt new file mode 100644 index 000000000..e679dc58d --- /dev/null +++ b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainUiState.kt @@ -0,0 +1,15 @@ +package com.kusitms.connectdog.feature.main + +import com.kusitms.connectdog.domain.usecase.login.AppMode + +data class MainUiState( + val appMode: AppMode? +) { + companion object { + fun empty() = MainUiState( + appMode = null + ) + } +} + +sealed class MainSideEffect \ No newline at end of file diff --git a/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainViewModel.kt b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainViewModel.kt index d1e8351fa..e4d69f3bc 100644 --- a/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainViewModel.kt +++ b/feature/main/src/main/java/com/kusitms/connectdog/feature/main/MainViewModel.kt @@ -1,19 +1,42 @@ package com.kusitms.connectdog.feature.main +import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.kusitms.connectdog.core.data.repository.DataStoreRepository +import com.kusitms.connectdog.domain.usecase.GetAppModeUseCase +import com.kusitms.connectdog.domain.usecase.UpdateFcmTokenUseCase +import com.kusitms.connectdog.feature.login.state.LoginSideEffect +import com.kusitms.connectdog.feature.login.state.LoginUiState import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch +import org.orbitmvi.orbit.Container +import org.orbitmvi.orbit.ContainerHost +import org.orbitmvi.orbit.syntax.simple.intent +import org.orbitmvi.orbit.syntax.simple.reduce +import org.orbitmvi.orbit.viewmodel.container import javax.inject.Inject private const val TAG = "MAIN_VIEWMODEL" @HiltViewModel class MainViewModel @Inject constructor( - private val dataStoreRepository: DataStoreRepository -) : ViewModel() { + private val updateFcmTokenUseCase: UpdateFcmTokenUseCase, + private val getAppModeUseCase: GetAppModeUseCase +): ContainerHost, ViewModel() { + override val container: Container = container(MainUiState.empty()) + + init { + initAppMode() + } + + private fun initAppMode() = viewModelScope.launch { + getAppModeUseCase().collect { appMode -> + intent { reduce { state.copy(appMode = appMode) } } + } + } + fun updateFcmToken(token: String) = viewModelScope.launch { - dataStoreRepository.saveFcmToken(token) + updateFcmTokenUseCase(token) } } diff --git a/feature/mypage/build.gradle.kts b/feature/mypage/build.gradle.kts index 364c30bdf..c364cc3f6 100644 --- a/feature/mypage/build.gradle.kts +++ b/feature/mypage/build.gradle.kts @@ -46,7 +46,7 @@ android { } dependencies { - + implementation(projects.domain) implementation(project(":core:model")) implementation(project(":core:data")) implementation(project(":core:designsystem")) diff --git a/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/EditProfileViewModel.kt b/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/EditProfileViewModel.kt index 8418a79b3..9f7e1ee22 100644 --- a/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/EditProfileViewModel.kt +++ b/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/EditProfileViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.viewModelScope import com.kusitms.connectdog.core.data.api.model.volunteer.IsDuplicateNicknameBody import com.kusitms.connectdog.core.data.api.model.volunteer.UserInfoResponse import com.kusitms.connectdog.core.data.repository.MyPageRepository +import com.kusitms.connectdog.core.model.signup.Nickname import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -42,7 +43,7 @@ class EditProfileViewModel @Inject constructor( } fun updateNicknameAvailability() { - val body = IsDuplicateNicknameBody(nickname = _nickname.value) + val body = Nickname(nickname = _nickname.value) viewModelScope.launch { try { val response = myPageRepository.postNickname(body) diff --git a/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/PasswordChangeViewModel.kt b/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/PasswordChangeViewModel.kt index c85727544..8ed0e7745 100644 --- a/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/PasswordChangeViewModel.kt +++ b/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/PasswordChangeViewModel.kt @@ -4,9 +4,9 @@ import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.kusitms.connectdog.core.data.repository.DataStoreRepository import com.kusitms.connectdog.core.data.repository.SignUpRepository import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.domain.usecase.login.DeleteAccessTokenUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -16,7 +16,7 @@ import javax.inject.Inject @HiltViewModel class PasswordChangeViewModel @Inject constructor( private val repository: SignUpRepository, - private val dataStoreRepository: DataStoreRepository + private val deleteAccessTokenUseCase: DeleteAccessTokenUseCase ) : ViewModel() { private val _previousPassword: MutableState = mutableStateOf("") val previousPassword: String @@ -71,7 +71,7 @@ class PasswordChangeViewModel @Inject constructor( UserType.INTERMEDIATOR -> repository.changeInterPassword(_newPassword.value) else -> repository.changeVolunteerPassword(_newPassword.value) } - dataStoreRepository.deleteAccessToken() + deleteAccessTokenUseCase() } catch (e: Exception) { } } diff --git a/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/SettingViewModel.kt b/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/SettingViewModel.kt index 5d3e6ad9c..f0d938fdb 100644 --- a/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/SettingViewModel.kt +++ b/feature/mypage/src/main/java/com/kusitms/connectdog/feature/mypage/viewmodel/SettingViewModel.kt @@ -3,12 +3,13 @@ package com.kusitms.connectdog.feature.mypage.viewmodel import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.kusitms.connectdog.core.data.repository.DataStoreRepository import com.kusitms.connectdog.core.data.repository.InterManagementRepository -import com.kusitms.connectdog.core.data.repository.LoginRepository import com.kusitms.connectdog.core.data.repository.MyPageRepository -import com.kusitms.connectdog.core.util.AppMode import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.domain.usecase.login.AppMode +import com.kusitms.connectdog.domain.usecase.login.DeleteAccessTokenUseCase +import com.kusitms.connectdog.domain.usecase.login.LogoutUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateAppModeUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow @@ -19,33 +20,30 @@ private const val TAG = "MyPageViewModel" @HiltViewModel class SettingViewModel @Inject constructor( - private val dataStoreRepository: DataStoreRepository, private val myPageRepository: MyPageRepository, - private val loginRepository: LoginRepository, - private val interRepository: InterManagementRepository + private val interRepository: InterManagementRepository, + private val updateAppModeUseCase: UpdateAppModeUseCase, + private val deleteAccessTokenUseCase: DeleteAccessTokenUseCase, + private val logoutUseCase: LogoutUseCase ) : ViewModel() { private val _isAbleWithdraw = MutableSharedFlow() val isAbleWithdraw: SharedFlow get() = _isAbleWithdraw fun initLogout() = viewModelScope.launch { - try { - dataStoreRepository.saveAppMode(AppMode.LOGIN) - loginRepository.logout() - dataStoreRepository.deleteAccessToken() - } catch (e: Exception) { - Log.d(TAG, e.message.toString()) - } + updateAppModeUseCase(AppMode.LOGIN) + deleteAccessTokenUseCase() + logoutUseCase() } fun deleteAccount(userType: UserType) = viewModelScope.launch { try { - dataStoreRepository.saveAppMode(AppMode.LOGIN) + updateAppModeUseCase(AppMode.LOGIN) when (userType) { UserType.INTERMEDIATOR -> myPageRepository.interWithdraw() else -> myPageRepository.volunteerWithdraw() } - dataStoreRepository.deleteAccessToken() + deleteAccessTokenUseCase() } catch (e: Exception) { Log.d(TAG, e.message.toString()) } diff --git a/feature/signup/build.gradle.kts b/feature/signup/build.gradle.kts index 29400106b..19fc48186 100644 --- a/feature/signup/build.gradle.kts +++ b/feature/signup/build.gradle.kts @@ -45,11 +45,17 @@ android { dependencies { - implementation(project(":core:designsystem")) - implementation(project(":core:util")) + implementation(projects.domain) + implementation(projects.core.designsystem) + implementation(projects.core.util) + implementation(projects.core.data) + implementation(projects.core.model) implementation(libs.androidx.core.splashscreen) - implementation(project(mapOf("path" to ":core:data"))) + + implementation(libs.orbit.core) + implementation(libs.orbit.compose) + implementation(libs.orbit.viewmodel) kapt(libs.hilt.compiler) implementation(libs.hilt.android) diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/navigation/SignUpNavigation.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/navigation/SignUpNavigation.kt index 7c1b822fe..56c91b56b 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/navigation/SignUpNavigation.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/navigation/SignUpNavigation.kt @@ -1,7 +1,12 @@ package com.kusitms.connectdog.signup.navigation +import android.annotation.SuppressLint +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavHostController import androidx.navigation.NavOptions import androidx.navigation.NavType import androidx.navigation.compose.composable @@ -16,189 +21,147 @@ import com.kusitms.connectdog.signup.screen.intermediator.IntermediatorInformati import com.kusitms.connectdog.signup.screen.intermediator.IntermediatorProfileScreen import com.kusitms.connectdog.signup.screen.volunteer.SelectProfileImageScreen import com.kusitms.connectdog.signup.screen.volunteer.VolunteerProfileScreen -import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel -import com.kusitms.connectdog.signup.viewmodel.VolunteerProfileViewModel -fun NavController.navigateSignup(userType: UserType) { - navigate("${SignUpRoute.route}/$userType") -} - -fun NavController.navigateToIntermediatorProfile() { - navigate(SignUpRoute.intermediator_profile) -} - -fun NavController.navigateToCertification(userType: UserType) { - navigate("${SignUpRoute.certification}/$userType") -} - -fun NavController.navigateToVolunteerProfile(userType: UserType) { - navigate("${SignUpRoute.volunteer_profile}/$userType") -} - -fun NavController.navigateRegisterEmail(userType: UserType) { - navigate("${SignUpRoute.register_email}/$userType") -} - -fun NavController.navigateRegisterPassword(userType: UserType) { - navigate("${SignUpRoute.register_password}/$userType") -} - -fun NavController.navigateSelectProfileImage() { - navigate(SignUpRoute.profile_image) -} - -fun NavController.navigateCompleteSignUp(userType: UserType) { - val navOption = NavOptions.Builder() - .setPopUpTo(SignUpRoute.route, false) +fun NavController.navigateSignup(userType: UserType) = navigate("${SignUpRoute.ROUTE}/$userType") +fun NavController.navigateToIntermediatorProfile() = navigate(SignUpRoute.INTERMEDIATOR_PROFILE) +fun NavController.navigateToCertification() = navigate(SignUpRoute.CERTIFICATION) +fun NavController.navigateToVolunteerProfile() = navigate(SignUpRoute.VOLUNTEER_PROFILE) +fun NavController.navigateRegisterEmail() = navigate(SignUpRoute.REGISTER_EMAIL) +fun NavController.navigateRegisterPassword() = navigate(SignUpRoute.REGISTER_PASSWORD) +fun NavController.navigateSelectProfileImage() = navigate(SignUpRoute.SELECT_PROFILE_IMAGE) +fun NavController.navigateIntermediatorInformation() = navigate(SignUpRoute.INTERMEDIATOR_INFORMATION) +fun NavController.navigateCompleteSignUp() = navigate( + route = SignUpRoute.COMPLETE_SIGNUP, + navOptions = NavOptions.Builder() + .setPopUpTo(SignUpRoute.ROUTE, false) .build() - navigate("${SignUpRoute.complete_signup}/$userType", navOption) -} - -fun NavController.navigateIntermediatorInformation() { - navigate(SignUpRoute.intermediator_information) -} +) +@SuppressLint("UnrememberedGetBackStackEntry") +@RequiresApi(Build.VERSION_CODES.TIRAMISU) fun NavGraphBuilder.signUpGraph( + navController: NavHostController, onBackClick: () -> Unit, - navigateToVolunteerProfile: (UserType) -> Unit, + navigateToVolunteerProfile: () -> Unit, navigateToIntermediatorProfile: () -> Unit, navigateToIntermediatorInformation: () -> Unit, - navigateToRegisterEmail: (UserType) -> Unit, - navigateToRegisterPassword: (UserType) -> Unit, + navigateToRegisterEmail: () -> Unit, + navigateToRegisterPassword: () -> Unit, navigateToSelectProfileImage: () -> Unit, - navigateToCompleteSignUp: (UserType) -> Unit, - navigateToVolunteer: () -> Unit, - navigateToIntermediator: () -> Unit, - navigateToCertification: (UserType) -> Unit, + navigateToCompleteSignUp: () -> Unit, + navigateToVolunteerHome: () -> Unit, + navigateToIntermediatorHome: () -> Unit, + navigateToCertification: () -> Unit, navigateToLogin: () -> Unit, onSendMessage: (String) -> Unit, onVerifyCode: (String, (Boolean) -> Unit) -> Unit, openWebBrowser: (String) -> Unit, imeHeight: Int, - signUpViewModel: SignUpViewModel, - profileViewModel: VolunteerProfileViewModel ) { - val userTypeArgument = listOf( - navArgument("type") { - type = NavType.EnumType(UserType::class.java) - } - ) + val signUpRoute = "${SignUpRoute.ROUTE}/{userType}" composable( - route = "${SignUpRoute.route}/{type}", - arguments = userTypeArgument + route = signUpRoute, + arguments = listOf( + navArgument("userType") { + type = NavType.EnumType(UserType::class.java) + } + ) ) { SignUpRoute( onBackClick = navigateToLogin, - userType = it.arguments!!.getSerializable("type") as UserType, + userType = it.arguments?.getSerializable("userType", UserType::class.java) ?: UserType.NORMAL_VOLUNTEER, navigateToCertification = navigateToCertification, - openWebBrowser = openWebBrowser + openWebBrowser = openWebBrowser, + signUpViewModel = hiltViewModel(it) ) } - composable( - route = "${SignUpRoute.register_email}/{type}", - arguments = userTypeArgument - ) { + composable(route = SignUpRoute.CERTIFICATION) { + CertificationScreen( + onBackClick = onBackClick, + onNavigateToRegisterEmail = navigateToRegisterEmail, + onNavigateToVolunteerProfile = navigateToVolunteerProfile, + onSendMessageClick = onSendMessage, + onVerifyCodeClick = onVerifyCode, + imeHeight = imeHeight, + viewModel = hiltViewModel(navController.getBackStackEntry(signUpRoute)) + ) + } + + composable(route = SignUpRoute.REGISTER_EMAIL) { RegisterEmailScreen( onBackClick = onBackClick, - userType = it.arguments!!.getSerializable("type") as UserType, onNavigateToRegisterPassword = navigateToRegisterPassword, - signUpViewModel = signUpViewModel, - imeHeight = imeHeight + imeHeight = imeHeight, + viewModel = hiltViewModel(navController.getBackStackEntry(signUpRoute)) ) } - composable( - route = "${SignUpRoute.register_password}/{type}", - arguments = userTypeArgument - ) { + composable(route = SignUpRoute.REGISTER_PASSWORD) { RegisterPasswordScreen( onBackClick = onBackClick, onNavigateToIntermediatorProfile = navigateToIntermediatorProfile, onNavigateToVolunteerProfile = navigateToVolunteerProfile, - userType = it.arguments!!.getSerializable("type") as UserType, - signUpViewModel = signUpViewModel, - imeHeight = imeHeight + imeHeight = imeHeight, + viewModel = hiltViewModel(navController.getBackStackEntry(signUpRoute)) ) } - composable( - route = "${SignUpRoute.volunteer_profile}/{type}", - arguments = userTypeArgument - ) { + composable(route = SignUpRoute.VOLUNTEER_PROFILE) { VolunteerProfileScreen( onBackClick = onBackClick, onNavigateToSelectProfileImage = navigateToSelectProfileImage, onNavigateToCompleteSignUp = navigateToCompleteSignUp, imeHeight = imeHeight, - signUpViewModel = signUpViewModel, - viewModel = profileViewModel, - userType = it.arguments!!.getSerializable("type") as UserType + viewModel = hiltViewModel(navController.getBackStackEntry(signUpRoute)) ) } - composable(route = SignUpRoute.intermediator_profile) { + composable(route = SignUpRoute.INTERMEDIATOR_PROFILE) { IntermediatorProfileScreen( onBackClick = onBackClick, imeHeight = imeHeight, navigateToIntermediatorInfo = navigateToIntermediatorInformation, - signUpViewModel = signUpViewModel + viewModel = hiltViewModel(navController.getBackStackEntry(signUpRoute)) ) } - composable(route = SignUpRoute.intermediator_information) { + composable(route = SignUpRoute.INTERMEDIATOR_INFORMATION) { IntermediatorInformationScreen( onBackClick = onBackClick, imeHeight = imeHeight, onNavigateToCompleteSignUp = navigateToCompleteSignUp, - signUpViewModel = signUpViewModel + signUpViewModel = hiltViewModel(navController.getBackStackEntry(signUpRoute)) ) } - composable(route = SignUpRoute.profile_image) { + composable(route = SignUpRoute.SELECT_PROFILE_IMAGE) { SelectProfileImageScreen( onBackClick = onBackClick, - viewModel = profileViewModel + signUpViewModel = hiltViewModel(navController.getBackStackEntry(signUpRoute)) ) } composable( - route = "${SignUpRoute.complete_signup}/{type}", - arguments = userTypeArgument + route = SignUpRoute.COMPLETE_SIGNUP, ) { CompleteSignUpScreen( - navigateToLoginRoute = navigateToLogin - ) - } - - composable( - route = "${SignUpRoute.certification}/{type}", - arguments = userTypeArgument - ) { - CertificationScreen( - onBackClick = onBackClick, - onNavigateToRegisterEmail = navigateToRegisterEmail, - onNavigateToVolunteerProfile = navigateToVolunteerProfile, - onSendMessageClick = onSendMessage, - onVerifyCodeClick = onVerifyCode, - imeHeight = imeHeight, - userType = it.arguments!!.getSerializable("type") as UserType, - signUpViewModel = signUpViewModel + viewModel = hiltViewModel(navController.getBackStackEntry(signUpRoute)), + navigateToVolunteerHome = navigateToVolunteerHome, + navigateToIntermediatorHome = navigateToIntermediatorHome ) } } object SignUpRoute { - const val route = "sign_up" - const val volunteer_profile = "volunteer_profile" - const val intermediator_profile = "intermediator_profile" - const val intermediator_information = "intermediator_information" - const val register_email = "register_email" - const val register_password = "register_password" - const val profile_image = "profile_image" - const val complete_signup = "complete_signup" - const val volunteer = "volunteer" - const val certification = "certification" - const val intermediator = "intermediator" + const val ROUTE = "sign_up" + const val VOLUNTEER_PROFILE = "volunteer_profile" + const val INTERMEDIATOR_PROFILE = "intermediator_profile" + const val INTERMEDIATOR_INFORMATION = "intermediator_information" + const val REGISTER_EMAIL = "register_email" + const val REGISTER_PASSWORD = "register_password" + const val SELECT_PROFILE_IMAGE = "profile_image" + const val COMPLETE_SIGNUP = "complete_signup" + const val CERTIFICATION = "certification" } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/CeritificationScreen.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/CeritificationScreen.kt index 74828f3e8..c49dca9ce 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/CeritificationScreen.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/CeritificationScreen.kt @@ -1,7 +1,7 @@ package com.kusitms.connectdog.signup.screen.common import android.annotation.SuppressLint -import android.widget.Toast +import android.util.Log import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement @@ -22,7 +22,6 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight @@ -30,41 +29,52 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.navigation.NavBackStackEntry import com.kusitms.connectdog.core.designsystem.component.ConnectDogNormalButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextFieldWithTimer import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType -import com.kusitms.connectdog.core.designsystem.theme.Gray6 -import com.kusitms.connectdog.core.designsystem.theme.Gray8 +import com.kusitms.connectdog.core.designsystem.theme.Gray100 +import com.kusitms.connectdog.core.designsystem.theme.Gray60 +import com.kusitms.connectdog.core.designsystem.theme.Red1 import com.kusitms.connectdog.core.util.UserType import com.kusitms.connectdog.feature.signup.R -import com.kusitms.connectdog.signup.state.CertificationSideEffect -import com.kusitms.connectdog.signup.viewmodel.CertificationViewModel +import com.kusitms.connectdog.signup.state.SignUpSideEffect import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel import org.orbitmvi.orbit.compose.collectAsState import org.orbitmvi.orbit.compose.collectSideEffect -@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter", "ResourceType") @Composable fun CertificationScreen( onBackClick: () -> Unit, - onNavigateToRegisterEmail: (UserType) -> Unit, - onNavigateToVolunteerProfile: (UserType) -> Unit, + onNavigateToRegisterEmail: () -> Unit, + onNavigateToVolunteerProfile: () -> Unit, onSendMessageClick: (String) -> Unit, onVerifyCodeClick: (String, (Boolean) -> Unit) -> Unit, imeHeight: Int, - userType: UserType, - signUpViewModel: SignUpViewModel, - viewModel: CertificationViewModel = hiltViewModel() + viewModel: SignUpViewModel, ) { + val uiState by viewModel.collectAsState() + + viewModel.collectSideEffect { sideEffect -> + when (sideEffect) { + is SignUpSideEffect.NavigateToProfile -> onNavigateToVolunteerProfile() + is SignUpSideEffect.NavigateToEmailRegister -> onNavigateToRegisterEmail() + else -> Unit + } + } + + LaunchedEffect(Unit) { + Log.d("aswwwwaa", uiState.userType.toString()) + } + Scaffold( topBar = { ConnectDogTopAppBar( - titleRes = when (userType) { - UserType.INTERMEDIATOR -> R.string.intermediator_signup - else -> R.string.volunteer_signup - }, + titleRes = uiState.userType.topBarTitleRes, navigationType = TopAppBarNavigationType.BACK, navigationIconContentDescription = "Navigation icon", onNavigationClick = onBackClick @@ -72,14 +82,10 @@ fun CertificationScreen( } ) { Content( - onNavigateToRegisterEmail = { onNavigateToRegisterEmail(userType) }, - onNavigateToVolunteerProfile = { onNavigateToVolunteerProfile(userType) }, onSendMessageClick = onSendMessageClick, onVerifyCodeClick = onVerifyCodeClick, imeHeight = imeHeight, - userType = userType, viewModel = viewModel, - signUpViewModel = signUpViewModel ) } } @@ -87,48 +93,20 @@ fun CertificationScreen( @Composable private fun Content( imeHeight: Int, - userType: UserType, - onNavigateToRegisterEmail: (UserType) -> Unit, - onNavigateToVolunteerProfile: (UserType) -> Unit, onSendMessageClick: (String) -> Unit, onVerifyCodeClick: (String, (Boolean) -> Unit) -> Unit, - signUpViewModel: SignUpViewModel, - viewModel: CertificationViewModel + viewModel: SignUpViewModel, ) { val focusManager = LocalFocusManager.current val interactionSource = remember { MutableInteractionSource() } - val context = LocalContext.current val scrollState = rememberScrollState() - val uiState by viewModel.collectAsState() - LaunchedEffect(key1 = signUpViewModel) { - signUpViewModel.isDuplicatePhoneNumber.collect { - if (it) { - Toast.makeText(context, "중복된 휴대폰 번호입니다.", Toast.LENGTH_SHORT).show() - } else { - Toast.makeText(context, "인증번호를 전송하였습니다.", Toast.LENGTH_SHORT).show() - } - } - } - - viewModel.collectSideEffect { sideEffect -> - when (sideEffect) { - is CertificationSideEffect.NavigateToProfile -> { - signUpViewModel.updateName(uiState.name) - signUpViewModel.updatePhoneNumber(uiState.phoneNumber) - when (userType) { - UserType.SOCIAL_VOLUNTEER -> onNavigateToVolunteerProfile(userType) - else -> onNavigateToRegisterEmail(userType) - } - } - } - } - Column( modifier = Modifier .fillMaxSize() - .padding(start = 20.dp, end = 20.dp, top = 32.dp) + .padding(vertical = 32.dp) + .padding(horizontal = 20.dp) .clickable( onClick = { focusManager.clearFocus() }, indication = null, @@ -145,8 +123,8 @@ private fun Content( Spacer(modifier = Modifier.height(40.dp)) ConnectDogTextField( text = uiState.name, - label = "이름", - placeholder = "이름 입력", + label = stringResource(id = R.string.name), + placeholder = stringResource(id = R.string.input_name), keyboardType = KeyboardType.Text, onTextChanged = viewModel::onNameChanged ) @@ -155,48 +133,61 @@ private fun Content( text = uiState.phoneNumber, onTextChanged = viewModel::onPhoneNumberChanged, label = stringResource(id = R.string.phone_number), - placeholder = "'-'빼고 입력", + placeholder = stringResource(id = R.string.phone_number_requirement), keyboardType = KeyboardType.Number ) - - if (uiState.isSendCertificationNumber) { + if (uiState.isSendPhoneAuthCode) { Spacer(modifier = Modifier.height(12.dp)) ConnectDogTextFieldWithTimer( - text = uiState.certificationNumber, - textFieldLabel = "인증번호", - placeholder = "숫자 6자리", + text = uiState.phoneAuthCode, + textFieldLabel = stringResource(id = R.string.auth_code), + placeholder = stringResource(id = R.string.auth_code_requirement), keyboardType = KeyboardType.Number, - onTextChanged = viewModel::onChangeCertificationNumber + onTextChanged = viewModel::onPhoneAuthCodeChanged, + isError = (uiState.isPhoneNumberCertified == false) ) + if(uiState.isPhoneNumberCertified == false) { + Text( + modifier = Modifier.padding(top = 4.dp), + text = stringResource(id = R.string.auth_code_incorrect), + color = Red1, + fontSize = 10.sp + ) + } Spacer(modifier = Modifier.height(28.dp)) Row( modifier = Modifier.fillMaxSize(), horizontalArrangement = Arrangement.Center ) { Text( - text = "인증번호가 오지 않는다면?", - color = Gray6, + text = stringResource(id = R.string.resend_title), + color = Gray60, fontSize = 12.sp ) Spacer(modifier = Modifier.width(8.dp)) Text( modifier = Modifier.clickable { }, - text = "재발송", + text = stringResource(id = R.string.resend), fontSize = 12.sp, - color = Gray8, + color = Gray100, fontWeight = FontWeight.SemiBold ) } } Spacer(modifier = Modifier.weight(1f)) ConnectDogNormalButton( - content = uiState.bottomButtonText, - enabled = if (!uiState.isSendCertificationNumber) uiState.enableNext else uiState.enableCertification, modifier = Modifier .fillMaxWidth() .height(56.dp), - onClick = { viewModel.onNextClick(onSendMessageClick, onVerifyCodeClick) } + content = uiState.phoneCertificationButtonText, + enabled = uiState.enablePhoneCertification, + onClick = { + viewModel.onPhoneCertificationButtonClick( + onSendMessageClick = onSendMessageClick, + onVerifyCodeClick = onVerifyCodeClick, + ) + } ) - Spacer(modifier = Modifier.height((imeHeight + 32).dp)) + Spacer(modifier = Modifier.height((imeHeight).dp)) } } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/CompleteSignUpScreen.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/CompleteSignUpScreen.kt index f7a523a16..9651ffa40 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/CompleteSignUpScreen.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/CompleteSignUpScreen.kt @@ -2,8 +2,6 @@ package com.kusitms.connectdog.signup.screen.common import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -14,12 +12,10 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.layout -import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign @@ -27,24 +23,28 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.kusitms.connectdog.core.designsystem.R import com.kusitms.connectdog.core.designsystem.component.ConnectDogNormalButton +import com.kusitms.connectdog.signup.state.SignUpSideEffect +import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel +import org.orbitmvi.orbit.compose.collectSideEffect @Composable fun CompleteSignUpScreen( - navigateToLoginRoute: () -> Unit + viewModel: SignUpViewModel, + navigateToVolunteerHome: () -> Unit, + navigateToIntermediatorHome: () -> Unit, ) { - val focusManager = LocalFocusManager.current - val interactionSource = remember { MutableInteractionSource() } + viewModel.collectSideEffect { + when(it) { + is SignUpSideEffect.NavigateToVolunteerHome -> navigateToVolunteerHome() + is SignUpSideEffect.NavigateToIntermediatorHome -> navigateToIntermediatorHome() + else -> Unit + } + } Box( - modifier = - Modifier + modifier = Modifier .fillMaxSize() .background(Color.White) - .clickable( - onClick = { focusManager.clearFocus() }, - indication = null, - interactionSource = interactionSource - ) ) { Image( painter = painterResource(id = R.drawable.background), @@ -75,8 +75,7 @@ fun CompleteSignUpScreen( } ConnectDogNormalButton( content = "확인", - modifier = - Modifier + modifier = Modifier .fillMaxWidth() .height(56.dp) .align(Alignment.BottomCenter) @@ -87,7 +86,7 @@ fun CompleteSignUpScreen( placeable.place(0, 0) } }, - onClick = navigateToLoginRoute + onClick = viewModel::onStartClick ) } } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/RegisterEmailScreen.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/RegisterEmailScreen.kt index d3c209f8b..aec0bea17 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/RegisterEmailScreen.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/RegisterEmailScreen.kt @@ -1,6 +1,7 @@ package com.kusitms.connectdog.signup.screen.common import android.annotation.SuppressLint +import android.util.Log import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Column @@ -11,136 +12,130 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.res.stringResource 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.kusitms.connectdog.core.designsystem.R +import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.navigation.NavBackStackEntry import com.kusitms.connectdog.core.designsystem.component.ConnectDogBottomButton -import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextFieldWithButton +import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType -import com.kusitms.connectdog.core.designsystem.theme.ConnectDogTheme -import com.kusitms.connectdog.core.designsystem.theme.Gray5 -import com.kusitms.connectdog.core.designsystem.theme.PetOrange import com.kusitms.connectdog.core.designsystem.theme.Red1 import com.kusitms.connectdog.core.util.UserType -import com.kusitms.connectdog.signup.viewmodel.RegisterEmailViewModel +import com.kusitms.connectdog.feature.signup.R +import com.kusitms.connectdog.signup.state.SignUpSideEffect +import com.kusitms.connectdog.signup.state.SignUpUiState import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel +import org.orbitmvi.orbit.compose.collectAsState +import org.orbitmvi.orbit.compose.collectSideEffect -@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter", "ResourceType") @Composable fun RegisterEmailScreen( onBackClick: () -> Unit, - userType: UserType, - onNavigateToRegisterPassword: (UserType) -> Unit, - signUpViewModel: SignUpViewModel, - viewModel: RegisterEmailViewModel = hiltViewModel(), - imeHeight: Int + onNavigateToRegisterPassword: () -> Unit, + viewModel: SignUpViewModel, + imeHeight: Int, ) { - val focusManager = LocalFocusManager.current - val interactionSource = remember { MutableInteractionSource() } - val context = LocalContext.current - val isValidEmail by viewModel.isValidEmail.collectAsState() - val isEmailVerified by viewModel.isEmailVerified.collectAsState() - val isEmailDuplicated by viewModel.isEmailDuplicated.collectAsState() + val uiState by viewModel.collectAsState() + + LaunchedEffect(key1 = Unit) { + Log.d("aswwwwaa", uiState.userType.toString()) + } + + viewModel.collectSideEffect { + when(it) { + SignUpSideEffect.NavigateToPasswordRegister -> onNavigateToRegisterPassword() + else -> Unit + } + } Scaffold( topBar = { ConnectDogTopAppBar( - titleRes = when (userType) { - UserType.SOCIAL_VOLUNTEER -> R.string.volunteer_signup - UserType.NORMAL_VOLUNTEER -> R.string.volunteer_signup - UserType.INTERMEDIATOR -> R.string.intermediator_signup - }, + titleRes = uiState.userType.topBarTitleRes, navigationType = TopAppBarNavigationType.BACK, - navigationIconContentDescription = "Navigation icon", onNavigationClick = onBackClick ) } ) { - Column( - modifier = Modifier - .padding(horizontal = 20.dp) - .clickable( - onClick = { focusManager.clearFocus() }, - indication = null, - interactionSource = interactionSource - ) - ) { - Spacer(modifier = Modifier.height(80.dp)) - Text( - text = "로그인에 사용할\n이메일을 입력해주세요", - fontSize = 20.sp, - fontWeight = FontWeight.Bold - ) - Spacer(modifier = Modifier.height(40.dp)) - ConnectDogTextFieldWithButton( - text = viewModel.email, - width = 62, - height = 27, - textFieldLabel = "이메일", - placeholder = "이메일 입력", - buttonLabel = "인증 요청", - isError = (isValidEmail ?: false) || (isEmailDuplicated ?: false), - onTextChanged = { - viewModel.updateEmail(it) - viewModel.updateEmailValidity() - }, - borderColor = if (isValidEmail == false && isEmailDuplicated == false) PetOrange else Gray5, - onClick = { viewModel.postEmail(context) }, - padding = 5 - ) - Spacer(modifier = Modifier.height(12.dp)) - ConnectDogTextFieldWithButton( - text = viewModel.certificationNumber, - width = 62, - height = 27, - textFieldLabel = "인증 번호", - placeholder = "숫자 6자리", - buttonLabel = "인증 확인", - keyboardType = KeyboardType.Text, - onTextChanged = { viewModel.updateCertificationNumber(it) }, - borderColor = if (viewModel.isEmailVerified.value == true) PetOrange else if (viewModel.isEmailVerified.value == false) Red1 else Gray5, - onClick = { viewModel.checkCertificationNumber(context) }, - padding = 5, - isError = isEmailVerified == false - ) - Spacer(modifier = Modifier.weight(1f)) - ConnectDogBottomButton( - content = "다음", - enabled = isEmailVerified == true, - onClick = { - signUpViewModel.updateEmail(viewModel.email) - onNavigateToRegisterPassword(userType) - }, - modifier = Modifier - .fillMaxWidth() - .height(56.dp) - ) - Spacer(modifier = Modifier.height((imeHeight + 32).dp)) - } + Content( + viewModel = viewModel, + imeHeight = imeHeight, + uiState = uiState + ) } } -@Preview @Composable -private fun test() { - ConnectDogTheme { - RegisterEmailScreen( - onBackClick = {}, - userType = UserType.NORMAL_VOLUNTEER, - onNavigateToRegisterPassword = {}, - hiltViewModel(), - imeHeight = 10 +private fun Content( + viewModel: SignUpViewModel, + uiState: SignUpUiState, + imeHeight: Int +) { + val focusManager = LocalFocusManager.current + val interactionSource = remember { MutableInteractionSource() } + + Column( + modifier = Modifier + .padding(horizontal = 20.dp) + .clickable( + onClick = { focusManager.clearFocus() }, + indication = null, + interactionSource = interactionSource + ) + ) { + Spacer(modifier = Modifier.height(80.dp)) + Text( + text = stringResource(id = R.string.email_auth_title), + fontSize = 20.sp, + fontWeight = FontWeight.Bold ) + Spacer(modifier = Modifier.height(40.dp)) + ConnectDogTextField( + text = uiState.email, + label = stringResource(id = R.string.email), + placeholder = stringResource(id = R.string.input_email), + isError = uiState.isValidEmail == false, + onTextChanged = viewModel::onEmailChanged, + ) + Spacer(modifier = Modifier.height(12.dp)) + if (uiState.isSendEmailAuthCode) { + ConnectDogTextField( + text = uiState.inputEmailAuthCode, + label = stringResource(id = R.string.auth_code), + placeholder = stringResource(id = R.string.input_auth_code), + keyboardType = KeyboardType.Text, + onTextChanged = viewModel::onEmailAuthCodeChanged, + isError = uiState.isEmailAuthCodeError == true + ) + if(uiState.isEmailAuthCodeError == true) { + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = "올바른 인증번호를 입력해주세요", + fontSize = 10.sp, + color = Red1 + ) + } + } + Spacer(modifier = Modifier.weight(1f)) + ConnectDogBottomButton( + modifier = Modifier + .fillMaxWidth() + .height(56.dp), + content = uiState.emailCertificationButtonText, + enabled = uiState.enableEmailCertification, + onClick = viewModel::onEmailCertificationButtonClick, + ) + Spacer(modifier = Modifier.height((imeHeight + 32).dp)) } -} +} \ No newline at end of file diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/RegisterPasswordScreen.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/RegisterPasswordScreen.kt index a89ab5eb4..ab065ae89 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/RegisterPasswordScreen.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/RegisterPasswordScreen.kt @@ -1,6 +1,7 @@ package com.kusitms.connectdog.signup.screen.common import android.annotation.SuppressLint +import android.util.Log import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource @@ -13,139 +14,122 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.res.stringResource 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.kusitms.connectdog.core.designsystem.R +import com.kusitms.connectdog.core.designsystem.component.ConnectDogBottomButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogNormalButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType -import com.kusitms.connectdog.core.designsystem.theme.ConnectDogTheme import com.kusitms.connectdog.core.designsystem.theme.Gray3 -import com.kusitms.connectdog.core.designsystem.theme.Orange_40 -import com.kusitms.connectdog.core.designsystem.theme.PetOrange -import com.kusitms.connectdog.core.util.UserType -import com.kusitms.connectdog.signup.viewmodel.RegisterPasswordViewModel +import com.kusitms.connectdog.feature.signup.R +import com.kusitms.connectdog.signup.state.SignUpSideEffect +import com.kusitms.connectdog.signup.state.SignUpUiState import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel +import org.orbitmvi.orbit.compose.collectAsState +import org.orbitmvi.orbit.compose.collectSideEffect -@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter", "ResourceType") @Composable fun RegisterPasswordScreen( onBackClick: () -> Unit, - onNavigateToVolunteerProfile: (UserType) -> Unit, + onNavigateToVolunteerProfile: () -> Unit, onNavigateToIntermediatorProfile: () -> Unit, - userType: UserType, imeHeight: Int, - signUpViewModel: SignUpViewModel, - viewModel: RegisterPasswordViewModel = hiltViewModel() + viewModel: SignUpViewModel ) { - val focusManager = LocalFocusManager.current - val interactionSource = remember { MutableInteractionSource() } - val isValidPassword by viewModel.isValidPassword.collectAsState() - val isValidConfirmPassword by viewModel.isValidConfirmPassword.collectAsState() + val uiState by viewModel.collectAsState() + viewModel.collectSideEffect { + when(it) { + is SignUpSideEffect.NavigateToProfile -> onNavigateToVolunteerProfile() + else -> Unit + } + } Scaffold( topBar = { ConnectDogTopAppBar( - titleRes = when (userType) { - UserType.INTERMEDIATOR -> R.string.intermediator_signup - else -> R.string.volunteer_signup - }, + titleRes = uiState.userType.topBarTitleRes, navigationType = TopAppBarNavigationType.BACK, navigationIconContentDescription = "Navigation icon", onNavigationClick = onBackClick ) } ) { - Column( - modifier = Modifier - .fillMaxSize() - .background(Color.White) - .padding(horizontal = 20.dp) - .clickable( - onClick = { focusManager.clearFocus() }, - indication = null, - interactionSource = interactionSource - ) - ) { - Spacer(modifier = Modifier.height(80.dp)) - Text( - text = "로그인에 사용할\n비밀번호를 입력해주세요", - fontSize = 20.sp, - fontWeight = FontWeight.Bold - ) - Spacer(modifier = Modifier.height(40.dp)) - ConnectDogTextField( - text = viewModel.password, - label = "비밀번호", - placeholder = "비밀번호 입력", - keyboardType = KeyboardType.Password, - isError = isValidPassword ?: false, - onTextChanged = { - viewModel.updatePassword(it) - viewModel.checkPasswordValidity(it) - } - ) - Spacer(modifier = Modifier.height(12.dp)) - ConnectDogTextField( - text = viewModel.confirmPassword, - label = "비밀번호 확인", - placeholder = "비밀번호 확인", - keyboardType = KeyboardType.Password, - isError = isValidConfirmPassword ?: false, - onTextChanged = { - viewModel.updateConfirmPassword(it) - viewModel.checkConfirmPasswordValidity(it) - } - ) - Spacer(modifier = Modifier.height(4.dp)) - Text( - text = "영문+숫자 10자 이상", - modifier = Modifier.padding(start = 8.dp), - fontSize = 11.sp, - color = Gray3 - ) - Spacer(modifier = Modifier.weight(1f)) - ConnectDogNormalButton( - content = "다음", - modifier = - Modifier - .fillMaxWidth() - .height(56.dp), - color = if (isValidPassword == false && isValidConfirmPassword == false) { - PetOrange - } else { - Orange_40 - }, - onClick = { - if (isValidPassword == false && isValidConfirmPassword == false) { - signUpViewModel.updatePassword(viewModel.password) - when (userType) { - UserType.INTERMEDIATOR -> onNavigateToIntermediatorProfile() - else -> onNavigateToVolunteerProfile(userType) - } - } - } - ) - Spacer(modifier = Modifier.height((imeHeight + 32).dp)) - } + Content( + viewModel = viewModel, + imeHeight = imeHeight, + uiState = uiState + ) } } -@Preview + @Composable -private fun Preview() { - ConnectDogTheme { - RegisterPasswordScreen({}, {}, {}, UserType.INTERMEDIATOR, 10, hiltViewModel()) +private fun Content( + viewModel: SignUpViewModel, + imeHeight: Int, + uiState: SignUpUiState, +) { + val focusManager = LocalFocusManager.current + val interactionSource = remember { MutableInteractionSource() } + + Column( + modifier = Modifier + .fillMaxSize() + .background(Color.White) + .padding(horizontal = 20.dp) + .clickable( + onClick = { focusManager.clearFocus() }, + indication = null, + interactionSource = interactionSource + ) + ) { + Spacer(modifier = Modifier.height(80.dp)) + Text( + text = stringResource(id = R.string.register_password_title), + fontSize = 20.sp, + fontWeight = FontWeight.Bold + ) + Spacer(modifier = Modifier.height(40.dp)) + ConnectDogTextField( + text = uiState.password, + label = stringResource(id = R.string.password), + placeholder = stringResource(id = R.string.input_passwrod), + keyboardType = KeyboardType.Password, + isError = (uiState.isValidPassword == false), + onTextChanged = viewModel::onPasswordChanged + ) + Spacer(modifier = Modifier.height(12.dp)) + ConnectDogTextField( + text = uiState.confirmPassword, + label = stringResource(id = R.string.confirm_password), + placeholder = stringResource(id = R.string.confirm_password), + keyboardType = KeyboardType.Password, + isError = uiState.isValidConfirmPassword == false, + onTextChanged = viewModel::onConfirmPasswordChanged + ) + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = stringResource(id = R.string.password_requirement), + modifier = Modifier.padding(start = 8.dp), + fontSize = 11.sp, + color = Gray3 + ) + Spacer(modifier = Modifier.weight(1f)) + ConnectDogBottomButton( + content = stringResource(id = R.string.next), + enabled = uiState.enablePasswordRegister, + onClick = viewModel::onPasswordRegisterNextButtonClick + ) + Spacer(modifier = Modifier.height((imeHeight + 32).dp)) } } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/TermScreen.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/TermScreen.kt index 5150ea00e..32b00c309 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/TermScreen.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/common/TermScreen.kt @@ -1,64 +1,49 @@ package com.kusitms.connectdog.signup.screen.common -import android.view.Gravity -import android.widget.Toast +import android.annotation.SuppressLint import androidx.activity.compose.BackHandler -import androidx.compose.foundation.Canvas import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row 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.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue -import androidx.compose.runtime.livedata.observeAsState -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalFocusManager -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel -import com.kusitms.connectdog.core.designsystem.R -import com.kusitms.connectdog.core.designsystem.component.ConnectDogNormalButton +import com.kusitms.connectdog.core.designsystem.component.CheckBox +import com.kusitms.connectdog.core.designsystem.component.ConnectDogBottomButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar +import com.kusitms.connectdog.core.designsystem.component.HorizontalLine import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType -import com.kusitms.connectdog.core.designsystem.theme.Gray1 -import com.kusitms.connectdog.core.designsystem.theme.Gray2 import com.kusitms.connectdog.core.designsystem.theme.Gray3 -import com.kusitms.connectdog.core.designsystem.theme.Gray4 -import com.kusitms.connectdog.core.designsystem.theme.Orange_40 -import com.kusitms.connectdog.core.designsystem.theme.PetOrange import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.feature.signup.R +import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel import com.kusitms.connectdog.signup.viewmodel.TermsViewModel +import org.orbitmvi.orbit.compose.collectAsState @Composable internal fun SignUpRoute( onBackClick: () -> Unit, - navigateToCertification: (UserType) -> Unit, + navigateToCertification: () -> Unit, openWebBrowser: (String) -> Unit, - userType: UserType + userType: UserType, + signUpViewModel: SignUpViewModel ) { + LaunchedEffect(key1 = Unit) { + signUpViewModel.updateUserType(userType) + } + TermScreen( onBackClick = onBackClick, userType = userType, @@ -67,195 +52,97 @@ internal fun SignUpRoute( ) } +@SuppressLint("ResourceType", "UnusedMaterial3ScaffoldPaddingParameter") @Composable private fun TermScreen( userType: UserType, onBackClick: () -> Unit, - navigateToCertification: (UserType) -> Unit, + navigateToCertification: () -> Unit, openWebBrowser: (String) -> Unit, - viewModel: TermsViewModel = hiltViewModel() + viewModel: TermsViewModel = hiltViewModel(), ) { - val allChecked by viewModel.allChecked.observeAsState(initial = false) - val privacyChecked by viewModel.privacyChecked.observeAsState(initial = false) - val advertisementChecked by viewModel.advertisementChecked.observeAsState(initial = false) - val termsChecked by viewModel.termsChecked.observeAsState(initial = false) - val isAvailableNext by viewModel.isAvailableNext.observeAsState(initial = false) - - val context = LocalContext.current - val focusManager = LocalFocusManager.current - val interactionSource = remember { MutableInteractionSource() } - BackHandler { onBackClick() } - - Box( - modifier = - Modifier - .fillMaxSize() - .background(Color.White) - .padding(bottom = 32.dp) - .clickable( - onClick = { focusManager.clearFocus() }, - indication = null, - interactionSource = interactionSource - ) - ) { - Column( - modifier = Modifier - .fillMaxSize() - .background(Color.White) - ) { + Scaffold( + topBar = { ConnectDogTopAppBar( - titleRes = when (userType) { - UserType.SOCIAL_VOLUNTEER -> R.string.volunteer_signup - UserType.NORMAL_VOLUNTEER -> R.string.volunteer_signup - UserType.INTERMEDIATOR -> R.string.intermediator_signup - }, + titleRes = userType.topBarTitleRes, navigationType = TopAppBarNavigationType.BACK, navigationIconContentDescription = "Navigation icon", onNavigationClick = onBackClick ) - Spacer(modifier = Modifier.height(32.dp)) - Text( - text = "코넥독 서비스 이용약관에\n동의해주세요", - fontSize = 20.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(start = 20.dp) - ) - Spacer(modifier = Modifier.height(40.dp)) - - CustomCheckbox( - text = "모두 동의", - checked = allChecked, - hasDetail = false, - onCheckedChange = { - viewModel.updateAllChecked() - viewModel.updateTermsChecked() - viewModel.updatePrivacyChecked() - viewModel.updateAdvertisementChecked() - } - ) - - Spacer(modifier = Modifier.height(16.dp)) - HorizontalLine() - Spacer(modifier = Modifier.height(16.dp)) - CustomCheckbox( - text = "[필수] 이용약관 동의", - checked = termsChecked, - hasDetail = true, - onDetailClick = { openWebBrowser("https://docs.google.com/document/d/1Rr2sqZVGLVIqNyqI_YoaBazTZ2tqapRlX2zdqtM1ICs/edit?usp=sharing") }, - onCheckedChange = { viewModel.updateTermsChecked() } - ) - Spacer(modifier = Modifier.height(16.dp)) - CustomCheckbox( - text = "[필수] 개인정보 수집 및 이용 동의", - checked = privacyChecked, - onCheckedChange = { viewModel.updatePrivacyChecked() }, - hasDetail = true, - onDetailClick = { openWebBrowser("https://docs.google.com/document/d/14nF3hzCFfTVGSecKDddO4FJYy27v_c8BUkAU2w_m1O4/edit?usp=sharing") } - ) - Spacer(modifier = Modifier.height(16.dp)) - CustomCheckbox( - text = "[선택] 광고성 정보 수신 동의", - checked = advertisementChecked, - onCheckedChange = { viewModel.updateAdvertisementChecked() }, - hasDetail = true, - onDetailClick = { openWebBrowser("https://docs.google.com/document/d/14nF3hzCFfTVGSecKDddO4FJYy27v_c8BUkAU2w_m1O4/edit?usp=sharing") } - ) } - ConnectDogNormalButton( - content = "다음", - color = if (isAvailableNext) { - PetOrange - } else { - Orange_40 - }, - modifier = - Modifier - .fillMaxWidth() - .height(56.dp) - .align(Alignment.BottomCenter) - .padding(horizontal = 20.dp), - onClick = { - if (isAvailableNext) { - navigateToCertification(userType) - } else { - val toast = Toast.makeText(context, "모든 약관에 동의해주세요", Toast.LENGTH_SHORT) - toast.setGravity(Gravity.BOTTOM, 10, 1000) - toast.show() - } - } - ) - } -} - -@Composable -fun HorizontalLine() { - Canvas( - modifier = Modifier - .fillMaxWidth() - .height(1.dp) - .padding(horizontal = 20.dp) ) { - drawLine( - color = Gray3, - start = Offset(0f, 0f), - end = Offset(size.width, 0f), - strokeWidth = 1f + Content( + viewModel = viewModel, + navigateToCertification = navigateToCertification, + openWebBrowser = openWebBrowser ) } } @Composable -fun CustomCheckbox( - text: String, - checked: Boolean, - onCheckedChange: (Boolean) -> Unit, - hasDetail: Boolean, - onDetailClick: () -> Unit = {} +private fun Content( + viewModel: TermsViewModel, + navigateToCertification: () -> Unit, + openWebBrowser: (String) -> Unit, ) { - var isChecked by remember { mutableStateOf(checked) } - - if (checked != isChecked) { - isChecked = checked - } + val uiState by viewModel.collectAsState() - Row( - modifier = Modifier.padding(horizontal = 20.dp), - verticalAlignment = Alignment.CenterVertically + Column( + modifier = Modifier + .fillMaxSize() + .background(Color.White) + .padding(top = 48.dp, bottom = 32.dp) ) { - Row( - modifier = Modifier.clickable { - isChecked = !isChecked - onCheckedChange(isChecked) - }, - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - painter = painterResource( - id = R.drawable.ic_checked - ), - contentDescription = "Custom Checkbox", - tint = if (isChecked) MaterialTheme.colorScheme.primary else Gray4, - modifier = Modifier.size(24.dp) - ) - Spacer(modifier = Modifier.width(12.dp)) - Text( - text = text, - fontSize = 14.sp, - fontWeight = FontWeight.Medium, - color = if (isChecked) Color.Black else Gray2 - ) - } + Spacer(modifier = Modifier.height(32.dp)) + Text( + text = "코넥독 서비스 이용약관에\n동의해주세요", + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(start = 20.dp) + ) + Spacer(modifier = Modifier.height(40.dp)) + CheckBox( + text = uiState.agreeAll.title, + checked = uiState.agreeAll.isChecked, + hasDetail = uiState.agreeAll.hasDetail, + onClick = viewModel::onAgreeAllClick + ) + Spacer(modifier = Modifier.height(16.dp)) + HorizontalLine( + height = 1, + color = Gray3 + ) + Spacer(modifier = Modifier.height(16.dp)) + CheckBox( + text = uiState.termsOfService.title, + checked = uiState.termsOfService.isChecked, + hasDetail = uiState.termsOfService.hasDetail, + onDetailClick = { openWebBrowser(uiState.termsOfService.url!!) }, + onClick = viewModel::onTermsOfServiceClick + ) + Spacer(modifier = Modifier.height(16.dp)) + CheckBox( + text = uiState.privacy.title, + checked = uiState.privacy.isChecked, + onClick = viewModel::onPrivacyClick, + hasDetail = uiState.privacy.hasDetail, + onDetailClick = { openWebBrowser(uiState.privacy.url!!) } + ) + Spacer(modifier = Modifier.height(16.dp)) + CheckBox( + text = uiState.advertisement.title, + checked = uiState.advertisement.isChecked, + onClick = viewModel::onAdvertisementClick, + hasDetail = uiState.advertisement.hasDetail, + onDetailClick = { openWebBrowser(uiState.advertisement.url!!) } + ) Spacer(modifier = Modifier.weight(1f)) - if (hasDetail) { - Text( - text = "보기", - style = TextStyle(textDecoration = TextDecoration.Underline), - fontSize = 14.sp, - fontWeight = FontWeight.Medium, - color = if (isChecked) Gray1 else Gray2, - modifier = Modifier.clickable { onDetailClick() } - ) - } + ConnectDogBottomButton( + modifier = Modifier.padding(horizontal = 20.dp), + content = stringResource(id = R.string.next), + enabled = uiState.enableNext, + onClick = navigateToCertification + ) } } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/intermediator/IntermediatorInformationScreen.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/intermediator/IntermediatorInformationScreen.kt index 33d657781..943e9c1d8 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/intermediator/IntermediatorInformationScreen.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/intermediator/IntermediatorInformationScreen.kt @@ -22,6 +22,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavBackStackEntry import com.kusitms.connectdog.core.designsystem.component.ConnectDogNormalButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar @@ -35,7 +36,7 @@ import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel @Composable fun IntermediatorInformationScreen( onBackClick: () -> Unit, - onNavigateToCompleteSignUp: (UserType) -> Unit, + onNavigateToCompleteSignUp: () -> Unit, imeHeight: Int, viewModel: IntermediatorInformationViewModel = hiltViewModel(), signUpViewModel: SignUpViewModel @@ -91,10 +92,10 @@ fun IntermediatorInformationScreen( ConnectDogNormalButton( content = "다음", onClick = { - onNavigateToCompleteSignUp(UserType.INTERMEDIATOR) - signUpViewModel.updateUrl(viewModel.url) - signUpViewModel.updateContact(viewModel.contact) - signUpViewModel.postIntermediatorSignUp(context) + onNavigateToCompleteSignUp() +// signUpViewModel.updateUrl(viewModel.url) +// signUpViewModel.updateContact(viewModel.contact) +// signUpViewModel.postIntermediatorSignUp(context) }, modifier = Modifier .fillMaxWidth() diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/intermediator/IntermediatorProfileScreen.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/intermediator/IntermediatorProfileScreen.kt index 08aa12052..9c4a438fb 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/intermediator/IntermediatorProfileScreen.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/intermediator/IntermediatorProfileScreen.kt @@ -44,6 +44,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavBackStackEntry import com.kusitms.connectdog.core.designsystem.component.ConnectDogBottomButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogOutlinedButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField @@ -56,6 +57,7 @@ import com.kusitms.connectdog.core.designsystem.theme.Red1 import com.kusitms.connectdog.feature.signup.R import com.kusitms.connectdog.signup.viewmodel.IntermediatorProfileViewModel import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel +import org.orbitmvi.orbit.compose.collectAsState @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable @@ -63,10 +65,34 @@ fun IntermediatorProfileScreen( onBackClick: () -> Unit, navigateToIntermediatorInfo: () -> Unit, imeHeight: Int, - viewModel: IntermediatorProfileViewModel = hiltViewModel(), - signUpViewModel: SignUpViewModel + viewModel: SignUpViewModel +) { + Scaffold( + topBar = { + ConnectDogTopAppBar( + titleRes = R.string.intermediator_signup, + navigationType = TopAppBarNavigationType.BACK, + onNavigationClick = onBackClick + ) + } + ) { + Content( + viewModel = viewModel, + imeHeight = imeHeight + ) + } +} + +@Composable +private fun Content( + viewModel: SignUpViewModel, + imeHeight: Int ) { val context = LocalContext.current + val focusManager = LocalFocusManager.current + val interactionSource = remember { MutableInteractionSource() } + val scrollState = rememberScrollState() + val uiState by viewModel.collectAsState() fun convertToBitmap(uri: Uri): Bitmap = ImageDecoder .decodeBitmap( @@ -78,124 +104,108 @@ fun IntermediatorProfileScreen( onResult = { imageUri = it } ) - Scaffold( - topBar = { - ConnectDogTopAppBar( - titleRes = R.string.intermediator_signup, - navigationType = TopAppBarNavigationType.BACK, - onNavigationClick = onBackClick + Column( + modifier = Modifier + .fillMaxSize() + .background(Color.White) + .padding(horizontal = 20.dp) + .clickable( + onClick = { focusManager.clearFocus() }, + indication = null, + interactionSource = interactionSource ) - } + .verticalScroll(scrollState) ) { - val focusManager = LocalFocusManager.current - val interactionSource = remember { MutableInteractionSource() } - val scrollState = rememberScrollState() - - val isDuplicatedName by viewModel.isDuplicateName.collectAsState() - - Column( + LaunchedEffect(imeHeight) { + scrollState.animateScrollTo(scrollState.maxValue) + } + Spacer(modifier = Modifier.height(80.dp)) + Text( + text = "모집자 프로필에 사용할\n정보를 입력해주세요", + fontSize = 20.sp, + fontWeight = FontWeight.Bold + ) + Spacer(modifier = Modifier.height(40.dp)) + Row( modifier = Modifier - .fillMaxSize() - .background(Color.White) - .padding(horizontal = 20.dp) - .clickable( - onClick = { focusManager.clearFocus() }, - indication = null, - interactionSource = interactionSource - ) - .verticalScroll(scrollState) + .fillMaxWidth(), + horizontalArrangement = Arrangement.Center ) { - LaunchedEffect(imeHeight) { - scrollState.animateScrollTo(scrollState.maxValue) - } - Spacer(modifier = Modifier.height(80.dp)) - Text( - text = "모집자 프로필에 사용할\n정보를 입력해주세요", - fontSize = 20.sp, - fontWeight = FontWeight.Bold - ) - Spacer(modifier = Modifier.height(40.dp)) - Row( - modifier = Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - imageUri?.let { - Image( - bitmap = convertToBitmap(it).asImageBitmap(), - modifier = Modifier - .size(100.dp) - .clip(CircleShape), - contentDescription = "" - ) - viewModel.updateUri(it) - } ?: run { - Image( - painter = painterResource(id = com.kusitms.connectdog.core.util.R.drawable.ic_profile_1), - contentDescription = "" - ) - } - } - Spacer(modifier = Modifier.height(12.dp)) - Row( - modifier = Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - ConnectDogOutlinedButton( - width = 105, - height = 27, - text = "프로필 사진 선택", - padding = 5, - onClick = { - photoPicker.launch( - PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly) - ) - } + imageUri?.let { + Image( + bitmap = convertToBitmap(it).asImageBitmap(), + modifier = Modifier + .size(100.dp) + .clip(CircleShape), + contentDescription = "" + ) +// viewModel.updateUri(it) + } ?: run { + Image( + painter = painterResource(id = com.kusitms.connectdog.core.util.R.drawable.ic_profile_1), + contentDescription = "" ) } - Spacer(modifier = Modifier.height(40.dp)) - ConnectDogTextFieldWithButton( - text = viewModel.name, - width = 62, + } + Spacer(modifier = Modifier.height(12.dp)) + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + ConnectDogOutlinedButton( + width = 105, height = 27, - textFieldLabel = stringResource(id = R.string.intermediator_name), - placeholder = stringResource(id = R.string.intermediator_name_input), + text = "프로필 사진 선택", padding = 5, - onTextChanged = viewModel::updateName, - isError = isDuplicatedName == true, - onClick = { viewModel.checkNickNameDuplicate() } - ) - Spacer(modifier = Modifier.height(4.dp)) - Text( - text = if (isDuplicatedName == true) "이미 사용중인 모집자명입니다." else if (isDuplicatedName == false) "사용 가능한 모집자명 입니다." else "", - fontSize = 10.sp, - color = if (isDuplicatedName == true) Red1 else if (isDuplicatedName == false) PetOrange else Gray1, - fontWeight = FontWeight.Normal - ) - Spacer(modifier = Modifier.height(6.dp)) - ConnectDogTextField( - text = viewModel.introduce, - onTextChanged = viewModel::updateIntroduce, - placeholder = stringResource(id = R.string.introduce_placeholder), - height = 130 - ) - Spacer(modifier = Modifier.height(20.dp)) - Spacer(modifier = Modifier.weight(1f)) - ConnectDogBottomButton( - content = "다음", - modifier = Modifier - .fillMaxWidth() - .height(56.dp), - enabled = viewModel.name != "" && viewModel.introduce != "" && viewModel.uri != null, onClick = { - navigateToIntermediatorInfo() - signUpViewModel.updateIntro(viewModel.introduce) - signUpViewModel.updateNickname(viewModel.name) - signUpViewModel.updateInterProfileImage(viewModel.uri!!) + photoPicker.launch( + PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly) + ) } ) - Spacer(modifier = Modifier.height((imeHeight + 32).dp)) } + Spacer(modifier = Modifier.height(40.dp)) + ConnectDogTextFieldWithButton( + text = uiState.name, + width = 62, + height = 27, + textFieldLabel = stringResource(id = R.string.intermediator_name), + placeholder = stringResource(id = R.string.intermediator_name_input), + padding = 5, + onTextChanged = {}, + isError = false, + onClick = { } + ) + Spacer(modifier = Modifier.height(4.dp)) +// Text( +// text = if (isDuplicatedName == true) "이미 사용중인 모집자명입니다." else if (isDuplicatedName == false) "사용 가능한 모집자명 입니다." else "", +// fontSize = 10.sp, +// color = if (isDuplicatedName == true) Red1 else if (isDuplicatedName == false) PetOrange else Gray1, +// fontWeight = FontWeight.Normal +// ) +// Spacer(modifier = Modifier.height(6.dp)) +// ConnectDogTextField( +// text = viewModel.introduce, +// onTextChanged = viewModel::updateIntroduce, +// placeholder = stringResource(id = R.string.introduce_placeholder), +// height = 130 +// ) +// Spacer(modifier = Modifier.height(20.dp)) +// Spacer(modifier = Modifier.weight(1f)) +// ConnectDogBottomButton( +// content = "다음", +// modifier = Modifier +// .fillMaxWidth() +// .height(56.dp), +// enabled = viewModel.name != "" && viewModel.introduce != "" && viewModel.uri != null, +// onClick = { +// navigateToIntermediatorInfo() +// signUpViewModel.updateIntro(viewModel.introduce) +// signUpViewModel.updateNickname(viewModel.name) +// signUpViewModel.updateInterProfileImage(viewModel.uri!!) +// } +// ) + Spacer(modifier = Modifier.height((imeHeight + 32).dp)) } } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/volunteer/SelectProfileImageScreen.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/volunteer/SelectProfileImageScreen.kt index b529efb04..fef8fcf95 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/volunteer/SelectProfileImageScreen.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/volunteer/SelectProfileImageScreen.kt @@ -1,11 +1,11 @@ package com.kusitms.connectdog.signup.screen.volunteer +import android.annotation.SuppressLint import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -15,85 +15,96 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.kusitms.connectdog.core.designsystem.R +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavBackStackEntry +import com.kusitms.connectdog.core.designsystem.component.ConnectDogBottomButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogNormalButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType import com.kusitms.connectdog.core.designsystem.theme.Orange_40 import com.kusitms.connectdog.core.designsystem.theme.PetOrange import com.kusitms.connectdog.core.util.getProfileImageId -import com.kusitms.connectdog.signup.viewmodel.VolunteerProfileViewModel +import com.kusitms.connectdog.feature.signup.R +import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel +import com.kusitms.connectdog.signup.viewmodel.SelectProfileImageViewModel +import org.orbitmvi.orbit.compose.collectAsState +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter", "ResourceType") @Composable fun SelectProfileImageScreen( onBackClick: () -> Unit, - viewModel: VolunteerProfileViewModel + viewModel: SelectProfileImageViewModel = hiltViewModel(), + signUpViewModel: SignUpViewModel ) { - val focusManager = LocalFocusManager.current - val interactionSource = remember { MutableInteractionSource() } - val selectedImageIndex by viewModel.selectedImageIndex.collectAsState() + val uiState by signUpViewModel.collectAsState() - Box( - modifier = Modifier - .fillMaxSize() - .background(Color.White) - .padding(bottom = 32.dp) - .clickable( - onClick = { focusManager.clearFocus() }, - indication = null, - interactionSource = interactionSource - ) - ) { - Column( - modifier = Modifier - .fillMaxSize() - .background(Color.White) - ) { + LaunchedEffect(key1 = Unit) { + viewModel.updateProfileImageIndex(uiState.profileImageId) + } + + Scaffold( + topBar = { ConnectDogTopAppBar( - titleRes = R.string.volunteer_signup, + titleRes = uiState.userType.topBarTitleRes, navigationType = TopAppBarNavigationType.BACK, - navigationIconContentDescription = "Navigation icon", onNavigationClick = onBackClick ) - Spacer(modifier = Modifier.height(32.dp)) - Text( - text = "프로필 이미지를\n선택해주세요", - fontSize = 20.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(horizontal = 20.dp) - ) - Spacer(modifier = Modifier.height(40.dp)) - ProfileImageGrid(selectedImageIndex, viewModel) } + ) { + Content( + onBackClick = onBackClick, + viewModel = viewModel, + updateProfileImageIndex = signUpViewModel::updateProfileImageIndex + ) + } +} - ConnectDogNormalButton( - content = "선택", - color = if (selectedImageIndex != -1) { - PetOrange - } else { - Orange_40 - }, - modifier = Modifier - .fillMaxWidth() - .height(56.dp) - .align(Alignment.BottomCenter) - .padding(horizontal = 20.dp), +@Composable +private fun Content( + onBackClick: () -> Unit, + viewModel: SelectProfileImageViewModel, + updateProfileImageIndex: (Int) -> Unit +) { + val uiState by viewModel.collectAsState() + + Column( + modifier = Modifier + .fillMaxSize() + .background(Color.White) + .padding(top = 48.dp, bottom = 32.dp) + .padding(horizontal = 20.dp) + ) { + Spacer(modifier = Modifier.height(32.dp)) + Text( + text = stringResource(id = R.string.select_profile_image_title), + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + ) + Spacer(modifier = Modifier.height(40.dp)) + ProfileImageGrid( + selectedImageIndex = uiState.selectedImageId, + updateProfileImageIndex = viewModel::updateProfileImageIndex + ) + Spacer(modifier = Modifier.weight(1f)) + ConnectDogBottomButton( + content = stringResource(id = R.string.select), onClick = { - viewModel.updateProfileImageIndex(selectedImageIndex) + updateProfileImageIndex(uiState.selectedImageId) onBackClick() } ) @@ -103,7 +114,7 @@ fun SelectProfileImageScreen( @Composable fun ProfileImageGrid( selectedImageIndex: Int, - viewModel: VolunteerProfileViewModel + updateProfileImageIndex: (Int) -> Unit ) { val modifier = Modifier .padding(15.dp) @@ -124,16 +135,11 @@ fun ProfileImageGrid( .weight(1f) .clickable( indication = null, - interactionSource = remember { MutableInteractionSource() } - ) { - viewModel.updateProfileImageIndex(index) - } - .then( - if (selectedImageIndex == index) { - modifier.border(4.dp, PetOrange, CircleShape) - } else { - modifier - } + interactionSource = remember { MutableInteractionSource() }, + onClick = { updateProfileImageIndex(index) } + ).then( + if (selectedImageIndex != index) modifier + else modifier.border(4.dp, PetOrange, CircleShape) ) ) } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/volunteer/VolunteerProfileScreen.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/volunteer/VolunteerProfileScreen.kt index c68834f62..038be72ee 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/volunteer/VolunteerProfileScreen.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/screen/volunteer/VolunteerProfileScreen.kt @@ -16,7 +16,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier @@ -26,36 +25,39 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.navigation.NavBackStackEntry +import com.kusitms.connectdog.core.designsystem.component.ConnectDogBottomButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogNormalButton import com.kusitms.connectdog.core.designsystem.component.ConnectDogOutlinedButton -import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextFieldWithButton +import com.kusitms.connectdog.core.designsystem.component.ConnectDogTextField import com.kusitms.connectdog.core.designsystem.component.ConnectDogTopAppBar import com.kusitms.connectdog.core.designsystem.component.TopAppBarNavigationType -import com.kusitms.connectdog.core.designsystem.theme.Gray5 -import com.kusitms.connectdog.core.designsystem.theme.Orange_40 -import com.kusitms.connectdog.core.designsystem.theme.PetOrange import com.kusitms.connectdog.core.designsystem.theme.Red1 import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.core.util.getProfileImageId import com.kusitms.connectdog.feature.signup.R +import com.kusitms.connectdog.signup.state.SignUpSideEffect import com.kusitms.connectdog.signup.viewmodel.SignUpViewModel -import com.kusitms.connectdog.signup.viewmodel.VolunteerProfileViewModel +import org.orbitmvi.orbit.compose.collectAsState +import org.orbitmvi.orbit.compose.collectSideEffect @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable fun VolunteerProfileScreen( onBackClick: () -> Unit, onNavigateToSelectProfileImage: () -> Unit, - onNavigateToCompleteSignUp: (UserType) -> Unit, - userType: UserType, + onNavigateToCompleteSignUp: () -> Unit, imeHeight: Int, - signUpViewModel: SignUpViewModel, - viewModel: VolunteerProfileViewModel + viewModel: SignUpViewModel ) { - val focusManager = LocalFocusManager.current - val interactionSource = remember { MutableInteractionSource() } - val isDuplicatedNickname by viewModel.isDuplicatedNickname.collectAsState() - val selectedImageIndex by viewModel.selectedImageIndex.collectAsState() - val isAvailableNickname by viewModel.isAvailableNickname.collectAsState() + viewModel.collectSideEffect { + when(it) { + is SignUpSideEffect.NavigateToSignUpComplete -> onNavigateToCompleteSignUp() + else -> Unit + } + } Scaffold( topBar = { @@ -67,102 +69,87 @@ fun VolunteerProfileScreen( ) } ) { - Column( - modifier = Modifier - .fillMaxSize() - .background(Color.White) - .padding(horizontal = 20.dp) - .clickable( - onClick = { focusManager.clearFocus() }, - indication = null, - interactionSource = interactionSource - ) + Content( + viewModel = viewModel, + onNavigateToSelectProfileImage = onNavigateToSelectProfileImage, + imeHeight = imeHeight + ) + } +} + +@Composable +private fun Content( + viewModel: SignUpViewModel, + onNavigateToSelectProfileImage: () -> Unit, + imeHeight: Int, +) { + val focusManager = LocalFocusManager.current + val interactionSource = remember { MutableInteractionSource() } + val uiState by viewModel.collectAsState() + + Column( + modifier = Modifier + .fillMaxSize() + .background(Color.White) + .padding(horizontal = 20.dp) + .clickable( + onClick = { focusManager.clearFocus() }, + indication = null, + interactionSource = interactionSource + ) + ) { + Spacer(modifier = Modifier.height(80.dp)) + Text( + text = "프로필 정보를\n입력해주세요", + fontSize = 20.sp, + fontWeight = FontWeight.Bold + ) + Spacer(modifier = Modifier.height(40.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center ) { - Spacer(modifier = Modifier.height(80.dp)) - Text( - text = "프로필 정보를\n입력해주세요", - fontSize = 20.sp, - fontWeight = FontWeight.Bold + Image( + painter = painterResource(id = getProfileImageId(uiState.profileImageId)), + contentDescription = "volunteer profile image" ) - Spacer(modifier = Modifier.height(40.dp)) - Row( - modifier = Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - Image( - painter = painterResource(id = viewModel.getProfileImageId()), - contentDescription = "volunteer profile image" - ) - } - Spacer(modifier = Modifier.height(12.dp)) - Row( - modifier = Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - ConnectDogOutlinedButton( - width = 105, - height = 27, - text = "프로필 사진 선택", - padding = 5, - onClick = onNavigateToSelectProfileImage - ) - } - Spacer(modifier = Modifier.height(40.dp)) - ConnectDogTextFieldWithButton( - text = viewModel.nickname, - width = 62, + } + Spacer(modifier = Modifier.height(12.dp)) + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + ConnectDogOutlinedButton( + width = 105, height = 27, - textFieldLabel = "닉네임", - placeholder = "닉네임 입력", - buttonLabel = "중복 확인", - onClick = { - viewModel.updateNicknameAvailability(it) - }, - onTextChanged = { - viewModel.updateNickname(it) - viewModel.isAvailableNickname() - }, - borderColor = if (isDuplicatedNickname == false) Red1 else if (isDuplicatedNickname == true) PetOrange else Gray5, + text = "프로필 사진 선택", padding = 5, - isError = (isDuplicatedNickname == false) || (isAvailableNickname ?: false) + onClick = onNavigateToSelectProfileImage ) + } + Spacer(modifier = Modifier.height(40.dp)) + ConnectDogTextField( + text = uiState.nickname, + label = "닉네임", + placeholder = "닉네임 입력", + onTextChanged = viewModel::onNickNameChanged, + isError = uiState.isDuplicatedNickname == true + ) + if(uiState.isDuplicatedNickname == true) { Text( - text = isDuplicatedNickname?.let { - if (!it) { "이미 사용중인 닉네임 입니다." } else { "사용할 수 있는 닉네임 입니다." } - } ?: run { "" }, - color = when (isDuplicatedNickname?.not()) { - false -> PetOrange - else -> Red1 - }, + modifier = Modifier.padding(top = 4.dp, start = 8.dp), + text = uiState.nickNameErrorMessage, + color = Red1, fontSize = 11.sp, - modifier = Modifier.padding(top = 4.dp, start = 8.dp) - ) - Spacer(modifier = Modifier.weight(1f)) - ConnectDogNormalButton( - content = "다음", - modifier = - Modifier - .fillMaxWidth() - .height(56.dp), - color = if (selectedImageIndex != -1 && isDuplicatedNickname == true) { PetOrange } else { Orange_40 }, - onClick = { - if (selectedImageIndex != -1 && isDuplicatedNickname == true) { - signUpViewModel.apply { - this.updateNickname(viewModel.nickname) - this.updateProfileImageId(viewModel.selectedImageIndex.value) - when (userType) { - UserType.SOCIAL_VOLUNTEER -> this.postSocialVolunteerSignUp() - UserType.NORMAL_VOLUNTEER -> this.postNormalVolunteerSignUp() - UserType.INTERMEDIATOR -> {} - } - } - onNavigateToCompleteSignUp(userType) - } - } ) - Spacer(modifier = Modifier.height((imeHeight + 32).dp)) } + Spacer(modifier = Modifier.weight(1f)) + ConnectDogBottomButton( + content = "중복 확인", + onClick = viewModel::onCheckNicknameDuplicationButtonClick, + enabled = uiState.enableNicknameDuplication + ) + Spacer(modifier = Modifier.height((imeHeight + 32).dp)) } } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/state/SelectProfileImageUiState.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/state/SelectProfileImageUiState.kt new file mode 100644 index 000000000..62eaa71ed --- /dev/null +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/state/SelectProfileImageUiState.kt @@ -0,0 +1,13 @@ +package com.kusitms.connectdog.signup.state + +data class SelectProfileImageUiState( + val selectedImageId: Int +) { + companion object { + fun empty() = SelectProfileImageUiState( + selectedImageId = 1 + ) + } +} + +sealed class SelectProfileImageSideEffect diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/state/SignUpUiState.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/state/SignUpUiState.kt new file mode 100644 index 000000000..e143e33c6 --- /dev/null +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/state/SignUpUiState.kt @@ -0,0 +1,95 @@ +package com.kusitms.connectdog.signup.state + +import android.net.Uri +import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.core.util.emptyString + +data class SignUpUiState( + val userType: UserType, + val email: String, + val password: String, + val confirmPassword: String, + val isValidPassword: Boolean?, + val isValidConfirmPassword: Boolean?, + val nickname: String, + val nicknameRegex: Regex, + val nickNameErrorMessage: String, + val profileImageId: Int, + val phoneNumber: String, + val phoneAuthCode: String, + val isSendPhoneAuthCode: Boolean, + val isDuplicatedPhoneNumber: Boolean, + val contact: String, + val intro: String, + val url: String, + val name: String, + val intermediatorProfileImage: Uri?, + val phoneCertificationButtonText: String, + val emailCertificationButtonText: String, + val enablePhoneCertification: Boolean, + val enableEmailCertification: Boolean, + val enablePasswordRegister: Boolean, + val enableNicknameDuplication: Boolean, + val isPhoneNumberCertified: Boolean?, + val isSendEmailAuthCode: Boolean, + val inputEmailAuthCode: String, + val emailAuthCode: String, + val isEmailAuthCodeError: Boolean?, + val isValidEmail: Boolean?, + val isAvailableNickName: Boolean, + val isDuplicatedNickname: Boolean?, + val isDuplicatedEmail: Boolean, + val englishAndNumberRegex: Regex, + val englishNumberSpecialRegex: Regex +) { + companion object { + fun empty() = SignUpUiState( + userType = UserType.INTERMEDIATOR, + email = emptyString(), + password = emptyString(), + confirmPassword = emptyString(), + isValidPassword = null, + isValidConfirmPassword = null, + nickname = emptyString(), + nicknameRegex = "^[ㄱ-ㅎ]+$".toRegex(), + nickNameErrorMessage = emptyString(), + profileImageId = 0, + phoneNumber = emptyString(), + phoneAuthCode = emptyString(), + isSendPhoneAuthCode = false, + contact = emptyString(), + intro = emptyString(), + url = emptyString(), + name = emptyString(), + intermediatorProfileImage = null, + phoneCertificationButtonText = "인증 요청", + emailCertificationButtonText = "인증 요청", + enablePhoneCertification = false, + enableEmailCertification = false, + enablePasswordRegister = false, + enableNicknameDuplication = false, + isPhoneNumberCertified = null, + isSendEmailAuthCode = false, + inputEmailAuthCode = emptyString(), + emailAuthCode = emptyString(), + isEmailAuthCodeError = null, + isValidEmail = null, + isAvailableNickName = false, + isDuplicatedNickname = null, + isDuplicatedEmail = false, + isDuplicatedPhoneNumber = false, + englishAndNumberRegex = Regex("^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{10,}$"), + englishNumberSpecialRegex = Regex("^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@#\$%^&+=!])[A-Za-z\\d@#\$%^&+=!]{8,}$") + ) + } +} + +sealed class SignUpSideEffect { + object NavigateToProfile : SignUpSideEffect() + object NavigateToEmailRegister: SignUpSideEffect() + object NavigateToPasswordRegister: SignUpSideEffect() + object NavigateToSignUpComplete: SignUpSideEffect() + object NavigateToVolunteerHome: SignUpSideEffect() + object NavigateToIntermediatorHome: SignUpSideEffect() + object NavigateTo: SignUpSideEffect() +} \ No newline at end of file diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/state/TermsUiState.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/state/TermsUiState.kt new file mode 100644 index 000000000..195950be6 --- /dev/null +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/state/TermsUiState.kt @@ -0,0 +1,48 @@ +package com.kusitms.connectdog.signup.state + +data class CheckBoxDetail( + val title: String, + val isChecked: Boolean, + val hasDetail: Boolean, + val url: String?, +) + +data class TermsUiState( + val agreeAll: CheckBoxDetail, + val termsOfService: CheckBoxDetail, + val privacy: CheckBoxDetail, + val advertisement: CheckBoxDetail, + val enableNext: Boolean, +) { + companion object { + fun empty() = TermsUiState( + agreeAll = CheckBoxDetail( + title = "모두 동의", + isChecked = false, + hasDetail = false, + url = null + ), + termsOfService = CheckBoxDetail( + title = "[필수] 이용약관 동의", + isChecked = false, + hasDetail = true, + url = "https://docs.google.com/document/d/14nF3hzCFfTVGSecKDddO4FJYy27v_c8BUkAU2w_m1O4/edit?usp=sharing" + ), + privacy = CheckBoxDetail( + title = "[필수] 개인정보 수집 및 이용 동의", + isChecked = false, + hasDetail = true, + url = "https://docs.google.com/document/d/14nF3hzCFfTVGSecKDddO4FJYy27v_c8BUkAU2w_m1O4/edit?usp=sharing" + ), + advertisement = CheckBoxDetail( + title = "[선택] 광고성 정보 수신 동의", + isChecked = false, + hasDetail = true, + url = "https://docs.google.com/document/d/14nF3hzCFfTVGSecKDddO4FJYy27v_c8BUkAU2w_m1O4/edit?usp=sharing" + ), + enableNext = false + ) + } +} + +sealed class TermsSideEffect diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/CertificationViewModel.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/CertificationViewModel.kt index fd256b665..b1aa56b8a 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/CertificationViewModel.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/CertificationViewModel.kt @@ -12,7 +12,9 @@ import org.orbitmvi.orbit.viewmodel.container import javax.inject.Inject @HiltViewModel -class CertificationViewModel @Inject constructor() : ContainerHost, ViewModel() { +class CertificationViewModel @Inject constructor( + +) : ContainerHost, ViewModel() { override val container = container(CertificationUiState.empty()) private val state: CertificationUiState get() = container.stateFlow.value diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/IntermediatorProfileViewModel.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/IntermediatorProfileViewModel.kt index 4a80f14ab..a8657f554 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/IntermediatorProfileViewModel.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/IntermediatorProfileViewModel.kt @@ -50,8 +50,8 @@ class IntermediatorProfileViewModel @Inject constructor( name = _name.value ) try { - val response = signUpRepository.isDuplicateInterNickName(body) - _isDuplicateName.value = response.isDuplicated +// val response = signUpRepository.isDuplicateInterNickName(body) +// _isDuplicateName.value = response.isDuplicated } catch (e: Exception) { } } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/RegisterEmailViewModel.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/RegisterEmailViewModel.kt deleted file mode 100644 index 71de8c338..000000000 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/RegisterEmailViewModel.kt +++ /dev/null @@ -1,89 +0,0 @@ -package com.kusitms.connectdog.signup.viewmodel - -import android.content.Context -import android.widget.Toast -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.kusitms.connectdog.core.data.api.model.volunteer.EmailCertificationBody -import com.kusitms.connectdog.core.data.repository.SignUpRepository -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch -import javax.inject.Inject - -@HiltViewModel -class RegisterEmailViewModel @Inject constructor( - private val signUpRepository: SignUpRepository -) : ViewModel() { - private val _isEmailVerified: MutableStateFlow = MutableStateFlow(null) - val isEmailVerified: StateFlow - get() = _isEmailVerified - - private val _isEmailDuplicated: MutableStateFlow = MutableStateFlow(null) - val isEmailDuplicated: StateFlow - get() = _isEmailDuplicated - - private val _isValidEmail: MutableStateFlow = MutableStateFlow(null) - val isValidEmail: StateFlow - get() = _isValidEmail - - private val _email: MutableState = mutableStateOf("") - val email: String - get() = _email.value - - private var postNumber: String = "" - - private val _certificationNumber: MutableState = mutableStateOf("") - val certificationNumber: String - get() = _certificationNumber.value - - fun updateEmail(email: String) { - _email.value = email - } - - fun updateCertificationNumber(certificationNumber: String) { - _certificationNumber.value = certificationNumber - } - - fun updateEmailValidity() { - _isValidEmail.value = !android.util.Patterns.EMAIL_ADDRESS.matcher(_email.value).matches() - } - - fun updateEmailVerify(value: Boolean) { - _isEmailVerified.value = value - } - - fun postEmail(context: Context) = viewModelScope.launch { - if (isValidEmail.value == true) { - Toast.makeText(context, "유효한 이메일을 입력해주세요", Toast.LENGTH_SHORT).show() - return@launch - } - - val body = EmailCertificationBody(_email.value) - try { - val response = signUpRepository.postEmail(body) - Toast.makeText(context, "이메일을 전송했습니다", Toast.LENGTH_SHORT).show() - _isEmailDuplicated.value = false - postNumber = response.authCode - } catch (e: Exception) { - _isEmailDuplicated.value = true - Toast.makeText(context, "이미 가입된 이메일입니다.", Toast.LENGTH_SHORT).show() - } - } - - fun checkCertificationNumber(context: Context) { - if (_certificationNumber.value.isEmpty()) { - Toast.makeText(context, "인증번호를 입력해주세요", Toast.LENGTH_SHORT).show() - } else { - _isEmailVerified.value = _certificationNumber.value == postNumber - if (_isEmailVerified.value == true) { - Toast.makeText(context, "인증이 완료되었습니다", Toast.LENGTH_SHORT).show() - } else if (_isEmailVerified.value == true) { - Toast.makeText(context, "인증에 실패하였습니다", Toast.LENGTH_SHORT).show() - } - } - } -} diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/SelectProfileImageViewModel.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/SelectProfileImageViewModel.kt new file mode 100644 index 000000000..03e7ee887 --- /dev/null +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/SelectProfileImageViewModel.kt @@ -0,0 +1,23 @@ +package com.kusitms.connectdog.signup.viewmodel + +import androidx.lifecycle.ViewModel +import com.kusitms.connectdog.signup.state.SelectProfileImageSideEffect +import com.kusitms.connectdog.signup.state.SelectProfileImageUiState +import dagger.hilt.android.lifecycle.HiltViewModel +import org.orbitmvi.orbit.Container +import org.orbitmvi.orbit.ContainerHost +import org.orbitmvi.orbit.syntax.simple.intent +import org.orbitmvi.orbit.syntax.simple.reduce +import org.orbitmvi.orbit.viewmodel.container +import javax.inject.Inject + +private const val TAG = "VolunteerProfileViewModel" + +@HiltViewModel +class SelectProfileImageViewModel @Inject constructor(): ContainerHost, ViewModel() { + override val container: Container = container(SelectProfileImageUiState.empty()) + private val state: SelectProfileImageUiState + get() = container.stateFlow.value + + fun updateProfileImageIndex(imageIndex: Int) = intent { reduce { state.copy(selectedImageId = imageIndex) } } +} diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/SignUpViewModel.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/SignUpViewModel.kt index a54722e02..e40bf338a 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/SignUpViewModel.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/SignUpViewModel.kt @@ -1,203 +1,347 @@ package com.kusitms.connectdog.signup.viewmodel -import android.content.Context -import android.net.Uri import android.util.Log +import android.util.Patterns import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.kusitms.connectdog.core.data.api.model.IsDuplicatePhoneNumberBody -import com.kusitms.connectdog.core.data.api.model.NormalLoginBody -import com.kusitms.connectdog.core.data.api.model.SocialLoginBody -import com.kusitms.connectdog.core.data.api.model.intermediator.IntermediatorSignUpBody -import com.kusitms.connectdog.core.data.api.model.volunteer.NormalVolunteerSignUpBody -import com.kusitms.connectdog.core.data.api.model.volunteer.SocialVolunteerSignUpBody -import com.kusitms.connectdog.core.data.repository.DataStoreRepository -import com.kusitms.connectdog.core.data.repository.LoginRepository -import com.kusitms.connectdog.core.data.repository.SignUpRepository -import com.kusitms.connectdog.core.util.AppMode -import com.kusitms.connectdog.core.util.ImageConverter import com.kusitms.connectdog.core.util.UserType +import com.kusitms.connectdog.domain.usecase.auth.GetEmailAuthCodeUseCase +import com.kusitms.connectdog.domain.usecase.auth.GetIntermediatorPhoneNumberDuplicationUseCase +import com.kusitms.connectdog.domain.usecase.auth.GetVolunteerPhoneNumberDuplicationUseCase +import com.kusitms.connectdog.domain.usecase.login.AppMode +import com.kusitms.connectdog.domain.usecase.login.SocialLoginUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateAccessTokenUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateAppModeUseCase +import com.kusitms.connectdog.domain.usecase.login.UpdateRefreshTokenUseCase +import com.kusitms.connectdog.domain.usecase.login.VolunteerLoginUseCase +import com.kusitms.connectdog.domain.usecase.signup.GetIntermediatorNameDuplication +import com.kusitms.connectdog.domain.usecase.signup.GetSocialProviderUseCase +import com.kusitms.connectdog.domain.usecase.signup.GetSocialTokenUseCase +import com.kusitms.connectdog.domain.usecase.signup.GetVolunteerNicknameDuplication +import com.kusitms.connectdog.domain.usecase.signup.InitNormalVolunteerSignUpUseCase +import com.kusitms.connectdog.domain.usecase.signup.InitSocialVolunteerSignUpUseCase +import com.kusitms.connectdog.signup.state.SignUpSideEffect +import com.kusitms.connectdog.signup.state.SignUpUiState import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch +import org.orbitmvi.orbit.Container +import org.orbitmvi.orbit.ContainerHost +import org.orbitmvi.orbit.syntax.simple.intent +import org.orbitmvi.orbit.syntax.simple.postSideEffect +import org.orbitmvi.orbit.syntax.simple.reduce +import org.orbitmvi.orbit.viewmodel.container import javax.inject.Inject private const val TAG = "SignUpViewModel" @HiltViewModel class SignUpViewModel @Inject constructor( - private val signupRepository: SignUpRepository, - private val loginRepository: LoginRepository, - private val dataStoreRepository: DataStoreRepository -) : ViewModel() { - private val _email = MutableStateFlow("") - private val _password = MutableStateFlow("") - private val _nickname = MutableStateFlow("") - private val _profileImageId = MutableStateFlow(null) - private val _phoneNumber = MutableStateFlow("") - private val _contact = MutableStateFlow("") - private val _intro = MutableStateFlow("") - private val _url = MutableStateFlow("") - private val _name = MutableStateFlow("") - private val _interProfileImage = MutableStateFlow(null) + private val getVolunteerPhoneNumberDuplicationUseCase: GetVolunteerPhoneNumberDuplicationUseCase, + private val getIntermediatorPhoneNumberDuplicationUseCase: GetIntermediatorPhoneNumberDuplicationUseCase, + private val getEmailAuthCodeUseCase: GetEmailAuthCodeUseCase, + private val getNicknameDuplicationUseCase: GetVolunteerNicknameDuplication, + private val getIntermediatorNameDuplicationUseCase: GetIntermediatorNameDuplication, + private val initNormalVolunteerSignUpUseCase: InitNormalVolunteerSignUpUseCase, + private val initSocialVolunteerSignUpUseCase: InitSocialVolunteerSignUpUseCase, + private val volunteerLoginUseCase: VolunteerLoginUseCase, + private val socialLoginUseCase: SocialLoginUseCase, + private val updateAccessTokenUseCase: UpdateAccessTokenUseCase, + private val updateRefreshTokenUseCase: UpdateRefreshTokenUseCase, + private val updateAppModeUseCase: UpdateAppModeUseCase, + private val getSocialTokenUseCase: GetSocialTokenUseCase, + private val getSocialProviderUseCase: GetSocialProviderUseCase, +) : ContainerHost, ViewModel() { + override val container: Container = + container(SignUpUiState.empty()) + private val state: SignUpUiState + get() = container.stateFlow.value - val isDuplicatePhoneNumber = MutableSharedFlow() + fun updateUserType(userType: UserType) = intent { + reduce { state.copy(userType = userType) } + } + + /*이름, 휴대폰 번호 인증*/ + fun onNameChanged(name: String) = intent { + reduce { state.copy(name = name) } + enableSendPhoneAuthCodeButton() + } - fun updateEmail(email: String) { - _email.value = email + fun onPhoneNumberChanged(phoneNumber: String) = intent { + if (phoneNumber.length <= 11) reduce { state.copy(phoneNumber = phoneNumber) } + enableSendPhoneAuthCodeButton() } - fun updatePassword(password: String) { - _password.value = password + fun onPhoneAuthCodeChanged(authCode: String) { + if (authCode.length <= 6) intent { reduce { state.copy(phoneAuthCode = authCode) } } + enableSendPhoneAuthCodeButton() } - fun updateNickname(nickname: String) { - _nickname.value = nickname + fun onPhoneCertificationButtonClick( + onSendMessageClick: (String) -> Unit, + onVerifyCodeClick: (String, (Boolean) -> Unit) -> Unit, + ) { + if (!state.isSendPhoneAuthCode) { + when (state.userType) { + UserType.INTERMEDIATOR -> getIntermediatorPhoneNumberDuplication() + else -> getVolunteerPhoneNumberDuplication() + } + if (!state.isDuplicatedPhoneNumber) sendPhoneAuthCode(onSendMessageClick) + else intent { postSideEffect(SignUpSideEffect.NavigateTo) } + } else checkPhoneAuthCode(onVerifyCodeClick, state.userType) } - fun updateProfileImageId(profileImageId: Int) { - _profileImageId.value = profileImageId + private fun getVolunteerPhoneNumberDuplication() = viewModelScope.launch { + getVolunteerPhoneNumberDuplicationUseCase( + phone = state.phoneNumber + ).onSuccess { + intent { reduce { state.copy(isDuplicatedPhoneNumber = it.isDuplicated) } } + }.onFailure { + + } } - fun updateName(name: String) { - _name.value = name + private fun getIntermediatorPhoneNumberDuplication() = viewModelScope.launch { + getIntermediatorPhoneNumberDuplicationUseCase( + phone = state.phoneNumber + ).onSuccess { + intent { reduce { state.copy(isDuplicatedPhoneNumber = it.isDuplicated) } } + }.onFailure { + + } } - fun updateIntro(intro: String) { - _intro.value = intro + private fun sendPhoneAuthCode(sendMessage: (String) -> Unit) { + sendMessage(state.phoneNumber) + intent { + reduce { + state.copy( + isSendPhoneAuthCode = true, + enablePhoneCertification = false + ) + } + } + updatePhoneCertificationButtonText() } - fun updateUrl(url: String) { - _url.value = url + private fun enableSendPhoneAuthCodeButton() = intent { + if (!state.isSendPhoneAuthCode && state.phoneNumber.length == 11 && state.name.isNotEmpty()) { + reduce { state.copy(enablePhoneCertification = true) } + } else if (state.isSendPhoneAuthCode && state.phoneAuthCode.length == 6) { + reduce { state.copy(enablePhoneCertification = true) } + } else { + reduce { state.copy(enablePhoneCertification = false) } + } } - fun updateContact(contact: String) { - _contact.value = contact + private fun checkPhoneAuthCode( + onVerifyCodeClick: (String, (Boolean) -> Unit) -> Unit, + userType: UserType, + ) { +// onVerifyCodeClick(state.phoneAuthCode) { isCertified -> +// intent { reduce { state.copy(isPhoneNumberCertified = isCertified) } } +// if (isCertified) intent { +// when(userType) { +// UserType.SOCIAL_VOLUNTEER -> postSideEffect(SignUpSideEffect.NavigateToProfile) +// else -> postSideEffect(SignUpSideEffect.NavigateToEmailRegister) +// } +// } +// } + intent { + when (userType) { + UserType.SOCIAL_VOLUNTEER -> postSideEffect(SignUpSideEffect.NavigateToProfile) + else -> postSideEffect(SignUpSideEffect.NavigateToEmailRegister) + } + } } - fun updatePhoneNumber(phone: String) { - _phoneNumber.value = phone + private fun updatePhoneCertificationButtonText() = + intent { reduce { state.copy(phoneCertificationButtonText = "인증 확인") } } + + /*이메일 인증*/ + fun onEmailChanged(email: String) = intent { + reduce { state.copy(email = email) } + checkValidEmail() + enableEmailCertification() } - fun updateInterProfileImage(uri: Uri) { - _interProfileImage.value = uri + fun onEmailAuthCodeChanged(authCode: String) = intent { + if (authCode.length <= 8) reduce { state.copy(inputEmailAuthCode = authCode) } + enableEmailCertification() } - fun postNormalVolunteerSignUp() = viewModelScope.launch { - val body = NormalVolunteerSignUpBody( - name = _name.value, - phone = _phoneNumber.value, - email = _email.value, - nickname = _nickname.value, - password = _password.value, - profileImageNum = _profileImageId.value!! - ) - try { - signupRepository.postNormalVolunteerSignUp(body) - } catch (e: Exception) { - Log.d(TAG, e.message.toString()) + private fun enableEmailCertification() = intent { + if (!state.isSendEmailAuthCode && state.isValidEmail == true) reduce { + state.copy(enableEmailCertification = true) + } + else if (state.isSendEmailAuthCode && state.inputEmailAuthCode.length == 8) reduce { + state.copy(enableEmailCertification = true) } + else reduce { state.copy(enableEmailCertification = false) } } - fun setAutoLogin(appMode: AppMode, userType: UserType) = viewModelScope.launch { - val body = NormalLoginBody( - email = _email.value, - password = _password.value - ) - val socialBody = SocialLoginBody( - accessToken = dataStoreRepository.socialTokenFlow.first()!!, - provider = dataStoreRepository.socialProviderFlow.first()!! - ) - try { - when (userType) { - UserType.SOCIAL_VOLUNTEER -> { - val response = loginRepository.postSocialLoginData(socialBody) - dataStoreRepository.apply { - saveAppMode(appMode) - saveAccessToken(response.accessToken) - saveRefreshToken(response.refreshToken) - } - } + fun onEmailCertificationButtonClick() { + if (!state.isSendEmailAuthCode) getEmailAuthCode() + else checkEmailAuthCode() + } - UserType.NORMAL_VOLUNTEER -> { - val response = loginRepository.postLoginData(body) - dataStoreRepository.apply { - saveAppMode(appMode) - saveAccessToken(response.accessToken) - saveRefreshToken(response.refreshToken) - } - } + private fun checkEmailAuthCode() = intent { + reduce { state.copy(isEmailAuthCodeError = state.inputEmailAuthCode != state.emailAuthCode) } + if (state.isEmailAuthCodeError == false) postSideEffect(SignUpSideEffect.NavigateToPasswordRegister) + } + + private fun checkValidEmail() = intent { + reduce { state.copy(isValidEmail = Patterns.EMAIL_ADDRESS.matcher(state.email).matches()) } + } - UserType.INTERMEDIATOR -> { - val response = loginRepository.postIntermediatorLoginData(body) - dataStoreRepository.apply { - saveAppMode(appMode) - saveAccessToken(response.accessToken) - saveRefreshToken(response.refreshToken) - } + private fun getEmailAuthCode() = viewModelScope.launch { + getEmailAuthCodeUseCase( + email = state.email + ).onSuccess { + intent { + reduce { + state.copy( + emailAuthCode = it.authCode, + isSendEmailAuthCode = true, + enableEmailCertification = false + ) } } - } catch (e: Exception) { - Log.d("asdftt", e.toString()) + updateEmailCertificationButtonText() } } - fun postSocialVolunteerSignUp() { - val body = SocialVolunteerSignUpBody( - nickname = _nickname.value, - profileImageNum = _profileImageId.value!!, - name = _name.value, - phone = _phoneNumber.value - ) + private fun updateEmailCertificationButtonText() = + intent { reduce { state.copy(emailCertificationButtonText = "인증 확인") } } - viewModelScope.launch { - try { - signupRepository.postSocialVolunteerSignUp(body) - } catch (e: Exception) { - Log.d("tesqz", e.message.toString()) - } + /*비밀번호 등록*/ + fun onPasswordChanged(password: String) = intent { + reduce { state.copy(password = password) } + checkPasswordValidity() + enablePasswordRegisterButton() + } + + fun onConfirmPasswordChanged(password: String) = intent { + reduce { state.copy(confirmPassword = password) } + checkConfirmPasswordValidity() + enablePasswordRegisterButton() + } + + fun onPasswordRegisterNextButtonClick() = intent { + when (state.userType) { + UserType.INTERMEDIATOR -> Unit + else -> postSideEffect(SignUpSideEffect.NavigateToProfile) + } + } + + private fun enablePasswordRegisterButton() = intent { + reduce { state.copy(enablePasswordRegister = (state.isValidPassword == true && state.isValidConfirmPassword == true)) } + } + + private fun checkPasswordValidity() = intent { + reduce { + state.copy( + isValidPassword = state.englishAndNumberRegex.matches(state.password) + || state.englishNumberSpecialRegex.matches(state.password) + ) } } - fun postIntermediatorSignUp(context: Context) { - val body = IntermediatorSignUpBody( - email = _email.value, - password = _password.value, - realName = _name.value, - isOptionAgr = true, - intro = _intro.value, - url = _url.value, - contact = _contact.value, - phone = _phoneNumber.value, - name = _nickname.value - ) + private fun checkConfirmPasswordValidity() = intent { + reduce { state.copy(isValidConfirmPassword = state.password == state.confirmPassword) } + } + + /*닉네임*/ + fun onNickNameChanged(nickname: String) = intent { + if (nickname.length <= 12) reduce { state.copy(nickname = nickname) } + isAvailableNickname() + enableNicknameDuplicationButton() + } - val file = ImageConverter.uriToFile(context, _interProfileImage.value!!, 80) + private fun isAvailableNickname() { + intent { + reduce { state.copy(isAvailableNickName = !state.nicknameRegex.matches(state.nickname)) } + } + } - viewModelScope.launch { - try { - signupRepository.postIntermediatorSignUp(body, file!!) - } catch (e: Exception) { - Log.d("SignUpViewModel", e.message.toString()) + fun onCheckNicknameDuplicationButtonClick() = viewModelScope.launch { + getNicknameDuplicationUseCase(state.nickname).onSuccess { + intent { reduce { state.copy(isDuplicatedNickname = it.isDuplicated) } } + when (state.userType) { + UserType.NORMAL_VOLUNTEER -> initNormalVolunteerSignUp() + UserType.SOCIAL_VOLUNTEER -> initSocialVolunteerSignUp() + else -> Unit } } } - fun checkIsDuplicatePhoneNumber(userType: UserType, phoneNumber: String) = - viewModelScope.launch { - val body = IsDuplicatePhoneNumberBody(phone = phoneNumber) - when (userType) { - UserType.INTERMEDIATOR -> { - val response = signupRepository.getInterMediatorPhoneNumberDuplicated(body) - isDuplicatePhoneNumber.emit(response.isDuplicated) - } + fun updateProfileImageIndex(index: Int) = + intent { reduce { state.copy(profileImageId = index) } } - else -> { - val response = signupRepository.getVolunteerPhoneNumberDuplicated(body) - isDuplicatePhoneNumber.emit(response.isDuplicated) - } - } + private fun enableNicknameDuplicationButton() = intent { + if (state.nickname.length >= 2 && state.isAvailableNickName) reduce { + state.copy( + enableNicknameDuplication = true + ) + } + else reduce { state.copy(enableNicknameDuplication = false) } + } + + private fun getNameDuplication() = viewModelScope.launch { + getIntermediatorNameDuplicationUseCase(state.name).onSuccess { + + } + } + + private fun initNormalVolunteerSignUp() = viewModelScope.launch { + initNormalVolunteerSignUpUseCase( + email = state.email, + password = state.password, + nickname = state.nickname, + profileImageNum = state.profileImageId, + phone = state.phoneNumber, + name = state.name + ).onSuccess { + intent { postSideEffect(SignUpSideEffect.NavigateToSignUpComplete) } + }.onFailure { + Log.d("asdf", it.toString()) + } + } + + private fun initSocialVolunteerSignUp() = viewModelScope.launch { + initSocialVolunteerSignUpUseCase( + email = state.email, + password = state.password, + nickname = state.nickname, + profileImageNum = state.profileImageId, + phone = state.phoneNumber, + name = state.name + ).onSuccess { + setSocialVolunteerLogin() + }.onFailure { + + } + } + + fun initIntermediatorSignUp() = viewModelScope.launch { + + } + + fun onStartClick() = when (state.userType) { + UserType.NORMAL_VOLUNTEER -> setNormalVolunteerLogin() + UserType.SOCIAL_VOLUNTEER -> setSocialVolunteerLogin() + UserType.INTERMEDIATOR -> setSocialVolunteerLogin() + } + + private fun setNormalVolunteerLogin() = viewModelScope.launch { + volunteerLoginUseCase(state.email, state.password).onSuccess { + updateAccessTokenUseCase(it.accessToken) + updateRefreshTokenUseCase(it.refreshToken) + updateAppModeUseCase(AppMode.VOLUNTEER) + intent { postSideEffect(SignUpSideEffect.NavigateToSignUpComplete) } } + } + + private fun setSocialVolunteerLogin() = viewModelScope.launch { +// + } } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/TermsViewModel.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/TermsViewModel.kt index 4636a83af..4b2fda225 100644 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/TermsViewModel.kt +++ b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/TermsViewModel.kt @@ -1,64 +1,65 @@ package com.kusitms.connectdog.signup.viewmodel -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import com.kusitms.connectdog.signup.state.TermsSideEffect +import com.kusitms.connectdog.signup.state.TermsUiState import dagger.hilt.android.lifecycle.HiltViewModel +import org.orbitmvi.orbit.Container +import org.orbitmvi.orbit.ContainerHost +import org.orbitmvi.orbit.syntax.simple.intent +import org.orbitmvi.orbit.syntax.simple.reduce +import org.orbitmvi.orbit.viewmodel.container import javax.inject.Inject @HiltViewModel -class TermsViewModel @Inject constructor() : ViewModel() { - private val _allChecked = MutableLiveData(false) - val allChecked: LiveData = _allChecked +class TermsViewModel @Inject constructor() : ContainerHost, + ViewModel() { + override val container: Container = + container(TermsUiState.empty()) + private val state: TermsUiState + get() = container.stateFlow.value - private val _termsChecked = MutableLiveData(false) - val termsChecked: LiveData = _termsChecked - - private val _privacyChecked = MutableLiveData(false) - val privacyChecked: LiveData = _privacyChecked - - private val _advertisementChecked = MutableLiveData(false) - val advertisementChecked: LiveData = _advertisementChecked - - private val _isAvailableNext = MutableLiveData(false) - val isAvailableNext: LiveData - get() = _isAvailableNext - - fun updateAllChecked() { - _allChecked.value = !_allChecked.value!! - _termsChecked.value = !_allChecked.value!! - _privacyChecked.value = !_allChecked.value!! - _advertisementChecked.value = !_allChecked.value!! - } - - fun updateTermsChecked() { - _termsChecked.value = !_termsChecked.value!! - updateAllCheckedState() - isAvailableNext() + fun onAgreeAllClick() = intent { + reduce { + state.copy( + agreeAll = state.agreeAll.copy(isChecked = !state.agreeAll.isChecked), + termsOfService = state.termsOfService.copy(isChecked = !state.agreeAll.isChecked), + privacy = state.privacy.copy(isChecked = !state.agreeAll.isChecked), + advertisement = state.advertisement.copy(isChecked = !state.agreeAll.isChecked), + ) + } + enableNext() } - fun updatePrivacyChecked() { - _privacyChecked.value = !_privacyChecked.value!! - updateAllCheckedState() - isAvailableNext() + fun onTermsOfServiceClick() = intent { + reduce { state.copy(termsOfService = state.termsOfService.copy(isChecked = !state.termsOfService.isChecked)) } + updateAllAgree() + enableNext() } - fun updateAdvertisementChecked() { - _advertisementChecked.value = !_advertisementChecked.value!! - updateAllCheckedState() + fun onPrivacyClick() = intent { + reduce { state.copy(privacy = state.privacy.copy(isChecked = !state.privacy.isChecked)) } + updateAllAgree() + enableNext() } - private fun updateAllCheckedState() { - _allChecked.value = _termsChecked.value == true && _privacyChecked.value == true && _advertisementChecked.value == true + fun onAdvertisementClick() = intent { + reduce { state.copy(advertisement = state.advertisement.copy(isChecked = !state.advertisement.isChecked)) } + updateAllAgree() + enableNext() } - private fun isAvailableNext() { - _isAvailableNext.value = _termsChecked.value == true && _privacyChecked.value == true + private fun updateAllAgree() = intent { + reduce { + state.copy( + agreeAll = state.agreeAll.copy( + isChecked = state.termsOfService.isChecked && state.privacy.isChecked && state.advertisement.isChecked + ) + ) + } } - fun resetState() { - _allChecked.value = false - _privacyChecked.value = false - _termsChecked.value = false + private fun enableNext() = intent { + reduce { state.copy(enableNext = state.termsOfService.isChecked && state.privacy.isChecked) } } } diff --git a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/VolunteerProfileViewModel.kt b/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/VolunteerProfileViewModel.kt deleted file mode 100644 index 0e9ea6fe0..000000000 --- a/feature/signup/src/main/java/com/kusitms/connectdog/signup/viewmodel/VolunteerProfileViewModel.kt +++ /dev/null @@ -1,73 +0,0 @@ -package com.kusitms.connectdog.signup.viewmodel - -import android.util.Log -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.kusitms.connectdog.core.data.api.model.volunteer.IsDuplicateNicknameBody -import com.kusitms.connectdog.core.data.repository.SignUpRepository -import com.kusitms.connectdog.core.util.getProfileImageId -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch -import javax.inject.Inject - -private const val TAG = "VolunteerProfileViewModel" - -@HiltViewModel -class VolunteerProfileViewModel @Inject constructor( - private val signupRepository: SignUpRepository -) : ViewModel() { - private val _selectedImageIndex = MutableStateFlow(-1) - val selectedImageIndex: StateFlow - get() = _selectedImageIndex - - private val _isDuplicatedNickname: MutableStateFlow = MutableStateFlow(null) - val isDuplicatedNickname: StateFlow - get() = _isDuplicatedNickname - - private val _isAvailableNickname: MutableStateFlow = MutableStateFlow(null) - val isAvailableNickname: StateFlow - get() = _isAvailableNickname - - private val _nickname: MutableState = mutableStateOf("") - val nickname: String - get() = _nickname.value - - fun isAvailableNickname() { - val regex = Regex("[가-힣0-9]+") - _isAvailableNickname.value = !regex.matches(_nickname.value) - Log.d("taswa", _isAvailableNickname.value.toString()) - } - - fun updateNicknameAvailability(nickname: String) { - val nicknameBody = IsDuplicateNicknameBody(nickname = nickname) - viewModelScope.launch { - try { - val response = signupRepository.postNickname(nicknameBody) - Log.d(TAG, response.toString()) - _isDuplicatedNickname.value = !response.isDuplicated - } catch (e: Exception) { - Log.d(TAG, e.message.toString()) - } - } - } - - fun updateProfileImageIndex(imageIndex: Int) { - _selectedImageIndex.value = imageIndex - } - - fun updateNickname(nickname: String) { - _nickname.value = nickname - } - - fun getProfileImageId(): Int { - return if (_selectedImageIndex.value == -1) { - com.kusitms.connectdog.core.designsystem.R.drawable.ic_circle - } else { - getProfileImageId(_selectedImageIndex.value) - } - } -} diff --git a/feature/signup/src/main/res/values/string.xml b/feature/signup/src/main/res/values/string.xml index 46fba4197..bea7f24b7 100644 --- a/feature/signup/src/main/res/values/string.xml +++ b/feature/signup/src/main/res/values/string.xml @@ -3,12 +3,40 @@ 이동봉사자 회원가입 이동봉사 모집자 회원가입 + + 다음 + + 이름 + 이름 입력 휴대폰 번호 인증을\n진행해 주세요 휴대폰 번호 + \'-\'빼고 입력 + 인증번호 + 숫자 6자리 + 인증번호 입력 + 인증번호가 일치하지 않습니다. + 인증번호가 오지 않는다면? + 재발송 + 한 줄 소개 한 줄 소개 입력 모집자명 모집자명 입력 + + + 이메일 + 이메일 입력 + 로그인에 사용할\n이메일 입력해주라 + + + 로그인에 사용할\n비밀번호를 입력해주세요 + 비밀번호 + 비밀번호 입력 + 비밀번호 확인 + 영문+숫자 10자 이상 또는 영문+숫자+특수기호 8자 이상 + + 프로필 이미지를\n선택해주세요 + 선택 \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 3c5031eb7..6920c05bd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,4 +20,5 @@ kotlin.code.style=official # Enables namespacing of each library's R class so that its R class includes only the # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library -android.nonTransitiveRClass=true \ No newline at end of file +android.nonTransitiveRClass=true +android.defaults.buildfeatures.buildconfig=true \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ec44bbd4a..c54693be7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,6 +15,8 @@ androidxComposeMaterial = "1.5.4" androidxComposeFoundation = "1.5.4" androidxSplash = "1.0.0-beta02" androidxDataStore = "1.0.0" +kotlinxCoroutines = "1.7.2" + hilt = "2.46.1" hiltNavigationCompose = "1.0.0" accompanistPager = "0.20.1" @@ -63,6 +65,7 @@ androidx-lifecycle-viewModelKtx = { group = "androidx.lifecycle", name = "lifecy androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "androidxActivity" } androidx-core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "androidxSplash" } androidx-datastore = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "androidxDataStore" } +kotlinx-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" } androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "androidxComposeBom" } androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 69dbdd5b0..6312a2ea2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,16 +17,21 @@ dependencyResolutionManagement { } rootProject.name = "ConnectDog" +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") + include(":app") + +include(":domain") + include(":core:data") include(":core:model") include(":core:designsystem") +include(":core:util") + +include(":feature:intermediator") +include(":feature:signup") include(":feature:main") include(":feature:home") include(":feature:login") include(":feature:management") include(":feature:mypage") -include(":core:util") -include(":feature:intermediator") -include(":feature:signup") -include(":domain")