Skip to content

Commit

Permalink
feature: add organization
Browse files Browse the repository at this point in the history
  • Loading branch information
gracefulBrown committed Dec 28, 2024
1 parent f39025b commit b8433e5
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,31 @@
import wooteco.prolog.member.application.dto.MembersResponse;
import wooteco.prolog.member.application.dto.ProfileIntroRequest;
import wooteco.prolog.member.application.dto.ProfileIntroResponse;
import wooteco.prolog.member.application.dto.ProfileResponse;
import wooteco.prolog.member.application.dto.RoleUpdateRequest;
import wooteco.prolog.member.domain.Member;
import wooteco.prolog.member.domain.MemberCreatedEvent;
import wooteco.prolog.member.domain.MemberUpdatedEvent;
import wooteco.prolog.member.domain.Role;
import wooteco.prolog.member.domain.repository.MemberRepository;
import wooteco.prolog.organization.application.OrganizationService;
import wooteco.prolog.organization.domain.OrganizationGroup;
import wooteco.prolog.organization.domain.OrganizationGroupMember;

@Service
@Transactional(readOnly = true)
public class MemberService {

private final Role mangerRole;
private final OrganizationService organizationService;
private final ApplicationEventPublisher eventPublisher;
private final MemberRepository memberRepository;

public MemberService(@Value("${manager.role}") Role mangerRole,
public MemberService(@Value("${manager.role}") Role mangerRole, OrganizationService organizationService,
ApplicationEventPublisher eventPublisher,
MemberRepository memberRepository) {
this.mangerRole = mangerRole;
this.organizationService = organizationService;
this.eventPublisher = eventPublisher;
this.memberRepository = memberRepository;
}
Expand All @@ -66,9 +72,10 @@ public Member findByUsername(String username) {
.orElseThrow(() -> new BadRequestException(MEMBER_NOT_FOUND));
}

public MemberResponse findMemberResponseByUsername(String username) {
public ProfileResponse findMemberResponseByUsername(String username) {
Member member = findByUsername(username);
return MemberResponse.of(member);
List<OrganizationGroup> groups = organizationService.findOrganizationGroupsByMemberId(member.getId());
return ProfileResponse.of(member, groups);
}

public ProfileIntroResponse findProfileIntro(String username) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package wooteco.prolog.member.application.dto;

import java.util.List;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import wooteco.prolog.member.domain.Member;
import wooteco.prolog.organization.domain.OrganizationGroup;

@NoArgsConstructor
@AllArgsConstructor
@Getter
public class ProfileResponse {

private Long id;
private String username;
private String nickname;
private String imageUrl;
private String rssFeedUrl;
private List<String> organizationGroups;

public static ProfileResponse of(Member member, List<OrganizationGroup> organizationGroups) {
List<String> organizationGroupNames = organizationGroups.stream().map(OrganizationGroup::getName).collect(
Collectors.toList());

return new ProfileResponse(member.getId(), member.getUsername(), member.getNickname(),
member.getImageUrl(), member.getRssFeedUrl(), organizationGroupNames);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,35 @@
import java.util.stream.Collectors;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import wooteco.prolog.member.application.MemberService;
import wooteco.prolog.member.domain.MemberCreatedEvent;
import wooteco.prolog.organization.domain.Organization;
import wooteco.prolog.organization.domain.OrganizationGroup;
import wooteco.prolog.organization.domain.OrganizationGroupMember;
import wooteco.prolog.organization.domain.OrganizationGroupSession;
import wooteco.prolog.organization.domain.repository.OrganizationGroupMemberRepository;
import wooteco.prolog.organization.domain.repository.OrganizationGroupRepository;
import wooteco.prolog.organization.domain.OrganizationGroupSession;
import wooteco.prolog.organization.domain.repository.OrganizationGroupSessionRepository;
import wooteco.prolog.organization.domain.repository.OrganizationRepository;
import wooteco.prolog.session.domain.Session;

@Service
public class OrganizationService {

private final MemberService memberService;
private final OrganizationRepository organizationRepository;
private final OrganizationGroupRepository organizationGroupRepository;
private final OrganizationGroupMemberRepository organizationGroupMemberRepository;
private final OrganizationGroupSessionRepository organizationGroupSessionRepository;

public OrganizationService(OrganizationRepository organizationRepository,
OrganizationGroupRepository organizationGroupRepository, MemberService memberService,
OrganizationGroupRepository organizationGroupRepository,
OrganizationGroupMemberRepository organizationGroupMemberRepository,
OrganizationGroupSessionRepository organizationGroupSessionRepository) {
this.organizationRepository = organizationRepository;
this.organizationGroupRepository = organizationGroupRepository;
this.memberService = memberService;
this.organizationGroupMemberRepository = organizationGroupMemberRepository;
this.organizationGroupSessionRepository = organizationGroupSessionRepository;
}

//
// public List<OrganizationGroup> findMyOrganizationGroupByMemberId(Long memberId) {
// List<OrganizationGroupMember> organizationGroupMembers = organizationGroupMemberRepository.findByMemberId(
// memberId);
// List<Long> organizationGroupId = organizationGroupMembers.stream()
// .map(it -> it.getOrganizationGroupId())
// .collect(Collectors.toList());
//
// List<OrganizationGroup> organizationGroups = organizationGroupRepository.findByIdIn(organizationGroupId);
// return organizationGroups;
// }

public Organization saveOrganization(String name) {
return organizationRepository.save(new Organization(name));
}
Expand Down Expand Up @@ -109,4 +94,10 @@ public void handleMemberCreatedEvent(MemberCreatedEvent event) {
// 조회한 OrganizationGroupMember 의 memberId를 변경
organizationGroupMembers.forEach(it -> it.updateMemberId(event.getMember().getId()));
}

public List<OrganizationGroup> findOrganizationGroupsByMemberId(Long memberId) {
List<Long> organizationGroupIds = organizationGroupMemberRepository.findByMemberId(
memberId).stream().map(OrganizationGroupMember::getOrganizationGroupId).collect(Collectors.toList());
return organizationGroupRepository.findByIdInOrderByIdDesc(organizationGroupIds);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ public interface OrganizationGroupMemberRepository extends JpaRepository<Organiz
List<OrganizationGroupMember> findByUsername(String username);

List<OrganizationGroupMember> findByMemberId(Long memberId);

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package wooteco.prolog.organization.domain.repository;

import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import wooteco.prolog.organization.domain.OrganizationGroup;

public interface OrganizationGroupRepository extends JpaRepository<OrganizationGroup, Long> {

List<OrganizationGroup> findByIdInOrderByIdDesc(List<Long> organizationGroupIds);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import wooteco.prolog.member.application.dto.MemberResponse;
import wooteco.prolog.member.application.dto.ProfileIntroRequest;
import wooteco.prolog.member.application.dto.ProfileIntroResponse;
import wooteco.prolog.member.application.dto.ProfileResponse;
import wooteco.prolog.studylog.application.StudylogService;
import wooteco.prolog.studylog.application.dto.StudylogsResponse;

Expand Down Expand Up @@ -72,9 +73,9 @@ public ResponseEntity<StudylogsResponse> findAllStudylogsOfMine(@PathVariable St
}

@GetMapping(value = "/{username}/profile", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<MemberResponse> findMemberProfile(@PathVariable String username) {
MemberResponse member = memberService.findMemberResponseByUsername(username);
return ResponseEntity.ok().body(member);
public ResponseEntity<ProfileResponse> findMemberProfile(@PathVariable String username) {
ProfileResponse profileResponse = memberService.findMemberResponseByUsername(username);
return ResponseEntity.ok().body(profileResponse);
}

@GetMapping(value = "/{username}/profile-intro", produces = MediaType.APPLICATION_JSON_VALUE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.LongStream;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
Expand All @@ -34,10 +35,12 @@
import wooteco.prolog.member.application.dto.MembersResponse;
import wooteco.prolog.member.application.dto.ProfileIntroRequest;
import wooteco.prolog.member.application.dto.ProfileIntroResponse;
import wooteco.prolog.member.application.dto.ProfileResponse;
import wooteco.prolog.member.application.dto.RoleUpdateRequest;
import wooteco.prolog.member.domain.Member;
import wooteco.prolog.member.domain.Role;
import wooteco.prolog.member.domain.repository.MemberRepository;
import wooteco.prolog.organization.application.OrganizationService;

@ExtendWith(MockitoExtension.class)
class MemberServiceTest {
Expand All @@ -48,12 +51,14 @@ class MemberServiceTest {

@Mock
private ApplicationEventPublisher eventPublisher;
@Mock
private OrganizationService organizationService;

private MemberService memberService;

@BeforeEach
void setUp() {
memberService = new MemberService(MANGER_ROLE, eventPublisher, memberRepository);
memberService = new MemberService(MANGER_ROLE, organizationService, eventPublisher, memberRepository);
}

@DisplayName("findOrCreateMember() : gitHub Id 를 통해서 이미 존재한 Member 조회")
Expand Down Expand Up @@ -169,27 +174,25 @@ void findByUsername_MemberNotFoundException() {
.hasMessage(MEMBER_NOT_FOUND.getMessage());
}

@DisplayName("findMemberResponseByUsername() : username을 통해서 MemberResponse를 조회할 수 있다.")
@DisplayName("findMemberResponseByUsername() : username 을 통해서 ProfileResponse 를 조회할 수 있다.")
@Test
void findMemberResponseByUsername() {
//given
final String username = "username";
final String nickname = "nickname";
final String imageUrl = "imageUrl";

final MemberResponse memberResponse = new MemberResponse(1L, username, nickname, Role.ADMIN,
imageUrl);
final Member member = new Member(1L, username, nickname, Role.ADMIN, 1L, imageUrl);
final ProfileResponse profileResponse = ProfileResponse.of(member, Lists.emptyList());

when(memberRepository.findByUsername(any()))
.thenReturn(Optional.of(member));

//when
final MemberResponse foundMemberResponse = memberService.findMemberResponseByUsername(
username);
final ProfileResponse foundMemberResponse = memberService.findMemberResponseByUsername(username);

//then
assertEquals(foundMemberResponse, memberResponse);
assertEquals(foundMemberResponse.getUsername(), profileResponse.getUsername());
}

@DisplayName("ProfileIntroResponse() : username을 통해서 ProfileIntroResponse를 조회할 수 있다.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,25 @@ const RssFeedUrl = styled.div`
`;

const Role = styled.div`
margin-top: 1rem;
margin-bottom: 1rem;
padding-left: 1.2rem;
font-size: 1.2rem;
color: ${COLOR.LIGHT_GRAY_900};
`;

const RoleButton = styled.button`
margin-top: .3rem;
font-size: 1.2rem;
color: ${COLOR.DARK_GRAY_700};
`;

const RoleLabel = styled.div`
margin-top: 1rem;
padding-left: 1.2rem;
font-size: 1.5rem;
color: ${COLOR.DARK_GRAY_700};
`;

const RssLinkLabel = styled.div`
margin-top: 1rem;
padding-left: 1.2rem;
Expand Down Expand Up @@ -196,6 +209,8 @@ export {
Nickname,
RssFeedUrl,
Role,
RoleButton,
RoleLabel,
RssLinkLabel,
MenuList,
MenuItem,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
MenuItem,
MenuButton,
Role,
RoleButton,
RoleLabel,
RssLinkLabel,
Container,
EditButtonStyle,
Expand Down Expand Up @@ -86,10 +88,30 @@ const ProfilePageSideBar = ({ menu }: ProfilePageSideBarProps) => {
history.push(path);
};

const [showAll, setShowAll] = useState(false); // 상태 관리: 전체 표시 여부

const toggleShowAll = () => setShowAll((prev) => !prev); // 상태 토글 함수

const displayedGroups = showAll
? user?.organizationGroups // 전체 항목 표시
: user?.organizationGroups?.slice(0, 2); // 첫 2개만 표시

return (
<Container>
<Profile>
<Image src={user?.imageUrl} alt="프로필 이미지" /> <Role>{user?.role}</Role>
<Image src={user?.imageUrl} alt="프로필 이미지" />
<RoleLabel>소속</RoleLabel>
<Role>
{displayedGroups?.map((group, index) => (
<div key={index}>{group}</div>
))}

{user?.organizationGroups?.length > 2 && (
<RoleButton onClick={toggleShowAll}>
{showAll ? "가리기" : "더보기"}
</RoleButton>
)}
</Role>
<NicknameWrapper>
{isProfileEditing ? (
<NicknameInput
Expand Down

0 comments on commit b8433e5

Please sign in to comment.