mirror of
https://github.com/ThatGuySam/doesitarm.git
synced 2026-05-18 06:44:46 -07:00
227 lines
9.2 KiB
Vue
227 lines
9.2 KiB
Vue
<template>
|
|
<div class="search w-full">
|
|
<div class="search-input relative">
|
|
<input
|
|
id="search"
|
|
ref="search"
|
|
v-model="query"
|
|
aria-label="Type here to Search"
|
|
class="appearance-none w-full text-white font-hairline sm:text-5xl outline-none bg-transparent p-3"
|
|
type="search"
|
|
placeholder="Type to Search"
|
|
autofocus
|
|
autocomplete="off"
|
|
@keyup="queryResults(query)"
|
|
@focus="scrollInputToTop()"
|
|
>
|
|
<div class="search-input-separator border-white border-t-2" />
|
|
</div>
|
|
<div
|
|
ref="search-container"
|
|
class="search-container relative w-full"
|
|
>
|
|
<div class="search-wrapper flex justify-center">
|
|
<div class="search-scroller w-full relative">
|
|
|
|
<div class="search-results py-8">
|
|
|
|
<ul class="results-container rounded-lg border border-gray-700 divide-y divide-gray-700 neumorphic-shadow px-5">
|
|
<li
|
|
v-if="results.length === 0"
|
|
class="text-center py-4"
|
|
>
|
|
No apps found
|
|
</li>
|
|
<li
|
|
v-for="(app, i) in results"
|
|
:key="`${app.slug}-${i}`"
|
|
>
|
|
<a
|
|
:href="`/app/${ app.slug }`"
|
|
class="block hover:neumorphic-shadow hover:bg-gradient-to-br from-darkest to-dark focus:outline-none focus:bg-gray-50 transition duration-300 ease-in-out rounded-lg -mx-5"
|
|
>
|
|
<div class="flex items-center px-4 py-4 sm:px-6">
|
|
<div class="min-w-0 flex-1 flex items-center">
|
|
<div class="flex-shrink-0">
|
|
<div
|
|
class="h-12 w-12 rounded-full flex items-center justify-center neumorphic-shadow-inner"
|
|
>
|
|
<div>{{ app.name.charAt(0) }}</div>
|
|
</div>
|
|
</div>
|
|
<div class="min-w-0 flex-1 px-4 md:grid md:grid-cols-2 md:gap-4">
|
|
<div>
|
|
<div class="text-sm leading-5 font-light truncate">{{ app.name }}</div>
|
|
<div class="mt-2 flex items-center text-sm leading-5 text-gray-500">
|
|
<span class="">{{ app.text }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="hidden md:block">
|
|
<div>
|
|
<!-- <div class="text-sm leading-5 text-gray-900">
|
|
Applied on
|
|
<time datetime="2020-01-07">January 7, 2020</time>
|
|
</div> -->
|
|
<!-- <div class="mt-2 flex items-center text-sm leading-5 text-gray-500">
|
|
{{ app.text }}
|
|
</div> -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<!-- Heroicon name: chevron-right -->
|
|
<svg
|
|
class="h-5 w-5 text-gray-400"
|
|
viewBox="0 0 20 20"
|
|
fill="currentColor">
|
|
<path
|
|
fill-rule="evenodd"
|
|
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
|
|
clip-rule="evenodd" />
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import scrollIntoView from 'scroll-into-view-if-needed'
|
|
|
|
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: [],
|
|
sectionNameContainsResults: [],
|
|
// store: overlayStore.state
|
|
}
|
|
},
|
|
computed: {
|
|
results () {
|
|
if (!this.hasSearchInputText) return appList
|
|
|
|
return [
|
|
...this.titleStartsWithResults,
|
|
...this.titleContainsResults,
|
|
...this.sectionNameContainsResults
|
|
]
|
|
},
|
|
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
|
|
},
|
|
sectionNameContains (query, app) {
|
|
const matches = app.sectionName.toLowerCase().includes(query)
|
|
if (matches) {
|
|
this.sectionNameContainsResults.push(app)
|
|
}
|
|
return matches
|
|
},
|
|
// Search tools
|
|
pluck (array, index) {
|
|
const pluckedItem = array[index]
|
|
array.splice(index, 1)
|
|
return pluckedItem
|
|
},
|
|
scrollInputToTop () {
|
|
scrollIntoView(this.$refs['search'], {
|
|
block: 'start',
|
|
behavior: 'smooth'
|
|
})
|
|
},
|
|
queryResults (rawQuery) {
|
|
// Clear any results from before
|
|
this.titleStartsWithResults = []
|
|
this.titleContainsResults = []
|
|
this.sectionNameContainsResults = []
|
|
|
|
|
|
// 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.sectionNameContains
|
|
]
|
|
|
|
// 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>
|