Skip to content

Commit 73835b9

Browse files
authored
design, feat, chore : 편지 작성 페이지 추가 퍼블리싱 + 기능구현 + API연결 + 관리자페이지 퍼블리싱 (#28)
* design : 카테고리 버튼 사이즈 full로 변경 * design : 옵션 슬라이드 바텀시트 애니메이션 구현(약간 미완) * refactor:관리자 / 모바일용 레이아웃 분리 * design : 관리자 페이지 퍼블리싱 * design:관리자 페이지 퍼블리싱 * refactor : 폰트 선택 모달 아이콘 svgr 변경 + 목API 형식에 맞춰 타입 수정 + API 연결 작업 90% 완료 * feat:글작성 페이지 쿼리스트링으로 이전편지 가져오기 API연결 * feat:편지 상세 페이지 API 데이터바인딩 90%완료(유저 우편번호 데이터 필요) * feat:편지삭제 api 생성 * feat:글작성, 상세 페이지 뒤로가기 버튼 + 상세페이지 글 삭제 버튼 추가 * refactor : ResultLetter 타입 변경 * feat:글 작성 페이지 네비게이션 가드 테스트 * fix:코드리뷰 수정사항 반영
1 parent 5b79a33 commit 73835b9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+975
-294
lines changed

src/App.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import { Route, Routes } from 'react-router';
22

33
import useViewport from './hooks/useViewport';
44
import Layout from './layouts/Layout';
5+
import MobileLayout from './layouts/MobileLayout';
6+
import AdminPage from './pages/Admin';
7+
import ReportManage from './pages/Admin/Report';
58
import Home from './pages/Home';
69
import Landing from './pages/Landing';
710
import LetterBoardPage from './pages/LetterBoard';
@@ -22,7 +25,7 @@ const App = () => {
2225

2326
return (
2427
<Routes>
25-
<Route>
28+
<Route element={<MobileLayout />}>
2629
<Route index element={<Home />} />
2730
<Route path="login" element={<LoginPage />} />
2831
<Route path="landing" element={<Landing />} />
@@ -49,6 +52,9 @@ const App = () => {
4952
<Route path="notifications" element={<NotificationsPage />} />
5053
</Route>
5154
</Route>
55+
<Route path="admin" element={<AdminPage />}>
56+
<Route path="report" element={<ReportManage />} />
57+
</Route>
5258
</Routes>
5359
);
5460
};

src/apis/letterDetail.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { client } from './client';
2+
3+
const getLetter = async (
4+
letterId: string,
5+
setLetterState: React.Dispatch<React.SetStateAction<LetterDetail | null>>,
6+
) => {
7+
try {
8+
const res = await client.get(`/api/letters/${letterId}`);
9+
setLetterState(res.data.data);
10+
console.log(res);
11+
} catch (error) {
12+
console.error(error);
13+
}
14+
};
15+
16+
const deleteLetter = async (letterId: string) => {
17+
try {
18+
console.log(`/api/letters/${letterId}`);
19+
const res = await client.delete(`/api/letters/${letterId}`);
20+
console.log(res);
21+
} catch (error) {
22+
console.error(error);
23+
}
24+
};
25+
26+
export { getLetter, deleteLetter };

src/apis/write.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { client } from './client';
2+
3+
const postLetter = async (
4+
data: LetterRequest,
5+
setState?: React.Dispatch<React.SetStateAction<boolean>>,
6+
) => {
7+
try {
8+
const res = await client.post('/api/letters', data);
9+
if (setState) setState(true);
10+
console.log(res);
11+
} catch (error) {
12+
console.error(error);
13+
}
14+
};
15+
16+
const getPrevLetter = async (
17+
setPrevLetterState: React.Dispatch<React.SetStateAction<PrevLetter[]>>,
18+
letterId: string,
19+
) => {
20+
try {
21+
const res = await client.get(`/api/letters/${letterId}/previous`);
22+
setPrevLetterState(res.data.data);
23+
console.log(res);
24+
} catch (error) {
25+
console.error(error);
26+
}
27+
};
28+
29+
export { postLetter, getPrevLetter };

src/assets/icons/arrow-down.svg

Lines changed: 3 additions & 0 deletions
Loading

src/assets/icons/check.svg

Lines changed: 17 additions & 0 deletions
Loading

src/assets/icons/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import AlarmIcon from './alarm.svg?react';
2+
import ArrowDownIcon from './arrow-down.svg?react';
23
import ArrowLeftIcon from './arrow-left.svg?react';
34
import BoardIcon from './board.svg?react';
5+
import CheckIcon from './check.svg?react';
46
import CloudIcon from './cloud.svg?react';
57
import DeleteIcon from './delete.svg?react';
68
import EnvelopeIcon from './envelope.svg?react';
79
import GoogleIcon from './google.svg?react';
810
import InformationIcon from './information.svg?react';
911
import KakaoIcon from './kakao.svg?react';
12+
import KebobMenuIcon from './kebob-menu.svg?react';
1013
import LikeFilledIcon from './like-filled.svg?react';
1114
import LikeOutlinedIcon from './like-outlined.svg?react';
1215
import NaverIcon from './naver.svg?react';
@@ -26,9 +29,12 @@ export {
2629
GoogleIcon,
2730
StampIcon,
2831
AlarmIcon,
32+
CheckIcon,
33+
ArrowDownIcon,
2934
PersonIcon,
3035
ArrowLeftIcon,
3136
InformationIcon,
37+
KebobMenuIcon,
3238
EnvelopeIcon,
3339
BoardIcon,
3440
RestartIcon,

src/assets/icons/kebob-menu.svg

Lines changed: 3 additions & 0 deletions
Loading

src/components/BackButton.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { useNavigate } from 'react-router';
2+
3+
import { ArrowLeftIcon } from '@/assets/icons';
4+
5+
export default function BackButton() {
6+
const navigate = useNavigate();
7+
return (
8+
<button onClick={() => navigate(-1)} aria-label="뒤로 가기">
9+
<ArrowLeftIcon className="text-primary-1 h-6 w-6" />
10+
</button>
11+
);
12+
}

src/components/ResultLetter.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import letterPink from '@/assets/images/letter-pink.png';
22

3-
import { STAMPS } from '../pages/Write/constants';
3+
import { CATEGORYS } from '../pages/Write/constants';
44

55
export default function ResultLetter({
6-
stampName = '위로와 공감',
6+
categoryName = 'CONSOLATION',
77
title,
88
}: {
9-
stampName: Stamp;
9+
categoryName: Category;
1010
title: string;
1111
}) {
1212
const address = '1A3E2';
@@ -15,15 +15,15 @@ export default function ResultLetter({
1515

1616
return (
1717
<div
18-
className="flex w-full flex-col gap-[35px] p-4"
18+
className="flex w-full max-w-[300px] flex-col gap-[35px] p-4"
1919
style={{ backgroundImage: `url(${letterPink})` }}
2020
>
2121
<div className="flex justify-between gap-3">
2222
<div className="flex flex-col gap-2.5">
2323
<span className="caption-b text-gray-60">따숨이님께</span>
2424
<span className="caption-r text-gray-80 line-clamp-3 break-all">{title}</span>
2525
</div>
26-
<img src={STAMPS[stampName]} alt="우표" />
26+
<img src={CATEGORYS[categoryName]} alt="우표" />
2727
</div>
2828
<div className="flex flex-col gap-[5px]">
2929
<span className="caption-sb text-gray-60">{today}</span>

src/layouts/MobileLayout.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Outlet } from 'react-router';
2+
3+
const MobileLayout = () => {
4+
return (
5+
<div className="mobile-bg">
6+
<div className="mobile-layout">
7+
<Outlet />
8+
</div>
9+
</div>
10+
);
11+
};
12+
export default MobileLayout;

0 commit comments

Comments
 (0)