[백은결] sprint5#75
Hidden character warning
Conversation
…, and fake navigation
| @@ -0,0 +1,52 @@ | |||
| const BASE_URL = 'https://panda-market-api.vercel.app'; | |||
There was a problem hiding this comment.
BASE_URL을 환경변수로 분리하면 배포 환경에 따라 API 서버 주소를 쉽게 변경할 수 있습니다.
const BASE_URL = import.meta.env.VITE_API_URL || 'https://panda-market-api.vercel.app';| const { productName, productDescription, productPrice } = form; | ||
|
|
||
| const errors = {}; | ||
| let isNotError = true; |
There was a problem hiding this comment.
isNotError는 이중 부정(not + error)으로 가독성이 떨어집니다. isValid로 변경하면 더 직관적입니다.
return { errors, isValid: Object.keys(errors).length === 0 };| const errors = {}; | ||
| let isNotError = true; | ||
|
|
||
| if (productName && productName.length > 10) { |
There was a problem hiding this comment.
상품명 유효성 검사에서 1자 이상 조건이 누락되어 있습니다. (요구사항: 1자 이상, 10자 이내)
| @@ -0,0 +1,39 @@ | |||
| import clsx from 'clsx'; | |||
There was a problem hiding this comment.
파일명에 오타가 있습니다: OrderByButtton.jsx → OrderByButton.jsx (t가 3개)
파일명, CSS 모듈명, index.js export도 함께 수정해주세요.
| export function OrderByButtton() { | ||
| const [isOpen, setIsOpen] = useState(false); | ||
|
|
||
| const handleSelect = () => setIsOpen(false); |
There was a problem hiding this comment.
handleSelect 함수가 인자를 받지만 사용하지 않고 있습니다. 정렬 기능이 미구현 상태입니다.
| <div className={styles.imgWrapper}> | ||
| <img src={defaultProductImg} alt={title} className={styles.productImg} /> | ||
| </div> | ||
|
|
There was a problem hiding this comment.
상품 클릭 시 상세 페이지로 이동해야 하지만 href가 비어있습니다. id prop을 받아서 /items/${id}로 이동하도록 수정해주세요.
| const { currentPage, totalPages, setTotalItems, goToPage, next, prev } = | ||
| usePagination(); | ||
|
|
||
| useEffect(() => { |
There was a problem hiding this comment.
API 호출 실패 시 에러 처리가 없습니다. try-catch로 감싸고 에러 상태를 관리해주세요.
try {
const result = await getProductList({ ... });
setProducts(result.list);
} catch (error) {
console.error('상품 목록 조회 실패:', error);
}| return; | ||
| } | ||
|
|
||
| setTags((prev) => [...prev, value]); // 배열에 태그 추가 |
There was a problem hiding this comment.
동일한 태그가 중복으로 추가될 수 있습니다. 중복 체크 로직을 추가해주세요.
if (tags.includes(value)) {
setForm((prev) => ({ ...prev, productTag: '' }));
return;
}| const navigate = useNavigate(); | ||
|
|
||
| const handleSubmit = async () => { | ||
| try { |
There was a problem hiding this comment.
주석 처리된 코드가 남아있습니다. TODO 주석으로 명확히 표시해주세요.
// TODO: 로그인 기능 구현 후 실제 API 연동 필요
const fakeProductId = 1234;| return !isTextarea ? ( | ||
| <div className={clsx(styles.container, error && styles.error)}> | ||
| <label htmlFor={id}>{label}</label> | ||
| <input |
There was a problem hiding this comment.
input과 textarea의 wrapper 코드가 중복됩니다. 동적 컴포넌트로 리팩토링하면 코드가 간결해집니다.
const InputComponent = isTextarea ? 'textarea' : 'input';
요구사항
기본
공통
프론트엔드 구현 요구사항
랜딩 페이지
중고마켓 페이지
상품 등록 페이지
심화
프론트엔드 구현 요구사항
상품 등록 페이지
🔧 주요 변경사항
기존 HTML/CSS 랜딩 페이지를 React 컴포넌트로 마이그레이션 (HomePage)
/items 페이지 구현 (ItemPage) – 판매 중인 상품 목록, 검색, 페이지네이션 포함
/registration 상품 등록 페이지 구현 (RegistrationPage) – 입력 폼, 태그 입력, 등록 버튼 UI 포함
CSS 모듈 기반 스타일 적용 및 반응형 레이아웃 구성
상품 등록 폼 유효성 검사 훅(useFormValidation) 적용 및 에러 표시
등록 버튼 활성/비활성 상태 처리 및 스타일 적용
💬 멘토님께 남기는 메시지
<RegistrationPage>)에서는 요구사항에 따라 직접 구현한 POST 메서드를 사용해 상품 등록 로직을 작성했습니다. 다만 현재 로그인 기능이 구현되지 않아 인증 토큰이 없어 서버에서 401 에러가 발생하는 상황입니다. 요구사항인 “등록 성공 시 상품 상세 페이지로 이동”을 만족하기 위해, 임시로fakeProductId를 사용해 상세 페이지(빈 페이지)로 이동하도록 처리해 두었습니다.clamp,flex-basis,order등의 CSS 속성을 처음 사용해 보았습니다. 반응형 레이아웃을 구현할 때 실무에서 자주 사용되는 CSS 속성이나, 알아두면 좋은 패턴에는 어떤 것들이 있는지 궁금합니다.