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

공통 - PopUp (Modal) 컴포넌트 #29

Merged
merged 12 commits into from
Aug 15, 2024
81 changes: 44 additions & 37 deletions gamgyul-front/src/components/common/AttractionItem/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import { useEffect, useState } from "react";
import { applyFontStyles } from "../../../utils/fontStyles";

/** 관광지 아이템 컴포넌트 (분리 필요) */
const AttractionItem = ({ isChecked, onCheckChange, type }) => {
const AttractionItem = ({ onDelete, isChecked, onCheckChange, type }) => {
const [bookmark, setBookmark] = useState("off");
const [isModal, setIsModal] = useState(false);

useEffect(() => {}, []);

Expand All @@ -24,40 +23,37 @@ const AttractionItem = ({ isChecked, onCheckChange, type }) => {
console.log("임시 체크박스 클릭 핸들러입니다.");
};

/** 삭제 버튼 클릭 => 이후 추가 */
const handleDeleteClick = () => {
console.log("삭제 버튼을 클릭했습니다.");
};

return (
<AtrctItemContainer>
<AtrctItemInfo>
{type === "CHECK" && (
<StyledCheckBtn>
<img src={`/images/Icon/check_${bookmark}.svg`} alt="북마크버튼" onClick={() => handleCheckClick()} />
</StyledCheckBtn>
<AtrctItemContents>
<AtrctItemInfo>
{type === "CHECK" && (
<StyledCheckBtn>
<img src={`/images/Icon/check_${bookmark}.svg`} alt="체크버튼" onClick={() => handleCheckClick()} />
</StyledCheckBtn>
)}
<figure>
<img src="" alt="관광지 이미지" />
<figcaption>
<h3>리스트이름</h3>
<p>리스트내용</p>
</figcaption>
</figure>
</AtrctItemInfo>
{type === "DELETE" ? (
<StyledIconBtn>
<img src={`/images/Icon/delete.svg`} alt="삭제버튼" onClick={onDelete} />
</StyledIconBtn>
) : (
<StyledIconBtn>
<img
src={`/images/Icon/bookmark_${bookmark}.svg`}
alt="북마크버튼"
onClick={() => handleBookmarkClick(bookmark)}
/>
</StyledIconBtn>
)}
<figure>
<img src="" alt="관광지 이미지" />
<figcaption>
<h3>리스트이름</h3>
<p>리스트내용</p>
</figcaption>
</figure>
</AtrctItemInfo>
{type === "DELETE" ? (
<StyledIconBtn>
<img src={`/images/Icon/delete.svg`} alt="삭제버튼" onClick={() => handleDeleteClick()} />
</StyledIconBtn>
) : (
<StyledIconBtn>
<img
src={`/images/Icon/bookmark_${bookmark}.svg`}
alt="북마크버튼"
onClick={() => handleBookmarkClick(bookmark)}
/>
</StyledIconBtn>
)}
</AtrctItemContents>
</AtrctItemContainer>
);
};
Expand Down Expand Up @@ -88,20 +84,30 @@ const AtrctItemInfo = styled.section`
}
`;

/** 관광지 아이템 컴포넌트 스타일링 */
const AtrctItemContainer = styled.li`
const AtrctItemContents = styled.li`
width: 100%;
height: 90px;
border-bottom: 1px solid ${theme.color.sub2};
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid ${theme.color.sub2};
`;

/** 관광지 아이템 컴포넌트 스타일링 */
const AtrctItemContainer = styled.div`
padding: 0 20px;

&:hover {
background: #1eb17b0d;
}
`;

const StyledIconBtn = styled.button`
width: 24px;
height: 24px;
border: none;
background-color: inherit;
cursor: pointer;
`;

const StyledCheckBtn = styled.button`
Expand All @@ -111,8 +117,9 @@ const StyledCheckBtn = styled.button`
background-color: inherit;
margin-right: 16px;
& > img {
cursor: pointer;
width: 100%;
hegiht: 100%;
height: 100%;
}
`;

Expand Down
1 change: 1 addition & 0 deletions gamgyul-front/src/components/common/BackNaviBtn/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const StyledBackBtn = styled.button`
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;

width: 50px;
height: 50px;
Expand Down
7 changes: 4 additions & 3 deletions gamgyul-front/src/components/common/Button/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ const StyledButton = styled.button`
${applyFontStyles(theme.font.body2)}
width: 100%;
height: ${({ type }) => (type === "small" ? "42px" : "55px")};
border-radius: 20px;
border-radius: ${({ type }) => (type === "small" ? "10px" : "20px")};
border: 0;
cursor: ${({ disabled }) => (disabled ? "not-allowed" : "pointer")};
background-color: ${({ disabled }) => (disabled ? theme.color.grayscale_BF : theme.color.primary)};
color: ${theme.color.white};
background-color: ${({ disabled, color }) =>
disabled ? theme.color.gray2 : color === "gray" ? theme.color.white : theme.color.primary};
color: ${({ color }) => (color === "gray" ? theme.color.gray2 : theme.color.white)};
box-shadow: ${({ isShadow }) => (isShadow ? "0px 2px 2px 0px #00000033" : "none")};
`;
export default Button;
136 changes: 87 additions & 49 deletions gamgyul-front/src/components/common/Modal/index.jsx
Original file line number Diff line number Diff line change
@@ -1,73 +1,111 @@
import { StyledBody2Gray } from "../../../pages/MapDetailPage";
import { useState } from "react";
import styled from "styled-components";
import { theme } from "../../../style/theme";
import Button from "../Button";
import { styled } from "styled-components";
import { Link } from "react-router-dom";
import { applyFontStyles } from "../../../utils/fontStyles";
import Button from "../Button";

const Modal = ({ onClose, onClick, type }) => {
const [routeValue, setRouteValue] = useState("");
const isSaveButtonDisabled = type === "SAVE" && routeValue.trim() === "";
// 경로 삭제일 때 : 확인 => 경로 삭제 api 요청 / 취소 => 모달 닫기
// 경로 저장일 때 : 확인 => 경로 저장 api 요청 / 취소 => 모달 닫기

const Modal = ({ onClose }) => {
return (
<StyledOverlay>
<StyledModal>
<StyledBody1Text>You got a stamp!</StyledBody1Text>
<StyledStampWrap>
<img src="images/Stamp/stamp.svg" />
<StyledBody2Gray>영실기암</StyledBody2Gray>
</StyledStampWrap>
<Link to="/complete">
<Button type="small" onClick={onClose}>
Next
</Button>
</Link>
</StyledModal>
</StyledOverlay>
<ModalOverlayContainer>
<ModalContents>
{type === "DELETE" && <ModalDeleteH2>경로를 삭제 하시겠어요?</ModalDeleteH2>}
{type === "SAVE" && (
<ModalRoutesSection>
<h2>경로 이름</h2>
<p>경로를 저장하려면 이름이 필요합니다.</p>
<StyledInputBox
type="text"
id="route-input"
value={routeValue}
placeholder="이름을 입력해주세요."
onChange={(event) => setRouteValue(event.target.value)}
/>
</ModalRoutesSection>
)}
<div>
<StyledModalBtn type="small" onClick={onClose} color="gray">
취소
</StyledModalBtn>
<StyledModalBtn type="small" onClick={() => onClick(routeValue)} disabled={isSaveButtonDisabled}>
확인
</StyledModalBtn>
</div>
</ModalContents>
</ModalOverlayContainer>
);
};

/** body1 텍스트 스타일링 */
export const StyledBody1Text = styled.span`
${applyFontStyles(theme.font.body1)}
const ModalDeleteH2 = styled.h2`
width: 100%;
padding: 0 8px;
margin-top: 80px;
box-sizing: border-box;
text-align: center;
`;

/** 오버레이 스타일링 */
const StyledOverlay = styled.div`
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.3);
const ModalOverlayContainer = styled.div`
position: fixed;
height: 100%;
width: 100%;
max-width: ${theme.maxWidth};
display: flex;
justify-content: center;
align-items: center;
z-index: 999;
z-index: 9999;
background: #00000066;
`;

/** 모달 스타일링 */
const StyledModal = styled.div`
margin: 0 auto;
text-align: center;
width: 300px;
height: 300px;
padding: 20px;
border-radius: 10px;
const ModalContents = styled.div`
width: 100%;
min-height: 252px;
border-radius: 20px;
padding: 14px 16px;
box-sizing: border-box;
box-shadow: 0px 2px 10px 0px #0000001a;
max-width: calc(${theme.maxWidth} - 88px);
background-color: ${theme.color.white};
box-shadow: 0px 3.39px 16.94px 0px #0000001a;

display: flex;
flex-direction: column;
justify-content: space-between;

h2 {
${applyFontStyles(theme.font.subtitle)}
}

Button:last-child {
margin-right: 0;
}
`;

const StyledStampWrap = styled.div`
display: flex;
flex-direction: column;
align-items: center;
const StyledModalBtn = styled(Button)`
width: calc(50% - 4px);
margin-right: 8px;
`;

const ModalRoutesSection = styled.section`
margin: 10px 8px;
p {
${applyFontStyles(theme.font.body3)}
margin: 4px 0 28px 0;
}
`;

const StyledInputBox = styled.input`
${applyFontStyles(theme.font.body2)}
width: 100%;
height: 42px;
border: none;
border-bottom: 1px solid ${theme.color.primary};
box-sizing: border-box;
padding: 10px;

*:nth-child(1) {
width: 128px;
height: 128px;
margin-bottom: 8px;
&::placeholder {
color: ${theme.color.gray2};
}
`;

Expand Down
31 changes: 18 additions & 13 deletions gamgyul-front/src/components/common/NavigationBar/index.jsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,40 @@
import { useState } from "react";
import { Link } from "react-router-dom";
import { useEffect, useState } from "react";
import { Link, useLocation, useParams } from "react-router-dom";
import styled from "styled-components";
import { theme } from "../../../style/theme";
import { applyFontStyles } from "../../../utils/fontStyles";

const NavigationBar = () => {
const [activeTab, setActiveTab] = useState("map");
const location = useLocation();
const [activeTab, setActiveTab] = useState(location.pathname);

useEffect(() => {
setActiveTab(location.pathname);
}, [location.pathname]);

const handleTabClick = (tab) => {
setActiveTab(tab);
};

return (
<NaviContainer>
<NavbarLink to="/complete" onClick={() => handleTabClick("map")}>
<NavbarLink to="/complete" onClick={() => handleTabClick("/map")}>
<NaviBtn
src={activeTab === "map" ? "/src/assets/NavigationBar/mapOn.svg" : "/src/assets/NavigationBar/mapOff.svg"}
src={activeTab === "/map" ? "/src/assets/NavigationBar/mapOn.svg" : "/src/assets/NavigationBar/mapOff.svg"}
/>
<NaviText $active={activeTab === "map"}>Map</NaviText>
<NaviText $active={activeTab === "/map"}>Map</NaviText>
</NavbarLink>
<NavbarLink to="/detail" onClick={() => handleTabClick("home")}>
<NavbarLink to="/home" onClick={() => handleTabClick("/home")}>
<NaviBtn
src={activeTab === "home" ? "/src/assets/NavigationBar/homeOn.svg" : "/src/assets/NavigationBar/homeOff.svg"}
src={activeTab === "/home" ? "/src/assets/NavigationBar/homeOn.svg" : "/src/assets/NavigationBar/homeOff.svg"}
/>
<NaviText $active={activeTab === "home"}>Home</NaviText>
<NaviText $active={activeTab === "/home"}>Home</NaviText>
</NavbarLink>
<NavbarLink to="/detail2" onClick={() => handleTabClick("trip")}>
<NavbarLink to="/trip" onClick={() => handleTabClick("/trip")}>
<NaviBtn
src={activeTab === "trip" ? "/src/assets/NavigationBar/tripOn.svg" : "/src/assets/NavigationBar/tripOff.svg"}
src={activeTab === "/trip" ? "/src/assets/NavigationBar/tripOn.svg" : "/src/assets/NavigationBar/tripOff.svg"}
/>
<NaviText $active={activeTab === "trip"}>My Trip</NaviText>
<NaviText $active={activeTab === "/trip"}>My Trip</NaviText>
</NavbarLink>
</NaviContainer>
);
Expand All @@ -40,7 +45,7 @@ const NaviContainer = styled.div`
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 100%;
width: ${theme.maxWidth};
display: flex;
justify-content: space-around;
background-color: #f6faed;
Expand Down
Loading