Skip to content

Commit

Permalink
Merge branch 'develop' into fix/#170
Browse files Browse the repository at this point in the history
  • Loading branch information
heejung0413 authored Apr 19, 2024
2 parents e9f4f7e + 93589e5 commit d7c32d8
Show file tree
Hide file tree
Showing 24 changed files with 769 additions and 772 deletions.
4 changes: 4 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { Navigate, useLocation } from 'react-router-dom';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import { getCurrentUser } from 'aws-amplify/auth';
import { RecoilRoot } from 'recoil';

import AcceptInvite from './components/inviteTeam/AcceptInvite';

import RetroRevisePage from './pages/RevisePage';
import RetroTeamPage from './pages/SectionPage';
import MainLayout from '@/components/layout/MainLayout';
Expand Down Expand Up @@ -130,6 +133,7 @@ const App = () => {
</PrivateRoute>
}
/>
<Route path="/invitations/:invitationId" Component={AcceptInvite} />
</Routes>
</Router>
</RecoilRoot>
Expand Down
7 changes: 7 additions & 0 deletions src/api/@types/InviteTeam.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// get
export interface GetInviteTeamRequest {
// teamId: number;
}
Expand All @@ -14,3 +15,9 @@ export interface InviteTeamData {
expirationTime: string;
qrCodeImage: string;
}

// post
export interface PostInviteTeamRequest {
invitationCode: string;
}
export interface PostInviteTeamResponse {}
2 changes: 1 addition & 1 deletion src/api/@types/Retrospectives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export interface PostRetrospectivesRequest {
templateId: number;
status: keyof TStatus;
thumbnail: string | null;
startDate: string;
startDate: Date | string;
description: string;
}

Expand Down
15 changes: 15 additions & 0 deletions src/api/@types/Survey.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// post
export interface PostSurveyRequest {
age: number;
gender: string;
occupation: string;
region: string;
source: string;
purpose: string;
}

