-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Revert "[최제원] Sprint4 (#155)" This reverts commit e46d37a. * react npm start 오류로 인한 npm install 및 react 개발환경 셋팅 * header 추가 및 GET 리퀘스트를 받아 itemList 정렬 * 클래스 이름 추가 및 CSS 추가 * 파일 구조 정리 및 상품 정렬 쿼리 생성 * 최신순, 인기순 드롭아웃 html 구현과 검색 input 기능 html 구현 * form 태그 내부에 있는 태그들의 css 추가 및 수정 * 스프린트 미션5 미완성으로 코드잇에서 제공한 스프린트 미션5 완성본을 표본으로 커밋 * addItemPage html과 css 추가 * 이미지 삭제 기능 추가 * input 안에 들어가있는 value값 삭제 * sprint6 templete code copy and commit * 상품 상세페이지 html 추가 및 api 연결과 간단한 css 작업도중 git push * ItemDetailPage css 작업완료 * user information 추가 및 useNavigate를 이용하여 목록으로 돌아가기 기능 구현
- Loading branch information
Showing
30 changed files
with
16,409 additions
and
1,817 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import React from "react"; | ||
import styled from "styled-components"; | ||
import { ReactComponent as CloseIcon } from "../../assets/images/icons/ic_x.svg"; | ||
|
||
const Button = styled.button` | ||
background-color: ${({ theme }) => theme.colors.gray[0]}; | ||
width: 20px; | ||
height: 20px; | ||
border-radius: 50%; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
&:hover { | ||
background-color: ${({ theme }) => theme.colors.blue[0]}; | ||
} | ||
`; | ||
|
||
function DeleteButton({ onClick, label }) { | ||
return ( | ||
<Button aria-label={`${label} 삭제`} onClick={onClick}> | ||
<CloseIcon /> | ||
</Button> | ||
); | ||
} | ||
|
||
export default DeleteButton; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
.sortButtonWrapper { | ||
position: relative; | ||
} | ||
|
||
.sortDropdownTriggerButton { | ||
border: 1px solid #e5e7eb; | ||
border-radius: 12px; | ||
padding: 9px; | ||
margin-left: 8px; | ||
} | ||
|
||
.dropdownMenu { | ||
position: absolute; | ||
top: 110%; | ||
right: 0; | ||
background: #fff; | ||
border-radius: 8px; | ||
border: 1px solid #e5e7eb; | ||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); | ||
z-index: 99; | ||
} | ||
|
||
.dropdownItem { | ||
padding: 12px 44px; | ||
border-bottom: 1px solid #e5e7eb; | ||
font-size: 16px; | ||
color: #1f2937; | ||
cursor: pointer; | ||
} | ||
|
||
.dropdownItem:last-child { | ||
border-bottom: none; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import React, { useState } from "react"; | ||
import "./DropdownMenu.css"; | ||
import { ReactComponent as SortIcon } from "../../assets/images/icons/ic_sort.svg"; | ||
|
||
function DropdownMenu({ onSortSelection }) { | ||
const [isDropdownVisible, setIsDropdownVisible] = useState(false); | ||
|
||
const toggleDropdown = () => { | ||
setIsDropdownVisible(!isDropdownVisible); | ||
}; | ||
|
||
return ( | ||
<div className="sortButtonWrapper"> | ||
<button className="sortDropdownTriggerButton" onClick={toggleDropdown}> | ||
<SortIcon /> | ||
</button> | ||
|
||
{isDropdownVisible && ( | ||
<div className="dropdownMenu"> | ||
<div | ||
className="dropdownItem" | ||
onClick={() => { | ||
onSortSelection("recent"); | ||
setIsDropdownVisible(false); | ||
}} | ||
> | ||
최신순 | ||
</div> | ||
<div | ||
className="dropdownItem" | ||
onClick={() => { | ||
onSortSelection("favorite"); | ||
setIsDropdownVisible(false); | ||
}} | ||
> | ||
인기순 | ||
</div> | ||
</div> | ||
)} | ||
</div> | ||
); | ||
} | ||
export default DropdownMenu; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import React, { useState } from "react"; | ||
import { Label } from "./InputItem"; | ||
import styled, { css } from "styled-components"; | ||
import { ReactComponent as PlusIcon } from "../../assets/images/icons/ic_plus.svg"; | ||
import DeleteButton from "./DeleteButton"; | ||
|
||
const ImageUploadContainer = styled.div` | ||
display: flex; | ||
gap: 8px; | ||
@media ${({ theme }) => theme.mediaQuery.tablet} { | ||
gap: 18px; | ||
} | ||
@media ${({ theme }) => theme.mediaQuery.desktop} { | ||
gap: 24px; | ||
} | ||
`; | ||
|
||
const squareStyles = css` | ||
// 작은 화면에서는 max-width가 되기 전까지는 UploadButton과 ImagePreview가 각각 gap을 포함해 컨테이너 너비의 절반을 차지하도록 함 | ||
width: calc(50% - 4px); | ||
max-width: 200px; | ||
aspect-ratio: 1 / 1; // 정사각형 비율 유지 | ||
border-radius: 12px; | ||
@media ${({ theme }) => theme.mediaQuery.tablet} { | ||
width: 162px; | ||
} | ||
@media ${({ theme }) => theme.mediaQuery.desktop} { | ||
width: 282px; | ||
} | ||
`; | ||
|
||
// file input과 연관 짓기 위해 버튼이 대신 label로 설정 | ||
const UploadButton = styled.label` | ||
background-color: ${({ theme }) => theme.colors.gray[1]}; | ||
color: ${({ theme }) => theme.colors.gray[0]}; | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
justify-content: center; | ||
gap: 12px; | ||
font-size: 16px; | ||
cursor: pointer; // 버튼이 아닌 label을 사용한 경우 별도로 추가해 주세요 | ||
&:hover { | ||
background-color: ${({ theme }) => theme.colors.gray[2]}; | ||
} | ||
${squareStyles} | ||
`; | ||
|
||
const ImagePreview = styled.div` | ||
background-image: url(${({ src }) => src}); | ||
background-size: cover; | ||
background-position: center; | ||
position: relative; // DeleteButton 포지셔닝을 위해 추가 | ||
${squareStyles} | ||
`; | ||
|
||
const DeleteButtonWrapper = styled.div` | ||
position: absolute; | ||
top: 12px; | ||
right: 12px; | ||
`; | ||
|
||
// 브라우저 기본 '파일 선택' 버튼 대신 커스텀 버튼을 사용하기 위해 file input을 숨김 처리 | ||
const HiddenFileInput = styled.input` | ||
display: none; | ||
`; | ||
|
||
function ImageUpload({ title }) { | ||
const [imagePreviewUrl, setImagePreviewUrl] = useState(""); | ||
|
||
const handleImageChange = (event) => { | ||
const file = event.target.files[0]; | ||
if (file) { | ||
// 미리보기 주소 값(Object URL) 생성 | ||
const imageUrl = URL.createObjectURL(file); | ||
setImagePreviewUrl(imageUrl); | ||
} | ||
}; | ||
|
||
const handleDelete = () => { | ||
setImagePreviewUrl(""); // 미리보기 URL 리셋 | ||
}; | ||
|
||
return ( | ||
<div> | ||
{title && <Label>{title}</Label>} | ||
|
||
<ImageUploadContainer> | ||
{/* HiddenFileInput의 id와 label의 htmlFor 값을 매칭해 주세요 */} | ||
<UploadButton htmlFor="image-upload"> | ||
<PlusIcon /> | ||
이미지 등록 | ||
</UploadButton> | ||
|
||
<HiddenFileInput | ||
id="image-upload" | ||
type="file" | ||
onChange={handleImageChange} | ||
accept="image/*" // 이미지 파일만 업로드 가능하도록 제한 | ||
/> | ||
|
||
{/* 업로드된 이미지가 있으면 썸네일 렌더링 */} | ||
{imagePreviewUrl && ( | ||
<ImagePreview src={imagePreviewUrl}> | ||
<DeleteButtonWrapper> | ||
<DeleteButton onClick={handleDelete} label="이미지 파일" /> | ||
</DeleteButtonWrapper> | ||
</ImagePreview> | ||
)} | ||
</ImageUploadContainer> | ||
</div> | ||
); | ||
} | ||
|
||
export default ImageUpload; |
Oops, something went wrong.