Add search
This commit is contained in:
parent
ae88e2e4c9
commit
e4c712d5ad
@ -2,32 +2,42 @@
|
|||||||
<header class="flex justify-between mx-2 mt-1">
|
<header class="flex justify-between mx-2 mt-1">
|
||||||
<span class="font-bold">Tools</span>
|
<span class="font-bold">Tools</span>
|
||||||
<router-link :to="{ name: 'home' }" class="ml-4" tag="button"
|
<router-link :to="{ name: 'home' }" class="ml-4" tag="button"
|
||||||
>Home</router-link
|
>Home</router-link
|
||||||
>
|
>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<hr class="mt-2 mb-2" />
|
<hr class="mt-2 mb-2" />
|
||||||
|
|
||||||
|
<div class="mx-2">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
v-model="searchQuery"
|
||||||
|
placeholder="Search.."
|
||||||
|
class="mb-4 border w-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<nav class="flex flex-col ml-2">
|
<nav class="flex flex-col ml-2">
|
||||||
<div
|
<div
|
||||||
v-for="[title, routes] of Object.entries(menuRoutes).sort((a, b) =>
|
v-for="[title, routes] of filteredMenuRoutes"
|
||||||
a[0].localeCompare(b[0])
|
:key="title"
|
||||||
)"
|
|
||||||
class="flex flex-col mb-2"
|
class="flex flex-col mb-2"
|
||||||
|
v-show="Object.keys(routes).length > 0"
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
<i>{{ title }}</i>
|
<i>{{ title }}</i>
|
||||||
</p>
|
</p>
|
||||||
<router-link
|
<router-link
|
||||||
v-for="[key, value] of Object.entries(routes)"
|
v-for="[key, value] of Object.entries(routes)"
|
||||||
|
:key="key"
|
||||||
:to="{ name: key }"
|
:to="{ name: key }"
|
||||||
class="ml-4"
|
class="ml-4"
|
||||||
tag="button"
|
tag="button"
|
||||||
>{{ value }}</router-link
|
>{{ value }}</router-link
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr class="mt-3 mb-3" />
|
<hr class="mt-3 mb-3" v-show="filteredMenuRoutes.length > 0" />
|
||||||
|
|
||||||
<div class="flex flex-col mb-2">
|
<div class="flex flex-col mb-2">
|
||||||
<p><i>Other</i></p>
|
<p><i>Other</i></p>
|
||||||
@ -35,10 +45,10 @@
|
|||||||
href="https://gist.stuzer.link/stuzer05/liked"
|
href="https://gist.stuzer.link/stuzer05/liked"
|
||||||
class="ml-4"
|
class="ml-4"
|
||||||
tag="button"
|
tag="button"
|
||||||
>Gist</a
|
>Gist</a
|
||||||
>
|
>
|
||||||
<a href="https://pdf.stuzer.link/" class="ml-4" tag="button"
|
<a href="https://pdf.stuzer.link/" class="ml-4" tag="button"
|
||||||
>PDF tools</a
|
>PDF tools</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
@ -46,17 +56,37 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { useToolsStore } from "@/stores/toolsStore";
|
import { useToolsStore } from "@/stores/toolsStore";
|
||||||
|
import { ref, computed } from 'vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Sidebar",
|
name: "Sidebar",
|
||||||
components: {},
|
components: {},
|
||||||
data() {
|
setup() {
|
||||||
|
const toolsStore = useToolsStore();
|
||||||
|
const searchQuery = ref('');
|
||||||
|
|
||||||
|
const filteredMenuRoutes = computed(() => {
|
||||||
|
const query = searchQuery.value.toLowerCase();
|
||||||
|
if (query) {
|
||||||
|
return Object.entries(toolsStore.tools)
|
||||||
|
.map(([categoryName, routes]) => [
|
||||||
|
categoryName,
|
||||||
|
Object.fromEntries(
|
||||||
|
Object.entries(routes).filter(
|
||||||
|
([_, routeName]) => routeName.toLowerCase().includes(query)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.filter(([categoryName, routes]) => Object.keys(routes).length > 0);
|
||||||
|
} else {
|
||||||
|
return Object.entries(toolsStore.tools);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
menuRoutes: {},
|
searchQuery,
|
||||||
|
filteredMenuRoutes,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
this.menuRoutes = useToolsStore().tools;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
@ -1,12 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="container mx-auto p-4">
|
<div class="container mx-auto p-4">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
v-model="searchQuery"
|
||||||
|
placeholder="Search.."
|
||||||
|
class="mb-4 border w-full"
|
||||||
|
/>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-5"
|
class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-5"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(category, categoryName) in tools"
|
v-for="(category, categoryName) in filteredTools"
|
||||||
:key="categoryName"
|
:key="categoryName"
|
||||||
class="bg-white rounded-lg shadow-md p-4"
|
class="bg-white shadow-md p-4"
|
||||||
|
v-show="Object.keys(category).length > 0"
|
||||||
>
|
>
|
||||||
<h2 class="text-xl font-semibold mb-3">{{ categoryName }}</h2>
|
<h2 class="text-xl font-semibold mb-3">{{ categoryName }}</h2>
|
||||||
<div class="max-h-80 overflow-y-auto">
|
<div class="max-h-80 overflow-y-auto">
|
||||||
@ -31,7 +39,7 @@
|
|||||||
<div class="flex flex-wrap justify-center items-center gap-4 max-w-4xl">
|
<div class="flex flex-wrap justify-center items-center gap-4 max-w-4xl">
|
||||||
<a
|
<a
|
||||||
href="https://gist.stuzer.link/stuzer05/liked"
|
href="https://gist.stuzer.link/stuzer05/liked"
|
||||||
class="flex items-center w-64 p-4 bg-white rounded-lg shadow-md hover:bg-gray-50 transition-colors duration-300"
|
class="flex items-center w-64 p-4 bg-white shadow-md hover:bg-gray-50 transition-colors duration-300"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src="https://gist.stuzer.link/assets/opengist-85b89b9c.svg"
|
src="https://gist.stuzer.link/assets/opengist-85b89b9c.svg"
|
||||||
@ -43,7 +51,7 @@
|
|||||||
|
|
||||||
<a
|
<a
|
||||||
href="https://pdf.stuzer.link/"
|
href="https://pdf.stuzer.link/"
|
||||||
class="flex items-center w-64 p-4 bg-white rounded-lg shadow-md hover:bg-gray-50 transition-colors duration-300"
|
class="flex items-center w-64 p-4 bg-white shadow-md hover:bg-gray-50 transition-colors duration-300"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src="https://pdf.stuzer.link/favicon.svg"
|
src="https://pdf.stuzer.link/favicon.svg"
|
||||||
@ -59,11 +67,13 @@
|
|||||||
<script>
|
<script>
|
||||||
import { useToolsStore } from "@/stores/toolsStore";
|
import { useToolsStore } from "@/stores/toolsStore";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tools: {},
|
tools: {},
|
||||||
|
searchQuery: ref(''),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
@ -78,6 +88,25 @@ export default {
|
|||||||
mounted() {
|
mounted() {
|
||||||
this.tools = useToolsStore().tools;
|
this.tools = useToolsStore().tools;
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
filteredTools() {
|
||||||
|
const query = this.searchQuery.toLowerCase();
|
||||||
|
if (query) {
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(this.tools).map(([categoryName, tools]) => [
|
||||||
|
categoryName,
|
||||||
|
Object.fromEntries(
|
||||||
|
Object.entries(tools).filter(
|
||||||
|
([_, toolName]) => toolName.toLowerCase().includes(query)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return this.tools;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user