Skip to content
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
6 changes: 3 additions & 3 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<!doctype html>
<html lang="en">
<html lang="kr">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/svg+xml" href="/public/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<title>36.5</title>
<link
rel="stylesheet"
as="style"
Expand Down
Binary file added public/favicon.ico
Binary file not shown.
1 change: 0 additions & 1 deletion public/vite.svg

This file was deleted.

1 change: 1 addition & 0 deletions src/apis/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const getNewToken = async () => {
try {
const response = await client.post('/api/reissue', {}, { withCredentials: true });
if (!response) throw new Error('getNewToken: no response data');
console.log(response.data);
return response;
} catch (error) {
console.error(error);
Expand Down
41 changes: 3 additions & 38 deletions src/apis/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,13 @@ const client = axios.create({
headers: { 'Content-Type': 'application/json' },
});

// type FailedRequest = {
// resolve: (token: string) => void;
// reject: (error: unknown) => void;
// };

let isRefreshing = false;
// let failedQueue: FailedRequest[] = [];

// const processQueue = (error: unknown, token: string | null = null) => {
// failedQueue.forEach((prom) => {
// if (error) {
// prom.reject(error);
// } else {
// if (token) {
// prom.resolve(token);
// }
// }
// });

// failedQueue = [];
// };

const callReissue = async () => {
try {
const response = await getNewToken();
const newToken = response?.data.accessToken;
if(response?.status !== 200) throw new Error('error while fetching newToken');
const newToken = response?.data.data.accessToken;
return newToken;
} catch (e) {
return Promise.reject(e);
Expand All @@ -48,6 +29,7 @@ client.interceptors.request.use(
const accessToken = useAuthStore.getState().accessToken;
if (config.url !== '/api/reissue' && accessToken) {
config.headers.Authorization = `Bearer ${accessToken}`;
console.log('interceptor', config);
}
return config;
},
Expand All @@ -72,38 +54,21 @@ client.interceptors.response.use(
retry = true;
if (isRefreshing) {
if (isLoggedIn) logout();
// try {
// return new Promise((resolve, reject) => {
// failedQueue.push({
// resolve: (token: string) => {
// originalRequest.headers.Authorization = `Bearer ${token}`;
// resolve(client(originalRequest));
// },
// reject: (err: unknown) => reject(err),
// });
// });
// } catch (e) {
// return Promise.reject(e);
// }
} else {
isRefreshing = true;
try {
const newToken = await callReissue();
setAccessToken(newToken);
// processQueue(null, newToken);
isRefreshing = false;
originalRequest.headers.Authorization = `Bearer ${newToken}`;
return client(originalRequest);
} catch (e) {
// processQueue(e, null);
isRefreshing = false;
if (isLoggedIn) logout();
return Promise.reject(e);
}
}
}
// if (isLoggedIn) logout();
// console.error('Failed to refresh token', error);
return Promise.reject(error);
},
);
Expand Down
2 changes: 1 addition & 1 deletion src/apis/mailBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const getMailbox = async () => {
export const getMailboxDetail = async (id: number, pageParam: number) => {
try {
const response = await client.get(`/api/mailbox/${id}/detail?page=${pageParam}&size=20`);

console.log(response.data);
if (!response) throw new Error('error while fetching mailbox detail data');
return response.data;
} catch (error) {
Expand Down
6 changes: 3 additions & 3 deletions src/components/ToastItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ export default function ToastItem({ toastObj, index }: { toastObj: ToastObj; ind

const TOAST_DESIGN = {
Warning: { style: 'bg-primary-4', imoji: '⚠️' },
Success: { style: 'bg-[#38d9a9] text-[#FFFFFF]', imoji: '✅' },
Success: { style: 'bg-[#DFFFDA] text-[#000000]', imoji: '✅' },
Error: { style: 'bg-[#FFDCD8] text-[#FF0000]', imoji: '🚨' },
Info: { style: 'bg-[#FFFFFF]', imoji: '📫' },
};

const TOAST_POSITION = {
Top: 'top-20',
Bottom: 'bottom-20',
Bottom: 'bottom-5',
};

const animation = `toast-blink ${toastObj.time}s ease-in-out forwards`;
const toastStyle = twMerge(
'fixed bottom-20 left-1/2 z-40 flex h-[40px] max-w-150 min-w-[335px] w-[85%] -translate-1/2 items-center justify-center rounded-2xl caption-sb',
'fixed bottom-5 left-1/2 z-40 flex h-[40px] max-w-150 min-w-[300px] w-[100%] -translate-1/2 items-center justify-center rounded-lg caption-sb shadow-[0_1px_6px_rgba(200,200,200,0.2)]',
TOAST_POSITION[toastObj.position],
TOAST_DESIGN[toastObj.toastType].style,
);
Expand Down
6 changes: 6 additions & 0 deletions src/pages/Auth/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import useAuthStore from '@/stores/authStore';
const AuthCallbackPage = () => {
const stateToken = new URLSearchParams(window.location.search).get('state');
const redirectURL = new URLSearchParams(window.location.search).get('redirect');
const error = new URLSearchParams(window.location.search).get('error');

const login = useAuthStore((state) => state.login);
const logout = useAuthStore((state) => state.logout);
Expand All @@ -32,6 +33,8 @@ const AuthCallbackPage = () => {
login();
if (userInfo.accessToken) setAccessToken(userInfo.accessToken);

console.log(redirectURL);

switch (redirectURL) {
case 'home':
{
Expand Down Expand Up @@ -67,6 +70,9 @@ const AuthCallbackPage = () => {
useEffect(() => {
if (!stateToken) {
navigate('/notFound');
if (error === 'deleted_member') {
alert('탈퇴한 회원입니다.');
}
return;
}

Expand Down
50 changes: 30 additions & 20 deletions src/pages/LetterBoard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@ const LetterBoardPage = () => {
const fetchPostList = async (page: number = 1) => {
try {
const response = await getSharePostList(page);
if (!response) throw new Error('게시글 목록을 불러오는데 실패했습니다.');
if (!response || !response.content) {
console.error('게시글 목록을 불러오는데 실패했습니다.');
return { content: [], currentPage: page, totalPages: 1 };
}
console.log('page', response);
return response as SharePostResponse;
} catch (e) {
console.error(e);
return { content: [], currentPage: page, totalPages: 1 };
}
};

Expand All @@ -32,7 +36,7 @@ const LetterBoardPage = () => {
enabled: true,
initialPageParam: 1,
getNextPageParam: (res) => {
if (!res || res.currentPage >= res.totalPages) {
if (!res || !res?.content || res?.currentPage >= res?.totalPages) {
return undefined;
}
return res.currentPage + 1;
Expand All @@ -41,7 +45,7 @@ const LetterBoardPage = () => {
gcTime: 1000 * 60 * 10,
});

const postLists = data?.pages.flatMap((page) => page?.content) || [];
const postLists = data?.pages?.flatMap((page) => page?.content || []) || [];

useEffect(() => {
if (!hasNextPage) return;
Expand All @@ -65,24 +69,30 @@ const LetterBoardPage = () => {
</p>
</>
{isLoading ? (
<p>loading</p>
) : postLists && postLists?.length > 0 ? (
<section className="mt-6 grid grid-cols-2 gap-x-5 gap-y-4">
{postLists?.map((item, index) => {
return (
<LetterPreview
key={index}
id={item?.sharePostId || 0}
to={item?.receiverZipCode || 'ERROR'}
from={item?.writerZipCode || 'ERROR'}
content={item?.content || 'no Data'}
ref={index === postLists.length - 1 ? ref : null}
/>
);
})}
</section>
<p className="body-m text-gray-60 mt-10 text-center">로딩 중 입니다.</p>
) : postLists ? (
postLists?.length > 0 ? (
<section className="mt-6 grid grid-cols-2 gap-x-5 gap-y-4">
{postLists?.map((item, index) => {
return (
<LetterPreview
key={index}
id={item?.sharePostId || 0}
to={item?.receiverZipCode || 'ERROR'}
from={item?.writerZipCode || 'ERROR'}
content={item?.content || 'no Data'}
ref={index === postLists.length - 1 ? ref : null}
/>
);
})}
</section>
) : (
<p className="body-m text-gray-60 mt-10 text-center">게시글이 없습니다.</p>
)
) : (
<p className="body-m text-gray-60 mt-10 text-center">게시글이 없습니다.</p>
<p className="body-m text-gray-60 mt-10 text-center">
오류가 발생했습니다. 다시 한 번 시도해주세요
</p>
)}
</main>
<BackgroundBottom />
Expand Down
2 changes: 1 addition & 1 deletion src/pages/LetterBox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const LetterBoxPage = () => {
isLoading,
isError,
} = useQuery({
queryKey: ['mailbox'],
queryKey: ['mailBox'],
queryFn: fetchMailLists,
staleTime: 1000 * 60 * 5,
gcTime: 1000 * 60 * 10,
Expand Down
30 changes: 25 additions & 5 deletions src/pages/LetterBoxDetail/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useMutation, useInfiniteQuery } from '@tanstack/react-query';
import { useMutation, useInfiniteQuery, useQueryClient } from '@tanstack/react-query';
import { ChangeEvent, useEffect, useState } from 'react';
import { useInView } from 'react-intersection-observer';
import { useLocation, useNavigate } from 'react-router';
Expand All @@ -11,6 +11,9 @@ import PageTitle from '@/components/PageTitle';

import InformationTooltip from './components/InformationTooltip';
import LetterPreview from './components/LetterPreview';

import useToastStore from '@/stores/toastStore';

interface MailBoxDetailProps {
letterId: number;
title: string;
Expand All @@ -28,6 +31,8 @@ const LetterBoxDetailPage = () => {
const [isOpenShareModal, setIsOpenShareModal] = useState(false);
const [selected, setSelected] = useState<number[]>([]);
const [shareComment, setShareComment] = useState('');
const queryClient = useQueryClient();
const setToastActive = useToastStore((state) => state.setToastActive);

const navigate = useNavigate();

Expand Down Expand Up @@ -63,10 +68,19 @@ const LetterBoxDetailPage = () => {
mutationFn: async () => await postMailboxDisconnect(userInfo.id),
onSuccess: () => {
navigate(-1);
setToastActive({
toastType: 'Success',
title: '차단 완료 되었습니다.',
time: 5,
});
queryClient.invalidateQueries({ queryKey: ['mailBox'] });
},
onError: (error) => {
// TODO: 차단 실패 toastUI 띄워주기
// 요청이 실패했어요 잠시 후에 다시 시도해주세요.
setToastActive({
toastType: 'Error',
title: '차단이 실패했습니다. 잠시 후에 다시 시도해주세요.',
time: 5,
});
console.error(error);
},
});
Expand All @@ -76,10 +90,16 @@ const LetterBoxDetailPage = () => {
onSuccess: () => {
toggleShareMode();
setShareComment('');
setToastActive({
toastType: 'Success',
title: '공유 완료 되었습니다.',
});
},
onError: (error) => {
// TODO: 차단 실패 toastUI 띄워주기
// 요청이 실패했어요 잠시 후에 다시 시도해주세요.
setToastActive({
toastType: 'Error',
title: '공유가 실패했습니다. 잠시 후에 다시 시도해주세요.',
});
console.error(error);
},
});
Expand Down
18 changes: 11 additions & 7 deletions src/pages/LetterDetail/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,30 @@ import useAuthStore from '@/stores/authStore';
import LetterDetailContent from './components/LetterDetailContent';
import LetterDetailHeader from './components/LetterDetailHeader';
import LetterDetailReplyButton from './components/LetterDetailReplyButton';
import { useMutation, useQueryClient } from '@tanstack/react-query';

const LetterDetailPage = () => {
const params = useParams();
const navigate = useNavigate();
const queryClient = useQueryClient();

const [letterDetail, setLetterDetail] = useState<LetterDetail>({} as LetterDetail);
const userZipCode = useAuthStore((state) => state.zipCode);

const [reportModalOpen, setReportModalOpen] = useState<boolean>(false);
const [deleteModalOpen, setDeleteModalOpen] = useState<boolean>(false);

const handleDeleteLetter = async (letterId: string) => {
const res = await deleteLetter(letterId);
if (res?.status === 200) {
const { mutate: handleDeleteLetter } = useMutation({
mutationFn: (letterId: string) => deleteLetter(letterId),
onSuccess: () => {
navigate(-1);
} else {
queryClient.invalidateQueries({ queryKey: ['mailBoxDetail'] });
queryClient.invalidateQueries({ queryKey: ['mailBox'] });
},
onError: () => {
alert('편지 삭제 도중 오류 발생(임시)');
}
};
},
});

useEffect(() => {
const handleGetLetter = async (letterId: string) => {
Expand Down Expand Up @@ -86,7 +91,6 @@ const LetterDetailPage = () => {
}}
onConfirm={() => {
if (params.id) handleDeleteLetter(params.id);
navigate(-1);
}}
/>
)}
Expand Down
7 changes: 5 additions & 2 deletions src/pages/MyPage/components/MyBoardPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ const MyBoardPage = () => {
const fetchMyPostList = async () => {
try {
const response = await getMySharePostList();
if (!response) throw new Error('게시글 목록을 불러오는데 실패했습니다.');
if (!response) {
throw new Error('게시글 목록을 불러오는데 실패했습니다.');
}
console.log('myPostList', response);
return response.data as SharePost[];
} catch (e) {
console.error(e);
return [];
}
};

Expand All @@ -42,7 +45,7 @@ const MyBoardPage = () => {
<main className={twMerge('z-1 flex grow flex-col px-5 pt-20 pb-10')}>
<PageTitle className="mx-auto mb-11">내가 올린 게시물</PageTitle>
{isLoading ? (
<p>loading</p>
<p className="body-m text-gray-60 text-center">로딩 중 입니다.</p>
) : postLists && postLists?.length > 0 ? (
<section className="mt-6 grid grid-cols-2 gap-x-5 gap-y-4">
{postLists?.map((item, index) => (
Expand Down
Loading