applications-tracker/site/src/routes/ApplicationsList.svelte

125 lines
2.8 KiB
Svelte

<script lang="ts">
import { applicationStore, type Application } from '$lib/ApplicationsStore.svelte';
import { get } from '$lib/utils';
import { onMount } from 'svelte';
let filter = $state('');
onMount(() => {
applicationStore.loadAll();
});
let apps = $derived(
applicationStore.all.filter((i) => i.status_id === null && !i.linked_application)
);
let internal = $derived(
apps.filter((i) => {
if (!filter) {
return true;
}
const f = new RegExp(filter, 'ig');
let x = i.title;
if (i.company) {
x = `${x} @ ${i.company}`;
}
return x.match(f);
})
);
let gettingNext = $state(false);
async function getNext() {
gettingNext = true;
try {
const r: Application[] = await get('mail/getNext');
for (const app of r) {
applicationStore.all.push(app);
}
if (r.length > 0) {
applicationStore.loadItem = r[0];
}
} catch (e) {
console.error('TODO inform user', e);
} finally {
gettingNext = false;
}
}
function docKey(e: KeyboardEvent) {
if (e.ctrlKey && e.code === 'KeyJ' && internal.length > 0) {
applicationStore.loadItem = internal[0];
e.stopPropagation();
e.preventDefault();
return;
}
}
$effect(() => {
document.addEventListener('keydown', docKey, false);
return () => {
document.removeEventListener('keydown', docKey);
};
});
</script>
<div class="w-2/12 card p-3 flex flex-col flex-shrink min-h-0">
<h1>To Apply</h1>
<div class="flex pb-2 items-center">
<input placeholder="Filter" class="p-2 flex-grow" bind:value={filter} />
<div>
{internal.length}
</div>
{#if !gettingNext}
<button class="p-2 text-violet-500" onclick={() => getNext()}>
<span class="bi bi-send-arrow-down"></span>
</button>
{:else}
<span class="bi bi-arrow-repeat animate-spin"></span>
{/if}
</div>
<div class="overflow-auto flex-grow p-2">
{#each internal as item}
<div
class="card p-2 my-2 bg-slate-100 max-w-full"
draggable="true"
ondragstart={() => applicationStore.dragStart(item)}
ondragend={() => {
window.requestAnimationFrame(() => {
applicationStore.dragEnd();
});
}}
role="none"
>
<div
class="max-w-full"
class:animate-pulse={applicationStore.dragging?.id === item.id}
>
<h2 class="text-lg text-blue-500 flex gap-2 max-w-full overflow-hidden">
<div class="flex-grow max-w-[90%]">
<div class="whitespace-nowrap overflow-hidden">
{item.title}
</div>
{#if item.company}
<div class="text-violet-800">
@ {item.company}
</div>
{/if}
</div>
<div>
{#if item.url.includes('linkedin')}
<span class="bi bi-linkedin"></span>
{:else if item.url.includes('glassdoor')}
<span class="bi bi-eyeglasses"></span>
{/if}
</div>
</h2>
</div>
</div>
{/each}
</div>
</div>