-
OnlineShop 만들기 - 6) Landing Page 만들기 3(check 필터링, price 필터링 만들기)NODE.JS 2021. 5. 15. 22:03
순서 체크한 나라에 관한 (continents) 자료들만 로드되도록 한다.
checkbox에 관한 내용들은 sections폴더안에 따로 생성한다.
src>components>views>LandingPage>Sections>CheckBox.js파일을 생성한다.
import React from 'react' import { Checkbox, Collapse } from 'antd'; const continents = [ { "_id": 1, "name": "Africa" }, { "_id": 2, "name": "Europe" }, { "_id": 3, "name": "Asia" }, { "_id": 4, "name": "North America" }, { "_id": 5, "name": "South America" }, { "_id": 6, "name": "Australia" }, { "_id": 7, "name": "Antarctica" } ] function CheckBox() { return ( <div> <Collapse defaultActiveKey={['0']} > <Panel header key="1"> <React.Fragment key={index}> <Checkbox onChange type checked /> <span>{value.name}</span> </React.Fragment> )) </Panel> </Collapse> </div> ) }
랜딩페이지안에도 넣어준다.
import CheckBox from './Sections/CheckBox'; {/* Filter */} <CheckBox />
현재상태 onChange Function을 만들어보자.
import React ,{useState} from 'react' import { Checkbox, Collapse } from 'antd'; function CheckBox(props) { const [Checked, setChecked] = useState([])//어떤걸 체크했는지 배열에 넣어서 알려준다. const handleToggle = (value) => {//어떤 체크박스를 넣어줄건지 value를 준다. const currentIndex = Checked.indexOf(value);//체크된 것의 인덱스를 가져온다. const newChecked = [...Checked]; //체크된것들 if (currentIndex === -1) {//체크가 안되어 있었으면 newChecked.push(value)//가져올 checked에 값을 추가한다. } else {//이미 체크가 되어있으면 newChecked.splice(currentIndex, 1)//체크에서 제외해준다. } setChecked(newChecked)//새로 체크 변화된 것 다시 한번 세팅 props.handleFilters(newChecked)//변화된것 부모에게 전달해준다. //update this checked information into Parent Component } const renderCheckboxLists = () => props.list && props.list.map((value, index) => ( <React.Fragment key={index}> <Checkbox onChange={() => handleToggle(value._id)}//체크 표시 type="checkbox" checked={Checked.indexOf(value._id) === -1 ? false : true}//체크 여부(되지않으면 -1, 되어있으면 !=-1)에 따라서 checked 가 true, false /> <span>{value.name}</span> </React.Fragment> )) return ( <div> <Collapse defaultActiveKey={['0']} > <Panel header="Continents" key="1"> {renderCheckboxLists()} </Panel> </Collapse> </div> ) }
여기서 부모에게 전달해줄 handletoggle함수는 부모가 가지고 있어야 하므로
랜딩페이지에 구현해준다.
순서 const [Filters, setFilters] = useState({//두가지의 필터를 가지고 있다. continents: [], price: [] }) const showFilteredResults = (filters) => {//필터링한 결과를 가지고 온다. const variables = { skip: 0,//체크박스를 새로 설정하면 처음부터 다시 보여줘야 한다. limit: Limit, filters: filters } getProducts(variables)//결과를 가져오기 위해서 getProducts사용한다. setSkip(0) } const handleFilters = (filters, category) => {//체크된것들에 변화가 있으면 새로 받아오는 것(자식으로 부터 변화 받아오는 함수 ) //체크가 된다면 배열 안에 체크된 인덱스 번호가 추가될 것이다. const newFilters = { ...Filters }//새로운 필터만들고 newFilters[category] = filters//해당카테고리의 필터는 입력된 filters가 될 것이다. if (category === "price") { } console.log(newFilters) //필터링한 결과를 세팅해준다. showFilteredResults(newFilters) //필터의 상태를 새로운 필터로 바꿔준다. setFilters(newFilters) } {/* Filter */} <CheckBox handleFilters={filters => handleFilters(filters, "continents")} />
getproducts 라우터에서 필터링에 따라서 가져오는 종류가 달라질 수 있도록 수정해준다.
router.post("/getProducts", (req, res) => { //variables가 있을때와 없을 때를 나눈다. let order = req.body.order ? req.body.order : "desc"; let sortBy = req.body.sortBy ? req.body.sortBy : "_id"; let limit = req.body.limit ? parseInt(req.body.limit) : 100; let skip = parseInt(req.body.skip); let findArgs = {}; for (let key in req.body.filters) { //필터에 따라서 if (req.body.filters[key].length > 0) { if (key === "price") { } } else {//키가 price가 아니라면 findArgs[key] = req.body.filters[key];//findArgs[continents] = [인덱스 배열]의 형태 } } } Product.find(findArgs) .populate("writer") .sort([[sortBy, order]]) .skip(skip) .limit(limit) .exec((err, products) => { if (err) return res.status(400).json({ success: false, err }) res.status(200).json({ success: true, products, postSize: products.length }) }) });
이제 가격에 의한 필터링을 만들어보자.
순서 체크박스 component처럼 라디오 박스 component를 만들어준다.
src>component>views>Sections>RadioBox.js파일
import React from 'react' import { Collapse, Radio } from 'antd'; const { Panel } = Collapse; const price = [ { "_id": 0, "name": "Any", "array": [] }, { "_id": 1, "name": "$0 to $199", "array": [0, 199] }, { "_id": 2, "name": "$200 to $249", "array": [200, 249] }, { "_id": 3, "name": "$250 to $279", "array": [250, 279] }, { "_id": 4, "name": "$280 to $299", "array": [280, 299] }, { "_id": 5, "name": "More than $300", "array": [300, 1500000] } ] function RadioBox() { const [Value, setValue] = useState('0') const renderRadioBox = () => ( props.list && props.list.map((value) => ( <Radio key={value._id} value={`${value._id}`}>{value.name}</Radio> )) ) return ( <div> <Collapse defaultActiveKey={['0']}> <Panel header="price" key="1"> <Radio.Group onChange value> {renderRadioBox()} </Radio.Group> </Panel> </Collapse> </div> ) } export default RadioBox
랜딩페이지에도 추가해준다.
import RadioBox from './Sections/RadioBox'; {/* Filter */} <RadioBox handleFilters={filters => handleFilters(filters, "price")} />
antd를 이용해서 col, row디자인을 준다.
{/* Filter */} <Row gutter={[16, 16]}> <Col lg={12} xs={24} > <CheckBox list={continents} handleFilters={filters => handleFilters(filters, "continents")} /> </Col> <Col lg={12} xs={24}> <RadioBox list={price} handleFilters={filters => handleFilters(filters, "price")} /> </Col> </Row>
RadioBox 에 onChange Function을 만들어준다.
const [Value, setValue] = useState('0')//id가 0부터 시작하니까 const handleChange = (event) => { setValue(event.target.value) props.handleFilters(event.target.value)//부모컴포넌트로 보내준다. } return ( <div> <Collapse defaultActiveKey={['0']}> <Panel header="price" key="1"> <Radio.Group onChange={handleChange} value={Value}> {renderRadioBox()} </Radio.Group> </Panel> </Collapse> </div> ) }
handleFilter Function을 만들어보자.
순서 먼저 가격정보랑 continents 정보를 담았던 CheckBox, RadioBox에서 정보들만 따로 모으자.
Sections>Datas.js파일을 만든다.
const price = [ { "_id": 0, "name": "Any", "array": [] }, { "_id": 1, "name": "$0 to $199", "array": [0, 199] }, { "_id": 2, "name": "$200 to $249", "array": [200, 249] }, { "_id": 3, "name": "$250 to $279", "array": [250, 279] }, { "_id": 4, "name": "$280 to $299", "array": [280, 299] }, { "_id": 5, "name": "More than $300", "array": [300, 1500000] } ] const continents = [ { "_id": 1, "name": "Africa" }, { "_id": 2, "name": "Europe" }, { "_id": 3, "name": "Asia" }, { "_id": 4, "name": "North America" }, { "_id": 5, "name": "South America" }, { "_id": 6, "name": "Australia" }, { "_id": 7, "name": "Antarctica" } ] export { price, continents }
랜딩페이지에 둘다 임포트 해준다.
import { continents, price } from './Sections/Datas';
각각 CheckBox, RadioBox에는 props로 보내주자.
{/* Filter */} <Row gutter={[16, 16]}> <Col lg={12} xs={24} > <CheckBox list={continents}//filter보내준다. handleFilters={filters => handleFilters(filters, "continents")} /> </Col> <Col lg={12} xs={24}> <RadioBox list={price}//filter보내준다. handleFilters={filters => handleFilters(filters, "price")} /> </Col> </Row>
//각각 radiobox, checkbox도 props.list로 변경해준다. const renderRadioBox = () => ( props.list && props.list.map((value) => ( <Radio key={value._id} value={`${value._id}`}>{value.name}</Radio> )) ) const renderCheckboxLists = () => props.list && props.list.map((value, index) => (
랜딩페이지에서 handleFilters함수에 다음 내용을 추가한다.
const handlePrice = (value) => {//가격 조정함수 const data = price; let array = []; for (let key in data) {//데이터 안의 키들 if (data[key]._id === parseInt(value, 10)) {// key는 가격이 아니라 인덱스, value는 string으로 되어있는데 이를 int로 바꿔준다. array = data[key].array; } } console.log('array', array) return array //가격[300, 1500]의 형태 } const handleFilters = (filters, category) => {//체크된것들에 변화가 있으면 새로 받아오는 것(자식으로 부터 변화 받아오는 함수 ) //체크가 된다면 배열 안에 체크된 인덱스 번호가 추가될 것이다. const newFilters = { ...Filters }//새로운 필터만들고 newFilters[category] = filters//해당카테고리의 필터는 입력된 filters가 될 것이다. if (category === "price") {//필터카테고리가 가격이라면 let priceValues = handlePrice(filters) newFilters[category] = priceValues//가격범위 지정 } console.log(newFilters) //필터링한 결과를 세팅해준다. showFilteredResults(newFilters) //필터의 상태를 새로운 필터로 바꿔준다. setFilters(newFilters) }
가격조정이라면 route가 다르게 행동하도록 다음과 같이 수정해준다.
for (let key in req.body.filters) { //필터에 따라서 if (req.body.filters[key].length > 0) { if (key === "price") { findArgs[key] = { $gte: req.body.filters[key][0],//greater than equal $lte: req.body.filters[key][1]//lower than equal } } else {//키가 price가 아니라면 findArgs[key] = req.body.filters[key];//findArgs[continents] = [인덱스 배열]의 형태 } } }
완성된 화면 'NODE.JS' 카테고리의 다른 글
OnlineShop 만들기 - 8) Product Detail Page 만들기1 (상품 이미지, 상품 설명란 만들기) (0) 2021.05.15 OnlineShop 만들기 - 7) Landing Page 만들기 4(Search feature 만들기) (0) 2021.05.15 OnlineShop 만들기 - 5) Landing Page 만들기 2(loadmore 버튼) (0) 2021.05.15 OnlineShop 만들기 - 4) Landing Page 만들기 1(상품리스트 가져오기) (0) 2021.05.15 OnlineShop 만들기 - 3)업로드 페이지에 onSubmit 기능 만들기 (0) 2021.05.15