Add option to search recipes by tag, tweak UI of search results

This commit is contained in:
Maël Brunet 2021-06-07 00:29:31 +02:00
parent 6b2d108c3d
commit 3c9e10dca1
5 changed files with 57 additions and 33 deletions

View file

@ -4,7 +4,8 @@
"author": "John Doe", "author": "John Doe",
"primaryColor": "#ffdb70", "primaryColor": "#ffdb70",
"secondaryColor": "#32816e", "secondaryColor": "#32816e",
"searchLabel": "Find recipes by name or ingredients", "searchLabel": "Find recipes by name, tag or ingredients",
"searchContainsLabel": "Contains",
"servingsLabel": "servings", "servingsLabel": "servings",
"ingredientsLabel": "Ingredients" "ingredientsLabel": "Ingredients"
} }

View file

@ -2,25 +2,15 @@
<label for="{{ 'search-home' if homeSearch else 'search' }}" class="c-search__label {{ 'c-search__label--home' if homeSearch }}">{{ site.searchLabel }}&nbsp;:</label> <label for="{{ 'search-home' if homeSearch else 'search' }}" class="c-search__label {{ 'c-search__label--home' if homeSearch }}">{{ site.searchLabel }}&nbsp;:</label>
<div class="c-search__input-wrapper {{ 'c-search__input-wrapper--home' if homeSearch }}"> <div class="c-search__input-wrapper {{ 'c-search__input-wrapper--home' if homeSearch }}">
<input type="text" id="{{ 'search-home' if homeSearch else 'search' }}" class="c-search__input {{ 'c-search__input--home' if homeSearch }}" x-model="searchInput" @focus=" <input type="text" id="{{ 'search-home' if homeSearch else 'search' }}" class="c-search__input {{ 'c-search__input--home' if homeSearch }}" x-model="searchInput" @focus="
if (!window.searchResults) {
fetch('/search.json').then(res => res.json()).then(res => {
window.searchResults = res;
searchResults = window.searchResults;
});
} else {
searchResults = window.searchResults;
}
if (sessionStorage.getItem('searchResults')) { if (sessionStorage.getItem('searchResults')) {
searchResults = JSON.parse(sessionStorage.getItem('searchResults')); searchResults = JSON.parse(sessionStorage.getItem('searchResults'));
} else { } else {
fetch('/search.json').then(res => res.json()).then(res => { fetch('/search.json').then(res => res.json()).then(res => {
sessionStorage.setItem('searchResults', JSON.stringify(res)); sessionStorage.setItem('searchResults', JSON.stringify(res));
searchResults = random(res); searchResults = JSON.stringify(res);
}); });
} }
" @input=" " @input="
console.log(searchInput);
matches = []; matches = [];
if (searchInput.length < 3) { return }; if (searchInput.length < 3) { return };
@ -28,12 +18,14 @@
searchResults.forEach(recipe => { searchResults.forEach(recipe => {
const matchTitle = recipe.title.toLowerCase().includes(searchInput); const matchTitle = recipe.title.toLowerCase().includes(searchInput);
const matchIngredient = recipe.ingredients.find(ingredient => ingredient.toLowerCase().includes(searchInput)); const matchIngredient = recipe.ingredients.find(ingredient => ingredient.toLowerCase().includes(searchInput));
const matchTag = recipe.tags.find(tag => tag.toLowerCase().includes(searchInput));
if (!matchTitle && !matchIngredient) { return }; if (!matchTitle && !matchIngredient && !matchTag) { return };
const match = {...recipe}; const match = {...recipe};
if (matchTitle) { match.matchTitle = matchTitle }; if (matchTitle) { match.matchTitle = matchTitle };
if (matchIngredient) { match.matchIngredient = matchIngredient }; if (matchIngredient) { match.matchIngredient = matchIngredient };
if (matchTag) { match.matchTag = matchTag };
matches.push(match) matches.push(match)
}); });
@ -49,18 +41,25 @@
</div> </div>
<template x-if="matches.length"> <template x-if="matches.length">
<ul class="c-search__search-results"> <div class="c-search__results-wrapper">
<template x-for="(match, index) in matches" :key="index"> <ul class="c-search__results {{ 'c-search__results--home' if homeSearch }}">
<li> <template x-for="(match, index) in matches" :key="index">
<a x-bind:href="match.url" x-html="highlightText(match.title, searchInput)" class="c-search__search-result-link {{ 'c-search__search-result-link--home' if homeSearch }}"></a> <li>
<template x-if="match.matchIngredient"> <div class="c-search__result-link {{ 'c-search__result-link--home' if homeSearch }}">
<p class="c-search__search-result-ingredients {{ 'c-search__search-result-ingredients--home' if homeSearch }}" > <a x-bind:href="match.url" x-html="highlightText(match.title, searchInput)"></a>
Contains: <span x-html="highlightText(match.matchIngredient, searchInput)"></span> <template x-if="match.matchTag">
</p> <div class="c-tags__tag c-tag__tag--selected" x-html="highlightText(match.matchTag, searchInput)"></div>
</template> </template>
</li> </div>
</template> <template x-if="match.matchIngredient">
</ul> <p class="c-search__result-ingredients {{ 'c-search__result-ingredients--home' if homeSearch }}" >
{{ site.searchContainsLabel }}: <span x-html="highlightText(match.matchIngredient, searchInput)"></span>
</p>
</template>
</li>
</template>
</ul>
</div>
</template> </template>
</div> </div>

