-
+
+ ) =>
+ setActivityEndDate(e.target.value)
+ }
+ $isValid={isActivityEndDateValid()}
+ />
+
+ YYYY-MM-DD와 동일한 형식으로 올바른 날짜를 입력해주세요.
+
+
활동 종료 날짜에 팀원 모두에게 추천사 작성 링크가 발송됩니다. 팀
활동 종료 후 추천사를 작성할 날짜로 입력해주세요.
@@ -47,6 +127,7 @@ const MyTeamCreateOpen = () => {
setText1(e.target.value)}
/>
@@ -58,6 +139,7 @@ const MyTeamCreateOpen = () => {
setText2(e.target.value)}
/>
@@ -69,6 +151,7 @@ const MyTeamCreateOpen = () => {
setText3(e.target.value)}
/>
@@ -121,13 +204,36 @@ const FormInputBox = styled.div`
gap: 0.8rem;
`;
-const RecruitmentInput = styled(Input)`
+const RecruitmentInput = styled(Input)<{ $isValid: boolean }>`
width: 7rem;
margin-right: 0.5rem;
+ border-color: ${({ $isValid, theme }) =>
+ $isValid ? theme.colors.gray40 : theme.colors.error60};
+ color: ${({ $isValid, theme }) =>
+ $isValid ? 'inherit' : theme.colors.error60};
+`;
+
+const Description = styled.div<{ $isValid: boolean }>`
+ color: ${({ $isValid, theme }) =>
+ $isValid ? 'inherit' : theme.colors.error60};
+`;
+
+const ActivityDescription = styled(Description)<{ $isValid: boolean }>`
+ display: ${({ $isValid }) => ($isValid ? 'none' : 'block')};
+`;
+
+const ActivityInputBox = styled.div`
+ display: flex;
+ align-items: center;
+ gap: 1rem;
`;
-const ActivityEndInput = styled(Input)`
+const ActivityEndInput = styled(Input)<{ $isValid: boolean }>`
width: 20rem;
+ border-color: ${({ $isValid, theme }) =>
+ $isValid ? theme.colors.gray40 : theme.colors.error60};
+ color: ${({ $isValid, theme }) =>
+ $isValid ? 'inherit' : theme.colors.error60};
`;
const Hr = styled.hr`
diff --git a/src/components/myteam/MyTeamOpen.tsx b/src/components/myteam/MyTeamOpen.tsx
deleted file mode 100644
index 1317739..0000000
--- a/src/components/myteam/MyTeamOpen.tsx
+++ /dev/null
@@ -1,103 +0,0 @@
-import { styled } from 'styled-components';
-import Button from '../common/Button';
-import Title from '../common/Title';
-import ProfileBoxMember from '../common/ProfileBoxMember';
-
-const teamMember = {
- teamMemberId: 1,
- teamMemberName: '김민수',
- teamMemberImage: '/assets/images/review/profile.svg',
- teamMemberTask: ['기획', '디자인'],
- teamMemberMajor: ['경영학과', '컴퓨터공학과'],
-};
-
-const MyTeamOpen = () => {
- return (
-
-
-
- 2024 국제 대학생 창업교류전 한국대표 모집
-
-
-
-
-
- <>
- 합류한 팀원들
-
-
-
- >
- <>
- 지원자
-
-
-
- >
-
-
- );
-};
-
-export default MyTeamOpen;
-
-const MyTeamOpenContainer = styled.div`
- display: flex;
- align-items: center;
- justify-content: center;
- background: ${({ theme }) => theme.colors.primary10};
- padding: 6rem 10rem;
- gap: 4rem;
-`;
-
-const CompetitionBox = styled.div`
- display: flex;
- flex-direction: column;
- align-items: center;
- width: 25rem;
- gap: 1.5rem;
-`;
-
-const TeamMemberBox = styled.div`
- display: flex;
- flex-direction: column;
- align-items: center;
- width: 100%;
-`;
-
-const TeamMembers = styled.div`
- border-radius: 8px;
- background: ${({ theme }) => theme.colors.white};
- padding: 2rem;
-
- display: flex;
- gap: 1.5rem;
- overflow-x: scroll;
-`;
-
-const CompetitionTitle = styled.div`
- ${({ theme }) => theme.fonts.subtitleXL};
- color: ${({ theme }) => theme.colors.gray90};
-`;
-
-const CompetitionImg = styled.img`
- width: 100%;
- height: 31.7rem;
- object-fit: cover;
- border-radius: 8px;
- border: 1px solid ${({ theme }) => theme.colors.gray40};
-`;
diff --git a/src/components/myteam/active/MyTeamActiveContainer.tsx b/src/components/myteam/active/MyTeamActiveContainer.tsx
new file mode 100644
index 0000000..6200470
--- /dev/null
+++ b/src/components/myteam/active/MyTeamActiveContainer.tsx
@@ -0,0 +1,164 @@
+import styled from 'styled-components';
+import { ActiveTeamData } from '../../../interface/MyTeam';
+import starSrc from '/assets/images/common/star.svg';
+import TeamMemberScrollBox from './TeamMemberScrollBox';
+
+const MyTeamActiveContainer: React.FC = (props) => {
+ return (
+
+
+
+ {props.contestTitle}
+
+
+
+
+ 카카오톡 오픈채팅방 링크 :
+ {props.chatLink}
+
+
+
+ 팀원 :
+ {props.memberSize}명
+ {' '}
+
+ 활동 지역 :
+ {props.location}
+ {' '}
+
+ 활동 종료 예정일 :
+ {props.endDate}
+ {' '}
+
+ 팀장의 한마디 :
+ {props.leaderMessage}
+ {' '}
+
+ 모집 공고 :
+ {props.notice}
+
+
+
+
+
+
+ 합류한 팀원들
+ 총 {props.memberSize}명
+
+
+
+ );
+};
+const Layout = styled.div`
+ width: 100%;
+ /* height: 80.3rem; */
+ background-color: ${(props) => props.theme.colors.primary10};
+
+ border: 1px solid ${(props) => props.theme.colors.primary10};
+ border-radius: 1.4rem;
+
+ display: flex;
+ flex-direction: column;
+ gap: 2rem;
+
+ padding: 3rem 4rem;
+`;
+const ContestInfoContainer = styled.div`
+ display: flex;
+ justify-content: center;
+ /* align-items: center; */
+ gap: 2rem;
+`;
+//공모전 제목 및 이미지 박스
+const TitleBox = styled.div`
+ width: 17rem;
+
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ justify-content: center;
+ align-items: center;
+`;
+const Title = styled.div`
+ ${(props) => props.theme.fonts.subtitleS};
+ color: ${(props) => props.theme.colors.gray90};
+ width: 100%;
+`;
+const ContestImg = styled.img`
+ width: 16.9rem;
+ /* height: 23.1rem; */
+ border-radius: 0.5rem;
+`;
+
+// 공모전 링크 및 정보 박스
+const ContentBox = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ justify-content: center;
+ align-items: center;
+
+ flex-grow: 1;
+`;
+const KakaotalkLink = styled.div`
+ width: 100%;
+
+ ${(props) => props.theme.fonts.subtitleM};
+ color: ${(props) => props.theme.colors.white};
+ background-color: ${(props) => props.theme.colors.primary40};
+
+ display: flex;
+ /* justify-content: center; */
+ align-items: center;
+
+ border-radius: 1.2rem;
+ border: 1px soild ${(props) => props.theme.colors.gray20};
+
+ padding: 1.3rem 2.8rem;
+ a {
+ text-decoration: underline;
+ }
+`;
+const TeamInfoBox = styled.div`
+ width: 100%;
+
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ /* align-items: center; */
+ gap: 0.7rem;
+
+ border-radius: 0.8rem;
+ background-color: ${(props) => props.theme.colors.white};
+
+ padding: 2.1rem 2.5rem;
+`;
+const TeamInfoItem = styled.div`
+ ${(props) => props.theme.fonts.bodyM};
+ color: ${(props) => props.theme.colors.gray90};
+
+ span,
+ div {
+ ${(props) => props.theme.fonts.subtitleM};
+ }
+`;
+const MemberTitle = styled.div`
+ display: flex;
+ align-items: center;
+ gap: 0.8rem;
+ & span:nth-child(2) {
+ ${(props) => props.theme.fonts.heading4};
+ color: ${(props) => props.theme.colors.primary90};
+ }
+ & span:nth-child(3) {
+ ${(props) => props.theme.fonts.subtitleL};
+ color: ${(props) => props.theme.colors.primary40};
+ }
+`;
+const StarImg = styled.img`
+ width: 2.8rem;
+`;
+export default MyTeamActiveContainer;
diff --git a/src/components/myteam/active/TeamMemberScrollBox.tsx b/src/components/myteam/active/TeamMemberScrollBox.tsx
new file mode 100644
index 0000000..b8cdb84
--- /dev/null
+++ b/src/components/myteam/active/TeamMemberScrollBox.tsx
@@ -0,0 +1,57 @@
+import styled from 'styled-components';
+import { ProfileBoxProps, ProfileProps } from '../../../interface/Contest';
+import ProfileBoxMember from '../../common/ProfileBoxMember';
+import { Role } from '../../contest/RecruitTeamItem';
+interface TeamMemberScrollBoxProps {
+ teamLeaderInfo: ProfileProps;
+ teamMembersInfo: ProfileProps[];
+ width?: number;
+}
+const TeamMemberScrollBox: React.FC = (props) => {
+ return (
+
+
+ 팀장
+
+
+ {props.teamMembersInfo.map((memberData) => {
+ const profileProps: ProfileBoxProps = {
+ hasBorder: true,
+ hasProfileButton: true,
+ isBgColorWhite: true,
+ memberInfo: memberData,
+ };
+ return ;
+ })}
+
+ );
+};
+const Layout = styled.div`
+ display: flex;
+ gap: 2.4rem;
+
+ overflow-x: scroll;
+
+ padding: 20px 0;
+
+ &::-webkit-scrollbar {
+ width: 7px;
+ height: 7px;
+ border-radius: 6px;
+ /* background: ${(props) => props.theme.colors.gray20}; */
+ }
+ &::-webkit-scrollbar-thumb {
+ background: ${(props) => props.theme.colors.primary60};
+ border-radius: 6px;
+ }
+`;
+const TeamLeaderTmpBox = styled.div`
+ position: relative;
+ ${(props) => props.theme.fonts.subtitleS};
+`;
+export default TeamMemberScrollBox;
diff --git a/src/components/myteam/apply/MyTeamApplyContainer.tsx b/src/components/myteam/apply/MyTeamApplyContainer.tsx
index acb7760..798214e 100644
--- a/src/components/myteam/apply/MyTeamApplyContainer.tsx
+++ b/src/components/myteam/apply/MyTeamApplyContainer.tsx
@@ -1,14 +1,57 @@
import styled from 'styled-components';
import { AppliedTeamData } from '../../../interface/MyTeam';
+import ProfileBoxMember from '../../common/ProfileBoxMember';
+import { ProfileBoxProps } from '../../../interface/Contest';
+import { Role } from '../../contest/RecruitTeamItem';
+import { useNavigate } from 'react-router-dom';
const MyTeamApplyContainer: React.FC = (props) => {
- props;
+ const teamLeaderBoxProps: ProfileBoxProps = {
+ hasBorder: true,
+ hasProfileButton: false,
+ isBgColorWhite: false,
+ memberInfo: props.leaderInfo,
+ // width: 20,
+ // height: 22.7,
+ };
+ const navigate = useNavigate();
return (
-
- {/* */}
+ {props.contestTitle}
+
+
+
+ 팀장
+
+
+ navigate(`/list/${props.contestId}/${props.teamId}`)}
+ >
+ 자세히 보러가기
+
+
+
+
+ 팀 합류 여부 :
+
+ {props.status}
+
+
+
+ 팀장의 한 마디
+
+
+ {props.leaderMessage}
+
+
+ 모집 현황 : {props.cur}명 / {props.max}명{' '}
+
+ 활동 지역 : {props.location}
+ 활동 종료 예정일 : {props.endDate}
+
+
);
};
@@ -16,16 +59,164 @@ const Layout = styled.div`
width: 100%;
height: 35.3rem;
background-color: ${(props) => props.theme.colors.primary10};
+
+ border: 1px solid ${(props) => props.theme.colors.primary10};
+ border-radius: 1.4rem;
+
+ display: flex;
+ justify-content: center;
+ /* align-items: center; */
+ gap: 2rem;
+
+ padding: 3rem 4rem;
+`;
+const TitleBox = styled.div`
+ width: 17rem;
+
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ justify-content: center;
+ align-items: center;
`;
-const TitleBox = styled.div``;
const Title = styled.div`
${(props) => props.theme.fonts.subtitleS};
color: ${(props) => props.theme.colors.gray90};
width: 100%;
- height: 35.3rem;
`;
-// const ContestImg = styled.img`
-// width: 16.9rem;
-// height: 23.1rem;
-// `;
+const ContestImg = styled.img`
+ width: 16.9rem;
+ /* height: 23.1rem; */
+ border-radius: 0.5rem;
+`;
+
+//팀장 컴포넌트 박스
+const TeamLeaderBox = styled.div`
+ width: 17rem;
+ /* height: 100%; */
+
+ /* flex-grow: 1; */
+
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ gap: 1rem;
+
+ margin-top: 2rem;
+`;
+const TeamLeaderEmptyBox = styled.div`
+ position: relative;
+ ${(props) => props.theme.fonts.subtitleS};
+`;
+const TeamInfoButton = styled.button`
+ height: 3rem;
+
+ color: ${(props) => props.theme.colors.white};
+ background-color: ${(props) => props.theme.colors.primary40};
+ border-radius: 0.8rem;
+
+ display: flex;
+ justify-content: center;
+ align-items: center;
+`;
+
+//팀 정보 박스
+const TeamInfoBox = styled.div`
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ /* align-items: center; */
+ gap: 1rem;
+
+ flex-grow: 1;
+
+ ${(props) => props.theme.fonts.subtitleM}
+ border: 1px solid ${(props) => props.theme.colors.gray20};
+ border-radius: 0.8rem;
+
+ padding: 2.7rem 3.6rem;
+ margin-top: 2rem;
+`;
+const TeamJoinStatus = styled.div`
+ display: flex;
+ align-items: center;
+
+ gap: 0.5rem;
+ /* border-radius: 0.7rem; */
+`;
+const TeamJoinStatusBox = styled.div<{ $status: any }>`
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ /* width: 5.2rem; */
+ height: 3.3rem;
+
+ border-radius: 0.7rem;
+ color: ${(props) => props.theme.colors.white};
+ background-color: ${(props) => {
+ if (props.$status === '합류') {
+ return '#83C877';
+ } else if (props.$status === '검토 중') {
+ return '#F5BD68';
+ } else if (props.$status === '반려') {
+ return '#D9635D';
+ } else {
+ console.log('민정아 반환값 잘못줬다.');
+ return '#83C877'; // 다른 경우 투명색 또는 다른 적절한 기본값
+ }
+ }};
+
+ padding: 0.3rem 0.8rem;
+`;
+
+const TeamLeaderIntroduceTitle = styled.div`
+ color: ${(props) => props.theme.colors.gray90};
+
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 1rem;
+
+ width: 100%;
+ > div {
+ flex-grow: 1; //너비를 제외하고 최대로 차지
+ height: 1px;
+ border-top: 1px solid ${(props) => props.theme.colors.primary40};
+ }
+`;
+
+//재사용
+
+const TeamLeaderIntroduce = styled.div`
+ width: 100%;
+ height: 100px;
+
+ border: 1px solid ${(props) => props.theme.colors.gray40};
+ border-radius: 1.2rem;
+ background-color: ${(props) => props.theme.colors.white};
+
+ color: ${(props) => props.theme.colors.primary60};
+
+ display: flex;
+ justify-content: center;
+ align-items: center;
+`;
+const TeamStatusBox = styled.div`
+ width: 100%;
+ /* height: 100px; */
+
+ color: ${(props) => props.theme.colors.primary60};
+
+ display: flex;
+ /* justify-content: center; */
+ align-items: center;
+ gap: 6rem;
+`;
+const TeamStatusItem = styled.div`
+ color: ${(props) => props.theme.colors.gray90};
+ span {
+ color: ${(props) => props.theme.colors.primary60};
+ }
+`;
export default MyTeamApplyContainer;
diff --git a/src/components/myteam/end/MyTeamEndBox.tsx b/src/components/myteam/end/MyTeamEndBox.tsx
new file mode 100644
index 0000000..49046b4
--- /dev/null
+++ b/src/components/myteam/end/MyTeamEndBox.tsx
@@ -0,0 +1,142 @@
+import { styled } from 'styled-components';
+import StarTtile from '../../common/StarTtile';
+import Button from '../../common/Button';
+import TeamMemberScrollBox from '../active/TeamMemberScrollBox';
+import Title from '../../common/Title';
+import { EndTeamData } from '../../../interface/MyTeam';
+
+interface MyTeamEndBoxProps {
+ endTeam: EndTeamData;
+}
+
+const MyTeamEndBox = ({ endTeam }: MyTeamEndBoxProps) => {
+ return (
+
+ {endTeam && (
+ <>
+
+ 다음 팀 활동을 위해
+ 팀원들에게 추천사를 남겨주세요!
+ 팀원들에게 추천사를 남겨야
+ 내가 받은 추천사를 볼 수 있어요!
+
+
+
+ 추천사 작성하러 가기
+
+
+
+
+
+
+ 대회명
+ {endTeam.contestTitle}
+
+
+
+ 함께했던 팀원들 총 {endTeam.memberSize}명
+
+ 활동 종료일 : {endTeam.endDate}
+
+ {endTeam.leaderInfo && endTeam.teamMemberInfos && (
+
+ )}
+
+ >
+ )}
+
+ );
+};
+
+export default MyTeamEndBox;
+
+const MyTeamEndBoxContainer = styled.div`
+ display: flex;
+ background: ${({ theme }) => theme.colors.primary10};
+ padding: 6rem;
+ gap: 4rem;
+ border-radius: 10px;
+ margin-bottom: 3rem;
+`;
+
+const Box = styled.div`
+ background: ${({ theme }) => theme.colors.white};
+ border-radius: 10px;
+ border: 1px solid ${({ theme }) => theme.colors.gray20};
+`;
+
+const MyTeamEndLeft = styled(Box)`
+ width: 35%;
+ padding: 5rem 5.5rem;
+
+ h1 {
+ ${({ theme }) => theme.fonts.subtitleXL};
+ color: ${({ theme }) => theme.colors.primary60};
+ margin-bottom: 1.5rem;
+ }
+ p {
+ ${({ theme }) => theme.fonts.bodyM};
+ color: ${({ theme }) => theme.colors.primary90};
+ }
+`;
+
+const MyTeamDiv = styled.div`
+ margin: 3rem 0 5rem 0;
+ text-align: center;
+ position: relative;
+`;
+
+const MyTeamEndRight = styled.div`
+ width: 65%;
+ display: flex;
+ justify-content: space-between;
+ flex-direction: column;
+`;
+
+const MyTeamEndRightTop = styled(Box)`
+ padding: 1rem 2rem;
+ display: flex;
+ align-items: center;
+
+ gap: 1.5rem;
+ color: ${({ theme }) => theme.colors.gray90};
+ p {
+ ${({ theme }) => theme.fonts.bodyL};
+ }
+ h1 {
+ ${({ theme }) => theme.fonts.subtitleL};
+ }
+`;
+
+const ButtonStyle = styled(Button)`
+ height: 6rem;
+ position: absolute;
+ bottom: -5rem;
+ left: 50%;
+ transform: translateX(-50%);
+ padding: 0 4rem;
+`;
+
+const RightFlexBox = styled.div`
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ p {
+ ${({ theme }) => theme.fonts.subtitleS};
+ color: ${({ theme }) => theme.colors.gray90};
+ }
+`;
+
+const EndTitle = styled(Title)`
+ ${({ theme }) => theme.fonts.subtitleL};
+`;
diff --git a/src/components/myteam/open/FormTitle.tsx b/src/components/myteam/open/FormTitle.tsx
new file mode 100644
index 0000000..7d58f20
--- /dev/null
+++ b/src/components/myteam/open/FormTitle.tsx
@@ -0,0 +1,37 @@
+import { styled } from 'styled-components';
+
+interface FormTitleProps {
+ title: string;
+}
+
+const FormTitle = ({ title }: FormTitleProps) => {
+ return (
+
+
+ {title}
+
+
+
+ );
+};
+
+export default FormTitle;
+
+const FormTitleBox = styled.div`
+ min-width: 20rem;
+`;
+
+const FormTitleText = styled.div`
+ position: relative;
+ ${({ theme }) => theme.fonts.subtitleXXL};
+ color: ${({ theme }) => theme.colors.gray90};
+ display: inline-block;
+`;
+
+const FormTitleCircle = styled.img`
+ width: 0.8rem;
+ height: 0.8rem;
+ position: absolute;
+ top: -0.1rem;
+ right: -1.4rem;
+`;
diff --git a/src/components/myteam/open/MyTeamOpenBox.tsx b/src/components/myteam/open/MyTeamOpenBox.tsx
new file mode 100644
index 0000000..d8005d6
--- /dev/null
+++ b/src/components/myteam/open/MyTeamOpenBox.tsx
@@ -0,0 +1,193 @@
+import { styled } from 'styled-components';
+import Button from '../../common/Button';
+import ProfileBoxMember from '../../common/ProfileBoxMember';
+import StarTitle from '../../common/StarTtile';
+import { TeamData } from '../../../interface/MyTeam';
+
+interface MyTeamOpenBoxProps {
+ myTeamOpen: TeamData;
+}
+
+const MyTeamOpenBox = ({ myTeamOpen }: MyTeamOpenBoxProps) => {
+ return (
+
+ {myTeamOpen && (
+ <>
+
+ {myTeamOpen.contestTitle}
+
+
+
+
+
+
+
+ 합류한 팀원들
+ 총 {myTeamOpen.teamMemberSize}명
+
+
+ {myTeamOpen.teamMemberSize !== 0 &&
+ myTeamOpen.teamMemberInfos ? (
+ myTeamOpen.teamMemberInfos.map((teamMember) => (
+
+ ))
+ ) : (
+
+
+ 아직 합류한 팀원이 없어요
+
+ )}
+
+
+
+
지원자
+
+ {myTeamOpen.applyMemberSize !== 0 &&
+ myTeamOpen.teamMemberInfos ? (
+ <>
+
+
+
+ 현재 {myTeamOpen.applyMemberSize}명이
+
+ 팀원으로 지원했어요.
+
+ {myTeamOpen.applyMemberSize !== 0 &&
+ myTeamOpen.teamMemberInfos.map((teamMember) => (
+
+ ))}
+ >
+ ) : (
+
+
+ 아직 합류한 팀원이 없어요
+
+ )}
+
+
+
+ >
+ )}
+
+ );
+};
+
+export default MyTeamOpenBox;
+
+const MyTeamOpenContainer = styled.div`
+ display: flex;
+ background: ${({ theme }) => theme.colors.primary10};
+ padding: 6rem 10rem;
+ gap: 4rem;
+ margin-bottom: 3rem;
+ border-radius: 10px;
+`;
+
+const CompetitionBox = styled.div`
+ display: flex;
+ flex-direction: column;
+ width: 30%;
+ justify-content: space-between;
+`;
+
+const CompetitionTitle = styled.div`
+ ${({ theme }) => theme.fonts.subtitleXL};
+ color: ${({ theme }) => theme.colors.gray90};
+`;
+
+const CompetitionImg = styled.img`
+ width: 100%;
+ object-fit: cover;
+ border-radius: 8px;
+ border: 1px solid ${({ theme }) => theme.colors.gray40};
+ margin: 0.5rem 0 1rem 0;
+`;
+
+const TeamMemberBox = styled.div`
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ width: 70%;
+ gap: 2rem;
+`;
+
+const TeamMembersBox = styled.div`
+ border-radius: 8px;
+ background: ${({ theme }) => theme.colors.white};
+ padding: 2rem;
+ width: 100%;
+
+ display: flex;
+ align-items: center;
+ gap: 1.5rem;
+ overflow-x: scroll;
+
+ &::-webkit-scrollbar {
+ width: 1rem;
+ height: 0.8rem;
+ }
+ &::-webkit-scrollbar-thumb {
+ background: ${({ theme }) => theme.colors.primary60};
+ border-radius: 10px;
+ }
+`;
+
+const NoTeamMember = styled.div`
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 3rem;
+ gap: 1rem;
+
+ ${({ theme }) => theme.fonts.subtitleL};
+ color: ${({ theme }) => theme.colors.gray90};
+`;
+
+const ApplyContent = styled.div`
+ width: 13.2rem;
+ flex-shrink: 0;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+
+ p {
+ ${({ theme }) => theme.fonts.subtitleS};
+ color: ${({ theme }) => theme.colors.gray90};
+ text-align: center;
+ }
+ span {
+ ${({ theme }) => theme.fonts.subtitleS};
+ color: ${({ theme }) => theme.colors.primary60};
+ }
+`;
+
+const ApplyFireImg = styled.img`
+ margin-bottom: 1rem;
+`;
diff --git a/src/components/profile/ProfileInfo.tsx b/src/components/profile/ProfileInfo.tsx
index cdfa6e6..40ede42 100644
--- a/src/components/profile/ProfileInfo.tsx
+++ b/src/components/profile/ProfileInfo.tsx
@@ -1,3 +1,4 @@
+import { useNavigate } from 'react-router-dom';
import styled from 'styled-components';
const ProfileInfo = ({
@@ -15,10 +16,14 @@ const ProfileInfo = ({
major?: string;
selfIntroduction?: string;
}) => {
+ const navigate = useNavigate();
return (
<>
{name} 님의 프로필
+ navigate('/profile/modify')}>
+ 계정 설정에서 변경하기
+
{name}
@@ -47,13 +52,15 @@ const ProfileText = styled.div`
margin: 3rem 0;
`;
const ProfileContainer = styled.div`
+ position: relative;
width: 100%;
height: 29.6rem;
background-color: ${(props) => props.theme.colors.primary10};
- border-radius: 1 as {
+ border-radius: 1rem;
+ /* as {
profiledata: ProfileData;
isloading: boolean;
- }
+ } */
display: flex;
align-items: center;
@@ -92,4 +99,15 @@ const ProfileValue = styled.div`
display: inline-block;
`;
+const ModifyProfile = styled.div`
+ position: absolute;
+ bottom: 1rem;
+ right: 1rem;
+
+ ${(props) => props.theme.fonts.subtitleXL};
+ color: ${(props) => props.theme.colors.primary60};
+ text-decoration: underline;
+
+ cursor: pointer;
+`;
export default ProfileInfo;
diff --git a/src/components/profile/ProfileKeyword.tsx b/src/components/profile/ProfileKeyword.tsx
index 1b90c24..e4afea0 100644
--- a/src/components/profile/ProfileKeyword.tsx
+++ b/src/components/profile/ProfileKeyword.tsx
@@ -1,29 +1,35 @@
import styled from 'styled-components';
import { keywordList } from '../../constants/KeywordList';
import { Keyword } from '../../interface/Profile';
+import ProfileNotReviewed from './ProfileNotReviewed';
const DETAIL =
'키워드 옆의 레벨은 해당 키워드를 받은 횟수를 의미해요.\n키워드는 가장 많이 받은 순서대로 상위 5개까지만 노출돼요.';
const ProfileKeyword = ({
keywords,
name,
+ isUserGetExternalReview,
}: {
keywords?: Keyword[];
name?: string;
+ isUserGetExternalReview?: boolean;
}) => {
return (
{name} 님의 장점 키워드
{DETAIL}
-
- {keywords?.map((data: Keyword, index: number) => {
- const [keywordIdx, count] = Object.values(data) as [number, number];
- return (
-
- {keywordList[keywordIdx]} | Lv.{count}
-
- );
- })}
+ {isUserGetExternalReview ? (
+ keywords?.map((data: Keyword, index: number) => {
+ const [keywordIdx, count] = Object.values(data) as [number, number];
+ return (
+
+ {keywordList[keywordIdx]} | Lv.{count}
+
+ );
+ })
+ ) : (
+
+ )}
);
};
diff --git a/src/components/profile/ProfileNotReviewed.tsx b/src/components/profile/ProfileNotReviewed.tsx
new file mode 100644
index 0000000..65c8095
--- /dev/null
+++ b/src/components/profile/ProfileNotReviewed.tsx
@@ -0,0 +1,59 @@
+import styled from 'styled-components';
+
+import questionmarkSrc from '/assets/images/common/questionmark.svg';
+import { useSetRecoilState } from 'recoil';
+import { needKakaoReviewModalState } from '../../recoil/atom';
+
+const ProfileNotReviewed = () => {
+ const setKakaoReviewModalVisible = useSetRecoilState(
+ needKakaoReviewModalState,
+ );
+ return (
+
+
+
+ {'아직 받은 추천사가 없어요!\n추천사를 요청해 프로필을 채워보세요.'}
+
+
+
+ );
+};
+const Layout = styled.div`
+ width: 100%;
+ height: 31rem;
+
+ border-radius: 1rem;
+ border: 1px solid ${(props) => props.theme.colors.gray20};
+ background-color: ${(props) => props.theme.colors.gray5};
+
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ gap: 2rem;
+`;
+const QuestionmarkImg = styled.img`
+ width: 9rem;
+`;
+const Subtitle = styled.div`
+ ${({ theme }) => theme.fonts.subtitleL};
+ white-space: break-spaces;
+
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+`;
+const Button = styled.button`
+ width: 31.2rem;
+ height: 6.4rem;
+
+ ${({ theme }) => theme.fonts.buttonL};
+ border: 1px solid ${(props) => props.theme.colors.primary20};
+ border-radius: 3.2rem;
+ background-color: ${(props) => props.theme.colors.primary60};
+ color: ${(props) => props.theme.colors.white};
+`;
+export default ProfileNotReviewed;
diff --git a/src/components/profile/ProfilePersonality.tsx b/src/components/profile/ProfilePersonality.tsx
index 76903fd..bdab051 100644
--- a/src/components/profile/ProfilePersonality.tsx
+++ b/src/components/profile/ProfilePersonality.tsx
@@ -5,15 +5,18 @@ import {
TEAM_CURTURE_CATEGORY,
WORK_METHOD_CATEGORY,
} from '../../constants/Profile';
+import ProfileNotReviewed from './ProfileNotReviewed';
const ProfilePersonality = ({
teamCurturesData,
workMethodsData,
name,
+ isUserGetExternalReview,
}: {
teamCurturesData?: TeamCulture[];
workMethodsData?: WorkMethod[];
name?: string;
+ isUserGetExternalReview?: boolean;
}) => {
return (
@@ -21,16 +24,20 @@ const ProfilePersonality = ({
스펙트럼 위의 별은 {name} 님이 받은 후기의 평균치를 의미해요.
-
-
-
-
+ {isUserGetExternalReview ? (
+
+
+
+
+ ) : (
+
+ )}
);
};
diff --git a/src/components/profile/ProfileReview.tsx b/src/components/profile/ProfileReview.tsx
index a1ac086..e170221 100644
--- a/src/components/profile/ProfileReview.tsx
+++ b/src/components/profile/ProfileReview.tsx
@@ -1,6 +1,7 @@
import styled from 'styled-components';
import ProfileReviewContentsBox from './ProfileReviewContentsBox';
import { Comment } from '../../interface/Profile';
+import ProfileNotReviewed from './ProfileNotReviewed';
const ProfileReview = ({
reviewData,
@@ -8,12 +9,14 @@ const ProfileReview = ({
isLocked,
setIsLackModalVisible,
setIsUseModalVisible,
+ isUserGetExternalReview,
}: {
reviewData?: Comment[];
name?: string;
isLocked?: boolean;
setIsLackModalVisible: React.Dispatch>;
setIsUseModalVisible: React.Dispatch>;
+ isUserGetExternalReview?: boolean;
}) => {
const DETAIL_LOCKED_TICKET = isLocked
? `티켓을 사용하면 ${name} 님의 한 줄 추천사를 언제든지 열람하실 수 있습니다.`
@@ -22,20 +25,26 @@ const ProfileReview = ({
return (
{name} 님이 받은 한 줄 추천사
-
- {DETAIL_LOCKED_TICKET}
-
- 한 줄 추천사 수{LOCKED_TICKET_AMMOUNT}개
- 최신순↑
-
-
-
+ {isUserGetExternalReview ? (
+ <>
+
+ {DETAIL_LOCKED_TICKET}
+
+ 한 줄 추천사 수{LOCKED_TICKET_AMMOUNT}개
+ 최신순↑
+
+
+ {' '}
+ >
+ ) : (
+
+ )}
);
};
diff --git a/src/components/profile/ProfileSubInfo.tsx b/src/components/profile/ProfileSubInfo.tsx
index e3ecbfe..d7b1168 100644
--- a/src/components/profile/ProfileSubInfo.tsx
+++ b/src/components/profile/ProfileSubInfo.tsx
@@ -1,5 +1,6 @@
import styled from 'styled-components';
-import ProfileSubInfoContents from './ProfileSubInfoContent';
+import { useState } from 'react';
+import { useProfileCreate } from '../../hooks/profile/useProfileCreate';
/*
const activitiesData: SubInfoContentsProps = {
@@ -47,25 +48,133 @@ const ProfileSubInfo = ({
tools?: string[];
certificates?: string[];
}) => {
- const titles1 = ['대외활동 및 인턴', '수상 경력'];
- const titles2 = ['사용 가능 툴', '보유 자격증'];
+ const TITLES = [
+ '대외활동 및 인턴',
+ '수상 경력',
+ '사용 가능 툴',
+ '보유 자격증',
+ ];
+ const NAMES = ['internships', 'awards', 'tools', 'certificates'];
+
+ const [isModifying, setIsModyfying] = useState(false);
+ const [texts, setTexts] = useState({
+ internships: internships?.join('\n'),
+ awards: awards?.join('\n'),
+ tools: tools?.join('\n'),
+ certificates: certificates?.join('\n'),
+ });
+
+ const handleTextChange = (event: React.ChangeEvent) => {
+ setTexts((prev: any) => ({
+ ...prev,
+ [event.target.name]: event.target.value,
+ }));
+ };
+
+ const profileCreateMutation = useProfileCreate({
+ internships: texts?.internships?.split('\n') as string[],
+ awards: texts?.awards?.split('\n') as string[],
+ tools: texts?.tools?.split('\n') as string[],
+ certificates: texts?.certificates?.split('\n') as string[],
+ });
+ const handleClickModify = () => {
+ setIsModyfying((curr) => !curr);
+ if (isModifying) {
+ profileCreateMutation.mutate();
+ }
+ };
return (
이력
-
+
+
+ {isModifying && '저장'}
+ {!isModifying && '수정'}
+
+ {TITLES[0]}
+
+ {isModifying ? (
+ <>
+ {texts?.internships?.length}/150
+
+ >
+ ) : (
+ internships?.map((content: any, index: number) => (
+ {content}
+ ))
+ )}
+
+ {TITLES[1]}
+
+ {isModifying ? (
+ <>
+ {texts?.awards?.length}/150
+
+ >
+ ) : (
+ awards?.map((content: any, index: number) => (
+ {content}
+ ))
+ )}
+
+
스킬
-
+
+ {' '}
+
+ {isModifying && '저장'}
+ {!isModifying && '수정'}
+
+ {TITLES[2]}
+
+ {isModifying ? (
+ <>
+ {texts?.tools?.length}/150
+
+ >
+ ) : (
+ tools?.map((content: any, index: number) => (
+ {content}
+ ))
+ )}
+
+ {TITLES[3]}
+
+ {isModifying ? (
+ <>
+ {texts?.certificates?.length}/150
+
+ >
+ ) : (
+ certificates?.map((content: any, index: number) => (
+ {content}
+ ))
+ )}
+
+
);
@@ -82,5 +191,61 @@ const ProfileSubInfoTitle = styled.div`
color: ${(props) => props.theme.colors.gray100};
margin: 1.8rem 0;
`;
+const ProfileSubInfoContents = styled.div`
+ position: relative;
+
+ background-color: ${(props) => props.theme.colors.primary10};
+ width: 60rem;
+ /* height: 28.4rem; */
+
+ border-radius: 1.2rem;
+ padding: 1rem 3rem 4rem 3rem;
+`;
+
+//
+
+const ContentsSubTitle = styled.div`
+ ${(props) => props.theme.fonts.heading4};
+ color: ${(props) => props.theme.colors.gray100};
+ padding: 1rem 0;
+`;
+const ContentsDetailBox = styled.div`
+ position: relative;
+`;
+const ContentsDetail = styled.div`
+ ${(props) => props.theme.fonts.bodyM};
+ color: ${(props) => props.theme.colors.gray90};
+ margin-left: 2.2rem;
+`;
+const ModifyProfile = styled.div`
+ position: absolute;
+ top: 1rem;
+ right: 2rem;
+
+ ${(props) => props.theme.fonts.subtitleXL};
+ color: ${(props) => props.theme.colors.primary60};
+ text-decoration: underline;
+
+ cursor: pointer;
+`;
+const ModifyingArea = styled.textarea`
+ width: 100%;
+ min-height: 15rem;
+
+ border-radius: 0.8rem;
+ border: 1px solid ${(props) => props.theme.colors.gray20};
+ color: ${(props) => props.theme.colors.gray90};
+ ${(props) => props.theme.fonts.bodyM};
+
+ resize: none;
+`;
+const LengthCount = styled.div`
+ position: absolute;
+ right: 1.5rem;
+ bottom: 1.5rem;
+
+ color: ${(props) => props.theme.colors.gray70};
+ ${(props) => props.theme.fonts.bodyM};
+`;
export default ProfileSubInfo;
diff --git a/src/components/profile/ProfileSubInfoContent.tsx b/src/components/profile/ProfileSubInfoContent.tsx
deleted file mode 100644
index 41d4433..0000000
--- a/src/components/profile/ProfileSubInfoContent.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import styled from 'styled-components';
-
-const ProfileSubInfoContents = ({
- props1,
- props2,
- titles,
-}: {
- props1?: string[];
- props2?: string[];
- titles: string[];
-}) => {
- return (
-
- {titles[0]}
- {props1?.map((content: any, index: number) => (
- {content}
- ))}
- {titles[1]}
- {props2?.map((content: any, index: number) => (
- {content}
- ))}
-
- );
-};
-
-const ContentsContainer = styled.div`
- background-color: ${(props) => props.theme.colors.primary10};
- width: 60rem;
- /* height: 28.4rem; */
-
- border-radius: 1.2rem;
- padding: 3rem 3rem;
-`;
-
-const ContentsSubTitle = styled.div`
- ${(props) => props.theme.fonts.heading4};
- color: ${(props) => props.theme.colors.gray100};
- padding: 1rem 0;
-`;
-const ContentsDetail = styled.div`
- ${(props) => props.theme.fonts.bodyM};
- color: ${(props) => props.theme.colors.gray90};
- margin-left: 2.2rem;
-`;
-
-export default ProfileSubInfoContents;
diff --git a/src/constants/Profile.ts b/src/constants/Profile.ts
index b2afc40..3b540ef 100644
--- a/src/constants/Profile.ts
+++ b/src/constants/Profile.ts
@@ -1,40 +1,5 @@
import { ICategory } from '../interface/Profile';
-// export const ProfileSubInfoData: IProfileSubInfoData = {
-// activitiesData: {
-// title: '대외활동 및 인턴',
-// contents: [
-// '한국대학생IT경영학회 (23.08~): 기획 파트, 팀원 모집 플랫폼 "Wanteam." 기획',
-// '캐캐오기업 (22.01~22.12): 제품 기획 부서, 초콜릿 신제품 맛보기 테스트',
-// '코코넛기업 (21.06~21.09): 영업 부서, 코코넛 사세요 맛 좋은 코코넛 사세요',
-// ],
-// },
-// awardsData: {
-// title: '수상 경력',
-// contents: [
-// '초콜릿 맛있게 먹기 공모전 최우수상',
-// '샘송 광고 기획 아이디어 공모전 장려상',
-// '멍 때리기 대회 대상',
-// ],
-// },
-// toolsData: {
-// title: '사용 가능 툴',
-// contents: [
-// '노션: 휘황찬란하게 활용하지는 못하지만 적당히 쓸 줄은 알아요!',
-// '지라: 인턴할 때 써봐서 어느 정도 활용 가능합니다.',
-// '피그마: 간단한 와이어프레임 정도는 그릴 수 있어요! ',
-// ],
-// },
-// licensesData: {
-// title: '대외활동 및 인턴',
-// contents: [
-// '늦게 자기 자격증 1급',
-// '해리 포터 덕후 자격증 마스터',
-// '(G)-IDLE 팬클럽 ‘네버랜드’ 4기',
-// ],
-// },
-// };
-
export const TEAM_CURTURE_CATEGORY: ICategory = {
title: '팀 문화',
category: [
diff --git a/src/constants/competitionList.ts b/src/constants/competitionList.ts
index 7c96633..d90d20f 100644
--- a/src/constants/competitionList.ts
+++ b/src/constants/competitionList.ts
@@ -1,41 +1,3 @@
-export const recruitingList = [
- {
- id: 1,
- title: '세종특별자치시 2023 일자리 아이디어(정책) 공모전',
- name: '박형준',
- description: '봄감자가 맛있답니다',
- profile: '/assets/images/review/profile.svg',
- },
- {
- id: 2,
- title: '외국인 인식 개선을 위한 콘텐츠(영상, 웹툰) 제작 공모전',
- name: '민혜린',
- description: '봄감자가 맛있답니다',
- profile: '/assets/images/review/profile.svg',
- },
- {
- id: 3,
- title: '[인천국제공항공사] 우리동네 여행코스 대국민 공모전',
- name: '채영대',
- description: '봄감자가 맛있답니다',
- profile: '/assets/images/review/profile.svg',
- },
- {
- id: 4,
- title: '2024 KT&G 국제 대학생 창업교류전(ASVF) 한국 대표 모집',
- name: '이재영',
- description: '디자인',
- profile: '/assets/images/review/profile.svg',
- },
- {
- id: 5,
- title: '세종특별자치시 2023 일자리 아이디어(정책) 공모전',
- name: '박진우',
- description: '프론트엔드',
- profile: '/assets/images/review/profile.svg',
- },
-];
-
export const searchButtonList = [
'전체',
'기획/아이디어',
@@ -49,46 +11,3 @@ export const searchButtonList = [
'창업/스타트업',
'기타',
];
-
-export const competitionList = [
- {
- contestId: 1,
- title: '제 1회 삼성전자 주니어 소프트웨어 창작대회',
- images: '/assets/images/competition/competition.svg',
- teamNum: 8,
- remainDay: 11,
- company: '한국경제신문',
- },
- {
- contestId: 2,
- title: '2024 KT&G 국제 대학생 창업교류전(ASVF) 한국 대표 모집',
- images: '/assets/images/competition/competition.svg',
- teamNum: 8,
- remainDay: 11,
- company: '한국경제신문',
- },
- {
- contestId: 3,
- title: '제 1회 삼성전자 주니어 소프트웨어 창작대회',
- images: '/assets/images/competition/competition.svg',
- teamNum: 8,
- remainDay: 11,
- company: '한국경제신문',
- },
- {
- contestId: 4,
- title: '제 1회 삼성전자 주니어 소프트웨어 창작대회',
- images: '/assets/images/competition/competition.svg',
- teamNum: 8,
- remainDay: 11,
- company: '한국경제신문',
- },
- {
- contestId: 5,
- title: '제 1회 삼성전자 주니어 소프트웨어 창작대회',
- images: '/assets/images/competition/competition.svg',
- teamNum: 8,
- remainDay: 11,
- company: '한국경제신문',
- },
-];
diff --git a/src/constants/main.ts b/src/constants/main.ts
index 8d52fb4..95766a3 100644
--- a/src/constants/main.ts
+++ b/src/constants/main.ts
@@ -8,7 +8,7 @@ export const competitionList = [
teamNum: 3,
},
{
- contestId: '1',
+ contestId: '2',
title: '2021년도 제 1회 삼성 SDS 아이디어 공모전',
company: '삼성 SDS',
images: ['/assets/images/competition/competition.svg'],
@@ -16,7 +16,7 @@ export const competitionList = [
teamNum: 3,
},
{
- contestId: '1',
+ contestId: '3',
title: '2021년도 제 1회 삼성 SDS 아이디어 공모전',
company: '삼성 SDS',
images: ['/assets/images/competition/competition.svg'],
@@ -24,7 +24,7 @@ export const competitionList = [
teamNum: 3,
},
{
- contestId: '1',
+ contestId: '4',
title: '2021년도 제 1회 삼성 SDS 아이디어 공모전',
company: '삼성 SDS',
images: ['/assets/images/competition/competition.svg'],
diff --git a/src/constants/myteam.ts b/src/constants/myteam.ts
index 12168c2..383a4a4 100644
--- a/src/constants/myteam.ts
+++ b/src/constants/myteam.ts
@@ -15,4 +15,4 @@ export const activityAreaOptions = [
'경상북도',
'경상남도',
'제주도',
-];
+].map((name, index) => ({ id: index + 1, name }));
diff --git a/src/hooks/competition/useRecruitingTeam.tsx b/src/hooks/competition/useRecruitingTeam.tsx
new file mode 100644
index 0000000..e56a4ea
--- /dev/null
+++ b/src/hooks/competition/useRecruitingTeam.tsx
@@ -0,0 +1,15 @@
+import { useQuery } from 'react-query';
+import { ResponseRecruitingTeam } from '../../interface/MyTeam';
+import { recruitingTeamKeys } from '../../keys/competitionKeys';
+import { getRecruitingTeam } from '../../apis/competition/getRecruitingTeam';
+
+interface UseRecruitingTeam {
+ recruitingTeam?: ResponseRecruitingTeam;
+}
+
+export function useRecruitingTeam(): UseRecruitingTeam {
+ const { data: recruitingTeam } = useQuery(recruitingTeamKeys.all, () =>
+ getRecruitingTeam(),
+ );
+ return { recruitingTeam };
+}
diff --git a/src/hooks/contest/useJoinTeam.ts b/src/hooks/contest/useJoinTeam.ts
new file mode 100644
index 0000000..70f4a3d
--- /dev/null
+++ b/src/hooks/contest/useJoinTeam.ts
@@ -0,0 +1,31 @@
+import { useMutation } from 'react-query';
+import postJoinTeam from '../../apis/contest/postJoinTeam';
+
+// export const useJoinTeam = (teamId: string) => {
+// const { data: joinTeamData } = useQuery('joinTeam', () =>
+// postJoinTeam({
+// teamId: teamId as string,
+// }),
+// );
+
+// return { joinTeamData };
+// };
+
+// export default useJoinTeam;
+
+interface UseJoinTeam {
+ mutate: () => void;
+}
+export function useJoinTeam(teamId: string): UseJoinTeam {
+ const { mutate } = useMutation(
+ 'joinTeam',
+ () =>
+ postJoinTeam({
+ teamId: teamId as string,
+ }),
+ {},
+ );
+ return { mutate };
+}
+
+export default useJoinTeam;
diff --git a/src/hooks/login/useLoginWithKakaoToken.tsx b/src/hooks/login/useLoginWithKakaoToken.tsx
index eac88a7..51f85ae 100644
--- a/src/hooks/login/useLoginWithKakaoToken.tsx
+++ b/src/hooks/login/useLoginWithKakaoToken.tsx
@@ -30,6 +30,7 @@ const useLoginWithKakaoToken = () => {
},
});
navigate('/join/request');
+ // window.location.reload();
} else {
if (responseLogin.statusCode == 404) {
console.log('로그인실패 회원이 아님', responseLogin);
diff --git a/src/hooks/modify/useModifyProfile.ts b/src/hooks/modify/useModifyProfile.ts
new file mode 100644
index 0000000..75dd4e6
--- /dev/null
+++ b/src/hooks/modify/useModifyProfile.ts
@@ -0,0 +1,35 @@
+import { useMutation, useQueryClient } from 'react-query';
+import { RequestModifyProfile } from '../../interface/Modify';
+import patchModifyProfile from '../../apis/modify/patchModifyProfile';
+import { useNavigate } from 'react-router-dom';
+import { useSetRecoilState } from 'recoil';
+import { loginInfoState } from '../../recoil/atom';
+
+interface UseModifyProfile {
+ mutate: () => void;
+}
+
+export function useModifyProfile(
+ requestData: RequestModifyProfile,
+ userId: string,
+): UseModifyProfile {
+ const queryClient = useQueryClient();
+ const navigate = useNavigate();
+ const setLoginInfo = useSetRecoilState(loginInfoState);
+
+ const { mutate } = useMutation(() => patchModifyProfile(requestData), {
+ onSuccess: () => {
+ queryClient.invalidateQueries('modifyProfile');
+ navigate(`/profile/${userId}`); //미쳤다 이 코드
+ setLoginInfo((curr) => ({
+ ...curr,
+ data: {
+ ...curr.data!,
+ name: requestData.username,
+ },
+ }));
+ // setLoginInfo((curr) => ({ ...curr, data: {...curr.data,name:requestData.username}} }));
+ },
+ });
+ return { mutate };
+}
diff --git a/src/hooks/myTeam/useActiveTeam.ts b/src/hooks/myTeam/useActiveTeam.ts
new file mode 100644
index 0000000..ed4e2ff
--- /dev/null
+++ b/src/hooks/myTeam/useActiveTeam.ts
@@ -0,0 +1,12 @@
+import { useQuery } from 'react-query';
+import getActiveTeam from '../../apis/myTeam/getActiveTeam';
+
+export const useActiveTeam = () => {
+ const { data: activeTeamData } = useQuery('activeTeam', () =>
+ getActiveTeam(),
+ );
+
+ return { activeTeamData };
+};
+
+export default useActiveTeam;
diff --git a/src/hooks/myTeam/useEndTeam.ts b/src/hooks/myTeam/useEndTeam.ts
new file mode 100644
index 0000000..7067518
--- /dev/null
+++ b/src/hooks/myTeam/useEndTeam.ts
@@ -0,0 +1,12 @@
+import { useQuery } from 'react-query';
+import { getEndTeam } from '../../apis/myTeam/getEndTeam';
+import { ResponseEndTeam } from '../../interface/MyTeam';
+
+interface UseEndTeam {
+ endTeam?: ResponseEndTeam;
+}
+
+export function useEndTeam(): UseEndTeam {
+ const { data: endTeam } = useQuery('endTeam', () => getEndTeam());
+ return { endTeam };
+}
diff --git a/src/hooks/myTeam/useOpenedTeam.ts b/src/hooks/myTeam/useOpenedTeam.ts
new file mode 100644
index 0000000..943d7b6
--- /dev/null
+++ b/src/hooks/myTeam/useOpenedTeam.ts
@@ -0,0 +1,12 @@
+import { useQuery } from 'react-query';
+import { getOpenedTeam } from '../../apis/myTeam/getOpenedTeam';
+import { ResponseOpenedTeam } from '../../interface/MyTeam';
+
+interface UseOpenedTeam {
+ openedTeam?: ResponseOpenedTeam;
+}
+
+export function useOpenedTeam(): UseOpenedTeam {
+ const { data: openedTeam } = useQuery('openedTeam', () => getOpenedTeam());
+ return { openedTeam };
+}
diff --git a/src/hooks/myTeam/useTeamOpen.ts b/src/hooks/myTeam/useTeamOpen.ts
new file mode 100644
index 0000000..25829d4
--- /dev/null
+++ b/src/hooks/myTeam/useTeamOpen.ts
@@ -0,0 +1,19 @@
+import { useMutation, useQueryClient } from 'react-query';
+import { RequestTeamOpen } from '../../interface/MyTeam';
+import postTeamOpen from '../../apis/myTeam/postTeamOpen';
+import { myteamKeys } from '../../keys/myteamKeys';
+
+interface UseTeamOpen {
+ mutate: () => void;
+}
+
+export function UseTeamOpen(teamOpen: RequestTeamOpen): UseTeamOpen {
+ const queryClient = useQueryClient();
+
+ const { mutate } = useMutation(myteamKeys.all, () => postTeamOpen(teamOpen), {
+ onSuccess: () => {
+ queryClient.invalidateQueries();
+ },
+ });
+ return { mutate };
+}
diff --git a/src/hooks/profile/useIsUserGetExternalReview.ts b/src/hooks/profile/useIsUserGetExternalReview.ts
new file mode 100644
index 0000000..4f72249
--- /dev/null
+++ b/src/hooks/profile/useIsUserGetExternalReview.ts
@@ -0,0 +1,17 @@
+import { useQuery } from 'react-query';
+
+import getIsUserGetExternalReview from '../../apis/profile/getIsUserGetExternalReview';
+
+export const useIsUserGetExternalReview = (userId: string) => {
+ const { data: isUserGetExternalReviewData } = useQuery(
+ 'isUserGetExternalReview',
+ () =>
+ getIsUserGetExternalReview({
+ userId: userId,
+ }),
+ );
+
+ return { isUserGetExternalReviewData };
+};
+
+export default useIsUserGetExternalReview;
diff --git a/src/hooks/profile/useProfile.ts b/src/hooks/profile/useProfile.ts
index c52d47f..ce77a65 100644
--- a/src/hooks/profile/useProfile.ts
+++ b/src/hooks/profile/useProfile.ts
@@ -2,10 +2,18 @@ import getProfile from '../../apis/profile/getProfile';
import { useQuery } from 'react-query';
export const useProfile = (userId?: string) => {
- const { data: profileData, isLoading } = useQuery('profile', () =>
- getProfile({
- userId: userId,
- }),
+ const { data: profileData, isLoading } = useQuery(
+ 'profile',
+ () =>
+ getProfile({
+ userId: userId,
+ }),
+ {
+ onSuccess: () => {
+ // queryClient.invalidateQueries('modifyProfile');
+ //새로고침이나 리렌더링
+ },
+ },
);
return { profileData, isLoading };
diff --git a/src/hooks/profile/useTicketNumber.ts b/src/hooks/profile/useTicketNumber.ts
index 5ecc125..44c43a4 100644
--- a/src/hooks/profile/useTicketNumber.ts
+++ b/src/hooks/profile/useTicketNumber.ts
@@ -1,10 +1,10 @@
import { useQuery } from 'react-query';
import getTicketNumber from '../../apis/profile/getTicketNumber';
-import { useSetRecoilState } from 'recoil';
-import { loginModalState } from '../../recoil/atom';
+// import { useSetRecoilState } from 'recoil';
+// import { loginModalState } from '../../recoil/atom';
export const useTicketNumber = () => {
- const setIsLoginModalVisible = useSetRecoilState(loginModalState);
+ // const setIsLoginModalVisible = useSetRecoilState(loginModalState);
const { data: TicketNumberData, isLoading } = useQuery(
'ticketNumber',
() => getTicketNumber(),
@@ -12,7 +12,7 @@ export const useTicketNumber = () => {
retry: 0, //이거다!!
// 에러가 발생했을 때 실행될 콜백
onError: (error) => {
- setIsLoginModalVisible(true);
+ // setIsLoginModalVisible(true);
// navigate('/login');
console.error('로그인이 필요한 에러가 발생했습니다:', error);
console.log(error);
diff --git a/src/interface/Contest.ts b/src/interface/Contest.ts
index 2d5a9bd..80e5179 100644
--- a/src/interface/Contest.ts
+++ b/src/interface/Contest.ts
@@ -71,3 +71,12 @@ export interface ResponseContestTeamDetailInfo {
message: string;
data: ContestTeamDetailInfo;
}
+
+////공모전 팀 합류하기 api
+export interface RequestJoinTeam {
+ teamId?: string;
+}
+
+export interface ResponseJoinTeam {
+ status: number;
+}
diff --git a/src/interface/Modify.ts b/src/interface/Modify.ts
new file mode 100644
index 0000000..2ae819c
--- /dev/null
+++ b/src/interface/Modify.ts
@@ -0,0 +1,13 @@
+//계정 정보 수정하기 api
+export interface RequestModifyProfile {
+ username: string;
+ location: number;
+ major: string;
+ task: string;
+ selfIntroduce: string;
+}
+export interface ResponseModifyProfile {
+ status: number;
+ message: string;
+ data: null;
+}
diff --git a/src/interface/MyTeam.ts b/src/interface/MyTeam.ts
index f998641..ea9c2fc 100644
--- a/src/interface/MyTeam.ts
+++ b/src/interface/MyTeam.ts
@@ -4,17 +4,114 @@ import { ProfileProps } from './Contest';
export interface RequestAppliedTeam {
// contestId: string;
}
+
+export interface RequestTeamOpen {
+ contestId?: string;
+ max: number;
+ location: number;
+ endDate: string;
+ leaderMessage: string;
+ notice: string;
+ chatLink: string;
+}
+
export interface AppliedTeamData {
+ contestId: string;
+ contestTitle: string;
+ contestImage: string[];
+ leaderInfo: ProfileProps;
+ teamId: number;
+ status: string;
+ leaderMessage: string;
+ max: number;
+ cur: number;
+ location: string;
+ endDate: string;
+}
+
+export interface ResponseAppliedTeam {
+ status: number;
+ message: string;
+ data: AppliedTeamData[];
+}
+
+export interface TeamData {
teamId?: number;
teamMemberSize?: number;
applyMemberSize?: number;
teamMemberInfos?: ProfileProps[];
- applyMemberInfos?: ProfileProps[]; // Apply Member 정보에 대한 타입이 없어서 any로 처리했습니다.
+ applyMemberInfos?: ProfileProps[];
contestTitle?: string;
- contestImage?: string[];
+ contestImage: string[];
}
-export interface ResponseAppliedTeam {
+
+export interface ResponseOpenedTeam {
status: number;
message: string;
- data: AppliedTeamData[];
+ data: TeamData[];
+}
+
+export interface RequestActiveTeam {
+ // contestId: string;
+}
+export interface ActiveTeamData {
+ contestId: string;
+ contestTitle: string;
+ contestImage: string[];
+ leaderInfo: ProfileProps;
+ leaderMessage: string;
+ memberSize: number;
+ location: string;
+ endDate: string;
+ notice: string;
+ teamMemberInfos: ProfileProps[];
+ chatLink: string;
+}
+export interface ResponseActiveTeam {
+ status: number;
+ message: string;
+ data: ActiveTeamData[];
+}
+
+export interface EndTeamData {
+ contestId: string;
+ contestTitle: string;
+ endDate: string;
+ memberSize: number;
+ leaderInfo: ProfileProps;
+ teamMemberInfos: ProfileProps[];
+ possibleWriteReviews: boolean;
+}
+
+export interface ResponseEndTeam {
+ status: number;
+ message: string;
+ data: EndTeamData[];
+}
+
+export interface PageResponseDTO {
+ startPage: number;
+ endPage: number;
+ currentPage: number;
+ totalCount: number;
+}
+
+export interface RecruitingTeamData {
+ contestId: string;
+ contesttitle: string;
+ teamLeaderId: number;
+ teamLeaderName: string;
+ teamLeaderImage: string;
+ teamLeaderMessage: string;
+}
+
+export interface RecruitingTeam {
+ pageResponseDTO: PageResponseDTO;
+ recruitingTeams: RecruitingTeamData[];
+}
+
+export interface ResponseRecruitingTeam {
+ status: number;
+ message: string;
+ data: RecruitingTeam;
}
diff --git a/src/interface/Profile.ts b/src/interface/Profile.ts
index b70e91a..2e470c5 100644
--- a/src/interface/Profile.ts
+++ b/src/interface/Profile.ts
@@ -159,3 +159,15 @@ export interface ResponseUseTicket {
message: string;
data: UseTicketData;
}
+//유저가 외부 추천사를 받았는지 여부
+export interface RequestIsUserGetExternalReview {
+ userId?: string;
+}
+export interface IsUserGetExternalReviewData {
+ alreadyReviewed: boolean;
+}
+export interface ResponseIsUserGetExternalReview {
+ status: number;
+ message: string;
+ data: IsUserGetExternalReviewData;
+}
diff --git a/src/keys/competitionKeys.tsx b/src/keys/competitionKeys.tsx
index 4be7c3d..ad8743d 100644
--- a/src/keys/competitionKeys.tsx
+++ b/src/keys/competitionKeys.tsx
@@ -1,3 +1,7 @@
export const competitionKeys = {
all: ['competition'] as const,
};
+
+export const recruitingTeamKeys = {
+ all: ['recruitingTeam'] as const,
+};
diff --git a/src/keys/myteamKeys.tsx b/src/keys/myteamKeys.tsx
new file mode 100644
index 0000000..cab887f
--- /dev/null
+++ b/src/keys/myteamKeys.tsx
@@ -0,0 +1,3 @@
+export const myteamKeys = {
+ all: ['myteam'] as const,
+};
diff --git a/src/pages/contestTeam/ContestTeam.tsx b/src/pages/contestTeam/ContestTeam.tsx
index 0fbfd02..25d5538 100644
--- a/src/pages/contestTeam/ContestTeam.tsx
+++ b/src/pages/contestTeam/ContestTeam.tsx
@@ -7,11 +7,12 @@ import ProfileBoxMember from '../../components/common/ProfileBoxMember';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { headerSelectedState, loginInfoState } from '../../recoil/atom';
import { Headers } from '../../constants/Header';
-import { useEffect } from 'react';
+import { useEffect, useState } from 'react';
import useContestTeamDetailInfo from '../../hooks/contest/useContestTeamDetailInfo';
import { useNavigate, useParams } from 'react-router-dom';
import { TEAM_DETAIL_STATUS } from '../../constants/Contest';
import TeamMembers from '../../components/contestTeam/TeamMembers';
+import JoinTeamModal from '../../components/contestTeam/JoinTeamModal';
const ContestTeam = () => {
const { teamId, contestId } = useParams();
@@ -21,7 +22,7 @@ const ContestTeam = () => {
const userLogininfo = useRecoilValue(loginInfoState);
const setHeaderSelected = useSetRecoilState(headerSelectedState);
const navigate = useNavigate();
- useEffect(() => setHeaderSelected(Headers.list));
+ const [isJoinTeamModalVisible, setIsJoinTeamModalVisible] = useState(false);
const teamLeaderBoxProps: ProfileBoxProps = isLoading
? ({} as ProfileBoxProps)
: {
@@ -33,17 +34,32 @@ const ContestTeam = () => {
height: 27.6,
};
+ const handleJoinTeam = () => {
+ setIsJoinTeamModalVisible(true);
+ };
+ console.log(contestTeamDetailData);
+
+ useEffect(() => setHeaderSelected(Headers.list));
+
+ //내가 오픈한 경우, 내 팀 페이지로 이동
if (
contestTeamDetailData?.data.data.status ==
TEAM_DETAIL_STATUS._1_내가오픈한경우
) {
navigate(`/myTeam/${userLogininfo.data?.userId}/${contestId}/${teamId}`);
}
- console.log(contestTeamDetailData);
+
return isLoading ? (
로딩중
) : (
+
+
navigate(-1)}>
{'공모전으로 돌아가기'}
@@ -91,6 +107,44 @@ const ContestTeam = () => {
cur={contestTeamDetailData?.data.data.cur}
max={contestTeamDetailData?.data.data.max}
/>
+
+ {contestTeamDetailData?.data.data.status ==
+ TEAM_DETAIL_STATUS._2_남이오픈한경우_내가지원안함 && (
+ <>
+
+ 합류 신청하기 →
+
+ >
+ )}
+ {contestTeamDetailData?.data.data.status ==
+ TEAM_DETAIL_STATUS._3_남이오픈한경우_내가지원완료_승인 && (
+ <>
+ 합류 신청하기 →
+ 이미 합류 승인된 팀입니다.
+ >
+ )}{' '}
+ {contestTeamDetailData?.data.data.status ==
+ TEAM_DETAIL_STATUS._4_남이오픈한경우_내가지원완료_반려 && (
+ <>
+ 합류 신청하기 →
+ 이미 지원이 반려된 팀입니다.
+ >
+ )}{' '}
+ {contestTeamDetailData?.data.data.status ==
+ TEAM_DETAIL_STATUS._5_남이오픈한경우_내가지원완료_승인반려아님 && (
+ <>
+
+ navigate(`/myteam/${userLogininfo.data?.userId}/apply`)
+ }
+ >
+ 지원 현황보기 →
+
+ 이미 지원을 완료한 팀입니다.
+ >
+ )}
+
);
};
@@ -100,6 +154,8 @@ const TeamLayout = styled.div`
display: flex;
flex-direction: column;
+ /* justify-content: center; */
+ /* align-items: center; */
gap: 4.4rem;
`;
const TeamUndo = styled.div`
@@ -216,4 +272,36 @@ const TeamNoticeContent = styled.div`
white-space: break-spaces;
`;
+const FlexBox = styled.div`
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ gap: 1.6rem;
+`;
+const CustomButton = styled.button<{ $isActive?: boolean }>`
+ width: 25.5rem;
+ height: 6.4rem;
+
+ border-radius: 3.2rem;
+ border: 1px solid
+ ${(props) =>
+ props.$isActive
+ ? props.theme.colors.primary20
+ : props.theme.colors.gray50};
+
+ background-color: ${(props) =>
+ props.$isActive ? props.theme.colors.primary60 : props.theme.colors.gray10};
+
+ ${(props) => props.theme.fonts.buttonL};
+ color: ${(props) =>
+ props.$isActive ? props.theme.colors.white : props.theme.colors.gray40};
+
+ cursor: ${(props) => (props.$isActive ? 'pointer' : 'default')};
+`;
+const CustomMessage = styled.div`
+ ${(props) => props.theme.fonts.buttonL};
+ color: ${(props) => props.theme.colors.gray70};
+`;
export default ContestTeam;
diff --git a/src/pages/login/Oauth.tsx b/src/pages/login/Oauth.tsx
index b8cbb6c..89b1e1e 100644
--- a/src/pages/login/Oauth.tsx
+++ b/src/pages/login/Oauth.tsx
@@ -55,38 +55,6 @@ const Oauth = () => {
}
};
- // /** 카카오 어세스 토큰를 통해 로그인 하는 함수
- // *
- // * @param kakaoAccessToken 카카오 어세스 토큰
- // */
- // const loginWithKakaoToken = async (kakaoAccessToken: string) => {
- // try {
- // const responseLogin: AxiosResponse =
- // await postLoginWithKakaoToken(kakaoAccessToken);
- // console.log('loginWithKakaoToken Complete', responseLogin);
-
- // setLoginInfoState({
- // isLogin: true,
- // data: {
- // userId: responseLogin.data.data.userId,
- // refreshToken: responseLogin.data.data.refreshToken,
- // accessToken: responseLogin.data.data.accessToken,
- // profileImage: responseLogin.data.data.profileImage,
- // name: responseLogin.data.data.name,
- // },
- // });
- // } catch (error: any) {
- // console.log('loginWithKakaoToken Error', error);
- // //여기에 setlogin하면 될듯
- // //회원가입 페이지로 연결
- // if (error.response.data.status == 404) {
- // navigate('/login/join', {
- // state: { kakaoAccessToken: kakaoAccessToken },
- // });
- // }
- // }
- // };
-
useEffect(() => {
const params = new URLSearchParams(location.search);
const kakaoAccessCode = params.get('code');
@@ -95,7 +63,7 @@ const Oauth = () => {
);
kakaoAccessToken;
//우리팀 서버에 카카오 토큰 유효성 검증하기
-
+ console.log('kakaoAccessToken 잘 됐니?', kakaoAccessToken);
navigate('/');
}, []);
return auth
;
diff --git a/src/pages/modify/ProfileModify.tsx b/src/pages/modify/ProfileModify.tsx
new file mode 100644
index 0000000..194324e
--- /dev/null
+++ b/src/pages/modify/ProfileModify.tsx
@@ -0,0 +1,196 @@
+import styled from 'styled-components';
+import React, { useEffect, useState } from 'react';
+import { useRecoilValue, useSetRecoilState } from 'recoil';
+import { headerSelectedState, loginInfoState } from '../../recoil/atom';
+import { Headers } from '../../constants/Header';
+
+import bgSrc from '/assets/images/join/join-bg.png';
+import starSrc from '/assets/images/common/star.svg';
+import { INPUT_PROPS, REGIONS } from '../../constants/Join';
+import { InputDataArray } from '../../interface/Join';
+
+import useProfile from '../../hooks/profile/useProfile';
+import TextInput from '../../components/modify/TextInput';
+import SelectInput from '../../components/modify/SelectInput';
+import TextAreaInput from '../../components/modify/TextAreaInput';
+import { RequestModifyProfile } from '../../interface/Modify';
+import { useModifyProfile } from '../../hooks/modify/useModifyProfile';
+
+const ProfileModify = () => {
+ const loginInfo = useRecoilValue(loginInfoState);
+ const { profileData, isLoading } = useProfile(
+ loginInfo.data?.userId as string | undefined,
+ );
+
+ const [inputValue, setInputValue] = useState({
+ username: profileData?.data.data.username,
+ location: REGIONS.indexOf(profileData?.data.data.location as string),
+ major: profileData?.data.data.major[0],
+ task: profileData?.data.data.task[0],
+ selfIntroduce: profileData?.data.data.selfIntroduction,
+ });
+
+ // useProfile 로딩이 끝났을 때
+ useEffect(() => {
+ if (!isLoading && profileData) {
+ setInputValue({
+ username: profileData?.data.data.username,
+ location: REGIONS.indexOf(profileData?.data.data.location as string),
+ major: profileData?.data.data.major[0],
+ task: profileData?.data.data.task[0],
+ selfIntroduce: profileData?.data.data.selfIntroduction,
+ });
+ }
+ }, [isLoading, profileData]);
+
+ const [buttonActiveCount, setButtonActiveCount] = useState([
+ true,
+ true,
+ true,
+ true,
+ true,
+ ]);
+ const handleModiftProfile = useModifyProfile(
+ inputValue as RequestModifyProfile,
+ loginInfo.data?.userId as unknown as string,
+ );
+ const handleSubmit = async (event: React.FormEvent) => {
+ event.preventDefault();
+ console.log({ ...inputValue });
+ handleModiftProfile.mutate();
+ };
+
+ const handleChange = (event: any) => {
+ setInputValue((prev: any) => ({
+ ...prev,
+ [event.target.name]: event.target.value,
+ }));
+ };
+ const isAcvivateButton = (buttonActiveArr: InputDataArray) => {
+ if (buttonActiveArr.every((value) => value === true)) return true;
+ else return false;
+ };
+
+ const setHeaderSelected = useSetRecoilState(headerSelectedState);
+ useEffect(() => setHeaderSelected(Headers.login));
+
+ return (
+
+
+
+
+ 계정 정보를 수정해주세요
+
+
+
+
+
+
+
+
+ 저장하기
+
+
+
+ );
+};
+
+const JoinLayout = styled.div`
+ width: 100%;
+ height: 100%; //수정 필요
+ background: url(${bgSrc}) left top no-repeat;
+ background-size: cover;
+
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ margin: auto;
+`;
+const JoinFormContainer = styled.form`
+ width: 78rem;
+ /* height: 70rem; */
+
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 2.4rem;
+
+ border: 1px solid #3b3ef1;
+ border-radius: 2.4rem;
+
+ background-color: rgba(239, 239, 253, 0.2);
+ backdrop-filter: blur(12px);
+
+ padding: 3.3rem 6.6rem;
+ margin: 4rem 0;
+`;
+const TitleBox = styled.div`
+ width: 100%;
+ display: flex;
+ /* justify-content: left; */
+ align-items: center;
+`;
+const TitleStarImg = styled.img`
+ width: 3rem;
+ height: 3rem;
+ margin-right: 1.2rem;
+`;
+const TitleText = styled.div`
+ ${(props) => props.theme.fonts.heading4};
+ color: ${(props) => props.theme.colors.gray90};
+`;
+const StartButton = styled.button<{ $isActive: boolean }>`
+ width: 25.5rem;
+ height: 6.4rem;
+
+ border-radius: 3.2rem;
+ border: 1px solid
+ ${(props) =>
+ props.$isActive
+ ? props.theme.colors.primary20
+ : props.theme.colors.gray50};
+
+ background-color: ${(props) =>
+ props.$isActive ? props.theme.colors.primary60 : props.theme.colors.gray10};
+
+ ${(props) => props.theme.fonts.buttonL};
+ color: ${(props) =>
+ props.$isActive ? props.theme.colors.white : props.theme.colors.gray40};
+
+ cursor: ${(props) => (props.$isActive ? 'pointer' : 'default')};
+`;
+export default ProfileModify;
diff --git a/src/pages/myteam/MyTeamActive.tsx b/src/pages/myteam/MyTeamActive.tsx
new file mode 100644
index 0000000..0d39981
--- /dev/null
+++ b/src/pages/myteam/MyTeamActive.tsx
@@ -0,0 +1,24 @@
+import styled from 'styled-components';
+import useActiveTeam from '../../hooks/myTeam/useActiveTeam';
+import MyTeamActiveContainer from '../../components/myteam/active/MyTeamActiveContainer';
+
+const MyTeamActive = () => {
+ const { activeTeamData } = useActiveTeam();
+ console.log(activeTeamData);
+
+ return (
+
+ {activeTeamData?.data.data.map((each) => (
+
+ ))}
+
+ );
+};
+const ApplyLayout = styled.div`
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
+ gap: 3rem;
+`;
+export default MyTeamActive;
diff --git a/src/pages/myteam/MyTeamApply.tsx b/src/pages/myteam/MyTeamApply.tsx
index 45be6a9..9c25929 100644
--- a/src/pages/myteam/MyTeamApply.tsx
+++ b/src/pages/myteam/MyTeamApply.tsx
@@ -1,44 +1,24 @@
import styled from 'styled-components';
-import { ResponseAppliedTeam } from '../../interface/MyTeam';
+import useAppliedTeam from '../../hooks/myTeam/useAppliedTeam';
+import MyTeamApplyContainer from '../../components/myteam/apply/MyTeamApplyContainer';
-const DUMMY: ResponseAppliedTeam = {
- status: 200,
- message: '요청이 성공했습니다.',
- data: [
- {
- teamId: 1,
- teamMemberSize: 1,
- applyMemberSize: 0,
- teamMemberInfos: [
- {
- teamMemberId: 3,
- teamMemberName: '맹구',
- teamMemberImage:
- 'http://k.kakaocdn.net/dn/1G9kp/btsAot8liOn/8CWudi3uy07rvFNUkk3ER0/img_640x640.jpg\t',
- teamMemberTask: [],
- teamMemberMajor: [],
- },
- ],
- applyMemberInfos: [],
- contestTitle:
- "[아모레퍼시픽/두리코스메틱등] 뷰티 대기업에서 마케팅/연구개발/MD '실무스펙' 한번에 쌓고 서류합격 확률 200%올리기",
- contestImage: [
- 'https://www.wevity.com/upload/contest/20231030101137_0309ea76.jpg',
- 'https://www.wevity.com/upload/contest/20231030100653_e642b132.jpg',
- ],
- },
- ],
-};
const MyTeamApply = () => {
- // const { appliedTeamData } = useAppliedTeam();
- DUMMY;
+ const { appliedTeamData } = useAppliedTeam();
+ console.log(appliedTeamData);
+
return (
- {/* {DUMMY.data.map((each) => (
-
- ))} */}
+ {appliedTeamData?.data.data.map((each) => (
+
+ ))}
);
};
-const ApplyLayout = styled.div``;
+const ApplyLayout = styled.div`
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
+ gap: 3rem;
+`;
export default MyTeamApply;
diff --git a/src/pages/myteam/MyTeamCreate.tsx b/src/pages/myteam/MyTeamCreate.tsx
index 2effb9c..2594265 100644
--- a/src/pages/myteam/MyTeamCreate.tsx
+++ b/src/pages/myteam/MyTeamCreate.tsx
@@ -3,19 +3,34 @@ import ContestInfo from '../../components/contest/ContestInfo';
import MyTeamCreateOpen from '../../components/myteam/MyTeamCreateOpen';
import ButtonBox from '../../components/myteam/ButtonBox';
import { useSetRecoilState } from 'recoil';
-import { useEffect } from 'react';
+import { useEffect, useState } from 'react';
import { headerSelectedState } from '../../recoil/atom';
import { Headers } from '../../constants/Header';
+import { RequestTeamOpen } from '../../interface/MyTeam';
const MyTeamCreate = () => {
const setHeaderSelected = useSetRecoilState(headerSelectedState);
useEffect(() => setHeaderSelected(Headers.myTeam));
+ const [teamOpen, setTeamOpen] = useState({
+ contestId: '',
+ max: 0,
+ location: 0,
+ endDate: '',
+ leaderMessage: '',
+ notice: '',
+ chatLink: '',
+ });
+
+ const handleTeamOpenChange = (newTeamOpen: RequestTeamOpen) => {
+ setTeamOpen(newTeamOpen);
+ };
+
return (
-
-
+
+
);
};
diff --git a/src/pages/myteam/MyTeamEnd.tsx b/src/pages/myteam/MyTeamEnd.tsx
new file mode 100644
index 0000000..0c438f7
--- /dev/null
+++ b/src/pages/myteam/MyTeamEnd.tsx
@@ -0,0 +1,24 @@
+import { styled } from 'styled-components';
+import MyTeamEndBox from '../../components/myteam/end/MyTeamEndBox';
+import { useEndTeam } from '../../hooks/myTeam/useEndTeam';
+
+const MyTeamEnd = () => {
+ const { endTeam } = useEndTeam();
+
+ return (
+
+ {endTeam &&
+ endTeam.data.length > 0 &&
+ endTeam.data.map((myEndTeam) => (
+
+ ))}
+
+ );
+};
+
+export default MyTeamEnd;
+
+const MyTeamEndContainer = styled.div`
+ width: 122.4rem;
+ margin: 0 auto;
+`;
diff --git a/src/pages/myteam/MyTeamOpen.tsx b/src/pages/myteam/MyTeamOpen.tsx
new file mode 100644
index 0000000..528d84a
--- /dev/null
+++ b/src/pages/myteam/MyTeamOpen.tsx
@@ -0,0 +1,24 @@
+import { styled } from 'styled-components';
+import MyTeamOpenBox from '../../components/myteam/open/MyTeamOpenBox';
+import { useOpenedTeam } from '../../hooks/myTeam/useOpenedTeam';
+
+const MyTeamOpen = () => {
+ const { openedTeam } = useOpenedTeam();
+
+ return (
+
+ {openedTeam &&
+ openedTeam.data.length > 0 &&
+ openedTeam.data.map((myTeamOpen) => (
+
+ ))}
+
+ );
+};
+
+export default MyTeamOpen;
+
+const MyTeamOpenContainer = styled.div`
+ width: 122.4rem;
+ margin: 0 auto;
+`;
diff --git a/src/pages/profile/Profile.tsx b/src/pages/profile/Profile.tsx
index 4a9215e..d912689 100644
--- a/src/pages/profile/Profile.tsx
+++ b/src/pages/profile/Profile.tsx
@@ -16,14 +16,23 @@ import ProfileTicketLackModal from '../../components/profile/ProfileTicketLack/P
import useIsTicketUsed from '../../hooks/profile/useIsTicketUsed';
import useTicketNumber from '../../hooks/profile/useTicketNumber';
import ProfileTicketUseModal from '../../components/profile/profileTicketUse/ProfileTicketUseModal';
+import useIsUserGetExternalReview from '../../hooks/profile/useIsUserGetExternalReview';
const Profile = () => {
const setHeaderSelected = useSetRecoilState(headerSelectedState);
const { userId } = useParams();
+
+ // 인증 미필요
const { profileData, isLoading } = useProfile(userId as string);
const { profileReviewData, isLoadingReview } = useProfileReview(
userId as string,
);
+ const { isUserGetExternalReviewData } = useIsUserGetExternalReview(
+ userId as string,
+ );
+ // console.log(isUserGetExternalReviewData);
+
+ // 인증 필요
const { IsTicketUsedData } = useIsTicketUsed(userId as string);
const { TicketNumberData } = useTicketNumber();
@@ -62,11 +71,17 @@ const Profile = () => {
{
isLocked={!IsTicketUsedData?.data.data.isUsed}
setIsLackModalVisible={setIsLackModalVisible}
setIsUseModalVisible={setIsUseModalVisible}
+ isUserGetExternalReview={
+ isUserGetExternalReviewData?.data.data.alreadyReviewed
+ }
/>
);
diff --git a/src/pages/request/Request.tsx b/src/pages/request/Request.tsx
index affda79..0f23c95 100644
--- a/src/pages/request/Request.tsx
+++ b/src/pages/request/Request.tsx
@@ -6,10 +6,11 @@ import bgSrc from '/assets/images/request/request-bg.png';
import starSrc from '/assets/images/common/star.svg';
import kakaotalkSrc from '/assets/images/request/request-kakaotalk.svg';
import OneButtonModal from '../../components/common/OneButtonModal';
-import ModalInner from '../../components/request/ModalInner';
+
import { kakao } from '../../components/login/KakaoLogin';
import { loginInfoState } from '../../recoil/atom';
import JoinCompleteModal from '../../components/join/JoinCompleteModal';
+import ModalInner from '../../components/request/ModalInner';
const TITLE = '매력적인 프로필 완성을 위해 추천사를 요청해보세요.';
const CONTENT = [
'나와 딱 맞는 탁월한 팀원을 한번에 찾고 싶다면,\n나보다 나를 더 잘 아는 동료에게 추천사를 요청해 멋진 프로필을 완성하세요.',
@@ -33,7 +34,7 @@ const Request = () => {
templateId: 99541,
templateArgs: {
name: loginUserInfo.data?.name,
- userId : loginUserInfo.data?.userId
+ userId: loginUserInfo.data?.userId,
},
// serverCallbackArgs: {
// isSendSuccess: 'no', // 사용자 정의 파라미터 설정
diff --git a/src/recoil/atom.ts b/src/recoil/atom.ts
index 2864108..f9f96ac 100644
--- a/src/recoil/atom.ts
+++ b/src/recoil/atom.ts
@@ -36,3 +36,7 @@ export const loginModalState = atom({
key: 'loginModal',
default: false,
});
+export const needKakaoReviewModalState = atom({
+ key: 'needKakaoReviewModal',
+ default: false,
+});
\ No newline at end of file
diff --git a/src/recoil/myteam.ts b/src/recoil/myteam.ts
index 625d915..4776fba 100644
--- a/src/recoil/myteam.ts
+++ b/src/recoil/myteam.ts
@@ -1,6 +1,10 @@
import { atom } from 'recoil';
+import { recoilPersist } from 'recoil-persist';
+
+const { persistAtom } = recoilPersist();
export const selectedTeamAtom = atom({
key: 'selectedTeamAtom',
default: 0,
+ effects_UNSTABLE: [persistAtom],
});