This commit is contained in:
Timothy Jaeryang Baek committed 2026-06-29 11:35:08 -05:00
1 parent 815446d5bb
commit 61cee42ded
10 files changed
+275 -141

No files matched your search

@@ -1,69 +1,62 @@
<script lang="ts">
import Checkbox from '$lib/components/common/Checkbox.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte';
import { getContext, onMount } from 'svelte';
import TypeaheadSelector from './TypeaheadSelector.svelte';
import { getContext } from 'svelte';
export let skills = [];
let _skills = {};
let searchQuery = '';
type Skill = {
id: string;
name?: string;
description?: string;
};
export let skills: Skill[] = [];
export let selectedSkillIds: string[] = [];
const i18n = getContext('i18n');
const i18n = getContext('i18n') as any;
$: filteredSkillKeys = Object.keys(_skills).filter((id) => {
if (!searchQuery.trim()) return true;
const q = searchQuery.toLowerCase();
return _skills[id].name?.toLowerCase().includes(q) || _skills[id].id?.toLowerCase().includes(q);
});
$: selectedSkills = skills.filter((skill) => selectedSkillIds.includes(skill.id));
$: availableSkills = skills.filter((skill) => !selectedSkillIds.includes(skill.id));
onMount(() => {
_skills = skills.reduce((acc, skill) => {
acc[skill.id] = {
...skill,
selected: selectedSkillIds.includes(skill.id)
};
return acc;
}, {});
});
const selectSkill = (skill: Skill) => {
selectedSkillIds = [...selectedSkillIds, skill.id];
};
</script>
<div>
<div class="flex w-full justify-between mb-1">
<div class=" self-center text-xs font-medium text-gray-500">{$i18n.t('Skills')}</div>
<div class=" self-center text-xs text-gray-500">{$i18n.t('Skills')}</div>
</div>
{#if Object.keys(_skills).length > 10}
<div class="mb-2">
<input
class="w-full text-sm bg-transparent outline-none border border-gray-100 dark:border-gray-800 rounded-lg px-3 py-1.5 placeholder-gray-400"
type="text"
placeholder={$i18n.t('Search skills...')}
bind:value={searchQuery}
/>
</div>
{/if}
<div class="flex flex-col mb-1">
{#if skills.length > 0}
<TypeaheadSelector
id="model-skills-selector"
items={availableSkills}
className="w-48 max-w-full"
placeholder={$i18n.t('Search skills')}
on:select={(e) => {
selectSkill(e.detail);
}}
/>
<div class=" flex items-center flex-wrap">
{#each filteredSkillKeys as skill, skillIdx}
{#each selectedSkills as skill, skillIdx}
<div class=" flex items-center gap-2 mr-3">
<div class="self-center flex items-center">
<Checkbox
state={_skills[skill].selected ? 'checked' : 'unchecked'}
state="checked"
on:change={(e) => {
_skills[skill].selected = e.detail === 'checked';
selectedSkillIds = Object.keys(_skills).filter((s) => _skills[s].selected);
if (e.detail === 'unchecked') {
selectedSkillIds = selectedSkillIds.filter((id) => id !== skill.id);
}
}}
/>
</div>
<Tooltip content={_skills[skill]?.description ?? _skills[skill].id}>
<div class=" py-0.5 text-sm w-full capitalize font-medium">
{_skills[skill].name}
<Tooltip content={skill.description ?? skill.id}>
<div class=" py-0.5 text-xs capitalize">
{skill.name}
</div>
</Tooltip>
</div>