티스토리 뷰

App.js

import React, { Component } from "react";
import './App.css'
import Header from "./Header";
import Cardlist from './Cardlist' 

class App extends Component{
  state = {
    serverData : [],
    flag : true,
    filteredData: [],
    enterSignal : true 
  }
// 검색하기  
  searchItem = (keyWord) => { // 검색어를 내려줘야한다
    // e.preventDefault()
    const { serverData, filteredData } = this.state
    this.setState( prevState => ({
      filteredData : serverData.filter(data =>  [data.brand, data.price, data.name, data.description].some(item =>
      item.toLowerCase().includes(keyWord)))}))
    console.log(filteredData)
}
// 가격별 오름차순, 내림차순 정렬하기
  sortItem = () => {
    const { serverData, filteredData } = this.state

    const selectData = filteredData.length > 0 ? filteredData : serverData
    this.setState(prevState => ({
      flag: !prevState.flag,
      filteredData: [...selectData].sort((a, b) =>
        prevState.flag ? a.price - b.price : b.price - a.price
      )
    }));
  }

  handleState = (trans) => {
    this.setState({ enterSignal : trans })
  }

  componentDidMount(){
    const API_URL = 'http://makeup-api.herokuapp.com/api/v1/products.json?brand=maybelline'
    fetch(API_URL)
    .then(res => res.json())
    .then(data => { this.setState({ serverData: data })})
    // console.log(this.state.searchResult)
  }
  

  render(){
    const { serverData, filteredData, enterSignal } = this.state
    // console.log(this.state.serverData, this.state.flag) // 디버깅용
    return(
      <>
      <Header
      handleClick={this.sortItem}
      serverData={serverData}
      searchClick={this.searchItem}
      enterSignal = {this.handleState}
      filteredData={filteredData}
      ></Header>
      <main>
        <Cardlist
        key = {serverData.id}
        products = {serverData}
        filterProducts = {filteredData}
        enterSignal = {this.handleState}
        ></Cardlist>
        
      </main>
      </>
    )
  }
}

export default App

Header.js

import React, { Component } from "react";
import './Header.css'
import Search from './Search.js'
import Button from "./Button";

class Header extends Component{
 state = {
  keyWord : ''
 }

 onSearch = (e) => {
  const { keyWord } = this.state 
  const { searchClick, enterSignal } = this.props
  // if (/\n/.test(e.target.value)) 검색어 중에 enter 키가 있는지 찾는 정규표현식
  // console.log(e.key)

  if(e.key !== 'Backspace'){
  if (e.key === 'Enter' && e.target.value.length > 1){
    // 검색하기
    enterSignal(false)
    this.setState({  
      keyWord : e.target.value.toLowerCase() 
    })
    searchClick(keyWord)
  }else if(e.key === 'Enter' && e.target.value.length === 1){
    alert('검색어를 2자 이상 입력해주세요')
  }else if(e.target.value === ''){
    alert('검색어를 입력해주세요')
  }else{
      enterSignal(true)
      this.setState({ keyWord : e.target.value })  
  }
}
 }
  

render(){
  const { keyWord, onSearch } = this.state
  const { handleClick, searchClick, handleState, filteredData } = this.props
  // console.log( keyWord)

  return (
    <header>
      <Search 
       inputEnter={(e) => this.onSearch(e)} 
       searchWord={keyWord}
      ></Search>
      <Button handleClick={handleClick}>가격별정렬</Button>
    </header>
  );
}
}

export default Header;

Search.js

import React from "react";
import './Search.css'

function Search({inputEnter,searchWord}){
    // console.log(searchWord)
    return(
       <form action="#">  
            <label> 
                <input type='search' placeholder="검색어를 입력하세요" onKeyUp={(e)=>inputEnter(e)} defaultValue={searchWord}></input>
            </label>
        </form>
    )
}

export default Search

Button.js

import './Button.css'

function Button({children, handleClick}){ //props

 return <button className={`Button`} onClick={handleClick}>{children}</button>
}
export default Button

Cardlist.js

import React from "react";
import './Cardlist.css'
import Card from "./Card";


function Cardlist({products, filterProducts, enterSignal}){ //props
    const newResults = filterProducts?.length > 0 ? filterProducts : products 
  return (
        <div className="card-list">
        {
       
       newResults?.map(product => 
              <Card
                key={product.id}
                brand={product.brand}
                image={product.image_link}
                name={product.name}
                price={product.price}
                description={product.description}
                >
              </Card>
        )
        }     
      </div>

        )
}

export default Cardlist

        // { reuturn } = ()  // 중괄호 안에 return 을 쓰는것과 ()괄호로 감싸주는것과 같은 결과가 나온다

Card.js

import React from "react";
import './Card.css'

function Card({ brand, image, name, price, description}){
    return(
     <>   
         <div className="product">
             <div className="product-img">
                <img src={image} alt={name}></img>
              </div>
                <div className="product-name"><h3>{brand}{name}({price})</h3></div>
                <div className="product-description">{description}</div>
            </div>
    </>
)
}

export default Card

Card.css

.product{
    flex: 200px;
    height: 500px;
    box-shadow: 1px 1px 5px 5px peru;
    color: white;
    background: peru;
    margin: 10px;
    overflow: hidden;
}
.product-img{
    width: 100%;
    height: 180px;
    overflow: hidden;
  }
  .product-img img{
    width: 100%;
    height: 100%;
  }
  .product-name{
    font-weight: bold;
    font-size: 1.1rem;
    text-align: center;
  }
  .product-description{
    font-weight: 400;
    font-size: 0.9rem;
    text-align: center;
    margin-top: 15px;
  }

Cardlist.css

.card-list{
    width: 60%;
    margin: 100px auto;
    
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
}

Header.css

 

header{
    width: 100%;
    height: 70px;
    position: fixed;
    left: 0;
    top: 0;
    right: 0;
    box-shadow: 1px 1px 5px 5px darkgray;
    background: white;
    z-index: 1;
  
    display: flex;
    justify-content: flex-end;
    align-items: center;
  }

Button.css

.Button{
    all: unset;
    width: 100px;
    height: 50px;
    background: peru;
    border-radius: 10px;
    cursor: pointer;
    color: white;
    font-size: 1rem;
    font-weight: bold;
    text-align: center;
    margin-right: 10px;
}
.Button:hover{
    background-color: rgb(255, 136, 0);
    opacity: 0.8;
}