TIL_60_2차 프로젝트 Nav 와 검색 모달창
네브 바와 검색 모달창에 대해 간단한 리뷰를 남겨보겠다.
- 네브 바에서 검색 인풋창을 클릭하면 검색 모달창이 뜨도록 구현했다.
- 검색 모달창의 이미지들에 호버효과도 추가했다.
(우리 팀원들의 사진은 보너스~~) - api 통신을 통해 영어 이름 과 한글 이름 둘 다로 가능하며, 10개씩 데이터를 fetch.
- 네브 바의 로고와 shop 을 누르면 메인페이지로 이동되도록 구현.
- 로그인을 누를 시 로그인 페이지로 이동.
//Nav.js
import React from "react";
import { Link } from "react-router-dom";
import SearchModal from "./SearchModal";
import styled from "styled-components";
import { FaSearch } from "react-icons/fa";
class Nav extends React.Component {
constructor() {
super();
this.state = {
modalOn: false,
};
}
handleSearchModal = () => {
this.setState({ modalOn: !this.state.modalOn });
};
render() {
return (
<WrapNav>
<NavContainer>
<Logo>
<Link to="/">HEUREAM</Link>
</Logo>
<FaSearch size="30" color="lightgray" />
{this.state.modalOn && (
<SearchModal
handleSearchModal={this.handleSearchModal}
modalOn={this.state.modalOn}
/>
)}
<SearchInput
type="text"
placeholder="브랜드명, 모델명, 모델번호 등"
onClick={this.handleSearchModal}
/>
<ListContainer>
<Ul>
<Li>
<Link to="/">SHOP</Link>
</Li>
<Li>고객센터</Li>
<Li>
<Link to="/login">로그인</Link>
</Li>
</Ul>
</ListContainer>
</NavContainer>
</WrapNav>
);
}
}
export default Nav;
const WrapNav = styled.div`
position: fixed;
z-index: 1000;
width: 100%;
height: 90px;
background-color: white;
`;
const NavContainer = styled.div`
display: flex;
justify-content: center;
align-items: center;
height: 90px;
padding: 0 32px 0 40px;
`;
const Logo = styled.h1`
width: 150px;
height: 24px;
font-size: 25px;
font-weight: bold;
font-family: "Fugaz One", cursive;
`;
const SearchInput = styled.input`
width: 800px;
height: 40px;
cursor: text;
border-radius: 8px;
background-color: rgb(244, 244, 244);
&::placeholder {
font-size: 13px;
color: gray;
padding-left: 10px;
}
`;
const ListContainer = styled.nav`
width: 187px;
height: 38px;
margin-left: 10px;
`;
const Ul = styled.ul`
margin: 0;
`;
const Li = styled.li`
display: list-item;
float: left;
margin: 10px 0 0 17px;
font-size: 13px;
`;
//SearchModal.js
import React from "react";
import SearchDataList from "./SearchDataList";
import styled from "styled-components";
import { FaSearch } from "react-icons/fa";
// `http://127.0.0.1:8000/product/search?q=${keyword}`
// "data/SearchList.json"
class SearchModal extends React.Component {
constructor() {
super();
this.state = {
keyWord: "",
keyWordList: [],
};
}
keyWordInput = e => {
this.setState({
keyWord: e.target.value,
});
this.filterKeyword(e);
};
// keyWordDelete = () => {
// this.setState({
// keyWord: "",
// });
// };
filterKeyword = e => {
let keyword = e.target.value;
if (keyword === "") {
keyword = "나이키";
}
fetch(`http://10.58.7.188:8000/product/search?q=${keyword}`)
.then(res => res.json())
.then(res =>
this.setState({
keyWordList: res.result,
})
);
};
render() {
return (
<WrapSearchModal>
<SearchWrap>
<FaSearch size="30" color="lightgray" />
<SearchInput
type="text"
placeholder="브랜드명, 모델명, 모델번호 등"
onChange={this.keyWordInput}
value={this.state.keyWord}
/>
{this.props.modalOn ? (
<CancleBtn onClick={this.props.handleSearchModal}>취소</CancleBtn>
) : null}
</SearchWrap>
{this.state.keyWord ? (
<SearchDataList keyWordList={this.state.keyWordList} />
) : (
<ImgArea>
<BrandList>
{BRANDLIST.map(brand => (
<Brand id={brand.id} key={brand.id}>
<BrandImg alt={brand.name} src={brand.img} />
<BrandName>{brand.name}</BrandName>
</Brand>
))}
</BrandList>
</ImgArea>
)}
</WrapSearchModal>
);
}
}
export default SearchModal;
const WrapSearchModal = styled.div`
position: fixed;
top: 0;
right: 0;
left: 0;
bottom: 0;
height: auto;
background-color: rgba(34, 34, 34, 0.5);
overflow-y: auto;
`;
const SearchWrap = styled.div`
display: flex;
justify-content: center;
padding: 0 32px 0 40px;
min-width: 320px;
width: 100%;
height: 90px;
align-items: center;
background-color: white;
`;
const SearchInput = styled.input`
width: 600px;
height: 40px;
cursor: text;
border-radius: 8px;
background-color: rgb(244, 244, 244);
&::placeholder {
font-size: 13px;
color: gray;
padding-left: 10px;
}
`;
const CancleBtn = styled.button`
background-color: white;
font-size: 11px;
`;
const ImgArea = styled.div`
background-color: white;
`;
const BrandList = styled.div`
display: flex;
justify-content: center;
width: 100%;
height: 140px;
text-align: center;
cursor: pointer;
`;
const Brand = styled.div`
width: 100px;
height: 100px;
align-items: center;
margin-left: 15px;
border-radius: 8px;
background-color: rgb(246, 238, 237);
&:hover {
cursor: pointer;
border: 3px solid white;
}
`;
const BrandImg = styled.img`
width: 80px;
height: 80px;
margin-left: 10px;
border-radius: 8px;
`;
const BrandName = styled.p`
margin-top: 5px;
font-size: 10px;
`;
const BRANDLIST = [
{
id: 1,
name: "Jordan 1",
img:
"https://media.vlpt.us/images/poohv7/post/32f43b4c-7dbd-4708-afc0-7d3a189747d3/%EC%BA%A1%EC%B2%985.JPG",
},
{
id: 2,
name: "꼼데가르송",
img:
"https://media.vlpt.us/images/poohv7/post/062eace6-d549-47b5-98f3-aa6e1809805e/%EC%BA%A1%EC%B2%981.JPG",
},
{
id: 3,
name: "IAB",
img:
"https://media.vlpt.us/images/poohv7/post/5d647b26-8e67-464b-9c2e-b455d0e427ed/%EC%BA%A1%EC%B2%982.JPG",
},
{
id: 4,
name: "마르지엘라",
img:
"https://media.vlpt.us/images/poohv7/post/34d9f7e2-0921-46bc-aacc-6a33a85781c5/KakaoTalk_20210225_133012878.jpg",
},
{
id: 5,
name: "메종키츠네",
img:
"https://media.vlpt.us/images/poohv7/post/b906e5e9-b55b-4d38-b3b6-03367afdacf5/%EC%BA%A1%EC%B2%983.JPG",
},
{
id: 6,
name: "뉴발란스",
img:
"https://media.vlpt.us/images/poohv7/post/fa37e960-03cd-4a79-81a9-9499089259aa/%EC%BA%A1%EC%B2%984.JPG",
},
];
//SearchDataList.js
import React from "react";
import styled from "styled-components";
import { Link } from "react-router-dom";
class SearchDataList extends React.Component {
render() {
return (
<DataList>
{this.props.keyWordList.length === 0 ? (
<NoResult>검색결과가 없습니다.</NoResult>
) : (
<SearchResult>
{this.props.keyWordList.map(data => (
<Li key={data.product_id}>
<div>
<Img src={data.product_image_url} alt={data.korean_name} />
</div>
<div>
<div>{data.korean_name}</div>
<div>{data.english_name}</div>
</div>
<Link to={`/product/search?q=${data.product_id}`}></Link>
</Li>
))}
</SearchResult>
)}
</DataList>
);
}
}
export default SearchDataList;
const DataList = styled.div`
width: 100%;
border-top: 1px solid lightgray;
background-color: white;
`;
const NoResult = styled.div`
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
color: rgb(154, 154, 158);
`;
const SearchResult = styled.div`
padding: 16.5px 0px 46px;
`;
const Li = styled.div`
display: flex;
padding: 6.5px 20px;
font-size: 11px;
border-bottom: 1px solid rgb(235, 235, 235);
line-height: 1.5;
`;
const Img = styled.img`
width: 70px;
height: 70px;
border-radius: 8px;
`;
Author And Source
이 문제에 관하여(TIL_60_2차 프로젝트 Nav 와 검색 모달창), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@poohv7/TIL602차-프로젝트-Nav-와-검색-모달창저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)