Skip to content

Conversation

KSJ27
Copy link
Collaborator

@KSJ27 KSJ27 commented Mar 12, 2025

요구사항

기본

  • 상품 등록 페이지 주소는 “/additem” 입니다.
  • 페이지 주소가 “/additem” 일때 상단네비게이션바의 '중고마켓' 버튼의 색상은 “3692FF”입니다.
  • 상품 이미지는 최대 한개 업로드가 가능합니다.
  • 각 input의 placeholder 값을 정확히 입력해주세요.
  • 이미지를 제외하고 input 에 모든 값을 입력하면 ‘등록' 버튼이 활성화 됩니다.
  • API를 통한 상품 등록은 추후 미션에서 적용합니다.

심화

  • 이미지 안의 X 버튼을 누르면 이미지가 삭제됩니다.
  • 추가된 태그 안의 X 버튼을 누르면 해당 태그는 삭제됩니다.

주요 변경사항

스크린샷

멘토에게

@KSJ27 KSJ27 requested a review from kiJu2 March 12, 2025 14:45
@KSJ27 KSJ27 self-assigned this Mar 12, 2025
@KSJ27 KSJ27 added the 매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다. label Mar 12, 2025
@kiJu2
Copy link
Collaborator

kiJu2 commented Mar 13, 2025

스프리트 미션 하시느라 수고 많으셨어요.
학습에 도움 되실 수 있게 꼼꼼히 리뷰 하도록 해보겠습니다. 😊

Comment on lines +26 to +27
# Environment variables
.env
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

굿굿 ! 환경 변수를 추가하고 gitignore에 추가하셨군요 ! 👍

Comment on lines +19 to +28
<Route element={<Layout />}>
<Route path="/" element={<Home />} />
<Route path="/items" element={<Items />} />
<Route path="/additem" element={<AddItem />} />
<Route path="/boards" element={<Boards />} />
</Route>
<Route path="/#" element={<Login />} />
<Route path="/#" element={<# />} />
<Route path="/privacy" element={<Policy />} />
<Route path="/faq" element={<Faq />} />
Copy link
Collaborator

@kiJu2 kiJu2 Mar 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

우와.. 활용도가 너무 좋으신데요?

라이브러리를 정말 잘 사용하시는군요 ! 👍👍👍

Comment on lines +30 to +34
export const postItem = async (item) => {
const response = await instance.post(PRODUCT_ENDPOINT, item);
const data = response.data;
return data;
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(선택/소소한 팁..?) 별 건 아니지만..!

Suggested change
export const postItem = async (item) => {
const response = await instance.post(PRODUCT_ENDPOINT, item);
const data = response.data;
return data;
};
export const postItem = async (item) => {
const { data } = await instance.post(PRODUCT_ENDPOINT, item);
return data;
};

위와 같이 구조 분해 할당으로 간략히 작성할 수 있습니다 ! 😊

구조 분해 할당 구문은 배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 JavaScript 표현식입니다.

Comment on lines +3 to +47
function AddItemInputField({
id,
name,
type,
label,
placeholder,
value,
setValue,
onEnterKeyDown,
onBlur,
}) {
const handleEnterKeyDown = (e) => {
if (!onEnterKeyDown) return;
if (e.key === "Enter") {
e.preventDefault();
onEnterKeyDown(e.target.value);
setValue("");
}
};

return (
<div>
<label htmlFor={id} className="text-lg font-bold text-gray-800">
{label}
</label>
<div
className={`mt-4 flex h-14 w-full items-center justify-stretch gap-3 rounded-xl bg-gray-100 px-6`}
>
<input
id={id}
name={name}
type={type}
placeholder={placeholder}
value={value}
className={`w-full text-gray-800 placeholder:font-normal placeholder:text-gray-400 focus:outline-none ${type === "number" ? "[appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none" : ""}`}
onChange={(e) => setValue(e.target.value)}
onKeyDown={handleEnterKeyDown}
onBlur={onBlur}
/>
</div>
</div>
);
}

export default AddItemInputField;
Copy link
Collaborator

@kiJu2 kiJu2 Mar 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(심화/의견/제안) LabelInput을 분리해볼 수 있습니다 !:

현재 Label과 Input이 붙어있어요. 분리하면 더욱 활용도가 좋아질 수 있을 것 같아요 !:

Suggested change
function AddItemInputField({
id,
name,
type,
label,
placeholder,
value,
setValue,
onEnterKeyDown,
onBlur,
}) {
const handleEnterKeyDown = (e) => {
if (!onEnterKeyDown) return;
if (e.key === "Enter") {
e.preventDefault();
onEnterKeyDown(e.target.value);
setValue("");
}
};
return (
<div>
<label htmlFor={id} className="text-lg font-bold text-gray-800">
{label}
</label>
<div
className={`mt-4 flex h-14 w-full items-center justify-stretch gap-3 rounded-xl bg-gray-100 px-6`}
>
<input
id={id}
name={name}
type={type}
placeholder={placeholder}
value={value}
className={`w-full text-gray-800 placeholder:font-normal placeholder:text-gray-400 focus:outline-none ${type === "number" ? "[appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none" : ""}`}
onChange={(e) => setValue(e.target.value)}
onKeyDown={handleEnterKeyDown}
onBlur={onBlur}
/>
</div>
</div>
);
}
export default AddItemInputField;
function Label({ htmlFor, children }) {
return (
<label htmlFor={htmlFor} className="text-lg font-bold text-gray-800">
{children}
</label>
);
}
function Input({ id, name, type = "text", className, onEnterKeyDown, setValue, ...rest }) {
const handleEnterKeyDown = (e) => {
if (!onEnterKeyDown) return;
if (e.key === "Enter") {
e.preventDefault();
onEnterKeyDown(e.target.value);
setValue && setValue("");
}
};
return (
<input
id={id}
name={name}
type={type}
className={cn(
"w-full text-gray-800 placeholder:font-normal placeholder:text-gray-400 focus:outline-none",
{
"[appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none":
type === "number",
},
className
)}
onKeyDown={handleEnterKeyDown}
{...rest}
/>
);
}

이렇게 하면 Label과 Input이 각각 독립적인 컴포넌트가 되어 다른 곳에서도 재사용을 기대해볼 수 있고 각각의 스타일과 속성을 확장할 수 있습니다 !
또한 ...rest로 생략가능한(별도 논리적인 연산이 필요 없는) props들을 생략해볼 수 있어요 !

<div className="my-6 flex items-center justify-between">
<div className="text-xl font-bold text-gray-800">상품 등록하기</div>
<button
type="submit"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호 ~ 버튼은 항상 타입을 명시해주시는군요 ? 👍👍

@kiJu2
Copy link
Collaborator

kiJu2 commented Mar 13, 2025

수고하셨습니다 석준님 !
정말 열심히 잘 해주셔서 제가 다 뿌듯하네요 ㅎㅎㅎ
컴포넌트와 관련하여 살짝 심화 피드백을 해드리고 싶었습니다 !
라벨과 인풋은 한 번 고민해보시고 적용해보셔도 좋을 것 같아요 😊

미션 수행하시느라 정말 수고 많으셨습니다 석준님 !! 💪💪

@kiJu2 kiJu2 merged commit ebe3175 into codeit-bootcamp-frontend:React-강석준 Mar 13, 2025
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants