File size: 3,767 Bytes
10b8070
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33c382c
 
 
10b8070
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<script lang="ts">
	import { base } from "$app/paths";
	import type { ToolLogoColor, ToolLogoIcon } from "$lib/types/Tool";
	import { debounce } from "$lib/utils/debounce";
	import { onMount } from "svelte";
	import ToolLogo from "./ToolLogo.svelte";

	import CarbonClose from "~icons/carbon/close";

	interface ToolSuggestion {
		_id: string;
		displayName: string;
		createdByName: string;
		color: ToolLogoColor;
		icon: ToolLogoIcon;
	}

	export let toolIds: string[] = [];

	let selectedValues: ToolSuggestion[] = [];

	onMount(async () => {
		selectedValues = await Promise.all(
			toolIds.map(async (id) => await fetch(`${base}/api/tools/${id}`).then((res) => res.json()))
		);

		await fetchSuggestions("");
	});

	let inputValue = "";
	let maxValues = 3;

	let suggestions: ToolSuggestion[] = [];

	async function fetchSuggestions(query: string) {
		suggestions = (await fetch(`${base}/api/tools/search?q=${query}`).then((res) =>
			res.json()
		)) satisfies ToolSuggestion[];
	}

	const debouncedFetch = debounce((query: string) => fetchSuggestions(query), 300);

	function addValue(value: ToolSuggestion) {
		if (selectedValues.length < maxValues && !selectedValues.includes(value)) {
			selectedValues = [...selectedValues, value];
			toolIds = [...toolIds, value._id];
			inputValue = "";
			suggestions = [];
		}
	}

	function removeValue(id: ToolSuggestion["_id"]) {
		selectedValues = selectedValues.filter((v) => v._id !== id);
		toolIds = selectedValues.map((value) => value._id);
	}
</script>

{#if selectedValues.length > 0}
	<div class="flex flex-wrap items-center justify-center gap-2">
		{#each selectedValues as value}
			<div
				class="flex items-center justify-center space-x-2 rounded border border-gray-300 bg-gray-200 px-2 py-1"
			>
				<ToolLogo color={value.color} icon={value.icon} size="sm" />
				<div class="flex flex-col items-center justify-center py-1">
					<a
						href={`${base}/tools/${value._id}`}
						target="_blank"
						class="line-clamp-1 truncate font-semibold text-blue-600 hover:underline"
						>{value.displayName}</a
					>
					{#if value.createdByName}
						<p class="text-center text-xs text-gray-500">
							Created by
							<a class="underline" href="{base}/tools?user={value.createdByName}" target="_blank"
								>{value.createdByName}</a
							>
						</p>
					{:else}
						<p class="text-center text-xs text-gray-500">Official HuggingChat tool</p>
					{/if}
				</div>
				<button
					on:click|stopPropagation|preventDefault={() => removeValue(value._id)}
					class="text-lg text-gray-600"
				>
					<CarbonClose />
				</button>
			</div>
		{/each}
	</div>
{/if}

{#if selectedValues.length < maxValues}
	<div class="group relative block">
		<input
			type="text"
			bind:value={inputValue}
			on:input={(ev) => {
				inputValue = ev.currentTarget.value;
				debouncedFetch(inputValue);
			}}
			disabled={selectedValues.length >= maxValues}
			class="w-full rounded border border-gray-200 bg-gray-100 px-3 py-2"
			class:opacity-50={selectedValues.length >= maxValues}
			class:bg-gray-100={selectedValues.length >= maxValues}
			placeholder="Type to search tools..."
		/>
		{#if suggestions.length > 0}
			<div
				class="invisible absolute z-10 mt-1 w-full rounded border border-gray-300 bg-white shadow-lg group-focus-within:visible"
			>
				{#each suggestions as suggestion}
					<button
						on:click|stopPropagation|preventDefault={() => addValue(suggestion)}
						class="w-full cursor-pointer px-3 py-2 text-left hover:bg-blue-500 hover:text-white"
					>
						{suggestion.displayName}
						{#if suggestion.createdByName}
							<span class="text-xs text-gray-500"> by {suggestion.createdByName}</span>
						{/if}
					</button>
				{/each}
			</div>
		{/if}
	</div>
{/if}