Skip to content

Commit

Permalink
공지사항 api 연동
Browse files Browse the repository at this point in the history
공지사항 api 연동
  • Loading branch information
eejx0 authored May 30, 2024
2 parents b0eb29b + 8ee0dcf commit b2d391e
Show file tree
Hide file tree
Showing 19 changed files with 740 additions and 247 deletions.
49 changes: 7 additions & 42 deletions src/Apis/Files/index.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,10 @@
import { useMutation } from 'react-query';
// import { PresignedUrlRequest } from "./request"
import { PresignedUrlResponse } from './response';
import { instance } from '../axios';
import axios from 'axios';

// export const usePresignedUrl = () => {
// return useMutation(
// async (attachments: File[]) => {
// const files = attachments.map((item) => ({
// type: 'EXTENSION_FILE',
// file_name: item.name,
// }));

// const data = await instance.post(`${process.env.REACT_APP_BASE_URL}/files/pre-signed`, {files});

// return data;
// }, {
// onSuccess: ({data}) => {
// console.log(data);
// }
// }
// )
// }
// propsData: PresignedUrlRequest/

export const usePresignedUrl = () => {
return useMutation(
const res = useMutation(
async (attachments: File[]) => {
const files = attachments.map((item) => ({
type: 'EXTENSION_FILE',
Expand All @@ -41,29 +20,15 @@ export const usePresignedUrl = () => {
},
{
onSuccess: async ({ presignedUrls, attachments }) => {
const uploadPromises = presignedUrls.urls.map(
({ pre_signed_url }, idx) => {
return (async () =>
await axios.put(
pre_signed_url,
attachments[idx]
))();
}
const uploadPromises = await Promise.all(
presignedUrls.urls.map(({ pre_signed_url }, idx) => {
return axios.put(pre_signed_url, attachments[idx]);
})
);
await Promise.all(uploadPromises);
return;
},
}
);
return res;
};

// const readFileAsBinaryString = (file: File): Promise<string> => {
// return new Promise((resolve, reject) => {
// const reader = new FileReader();
// reader.onload = () => {
// const result = reader.result as string;
// resolve(result);
// };
// reader.onerror = reject;
// reader.readAsBinaryString(file);
// });
// }
8 changes: 3 additions & 5 deletions src/Apis/Files/response.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
export interface PresignedUrlResponse {
urls: [
{
urls: {
file_path: string,
pre_signed_url: string
}
]
pre_signed_url: string,
}[]
}
6 changes: 5 additions & 1 deletion src/Apis/Login/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ export const Login = (loginData: LoginDataType, checkBoxValue: boolean) => {
});
} else {
if (checkBoxValue) {
setCookies('account_id', loginData.account_id);
setCookies('account_id', loginData.account_id, {
path: '/'
});
} else {
removeCookies('account_id');
}
Expand All @@ -40,9 +42,11 @@ export const Login = (loginData: LoginDataType, checkBoxValue: boolean) => {
);
setCookies('refresh_token', res.data.refresh_token, {
expires: refreshExpired,
path: '/'
});
setCookies('access_token', res.data.access_token, {
expires: accessExpired,
path: '/'
});
navigator('/RecruitmentRequest');
}
Expand Down
158 changes: 138 additions & 20 deletions src/Apis/Notices/index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,139 @@
import { NoticeWrite } from "./request";
import { useMutation } from "react-query";
import { instance } from "../axios";

export const useNoticeWriteData = (noticeData: NoticeWrite) => {
const formData = new FormData()
noticeData.attachments.forEach((attachment) => { formData.append('file', attachment) })

return useMutation(
async () => {
const { data } = await instance.post(`${process.env.REACT_APP_BASE_URL}/notices`, {...noticeData, attachments: formData});
return data;
},
{
onError: (error: Error) => {
console.error("공지 작성에 실패하였습니다:", error.message);
}
}
)
}
import { NoticeWrite, NoticeEdit } from './request';
import { MutationOptions, useMutation } from 'react-query';
import { instance } from '../axios';
import { NoticeListResponse } from './response';
import { useCallback, useEffect, useState } from 'react';
import { NoticeDetailResponse } from './response';
import { useToastStore } from '@team-return/design-system';

const router = '/notices';

/** 공지사항 작성 */
export const useNoticeWriteData = () => {
const { append } = useToastStore();
return useMutation(
async (noticeData: NoticeWrite) => {
const { data } = await instance.post(`${router}`, noticeData);
return data;
},
{
onError: () => {
append({
title: '공지 작성에 실패했습니다.',
message: '',
type: 'RED',
});
},
}
);
};

/** 공지사항 수정 */
export const useNoticeEditData = (noticeId: string) => {
const { append } = useToastStore();
return useMutation(
async (noticeData: NoticeEdit) => {
const { data } = await instance.patch(
`${router}/${noticeId}`,
noticeData
);
return data;
},
{
onError: () => {
append({
title: '공지 수정에 실패했습니다.',
message: '',
type: 'RED',
});
},
}
);
};

/** 공지사항 상세보기 조회 */
export const useNoticeDetailData = (noticeId: string) => {
const [noticeDetail, setNoticeDetail] =
useState<NoticeDetailResponse | null>(null);
const { append } = useToastStore();

const fetchNoticeDetail = (noticeId: string) => {
return instance
.get(`${router}/${noticeId}`)
.then((response) => {
const data = response.data;
const fetchedNoticeDetail: NoticeDetailResponse = {
title: data.title,
content: data.content,
created_at: new Date(data.created_at).toISOString(),
attachments: data.attachments.map((attachment: any) => ({
url: attachment.url,
type: attachment.type,
})),
};
setNoticeDetail(fetchedNoticeDetail);
})
.catch(() => {
append({
title: '공지 상세보기에 실패했습니다.',
message: '',
type: 'RED',
});
});
};

useState(() => {
fetchNoticeDetail(noticeId);
});

return { noticeDetail };
};

/** 공지사항 리스트 조희 */
export const useNoticeListData = () => {
const [notices, setNotices] = useState<NoticeListResponse[]>([]);
const { append } = useToastStore();

const fetchNoticeList = useCallback(() => {
return instance
.get(`${router}`)
.then((response) => {
const data = response.data;

const fetchedNotices: NoticeListResponse[] = data.notices.map(
(notice: any) => ({
id: notice.id,
title: notice.title,
created_at: new Date(notice.created_at).toISOString(),
})
);
setNotices(fetchedNotices);
})
.catch(() => {
append({
title: '공지 상세보기에 실패했습니다.',
message: '',
type: 'RED',
});
});
}, [append]);

useEffect(() => {
fetchNoticeList();
}, [fetchNoticeList]);

return { notices };
};

/** 공지사항 삭제 */
export const useDeleteNotice = (noticeId: string, options: MutationOptions) => {
return useMutation(
async () =>
instance.delete(`${router}/${noticeId}`, {
data: { 'notice-id': noticeId },
}),
{
...options,
}
);
};
19 changes: 18 additions & 1 deletion src/Apis/Notices/request.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
import { AttachmentType } from "./response";

export interface NoticeWrite {
title: string;
content: string;
attachments: string[];
attachments: AttachmentRequest[];
}

export interface NoticeEdit {
title: string;
content: string;
attachments: AttachmentRequest[];
}

export interface AttachmentRequest {
url: string;
type: AttachmentType;
}

export interface NoticeDelete {
noticeId: string;
}
21 changes: 21 additions & 0 deletions src/Apis/Notices/response.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export interface NoticeListResponse {
id: number
title: string
created_at: string
}

export interface NoticeDetailResponse {
title: string;
content: string;
created_at: string;
attachments: AttachmentResponse[];
}

export type AttachmentType =
| "FILE"
| "URL"

export interface AttachmentResponse {
url: string;
type: AttachmentType;
}
2 changes: 1 addition & 1 deletion src/Apis/axios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ instance.interceptors.response.use(
if (!refreshToken) {
cookies.remove('access_token');
cookies.remove('refresh_token');
window.location.href = '/login';
// window.location.href = '/login';
return;
}
if (
Expand Down
62 changes: 62 additions & 0 deletions src/Components/Notice/AttachedBox/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Icon, useToastStore } from '@team-return/design-system';
import { AttachmentResponse } from '../../../Apis/Notices/response';
import * as _ from './style';
import axios from 'axios';

interface PropsType {
props: AttachmentResponse[];
}

export function AttachedBox({ props }: PropsType) {
const file_name_regex = (url: string) => {
return url.replace(/(?:.*?-){5}(.*)/, '$1').replaceAll('+', ' ');
};
const { append } = useToastStore();

const downLoadFile = async (attachment: AttachmentResponse) => {
try {
const { data } = await axios.get(
`${process.env.REACT_APP_FILE_URL}${attachment.url}`,
{
responseType: 'blob',
}
);
const url = window.URL.createObjectURL(new Blob([data]));
const a = document.createElement('a');
a.href = url;
a.download = file_name_regex(attachment.url);
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
} catch {
append({
title: '파일 다운로드에 실패했습니다.',
message: '',
type: 'RED',
});
}
};

return (
<>
<_.AttachedWrapper>
<_.AttachmentTitle>첨부자료</_.AttachmentTitle>
<_.Attachments>
{props.map((attachment, index) => (
<_.Attachment key={index}>
<div>{file_name_regex(attachment.url)}</div>
<Icon
icon="Download"
size={15}
color="liteBlue"
cursor="pointer"
onClick={() => downLoadFile(attachment)}
/>
</_.Attachment>
))}
</_.Attachments>
</_.AttachedWrapper>
</>
);
}
Loading

0 comments on commit b2d391e

Please sign in to comment.