Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FE][Feature] CreateRetro API 연결 #151

Merged
merged 3 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintcache
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"/Users/jeongmingong/past-forward-frontend/webpack.config.js":"1"},{"size":1775,"mtime":1713187107202,"results":"2","hashOfConfig":"3"},{"filePath":"4","messages":"5","suppressedMessages":"6","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1el0hh9","/Users/jeongmingong/past-forward-frontend/webpack.config.js",[],[]]
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"@emotion/eslint-plugin": "^11.11.0",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.0",
"@types/uuid": "^9.0.8",
"@types/webpack-env": "^1.18.4",
"aws-amplify": "^6.0.27",
"axios": "^1.6.8",
Expand All @@ -60,8 +61,9 @@
"styled-components": "^6.1.8",
"styled-reset": "^4.5.2",
"ts-node": "^10.9.2",
"uuid": "^9.0.1",
"webpack-env": "^0.8.0",
"yarn": "^1.22.21",
"yarn": "^1.22.22",
"yup": "^1.4.0"
},
"devDependencies": {
Expand Down
6 changes: 6 additions & 0 deletions src/api/@types/@asConst.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ export const Status = {
COMPLETED: 'COMPLETED',
} as const;

export const RetrospectiveType = {
TEAM: 'TEAM',
PERSONAL: 'PERSONAL',
};

export const Template = {
1: 'Keep',
2: 'Ploblem',
Expand All @@ -19,3 +24,4 @@ export const Template = {
export type TStatus = typeof Status;
export type TOrder = typeof Order;
export type TTemplate = typeof Template;
export type TRetrospective = typeof RetrospectiveType;
7 changes: 5 additions & 2 deletions src/api/@types/RetrospectiveTemplates.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
export interface RetrospectivesTemplateResponse {
code: number;
message: string;
data: [{ id: number; name: string }];
message: string | null;
data: Array<{
id: number;
name: string;
}>;
}

export interface retrospectivesTemplateClient {
Expand Down
24 changes: 9 additions & 15 deletions src/api/@types/Retrospectives.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TStatus } from './@asConst';
import { TRetrospective, TStatus } from './@asConst';

// get
export interface GetRetrospectiveRequest {
Expand All @@ -22,7 +22,7 @@ export interface GetRetrospectiveData {
//post
export interface PostRetrospectivesRequest {
title: string;
teamId: number;
type: keyof TRetrospective;
userId: number;
templateId: number;
status: keyof TStatus;
Expand All @@ -32,19 +32,13 @@ export interface PostRetrospectivesRequest {
}

export interface PostRetrospectivesResponse {
code: number;
message: string;
data: {
id: number;
title: string;
teamId: number;
userId: number;
templateId: number;
status: keyof TStatus;
thumbnail: string;
startDate: string;
description: string;
};
id: number;
title: string;
userId: number;
templateId: number;
status: keyof TStatus;
thumbnail: string;
description: string;
}

//delete
Expand Down
21 changes: 21 additions & 0 deletions src/api/@types/Thumbnail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//post
export interface PostImageToS3Request {
filename: string;
method: string;
}

export interface PostImageToS3Response {
filename: string;
preSignedUrl: string;
}

// 유저 프로필 사진
export interface PutThumbnailRequest {
thumbnail: string;
}

export interface PutThumbnailResponse {
userId: number;
email: string;
thumbnail: string;
}
16 changes: 9 additions & 7 deletions src/api/__mock__/retrospectiveTemplate.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// export const mockRetrospectiveTemplate: RetrospectivesTemplateResponse[] = [
// { id: 1, name: 'hee' },
// {
// id: 2,
// name: 'jung',
// },
// ];
import { RetrospectivesTemplateResponse } from '../@types/RetrospectiveTemplates';

export const mockRetrospectiveTemplate: RetrospectivesTemplateResponse[] = [
// { id: 1, name: 'hee' },
// {
// id: 2,
// name: 'jung',
// },
];
38 changes: 38 additions & 0 deletions src/api/axiosConfig.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { fetchAuthSession } from 'aws-amplify/auth';
import axios from 'axios';

// Axios 인스턴스 생성
const axiosInstance = axios.create({
baseURL: 'https://api.pastforward.link/',
headers: {
'Content-Type': 'application/json;charset=UTF-8',
},
});

// Axios 요청을 보내기 전에 실행
axiosInstance.interceptors.request.use(
async config => {
try {
// 현재 세션에서 토큰 가져오기
const { accessToken } = (await fetchAuthSession()).tokens || {};

// accessToken이 없으면 반환
if (!accessToken) {
console.log('세션 토큰 없음');
return config;
}

// 헤더에 토큰 추가
config.headers['Authorization'] = `Bearer ${accessToken}`;
return config;
} catch (err) {
console.error('에러', err);
return config;
}
},
error => {
return Promise.reject(error);
},
);

export default axiosInstance;
15 changes: 15 additions & 0 deletions src/api/imageApi/postImageToS3.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import axiosInstance from '../axiosConfig';
import { PostImageToS3Request, PostImageToS3Response } from '@/api/@types/Thumbnail';

// post 요청
const postImageToS3 = async (requestData: PostImageToS3Request): Promise<PostImageToS3Response> => {
try {
const response = await axiosInstance.post<PostImageToS3Response>('/s3/pre-signed-url', requestData);
console.log('사진 s3 업로드 성공', response.data);
return response.data;
} catch (error) {
throw new Error('실패');
}
};

export default postImageToS3;
15 changes: 15 additions & 0 deletions src/api/imageApi/putUserThumbnail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import axiosInstance from '../axiosConfig';
import { PutThumbnailRequest, PutThumbnailResponse } from '@/api/@types/Thumbnail';

// put 요청
const putUserThumbnail = async (requestData: PutThumbnailRequest): Promise<PutThumbnailResponse> => {
try {
const response = await axiosInstance.put<PutThumbnailResponse>('/users/{userId}/thumbnail', requestData);
console.log('프로필 사진 등록 성공', response.data);
return response.data;
} catch (error) {
throw new Error('실패');
}
};

export default putUserThumbnail;
14 changes: 14 additions & 0 deletions src/api/retrospectivesApi/getTemplate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import axiosInstance from '../axiosConfig';
import { RetrospectivesTemplateResponse } from '@/api/@types/RetrospectiveTemplates';

const getTemplate = async () => {
try {
const response = await axiosInstance.get<RetrospectivesTemplateResponse>('/retrospective-templates');
console.log('템플릿 조회 성공', response.data);
return response.data.data;
} catch (error) {
throw new Error('템플릿 조회 실패');
}
};

export default getTemplate;
15 changes: 15 additions & 0 deletions src/api/retrospectivesApi/postRetrospective.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import axiosInstance from '../axiosConfig';
import { PostRetrospectivesRequest, PostRetrospectivesResponse } from '@/api/@types/Retrospectives';

// post 요청
const postRetrospective = async (requestData: PostRetrospectivesRequest): Promise<PostRetrospectivesResponse> => {
try {
const response = await axiosInstance.post<PostRetrospectivesResponse>('/retrospectives', requestData);
console.log('회고 생성 성공', response.data);
return response.data;
} catch (error) {
throw new Error('회고 생성 실패');
}
};

export default postRetrospective;
22 changes: 18 additions & 4 deletions src/components/createRetro/CreateButtonBox.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useState } from 'react';
import { useDisclosure } from '@chakra-ui/react';
import PersonalRetroCreateButton from '@/components/createRetro/PersonalRetroCreateButton';
import TeamRetroCreateButton from '@/components/createRetro/TeamRetroCreateButton';
Expand All @@ -7,18 +7,32 @@ import * as S from '@/styles/createRetro/CreateButtonBox.style';

const CreateButtonBox: React.FC = () => {
const { isOpen, onOpen, onClose } = useDisclosure();
const [templateId, setTemplateId] = useState<number | null>(null);
const [type, setType] = useState<'TEAM' | 'PERSONAL'>('TEAM');

const handleTeamButtonClick = () => {
setTemplateId(1);
setType('TEAM'); // TEAM으로 type 설정
onOpen();
};

const handlePersonalButtonClick = () => {
setTemplateId(2);
setType('PERSONAL'); // PERSONAL로 type 설정
onOpen();
};

return (
<>
<S.ButtonListContainer>
<S.SpacedButton onClick={onOpen}>
<S.SpacedButton onClick={handleTeamButtonClick}>
<TeamRetroCreateButton />
</S.SpacedButton>
<S.SpacedButton onClick={onOpen}>
<S.SpacedButton onClick={handlePersonalButtonClick}>
<PersonalRetroCreateButton />
</S.SpacedButton>
</S.ButtonListContainer>
<CreateModal isOpen={isOpen} onClose={onClose} />
<CreateModal isOpen={isOpen} onClose={onClose} templateId={templateId} type={type} />
</>
);
};
Expand Down
50 changes: 39 additions & 11 deletions src/components/createRetro/modal/CreateModal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import {
Modal,
Expand All @@ -9,9 +9,10 @@ import {
ModalCloseButton,
Button,
} from '@chakra-ui/react';
import { Status } from '@/api/@types/@asConst';
import { Status, TRetrospective } from '@/api/@types/@asConst';
import { PostRetrospectivesRequest } from '@/api/@types/Retrospectives';
import { RetrospectiveService } from '@/api/services/Retrospectives';
import postImageToS3 from '@/api/imageApi/postImageToS3';
import postRetrospective from '@/api/retrospectivesApi/postRetrospective';
import DescriptionInput from '@/components/createRetro/modal/DescriptionInput';
import ImageUpload from '@/components/createRetro/modal/ImageUpload';
import StartDateCalendar from '@/components/createRetro/modal/StartDateCalender';
Expand All @@ -22,36 +23,60 @@ import * as S from '@/styles/createRetro/modal/CreateModal.style';
interface CreateModalProps {
isOpen: boolean;
onClose: () => void;
templateId: number | null;
type: keyof TRetrospective;
}

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

useEffect(() => {
setRequestData(prevData => ({
...prevData,
templateId: templateId || 1, // templateId가 변경될 때마다 업데이트
type: type,
}));
}, [templateId, type]);

const handleCreateClick = async () => {
try {
const response = await RetrospectiveService.create({
// 회고 먼저 생성
const retrospectiveResponse = await postRetrospective({
...requestData,
status: Status.NOT_STARTED,
});
console.log('생성', response);

// 이미지를 S3에 업로드
const imageResponse = await postImageToS3({
filename: requestData.thumbnail, // imageUUID를 filename으로 설정
method: 'PUT',
});

console.log('회고 생성 성공', retrospectiveResponse);
console.log('사진 S3 업로드 성공', imageResponse);

onClose();
navigate('/invite');
} catch (error) {
console.error('실패', error);
}
};

const handleTemplateChange = (selectedTemplateId: number) => {
setRequestData({ ...requestData, templateId: selectedTemplateId });
};

return (
<Modal isOpen={isOpen} size={size} onClose={onClose}>
<ModalOverlay />
Expand All @@ -61,12 +86,15 @@ const CreateModal: React.FC<CreateModalProps> = ({ isOpen, onClose }) => {

<S.CustomModalBody>
<S.LeftColumn>
<ImageUpload onChange={thumbnail => setRequestData({ ...requestData, thumbnail })} />
<ImageUpload
onChange={(_thumbnail, imageUUID) => setRequestData({ ...requestData, thumbnail: imageUUID })}
/>
</S.LeftColumn>
<S.RightColumn>
<TitleInput onChange={title => setRequestData({ ...requestData, title })} />
<TemplateSelect onChange={templateId => setRequestData({ ...requestData, templateId })} />
<StartDateCalendar onChange={startDate => setRequestData({ ...requestData, startDate })} />
<TemplateSelect onChange={handleTemplateChange} defaultTemplateId={requestData.templateId} />

<StartDateCalendar onDateChange={startDate => setRequestData({ ...requestData, startDate })} />
</S.RightColumn>
</S.CustomModalBody>
<S.BottomModalBody>
Expand Down
Loading
Loading