mirror of
https://github.com/anotherhadi/iknowyou.git
synced 2026-04-11 16:37:25 +02:00
84 lines
2.4 KiB
Svelte
84 lines
2.4 KiB
Svelte
<script lang="ts">
|
|
interface Sheet {
|
|
id: string;
|
|
title: string;
|
|
description?: string;
|
|
tags?: string[];
|
|
}
|
|
|
|
let { sheets }: { sheets: Sheet[] } = $props();
|
|
|
|
let search = $state("");
|
|
let activeTag: string | null = $state(
|
|
typeof window !== "undefined"
|
|
? new URLSearchParams(window.location.search).get("tag")
|
|
: null
|
|
);
|
|
|
|
const allTags = [...new Set(sheets.flatMap((s) => s.tags ?? []))].sort();
|
|
|
|
const filtered = $derived(
|
|
sheets.filter((s) => {
|
|
const q = search.toLowerCase();
|
|
const matchSearch =
|
|
!q ||
|
|
s.title.toLowerCase().includes(q) ||
|
|
(s.description?.toLowerCase().includes(q) ?? false);
|
|
const matchTag = !activeTag || (s.tags?.includes(activeTag) ?? false);
|
|
return matchSearch && matchTag;
|
|
})
|
|
);
|
|
</script>
|
|
|
|
<div class="flex flex-col gap-4">
|
|
<input
|
|
type="search"
|
|
placeholder="Search cheatsheets..."
|
|
bind:value={search}
|
|
class="input input-bordered w-full"
|
|
/>
|
|
|
|
{#if allTags.length > 0}
|
|
<div class="flex flex-wrap gap-2">
|
|
{#each allTags as tag}
|
|
<button
|
|
class="badge badge-md cursor-pointer transition-colors {activeTag === tag
|
|
? 'badge-primary'
|
|
: 'badge-ghost hover:badge-outline'}"
|
|
onclick={() => (activeTag = activeTag === tag ? null : tag)}
|
|
>
|
|
{tag}
|
|
</button>
|
|
{/each}
|
|
</div>
|
|
{/if}
|
|
|
|
<div class="flex flex-col gap-3">
|
|
{#if filtered.length === 0}
|
|
<p class="text-base-content/40 text-sm py-6 text-center">No results.</p>
|
|
{:else}
|
|
{#each filtered as sheet}
|
|
<a
|
|
href={`/cheatsheets/${sheet.id}`}
|
|
class="card bg-base-200 hover:bg-base-300 transition-colors p-4 flex flex-row items-center gap-4"
|
|
>
|
|
<div class="size-2 rounded-full bg-primary shrink-0"></div>
|
|
<div class="flex-1 min-w-0">
|
|
<div class="font-semibold text-sm">{sheet.title}</div>
|
|
{#if sheet.description}
|
|
<div class="text-base-content/50 text-xs mt-0.5">{sheet.description}</div>
|
|
{/if}
|
|
</div>
|
|
{#if sheet.tags && sheet.tags.length > 0}
|
|
<div class="flex gap-1 shrink-0">
|
|
{#each sheet.tags as tag}
|
|
<span class="badge badge-xs badge-ghost">{tag}</span>
|
|
{/each}
|
|
</div>
|
|
{/if}
|
|
</a>
|
|
{/each}
|
|
{/if}
|
|
</div>
|
|
</div>
|