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: 8 additions & 0 deletions .vite/deps/_metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"hash": "e6445809",
"configHash": "49744398",
"lockfileHash": "934bbf7c",
"browserHash": "4c0c12e4",
"optimized": {},
"chunks": {}
}
3 changes: 3 additions & 0 deletions .vite/deps/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "module"
}
Binary file added public/icons/ic_plus.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icons/ic_x_button.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions src/components/Header/Header.styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,11 @@ export const ProfileImgStyle = css`
margin-right: 16px;
`)}
`;

export const LinkStyle = css`
color: var(--blue100);
`;

export const DefaultStyle = css`
color: var(--gray600);
`;
17 changes: 16 additions & 1 deletion src/components/Header/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,24 @@ import {
LogoStyle,
ProfileImgStyle,
LinkWrapperStyle,
LinkStyle,
} from "./Header.styles";
import { useLocation } from "react-router";

function Header() {
const [logoImg, setLogoImg] = useState(logo);
const [logoSize, setLogoSize] = useState(true);
const location = useLocation();

const getName = () => {
switch (location.pathname) {
case "/items":
case "/additem":
return LinkStyle;
default:
return "DefaultStyle"; // 기본 클래스
}
};

useEffect(() => {
const handleResize = () => {
Expand Down Expand Up @@ -47,7 +60,9 @@ function Header() {
/>
<div css={LinkWrapperStyle}>
<Link to="/board">자유게시판</Link>
<Link to="/items">중고마켓</Link>
<Link to="/items" css={getName()}>
중고마켓
</Link>
</div>
</div>
<img css={ProfileImgStyle} src={profileImg} alt="프로필 이미지" />
Expand Down
5 changes: 0 additions & 5 deletions src/pages/AddItem.jsx

This file was deleted.

61 changes: 61 additions & 0 deletions src/pages/AddItem/AddItem.styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { css } from "@emotion/react";
import { tablet, mobile, desktop } from "@/styles/utils/mixins";

export const addItemContainer = css`
display: flex;
max-width: 1200px;
flex-direction: column;
align-items: flex-start;
gap: 21px;
margin: 24px auto;

${tablet(css`
max-width: 696px;
margin: 16px auto;
`)}

${mobile(css`
max-width: 346px;
margin: 24px auto;
`)}
`;

export const inputFieldContainer = css`
display: flex;
flex-direction: column;
gap: 24px;
width: 100%;
margin-bottom: 76px;

${desktop(css`
gap: 32px;
margin-bottom: 69px;
`)}

${mobile(css`
margin-bottom: 70px;
`)}
`;

export const tagContainer = css`
display: flex;
align-items: center;
gap: 12px;
`;

export const tagStyle = css`
display: flex;
align-items: center;
gap: 8px;
padding: 6px 12px 6px 16px;

