Skip to content

Commit 6c83166

Browse files
committed
feat: implement snippet search
1 parent a36da70 commit 6c83166

1 file changed

Lines changed: 46 additions & 12 deletions

File tree

src/routes/+page.svelte

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
Edit2,
1212
Trash2,
1313
Save,
14-
X
14+
X,
15+
Search
1516
} from '@lucide/svelte';
1617
import { slide } from 'svelte/transition';
1718
import { flip } from 'svelte/animate';
@@ -20,6 +21,7 @@
2021
let selectedCategoryId = $state<string | null>(null);
2122
let newlyCreatedSnippetId = $state<string | null>(null);
2223
let isReorderMode = $state(false);
24+
let searchQuery = $state('');
2325
let massDeleteModal: HTMLDialogElement;
2426
2527
function confirmMassDelete() {
@@ -39,20 +41,36 @@
3941
4042
for (const catId of categoryIds) {
4143
const cat = dbStore.data.categories.find((c) => c.id === catId);
42-
const snips = dbStore.data.snippets.filter((s) => s.categoryId === catId);
44+
let snips = dbStore.data.snippets.filter((s) => s.categoryId === catId);
45+
46+
if (searchQuery.trim()) {
47+
const query = searchQuery.toLowerCase();
48+
snips = snips.filter((s) =>
49+
Object.values(s.content).some((val) => val.toLowerCase().includes(query))
50+
);
51+
}
52+
4353
if (
4454
snips.length > 0 ||
45-
(selectedCategoryId === catId && dbStore.data.snippets.length > 0)
55+
(!searchQuery.trim() && selectedCategoryId === catId && dbStore.data.snippets.length > 0)
4656
) {
4757
// We only show empty groups if it's the currently selected category and there are NO snippets at all, which is handled in the template.
4858
groups.push({ categoryId: catId, category: cat, snippets: snips });
4959
}
5060
}
5161
5262
if (!selectedCategoryId) {
53-
const uncategorizedSnippets = dbStore.data.snippets.filter(
63+
let uncategorizedSnippets = dbStore.data.snippets.filter(
5464
(s) => !dbStore.data.categories.find((c) => c.id === s.categoryId)
5565
);
66+
67+
if (searchQuery.trim()) {
68+
const query = searchQuery.toLowerCase();
69+
uncategorizedSnippets = uncategorizedSnippets.filter((s) =>
70+
Object.values(s.content).some((val) => val.toLowerCase().includes(query))
71+
);
72+
}
73+
5674
if (uncategorizedSnippets.length > 0) {
5775
groups.push({
5876
categoryId: '',
@@ -180,7 +198,7 @@
180198
}}
181199
>
182200
<button
183-
class={!selectedCategoryId ? 'active text-left' : 'text-left'}
201+
class={!selectedCategoryId ? 'menu-active text-left' : 'text-left'}
184202
onclick={() => (selectedCategoryId = null)}
185203
>
186204
All Snippets
@@ -196,7 +214,7 @@
196214
}}
197215
>
198216
<button
199-
class={`text-left transition-colors ${selectedCategoryId === category.id ? 'active' : ''}`}
217+
class={`text-left transition-colors ${selectedCategoryId === category.id ? 'menu-active' : ''}`}
200218
onclick={() => (selectedCategoryId = category.id)}
201219
>
202220
{#if category.icon}
@@ -224,8 +242,18 @@
224242
All Snippets
225243
{/if}
226244
</h1>
227-
<div class="flex w-full items-center gap-2 sm:w-auto">
228-
<select
245+
<div class="flex w-full flex-col gap-3 sm:flex-row sm:w-auto sm:items-center">
246+
<label class="input input-sm input-bordered flex items-center gap-2 w-full sm:w-48">
247+
<Search class="h-4 w-4 opacity-50" />
248+
<input
249+
type="text"
250+
class="grow"
251+
placeholder="Search snippets..."
252+
bind:value={searchQuery}
253+
/>
254+
</label>
255+
<div class="flex items-center gap-2 w-full sm:w-auto">
256+
<select
229257
class="select-bordered select font-bold select-sm"
230258
value={dbStore.globalLanguageId}
231259
onchange={(e) => dbStore.setGlobalLanguageId(e.currentTarget.value)}
@@ -244,6 +272,7 @@
244272
<button class="btn btn-primary btn-sm" onclick={addSnippet}>
245273
<Plus class="h-4 w-4" /> Add
246274
</button>
275+
</div>
247276
</div>
248277
</div>
249278

@@ -281,15 +310,20 @@
281310

282311
{#if groupedSnippets.length === 0}
283312
<div class="rounded-box border border-dashed border-base-200 bg-base-100 py-12 text-center"
313+
transition:slide={{ duration: 300 }}
284314
use:droppable={{
285315
container: selectedCategoryId || '',
286316
disabled: !isReorderMode,
287317
callbacks: { onDrop: handleDrop }
288318
}}>
289-
<p class="mb-4 text-base-content/60">No snippets found in this category.</p>
290-
<button class="btn btn-outline btn-sm" onclick={addSnippet}>
291-
Create First Snippet
292-
</button>
319+
{#if searchQuery.trim()}
320+
<p class="text-base-content/60">No snippets found matching "{searchQuery}".</p>
321+
{:else}
322+
<p class="mb-4 text-base-content/60">No snippets found in this category.</p>
323+
<button class="btn btn-outline btn-sm" onclick={addSnippet}>
324+
Create First Snippet
325+
</button>
326+
{/if}
293327
</div>
294328
{:else}
295329
<div class="flex flex-col gap-6">

0 commit comments

Comments
 (0)