Improve search functionality with Fuse.js for better accuracy and UX (#76)
* Improve search functionality with Fuse.js * Centralized social media links in `data/index.ts` * Fix formatting Signed-off-by: nurRiyad <asadnurriyad@gmail.com> * Update dependency Signed-off-by: nurRiyad <asadnurriyad@gmail.com> * Fix formatting Signed-off-by: nurRiyad <asadnurriyad@gmail.com> --------- Signed-off-by: nurRiyad <asadnurriyad@gmail.com> Co-authored-by: nurRiyad <asadnurriyad@gmail.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { footerData } from '~/data'
|
import { footerData, socialLinks } from '~/data'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -12,7 +12,7 @@ import { footerData } from '~/data'
|
|||||||
</p>
|
</p>
|
||||||
<div class="my-3 space-x-3 pb-3">
|
<div class="my-3 space-x-3 pb-3">
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
to="https://github.com/nurRiyad"
|
:to="socialLinks.githubLink"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="p-2 bg-gray-300 text-gray-800 rounded-md dark:bg-sky-700 dark:text-[#F1F2F4]"
|
class="p-2 bg-gray-300 text-gray-800 rounded-md dark:bg-sky-700 dark:text-[#F1F2F4]"
|
||||||
aria-label="Github"
|
aria-label="Github"
|
||||||
@@ -20,7 +20,7 @@ import { footerData } from '~/data'
|
|||||||
<Icon name="fa:github" size="1em" />
|
<Icon name="fa:github" size="1em" />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
to="https://www.linkedin.com/in/nur-riyad/"
|
:to="socialLinks.linkedinLink"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="p-2 bg-gray-300 text-gray-800 rounded-md dark:bg-sky-700 dark:text-[#F1F2F4]"
|
class="p-2 bg-gray-300 text-gray-800 rounded-md dark:bg-sky-700 dark:text-[#F1F2F4]"
|
||||||
aria-label="LinkedIn"
|
aria-label="LinkedIn"
|
||||||
@@ -28,7 +28,7 @@ import { footerData } from '~/data'
|
|||||||
<Icon name="fa:linkedin-square" size="1em" />
|
<Icon name="fa:linkedin-square" size="1em" />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
to="https://twitter.com/qdnvubp"
|
:to="socialLinks.twitterLink"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="p-2 bg-gray-300 text-gray-800 rounded-md dark:bg-sky-700 dark:text-[#F1F2F4]"
|
class="p-2 bg-gray-300 text-gray-800 rounded-md dark:bg-sky-700 dark:text-[#F1F2F4]"
|
||||||
aria-label="Twitter"
|
aria-label="Twitter"
|
||||||
@@ -36,7 +36,7 @@ import { footerData } from '~/data'
|
|||||||
<Icon name="fa:twitter-square" size="1em" />
|
<Icon name="fa:twitter-square" size="1em" />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
to="https://stackoverflow.com/users/16781395/nur-riyad"
|
:to="socialLinks.stackoverflowLink"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="p-2 bg-gray-300 text-gray-800 rounded-md dark:bg-sky-700 dark:text-[#F1F2F4]"
|
class="p-2 bg-gray-300 text-gray-800 rounded-md dark:bg-sky-700 dark:text-[#F1F2F4]"
|
||||||
aria-label="StackOverflow"
|
aria-label="StackOverflow"
|
||||||
|
|||||||
@@ -48,6 +48,13 @@ export const seoData = {
|
|||||||
mailAddress: 'asadnurriyad@gmail.com',
|
mailAddress: 'asadnurriyad@gmail.com',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const socialLinks = {
|
||||||
|
githubLink: 'https://github.com/nurRiyad',
|
||||||
|
linkedinLink: 'https://www.linkedin.com/in/nur-riyad/',
|
||||||
|
twitterLink: 'https://twitter.com/qdnvubp',
|
||||||
|
stackoverflowLink: 'https://stackoverflow.com/users/16781395/nur-riyad',
|
||||||
|
}
|
||||||
|
|
||||||
export const siteMetaData = [
|
export const siteMetaData = [
|
||||||
{
|
{
|
||||||
name: 'description',
|
name: 'description',
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
"@vueuse/nuxt": "^10.9.0",
|
"@vueuse/nuxt": "^10.9.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"feed": "^4.2.2",
|
"feed": "^4.2.2",
|
||||||
|
"fuse.js": "^7.0.0",
|
||||||
"nuxt": "^3.14.159",
|
"nuxt": "^3.14.159",
|
||||||
"nuxt-icon": "^0.6.8",
|
"nuxt-icon": "^0.6.8",
|
||||||
"nuxt-og-image": "^3.0.0-rc.38",
|
"nuxt-og-image": "^3.0.0-rc.38",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { aboutPage, footerData, navbarData } from '~/data'
|
import { aboutPage, footerData, navbarData, socialLinks } from '~/data'
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: 'About',
|
title: 'About',
|
||||||
@@ -31,7 +31,7 @@ defineOgImageComponent('About', {
|
|||||||
|
|
||||||
<div class="my-3 space-x-2 md:space-x-3 pb-10">
|
<div class="my-3 space-x-2 md:space-x-3 pb-10">
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
to="https://github.com/nurRiyad"
|
:to="socialLinks.githubLink"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="px-2 py-1 lg:px-3 lg:py-2 bg-gray-300 text-gray-800 rounded-md dark:bg-slate-700 dark:text-[#F1F2F4]"
|
class="px-2 py-1 lg:px-3 lg:py-2 bg-gray-300 text-gray-800 rounded-md dark:bg-slate-700 dark:text-[#F1F2F4]"
|
||||||
aria-label="Github"
|
aria-label="Github"
|
||||||
@@ -39,7 +39,7 @@ defineOgImageComponent('About', {
|
|||||||
<Icon name="fa:github" size="1em" />
|
<Icon name="fa:github" size="1em" />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
to="https://www.linkedin.com/in/nur-riyad/"
|
:to="socialLinks.linkedinLink"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="px-2 py-1 lg:px-3 lg:py-2 bg-gray-300 text-gray-800 rounded-md dark:bg-slate-700 dark:text-[#F1F2F4]"
|
class="px-2 py-1 lg:px-3 lg:py-2 bg-gray-300 text-gray-800 rounded-md dark:bg-slate-700 dark:text-[#F1F2F4]"
|
||||||
aria-label="LinkedIn"
|
aria-label="LinkedIn"
|
||||||
@@ -47,7 +47,7 @@ defineOgImageComponent('About', {
|
|||||||
<Icon name="fa:linkedin-square" size="1em" />
|
<Icon name="fa:linkedin-square" size="1em" />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
to="https://twitter.com/qdnvubp"
|
:to="socialLinks.twitterLink"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="px-2 py-1 lg:px-3 lg:py-2 bg-gray-300 text-gray-800 rounded-md dark:bg-slate-700 dark:text-[#F1F2F4]"
|
class="px-2 py-1 lg:px-3 lg:py-2 bg-gray-300 text-gray-800 rounded-md dark:bg-slate-700 dark:text-[#F1F2F4]"
|
||||||
aria-label="Twitter"
|
aria-label="Twitter"
|
||||||
@@ -55,7 +55,7 @@ defineOgImageComponent('About', {
|
|||||||
<Icon name="fa:twitter-square" size="1em" />
|
<Icon name="fa:twitter-square" size="1em" />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
to="https://stackoverflow.com/users/16781395/nur-riyad"
|
:to="socialLinks.stackoverflowLink"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="px-2 py-1 lg:px-3 lg:py-2 bg-gray-300 text-gray-800 rounded-md dark:bg-slate-700 dark:text-[#F1F2F4]"
|
class="px-2 py-1 lg:px-3 lg:py-2 bg-gray-300 text-gray-800 rounded-md dark:bg-slate-700 dark:text-[#F1F2F4]"
|
||||||
aria-label="StackOverflow"
|
aria-label="StackOverflow"
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import Fuse from 'fuse.js'
|
||||||
|
|
||||||
const { data } = await useAsyncData('home', () => queryContent('/blogs').sort({ _id: -1 }).find())
|
const { data } = await useAsyncData('home', () => queryContent('/blogs').sort({ _id: -1 }).find())
|
||||||
|
|
||||||
const elementPerPage = ref(5)
|
const elementPerPage = ref(5)
|
||||||
@@ -23,26 +25,28 @@ const formattedData = computed(() => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const fuse = computed(() => {
|
||||||
|
return new Fuse(formattedData.value, {
|
||||||
|
keys: ['title', 'description'],
|
||||||
|
threshold: 0.4,
|
||||||
|
includeScore: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
const searchData = computed(() => {
|
const searchData = computed(() => {
|
||||||
return (
|
if (!searchTest.value.trim()) {
|
||||||
formattedData.value.filter((data) => {
|
return formattedData.value
|
||||||
const lowerTitle = data.title.toLocaleLowerCase()
|
}
|
||||||
if (lowerTitle.search(searchTest.value) !== -1) return true
|
|
||||||
else return false
|
const results = fuse.value.search(searchTest.value)
|
||||||
}) || []
|
return results.map((result) => result.item)
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const paginatedData = computed(() => {
|
const paginatedData = computed(() => {
|
||||||
return (
|
const startInd = (pageNumber.value - 1) * elementPerPage.value
|
||||||
searchData.value.filter((data, idx) => {
|
const endInd = pageNumber.value * elementPerPage.value
|
||||||
const startInd = (pageNumber.value - 1) * elementPerPage.value
|
|
||||||
const endInd = pageNumber.value * elementPerPage.value - 1
|
|
||||||
|
|
||||||
if (idx >= startInd && idx <= endInd) return true
|
return searchData.value.slice(startInd, endInd)
|
||||||
else return false
|
|
||||||
}) || []
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
function onPreviousPageClick() {
|
function onPreviousPageClick() {
|
||||||
@@ -51,8 +55,7 @@ function onPreviousPageClick() {
|
|||||||
|
|
||||||
const totalPage = computed(() => {
|
const totalPage = computed(() => {
|
||||||
const ttlContent = searchData.value.length || 0
|
const ttlContent = searchData.value.length || 0
|
||||||
const totalPage = Math.ceil(ttlContent / elementPerPage.value)
|
return Math.ceil(ttlContent / elementPerPage.value)
|
||||||
return totalPage
|
|
||||||
})
|
})
|
||||||
|
|
||||||
function onNextPageClick() {
|
function onNextPageClick() {
|
||||||
|
|||||||
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@@ -55,6 +55,9 @@ importers:
|
|||||||
feed:
|
feed:
|
||||||
specifier: ^4.2.2
|
specifier: ^4.2.2
|
||||||
version: 4.2.2
|
version: 4.2.2
|
||||||
|
fuse.js:
|
||||||
|
specifier: ^7.0.0
|
||||||
|
version: 7.0.0
|
||||||
nuxt:
|
nuxt:
|
||||||
specifier: ^3.14.159
|
specifier: ^3.14.159
|
||||||
version: 3.14.159(@parcel/watcher@2.5.0)(@types/node@22.9.0)(eslint@9.14.0(jiti@2.4.0))(ioredis@5.4.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.24.4)(terser@5.36.0)(typescript@5.6.3)(vite@5.4.10(@types/node@22.9.0)(terser@5.36.0))
|
version: 3.14.159(@parcel/watcher@2.5.0)(@types/node@22.9.0)(eslint@9.14.0(jiti@2.4.0))(ioredis@5.4.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.24.4)(terser@5.36.0)(typescript@5.6.3)(vite@5.4.10(@types/node@22.9.0)(terser@5.36.0))
|
||||||
@@ -4228,6 +4231,13 @@ packages:
|
|||||||
integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==,
|
integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fuse.js@7.0.0:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==,
|
||||||
|
}
|
||||||
|
engines: { node: '>=10' }
|
||||||
|
|
||||||
gauge@3.0.2:
|
gauge@3.0.2:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -11785,6 +11795,8 @@ snapshots:
|
|||||||
|
|
||||||
function-bind@1.1.2: {}
|
function-bind@1.1.2: {}
|
||||||
|
|
||||||
|
fuse.js@7.0.0: {}
|
||||||
|
|
||||||
gauge@3.0.2:
|
gauge@3.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
aproba: 2.0.0
|
aproba: 2.0.0
|
||||||
|
|||||||
Reference in New Issue
Block a user