FindMyRecipe / src / lib / components / SearchBar.svelte
SearchBar.svelte
Raw
<!-- TODO: refactor Home with this somehow -->
<script>
  import RecipeBannerV2 from '../components/RecipeBannerV2.svelte'
  import { matchRecipes } from '../utils/recipes.js'
  import {
    autocompleteIngredients,
    getIngredientByName,
  } from '../utils/ingredients.js'
  import { getTagsOfRecipe } from '../utils/tags.js'

  let searchBar = ''
  let fridge = []
  let tags = []
  let recipes = []
  let searchMatches = []
  let matchedTags = []
  let searchStatus = ''
  let inputTimeout = null

  const handleAutoCompTO = (e) => {
    clearTimeout(inputTimeout)

    if (e.keyCode == 13) {
      handleInputEnd()
      return
    }
    // Make a new timeout set to go off in 1000ms (1 second)
    inputTimeout = setTimeout(async () => {
      if (searchBar != '' && searchBar[0] != '#') {
        await handleAutoComp()
      }
    }, 200)
  }

  const setInputVal = (ingredient) => {
    console.log('setInputValClick')
    fridge.push(ingredient)
    fridge = fridge
    searchBar = ''
    searchMatches = []
  }

  const mapIngredients = async (ingredientNames) => {
    let ids = []
    //ids = [4621,4684,6557,8899,10583,12245,14832]
    ids = await Promise.all(
      ingredientNames.map(async (i) => {
        console.log(i)
        return (await getIngredientByName(i)).data.id
      }),
    )
    console.log('mapping')
    console.log(ids)
    return ids
  }

  const handleAutoComp = async () => {
    searchMatches = []
    searchStatus = ''
    const response = await autocompleteIngredients(searchBar)
    if (response.data == null) {
      return
    }
    response.data.forEach((i) => {
      searchMatches.push(i.name)
    })
    searchMatches = searchMatches
  }

  const searchRecipes = async () => {
    recipes = []
    matchRecipes(await mapIngredients(fridge))
      .then(async (res) => {
        console.log(res)
        if (res.status == 'success') {
          recipes = res.data
          let ptags = await Promise.all(
            recipes.map(async (r) => {
              return (await getTagsOfRecipe(r.Id)).data
            }),
          )
          matchedTags = ptags
        } else {
          searchStatus = res.message
        }
      })
      .catch((err) => {
        console.log(err)
      })
  }
  const handleInputEnd = () => {
    console.log('handleInputEnd')
    console.log(searchBar)
    if (
      searchBar != '' &&
      searchBar[0] == '#' &&
      !tags.includes(searchBar.substring(1))
    ) {
      tags.push(searchBar.substring(1))
      tags = tags
    } else if (
      !fridge.includes(searchBar) &&
      searchMatches.includes(searchBar)
    ) {
      fridge.push(searchBar)
    } else if (
      searchMatches.length == 1 &&
      !fridge.includes(searchMatches[0])
    ) {
      fridge.push(searchMatches[0])
    } else {
      return
    }
    searchBar = ''
    fridge = fridge
    searchMatches = []
  }

  const removeFromFridge = (ing) => {
    const index = fridge.indexOf(ing)
    if (index > -1) {
      fridge.splice(index, 1)
    }
    fridge = fridge
  }

  const removeFromTags = (tag) => {
    const index = tags.indexOf(tag)
    if (index > -1) {
      tags.splice(index, 1)
    }
    tags = tags
  }
</script>

<!-- abandoned -->


<!-- QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ -->

<div class="input-group">
  <input
    on:click={() => {
      handleInputEnd()
    }}
    bind:value={searchBar}
    type="text"
    placeholder="Type ingredients and/or add a '#' in front to filter by tags"
    class="input input-bordered w-full"
  />
  <button
    on:click={async () => {
      await searchRecipes()
    }}
    class="btn btn-square"
  >
    <svg
      xmlns="http://www.w3.org/2000/svg"
      class="h-6 w-6"
      fill="none"
      viewBox="0 0 24 24"
      stroke="currentColor"
      ><path
        stroke-linecap="round"
        stroke-linejoin="round"
        stroke-width="2"
        d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
      /></svg
    >
  </button>
</div>

<!-- ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ -->

{#if searchMatches.length > 0}
  <ul id="autocomplete-items-list">
    {#each searchMatches as ingredient, i}
      <div
        class="btn btn-ghost btn-wide normal-case"
        on:click={() => setInputVal(ingredient)}
      >
        <li>{ingredient}</li>
      </div>
    {/each}
  </ul>
{/if}

<div class="fridge-tags">
  <br style="margin-bottom:0" />
  {#if tags.length > 0}
    <ul class="">
      {#each tags as tag, i}
        <div class="badge gap-2">
          <svg
            xmlns="http://www.w3.org/2000/svg"
            fill="none"
            viewBox="0 0 24 24"
            class="inline-block w-4 h-4 stroke-current"
            on:click={() => removeFromTags(tag)}
            ><path
              stroke-linecap="round"
              stroke-linejoin="round"
              stroke-width="2"
              d="M6 18L18 6M6 6l12 12"
            /></svg
          >
          #{tag}
        </div>
      {/each}
    </ul>
  {/if}
  {#if fridge.length > 0}
    <h3><b>Your Fridge:</b></h3>
    <ul class="">
      {#each fridge as ing, i}
        <div class="badge badge-info gap-2">
          <svg
            xmlns="http://www.w3.org/2000/svg"
            fill="none"
            viewBox="0 0 24 24"
            class="inline-block w-4 h-4 stroke-current"
            on:click={() => removeFromFridge(ing)}
            ><path
              stroke-linecap="round"
              stroke-linejoin="round"
              stroke-width="2"
              d="M6 18L18 6M6 6l12 12"
            /></svg
          >
          {ing}
        </div>
      {/each}
    </ul>
  {/if}
</div>

<!-- WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW -->

<div class="items-center">
  {#await tags then}
    {#if recipes.length > 0}
      <div class="items-center text-center">
        {#each recipes as recipe, i}
          <RecipeBannerV2
            recipeId={recipe.Id}
            recipeLabel={recipe.Name}
            description={recipe.Description}
            prepminutes={recipe.PrepMinutes}
            tags={matchedTags[i]}
            checkFavorite="false"
          />
        {/each}
      </div>
    {:else}
      {searchStatus}
    {/if}
  {/await}
</div>

<svelte:window
  on:keyup={(e) => {
    handleAutoCompTO(e)
  }}
/>