export interface PostSurveyResponse {
code: number;
message: string;
data: string;
}
2 changes: 1 addition & 1 deletion src/api/axiosConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ axiosInstance.interceptors.request.use(

// 헤더에 토큰 추가
config.headers.Authorization = `Bearer ${authToken}`;
// console.log('헤더에 토큰 추가 확인', config.headers.Authorization);
console.log('헤더에 토큰 추가 확인', config.headers.Authorization);
return config;
} catch (err) {
console.error('에러', err);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import axiosInstance from '../axiosConfig';
const getInviteTeam = async (teamId: GetInviteTeamRequest): Promise<GetInviteTeamResponse> => {
try {
const response = await axiosInstance.get<GetInviteTeamResponse>(`/teams/${teamId}/invitation-url`);
console.log('팀원 초대 호출 성공', response.data);
console.log('팀원 초대 링크 호출 성공', response.data);
return response.data;
} catch (error) {
throw new Error('팀원 초대 호출 실패');
throw new Error('팀원 초대 링크 호출 실패');
}
};

Expand Down
16 changes: 16 additions & 0 deletions src/api/inviteTeamApi/postInviteTeam.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// import { PostInviteTeamRequest } from '../@types/InviteTeam';
import axiosInstance from '../axiosConfig';

const postInviteTeam = async (invitationId: string) => {
try {
const response = await axiosInstance.post('/team/accept-invitation', {
invitationCode: invitationId,
});
console.log('팀원 초대 성공', response.data);
return response.data;
} catch (error) {
throw new Error('팀원 초대 실패');
}
};

export default postInviteTeam;
13 changes: 13 additions & 0 deletions src/api/survey/postSurvey.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { PostSurveyRequest, PostSurveyResponse } from '../@types/Survey';
import axiosInstance from '../axiosConfig';

// post 요청
export const PostSurvey = async (requestData: PostSurveyRequest): Promise<PostSurveyResponse> => {
try {
const response = await axiosInstance.post<PostSurveyResponse>('/surveys/response', requestData);
console.log('설문조사 전송 성공', response.data);
return response.data;
} catch (error) {
throw new Error('실패');
}
};
34 changes: 18 additions & 16 deletions src/components/RetroList/ContentsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,15 @@ const ContentList: React.FC<ContentListProps> = ({ data, viewMode, searchData, s
/>
<S.MoreIcon
src={MoreIcon}
onClick={() => openModalForItem(item.id)}
// onClick={() => {
// if(유저아이디 !== item.id) { // 수정 권한 없을 때(생성자가 아닐 때)
// openModalForItem(item.id)
// } else {
// navigate(`/revise?retrospectiveId=${item.id}&teamId=${item.teamId}`);
// }
// }}
// onClick={() => openModalForItem(item.id)}
onClick={() => {
if (item.userId === item.id) {
// 수정 권한 없을 때(생성자가 아닐 때 확인하고 고치기)
openModalForItem(item.id);
} else {
navigate(`/revise?retrospectiveId=${item.id}&teamId=${item.teamId}`);
}
}}
/>
</div>
<S.RetroUser>
Expand Down Expand Up @@ -175,14 +176,15 @@ const ContentList: React.FC<ContentListProps> = ({ data, viewMode, searchData, s
<S.ListLinkBox>
<S.MoreIconListView
src={MoreIcon}
onClick={() => openModalForItem(item.id)}
// onClick={() => {
// if(유저아이디 !== item.id) { // 수정 권한 없을 때(생성자가 아닐 때)
// openModalForItem(item.id)
// } else {
// navigate(`/revise?retrospectiveId=${item.id}&teamId=${item.teamId}`);
// }
// }}
// onClick={() => openModalForItem(item.id)}
onClick={() => {
if (item.userId === item.id) {
// 수정 권한 없을 때(생성자가 아닐 때 확인하고 고치기)
openModalForItem(item.id);
} else {
navigate(`/revise?retrospectiveId=${item.id}&teamId=${item.teamId}`);
}
}}
/>
<Modal onClose={closeModalForItem} isOpen={openModalId === item.id} />
</S.ListLinkBox>
Expand Down
6 changes: 5 additions & 1 deletion src/components/createRetro/CreateButtonBox.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState } from 'react';
import { useDisclosure } from '@chakra-ui/react';
import { TStatus } from '@/api/@types/@asConst';
import PersonalRetroCreateButton from '@/components/createRetro/PersonalRetroCreateButton';
import TeamRetroCreateButton from '@/components/createRetro/TeamRetroCreateButton';
import CreateModal from '@/components/createRetro/modal/CreateModal';
Expand All @@ -9,16 +10,19 @@ const CreateButtonBox: React.FC = () => {
const { isOpen, onOpen, onClose } = useDisclosure();
const [templateId, setTemplateId] = useState<number | null>(null);
const [type, setType] = useState<'TEAM' | 'PERSONAL'>('TEAM');
const [status, setStatus] = useState<keyof TStatus>('NOT_STARTED');

const handleTeamButtonClick = () => {
setTemplateId(1);
setType('TEAM'); // TEAM으로 type 설정
setStatus('NOT_STARTED'); // 초기 상태
onOpen();
};

const handlePersonalButtonClick = () => {
setTemplateId(2);
setType('PERSONAL'); // PERSONAL로 type 설정
setStatus('NOT_STARTED'); // 초기 상태
onOpen();
};

Expand All @@ -32,7 +36,7 @@ const CreateButtonBox: React.FC = () => {
<PersonalRetroCreateButton />
</S.SpacedButton>
</S.ButtonListContainer>
<CreateModal isOpen={isOpen} onClose={onClose} templateId={templateId} type={type} />
<CreateModal isOpen={isOpen} onClose={onClose} templateId={templateId} type={type} status={status} />
</>
);
};
Expand Down
36 changes: 28 additions & 8 deletions src/components/createRetro/modal/CreateModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
ModalCloseButton,
Button,
} from '@chakra-ui/react';
import { Status, TRetrospective } from '@/api/@types/@asConst';
import { TRetrospective, TStatus } from '@/api/@types/@asConst';
import { PostRetrospectivesRequest } from '@/api/@types/Retrospectives';
import postImageToS3 from '@/api/imageApi/postImageToS3';
import postRetrospective from '@/api/retrospectivesApi/postRetrospective';
Expand All @@ -25,19 +25,20 @@ interface CreateModalProps {
onClose: () => void;
templateId: number | null;
type: keyof TRetrospective;
status: keyof TStatus;
}

const CreateModal: React.FC<CreateModalProps> = ({ isOpen, onClose, templateId, type }) => {
const CreateModal: React.FC<CreateModalProps> = ({ isOpen, onClose, templateId, type, status }) => {
const size = 'xl';
const navigate = useNavigate();
const [requestData, setRequestData] = useState<PostRetrospectivesRequest>({
title: '',
type: type,
userId: 1,
templateId: templateId || 1,
status: Status.NOT_STARTED,
status: status,
thumbnail: null,
startDate: '',
startDate: new Date(),
description: '',
});

Expand All @@ -46,15 +47,30 @@ const CreateModal: React.FC<CreateModalProps> = ({ isOpen, onClose, templateId,
...prevData,
templateId: templateId || 1, // templateId가 변경될 때마다 업데이트
type: type,
status: status,
}));
}, [templateId, type]);
}, [templateId, type, status]);