View file

@ -42,6 +42,7 @@ collections:
- {label: "Primary color", name: "primaryColor", widget: "color", hint: "make sure to choose a color that is light enough to display as a background behind dark text"} - {label: "Primary color", name: "primaryColor", widget: "color", hint: "make sure to choose a color that is light enough to display as a background behind dark text"}
- {label: "Secondary color", name: "secondaryColor", widget: "color", hint: "used for links and focus styles"} - {label: "Secondary color", name: "secondaryColor", widget: "color", hint: "used for links and focus styles"}
- {label: "Search (label)", name: "searchLabel", widget: "string"} - {label: "Search (label)", name: "searchLabel", widget: "string"}
- {label: "Search \"contains\" (label)", name: "searchContainsLabel", widget: "string"}
- {label: "Servings (label)", name: "servingsLabel", widget: "string"} - {label: "Servings (label)", name: "servingsLabel", widget: "string"}
- {label: "Ingredients (label)", name: "ingredientsLabel", widget: "string"} - {label: "Ingredients (label)", name: "ingredientsLabel", widget: "string"}
- name: "nav" - name: "nav"

View file

@ -27,7 +27,7 @@
background-color: var(--color-white); background-color: var(--color-white);
padding: 24px; padding: 24px;
border: 1px solid var(--color-grey-300); border: 1px solid var(--color-grey-300);
border-radius: 6px; border-radius: 10px;
box-shadow: var(--shadow-xl); box-shadow: var(--shadow-xl);
font-size: 1rem; font-size: 1rem;
@ -101,24 +101,46 @@
} }
} }
.c-search__search-results { .c-search__results-wrapper {
position: relative;
margin: 0;
}
.c-search__results {
> * + * { > * + * {
margin-top: 10px; margin-top: 10px;
} }
} }
.c-search__search-results { .c-search__results.c-search__results--home {
margin-top: 30px; position: absolute;
z-index: 10;
top: 10px;
left: 50%;
transform: translateX(-50%);
width: 100%;
max-width: 500px;
padding: 24px;
background-color: var(--color-white);
border: 1px solid var(--color-grey-300);
box-shadow: var(--shadow-xl);
border-radius: 10px;
} }
.c-search__search-result-link--home { .c-search__result-link {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.c-search__result-link--home {
font-size: 1.2rem; font-size: 1.2rem;
} }
.c-search__search-result-ingredients { .c-search__result-ingredients {
font-style: italic; font-style: italic;
} }
.c-search__search-result-ingredients--home { .c-search__result-ingredients--home {
font-size: 1rem; font-size: 1rem;
} }

View file

@ -7,7 +7,8 @@ permalink: search.json
{ {
"title" : "{{ recipe.data.title }}", "title" : "{{ recipe.data.title }}",
"url" : "{{ recipe.url }}", "url" : "{{ recipe.url }}",
"ingredients" : [{% for ingredient in recipe.data.ingredients %}"{{ingredient}}"{% if not loop.last %},{% endif %}{% endfor %}] "ingredients" : [{% for ingredient in recipe.data.ingredients %}"{{ingredient}}"{% if not loop.last %},{% endif %}{% endfor %}],
"tags" : [{% for tag in recipe.data.tags %}"{{tag}}"{% if not loop.last %},{% endif %}{% endfor %}]
}{% if not loop.last %},{% endif %} }{% if not loop.last %},{% endif %}
{% endfor %} {% endfor %}
] ]