Skip to content

Commit

Permalink
Merge pull request #148 from Team-Notitime/feat/organization/147-memb…
Browse files Browse the repository at this point in the history
…er-management

Feat/organization/147 member management
  • Loading branch information
easyhz authored Aug 24, 2024
2 parents b09b92a + 875d99a commit 4f9056b
Show file tree
Hide file tree
Showing 26 changed files with 217 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ internal fun NavGraphBuilder.organizationGraph(
val args = it.toRoute<MemberManagement>()
MemberScreen(
organizationId = args.organizationId,
navigateToUp = navController::navigateUp
imageUrl = args.imageUrl,
navigateToUp = navController::navigateUp,
navigateToInvitation = navController::navigateToOrganizationInvitation
)
}
composable<OrganizationCreation> {
Expand All @@ -102,6 +104,7 @@ internal fun NavGraphBuilder.organizationGraph(
OrganizationInvitationScreen(
invitationUrl = args.invitationUrl,
imageUrl = args.imageUrl ?: "",
isCreation = args.isCreation,
navigateToHome = { navController.navigateToHome(navOptions) }
)
}
Expand Down Expand Up @@ -143,8 +146,8 @@ internal fun NavController.navigateToOrganizationManagement(
navigate(OrganizationManagement(organizationInformation = information.encode()))
}

internal fun NavController.navigateToMemberManagement(id: Int) {
navigate(MemberManagement(id))
internal fun NavController.navigateToMemberManagement(id: Int, imageUrl: String?) {
navigate(MemberManagement(id, imageUrl))
}

internal fun NavController.navigateToOrganizationCreation() {
Expand All @@ -153,12 +156,13 @@ internal fun NavController.navigateToOrganizationCreation() {

internal fun NavController.navigateToOrganizationInvitation(
invitationUrl: String,
imageUrl: String?
imageUrl: String?,
isCreation: Boolean = true,
) {
val navOptions = navOptions {
popUpTo(OrganizationCreation) { inclusive = true }
}
navigate(OrganizationInvitation(invitationUrl = invitationUrl, imageUrl = imageUrl), navOptions)
navigate(OrganizationInvitation(invitationUrl = invitationUrl, imageUrl = imageUrl, isCreation = isCreation), navOptions)
}

internal fun NavController.navigateToStandbyMember(id: Int) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ import kotlinx.serialization.Serializable

@Serializable
data class MemberManagement(
val organizationId: Int
val organizationId: Int,
val imageUrl: String?,
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ import kotlinx.serialization.Serializable
data class OrganizationInvitation(
val invitationUrl: String,
val imageUrl: String? = null,
val isCreation: Boolean = true
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.easyhz.noffice.core.common.deepLink

import androidx.navigation.navDeepLink
import com.easyhz.noffice.core.common.util.Encryption

object NofficeDeepLink {
val announcement = navDeepLink {
Expand All @@ -10,3 +11,7 @@ object NofficeDeepLink {
uriPattern = DeepLinkPatterns.join("{organizationId}")
}
}
fun Int.toNofficeDeepLink(): String {
val id = Encryption.encrypt(this.toString())
return DeepLinkPatterns.join(id)
}
1 change: 1 addition & 0 deletions core/design-system/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
<string name="organization_creation_promotion_placeholder">코드를 입력해 주세요.</string>

<string name="organization_creation_success_title">그룹을 만들었어요!</string>
<string name="organization_invitation_title">링크를 복사했습니다!</string>
<string name="organization_creation_success_sub_title">링크를 통해 멤버들을 초대해 보세요.</string>
<string name="organization_creation_success_home_button">그룹 메인으로</string>
<string name="organization_creation_success_copy_button">초대 링크 복사</string>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.easyhz.noffice.core.network.api.organization

import com.easyhz.noffice.core.network.model.request.organization.RegisterMemberRequest
import com.easyhz.noffice.core.network.model.response.announcement.MemberResponse
import com.easyhz.noffice.core.network.util.NofficeResult
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.PATCH
import retrofit2.http.Path

interface OrganizationMemberService {

/* 조직 가입 대기자 조회 */
@GET("/api/v1/organizations/{organizationId}/pending-members")
suspend fun fetchOrganizationPendingMembers(
@Path("organizationId") organizationId: Int
): NofficeResult<List<MemberResponse>>

/* 조직 가입 수락 */
@PATCH("/api/v1/organizations/{organizationId}/register")
suspend fun acceptRegisterMember(
@Path("organizationId") organizationId: Int,
@Body body: RegisterMemberRequest
): NofficeResult<Unit>

/* 조직원 권한 변경 */
@PATCH("/api/v1/organizations/{organizationId}/roles")
suspend fun changeMemberRole(
@Path("organizationId") organizationId: Int,
@Body body: RegisterMemberRequest
): NofficeResult<Unit>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ package com.easyhz.noffice.core.network.api.organization

import com.easyhz.noffice.core.network.model.request.organization.CategoryRequest
import com.easyhz.noffice.core.network.model.request.organization.OrganizationCreationRequest
import com.easyhz.noffice.core.network.model.request.organization.RegisterMemberRequest
import com.easyhz.noffice.core.network.model.response.announcement.AnnouncementResponse
import com.easyhz.noffice.core.network.model.response.announcement.MemberResponse
import com.easyhz.noffice.core.network.model.response.category.CategoryUpdateResponse
import com.easyhz.noffice.core.network.model.response.organization.OrganizationCapsuleResponse
import com.easyhz.noffice.core.network.model.response.organization.OrganizationInformationResponse
Expand All @@ -15,7 +13,6 @@ import com.easyhz.noffice.core.network.util.NofficeResult
import com.easyhz.noffice.core.network.util.PagingResult
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.PATCH
import retrofit2.http.POST
import retrofit2.http.PUT
import retrofit2.http.Path
Expand Down Expand Up @@ -70,16 +67,4 @@ interface OrganizationService {
suspend fun fetchOrganizationSignUpInfo(
@Path("organizationId") organizationId: Int
): NofficeResult<OrganizationSignUpInformationResponse>

/* 조직 가입 대기자 조회 */
@GET("/api/v1/organizations/{organizationId}/pending-members")
suspend fun fetchOrganizationPendingMembers(
@Path("organizationId") organizationId: Int
): NofficeResult<List<MemberResponse>>

@PATCH("/api/v1/organizations/{organizationId}/register")
suspend fun acceptRegisterMember(
@Path("organizationId") organizationId: Int,
@Body body: RegisterMemberRequest
): NofficeResult<Unit>
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.easyhz.noffice.core.network.di.service

import com.easyhz.noffice.core.network.api.organization.OrganizationMemberService
import com.easyhz.noffice.core.network.api.organization.OrganizationService
import com.easyhz.noffice.core.network.di.NofficeRetrofit
import dagger.Module
Expand All @@ -14,4 +15,8 @@ object OrganizationServiceModule {
@Provides
fun provideOrganizationService(@NofficeRetrofit retrofit: Retrofit): OrganizationService =
retrofit.create(OrganizationService::class.java)

@Provides
fun provideOrganizationMemberService(@NofficeRetrofit retrofit: Retrofit): OrganizationMemberService =
retrofit.create(OrganizationMemberService::class.java)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.easyhz.noffice.data.organization.di.repository

import com.easyhz.noffice.data.organization.repository.member.OrganizationMemberRepository
import com.easyhz.noffice.data.organization.repository.member.OrganizationMemberRepositoryImpl
import com.easyhz.noffice.data.organization.repository.organization.OrganizationRepository
import com.easyhz.noffice.data.organization.repository.organization.OrganizationRepositoryImpl
import dagger.Binds
Expand All @@ -14,4 +16,9 @@ interface OrganizationRepositoryModule {
fun bindOrganizationRepository(
organizationRepositoryImpl: OrganizationRepositoryImpl
): OrganizationRepository

@Binds
fun bindOrganizationMemberRepository(
organizationMemberRepositoryImpl: OrganizationMemberRepositoryImpl
): OrganizationMemberRepository
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.easyhz.noffice.data.organization.repository.member

import com.easyhz.noffice.core.model.common.Member
import com.easyhz.noffice.core.model.organization.param.RegisterMemberParam

interface OrganizationMemberRepository {
suspend fun fetchOrganizationPendingMembers(organizationId: Int): Result<List<Member>>
suspend fun acceptRegisterMember(param: RegisterMemberParam): Result<Unit>
suspend fun changeMemberRole(param: RegisterMemberParam): Result<Unit>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.easyhz.noffice.data.organization.repository.member

import com.easyhz.noffice.core.common.di.Dispatcher
import com.easyhz.noffice.core.common.di.NofficeDispatchers
import com.easyhz.noffice.core.model.common.Member
import com.easyhz.noffice.core.model.organization.param.RegisterMemberParam
import com.easyhz.noffice.core.network.api.organization.OrganizationMemberService
import com.easyhz.noffice.core.network.util.toResult
import com.easyhz.noffice.data.announcement.mapper.announcement.toModel
import com.easyhz.noffice.data.organization.mapper.toRequest
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
import javax.inject.Inject

class OrganizationMemberRepositoryImpl @Inject constructor(
@Dispatcher(NofficeDispatchers.IO) private val dispatcher: CoroutineDispatcher,
private val organizationMemberService: OrganizationMemberService
): OrganizationMemberRepository {
override suspend fun fetchOrganizationPendingMembers(organizationId: Int): Result<List<Member>> =
withContext(dispatcher) {
return@withContext organizationMemberService.fetchOrganizationPendingMembers(organizationId)
.toResult().map { it.map { item -> item.toModel() } }
}

override suspend fun acceptRegisterMember(param: RegisterMemberParam): Result<Unit> =
withContext(dispatcher) {
return@withContext organizationMemberService.acceptRegisterMember(
organizationId = param.organizationId,
body = param.toRequest()
).toResult()
}

override suspend fun changeMemberRole(param: RegisterMemberParam): Result<Unit> =
withContext(dispatcher) {
return@withContext organizationMemberService.changeMemberRole(
organizationId = param.organizationId,
body = param.toRequest()
).toResult()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@ package com.easyhz.noffice.data.organization.repository.organization

import androidx.paging.PagingData
import com.easyhz.noffice.core.common.util.DateFormat
import com.easyhz.noffice.core.model.common.Member
import com.easyhz.noffice.core.model.organization.Organization
import com.easyhz.noffice.core.model.organization.OrganizationInformation
import com.easyhz.noffice.core.model.organization.OrganizationJoin
import com.easyhz.noffice.core.model.organization.OrganizationSignUpInformation
import com.easyhz.noffice.core.model.organization.announcement.OrganizationAnnouncement
import com.easyhz.noffice.core.model.organization.category.Category
import com.easyhz.noffice.core.model.organization.param.OrganizationCreationParam
import com.easyhz.noffice.core.model.organization.param.RegisterMemberParam
import kotlinx.coroutines.flow.Flow

interface OrganizationRepository {
Expand All @@ -21,6 +19,4 @@ interface OrganizationRepository {
suspend fun updateOrganizationCategory(organizationId: Int, category: List<Int>): Result<List<Category>>
suspend fun joinOrganization(organizationId: Int): Result<OrganizationJoin>
suspend fun fetchOrganizationSignUpInfo(organizationId: Int): Result<OrganizationSignUpInformation>
suspend fun fetchOrganizationPendingMembers(organizationId: Int): Result<List<Member>>
suspend fun acceptRegisterMember(param: RegisterMemberParam): Result<Unit>
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,18 +107,4 @@ class OrganizationRepositoryImpl @Inject constructor(
return@withContext organizationService.fetchOrganizationSignUpInfo(organizationId)
.toResult().map { it.toModel() }
}

override suspend fun fetchOrganizationPendingMembers(organizationId: Int): Result<List<Member>> =
withContext(dispatcher) {
return@withContext organizationService.fetchOrganizationPendingMembers(organizationId)
.toResult().map { it.map { item -> item.toModel() } }
}

override suspend fun acceptRegisterMember(param: RegisterMemberParam): Result<Unit> =
withContext(dispatcher) {
return@withContext organizationService.acceptRegisterMember(
organizationId = param.organizationId,
body = param.toRequest()
).toResult()
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package com.easyhz.noffice.domain.organization.usecase.organization
package com.easyhz.noffice.domain.organization.usecase.member

import com.easyhz.noffice.core.common.base.BaseUseCase
import com.easyhz.noffice.core.model.organization.param.RegisterMemberParam
import com.easyhz.noffice.data.organization.repository.organization.OrganizationRepository
import com.easyhz.noffice.data.organization.repository.member.OrganizationMemberRepository
import javax.inject.Inject

class AcceptRegisterMemberUseCase @Inject constructor(
private val organizationRepository: OrganizationRepository
private val organizationMemberRepository: OrganizationMemberRepository
): BaseUseCase<RegisterMemberParam, Unit>() {
override suspend fun invoke(param: RegisterMemberParam): Result<Unit> {
return organizationRepository.acceptRegisterMember(param)
return organizationMemberRepository.acceptRegisterMember(param)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.easyhz.noffice.domain.organization.usecase.member

import com.easyhz.noffice.core.common.base.BaseUseCase
import com.easyhz.noffice.core.model.organization.param.RegisterMemberParam
import com.easyhz.noffice.data.organization.repository.member.OrganizationMemberRepository
import javax.inject.Inject

class ChangeMemberRoleUseCase @Inject constructor(
private val organizationMemberRepository: OrganizationMemberRepository
): BaseUseCase<RegisterMemberParam, Unit>() {
override suspend fun invoke(param: RegisterMemberParam): Result<Unit> {
return organizationMemberRepository.changeMemberRole(param)
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package com.easyhz.noffice.domain.organization.usecase.organization
package com.easyhz.noffice.domain.organization.usecase.member

import com.easyhz.noffice.core.common.base.BaseUseCase
import com.easyhz.noffice.core.model.common.Member
import com.easyhz.noffice.data.organization.repository.organization.OrganizationRepository
import com.easyhz.noffice.data.organization.repository.member.OrganizationMemberRepository
import javax.inject.Inject

class FetchOrganizationPendingMembersUseCase @Inject constructor(
private val organizationRepository: OrganizationRepository
private val organizationMemberRepository: OrganizationMemberRepository
): BaseUseCase<Int, List<Member>>() {
override suspend fun invoke(param: Int): Result<List<Member>> {
return organizationRepository.fetchOrganizationPendingMembers(param)
return organizationMemberRepository.fetchOrganizationPendingMembers(param)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.easyhz.noffice.core.design_system.extension.noRippleClickable
import com.easyhz.noffice.core.design_system.theme.Grey100
import com.easyhz.noffice.core.design_system.theme.Grey600
Expand All @@ -35,6 +36,7 @@ internal fun UrlView(
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = SubBody14,
lineHeight = 20.sp,
color = Grey600
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.easyhz.noffice.core.common.base.UiIntent
import com.easyhz.noffice.core.model.organization.member.MemberType

sealed class MemberIntent: UiIntent() {
data class InitScreen(val organizationId: Int, val imageUrl: String?): MemberIntent()
data object ClickBackButton: MemberIntent()
data object ClickLeftButton: MemberIntent()
data object ClickRightButton: MemberIntent()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ import com.easyhz.noffice.core.common.base.UiSideEffect

sealed class MemberSideEffect: UiSideEffect() {
data object NavigateToUp: MemberSideEffect()
data class NavigateToInitiation(val url: String, val imageUrl: String): MemberSideEffect()
data object HideBottomSheet: MemberSideEffect()
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ import com.easyhz.noffice.core.model.organization.member.MemberType
import com.easyhz.noffice.feature.organization.util.member.MemberViewType

data class MemberState(
val organizationId: Int,
val imageUrl: String?,
val memberList: List<String>,
val viewType: MemberViewType,
val isOpenBottomSheet: Boolean,
val authorityType: MemberType,
): UiState() {
companion object {
fun init() = MemberState(
organizationId = -1,
imageUrl = null,
memberList = emptyList(),
viewType = MemberViewType.MANAGEMENT,
isOpenBottomSheet = false,
Expand Down
Loading

0 comments on commit 4f9056b

Please sign in to comment.