From 2a38b834c30b044fb989db75dd25ddc38b9b4c82 Mon Sep 17 00:00:00 2001
From: pheralb
Date: Mon, 1 Sep 2025 11:34:24 +0100
Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A0=EF=B8=8F=20Refactor=20search=20han?=
=?UTF-8?q?dling=20in=20search.svelte=20and=20+page.svelte;=20implement=20?=
=?UTF-8?q?custom=20addParams=20and=20deleteParam=20utility?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/search.svelte | 20 ++---
src/routes/+page.svelte | 22 ++++-
src/routes/directory/[category]/+page.svelte | 88 ++++++++++++--------
src/utils/searchParams.ts | 35 ++++++++
4 files changed, 110 insertions(+), 55 deletions(-)
create mode 100644 src/utils/searchParams.ts
diff --git a/src/components/search.svelte b/src/components/search.svelte
index 8559ec6..d625110 100644
--- a/src/components/search.svelte
+++ b/src/components/search.svelte
@@ -2,12 +2,9 @@
import { cn } from "@/utils/cn";
import { onMount } from "svelte";
- import { page } from "$app/state";
- import { goto } from "$app/navigation";
-
+ import { addParams } from "@/utils/searchParams";
import SearchIcon from "@lucide/svelte/icons/search";
import CommandIcon from "@lucide/svelte/icons/command";
- import { SvelteURLSearchParams } from "svelte/reactivity";
interface Props {
searchValue: string;
@@ -19,19 +16,12 @@
let inputElement: HTMLInputElement;
const onInput = (event: Event) => {
- const param = "search";
const value = (event.target as HTMLInputElement).value;
onSearch(value);
- const params = new SvelteURLSearchParams(page.url.searchParams);
- if (value) {
- params.set(param, value);
- } else {
- params.delete(param);
- }
- goto(`?${params.toString()}`, {
- keepFocus: true,
- noScroll: true,
- replaceState: true,
+ addParams({
+ params: {
+ search: value,
+ },
});
};
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index 1f680ae..86e30f1 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -3,6 +3,7 @@
import type { PageProps } from "./$types";
import { cn } from "@/utils/cn";
+ import { deleteParam } from "@/utils/searchParams";
import { svgsData } from "@/data";
import { searchWithFuse } from "@/utils/searchWithFuse";
@@ -12,11 +13,12 @@
import SvgCard from "@/components/svgs/svgCard.svelte";
import SortSvgs from "@/components/svgs/sortSvgs.svelte";
import Container from "@/components/container.svelte";
+ import SearchXIcon from "@lucide/svelte/icons/search-x";
import PageCard from "@/components/pageCard.svelte";
- import PageHeader from "@/components/pageHeader.svelte";
import FolderIcon from "@lucide/svelte/icons/folder";
- import FolderSearchIcon from "@lucide/svelte/icons/folder-search";
+ import PageHeader from "@/components/pageHeader.svelte";
+ import Button from "@/components/ui/button/button.svelte";
// SSR Data:
let { data }: PageProps = $props();
@@ -60,6 +62,13 @@
searchSvgs();
};
+ const handleClearSearch = () => {
+ searchTerm = "";
+ filteredSvgs = sorted ? alphabeticallySorted : latestSorted;
+ deleteParam("search");
+ updateDisplaySvgs();
+ };
+
$effect(() => {
updateDisplaySvgs();
});
@@ -87,7 +96,14 @@
logos
{:else}
-
+
{filteredSvgs.length}
logos
diff --git a/src/routes/directory/[category]/+page.svelte b/src/routes/directory/[category]/+page.svelte
index 6e84561..d0900de 100644
--- a/src/routes/directory/[category]/+page.svelte
+++ b/src/routes/directory/[category]/+page.svelte
@@ -3,7 +3,6 @@
import type { PageProps } from "./$types";
import { page } from "$app/state";
- import { goto } from "$app/navigation";
import { SvelteURLSearchParams } from "svelte/reactivity";
import { cn } from "@/utils/cn";
@@ -14,68 +13,70 @@
import Search from "@/components/search.svelte";
import SvgCard from "@/components/svgs/svgCard.svelte";
import Container from "@/components/container.svelte";
+ import SearchXIcon from "@lucide/svelte/icons/search-x";
import PageCard from "@/components/pageCard.svelte";
import PageHeader from "@/components/pageHeader.svelte";
import FolderIcon from "@lucide/svelte/icons/folder-open";
import ArrowLeftIcon from "@lucide/svelte/icons/arrow-left";
- import { buttonVariants } from "@/components/ui/button";
+ import { Button, buttonVariants } from "@/components/ui/button";
+ import SortSvgs from "@/components/svgs/sortSvgs.svelte";
+ import { deleteParam } from "@/utils/searchParams";
// SSR Data:
let { data }: PageProps = $props();
const directoryData = $derived(data);
// States:
+ let maxDisplay = 30;
let searchTerm = $state(data.searchTerm || "");
- let filteredSvgs = $derived(data.filteredSvgs);
+ let filteredSvgs = $derived(data.initialSvgs);
+ let sorted = $state(data.sorted);
+ let displaySvgs = $state([]);
+ let showAll = $state(false);
+
+ const updateDisplaySvgs = () => {
+ displaySvgs = showAll ? filteredSvgs : filteredSvgs.slice(0, maxDisplay);
+ };
const searchSvgs = () => {
if (!searchTerm) {
- filteredSvgs = data.svgs;
+ filteredSvgs = sorted ? data.alphabeticallySorted : data.latestSorted;
+ updateDisplaySvgs();
return;
}
if (searchTerm.length < 3) {
- filteredSvgs = data.svgs.filter((svg: iSVG) =>
+ filteredSvgs = (
+ sorted ? data.alphabeticallySorted : data.latestSorted
+ ).filter((svg: iSVG) =>
svg.title.toLowerCase().includes(searchTerm.toLowerCase()),
);
} else {
- filteredSvgs = searchWithFuse(data.svgs)
+ filteredSvgs = searchWithFuse(filteredSvgs)
.search(searchTerm)
.map((result) => result.item);
}
+ updateDisplaySvgs();
};
const handleSearch = (value: string) => {
searchTerm = value;
-
- const params = new SvelteURLSearchParams(page.url.searchParams);
- if (value) {
- params.set("search", value);
- } else {
- params.delete("search");
- }
-
- goto(`?${params.toString()}`, {
- keepFocus: true,
- noScroll: true,
- replaceState: true,
- });
-
searchSvgs();
};
- const formatCategory = (category: string) =>
- category.charAt(0).toUpperCase() + category.slice(1);
+ const handleClearSearch = () => {
+ searchTerm = "";
+ deleteParam("search");
+ updateDisplaySvgs();
+ };
$effect(() => {
- filteredSvgs = data.svgs.filter((svg: iSVG) =>
- svg.title.toLowerCase().includes(searchTerm.toLowerCase()),
- );
+ updateDisplaySvgs();
});
- {formatCategory(directoryData.category)} SVG logos - Svgl
+ {directoryData.category} SVG logos - Svgl
-
+
-
+ {#if searchTerm}
+
+ {:else}
+
+ {/if}
- {formatCategory(directoryData.category)}
+ {directoryData.category}
-
{#if !searchTerm}
- {data.svgs.length} SVGs
+ {data.initialSvgs.length} SVGs
{:else}
@@ -117,6 +123,14 @@
{/if}
+ {
+ sorted = value;
+ searchSvgs();
+ }}
+ />
diff --git a/src/utils/searchParams.ts b/src/utils/searchParams.ts
new file mode 100644
index 0000000..9ae5f44
--- /dev/null
+++ b/src/utils/searchParams.ts
@@ -0,0 +1,35 @@
+import { page } from "$app/state";
+import { goto } from "$app/navigation";
+import { SvelteURLSearchParams } from "svelte/reactivity";
+
+interface SearchParams {
+ params: Record;
+}
+
+const addParams = ({ params }: SearchParams) => {
+ const searchParams = new SvelteURLSearchParams(page.url.searchParams);
+ Object.entries(params).forEach(([key, value]) => {
+ if (value) {
+ searchParams.set(key, value);
+ } else {
+ searchParams.delete(key);
+ }
+ });
+ goto(`?${searchParams.toString()}`, {
+ keepFocus: true,
+ noScroll: true,
+ replaceState: true,
+ });
+};
+
+const deleteParam = (key: string) => {
+ const params = new SvelteURLSearchParams(page.url.searchParams);
+ params.delete(key);
+ goto(`?${params.toString()}`, {
+ keepFocus: true,
+ noScroll: true,
+ replaceState: true,
+ });
+};
+
+export { addParams, deleteParam };