Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[정원식] Sprint6 #192

Merged
Changes from 1 commit
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
Prev Previous commit
feat(Sprint6): additems 페이지 추가
  • Loading branch information
wonsik3686 committed Jun 28, 2024
commit 966e847e6e10264e0d5bebd14316300d6129064c
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

#file
visualwind.wrapper.tsx

# dependencies
/node_modules
/.pnp
5 changes: 4 additions & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
@@ -19,7 +19,10 @@ function App() {
<Route path="/signup" element={<Signup />} /> */}
<Route path="faq" element={<Faq />} />
<Route path="privacy" element={<Privacy />} />
<Route path="items" element={<Items />} />
<Route path="items">
<Route index element={<Items />} />
<Route path="additems" element={<AddItems />} />
</Route>
<Route path="additems" element={<AddItems />} />
</Routes>
</BrowserRouter>
5 changes: 5 additions & 0 deletions src/assets/images/icons/ic_X.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/images/icons/ic_union.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/components/items/SellingItems/SellingItems.jsx
Original file line number Diff line number Diff line change
@@ -84,7 +84,7 @@ function SellingItems() {
</div>
<div className="header-selling-items-right">
<a
href="/additems"
href="/items/additems"
id="btn-add-item"
className="button btn-add-item"
>
1 change: 1 addition & 0 deletions src/components/navigationBar/NavigationBar.jsx
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@ function NavigationBar() {
</a> */}
<NavLink
to={'/items'}

className={({ isActive }) =>
`nav-bar-menu-link ${isActive ? 'active' : ''}`
}
38 changes: 38 additions & 0 deletions src/core/ui/buttons/Button/Button.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.btn-default {
background-color: var(--blue);
color: #ffffff;
font-family: inherit;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 16px;
font-weight: 600;
border: none;
outline: none;
box-shadow: none;
cursor: pointer;
line-height: inherit;
border-radius: 8px;
padding: 12px 23px;
}

.btn-default:hover {
background-color: #1967d6;
}

.btn-default:focus {
background-color: #1251aa;
}

.btn-default:disabled {
background-color: #9ca3af;
cursor: default;
pointer-events: none;
}

.btn-default.pill-button {
font-size: 16px;
font-weight: 600;
border-radius: 999px;
padding: 14.5px 33.5px;
}
18 changes: 18 additions & 0 deletions src/core/ui/buttons/Button/Button.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useEffect, useRef } from 'react';
import './Button.css';
function Button({ text = '버튼', onClick = () => {}, isDisabled = false }) {
const ref = useRef();

useEffect(() => {
ref.current.disabled = isDisabled ? true : false;
}, [isDisabled]);

return (
<>
<button className="btn-default" onClick={onClick} ref={ref}>
{text}
</button>
</>
);
}
export default Button;
93 changes: 93 additions & 0 deletions src/core/ui/inputs/ImageFileInput/ImageFileInput.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
.wrapper-btn-input-image-file {
display: flex;
justify-content: start;
align-items: center;
}

.card-input-image-file {
width: 168px;
height: 168px;
margin: 0 8px 0 0;
border-radius: 12px;
background-color: var(--gray-100);
display: inline-flex;
justify-content: center;
align-items: center;
}

.card-input-image-file:last-child {
margin: 0;
}

.input-image-file {
display: none;
}

.wrapper-content-btn-input-image-file {
display: inline-flex;
flex-direction: column;
align-items: center;
}

.icon-union-input-image-file {
width: 48px;
height: 48px;
margin: 0 0 12px 0;
}

.text-btn-input-image-file {
color: var(--gray-400);
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 24px;
}

.img-preview-input-image-file {
width: 100%;
height: 100%;
border-radius: 12px;
}

.btn-delete-input-image-file {
position: relative;
top: -60px;
left: -40px;
opacity: 70%;
}

.btn-delete-input-image-file:hover {
opacity: 100%;
}

.btn-delete-input-image-file:focus {
opacity: 100%;
}

@media (min-width: 768px) {
.card-input-image-file {
width: 162px;
height: 162px;
margin: 0 16px 0 0;
}

.btn-delete-input-image-file {
position: relative;
top: -60px;
left: -45px;
}
}

