StateAirlineClient 과제

Taehye.on·2023년 4월 3일
0

코드스테이츠 44기

목록 보기
47/89
post-thumbnail

D-34

🔍 PART 1

📌 Main.js

import { useEffect, useState } from 'react';
import FlightList from './component/FlightList';
import Search from './component/Search';
import json from '../resource/flightList'; 

export default function Main() {  // 항공편 검색 조건을 담고 있는 상태
  const [condition, setCondition] = useState({
    departure: 'ICN',
  });
  const [flightList, setFlightList] = useState(json);

  const search = ({ departure, destination }) => {  // 주어진 검색 키워드에 따라 condition 상태를 변경
    if (
      condition.departure !== departure ||
      condition.destination !== destination
    ) {
      //search 함수가 전달 받아온 '항공편 검색 조건' 인자를 condition에 담는다.
      setCondition({departure, destination});
    }
  };

  const filterByCondition = (flight) => {
    let pass = true;
    if (condition.departure) {
      pass = pass && flight.departure === condition.departure;
    }
    if (condition.destination) {
      pass = pass && flight.destination === condition.destination;
    }
    return pass;
  };
  return (
    <div>
      <Head>
        <title>States Airline</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main>
        <h1>여행가고 싶을 땐, States Airline</h1>
        <Search onSearch={search}/> //search 함수 => Search 컴포넌트
        <div className="table">
          <div className="row-header">
            //...생략
          </div>
          <FlightList list={flightList.filter(filterByCondition)} />
        </div>
      </main>
    </div>
  );
}

📌 Search.js

import { useState } from 'react';

function Search({ onSearch }) {
  const [textDestination, setTextDestination] = useState('');

  const handleChange = (e) => { //입력값 대문자로 변환 코드
    setTextDestination(e.target.value.toUpperCase());
  };

  const handleKeyPress = (e) => { //엔터, 버튼클릭 감지 코드
    if (e.type === 'keypress' && e.code === 'Enter') {
      handleSearchClick();
    }
  };

  const handleSearchClick = () => { //onSearch 이벤트를 받아온다.

    //상위 컴포넌트에서 props를 받아서, search함수 실행
    onSearch({departure: 'ICN', destination: textDestination})
  }; //검색 버튼을 누르거나, 엔터를 치면 search 함수가 실행된다

  return (
    <fieldset>
      <legend>공항 코드를 입력하고, 검색하세요</legend>
      <span>출발지</span>
      <input id="input-departure" type="text" disabled value="ICN"></input>
      <span>도착지</span>
      <input
        id="input-destination"
        type="text"
        value={textDestination}
        onChange={handleChange}
        placeholder="CJU, BKK, PUS 중 하나를 입력하세요"
        onKeyPress={handleKeyPress}
      />
      <button id="search-btn" onClick={handleSearchClick}>
        검색
      </button>
    </fieldset>
  );
}

export default Search;

🔍 Part 2 AJAX 요청

📌 FlightDataApi.js (REST API를 호출)

import flightList from "../resource/flightList";
import fetch from "node-fetch";

if (typeof window !== "undefined") {
  localStorage.setItem("flight", JSON.stringify(flightList));
}

export function getFlight(filterBy = {}) {
  // HINT: 가장 마지막 테스트를 통과하기 위해, fetch를 이용합니다. 아래 구현은 완전히 삭제되어도 상관없습니다.
  // TODO: 아래 구현을 REST API 호출로 대체하세요.

  // 전달된 경우 -> 쿼리 스트링이 뒤에 붙어야함
  // 전달되지 않은 경우 ->

  return fetch(`http://ec2-13-124-90-231.ap-northeast-2.compute.amazonaws.com:81/flight?departure=ICN&destination=${filterBy.destination}`).then((response) =>
    response.json()
  );
}

📌 Main.js

import Head from "next/head";
import {useEffect, useState} from "react";
import {getFlight} from "../api/FlightDataApi";
import FlightList from "./component/FlightList";
import LoadingIndicator from "./component/LoadingIndicator";
import Search from "./component/Search";
import Debug from "./component/Debug";
// 후반 테스트를 진행할 때 아래 import를 삭제합니다.

export default function Main() {
  // 항공편 검색 조건을 담고 있는 상태
  const [condition, setCondition] = useState({
    departure: "ICN",
  });
  const [flightList, setFlightList] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  // 네트워크 요청 전에는 로딩 상태가 아님 ->
  // 네트워크 요청이 시작되면 로딩 상태가 됨 -> true
  // 네트워크 요청이 마무리 되면 로딩 상태가 아님 -> false

  // 주어진 검색 키워드에 따라 condition 상태를 변경시켜주는 함수
  const search = ({departure, destination}) => {
    if (condition.departure !== departure || condition.destination !== destination) {
      // TODO: search 함수가 전달 받아온 '항공편 검색 조건' 인자를 condition 상태에 적절하게 담아보세요.
      setCondition({
        departure,
        destination,
      });
    }
  };

  const filterByCondition = (flight) => {
    let pass = true;
    if (condition.departure) {
      pass = pass && flight.departure === condition.departure;
    }
    if (condition.destination) {
      pass = pass && flight.destination === condition.destination;
    }
    return pass;
  };

  global.search = search; // 실행에는 전혀 지장이 없지만, 테스트를 위해 필요한 코드입니다. 이 코드는 지우지 마세요!

  // TODO: Effect Hook을 이용해 AJAX 요청을 보내보세요.
  // TODO: 더불어, 네트워크 요청이 진행됨을 보여주는 로딩 컴포넌트(<LoadingIndicator/>)를 제공해보세요.
  // 1. 처음 컴포넌트가 렌더링 되었을 때
  // 2. state(condition) 변경될 때
  useEffect(() => {
    setIsLoading(true);
    getFlight(condition).then((data) => {
      setFlightList(data);
      setIsLoading(false);
    });
  }, [condition]);

  return (
    <div>
      <Head>
        <title>States Airline</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main>
        <h1>여행가고 싶을 땐, States Airline</h1>
        {/* // TODO: 테스트 케이스의 지시에 따라 search 함수를 Search 컴포넌트로 내려주세요. */}
        <Search onSearch={search} />
        <div className="table">
          <div className="row-header">
            <div className="col">출발</div>
            <div className="col">도착</div>
            <div className="col">출발 시각</div>
            <div className="col">도착 시각</div>
            <div className="col"></div>
          </div>
          {isLoading ? <LoadingIndicator /> : <FlightList list={flightList} />}
          {/* 삼항 연산자 사용 */}
        </div>
        <div className="debug-area">
          <Debug condition={condition} />
        </div>
        <img id="logo" alt="logo" src="codestates-logo.png" />
      </main>
    </div>
  );
}

0개의 댓글