SEB_FE_44/과제
[coz-shopping] Modal
언젠간코딩잘함
2023. 5. 15. 22:51
Modal.js 컴포넌트 생성
더보기
import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faStar } from "@fortawesome/free-solid-svg-icons";
import { faX } from "@fortawesome/free-solid-svg-icons";
import classes from "./Modal.module.css";
const Modal = ({
imageUrl,
handleModalClose,
isBookmarked,
handleBookmark,
title,
}) => {
const handleOverlayClick = event => {
if (event.target === event.currentTarget) {
handleModalClose();
}
};
return (
<div className={classes.modalOverlay} onClick={handleOverlayClick}>
<div className={classes.modal}>
<FontAwesomeIcon
className={classes.close}
icon={faX}
size="lg"
color="white"
onClick={handleModalClose}
/>
<img className={classes.img} src={imageUrl} alt="modalImg" />
<span className={classes.title}>{title}</span>
<FontAwesomeIcon
className={isBookmarked ? classes.bookcolor : classes.bookmark}
size="lg"
icon={faStar}
onClick={handleBookmark}
/>
</div>
</div>
);
};
export default Modal;
Modal.module.css 스타일 생성
더보기
.modalOverlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 9998;
display: flex;
justify-content: center;
align-items: center;
}
.modal {
display: flex;
justify-content: flex-end;
position: fixed;
top: 50%;
left: 50%;
width: 750px;
height: 480px;
border-radius: 8px;
z-index: 9999;
transform: translate(-50%, -50%);
box-shadow: 0 4px 20px;
}
.img {
width: 100%;
height: 100%;
border-radius: 8px;
object-fit: cover;
}
.close {
margin: 20px;
position: absolute;
z-index: 1;
cursor: pointer;
}
.bookmark {
position: absolute;
bottom: 20px;
left: 20px;
color: #ffffff;
cursor: pointer;
}
.bookcolor {
position: absolute;
bottom: 20px;
left: 20px;
color: yellow;
cursor: pointer;
}
.title {
bottom: 20px;
left: 50px;
position: absolute;
font-weight: 800;
color: white;
}
Item.js 컴포넌트 변경
더보기
import React from "react";
import React, { useState } from "react";
import Modal from "../UI/Modal";
import classes from "./Item.module.css";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faStar } from "@fortawesome/free-solid-svg-icons";
const Item = ({ item, setBookmarkState, isBookmarked }) => {
const [modalState, setModalState] = useState(false);
const handleModalOpen = () => {
setModalState(true);
};
const handleModalClose = () => {
setModalState(false);
};
const handleBookmark = item => {
const bookmark = JSON.parse(localStorage.getItem("bookmark")) || [];
const existingItemIndex = bookmark.findIndex(x => x.id === item.id);
const isExistingItem = existingItemIndex !== -1;
if (isExistingItem) {
bookmark.splice(existingItemIndex, 1);
} else {
bookmark.unshift(item);
}
localStorage.setItem("bookmark", JSON.stringify(bookmark));
setBookmarkState(JSON.parse(localStorage.getItem("bookmark")));
};
return (
<div className={classes.item}>
<div className={classes.imgBox}>
<img
className={classes.img}
src={item.image_url ? item.image_url : item.brand_image_url}
alt="img"
/>
<FontAwesomeIcon
className={isBookmarked ? classes.bookcolor : classes.bookmark}
size="lg"
icon={faStar}
onClick={() => {
handleBookmark(item);
}}
<>
{modalState && (
<Modal
imageUrl={item.image_url || item.brand_image_url}
handleModalClose={handleModalClose}
isBookmarked={isBookmarked}
handleBookmark={() => handleBookmark(item)}
title={item.title || item.brand_name}
/>
</div>
<div className={classes.firstLine}>
{
<span className={classes.title}>
{item.title ? item.title : item.brand_name}
</span>
}
{(() => {
switch (item.type) {
case "Brand":
return <span className={classes.customer}>관심고객수</span>;
case "Product":
return (
<span className={classes.percent}>
{item.discountPercentage}%
</span>
);
default:
return "";
)}
<div className={classes.item}>
<div className={classes.imgBox}>
<img
className={classes.img}
src={item.image_url ? item.image_url : item.brand_image_url}
alt="img"
onClick={handleModalOpen}
/>
<FontAwesomeIcon
className={isBookmarked ? classes.bookcolor : classes.bookmark}
size="lg"
icon={faStar}
onClick={() => {
handleBookmark(item);
}}
/>
</div>
<div className={classes.firstLine}>
{
<span className={classes.title}>
{item.title ? item.title : item.brand_name}
</span>
}
})()}
</div>
<div className={classes.firstLine}>
<span>{item.sub_title ? item.sub_title : ""}</span>
<span className={classes.follower}>
{(() => {
switch (item.type) {
case "Product":
return `${item.price
.toString()
.replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",")}원`;
case "Brand":
return item.follower
.toString()
.replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
return <span className={classes.customer}>관심고객수</span>;
case "Product":
return (
<span className={classes.percent}>
{item.discountPercentage}%
</span>
);
default:
return "";
}
})()}
</span>
</div>
<div className={classes.firstLine}>
<span>{item.sub_title ? item.sub_title : ""}</span>
<span className={classes.follower}>
{(() => {
switch (item.type) {
case "Product":
return `${item.price
.toString()
.replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",")}원`;
case "Brand":
return item.follower
.toString()
.replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
default:
return "";
}
})()}
</span>
</div>
</div>
</div>
</>
);
};
export default Item;
Modal.js 컴포넌트 변경
더보기
import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faStar } from "@fortawesome/free-solid-svg-icons";
import { faX } from "@fortawesome/free-solid-svg-icons";
import classes from "./Modal.module.css";
const Modal = ({
imageUrl,
handleModalClose,
title,
setWillBookmarked,
willBookmarked,
}) => {
const handleOverlayClick = event => {
if (event.target === event.currentTarget) {
handleModalClose();
}
};
const handleModalBookmark = () => {
setWillBookmarked(prev => !prev);
};
return (
<div className={classes.modalOverlay} onClick={handleOverlayClick}>
<div className={classes.modal}>
<FontAwesomeIcon
className={classes.close}
icon={faX}
size="lg"
color="white"
onClick={handleModalClose}
/>
<img className={classes.img} src={imageUrl} alt="modalImg" />
<span className={classes.title}>{title}</span>
<FontAwesomeIcon
className={willBookmarked ? classes.bookcolor : classes.bookmark}
size="lg"
icon={faStar}
onClick={handleModalBookmark}
/>
</div>
</div>
);
};
export default Modal;
Item.js 컴포넌트 변경
더보기
const Item = ({ item, setBookmarkState, isBookmarked }) => {
const [modalState, setModalState] = useState(false);
const [willBookmarked, setWillBookmarked] = useState(false);
const handleModalOpen = () => {
setModalState(true);
setWillBookmarked(isBookmarked);
};
const handleModalClose = () => {
if (isBookmarked && !willBookmarked) {
const bookmark = JSON.parse(localStorage.getItem("bookmark"));
const existingItemIndex = bookmark.findIndex(x => x.id === item.id);
bookmark.splice(existingItemIndex, 1);
localStorage.setItem("bookmark", JSON.stringify(bookmark));
setBookmarkState(JSON.parse(localStorage.getItem("bookmark")));
}
if (!isBookmarked && willBookmarked) {
const bookmark = JSON.parse(localStorage.getItem("bookmark")) || [];
bookmark.unshift(item);
localStorage.setItem("bookmark", JSON.stringify(bookmark));
setBookmarkState(JSON.parse(localStorage.getItem("bookmark")));
}
setModalState(false);
};
const handleBookmark = item => {
const bookmark = JSON.parse(localStorage.getItem("bookmark")) || [];
const existingItemIndex = bookmark.findIndex(x => x.id === item.id);
const isExistingItem = existingItemIndex !== -1;
if (isExistingItem) {
bookmark.splice(existingItemIndex, 1);
} else {
bookmark.unshift(item);
}
localStorage.setItem("bookmark", JSON.stringify(bookmark));
setBookmarkState(JSON.parse(localStorage.getItem("bookmark")));
};
return (
<>
{modalState && (
<Modal
imageUrl={item.image_url || item.brand_image_url}
handleModalClose={handleModalClose}
isBookmarked={isBookmarked}
handleBookmark={() => handleBookmark(item)}
title={item.title || item.brand_name}
setWillBookmarked={setWillBookmarked}
willBookmarked={willBookmarked}
/>
)}
<div className={classes.item}>
<div className={classes.imgBox}>
<img
className={classes.img}
src={item.image_url ? item.image_url : item.brand_image_url}
alt="img"
onClick={handleModalOpen}
/>
<FontAwesomeIcon
className={isBookmarked ? classes.bookcolor : classes.bookmark}
size="lg"
icon={faStar}
onClick={() => {
handleBookmark(item);
}}
/>
</div>
<div className={classes.firstLine}>
{
<span className={classes.title}>
{item.title ? item.title : item.brand_name}
</span>
}
{(() => {
switch (item.type) {
case "Brand":
return <span className={classes.customer}>관심고객수</span>;
case "Product":
return (
<span className={classes.percent}>
{item.discountPercentage}%
</span>
);
default:
return "";
}
})()}
</div>
<div className={classes.firstLine}>
<span>{item.sub_title ? item.sub_title : ""}</span>
<span className={classes.follower}>
{(() => {
switch (item.type) {
case "Product":
return `${item.price
.toString()
.replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",")}원`;
case "Brand":
return item.follower
.toString()
.replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
default:
return "";
}
})()}
</span>
</div>
</div>
</>
);
};
export default Item;