add basic search bar

This commit is contained in:
2025-03-24 18:49:20 +01:00
parent 16186baf7f
commit fe3329fc37

View File

@@ -1,5 +1,16 @@
<script lang="ts"> <script lang="ts">
let { data } = $props(); let { data } = $props();
let searchTerm = $state('');
let filteredTasks = $derived(
data.tasks.filter(
(task) =>
task.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
task.tasksToTopics.some((t) =>
t.topic.name.toLowerCase().includes(searchTerm.toLowerCase())
)
)
);
</script> </script>
<div class="flex flex-col items-center p-4"> <div class="flex flex-col items-center p-4">
@@ -16,6 +27,15 @@
</a> </a>
{/if} {/if}
</div> </div>
<!-- Search Bar -->
<div class="w-full max-w-md">
<input
type="text"
bind:value={searchTerm}
placeholder="Search tasks or topics..."
class="w-full px-4 py-2 rounded bg-gray-800 border border-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
</div>
Total progress: {data.tasks.reduce((acc, task) => acc + task.currentPoints, 0)} / {data.tasks.reduce( Total progress: {data.tasks.reduce((acc, task) => acc + task.currentPoints, 0)} / {data.tasks.reduce(
(acc, task) => acc + task.totalPoints, (acc, task) => acc + task.totalPoints,
0 0
@@ -26,103 +46,101 @@
).toFixed(3)}%) ).toFixed(3)}%)
</div> </div>
{#if data.tasks.length > 0} {#if filteredTasks.length > 0}
<div class="overflow-x-auto w-full"> <div class="overflow-x-auto w-full">
{#if data.tasks.length > 0} <!-- Desktop Table View -->
<!-- Desktop Table View --> <div class="hidden md:block">
<div class="hidden md:block"> <table class="min-w-full">
<table class="min-w-full"> <thead>
<thead> <tr class="border-b border-white">
<tr class="border-b border-white"> <th class="px-6 py-3 text-left text-sm font-semibold">Name</th>
<th class="px-6 py-3 text-left text-sm font-semibold">Name</th> <th class="px-6 py-3 text-left text-sm font-semibold">Topics</th>
<th class="px-6 py-3 text-left text-sm font-semibold">Topics</th> <th class="px-6 py-3 text-left text-sm font-semibold min-w-[200px]">Progress</th>
<th class="px-6 py-3 text-left text-sm font-semibold min-w-[200px]">Progress</th> </tr>
</tr> </thead>
</thead> <tbody>
<tbody> {#each filteredTasks as task, index}
{#each data.tasks as task, index} <tr class="{index % 2 === 0 ? 'bg-black' : 'bg-gray-950'} hover:bg-gray-800">
<tr class="{index % 2 === 0 ? 'bg-black' : 'bg-gray-950'} hover:bg-gray-800"> <td class="px-6 py-2 border-b">
<td class="px-6 py-2 border-b"> <a href={`/progress/${task.id}`} class="text-blue-500 hover:underline">
<a href={`/progress/${task.id}`} class="text-blue-500 hover:underline"> {task.name}
{task.name} </a>
</a> </td>
</td> <td class="px-6 py-2 border-b">
<td class="px-6 py-2 border-b"> <a href={`/progress/${task.id}`} class="flex gap-2 flex-wrap">
<a href={`/progress/${task.id}`} class="flex gap-2 flex-wrap"> {#each task.tasksToTopics as topic}
{#each task.tasksToTopics as topic}
<div
class="relative bg-blue-500 text-white rounded-full px-2 py-1 shadow font-medium hover:bg-blue-600 transition cursor-pointer"
title="Click for more details about {topic.topic.name}"
>
{topic.topic.name}
</div>
{/each}
</a>
</td>
<td class="px-6 py-2 border-b min-w-[200px]">
<div class="relative w-full h-6 bg-gray-700 rounded-full overflow-hidden">
<div <div
class="absolute h-full bg-green-500" class="relative bg-blue-500 text-white rounded-full px-2 py-1 shadow font-medium hover:bg-blue-600 transition cursor-pointer"
style="width: {(task.currentPoints / task.totalPoints) * 100}%" title="Click for more details about {topic.topic.name}"
></div> >
<span class="absolute inset-0 flex items-center justify-center text-sm"> {topic.topic.name}
{task.currentPoints} / {task.totalPoints} ({( </div>
(task.currentPoints / task.totalPoints) * {/each}
100 </a>
).toFixed(1)}%) </td>
</span> <td class="px-6 py-2 border-b min-w-[200px]">
</div> <div class="relative w-full h-6 bg-gray-700 rounded-full overflow-hidden">
</td>
</tr>
{/each}
</tbody>
</table>
</div>
<!-- Mobile Card View -->
<div class="md:hidden space-y-4">
{#each data.tasks as task}
<div class="bg-gray-800 rounded-lg p-2 w-full">
<a
href={`/progress/${task.id}`}
class="text-blue-500 hover:underline text-lg font-bold"
>
{task.name}
</a>
<div class="mt-1">
<div class="mb-1"></div>
<span class="font-medium">Topics:</span>
<div class="flex flex-wrap gap-1 mt-1">
{#each task.tasksToTopics as topic}
<div <div
class="bg-blue-500 text-white rounded-full px-2 py-1 shadow font-medium hover:bg-blue-600 transition cursor-pointer" class="absolute h-full bg-green-500"
title="Click for more details about {topic.topic.name}" style="width: {(task.currentPoints / task.totalPoints) * 100}%"
> ></div>
{topic.topic.name} <span class="absolute inset-0 flex items-center justify-center text-sm">
</div> {task.currentPoints} / {task.totalPoints} ({(
{/each} (task.currentPoints / task.totalPoints) *
</div> 100
</div> ).toFixed(1)}%)
<div class="w-full h-4 bg-gray-700 rounded-full relative overflow-hidden"> </span>
<div </div>
class="absolute h-full bg-green-500" </td>
style="width: {(task.currentPoints / task.totalPoints) * 100}%" </tr>
></div> {/each}
<span class="absolute inset-0 flex items-center justify-center text-xs"> </tbody>
{task.currentPoints} / {task.totalPoints} ({( </table>
(task.currentPoints / task.totalPoints) * </div>
100
).toFixed(1)}%) <!-- Mobile Card View -->
</span> <div class="md:hidden space-y-4">
{#each filteredTasks as task}
<div class="bg-gray-800 rounded-lg p-2 w-full">
<a
href={`/progress/${task.id}`}
class="text-blue-500 hover:underline text-lg font-bold"
>
{task.name}
</a>
<div class="mt-1">
<div class="mb-1"></div>
<span class="font-medium">Topics:</span>
<div class="flex flex-wrap gap-1 mt-1">
{#each task.tasksToTopics as topic}
<div
class="bg-blue-500 text-white rounded-full px-2 py-1 shadow font-medium hover:bg-blue-600 transition cursor-pointer"
title="Click for more details about {topic.topic.name}"
>
{topic.topic.name}
</div>
{/each}
</div> </div>
</div> </div>
{/each} <div class="w-full h-4 bg-gray-700 rounded-full relative overflow-hidden">
</div> <div
{:else} class="absolute h-full bg-green-500"
<p class="text-gray-500">No tasks available. Click "Create" to add a new task.</p> style="width: {(task.currentPoints / task.totalPoints) * 100}%"
{/if} ></div>
<span class="absolute inset-0 flex items-center justify-center text-xs">
{task.currentPoints} / {task.totalPoints} ({(
(task.currentPoints / task.totalPoints) *
100
).toFixed(1)}%)
</span>
</div>
</div>
{/each}
</div>
</div> </div>
{:else} {:else}
<p class="text-gray-500">No tasks available. Click "Create" to add a new task.</p> <p class="text-gray-500">
No tasks found matching your search. Try a different keyword or clear the search.
</p>
{/if} {/if}
</div> </div>