Skip to content

Commit

Permalink
refactor: 공지사항 리펙토링
Browse files Browse the repository at this point in the history
  • Loading branch information
eejx0 committed Apr 2, 2024
1 parent 71a55cf commit d77e20b
Show file tree
Hide file tree
Showing 16 changed files with 410 additions and 72 deletions.
43 changes: 5 additions & 38 deletions src/Apis/Files/index.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,7 @@
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/
import { useMutation } from "react-query";
import { PresignedUrlResponse } from "./response";
import { instance } from "../axios";
import axios from "axios";

export const usePresignedUrl = () => {
return useMutation(
Expand All @@ -44,16 +23,4 @@ export const usePresignedUrl = () => {
}
}
)
}

// 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);
// });
// }
}
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
73 changes: 71 additions & 2 deletions src/Apis/Notices/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { NoticeWrite } from "./request";
import { useMutation } from "react-query";
import { MutationOptions, useMutation } from "react-query";
import { instance } from "../axios";
import { NoticeListResponse } from "./response";
import { useEffect, useState } from "react";
import { NoticeDetailResponse } from "./response";

/** 공지사항 작성 */
export const useNoticeWriteData = (noticeData: NoticeWrite) => {
const formData = new FormData()
noticeData.attachments.forEach((attachment) => { formData.append('file', attachment) })
Expand All @@ -13,9 +17,74 @@ export const useNoticeWriteData = (noticeData: NoticeWrite) => {
},
{
onError: (error: Error) => {
console.error("공지 작성에 실패하였습니다:", error.message);
console.error("notice write error:", error.message);
}
}
)
}

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

useEffect(() => {
const fetchNoticeDetail = async () => {
try {
const response = await instance.get(`${process.env.REACT_APP_BASE_URL}/notices/${noticeId}`);
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 (error: any) {
console.error('notice detail error:', error.message);
}
};
fetchNoticeDetail();
}, [noticeId]);

return { noticeDetail };
};

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

useEffect(() => {
const fetchNoticeList = async () => {
try {
const response = await instance.get(`${process.env.REACT_APP_BASE_URL}/notices`);
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 (error: any) {
console.error('notice list error: ', error.message);
}
};
fetchNoticeList();
}, []);

return { notices };
}

/** 공지사항 삭제 */
export const useDeleteNotice = (noticeId: string, options: MutationOptions) => {
return useMutation(
async () => instance.delete(`${process.env.REACT_APP_BASE_URL}/notices/${noticeId}`, { data: { "notice-id": noticeId } }),
{
...options
}
)
}
4 changes: 4 additions & 0 deletions src/Apis/Notices/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@ export interface NoticeWrite {
title: string;
content: string;
attachments: string[];
}

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[];
}

type AttachmentType =
| "FILE"
| "URL"

export interface AttachmentResponse {
url: string;
type: AttachmentType;
}
5 changes: 4 additions & 1 deletion src/Apis/axios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ let flag = false;
instance.interceptors.request.use(
(config) => {
const accessToken = cookies.get('access_token');
console.log();

const returnConfig = { ...config };
if (accessToken) {
returnConfig.headers!['Authorization'] = `Bearer ${accessToken}`;
Expand All @@ -28,10 +30,11 @@ instance.interceptors.response.use(
if (axios.isAxiosError(error) && error.response) {
const { config } = error;
const refreshToken = cookies.get('refresh_token');
console.log(refreshToken);
if (!refreshToken) {
cookies.remove('access_token');
cookies.remove('refresh_token');
window.location.href = '/login';
// window.location.href = '/login';
return;
}
if (
Expand Down
58 changes: 58 additions & 0 deletions src/Components/Notice/AttachedBox/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Icon } 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 downLoadFile = async (attachment: AttachmentResponse) => {
try {
const response = await axios.get(
`${process.env.REACT_APP_FILE_URL}${attachment.url}`,
{
responseType: 'blob',
}
);

const url = window.URL.createObjectURL(new Blob([response.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 (error) {
console.error('파일 다운로드 에러: ', error);
}
};

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>
</>
);
}
31 changes: 31 additions & 0 deletions src/Components/Notice/AttachedBox/style.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import styled from 'styled-components';

export const AttachedWrapper = styled.div`
display: flex;
flex-direction: row;
width: 100%;
height: auto;
margin-top: 32px;
border-top: 2px solid #135c9d;
border-bottom: 1px solid #135c9d;
padding: 16px;
gap: 20px;
`;

export const AttachmentTitle = styled.div`
font-weight: 500;
font-size: 18px;
`;

export const Attachments = styled.div`
display: flex;
flex-direction: column;
gap: 4px;
justify-content: center;
`;

export const Attachment = styled.div`
display: flex;
gap: 7px;
align-items: center;
`;
68 changes: 68 additions & 0 deletions src/Pages/NoticePage/NoticeDetailPage/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { useNoticeDetailData } from '../../../Apis/Notices';
import { useNavigate, useParams } from 'react-router-dom';
import { Header } from '../../../Components/Header';
import { Icon } from '@team-return/design-system';
import { useDeleteNotice } from '../../../Apis/Notices';
import * as _ from './style';
import { AttachedBox } from '../../../Components/Notice/AttachedBox';

export function NoticeDetailPage() {
const { id } = useParams<{ id: any }>();
const { noticeDetail } = useNoticeDetailData(id);
const items = [noticeDetail];

const navigate = useNavigate();
const { mutate: deleteNotice } = useDeleteNotice(id, {
onSuccess: () => {
navigate('/Notice');
},
onError: (error) => {
console.error('notice delete error:', error);
},
});

const handleDeleteClick = () => {
if (window.confirm('공지사항을 삭제하시겠습니까?')) {
deleteNotice();
}
};

return (
<>
<Header />
<_.Wrapper>
<_.Background>
<_.Box>
<_.HeaderWrapper>
<_.Title>{noticeDetail?.title}</_.Title>
<_.IconWrapper>
<_.IconBox>
<Icon
icon="Trash"
color={'gray90'}
size={40}
onClick={handleDeleteClick}
></Icon>
</_.IconBox>
<_.IconBox>
<Icon
icon="EditPencil"
color={'gray90'}
size={26}
></Icon>
</_.IconBox>
</_.IconWrapper>
</_.HeaderWrapper>
<_.Date>
{noticeDetail?.created_at.substring(0, 10)}
</_.Date>
<_.Contents>{noticeDetail?.content}</_.Contents>
{items?.map((item) => (
<AttachedBox props={item?.attachments || []} />
))}
</_.Box>
</_.Background>
</_.Wrapper>
</>
);
}
Loading

0 comments on commit d77e20b

Please sign in to comment.