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
8 changes: 2 additions & 6 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,9 @@
],
"eslint.workingDirectories": [
{
"mode": "auto",
"mode": "auto"
}
],
"cSpell.words": [
"kakao",
"signup",
"webp"
],
"cSpell.words": ["kakao", "signup", "webp"],
"editor.tabSize": 2
}
22 changes: 12 additions & 10 deletions apps/client/src/apis/axios.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,34 @@
import axios, { AxiosError } from 'axios';
import axios, { AxiosError } from "axios";

const axiosInstance = axios.create({
baseURL: process.env.SERVER_URL,
withCredentials: true,
});

axiosInstance.interceptors.response.use(
response => {
(response) => {
return response;
},
async error => {
async (error) => {
const customError = error as AxiosError;
const axiosError = customError.response?.status as number;


// 401 에러 응답 (인가 미들웨어에서 모든 토큰이 만료되었을때 401 리턴 -> 로그인 유도)
if ((axiosError === 401) && (window.location.pathname !== '/')) {
if (/^\/cake\/[^/]+$/.test(window.location.pathname)) {
if (axiosError === 401 && window.location.pathname !== "/") {
if (
/^\/cake\/[^/]+$/.test(window.location.pathname) ||
/^\/letter\/choose\/[^/]+$/.test(window.location.pathname) ||
/^\/letter\/create\/[^/]+$/.test(window.location.pathname)
) {
return Promise.reject(error);
}
window.location.replace('/');
window.location.replace("/");
return Promise.reject(error);
}

// 500 에러 응답
if (axiosError === 500) {
console.log('서버 오류');
console.log("서버 오류");
return Promise.reject(error);
}

Expand All @@ -35,8 +38,7 @@ axiosInstance.interceptors.response.use(
}

return Promise.reject(error);
},
}
);


export default axiosInstance;
16 changes: 11 additions & 5 deletions apps/client/src/components/cake/CakeInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import { useQueryClient } from '@tanstack/react-query';
import { useGetCakeLetters } from '#apis/cake/useGetCakeLetters.tsx';
import { useGetLetter } from '#apis/letter/useGetLetter.tsx';


interface CakeInfoProps {
year: string;
sheetColor: CakeColorType | null;
Expand Down Expand Up @@ -55,7 +54,11 @@ const CakeInfo: React.FC<CakeInfoProps> = ({
totalPage: 1,
});
const queryClient = useQueryClient();
const { data: cakeLettersData } = useGetCakeLetters(ownerId!, year, pageData.currentPage);
const { data: cakeLettersData } = useGetCakeLetters(
ownerId!,
year,
pageData.currentPage
);
const { data: letterData } = useGetLetter(selectedLetterId!);

useEffect(() => {
Expand All @@ -68,7 +71,8 @@ const CakeInfo: React.FC<CakeInfoProps> = ({
setCakeData(result.data);
setPageData({
currentPage: result.currentPage,
totalPage: result.totalPage === 0 ? result.totalPage + 1 : result.totalPage,
totalPage:
result.totalPage === 0 ? result.totalPage + 1 : result.totalPage,
});
}
}, [cakeLettersData]);
Expand Down Expand Up @@ -128,8 +132,10 @@ const CakeInfo: React.FC<CakeInfoProps> = ({
keyword={selectedItem?.keyword ?? ''}
/>
)}
<Modal open={open}>
<span>편지 내용은 생일 이후에 확인할 수 있어요!{'\n'}두근두근...👉👈</span>
<Modal open={open} onClose={() => setOpen(false)}>
<span id="modal-description">
편지 내용은 생일 이후에 확인할 수 있어요!{'\n'}두근두근...👉👈
</span>
<Button
type="default"
onClick={() => {
Expand Down
38 changes: 26 additions & 12 deletions apps/client/src/components/cake/GridInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import React, { useState, CSSProperties, useRef, useEffect, useCallback } from 'react';
import React, {
useState,
CSSProperties,
useRef,
useEffect,
useCallback,
} from 'react';
import { useParams } from 'react-router-dom';
import * as G from '#styles/GridStyle.tsx';
import { FixedSizeGrid as Grid } from 'react-window';
Expand All @@ -21,8 +27,10 @@ import Modal from '#components/modal/Modal.tsx';

const GRID_PAGE = 24;


const GridInfo: React.FC<{ year: string, handleTotalChange?: (total: number) => void }> = ({ year: init, handleTotalChange }) => {
const GridInfo: React.FC<{
year: string;
handleTotalChange?: (total: number) => void;
}> = ({ year: init, handleTotalChange }) => {
const [year, setYear] = useState(init);
const [cakeData, setCakeData] = useState<getCakeDataRes[]>([]);
const [page, setPage] = useState(1);
Expand All @@ -39,13 +47,15 @@ const GridInfo: React.FC<{ year: string, handleTotalChange?: (total: number) =>
const COL_WIDTH = isPC ? 155 : 130;
const WIDTH = isPC ? 155 * 5 : 390;

const { data, isFetching } = year === 'all'
? useGetMyLetters(page)
: useGetLetters(ownerId!, year, page);
const { data, isFetching } =
year === 'all'
? useGetMyLetters(page)
: useGetLetters(ownerId!, year, page);

const { data: letterData } = year === 'all'
? useGetAllLetter(selectedLetterId!)
: useGetLetter(selectedLetterId!);
const { data: letterData } =
year === 'all'
? useGetAllLetter(selectedLetterId!)
: useGetLetter(selectedLetterId!);

useEffect(() => {
if (data) {
Expand All @@ -59,7 +69,9 @@ const GridInfo: React.FC<{ year: string, handleTotalChange?: (total: number) =>
const result = getCakeLettersRes.parse(data);
setNoData(false);
setHasMore(result.data.length >= GRID_PAGE);
setCakeData((prev) => (page === 1 ? result.data : [...prev, ...result.data]));
setCakeData((prev) =>
page === 1 ? result.data : [...prev, ...result.data]
);
handleTotalChange?.(result.totalPage);
}
}
Expand Down Expand Up @@ -202,8 +214,10 @@ const GridInfo: React.FC<{ year: string, handleTotalChange?: (total: number) =>
candleImageUrl={selectedItem?.candleImageUrl ?? ''}
keyword={selectedItem?.keyword ?? ''}
/>
<Modal open={open}>
<span>편지 내용은 생일 이후에 확인할 수 있어요!</span>
<Modal open={open} onClose={() => setOpen(false)}>
<span id="modal-description">
편지 내용은 생일 이후에 확인할 수 있어요!
</span>
<Button
type="default"
onClick={() => {
Expand Down
18 changes: 7 additions & 11 deletions apps/client/src/components/cake/SharedCake.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import * as C from '#styles/CakeStyle.tsx'
import * as C from '#styles/CakeStyle.tsx';

import CakeHeader from '#components/cake/CakeHeader.tsx';
import CakeInfo from '#components/cake/CakeInfo.tsx';
Expand Down Expand Up @@ -71,21 +71,17 @@ const SharedCake: React.FC<MyCakeProps> = ({ ownerId, data }) => {
isMyCake={false}
/>
<C.Buttons>
<Button
type="default"
onClick={handleCheckLogin}
>
<Button type="default" onClick={handleCheckLogin}>
케이크 꾸며주기
</Button>
<Button
type="default"
onClick={handleNavigateToMyCake}
>
<Button type="default" onClick={handleNavigateToMyCake}>
내 케이크 보러가기
</Button>
</C.Buttons>
<Modal open={open}>
<span>편지를 작성하면 포인트를 얻을 수 있어요.{'\n'}로그인 하시겠어요?</span>
<Modal open={open} onClose={() => setOpen(false)}>
<span id="modal-description">
편지를 작성하면 포인트를 얻을 수 있어요.{'\n'}로그인 하시겠어요?
</span>
<Button
type="default"
onClick={() => {
Expand Down
4 changes: 2 additions & 2 deletions apps/client/src/components/modal/LoginModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ const LoginModal = ({
const navigate = useNavigate();

return (
<Modal open={open}>
<span>로그인이 필요합니다.</span>
<Modal open={open} onClose={handleOpen}>
<span id="modal-title">로그인이 필요합니다.</span>
<Button
type="default"
onClick={() => {
Expand Down
32 changes: 30 additions & 2 deletions apps/client/src/components/modal/Modal.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,46 @@
import React from 'react';
import React, { useEffect, useRef } from 'react';
import styled from 'styled-components';
import { ModalPortal } from '../../ModalPortal';

const Modal = ({
open,
onClose,
children,
}: {
open: boolean;
onClose: () => void;
children: React.ReactNode;
}) => {
const modalRef = useRef<HTMLDivElement>(null);

useEffect(() => {
const handleKey = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
onClose();
}
};

if (open) {
document.addEventListener('keydown', handleKey);
}

return () => {
document.removeEventListener('keydown', handleKey);
};
}, [open, onClose]);

return (
<ModalPortal>
<Overlay open={open}>
<ModalContainer>{children}</ModalContainer>
<ModalContainer
ref={modalRef}
role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
aria-describedby="modal-description"
>
{children}
</ModalContainer>
</Overlay>
</ModalPortal>
);
Expand Down
12 changes: 6 additions & 6 deletions apps/client/src/components/modal/ShareUrlModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function kakaoShare(nickname: string) {

function facebookShare(nickname: string) {
window.open(
`https://www.facebook.com/sharer/sharer.php?u=${window.location.href}&title=${nickname}님의 케이크`,
`https://www.facebook.com/sharer/sharer.php?u=${window.location.href}&title=${nickname}님의 케이크`
);
}

Expand All @@ -50,10 +50,10 @@ const ShareUrlModal = ({
}, []);

return (
<Modal open={open}>
<Modal open={open} onClose={handleOpen}>
<ShareBox>
<h3>내 케이크 공유하기</h3>
<div>
<h3 id="modal-title">내 케이크 공유하기</h3>
<div id="modal-description">
<IconButton onClick={() => kakaoShare(nickname)}>
<KakaoLogoIcon width={'3rem'} height={'3rem'} />
</IconButton>
Expand All @@ -64,7 +64,7 @@ const ShareUrlModal = ({
<LinkIcon width={'3rem'} height={'3rem'} />
</IconButton>
</div>
<Button type="default" onClick={handleOpen} >
<Button type="default" onClick={handleOpen}>
닫기
</Button>
</ShareBox>
Expand All @@ -87,4 +87,4 @@ const ShareBox = styled.div`
justify-content: center;
align-items: center;
gap: 24px;
`
`;
26 changes: 12 additions & 14 deletions apps/client/src/pages/ChooseCandle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const ChooseCandle = () => {
try {
// 선택한 장식초 정보 가져오기
const candleResponse = await axiosInstance.get<CandleType>(
`/candle/${candleId}`,
`/candle/${candleId}`
);
if (candleResponse.status === 200) {
const data = CandleType.parse(candleResponse.data);
Expand Down Expand Up @@ -118,7 +118,7 @@ const ChooseCandle = () => {
if (candle.point === 0) {
// 무료 장식초: 편지 페이지로 이동
navigate(
`/letter/create/${ownerId}?candleId=${candle.candleId}`,
`/letter/create/${ownerId}?candleId=${candle.candleId}`
);
} else {
// 유료 장식초: 결제 혹은 로그인 유도 모달 띄우기
Expand All @@ -135,15 +135,15 @@ const ChooseCandle = () => {
</CandleButton>
))}
</CandleContainer>
<Modal open={openBuy}>
<Modal open={openBuy} onClose={handleOpenBuy}>
<img
style={{ width: '5rem', height: '5rem' }}
src={candle?.imageUrl}
alt={candle?.candleId.toString()}
/>
<h3>해당 장식초를 구매하시겠습니까?</h3>
<h3 id="modal-title">해당 장식초를 구매하시겠습니까?</h3>
<span>남은 포인트: {userPoint}P</span>
<span>결제 포인트: {candle?.point}P</span>
<span id="modal-description">결제 포인트: {candle?.point}P</span>
{!isEnoughPoint && (
<span style={{ color: 'red' }}>포인트가 부족합니다.</span>
)}
Expand All @@ -155,11 +155,7 @@ const ChooseCandle = () => {
gap: '1rem',
}}
>
<Button
type="gray"
size="large"
onClick={handleOpenBuy}
>
<Button type="gray" size="large" onClick={handleOpenBuy}>
취소
</Button>
<Button
Expand All @@ -174,18 +170,20 @@ const ChooseCandle = () => {
</Button>
</div>
</Modal>
<Modal open={openSuccess}>
<Modal open={openSuccess} onClose={() => setOpenSuccess(false)}>
<img
style={{ width: '5rem', height: '5rem' }}
src={candle?.imageUrl}
alt={candle?.candleId.toString()}
/>
<h3>장식초 구매가 완료되었습니다.</h3>
<span>남은 포인트: {userPoint}P</span>
<h3 id="modal-title">장식초 구매가 완료되었습니다.</h3>
<span id="modal-description">남은 포인트: {userPoint}P</span>
<Button
type="default"
onClick={() => {
navigate(`/letter/create/${ownerId}?candleId=${candle?.candleId}`);
navigate(
`/letter/create/${ownerId}?candleId=${candle?.candleId}`
);
}}
>
확인
Expand Down
Loading