Add search to home page

This commit is contained in:
Sam Carlton 2020-09-19 19:37:23 -05:00
parent 2748394565
commit 7d4ae0310c
2 changed files with 170 additions and 10 deletions

166
components/search.vue Normal file
View file

@ -0,0 +1,166 @@
<template>
<div class="flex flex-col items-center">
<div class="search-input container relative">
<input
id="search"
ref="search"
v-model="query"
aria-label="Type here to Search"
class="appearance-none w-full text-white font-bold sm:text-5xl outline-none bg-transparent p-3"
type="search"
placeholder="Type to Search"
autofocus
autocomplete="off"
@keyup="queryResults(query)"
>
<div class="search-input-separator border-white border-t-4" />
</div>
<div
ref="search-container"
class="search-container relative w-full overflow-scroll scroll-elastic overscroll-contain"
>
<div class="search-wrapper flex justify-center pb-32">
<div class="search-scroller container w-full relative min-h-screen px-5">
<div class="search-results py-8">
<div class="results-container">
<div
v-for="(app, i) in results"
:key="`${app.slug}-${i}`"
>
{{ app.name }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import appList from '~/assets/app-list.json'
// import overlayStore from './mixins/store'
// import modalRouter from '~/components/modals/mixins/router'
// import Card from '~/components/cards/Default.vue'
// import CardsRow from '~/components/cards/Row.vue'
// import ComingSoonImage from '~/components/partials/ComingSoonImage.vue'
// import InfoCircle from '~/assets/svg/info-circle.svg?inline'
// import PlayCircle from '~/assets/svg/play-circle.svg?inline'
export default {
data: function () {
return {
appList,
query: '',
// results: [],
titleStartsWithResults: [],
titleContainsResults: [],
descriptionContainsResults: [],
// store: overlayStore.state
}
},
computed: {
results () {
if (!this.hasSearchInputText) return appList
return [
...this.titleStartsWithResults,
...this.titleContainsResults,
...this.descriptionContainsResults
]
},
hasSearchInputText () {
return this.query.length > 0
},
},
// watch: {
// 'store.mode': function (newMode) {
// // If we're showing the search
// // then focus on the search input
// // on the next tick when our input
// // exists
// if (newMode === 'search') {
// this.$nextTick(() => {
// this.$refs.search.focus()
// })
// }
// }
// },
// mounted () {
// },
methods: {
// Search priorities
titleStartsWith (query, app) {
const matches = app.name.toLowerCase().startsWith(query)
if (matches) {
this.titleStartsWithResults.push(app)
}
return matches
},
titleContains (query, app) {
const matches = app.name.toLowerCase().includes(query)
if (matches) {
this.titleContainsResults.push(app)
}
return matches
},
descriptionContains (query, app) {
const matches = app.description.toLowerCase().includes(query)
if (matches) {
this.descriptionContainsResults.push(app)
}
return matches
},
// Search tools
pluck (array, index) {
const pluckedItem = array[index]
array.splice(index, 1)
return pluckedItem
},
queryResults (rawQuery) {
// Clear any results from before
this.titleStartsWithResults = []
this.titleContainsResults = []
this.descriptionContainsResults = []
// Snap results scroll position back to top
this.$refs['search-container'].scrollTop = 0
// If our query is empty
// then bail
if (rawQuery.length === 0) return
const query = rawQuery.toLowerCase()
// Search App List
this.appList.forEach(app => {
const matchers = [
this.titleStartsWith,
this.titleContains,
// this.descriptionContains
]
// Run through our search priorities
for (const method of matchers){
// iterations++
const appMatches = method(query, app)
if (appMatches) {
// We've found a match for this app
// so let's stop trying match methods
// and search the next app
break
}
}
})
// console.log('query', query)
// console.log('iterations', iterations)
}
}
}
</script>

View file

@ -7,6 +7,8 @@
<h2 class="subtitle text-xl font-bold"> <h2 class="subtitle text-xl font-bold">
Apps that are reported to support Apple Silicon Apps that are reported to support Apple Silicon
</h2> </h2>
<Search />
<div class="apps"> <div class="apps">
<div <div
v-for="app in appList" v-for="app in appList"
@ -18,27 +20,19 @@
</div> </div>
</a> </a>
</div> </div>
<a
href="https://nuxtjs.org/"
target="_blank"
class="button--green">Documentation</a>
<a
href="https://github.com/nuxt/nuxt.js"
target="_blank"
class="button--grey">GitHub</a>
</div> </div>
</div> </div>
</section> </section>
</template> </template>
<script> <script>
import Logo from '~/components/Logo.vue' import Search from '~/components/search.vue'
import appList from '~/assets/app-list.json' import appList from '~/assets/app-list.json'
export default { export default {
components: { components: {
Logo Search
}, },
computed: { computed: {
appList() { appList() {