@media (min-width: 1280px) {
.card-input-image-file {
width: 282px;
height: 282px;
margin: 0 24px 0 0;
}

.btn-delete-input-image-file {
position: relative;
top: -110px;
left: -60px;
}
}
84 changes: 84 additions & 0 deletions src/core/ui/inputs/ImageFileInput/ImageFileInput.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { useEffect, useRef, useState } from 'react';
import { ReactComponent as IconUnion } from '../../../../assets/images/icons/ic_union.svg';
import { ReactComponent as IconX } from '../../../../assets/images/icons/ic_X.svg';
import ImgDeafault from '../../../../assets/images/market/img_default.png';
import './ImageFileInput.css';
function ImageFileInput({
className = '',
name,
value,
Copy link
Collaborator

Choose a reason for hiding this comment

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

value 보다는 어떤 상세한 변수명이 좋을 것 같습니다. 컴포넌트를 들여다 봤을때 이미지를 뜻하는거니까 productImage와 같이 좀 더 자세한 변수명을 사용해주세요.

initialPreview,
onChange,
}) {
const [preview, setPreview] = useState(initialPreview);
const inputRef = useRef();

const handleChange = (e) => {
const nextValue = e.target.files[0];
onChange(name, nextValue);
};

const handleClearClick = () => {
const inputNode = inputRef.current;
if (!inputNode) return;

inputNode.value = '';
onChange(name, null);
};

useEffect(() => {
if (!value) return;
const nextPreview = URL.createObjectURL(value);
setPreview(nextPreview);

return () => {
setPreview(initialPreview);
URL.revokeObjectURL(nextPreview);
};
}, [value, initialPreview]);

return (
<div className={`wrapper-btn-input-image-file ${className}`}>
{/* 추가 버튼 */}
<label htmlFor="input-image-file" className="card-input-image-file">
<div className="wrapper-content-btn-input-image-file">
<IconUnion
className="icon-union-input-image-file"
alt="이미지 등록 버튼"
/>
<div className="text-btn-input-image-file">이미지 등록</div>
</div>
</label>
<input
className="input-image-file"
type="file"
id="input-image-file"
name="imgFile"
onChange={handleChange}
ref={inputRef}
/>
{/* 미리보기 이미지 */}
{value && (
<>
<div className="card-input-image-file">
<img
src={preview || ImgDeafault}
Copy link
Collaborator

Choose a reason for hiding this comment

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

디폴트 이미지 사용해주신 점 아주 좋습니다 !

className="img-preview-input-image-file"
alt="상품 미리보기"
/>
</div>
<button
className="btn-delete-input-image-file"
onClick={handleClearClick}
>
<IconX
className="icon-delete-input-image-file"
alt="선택 해제 버튼"
/>
</button>
</>
)}
</div>
);
}
export default ImageFileInput;
39 changes: 39 additions & 0 deletions src/core/ui/inputs/TagInput/TagInput.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.wrapper-input-tags {
display: flex;
flex-direction: column;
align-items: start;
width: 100%;
}

.wrapper-list-tag-input-tag {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: flex-start;
width: 100%;
margin: 0;
}

.tag-input-tag {
display: flex;
align-items: center;
margin: 12px 12px 0 0;
padding: 12px 12px 12px 16px;
border-radius: 26px;
background-color: var(--gray-100);
}

.tag-input-tag:last-child {
margin: 12px 0 0;
}

.btn-delete-tag {
color: white;
width: 20px;
height: 20px;
margin: 0 0 0 5px;
background-color: var(--gray-500);
border-radius: 10px;
font-size: 15px;
font-weight: 400;
}
59 changes: 59 additions & 0 deletions src/core/ui/inputs/TagInput/TagInput.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { useState } from 'react';
import './TagInput.css';

function TagInput({ className = '', name, tags = [], onAdd, onRemove }) {
const [targetText, setTargetText] = useState('');

const handleChange = (e) => {
const { value } = e.target;
if (!value.trim()) return;
setTargetText(value);
};

const handlePress = (e) => {
if (e.key === 'Enter' && targetText) {
e.preventDefault();
onAdd(targetText.trim());
setTargetText('');
}
};

const handleDeleteTag = (e) => {
onRemove(e.currentTarget.parentNode.dataset.tagName);
};

return (
<>
<div className={`wrapper-input-tags ${className}`}>
<input
className="input-form-add-item"
type="text"
id={name}
name={name}
value={targetText || ''}
onChange={handleChange}
onKeyDown={handlePress}
placeholder="태그를 입력해주세요"
/>
{tags.length > 0 && (
<div className="wrapper-list-tag-input-tag">
{tags.map((tag, i) => (
<div
className="tag-input-tag"
key={`tag-item-${i}`}
data-tag-name={tag}
>
{tag}
<button className="btn-delete-tag" onClick={handleDeleteTag}>
X
</button>
</div>
))}
</div>
)}
</div>
</>
);
}

export default TagInput;
Loading
Loading