const handleCreateClick = async () => {
try {
let calculatedStatus: keyof TStatus = 'NOT_STARTED'; // 기본값은 'NOT_STARTED'로 설정

// startDate 값이 오늘 이전이면 'IN_PROGRESS'로 설정
const today = new Date();
const startedDate = new Date(requestData.startDate);
// console.log(startedDate);
if (startedDate <= today) {
calculatedStatus = 'IN_PROGRESS';
}

const isoDateString = startedDate.toISOString();
// console.log(isoDateString);

// 회고 생성 요청 전송
const retrospectiveResponse = await postRetrospective({
...requestData,
status: Status.NOT_STARTED,
startDate: isoDateString,
status: calculatedStatus, // 계산된 status 값으로 설정
thumbnail: requestData.thumbnail || null, // thumbnail이 없으면 null을 전송
});

Expand All @@ -79,6 +95,11 @@ const CreateModal: React.FC<CreateModalProps> = ({ isOpen, onClose, templateId,
setRequestData({ ...requestData, templateId: selectedTemplateId });
};

const handleStartDateChange = (startDate: Date) => {
console.log('startDate:', startDate); // startDate를 콘솔에 출력
setRequestData({ ...requestData, startDate }); // startDate 상태 업데이트
};

return (
<Modal isOpen={isOpen} size={size} onClose={onClose}>
<ModalOverlay />
Expand All @@ -95,8 +116,7 @@ const CreateModal: React.FC<CreateModalProps> = ({ isOpen, onClose, templateId,
<S.RightColumn>
<TitleInput onChange={title => setRequestData({ ...requestData, title })} />
<TemplateSelect onChange={handleTemplateChange} defaultTemplateId={requestData.templateId} />

<StartDateCalendar onDateChange={startDate => setRequestData({ ...requestData, startDate })} />
<StartDateCalendar onDateChange={handleStartDateChange} />
</S.RightColumn>
</S.CustomModalBody>
<S.BottomModalBody>
Expand Down
27 changes: 8 additions & 19 deletions src/components/createRetro/modal/StartDateCalender.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,20 @@
import React, { useState } from 'react';
import { ko } from 'date-fns/locale/ko';
import React from 'react';
import { Input } from '@chakra-ui/react';
import 'react-datepicker/dist/react-datepicker.css';
import * as S from '@/styles/createRetro/modal/StartDateCalendar.style';
import '@/styles/createRetro/modal/Calendar.css';

interface StartDateCalendarProps {
onDateChange: (dateString: string) => void;
onDateChange: (date: Date) => void;
}

const StartDateCalendar: React.FC<StartDateCalendarProps> = ({ onDateChange }) => {
const [selectedDate, setSelectedDate] = useState(new Date());

const handleDateChange = (date: Date) => {
setSelectedDate(date);
const isoDateString = date.toISOString(); // 백엔드 request body에 보낼 날짜 타입
onDateChange(isoDateString);
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const dateString = event.target.value; // 사용자가 입력한 날짜 문자열
const selectedDate = new Date(dateString); // 문자열을 Date 객체로 변환
onDateChange(selectedDate); // 부모 컴포넌트로 전달
};

return (
<S.DateInput
selected={selectedDate}
onChange={handleDateChange}
locale={ko}
dateFormat="yyyy-MM-dd"
showPopperArrow={false}
/>
);
return <Input placeholder="회고 시작일 선택" size="md" type="date" onChange={handleChange} />;
};

export default StartDateCalendar;
38 changes: 38 additions & 0 deletions src/components/inviteTeam/AcceptInvite.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React, { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import postInviteTeam from '@/api/inviteTeamApi/postInviteTeam';

const AcceptInvite: React.FC = () => {
const { invitationId } = useParams<{ invitationId?: string }>();
const navigate = useNavigate();
const [inviteSuccess, setInviteSuccess] = useState(false);

useEffect(() => {
const acceptInvitation = async () => {
try {
if (invitationId) {
await postInviteTeam(invitationId);
setInviteSuccess(true); // 초대 요청이 성공했을 때 상태를 true로 변경
} else {
console.error('InvitationId 추출 실패');
}
} catch (error) {
console.error('에러', error);
}
};

acceptInvitation();
}, [invitationId]);

useEffect(() => {
if (inviteSuccess) {
// 초대 성공 시 알림을 띄우고 retrolist 페이지로 navigate
alert('초대 성공했습니다!');
navigate('/retrolist');
}
}, [inviteSuccess, navigate]);

return <div>초대를 수락하는 중...</div>;
};

export default AcceptInvite;
Loading

0 comments on commit d7c32d8

Please sign in to comment.