From 946c505c0a300532d57cf3bb13bc57de4b731bd6 Mon Sep 17 00:00:00 2001 From: Sienna Date: Sun, 11 May 2025 18:01:36 +0900 Subject: [PATCH 01/25] feat: add product detail route --- README.md | 85 +++++++++++++++---- .../Comment/CommentInput/CommentInput.jsx | 57 +++++++++++++ .../CommentInput/CommentInput.module.scss | 6 ++ src/components/Comment/CommentInput/index.js | 1 + .../Comment/CommentList/CommentList.jsx | 59 +++++++++++++ .../CommentList/CommentList.module.scss | 0 src/components/Comment/CommentList/index.js | 1 + src/components/Comment/index.js | 2 + src/constants/messages/product.js | 4 +- src/pages/ProductDetail/ProductDetail.jsx | 66 ++++++++++++++ .../ProductDetail/ProductDetail.module.scss | 0 src/pages/ProductDetail/index.js | 1 + src/pages/index.js | 1 + src/routes/index.jsx | 24 ++++-- 14 files changed, 283 insertions(+), 24 deletions(-) create mode 100644 src/components/Comment/CommentInput/CommentInput.jsx create mode 100644 src/components/Comment/CommentInput/CommentInput.module.scss create mode 100644 src/components/Comment/CommentInput/index.js create mode 100644 src/components/Comment/CommentList/CommentList.jsx create mode 100644 src/components/Comment/CommentList/CommentList.module.scss create mode 100644 src/components/Comment/CommentList/index.js create mode 100644 src/components/Comment/index.js create mode 100644 src/pages/ProductDetail/ProductDetail.jsx create mode 100644 src/pages/ProductDetail/ProductDetail.module.scss create mode 100644 src/pages/ProductDetail/index.js diff --git a/README.md b/README.md index 1ea62873..2dc11e04 100644 --- a/README.md +++ b/README.md @@ -7,14 +7,60 @@ ## 미션 목록 -| 미션 | 날짜 | PR | 주요 내용 | -| ---- | ---------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | -| 1 | 2025-02-24 | [#10](https://github.com/codeit-bootcamp-frontend/15-Sprint-Mission/pull/10) | 랜딩 페이지의 HTML 및 CSS 구현 | -| 2 | 2025-03-05 | [#44](https://github.com/codeit-bootcamp-frontend/15-Sprint-Mission/pull/44) | 회원가입 및 로그인 페이지의 HTML, CSS 구현 | -| 3 | 2025-03-07 | [#60](https://github.com/codeit-bootcamp-frontend/15-Sprint-Mission/pull/60) | 반응형 디자인 구현(desktop-first, 1920px 이상 큰 모니터 기준), breakpoint: 1919px, 1199px, 767px | -| 4 | 2025-03-18 | [#101](https://github.com/codeit-bootcamp-frontend/15-Sprint-Mission/pull/101) | JS기능 추가(DOM 요소 조작 및 이벤트 리스너), 회원가입, 로그인 폼 유효성 검사 | -| 5 | 2025-05-05 | [#](https://github.com/codeit-bootcamp-frontend/15-Sprint-Mission/pull/181) | React, SCSS+CSS modules로 마이그레이션, items 페이지 구현(fetch data, 검색어, 정렬, pagination, 반응형 구현) | -| 6 | 2025-05-11 | [#](https://github.com/codeit-bootcamp-frontend/15-Sprint-Mission/pull/) | 상품 등록 페이지 구현 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
미션날짜PR주요 내용
12025-02-24#10랜딩 페이지의 HTML 및 CSS 구현
22025-03-05#44회원가입 및 로그인 페이지의 HTML, CSS 구현
32025-03-07#60반응형 디자인 구현(desktop-first, 1920px 이상 큰 모니터 기준), breakpoint: 1919px, 1199px, 767px
42025-03-18#101JS기능 추가(DOM 요소 조작 및 이벤트 리스너), 회원가입, 로그인 폼 유효성 검사
52025-05-05#181React, SCSS+CSS modules로 마이그레이션, items 페이지 구현(fetch data, 검색어, 정렬, pagination, 반응형 구현)
62025-05-11#203상품 등록 페이지 구현, 토스트 생성, 에러 처리 로직을 safeFetch 함수로 분리, UI 에러 메시지 상수화
72025-05-11#상품 상세 페이지 구현
--- @@ -85,21 +131,26 @@ ``` ## 에러 처리 전략 + > 모든 에러는 사용자에게 UX 혼란을 최소화하기 위한 피드백(UI/토스트 등)을 포함하여 처리됩니다. ### 1. 라우팅 오류 -- 잘못된 경로 접근 시 → `404 페이지` → 랜딩 페이지로 이동 버튼 + +- 잘못된 경로 접근 시 → `404 페이지` → 랜딩 페이지로 이동 버튼 ### 2. 전역 에러 (App 깨짐) -- 앱 전체 서버 에러 → `500 페이지` → 다시 시도 버튼 + +- 앱 전체 서버 에러 → `500 페이지` → 다시 시도 버튼 ### 3. API 응답 에러 (safeFetch 내부 → 토스트 처리 ) -| 상태 코드 | 처리 방식 | -|-----------|-----------| -| `401` | 인증 필요 안내 토스트 | -| `403` | 접근 권한 없음 안내 토스트 | -| `404` | 없는 리소스 조회 시 토스트 | + +| 상태 코드 | 처리 방식 | +| --------- | -------------------------- | +| `401` | 인증 필요 안내 토스트 | +| `403` | 접근 권한 없음 안내 토스트 | +| `404` | 없는 리소스 조회 시 토스트 | | `500~599` | 서버 응답 오류 토스트 노출 | -### 4. 특정 컴포넌트 렌더 실패 (예: 이미지 리스트 하나가 깨짐) -- 해당 컴포넌트 수준에서 fallback UI 처리 예정 +### 4. 특정 컴포넌트 렌더 실패 (예: 이미지 리스트 하나가 깨짐) + +- 해당 컴포넌트 수준에서 fallback UI 처리 예정 diff --git a/src/components/Comment/CommentInput/CommentInput.jsx b/src/components/Comment/CommentInput/CommentInput.jsx new file mode 100644 index 00000000..066eafda --- /dev/null +++ b/src/components/Comment/CommentInput/CommentInput.jsx @@ -0,0 +1,57 @@ +import { useState } from 'react'; +import { useToast } from '@/components/common'; +import { safeFetch } from '@/utils/api'; +import { baseUrl, ENDPOINTS } from '@/constants/urls'; +import { PRODUCT_ERROR_MESSAGES } from '@/constants/messages'; +import formStyles from '@/styles/helpers/formHelpers.module.scss'; +import buttonStyles from '@/styles/helpers/buttonHelpers.module.scss'; +import styles from './CommentInput.module.scss'; + +const CommentInput = ({ productId, refreshAfterSubmit }) => { + const { showToast } = useToast(); + const [content, setContent] = useState(''); + + const handleSubmit = async () => { + if (!content.trim()) return; + + await safeFetch({ + url: `${baseUrl}${ENDPOINTS.PRODUCTS}/${productId}/comments`, + options: { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ content }), + }, + showToast, + uiErrorMessage: PRODUCT_ERROR_MESSAGES.POST_COMMENT_FAILED, + }); + + setContent(''); + refreshAfterSubmit?.(); // 등록 후 댓글 목록 새로고침 + }; + + return ( +
+ +