gap: 10px;
border-radius: 26px;
background: var(--gray100);
`;

export const closeIconStyle = css`
width: 16px;
height: 16px;
cursor: pointer;
`;
81 changes: 81 additions & 0 deletions src/pages/AddItem/components/AddItemImage.jsx
Copy link
Collaborator

Choose a reason for hiding this comment

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

👍 칭찬
이미지 업로드 컴포넌트 잘 분리해주셨고 에러 메시지도 잘 추가해주셨어요~

Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// src/pages/AddItem/components/AddItemImage.jsx
import plusImage from "/icons/ic_plus.png";
import deleteImage from "/icons/ic_x_button.png";
import { useState, useRef } from "react";
import {
addItemImageContainer,
addItemImageButtonContainer,
addItemImageButtonStyle,
previewImageContainer,
previewImageStyle,
deleteImageStyle,
errorMessageStyle,
} from "./AddItemImage.styles";

function AddItemImage({ onImageChange }) {
const [preview, setPreview] = useState("");
const uploadImg = useRef(null);
const [errorMessage, setErrorMessage] = useState("");

const handleImageUpload = () => {
if (preview) {
setErrorMessage("*이미지 등록은 최대 1개까지 가능합니다.");
return;
}
uploadImg.current?.click();
};

const handlePreview = (e) => {
if (e.target.files && e.target.files.length > 0) {
const file = e.target.files[0];
setPreview(URL.createObjectURL(file));
onImageChange(file); // 선택한 이미지 전달
}
};

const handleDelete = () => {
setPreview("");
uploadImg.current.value = null;
onImageChange(null); // 이미지 삭제 시 null 전달
setErrorMessage("");
};

return (
<article css={addItemImageContainer}>
<h3>상품 이미지</h3>
<div>
<div css={addItemImageButtonContainer}>
<button onClick={handleImageUpload} css={addItemImageButtonStyle}>
<img src={plusImage} alt="이미지 등록" />
<p>이미지 등록</p>
</button>
Comment on lines +48 to +51
Copy link
Collaborator

Choose a reason for hiding this comment

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

💊 제안
이런경우 label로 하시고 file input과 연결해주시는 것이 더 적절할 것 같아요~

<div css={previewImageContainer}>
{preview && (
<img
src={preview}
alt="이미지 미리보기"
css={previewImageStyle}
/>
)}
<input
type="file"
accept="image/*"
Copy link
Collaborator

Choose a reason for hiding this comment

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

💊 제안
input의 accept 속성은 유저가 어떤 파일을 올려야하는지에 대한 힌트를 제공하는 속성입니다.
유저는 파일 업로드시 accept의 명시된 확장자 이외의 파일도 올릴 수 있으므로
실제 upload 함수에서 한번더 확장자를 검사해주시는 것이 좋습니다.

(사용자가 업로드창에서 옵션을 열어 확장자를 바꾸면 아래처럼 보입니다)
스크린샷 2025-05-08 오후 5 53 17

https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/accept

onChange={handlePreview}
ref={uploadImg}
style={{ display: "none" }}
/>
<img
src={deleteImage}
alt="이미지 삭제"
onClick={handleDelete}
css={deleteImageStyle}
/>
</div>
</div>
{errorMessage && <p css={errorMessageStyle}>{errorMessage}</p>}
</div>
</article>
);
}

export default AddItemImage;
87 changes: 87 additions & 0 deletions src/pages/AddItem/components/AddItemImage.styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { css } from "@emotion/react";
import { tablet, desktop } from "@/styles/utils/mixins";

export const addItemImageContainer = css`
width: 100%;
gap: 16px;
`;

export const addItemImageButtonStyle = css`
width: 168px;
height: 168px;
padding: 42px 47px;
flex-shrink: 0;
border-radius: 12px;
gap: 12px;
background: var(--gray200);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;

${desktop(css`
width: 282px;
height: 282px;
`)}

img {
width: 48px;
height: 48px;
}

p {
color: var(--gray400);
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 26px;
}
`;

export const addItemImageButtonContainer = css`
display: flex;
align-items: flex-start;
gap: 24px;

${tablet(css`
gap: 16px;
`)}

margin-bottom: 16px;
`;

export const previewImageContainer = css`
position: relative;
`;

export const previewImageStyle = css`
width: 168px;
height: 168px;

object-fit: cover;
border-radius: 12px;
${desktop(css`
width: 282px;
height: 282px;
`)}
`;

export const errorMessageStyle = css`
color: var(--red, #f74747);

font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 26px;
`;

export const deleteImageStyle = css`
cursor: pointer;
width: 20px;
height: 20px;
flex-shrink: 0;

position: absolute;
right: 12px;
top: 12px;
`;
49 changes: 49 additions & 0 deletions src/pages/AddItem/components/AddItemTop.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { css } from "@emotion/react";

export default function AddItemTop({ isDisabled, onDisableChange }) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

💊 제안
AddItemHeader같은 이름이 더 적절할 것 같아요~

return (
<section css={AddItemTopStyle}>
<h2>상품 등록하기</h2>
<button
type="submit"
disabled={isDisabled}
css={AddItemTopButtonStyle(isDisabled)}
onClick={onDisableChange} // 클릭 시 상태 변경
>
등록
</button>
</section>
);
}

const AddItemTopStyle = css`
display: flex;
justify-content: space-between;
align-items: center;
font-style: normal;
width: 100%;

h2 {
color: var(--gray800);
font-size: 20px;
font-weight: 700;
line-height: 32px;
}
`;

const AddItemTopButtonStyle = (isDisabled) => css`
display: flex;
height: 42px;
padding: 12px 23px;
justify-content: center;
align-items: center;

border-radius: 8px;
background: ${isDisabled ? "var(--gray400)" : "var(--blue100)"};

color: var(--gray100);

font-size: 16px;
font-weight: 600;
line-height: 26px;
`;
Loading
Loading