diff --git a/src/apis/management.ts b/src/apis/management.ts index a6f5884..6fb79f5 100644 --- a/src/apis/management.ts +++ b/src/apis/management.ts @@ -1,6 +1,17 @@ import { Axios } from '@apis/axios.ts'; import { TeamData } from '../types/management.ts'; +// 나.. 조회 +export const getMe = async () => { + try { + const response = await Axios.get(`/api/member`); + return response.data.result.name; + console.log(response); + } catch (error) { + console.error(error); + } +}; + // 내 팀 조회 export const getMyTeam = async () => { try { diff --git a/src/assets/management/stop-project-img.svg b/src/assets/management/stop-project-img.svg new file mode 100644 index 0000000..e542191 --- /dev/null +++ b/src/assets/management/stop-project-img.svg @@ -0,0 +1,310 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/management/end-project/CommentInput.tsx b/src/components/management/end-project/CommentInput.tsx index 5e5c63e..8c3adb0 100644 --- a/src/components/management/end-project/CommentInput.tsx +++ b/src/components/management/end-project/CommentInput.tsx @@ -1,15 +1,24 @@ import styled from 'styled-components'; import Profile from '@assets/management/default-profile.svg'; +import { MemberTypes, Role } from '../../../types/member.ts'; -export const CommentInputBox = () => { +interface CommentInputBoxProps { + member: MemberTypes; +} + +export const CommentInputBox = ({ member }: CommentInputBoxProps) => { return ( - - 이름 - - 역할 - + {member.imageUrl ? : } + {member.name} + + {member.roleList?.map((role: Role, index) => ( + + {role.name} + + ))} + @@ -29,6 +38,17 @@ const ProfileContainer = styled.div` margin-bottom: 8px; `; +const ProfileImg = styled.img` + width: 40px; + height: 40px; + border-radius: 100%; +`; + +const TagContainer = styled.div` + display: flex; + gap: 3px; +`; + const Name = styled.p` font-size: 14px; font-weight: 500; @@ -39,7 +59,7 @@ const Name = styled.p` `; const TagBox = styled.div` - width: 37px; + width: 40px; height: 24px; background: white; border-radius: 3px; @@ -52,7 +72,7 @@ const TagPart = styled.p` color: ${({ theme }) => theme.colors.mainBlue}; font-size: 9px; font-weight: 500; - line-height: 13.5px; + line-height: 24px; `; const CommentInput = styled.input` diff --git a/src/components/management/end-project/Comments.tsx b/src/components/management/end-project/Comments.tsx index f979feb..e55163b 100644 --- a/src/components/management/end-project/Comments.tsx +++ b/src/components/management/end-project/Comments.tsx @@ -1,21 +1,51 @@ import styled from 'styled-components'; import { CommentInputBox } from '@components/management/end-project/CommentInput.tsx'; +import { useEffect, useState } from 'react'; +import { MemberTypes } from '../../../types/member.ts'; +import { getMembers } from '@apis/management.ts'; +import { Axios } from '@apis/axios.ts'; export const Comments = () => { + const [me, setMe] = useState(''); + const [members, setMembers] = useState([]); + + useEffect(() => { + const getMe = async () => { + try { + const response = await Axios.get(`/api/member`); + setMe(response.data.result.name); + } catch (error) { + console.error(error); + } + }; + getMe(); + }, []); + + const fetchMembers = async () => { + try { + const response = await getMembers(1); + const filteredMembers = response.filter( + (member: MemberTypes) => member.name !== me + ); + setMembers(filteredMembers); + } catch (error) { + console.error(error); + } + }; + + useEffect(() => { + fetchMembers(); + }, []); + return ( UMC 6th 팀매니저 프로젝트가 종료되었어요! 그동안 고생한 팀원들에게 코멘트를 남길 수 있어요 - - - - - - - - + {members.map((member) => ( + + ))} 임의로 작성 diff --git a/src/components/management/end-project/StopProject.tsx b/src/components/management/end-project/StopProject.tsx new file mode 100644 index 0000000..ee922a6 --- /dev/null +++ b/src/components/management/end-project/StopProject.tsx @@ -0,0 +1,80 @@ +import styled from 'styled-components'; +import People from '@assets/management/stop-project-img.svg'; +import End from '@assets/management/end-icon.svg'; +import { useState } from 'react'; +import { StopProjectModal } from '@components/management/end-project/StopProjectModal.tsx'; + +export const StopProject = () => { + const [showModal, setShowModal] = useState(false); + + const openModal = () => { + setShowModal(true); + }; + + const closeModal = () => { + setShowModal(false); + }; + + return ( + + + 프로젝트가 완료되기 전에 팀을 나가시나요? + 팀장의 종료 이전에 팀을 나가면 포트폴리오에 + 프로젝트 기록이 남지 않습니다. + + + 팀 나가기 + + {showModal && } + + ); +}; + +const StopProjectContainer = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +`; + +const PeopleImg = styled(People)` + margin-top: 91px; +`; + +const TitleText = styled.h1` + font-size: 18px; + font-weight: 500; + color: ${({ theme }) => theme.colors.black}; + margin: 37px 0 10px 0; +`; + +const ContentText = styled.p` + font-size: 12px; + font-weight: 500; + color: ${({ theme }) => theme.colors.darkGray}; + line-height: 18px; + margin: 0; +`; + +const EndBtn = styled.div` + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; + width: 118px; + height: 103px; + border-radius: 4px; + border: solid 1px ${({ theme }) => theme.colors.red}; + margin-top: 19px; + cursor: pointer; +`; + +const EndIcon = styled(End)` + width: 37px; + height: 37px; + margin-top: 19px; +`; + +const BtnText = styled(ContentText)` + color: ${({ theme }) => theme.colors.red}; +`; diff --git a/src/components/management/end-project/StopProjectModal.tsx b/src/components/management/end-project/StopProjectModal.tsx new file mode 100644 index 0000000..9a15702 --- /dev/null +++ b/src/components/management/end-project/StopProjectModal.tsx @@ -0,0 +1,94 @@ +import styled from 'styled-components'; +import { useNavigate } from 'react-router-dom'; + +interface ModalStateProps { + closeModal: () => void; +} + +export const StopProjectModal = ({ closeModal }: ModalStateProps) => { + const navigate = useNavigate(); + + return ( + + + {'팀 매니저'}를 정말 나가실건가요? + 팀에서 나가기 전, 다시 한번 확인해 주세요. + + {/* navigate 수정하기 */} + navigate(`/management/end/comment`)}> + 종료하기 + + 취소 + + + + ); +}; + +const ModalBackground = styled.div` + width: 100%; + height: 100%; + background: rgb(0, 0, 0, 0.1); + position: fixed; + display: flex; + justify-content: center; + align-items: center; + top: 0; + left: 0; +`; + +const ModalContainer = styled.div` + display: flex; + flex-direction: column; + align-items: center; + width: 350px; + height: 200px; + background: white; + border-radius: 6px; + box-shadow: 1.52px 3.04px 9.12px rgba(0, 0, 0 0.08); +`; + +const TitleText = styled.h1` + font-size: 14px; + font-weight: 500; + line-height: 21px; + color: ${({ theme }) => theme.colors.black}; + margin: 58px 0 12px 0; +`; + +const ContentText = styled.p` + font-size: 12px; + line-height: 18px; + color: ${({ theme }) => theme.colors.darkGray}; + margin: 0 0 40px 0; +`; + +const BtnContainer = styled.div` + display: flex; + gap: 4px; +`; + +const Btn = styled.button` + width: 158px; + height: 36px; + border: none; + border-radius: 4px; + display: flex; + justify-content: center; + align-items: center; + font-size: 12px; + font-weight: 700; + line-height: 18px; + cursor: pointer; +`; + +const EndBtn = styled(Btn)` + background: ${({ theme }) => theme.colors.red}; + color: white; +`; + +const CancelBtn = styled(Btn)` + background: white; + color: ${({ theme }) => theme.colors.mainBlue}; + border: solid 1px ${({ theme }) => theme.colors.mainBlue}; +`; diff --git a/src/components/management/member/Member.tsx b/src/components/management/member/Member.tsx index 9dd17eb..0e9753c 100644 --- a/src/components/management/member/Member.tsx +++ b/src/components/management/member/Member.tsx @@ -15,6 +15,7 @@ import { interface MemberProps { teamManageId: number; + imageUrl: string; name: string; roleList: Role[]; refreshMembers: () => void; @@ -22,6 +23,7 @@ interface MemberProps { export const Member = ({ teamManageId, + imageUrl, name, roleList, refreshMembers @@ -55,7 +57,7 @@ export const Member = ({ return ( - + {imageUrl ? : } {name} {tags.map((tag, index) => ( @@ -113,9 +115,16 @@ const MemberContainer = styled.div` align-items: center; `; -const ProfileImg = styled(DefaultProfileImg)` +const ProfileImg = styled.img` width: 40px; height: 40px; + border-radius: 100%; +`; + +const DefaultProfileImage = styled(DefaultProfileImg)` + width: 40px; + height: 40px; + border-radius: 100%; `; const NameContainer = styled.div` diff --git a/src/components/management/member/Members.tsx b/src/components/management/member/Members.tsx index 8120cae..767e854 100644 --- a/src/components/management/member/Members.tsx +++ b/src/components/management/member/Members.tsx @@ -34,6 +34,7 @@ export const Members = () => { members.map((member) => ( theme.colors.lightGray}; + border-radius: 76px; + } + + &::-webkit-scrollbar-thumb:active { + background: ${({ theme }) => theme.colors.darkGray}; + } + +\` ; `; diff --git a/src/components/sidebar/SideBar.tsx b/src/components/sidebar/SideBar.tsx index 1a28246..419c837 100644 --- a/src/components/sidebar/SideBar.tsx +++ b/src/components/sidebar/SideBar.tsx @@ -20,21 +20,49 @@ import End from '@assets/sidebar/end.svg'; import { useLocation, useNavigate } from 'react-router-dom'; import { useEffect, useState } from 'react'; import { DropDown } from '@components/sidebar/DropDown.tsx'; -import { getMyTeam } from '@apis/management.ts'; +import { getMe, getMembers, getMyTeam } from '@apis/management.ts'; import { TeamProps } from '../../types/management.ts'; +import { MemberTypes } from '../../types/member.ts'; export const SideBar = () => { const [teams, setTeams] = useState([]); const [currentTeam, setCurrentTeam] = useState(null); const [hover, setHover] = useState(false); const [showDropDown, setShowDropDown] = useState(false); + const [isLeader, setIsLeader] = useState(false); const navigate = useNavigate(); const location = useLocation(); + useEffect(() => { + const checkLeader = async () => { + try { + const members = await getMembers(1); + const me = await getMe(); + + // 팀장 + const leader = members.reduce( + (prev: MemberTypes, curr: MemberTypes) => { + return prev.teamManageId < curr.teamManageId ? prev : curr; + } + ); + setIsLeader(me.teamManageId === leader.teamManageId); + } catch (error) { + console.error(error); + } + }; + checkLeader(); + }, []); + const handleNavigate = (path: string) => { navigate(path); }; + const handleNavigateEnd = () => { + if (isLeader) { + navigate(`/management/end`); + } else navigate(`/management/stop`); + }; + const handleDropDown = () => { setShowDropDown((prev) => !prev); }; @@ -191,19 +219,16 @@ export const SideBar = () => { 마이페이지 )} - { - // 추후에 path 수정이 필요할 수 있음 - handleNavigate(`/management`); - }} - isHovered={hover} - > + {hover && ( - - 프로젝트 -
- 종료 + + {isLeader ? '프로젝트 종료' : '팀 나가기'} )}
@@ -269,7 +294,7 @@ const Wrapper = styled.div` interface SelectedProps { selected?: boolean; - redText?: boolean; + red?: boolean; isHovered?: boolean; } @@ -283,8 +308,8 @@ const SideBarText = styled.p` white-space: nowrap; overflow: hidden; - ${({ redText, theme }) => - redText && + ${({ red, theme }) => + red && ` color: ${theme.colors.red}; `} @@ -293,8 +318,6 @@ const SideBarText = styled.p` const IconContainer = styled.div` width: 100%; height: 51px; - background-color: ${({ selected, theme }) => - selected ? theme.colors.background : 'white'}; display: flex; justify-content: ${({ isHovered }) => (isHovered ? 'flex-start' : 'center')}; padding-left: ${({ isHovered }) => (isHovered ? '19px' : '0')}; @@ -304,6 +327,14 @@ const IconContainer = styled.div` cursor: pointer; transition: width 0.3s ease; + // 얘 안돼 ㅜ.ㅜ + background-color: ${({ selected, theme, red }) => { + if (selected) { + return red ? '#FFE9E9' : theme.colors.background; + } + return 'white'; + }}; + &:last-child { margin-top: 18px; } diff --git a/src/pages/management/extra.tsx b/src/pages/management/extra.tsx index cb5fa61..2836031 100644 --- a/src/pages/management/extra.tsx +++ b/src/pages/management/extra.tsx @@ -1,11 +1,13 @@ import { Route, Routes } from 'react-router-dom'; import { EndProject } from '@components/management/end-project/EndProject.tsx'; import { Comments } from '@components/management/end-project/Comments.tsx'; +import { StopProject } from '@components/management/end-project/StopProject.tsx'; export const ExtraManagementPage = () => { return ( } /> + } /> } /> );