diff --git a/index.html b/index.html index ff314cf..3c08226 100644 --- a/index.html +++ b/index.html @@ -1,10 +1,10 @@ - + - + - Vite + React + TS + 36.5 \ No newline at end of file diff --git a/src/apis/auth.ts b/src/apis/auth.ts index 064fa5d..c963f64 100644 --- a/src/apis/auth.ts +++ b/src/apis/auth.ts @@ -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); diff --git a/src/apis/client.ts b/src/apis/client.ts index 2564af2..426b7c4 100644 --- a/src/apis/client.ts +++ b/src/apis/client.ts @@ -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); @@ -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; }, @@ -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); }, ); diff --git a/src/apis/mailBox.ts b/src/apis/mailBox.ts index 722e248..e0b9aca 100644 --- a/src/apis/mailBox.ts +++ b/src/apis/mailBox.ts @@ -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) { diff --git a/src/components/ToastItem.tsx b/src/components/ToastItem.tsx index d4b917e..2465e5b 100644 --- a/src/components/ToastItem.tsx +++ b/src/components/ToastItem.tsx @@ -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, ); diff --git a/src/pages/Auth/index.tsx b/src/pages/Auth/index.tsx index 0596a77..cd892d5 100644 --- a/src/pages/Auth/index.tsx +++ b/src/pages/Auth/index.tsx @@ -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); @@ -32,6 +33,8 @@ const AuthCallbackPage = () => { login(); if (userInfo.accessToken) setAccessToken(userInfo.accessToken); + console.log(redirectURL); + switch (redirectURL) { case 'home': { @@ -67,6 +70,9 @@ const AuthCallbackPage = () => { useEffect(() => { if (!stateToken) { navigate('/notFound'); + if (error === 'deleted_member') { + alert('νƒˆν‡΄ν•œ νšŒμ›μž…λ‹ˆλ‹€.'); + } return; } diff --git a/src/pages/LetterBoard/index.tsx b/src/pages/LetterBoard/index.tsx index a3e26ab..b6d4511 100644 --- a/src/pages/LetterBoard/index.tsx +++ b/src/pages/LetterBoard/index.tsx @@ -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 }; } }; @@ -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; @@ -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; @@ -65,24 +69,30 @@ const LetterBoardPage = () => {

{isLoading ? ( -

loading

- ) : postLists && postLists?.length > 0 ? ( -
- {postLists?.map((item, index) => { - return ( - - ); - })} -
+

λ‘œλ”© 쀑 μž…λ‹ˆλ‹€.

+ ) : postLists ? ( + postLists?.length > 0 ? ( +
+ {postLists?.map((item, index) => { + return ( + + ); + })} +
+ ) : ( +

κ²Œμ‹œκΈ€μ΄ μ—†μŠ΅λ‹ˆλ‹€.

+ ) ) : ( -

κ²Œμ‹œκΈ€μ΄ μ—†μŠ΅λ‹ˆλ‹€.

+

+ 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. λ‹€μ‹œ ν•œ 번 μ‹œλ„ν•΄μ£Όμ„Έμš” +

)} diff --git a/src/pages/LetterBox/index.tsx b/src/pages/LetterBox/index.tsx index c8010c9..5f173f1 100644 --- a/src/pages/LetterBox/index.tsx +++ b/src/pages/LetterBox/index.tsx @@ -32,7 +32,7 @@ const LetterBoxPage = () => { isLoading, isError, } = useQuery({ - queryKey: ['mailbox'], + queryKey: ['mailBox'], queryFn: fetchMailLists, staleTime: 1000 * 60 * 5, gcTime: 1000 * 60 * 10, diff --git a/src/pages/LetterBoxDetail/index.tsx b/src/pages/LetterBoxDetail/index.tsx index 262cc03..ee02012 100644 --- a/src/pages/LetterBoxDetail/index.tsx +++ b/src/pages/LetterBoxDetail/index.tsx @@ -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'; @@ -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; @@ -28,6 +31,8 @@ const LetterBoxDetailPage = () => { const [isOpenShareModal, setIsOpenShareModal] = useState(false); const [selected, setSelected] = useState([]); const [shareComment, setShareComment] = useState(''); + const queryClient = useQueryClient(); + const setToastActive = useToastStore((state) => state.setToastActive); const navigate = useNavigate(); @@ -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); }, }); @@ -76,10 +90,16 @@ const LetterBoxDetailPage = () => { onSuccess: () => { toggleShareMode(); setShareComment(''); + setToastActive({ + toastType: 'Success', + title: '곡유 μ™„λ£Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.', + }); }, onError: (error) => { - // TODO: 차단 μ‹€νŒ¨ toastUI λ„μ›Œμ£ΌκΈ° - // μš”μ²­μ΄ μ‹€νŒ¨ν–ˆμ–΄μš” μž μ‹œ 후에 λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”. + setToastActive({ + toastType: 'Error', + title: 'κ³΅μœ κ°€ μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€. μž μ‹œ 후에 λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”.', + }); console.error(error); }, }); diff --git a/src/pages/LetterDetail/index.tsx b/src/pages/LetterDetail/index.tsx index 86cf44f..2a34606 100644 --- a/src/pages/LetterDetail/index.tsx +++ b/src/pages/LetterDetail/index.tsx @@ -11,10 +11,12 @@ 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({} as LetterDetail); const userZipCode = useAuthStore((state) => state.zipCode); @@ -22,14 +24,17 @@ const LetterDetailPage = () => { const [reportModalOpen, setReportModalOpen] = useState(false); const [deleteModalOpen, setDeleteModalOpen] = useState(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) => { @@ -86,7 +91,6 @@ const LetterDetailPage = () => { }} onConfirm={() => { if (params.id) handleDeleteLetter(params.id); - navigate(-1); }} /> )} diff --git a/src/pages/MyPage/components/MyBoardPage.tsx b/src/pages/MyPage/components/MyBoardPage.tsx index d55cc9b..a4c3759 100644 --- a/src/pages/MyPage/components/MyBoardPage.tsx +++ b/src/pages/MyPage/components/MyBoardPage.tsx @@ -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 []; } }; @@ -42,7 +45,7 @@ const MyBoardPage = () => {
λ‚΄κ°€ 올린 κ²Œμ‹œλ¬Ό {isLoading ? ( -

loading

+

λ‘œλ”© 쀑 μž…λ‹ˆλ‹€.

) : postLists && postLists?.length > 0 ? (
{postLists?.map((item, index) => ( diff --git a/src/pages/MyPage/index.tsx b/src/pages/MyPage/index.tsx index 2ed0b5c..226eb36 100644 --- a/src/pages/MyPage/index.tsx +++ b/src/pages/MyPage/index.tsx @@ -7,6 +7,7 @@ import useAuthStore from '@/stores/authStore'; import useMyPageStore from '@/stores/myPageStore'; import { TEMPERATURE_RANGE } from './constants'; +import useToastStore from '@/stores/toastStore'; const MyPage = () => { useEffect(() => { @@ -16,6 +17,7 @@ const MyPage = () => { const { data, fetchMyPageInfo } = useMyPageStore(); const [isOpenModal, setIsOpenModal] = useState(false); const logout = useAuthStore((state) => state.logout); + const setToastActive = useToastStore((state) => state.setToastActive); const getDescriptionByTemperature = (temp: number) => { const range = TEMPERATURE_RANGE.find((range) => temp >= range.min && temp < range.max); @@ -28,9 +30,14 @@ const MyPage = () => { try { const response = await deleteUserInfo(); if (!response) throw new Error('deletioning failed'); - console.log(response); + return response; } catch (error) { console.error(error); + setToastActive({ + toastType: 'Error', + title: 'μ„œλ²„μ˜€λ₯˜λ‘œ νƒˆν‡΄μ²˜λ¦¬κ°€ λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. μž μ‹œ 후에 λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”.', + time: 5, + }); } }; @@ -43,9 +50,13 @@ const MyPage = () => { cancelText="λ˜λŒμ•„κ°€κΈ°" confirmText="νƒˆν‡΄ν•˜κΈ°" onCancel={() => setIsOpenModal(false)} - onConfirm={() => { - handleLeave(); + onConfirm={async () => { + const response = await handleLeave(); setIsOpenModal(false); + if (response?.status === 200) { + logout(); + alert('νƒˆν‡΄κ°€ μ™„λ£Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.'); + } }} /> )} diff --git a/src/pages/Onboarding/WelcomeLetter.tsx b/src/pages/Onboarding/WelcomeLetter.tsx index 50b7e4e..49a1716 100644 --- a/src/pages/Onboarding/WelcomeLetter.tsx +++ b/src/pages/Onboarding/WelcomeLetter.tsx @@ -5,7 +5,7 @@ export default function index() { const navigate = useNavigate(); return (
-
+

To.λ”°μˆ¨μ΄

ν™˜μ˜ν•©λ‹ˆλ‹€! 우리 ν•¨κ»˜ λ§ˆμŒμ„ λ‚˜λˆ„μ–΄ λ³΄μ•„μš”

@@ -22,7 +22,7 @@ export default function index() {

3. κ³ λ―Ό νŽΈμ§€μ— λŒ€ν•œ λ‹΅μž₯은 κ²€μˆ˜ 후에 μ „λ‹¬λ©λ‹ˆλ‹€.

-

From.9ν™©μž‘λ¬Ό

+

From.9ν™©μž‘λ¬Ό