React에서 값을 입력받아 해당하는 값을 보여주기

ahncheer·2023년 4월 12일
0

React

목록 보기
10/12

init했을때도 실행하고 싶은데, 방법을 찾지 못해 생략했습니다.

화면 미리보기

코드 작성 - MapShortCut.js

import { useState } from 'react';
import './MapShortCut.css';

/* ---- PersonSelect ---- */
function PersonSelect(props) {
    const lis = [];
    for(let i = 0; i < props.list.length; i++){
        let t = props.list[i];
        lis.push(<label key={t.value}>
            <input
                type="radio"
                value={t.value}
                checked={props.num === t.value}
                onChange={event=>{
                    props.onChangeMode(event.target.value);
                }}
            />{t.label}
        </label>);
    }
    return  <div className='person-select' key={props}>{lis}</div>
}

function PersonHeight(props) {
    console.log('---- props.hValue : ', props.hValue);
    const userHeight = {
        one: props.hValue.one,
        two: props.hValue.twoMin,
        three: props.hValue.twoMax
    };
    
    const onChangeInput = (e) => {
            userHeight[e.target.name] = e.target.value;
            
            let x = {
                one: Number(userHeight.one),
                twoMin: Number(userHeight.two),
                twoMax: Number(userHeight.three),
            };
            console.log('x : ', x);
            props.onChangeMode(x);
    }
    
    let content = [];
    if(props.num === 'one'){
        content = (
            <div className='person-height' key={props.num}>
                <p>탑승자의 키 : <input name="one" value={userHeight.one} onChange={onChangeInput}/></p>
            </div>
        )
    }else{
        content= ( <div className='person-height' key={props.num}>
            <p>탑승자의 최소키 : <input name="two" value={userHeight.two} onChange={onChangeInput}/></p>
            <p>탑승자의 최대키 : <input name="three" value={userHeight.three} onChange={onChangeInput}/></p>
        </div>);
    }
    return content
}


function MapShortCut(){
    
    const [totalType, setTotalType] = useState("one");
    const [totalTypeList, setTotalTypeList] = useState([
        {value : 'one', label : '1인'},
        {value : 'other', label : '2인 이상'}
    ]);

    // 최대값을 임의로 250으로 설정했습니다. 
    const amuseRides = [
        {name : '회전목마', minHeight: 100, maxHeight : 250},
        {name : '어린이 범퍼카', minHeight: 110, maxHeight : 140},
        {name : '풍선 비행', minHeight: 110, maxHeight : 120},
        {name : '파라오의 분노', minHeight: 110, maxHeight : 195},
        {name : '자이로스핀', minHeight: 130, maxHeight : 250},
        {name : '자이로스윙', minHeight: 130, maxHeight : 190},
        {name : '번지드롭', minHeight: 130, maxHeight : 200},
        {name : '범퍼카', minHeight: 140, maxHeight : 250},
        {name : '아틀란티스', minHeight: 135, maxHeight : 190}
    ];
    
    const [userRides, setUserRides] = useState([]);
    const userRideList = (value) => {
        let newList = [];
        if(totalType === 'one'){
            newList = amuseRides.filter(el => (el.minHeight <= value.one && value.one <= el.maxHeight) );
        }else{
            const lessNum  = value.twoMax < value.twoMin ? value.twoMax : value.twoMin;
            const moreNum  = value.twoMax < value.twoMin ? value.twoMin : value.twoMax;
            console.log('lessNum : ', lessNum, ', moreNum : ', moreNum);
            newList = amuseRides.filter(el => (el.minHeight <= lessNum && moreNum <= el.maxHeight) );
        }
        console.log('▶ newList : ', newList);
        setUserRides(newList);
    }
    
    let [heightValue, setHeightValue] = useState({
        one : 0,
        twoMin : 0,
        twoMax : 0
    });

    const rideContent = [];
    if(userRides.length === 0){
        rideContent.push(<div className='no-res'><p>키를 입력해주세요.</p></div>);
    }else{
        userRides.map((item, idx) => {
            rideContent.push(
                <div className='ride-wrap'>
                    <p>{item.minHeight} - {item.maxHeight}</p>
                    <p>{item.name}</p>
                </div>);
        });
    }
    
    return(
        <div className="wrapper">
            <h3 className="page-title">탑승가능 놀이기구</h3> 

            <div className="form-wrap layout">
                <div className='filter-wrap'>
                    <dl>
                        <dt>인원수</dt>
                        <dd><PersonSelect list={totalTypeList} num={totalType} onChangeMode={(value)=>{
                            console.log('onChangeMode > value : ', value);
                            setTotalType(value);
                            setHeightValue({ one : 0, twoMin : 0, twoMax : 0 });
                        }}></PersonSelect></dd>
                    </dl>
                    <dl>
                        <dt></dt>
                        <dd>
                            <PersonHeight num={totalType} hValue={heightValue} onChangeMode={(value)=>{
                                console.log('PersonHeight > value : ', value);
                                setHeightValue(value);
                            }}></PersonHeight>
                        </dd>
                    </dl>
                    <dl className='search-area'>
                        <dd>
                        <button onClick={ e =>{ 
                                userRideList(heightValue);
                            }}>검색</button>
                        </dd>
                    </dl>
                </div>

                <div className='ride-result-wrap'>
                    {userRides.length > 0 ? <p className='total-num'>총 {userRides.length}개</p> : ''} 
                <div className='ride-result'>{rideContent}</div>
                </div>
            </div>
        </div>

    )
}
export default MapShortCut;

const userRideList가 추가되었고, 조건에 맞는 놀이기구를 출력하는 rideContent부분이 추가되었습니다.

코드 작성 - MapShortCut.js

/* filter-wrap */
.form-wrap .filter-wrap{
    display: block;
    margin: 0 auto;
    padding: 20px;
    background-color: #eceef2;
    border-radius: 10px;
}

.filter-wrap dl {
    display: flex;
    font-size:  18px;
    color: #282828;
}

.filter-wrap dl dt {
    min-width: 100px;
    position: relative;
}
.filter-wrap dl dt:after {
    content: '';
    width: 1px;
    height: 80%;
    position: absolute;
    background-color: #a9aeae;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
}
.filter-wrap dd {
    margin-inline-start: 20px;
}
.person-select{
    display: flex;
    gap: 15px;
}
.person-height{
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.search-area{
    justify-content: flex-end;
    margin-bottom: 0;
}
.search-area button{
    width: 150px;
    height: 36px;
    background-color: #534c4c;
    border: none;
    color: #FFF;
    border-radius: 5px;
    font-size: 16px;
    font-weight: 500;
    cursor: pointer;
}
/* ride-result */
.ride-result-wrap{
    display: block;
    margin: 40px auto 0;
}
.ride-result .no-res{
    height: 300px;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: #fff0f0;
    font-size: 24px;
    color: #534545;
    grid-column: 1/4;
}

/* filter-wrap */
.ride-result-wrap .total-num{
    font-size: 14px;
    padding-bottom: 10px;
}

.ride-result{
    border-top: 1px solid #ddd;
    border-bottom: 1px solid #ddd;
    padding: 20px 10px;

    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 30px;
}

.ride-result .ride-wrap {
    padding: 20px;
    background-color: #f3f3f4;
    border-radius: 5px;
    box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
}

화면 확인

값을 입력하고 검색을 누른 경우에만 놀이기구 필터가 작동하도록 했습니다.

profile
개인 공부 기록용.

0개의 댓글