diff --git a/app/src/main/java/org/sopt/pingle/data/datasource/local/PingleLocalDataSource.kt b/app/src/main/java/org/sopt/pingle/data/datasource/local/PingleLocalDataSource.kt index 785b3440..b83ed88f 100644 --- a/app/src/main/java/org/sopt/pingle/data/datasource/local/PingleLocalDataSource.kt +++ b/app/src/main/java/org/sopt/pingle/data/datasource/local/PingleLocalDataSource.kt @@ -5,5 +5,7 @@ interface PingleLocalDataSource { var userName: String var accessToken: String var refreshToken: String + var groupId: Int + var groupName: String fun clear(): Unit } diff --git a/app/src/main/java/org/sopt/pingle/data/datasource/remote/JoinGroupRemoteDataSource.kt b/app/src/main/java/org/sopt/pingle/data/datasource/remote/JoinGroupRemoteDataSource.kt new file mode 100644 index 00000000..67ce4a0d --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/datasource/remote/JoinGroupRemoteDataSource.kt @@ -0,0 +1,14 @@ +package org.sopt.pingle.data.datasource.remote + +import org.sopt.pingle.data.model.remote.request.RequestJoinGroupCodeDto +import org.sopt.pingle.data.model.remote.response.ResponseJoinGroupCodeDto +import org.sopt.pingle.data.model.remote.response.ResponseJoinGroupInfoDto +import org.sopt.pingle.util.base.BaseResponse + +interface JoinGroupRemoteDataSource { + suspend fun getJoinGroupInfo(teamId: Int): BaseResponse + suspend fun postJoinGroupCode( + teamId: Int, + requestJoinGroupCode: RequestJoinGroupCodeDto + ): BaseResponse +} diff --git a/app/src/main/java/org/sopt/pingle/data/datasourceimpl/local/PingleLocalDataSourceImpl.kt b/app/src/main/java/org/sopt/pingle/data/datasourceimpl/local/PingleLocalDataSourceImpl.kt index d08a0f80..37b9e3bd 100644 --- a/app/src/main/java/org/sopt/pingle/data/datasourceimpl/local/PingleLocalDataSourceImpl.kt +++ b/app/src/main/java/org/sopt/pingle/data/datasourceimpl/local/PingleLocalDataSourceImpl.kt @@ -47,6 +47,14 @@ class PingleLocalDataSourceImpl @Inject constructor( get() = pref.getString(REFRESH_TOKEN, "") ?: "" set(value) = pref.edit { putString(REFRESH_TOKEN, value) } + override var groupId: Int + get() = pref.getInt(GROUP_ID, -1) + set(value) = pref.edit { putInt(GROUP_ID, value) } + + override var groupName: String + get() = pref.getString(GROUP_NAME, "") ?: "" + set(value) = pref.edit { putString(GROUP_NAME, value) } + override fun clear() { pref.edit { clear() @@ -59,5 +67,7 @@ class PingleLocalDataSourceImpl @Inject constructor( const val USER_NAME = "UserName" const val ACCESS_TOKEN = "AccessToken" const val REFRESH_TOKEN = "RefreshToken" + const val GROUP_ID = "GroupId" + const val GROUP_NAME = "GroupName" } } diff --git a/app/src/main/java/org/sopt/pingle/data/datasourceimpl/remote/JoinGroupRemoteDataSourceImpl.kt b/app/src/main/java/org/sopt/pingle/data/datasourceimpl/remote/JoinGroupRemoteDataSourceImpl.kt new file mode 100644 index 00000000..3bc8ab12 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/datasourceimpl/remote/JoinGroupRemoteDataSourceImpl.kt @@ -0,0 +1,25 @@ +package org.sopt.pingle.data.datasourceimpl.remote + +import javax.inject.Inject +import org.sopt.pingle.data.datasource.remote.JoinGroupRemoteDataSource +import org.sopt.pingle.data.model.remote.request.RequestJoinGroupCodeDto +import org.sopt.pingle.data.model.remote.response.ResponseJoinGroupCodeDto +import org.sopt.pingle.data.model.remote.response.ResponseJoinGroupInfoDto +import org.sopt.pingle.data.service.JoinGroupService +import org.sopt.pingle.util.base.BaseResponse + +class JoinGroupRemoteDataSourceImpl @Inject constructor( + private val joinGroupService: JoinGroupService +) : JoinGroupRemoteDataSource { + override suspend fun getJoinGroupInfo(teamId: Int): BaseResponse = + joinGroupService.getJoinGroupInfo(teamId = teamId) + + override suspend fun postJoinGroupCode( + teamId: Int, + requestJoinGroupCode: RequestJoinGroupCodeDto + ): BaseResponse = + joinGroupService.postJoinGroupCode( + teamId = teamId, + requestJoinGroupCode = requestJoinGroupCode + ) +} diff --git a/app/src/main/java/org/sopt/pingle/data/mapper/RequestJoinGroupCodeEntityMapper.kt b/app/src/main/java/org/sopt/pingle/data/mapper/RequestJoinGroupCodeEntityMapper.kt new file mode 100644 index 00000000..d23e6fee --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/mapper/RequestJoinGroupCodeEntityMapper.kt @@ -0,0 +1,8 @@ +package org.sopt.pingle.data.mapper + +import org.sopt.pingle.data.model.remote.request.RequestJoinGroupCodeDto +import org.sopt.pingle.domain.model.RequestJoinGroupCodeEntity + +fun RequestJoinGroupCodeEntity.toRequestJoinGroupCode() = RequestJoinGroupCodeDto( + code = code +) diff --git a/app/src/main/java/org/sopt/pingle/data/model/remote/request/RequestJoinGroupCodeDto.kt b/app/src/main/java/org/sopt/pingle/data/model/remote/request/RequestJoinGroupCodeDto.kt new file mode 100644 index 00000000..08bab328 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/model/remote/request/RequestJoinGroupCodeDto.kt @@ -0,0 +1,10 @@ +package org.sopt.pingle.data.model.remote.request + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class RequestJoinGroupCodeDto( + @SerialName("code") + val code: String +) diff --git a/app/src/main/java/org/sopt/pingle/data/model/remote/response/ResponseJoinGroupCodeDto.kt b/app/src/main/java/org/sopt/pingle/data/model/remote/response/ResponseJoinGroupCodeDto.kt index b5032ef6..d6c8523e 100644 --- a/app/src/main/java/org/sopt/pingle/data/model/remote/response/ResponseJoinGroupCodeDto.kt +++ b/app/src/main/java/org/sopt/pingle/data/model/remote/response/ResponseJoinGroupCodeDto.kt @@ -1,34 +1,18 @@ package org.sopt.pingle.data.model.remote.response import kotlinx.serialization.SerialName -import org.sopt.pingle.domain.model.JoinGroupCodeEntity +import kotlinx.serialization.Serializable +import org.sopt.pingle.domain.model.ResponseJoinGroupCodeEntity +@Serializable data class ResponseJoinGroupCodeDto( - @SerialName("code") - val code: Int, - @SerialName("message") - val message: String, - @SerialName("data") - val data: Data + @SerialName("id") + val id: Int, + @SerialName("name") + val name: String ) { - data class Data( - @SerialName("id") - val id: Int, - @SerialName("keyword") - val keyword: String, - @SerialName("name") - val name: String, - @SerialName("meetingCount") - val meetingCount: Int, - @SerialName("participantCount") - val participantCount: Int - ) { - fun toJoinGroupCodeEntity() = JoinGroupCodeEntity( - id = this.id, - keyword = this.keyword, - name = this.name, - meetingCount = this.meetingCount, - participantCount = this.participantCount - ) - } + fun toResponseJoinGroupCode() = ResponseJoinGroupCodeEntity( + id = id, + name = name + ) } diff --git a/app/src/main/java/org/sopt/pingle/data/model/remote/response/ResponseJoinGroupInfoDto.kt b/app/src/main/java/org/sopt/pingle/data/model/remote/response/ResponseJoinGroupInfoDto.kt new file mode 100644 index 00000000..608ccf4b --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/model/remote/response/ResponseJoinGroupInfoDto.kt @@ -0,0 +1,27 @@ +package org.sopt.pingle.data.model.remote.response + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import org.sopt.pingle.domain.model.JoinGroupInfoEntity + +@Serializable +data class ResponseJoinGroupInfoDto( + @SerialName("id") + val id: Int, + @SerialName("keyword") + val keyword: String, + @SerialName("name") + val name: String, + @SerialName("meetingCount") + val meetingCount: Int, + @SerialName("participantCount") + val participantCount: Int +) { + fun toJoinGroupCodeEntity() = JoinGroupInfoEntity( + id = this.id, + keyword = this.keyword, + name = this.name, + meetingCount = this.meetingCount, + participantCount = this.participantCount + ) +} diff --git a/app/src/main/java/org/sopt/pingle/data/repository/JoinGroupRepositoryImpl.kt b/app/src/main/java/org/sopt/pingle/data/repository/JoinGroupRepositoryImpl.kt new file mode 100644 index 00000000..5beb558f --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/repository/JoinGroupRepositoryImpl.kt @@ -0,0 +1,35 @@ +package org.sopt.pingle.data.repository + +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import org.sopt.pingle.data.datasource.remote.JoinGroupRemoteDataSource +import org.sopt.pingle.data.mapper.toRequestJoinGroupCode +import org.sopt.pingle.domain.model.JoinGroupInfoEntity +import org.sopt.pingle.domain.model.RequestJoinGroupCodeEntity +import org.sopt.pingle.domain.model.ResponseJoinGroupCodeEntity +import org.sopt.pingle.domain.repository.JoinGroupRepository + +class JoinGroupRepositoryImpl @Inject constructor( + private val joinGroupRemoteDataSource: JoinGroupRemoteDataSource +) : JoinGroupRepository { + override fun getJoinGroupInfo(teamId: Int): Flow = flow { + val result = runCatching { + joinGroupRemoteDataSource.getJoinGroupInfo(teamId = teamId).data.toJoinGroupCodeEntity() + } + emit(result.getOrThrow()) + } + + override fun postJoinGroupCode( + teamId: Int, + requestJoinGroupCode: RequestJoinGroupCodeEntity + ): Flow = flow { + val result = runCatching { + joinGroupRemoteDataSource.postJoinGroupCode( + teamId = teamId, + requestJoinGroupCode = requestJoinGroupCode.toRequestJoinGroupCode() + ).data.toResponseJoinGroupCode() + } + emit(result.getOrThrow()) + } +} diff --git a/app/src/main/java/org/sopt/pingle/data/service/JoinGroupService.kt b/app/src/main/java/org/sopt/pingle/data/service/JoinGroupService.kt new file mode 100644 index 00000000..0dcf2f4f --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/data/service/JoinGroupService.kt @@ -0,0 +1,30 @@ +package org.sopt.pingle.data.service + +import org.sopt.pingle.data.model.remote.request.RequestJoinGroupCodeDto +import org.sopt.pingle.data.model.remote.response.ResponseJoinGroupCodeDto +import org.sopt.pingle.data.model.remote.response.ResponseJoinGroupInfoDto +import org.sopt.pingle.util.base.BaseResponse +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.POST +import retrofit2.http.Path + +interface JoinGroupService { + @GET("$VERSION/$TEAMS/{$TEAM_ID}") + suspend fun getJoinGroupInfo( + @Path("$TEAM_ID") teamId: Int + ): BaseResponse + + @POST("$VERSION/$TEAMS/{$TEAM_ID}/$REGISTER") + suspend fun postJoinGroupCode( + @Path("$TEAM_ID") teamId: Int, + @Body requestJoinGroupCode: RequestJoinGroupCodeDto + ): BaseResponse + + companion object { + const val VERSION = "v1" + const val TEAMS = "teams" + const val TEAM_ID = "teamId" + const val REGISTER = "register" + } +} diff --git a/app/src/main/java/org/sopt/pingle/di/DataSourceModule.kt b/app/src/main/java/org/sopt/pingle/di/DataSourceModule.kt index d1e36f6d..98be5212 100644 --- a/app/src/main/java/org/sopt/pingle/di/DataSourceModule.kt +++ b/app/src/main/java/org/sopt/pingle/di/DataSourceModule.kt @@ -9,6 +9,7 @@ import org.sopt.pingle.data.datasource.local.DummyLocalDataSource import org.sopt.pingle.data.datasource.local.PingleLocalDataSource import org.sopt.pingle.data.datasource.remote.AuthRemoteDataSource import org.sopt.pingle.data.datasource.remote.DummyRemoteDataSource +import org.sopt.pingle.data.datasource.remote.JoinGroupRemoteDataSource import org.sopt.pingle.data.datasource.remote.MapRemoteDataSource import org.sopt.pingle.data.datasource.remote.PingleRemoteDataSource import org.sopt.pingle.data.datasource.remote.PlanRemoteDataSource @@ -16,6 +17,7 @@ import org.sopt.pingle.data.datasourceimpl.local.DummyLocalDataSourceImpl import org.sopt.pingle.data.datasourceimpl.local.PingleLocalDataSourceImpl import org.sopt.pingle.data.datasourceimpl.remote.AuthRemoteDataSourceImpl import org.sopt.pingle.data.datasourceimpl.remote.DummyRemoteDataSourceImpl +import org.sopt.pingle.data.datasourceimpl.remote.JoinGroupRemoteDataSourceImpl import org.sopt.pingle.data.datasourceimpl.remote.MapRemoteDataSourceImpl import org.sopt.pingle.data.datasourceimpl.remote.PingleRemoteDataSourceImpl import org.sopt.pingle.data.datasourceimpl.remote.PlanRemoteDataSourceImpl @@ -50,4 +52,8 @@ abstract class DataSourceModule { @Binds @Singleton abstract fun bindsPlanRemoteDataSource(planRemoteDataSourceImpl: PlanRemoteDataSourceImpl): PlanRemoteDataSource + + @Binds + @Singleton + abstract fun bindsJoinGroupRemoteDataSource(joinGroupRemoteDataSourceImpl: JoinGroupRemoteDataSourceImpl): JoinGroupRemoteDataSource } diff --git a/app/src/main/java/org/sopt/pingle/di/RepositoryModule.kt b/app/src/main/java/org/sopt/pingle/di/RepositoryModule.kt index 52c9d3a1..e379596e 100644 --- a/app/src/main/java/org/sopt/pingle/di/RepositoryModule.kt +++ b/app/src/main/java/org/sopt/pingle/di/RepositoryModule.kt @@ -7,11 +7,13 @@ import dagger.hilt.components.SingletonComponent import javax.inject.Singleton import org.sopt.pingle.data.repository.AuthRepositoryImpl import org.sopt.pingle.data.repository.DummyRepositoryImpl +import org.sopt.pingle.data.repository.JoinGroupRepositoryImpl import org.sopt.pingle.data.repository.MapRepositoryImpl import org.sopt.pingle.data.repository.PingleRepositoryImpl import org.sopt.pingle.data.repository.PlanRepositoryImpl import org.sopt.pingle.domain.repository.AuthRepository import org.sopt.pingle.domain.repository.DummyRepository +import org.sopt.pingle.domain.repository.JoinGroupRepository import org.sopt.pingle.domain.repository.MapRepository import org.sopt.pingle.domain.repository.PingleRepository import org.sopt.pingle.domain.repository.PlanRepository @@ -38,4 +40,8 @@ abstract class RepositoryModule { @Binds @Singleton abstract fun bindsPlanRepository(planRepositoryImpl: PlanRepositoryImpl): PlanRepository + + @Binds + @Singleton + abstract fun bindsJoinGroupRepository(joinGroupRepositoryImpl: JoinGroupRepositoryImpl): JoinGroupRepository } diff --git a/app/src/main/java/org/sopt/pingle/di/ServiceModule.kt b/app/src/main/java/org/sopt/pingle/di/ServiceModule.kt index 6c04eb0d..c99ac334 100644 --- a/app/src/main/java/org/sopt/pingle/di/ServiceModule.kt +++ b/app/src/main/java/org/sopt/pingle/di/ServiceModule.kt @@ -7,12 +7,12 @@ import dagger.hilt.components.SingletonComponent import javax.inject.Singleton import org.sopt.pingle.data.service.AuthService import org.sopt.pingle.data.service.DummyService +import org.sopt.pingle.data.service.JoinGroupService import org.sopt.pingle.data.service.MapService import org.sopt.pingle.data.service.PingleService import org.sopt.pingle.data.service.PlanService import org.sopt.pingle.di.qualifier.Pingle import retrofit2.Retrofit -import retrofit2.create @Module @InstallIn(SingletonComponent::class) @@ -41,4 +41,9 @@ object ServiceModule { @Singleton fun providesPlanService(@Pingle retrofit: Retrofit): PlanService = retrofit.create(PlanService::class.java) + + @Provides + @Singleton + fun providesJoinGroupService(@Pingle retrofit: Retrofit): JoinGroupService = + retrofit.create(JoinGroupService::class.java) } diff --git a/app/src/main/java/org/sopt/pingle/di/UseCaseModule.kt b/app/src/main/java/org/sopt/pingle/di/UseCaseModule.kt index 3056b06f..f828421b 100644 --- a/app/src/main/java/org/sopt/pingle/di/UseCaseModule.kt +++ b/app/src/main/java/org/sopt/pingle/di/UseCaseModule.kt @@ -6,13 +6,16 @@ import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import javax.inject.Singleton import org.sopt.pingle.domain.repository.DummyRepository +import org.sopt.pingle.domain.repository.JoinGroupRepository import org.sopt.pingle.domain.repository.MapRepository import org.sopt.pingle.domain.repository.PingleRepository import org.sopt.pingle.domain.repository.PlanRepository import org.sopt.pingle.domain.usecase.GetDummyUserListUseCase +import org.sopt.pingle.domain.usecase.GetJoinGroupInfoUseCase import org.sopt.pingle.domain.usecase.GetPinListWithoutFilteringUseCase import org.sopt.pingle.domain.usecase.GetPingleListUseCase import org.sopt.pingle.domain.usecase.GetPlanLocationListUseCase +import org.sopt.pingle.domain.usecase.PostJoinGroupCodeUseCase import org.sopt.pingle.domain.usecase.PostPingleCancelUseCase import org.sopt.pingle.domain.usecase.PostPingleJoinUseCase import org.sopt.pingle.domain.usecase.SetDummyDataUseCase @@ -54,4 +57,14 @@ class UseCaseModule { @Singleton fun providesGetPlanLocationListUseCase(planRepository: PlanRepository): GetPlanLocationListUseCase = GetPlanLocationListUseCase(planRepository = planRepository) + + @Provides + @Singleton + fun providesGetJoinGroupInfoUseCase(joinGroupRepository: JoinGroupRepository): GetJoinGroupInfoUseCase = + GetJoinGroupInfoUseCase(joinGroupRepository = joinGroupRepository) + + @Provides + @Singleton + fun providesPostJoinGroupCodeUseCase(joinGroupRepository: JoinGroupRepository): PostJoinGroupCodeUseCase = + PostJoinGroupCodeUseCase(joinGroupRepository = joinGroupRepository) } diff --git a/app/src/main/java/org/sopt/pingle/domain/model/JoinGroupCodeEntity.kt b/app/src/main/java/org/sopt/pingle/domain/model/JoinGroupInfoEntity.kt similarity index 83% rename from app/src/main/java/org/sopt/pingle/domain/model/JoinGroupCodeEntity.kt rename to app/src/main/java/org/sopt/pingle/domain/model/JoinGroupInfoEntity.kt index 63283e91..0f2942b7 100644 --- a/app/src/main/java/org/sopt/pingle/domain/model/JoinGroupCodeEntity.kt +++ b/app/src/main/java/org/sopt/pingle/domain/model/JoinGroupInfoEntity.kt @@ -1,6 +1,6 @@ package org.sopt.pingle.domain.model -data class JoinGroupCodeEntity( +data class JoinGroupInfoEntity( val id: Int, val keyword: String, val name: String, diff --git a/app/src/main/java/org/sopt/pingle/domain/model/RequestJoinGroupCodeEntity.kt b/app/src/main/java/org/sopt/pingle/domain/model/RequestJoinGroupCodeEntity.kt new file mode 100644 index 00000000..4e925d57 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/domain/model/RequestJoinGroupCodeEntity.kt @@ -0,0 +1,5 @@ +package org.sopt.pingle.domain.model + +class RequestJoinGroupCodeEntity( + val code: String +) diff --git a/app/src/main/java/org/sopt/pingle/domain/model/ResponseJoinGroupCodeEntity.kt b/app/src/main/java/org/sopt/pingle/domain/model/ResponseJoinGroupCodeEntity.kt new file mode 100644 index 00000000..8f85e140 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/domain/model/ResponseJoinGroupCodeEntity.kt @@ -0,0 +1,6 @@ +package org.sopt.pingle.domain.model + +data class ResponseJoinGroupCodeEntity( + val id: Int, + val name: String +) diff --git a/app/src/main/java/org/sopt/pingle/domain/repository/JoinGroupRepository.kt b/app/src/main/java/org/sopt/pingle/domain/repository/JoinGroupRepository.kt new file mode 100644 index 00000000..364054a9 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/domain/repository/JoinGroupRepository.kt @@ -0,0 +1,14 @@ +package org.sopt.pingle.domain.repository + +import kotlinx.coroutines.flow.Flow +import org.sopt.pingle.domain.model.JoinGroupInfoEntity +import org.sopt.pingle.domain.model.RequestJoinGroupCodeEntity +import org.sopt.pingle.domain.model.ResponseJoinGroupCodeEntity + +interface JoinGroupRepository { + fun getJoinGroupInfo(teamId: Int): Flow + fun postJoinGroupCode( + teamId: Int, + requestJoinGroupCode: RequestJoinGroupCodeEntity + ): Flow +} diff --git a/app/src/main/java/org/sopt/pingle/domain/usecase/GetJoinGroupInfoUseCase.kt b/app/src/main/java/org/sopt/pingle/domain/usecase/GetJoinGroupInfoUseCase.kt new file mode 100644 index 00000000..dd5aee85 --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/domain/usecase/GetJoinGroupInfoUseCase.kt @@ -0,0 +1,12 @@ +package org.sopt.pingle.domain.usecase + +import kotlinx.coroutines.flow.Flow +import org.sopt.pingle.domain.model.JoinGroupInfoEntity +import org.sopt.pingle.domain.repository.JoinGroupRepository + +class GetJoinGroupInfoUseCase( + private val joinGroupRepository: JoinGroupRepository +) { + operator fun invoke(teamId: Int): Flow = + joinGroupRepository.getJoinGroupInfo(teamId = teamId) +} diff --git a/app/src/main/java/org/sopt/pingle/domain/usecase/PostJoinGroupCodeUseCase.kt b/app/src/main/java/org/sopt/pingle/domain/usecase/PostJoinGroupCodeUseCase.kt new file mode 100644 index 00000000..ebcf449e --- /dev/null +++ b/app/src/main/java/org/sopt/pingle/domain/usecase/PostJoinGroupCodeUseCase.kt @@ -0,0 +1,19 @@ +package org.sopt.pingle.domain.usecase + +import kotlinx.coroutines.flow.Flow +import org.sopt.pingle.domain.model.RequestJoinGroupCodeEntity +import org.sopt.pingle.domain.model.ResponseJoinGroupCodeEntity +import org.sopt.pingle.domain.repository.JoinGroupRepository + +class PostJoinGroupCodeUseCase( + private val joinGroupRepository: JoinGroupRepository +) { + operator fun invoke( + teamId: Int, + requestJoinGroupCode: RequestJoinGroupCodeEntity + ): Flow = + joinGroupRepository.postJoinGroupCode( + teamId = teamId, + requestJoinGroupCode = requestJoinGroupCode + ) +} diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/joingroup/JoinGroupCodeActivity.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/joingroup/JoinGroupCodeActivity.kt index 24458ffb..a73d9ad5 100644 --- a/app/src/main/java/org/sopt/pingle/presentation/ui/joingroup/JoinGroupCodeActivity.kt +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/joingroup/JoinGroupCodeActivity.kt @@ -3,10 +3,18 @@ package org.sopt.pingle.presentation.ui.joingroup import android.content.Intent import android.os.Bundle import androidx.activity.viewModels +import androidx.lifecycle.flowWithLifecycle +import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import org.sopt.pingle.R import org.sopt.pingle.databinding.ActivityJoinGroupCodeBinding +import org.sopt.pingle.domain.model.RequestJoinGroupCodeEntity import org.sopt.pingle.util.base.BindingActivity +import org.sopt.pingle.util.component.PingleSnackbar +import org.sopt.pingle.util.view.UiState +import timber.log.Timber @AndroidEntryPoint class JoinGroupCodeActivity : @@ -17,15 +25,22 @@ class JoinGroupCodeActivity : super.onCreate(savedInstanceState) binding.joinViewModel = viewModel + initLayout() addListeners() addObservers() + collectData() + } + + private fun initLayout() { + viewModel.joinGroupInfoState(TEAM_ID) } private fun addListeners() { binding.btnJoinGroupCodeNext.setOnClickListener { - // TODO 초대코드 일치하지 않을 시 - // CustomSnackbar.makeSnackbar(binding.root, getString(R.string.join_group_code_snackbar_message), 97) - navigateToJoinGroupSuccess() + viewModel.joinGroupCodeState( + TEAM_ID, + RequestJoinGroupCodeEntity(viewModel.joinGroupCodeEditText.value.toString()) + ) } binding.includeJoinGroupCodeTopbar.ivAllTopbarArrowWithTitleArrowLeft.setOnClickListener { @@ -34,34 +49,71 @@ class JoinGroupCodeActivity : } private fun addObservers() { - viewModel.joinGroupData.observe(this) { joinGroupData -> - with(binding) { - tvJoinGroupCodeTag.text = joinGroupData.keyword - tvJoinGroupCodeGroupName.text = joinGroupData.name - tvJoinGroupCodeMeetingCount.text = - getString(R.string.join_group_code_meeting_count, joinGroupData.meetingCount) - tvJoinGroupCodeParticipantCount.text = - getString( - R.string.join_group_code_participant_count, - joinGroupData.participantCount - ) - } - } - - viewModel.joinGroupCode.observe(this) { editText -> + viewModel.joinGroupCodeEditText.observe(this) { editText -> binding.btnJoinGroupCodeNext.isEnabled = editText.isNotEmpty() } } + private fun collectData() { + viewModel.joinGroupInfoState.flowWithLifecycle(lifecycle).onEach { uiState -> + when (uiState) { + is UiState.Success -> { + with(binding) { + tvJoinGroupCodeTag.text = uiState.data.keyword + tvJoinGroupCodeGroupName.text = uiState.data.name + tvJoinGroupCodeMeetingCount.text = + getString( + R.string.join_group_code_meeting_count, + uiState.data.meetingCount + ) + tvJoinGroupCodeParticipantCount.text = + getString( + R.string.join_group_code_participant_count, + uiState.data.participantCount + ) + } + } + + is UiState.Error -> Timber.tag(JOIN_GROUP_CODE_ACTIVITY).d(uiState.message) + + is UiState.Loading -> Timber.tag(JOIN_GROUP_CODE_ACTIVITY).d(LOADING) + + is UiState.Empty -> Timber.tag(JOIN_GROUP_CODE_ACTIVITY).d(EMPTY) + } + }.launchIn(lifecycleScope) + + viewModel.joinGroupCodeState.flowWithLifecycle(lifecycle).onEach { uiState -> + when (uiState) { + is UiState.Success -> navigateToJoinGroupSuccess() + + is UiState.Error -> { + PingleSnackbar.makeSnackbar( + binding.root, + getString(R.string.join_group_code_snackbar_message), + SNACKBAR_BOTTOM_MARGIN + ) + } + + is UiState.Loading -> Timber.tag(JOIN_GROUP_CODE_ACTIVITY).d(LOADING) + + is UiState.Empty -> Timber.tag(JOIN_GROUP_CODE_ACTIVITY).d(EMPTY) + } + }.launchIn(lifecycleScope) + } + private fun navigateToJoinGroupSuccess() { Intent(this, JoinGroupSuccessActivity::class.java).apply { - // TODO 서버통신시 group name 가져와서 전달하기 - putExtra(GROUP_NAME, viewModel.joinGroupData.value?.name) + putExtra(GROUP_NAME, binding.tvJoinGroupCodeGroupName.text) startActivity(this) } } companion object { const val GROUP_NAME = "groupName" + const val TEAM_ID = 1 + const val LOADING = "Loding" + const val EMPTY = "Empty" + const val JOIN_GROUP_CODE_ACTIVITY = "JoinGroupCodeActivity" + const val SNACKBAR_BOTTOM_MARGIN = 97 } } diff --git a/app/src/main/java/org/sopt/pingle/presentation/ui/joingroup/JoinViewModel.kt b/app/src/main/java/org/sopt/pingle/presentation/ui/joingroup/JoinViewModel.kt index 57c05cc0..cab14b76 100644 --- a/app/src/main/java/org/sopt/pingle/presentation/ui/joingroup/JoinViewModel.kt +++ b/app/src/main/java/org/sopt/pingle/presentation/ui/joingroup/JoinViewModel.kt @@ -2,34 +2,52 @@ package org.sopt.pingle.presentation.ui.joingroup import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow -import org.sopt.pingle.domain.model.JoinGroupCodeEntity +import kotlinx.coroutines.launch +import org.sopt.pingle.data.datasource.local.PingleLocalDataSource +import org.sopt.pingle.domain.model.JoinGroupInfoEntity import org.sopt.pingle.domain.model.JoinGroupSearchEntity +import org.sopt.pingle.domain.model.RequestJoinGroupCodeEntity +import org.sopt.pingle.domain.model.ResponseJoinGroupCodeEntity +import org.sopt.pingle.domain.usecase.GetJoinGroupInfoUseCase +import org.sopt.pingle.domain.usecase.PostJoinGroupCodeUseCase +import org.sopt.pingle.util.view.UiState -class JoinViewModel : ViewModel() { - private val _joinGroupData = MutableLiveData() - val joinGroupData get() = _joinGroupData +@HiltViewModel +class JoinViewModel @Inject constructor( + private val localStorage: PingleLocalDataSource, + private val getJoinGroupInfoUseCase: GetJoinGroupInfoUseCase, + private val postJoinGroupCodeUseCase: PostJoinGroupCodeUseCase +) : ViewModel() { + private val _selectedJoinGroup = MutableStateFlow(null) + val selectedJoinGroup get() = _selectedJoinGroup.asStateFlow() + + private val _joinGroupSearchData = MutableStateFlow>(emptyList()) + val joinGroupSearchData get() = _joinGroupSearchData + + private val _joinGroupInfoState = + MutableStateFlow>(UiState.Empty) + val joinGroupInfoState get() = _joinGroupInfoState.asStateFlow() private var _isJoinGroupCodeBtn = MutableLiveData(false) val isJoinGroupCodeBtn get() = _isJoinGroupCodeBtn - val joinGroupCode = MutableLiveData() + private var _joinGroupCodeState = + MutableStateFlow>(UiState.Empty) + val joinGroupCodeState get() = _joinGroupCodeState - private val _joinGroupSearchData = MutableStateFlow>(emptyList()) - val joinGroupSearchData get() = _joinGroupSearchData - - private val _selectedJoinGroup = MutableStateFlow(null) - val selectedJoinGroup get() = _selectedJoinGroup.asStateFlow() + val joinGroupCodeEditText = MutableLiveData() val joinGroupSearchEditText = MutableLiveData("") private var oldPosition = DEFAULT_OLD_POSITION fun updateJoinGroupSearchList(newPosition: Int) { when (oldPosition) { - DEFAULT_OLD_POSITION -> { - setIsSelected(newPosition) - } + DEFAULT_OLD_POSITION -> setIsSelected(newPosition) newPosition -> { setIsSelected(newPosition) @@ -54,15 +72,39 @@ class JoinViewModel : ViewModel() { private fun getIsSelected(position: Int) = _joinGroupSearchData.value[position].isSelected.get() - init { - _joinGroupData.value = JoinGroupCodeEntity( - id = 0, - keyword = "연합동아리", - name = "SOPT", - meetingCount = 10, - participantCount = 200 - ) + fun joinGroupInfoState(teamId: Int) { + _joinGroupInfoState.value = UiState.Loading + viewModelScope.launch { + _joinGroupInfoState.value = UiState.Loading + runCatching { + getJoinGroupInfoUseCase(teamId = teamId).collect { joinGroupInfo -> + _joinGroupInfoState.value = UiState.Success(joinGroupInfo) + } + }.onFailure { + _joinGroupInfoState.value = UiState.Error(it.message) + } + } + } + fun joinGroupCodeState(teamId: Int, code: RequestJoinGroupCodeEntity) { + _joinGroupCodeState.value = UiState.Loading + viewModelScope.launch { + runCatching { + postJoinGroupCodeUseCase(teamId = teamId, requestJoinGroupCode = code) + .collect { joinGroupCode -> + _joinGroupCodeState.value = UiState.Success(joinGroupCode) + with(localStorage) { + groupId = joinGroupCode.id + groupName = joinGroupCode.name + } + } + }.onFailure { + _joinGroupCodeState.value = UiState.Error(it.message) + } + } + } + + init { _joinGroupSearchData.value = listOf( JoinGroupSearchEntity( id = 0, diff --git a/app/src/main/res/layout/activity_join_group_code.xml b/app/src/main/res/layout/activity_join_group_code.xml index 0700882c..a7459be6 100644 --- a/app/src/main/res/layout/activity_join_group_code.xml +++ b/app/src/main/res/layout/activity_join_group_code.xml @@ -163,7 +163,7 @@