[JavaScript Toy Project] Random Meal Generator | 오늘뭐먹지? 토이프로젝트

이은진·2020년 11월 13일
13
post-custom-banner

오늘뭐먹지 서비스는 점심메뉴를 정해야 하는 모든 회사의 막내들을 위해 만들어졌습니다. 인터넷 강의를 보고 만든 Menu Finder 앱을 제 입맛에 맞게 수정하여 완성했습니다. 랜덤 메뉴 API를 활용해 다양한 세계 음식 데이터를 불러와 제작했습니다.

1. Random Menu Generator UI/UX

오늘뭐먹지 앱은 반응형으로 제작되었으며, 단일 페이지 앱입니다. 검색어를 입력하면 해당 데이터를 포함한 결과가 나오고, 결과를 클릭하면 그에 대한 상세 정보가 나옵니다. 검색할 메뉴 키워드도 떠올리기 힘든 분들을 위해 검색창 옆에 랜덤 메뉴 호출 버튼을 만들었습니다.

2. Main Features

2-1. Searching Meals

검색한 키워드를 url에 넣으면 검색 결과가 나오는 API를 활용해서 메뉴를 검색할 수 있도록 했습니다. 그리고 검색결과에 해당하는 태그 내에 innerHTML을 적용해 엘리먼트를 추가했습니다.

const search = document.getElementById('search'),
	submit = document.getElementById('submit')

const searchMeal = async (e) => {
  //we dont want to actually try to submit to a file
  e.preventDefault();
  //Clear single meal
  single_mealEl.innerHTML = ''

  //Get the search term
  const term = search.value
  
  //Check for empty
  if (term.trim()) {
    const response = await fetch(`https://www.themealdb.com/api/json/v1/1/search.php?s=${term}`)
    const data = await response.json()
    //console.log(data.meals.length)

    resultHeading.innerHTML = `<h2>'${term}' 검색결과: ${data.meals.length}건</h2>`

    if (data.meals === null) {
      resultHeading.innerHTML = '<p>There are no search results. Try again!<p>'
    } else {
      mealsEl.innerHTML = data.meals.map((meal => `
      <div class="meal">
        <img src="${meal.strMealThumb}" alt="${meal.strMeal}"/>
        <div class="meal-info" data-mealID="${meal.idMeal}">
          <h3>${meal.strMeal}</h3>
        </div>
      </div>
      `))
      .join('')
    }
    
    //Clear searchText
    search.value = ''
  } else {
    alert('검색어는 1자 이상 입력해주세요')
  }
}

//EventListener
submit.addEventListener('submit', searchMeal)

2-2. Fetching Random Meals

랜덤 메뉴 API를 이용해, 메뉴 한 개에 대한 디테일한 데이터가 담긴 array를 가져와서 마찬가지로 innerHTML로 데이터를 추가했습니다.


const random = document.getElementById('random')

//fetch random meal from API
const getRandomMeal = async () => {
  //Clear meals and heading
  mealsEl.innerHTML = ''
  resultHeading.innerHTML = ''

  const response = await fetch('https://www.themealdb.com/api/json/v1/1/random.php')
  if (response.status === 200) {
    const data = await response.json()
    const meal = await data.meals[0]
    addMealToDOM(meal)
  } else {
    throw new Error('Unable to fetch random meal')
  }
}

//Add meal to DOM
const addMealToDOM = (meal) => {
  const ingredients = []

  for (let i = 1; i <= 10; i ++) {
    if (meal[`strIngredient${i}`]) {
      ingredients.push(`${meal[`strIngredient${i}`]} - ${meal[`strMeasure${i}`]}`)
    } else {
      break
    }
  }
  
  resultHeading.innerHTML = ''
  mealsEl.innerHTML = ''
  single_mealEl.innerHTML = `
    <div class="single-meal">
      <h1>${meal.strMeal}</h1>
      <div class="single-meal-info">
        ${meal.strCategory ? `<p>분류 : ${meal.strCategory}</p>` : ''}
        ${meal.strArea ? `<p>국가 : ${meal.strArea}</p>` : ''}
      </div>
      <img src="${meal.strMealThumb}" alt="${meal.strMeal}" />

      <div class="main">
        <h2>조리방법</h2>
        <span></span>
        <ul>
          ${ingredients.map(ing => `<li>${ing}</li>`).join('')}
        </ul>
        <p>${meal.strInstructions}</p>

      </div>
    </div>
  `
}

//EventListener
random.addEventListener('click', getRandomMeal)

2-3. Click To See Detailed Recipes

검색 결과에 하나씩 적용되어 있는 data-mealID attribute를 이용하여, 그 mealID값을 활용하여 메뉴를 찾는 비동기 함수를 만들었습니다. 애초부터 랜덤 API를 활용하는 2-2번 방식과 달리, 검색 결과에서 고유 아이디를 부여받아 그 아이디값을 활용하는 방식입니다.


//Getting id for description page
const getMealById = async (mealID) => {
  const response = await fetch(`https://www.themealdb.com/api/json/v1/1/lookup.php?i=${mealID}`)
  if (response.status === 200) {
    const data = await response.json()
    const meal = await data.meals[0]
    addMealToDOM(meal)
  } else {
    throw new Error('Unable to fetch ID')
  }
}

//Event Listener
mealsEl.addEventListener('click', (e) => {
  const path = e.path || (e.composedPath && e.composedPath());
  const mealInfo = path.find(item => {
    if (item.classList) {
      return item.classList.contains('meal-info')
    } else {
      return false
    }
  })

  if (mealInfo) {
    const mealID = mealInfo.getAttribute('data-mealID')
    getMealById(mealID)
  }
})

랜덤메뉴 생성 API
https://www.themealdb.com/api/json/v1/1/random.php
랜덤메뉴 키워드 검색 결과 API
https://www.themealdb.com/api/json/v1/1/search.php?s=chicken
랜덤메뉴 아이디값 검색 결과 API
https://www.themealdb.com/api/json/v1/1/lookup.php?i=52920

profile
빵굽는 프론트엔드 개발자
post-custom-banner

0개의 댓글