wip
This commit is contained in:
		| @@ -7,113 +7,8 @@ | ||||
| 	} from "@odit/lfk-client-js"; | ||||
| 	import Select from "svelte-select"; | ||||
| 	import toast from "svelte-french-toast"; | ||||
| 	import { onMount } from "svelte"; | ||||
| 	import VirtualSelect from "./VirtualSelect.svelte"; | ||||
|  | ||||
| 	// | ||||
| 	let options = [ | ||||
| 		{ label: "Bulbasaur", value: { id: 456 } }, | ||||
| 		{ label: "Ivysaur", value: { id: 456 } }, | ||||
| 		{ label: "Venusaur", value: { id: 456 } }, | ||||
| 		{ label: "Charmander", value: { id: 456 } }, | ||||
| 		{ label: "Charmeleon", value: { id: 456 } }, | ||||
| 		{ label: "Charizard", value: { id: 456 } }, | ||||
| 		{ label: "Squirtle", value: { id: 456 } }, | ||||
| 		{ label: "Wartortle", value: { id: 456 } }, | ||||
| 		{ label: "Blastoise", value: { id: 456 } }, | ||||
| 		{ label: "Caterpie", value: { id: 456 } }, | ||||
| 		{ label: "Metapod", value: { id: 456 } }, | ||||
| 		{ label: "Butterfree", value: { id: 456 } }, | ||||
| 		{ label: "Weedle", value: { id: 456 } }, | ||||
| 		{ label: "Kakuna", value: { id: 456 } }, | ||||
| 		{ label: "Beedrill", value: { id: 456 } }, | ||||
| 		{ label: "Pidgey", value: { id: 456 } }, | ||||
| 		{ label: "Pidgeotto", value: { id: 456 } }, | ||||
| 		{ label: "Pidgeot", value: { id: 456 } }, | ||||
| 		{ label: "Rattata", value: { id: 456 } }, | ||||
| 		{ label: "Raticate", value: { id: 456 } }, | ||||
| 		{ label: "Spearow", value: { id: 456 } }, | ||||
| 		{ label: "Fearow", value: { id: 456 } }, | ||||
| 		{ label: "Ekans", value: { id: 456 } }, | ||||
| 		{ label: "Arbok", value: { id: 456 } }, | ||||
| 		{ label: "Pikachu", value: { id: 456 } }, | ||||
| 		{ label: "Raichu", value: { id: 456 } }, | ||||
| 		{ label: "Sandshrew", value: { id: 456 } }, | ||||
| 		{ label: "Sandslash", value: { id: 456 } }, | ||||
| 		{ label: "Nidoran♀", value: { id: 456 } }, | ||||
| 		{ label: "Nidorina", value: { id: 456 } }, | ||||
| 		{ label: "Nidoqueen", value: { id: 456 } }, | ||||
| 		{ label: "Nidoran♂", value: { id: 456 } }, | ||||
| 		{ label: "Nidorino", value: { id: 456 } }, | ||||
| 		{ label: "Nidoking", value: { id: 456 } }, | ||||
| 		{ label: "Clefairy", value: { id: 456 } }, | ||||
| 		{ label: "Clefable", value: { id: 456 } }, | ||||
| 		{ label: "Vulpix", value: { id: 456 } }, | ||||
| 		{ label: "Ninetales", value: { id: 456 } }, | ||||
| 		{ label: "Jigglypuff", value: { id: 456 } }, | ||||
| 		{ label: "Wigglytuff", value: { id: 456 } }, | ||||
| 		{ label: "Zubat", value: { id: 456 } }, | ||||
| 		{ label: "Golbat", value: { id: 456 } }, | ||||
| 		{ label: "Oddish", value: { id: 456 } }, | ||||
| 		{ label: "Gloom", value: { id: 456 } }, | ||||
| 		{ label: "Vileplume", value: { id: 456 } }, | ||||
| 		{ label: "Paras", value: { id: 456 } }, | ||||
| 		{ label: "Parasect", value: { id: 456 } }, | ||||
| 		{ label: "Venonat", value: { id: 456 } }, | ||||
| 		{ label: "Venomoth", value: { id: 456 } }, | ||||
| 		{ label: "Diglett", value: { id: 456 } }, | ||||
| 		{ label: "Dugtrio", value: { id: 456 } }, | ||||
| 		{ label: "Meowth", value: { id: 456 } }, | ||||
| 		{ label: "Persian", value: { id: 456 } }, | ||||
| 		{ label: "Psyduck", value: { id: 456 } }, | ||||
| 		{ label: "Golduck", value: { id: 456 } }, | ||||
| 		{ label: "Mankey", value: { id: 456 } }, | ||||
| 		{ label: "Primeape", value: { id: 456 } }, | ||||
| 		{ label: "Growlithe", value: { id: 456 } }, | ||||
| 		{ label: "Arcanine", value: { id: 456 } }, | ||||
| 		{ label: "Poliwag", value: { id: 456 } }, | ||||
| 		{ label: "Poliwhirl", value: { id: 456 } }, | ||||
| 		{ label: "Poliwrath", value: { id: 456 } }, | ||||
| 		{ label: "Abra", value: { id: 456 } }, | ||||
| 		{ label: "Kadabra", value: { id: 456 } }, | ||||
| 		{ label: "Alakazam", value: { id: 456 } }, | ||||
| 		{ label: "Machop", value: { id: 456 } }, | ||||
| 		{ label: "Machoke", value: { id: 456 } }, | ||||
| 		{ label: "Machamp", value: { id: 456 } }, | ||||
| 		{ label: "Bellsprout", value: { id: 456 } }, | ||||
| 		{ label: "Weepinbell", value: { id: 456 } }, | ||||
| 		{ label: "Victreebel", value: { id: 456 } }, | ||||
| 		{ label: "Tentacool", value: { id: 456 } }, | ||||
| 		{ label: "Tentacruel", value: { id: 456 } }, | ||||
| 		{ label: "Geodude", value: { id: 456 } }, | ||||
| 		{ label: "Graveler", value: { id: 456 } }, | ||||
| 		{ label: "Golem", value: { id: 456 } }, | ||||
| 		{ label: "Ponyta", value: { id: 456 } }, | ||||
| 		{ label: "Rapidash", value: { id: 456 } }, | ||||
| 		{ label: "Slowpoke", value: { id: 456 } }, | ||||
| 		{ label: "Slowbro", value: { id: 456 } }, | ||||
| 		{ label: "Magnemite", value: { id: 456 } }, | ||||
| 		{ label: "Magneton", value: { id: 456 } }, | ||||
| 		{ label: "Farfetch'd", value: { id: 456 } }, | ||||
| 		{ label: "Doduo", value: { id: 456 } }, | ||||
| 		{ label: "Dodrio", value: { id: 456 } }, | ||||
| 		{ label: "Seel", value: { id: 456 } }, | ||||
| 		{ label: "Dewgong", value: { id: 456 } }, | ||||
| 		{ label: "Grimer", value: { id: 456 } }, | ||||
| 		{ label: "Muk", value: { id: 456 } }, | ||||
| 		{ label: "Shellder", value: { id: 456 } }, | ||||
| 		{ label: "Cloyster", value: { id: 456 } }, | ||||
| 		{ label: "Gastly", value: { id: 456 } }, | ||||
| 		{ label: "Haunter", value: { id: 456 } }, | ||||
| 	]; | ||||
| 	let selectedOption; | ||||
|  | ||||
| 	function handleSelect(event) { | ||||
| 		selectedOption = event.detail; | ||||
| 		console.log("Selected:", selectedOption); | ||||
| 	} | ||||
| 	// | ||||
|  | ||||
| 	let runners = []; | ||||
| 	let donors = []; | ||||
| 	let runnerinfo = { id: 0, firstname: "", lastname: "" }; | ||||
| @@ -157,15 +52,16 @@ | ||||
| 	} | ||||
| 	loadDonors(); | ||||
|  | ||||
| 	const getRunnerLabel = (option) => | ||||
| 		option.firstname + | ||||
| 		" " + | ||||
| 		(option.middlename || "") + | ||||
| 		" " + | ||||
| 		option.lastname + | ||||
| 		" [#" + | ||||
| 		option.id + | ||||
| 		"]"; | ||||
| 	const getRunnerLabel = (option) => { | ||||
| 		return ( | ||||
| 			[option.firstname, option.middlename, option.lastname] | ||||
| 				.join(" ") | ||||
| 				.replace("  ", " ") + | ||||
| 			" [#" + | ||||
| 			option.id + | ||||
| 			"]" | ||||
| 		); | ||||
| 	}; | ||||
|  | ||||
| 	const filterRunners = (label, filterText, option) => { | ||||
| 		if (filterText.startsWith("#")) { | ||||
| @@ -188,10 +84,6 @@ | ||||
| 			c.click(); | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	onMount(() => { | ||||
| 		document.querySelector("#wrapper_runner_select input").focus(); | ||||
| 	}); | ||||
| </script> | ||||
|  | ||||
| <div class="p-4"> | ||||
| @@ -211,40 +103,27 @@ | ||||
| 			{/if} | ||||
|  | ||||
| 			<!--  --> | ||||
| 			<h4 class="text-xl font-semibold">{$_("runner")}</h4> | ||||
| 			<VirtualSelect | ||||
| 				{options} | ||||
| 				filterFn={(option, searchTerm) => { | ||||
| 					// Example: Match if option starts with search term (case-insensitive) | ||||
| 					return option.label.toLowerCase().startsWith(searchTerm.toLowerCase()); | ||||
| 				autofocus={true} | ||||
| 				on:onClear={() => { | ||||
| 					console.log("Cleared selection"); | ||||
| 				}} | ||||
| 				bind:selected={selectedOption} | ||||
| 				options={runners} | ||||
| 				filterFn={(option, searchTerm) => { | ||||
| 					return option.label.toLowerCase().includes(searchTerm.toLowerCase()); | ||||
| 				}} | ||||
| 				bind:selected={runnerinfo} | ||||
| 				inputAriaLabel={$_("search-for-runner-by-name-or-id")} | ||||
| 				inputPlaceholder={$_("search-for-runner-by-name-or-id")} | ||||
|         noOptionsText={$_("no-runners-found")} | ||||
| 				on:select={handleSelect} | ||||
| 				noOptionsText={$_("no-runners-found")} | ||||
| 				on:onSelected={() => { | ||||
| 					document.querySelector("#donation_amount_eur").focus(); | ||||
| 				}} | ||||
| 			/> | ||||
| 			{#if selectedOption} | ||||
| 				<p class="mt-4 text-lg">Selected: {JSON.stringify(selectedOption)}</p> | ||||
| 			{/if} | ||||
| 			<!--  --> | ||||
|  | ||||
| 			<!-- Runner Selection --> | ||||
| 			<div id="wrapper_runner_select"> | ||||
| 				<h4 class="text-xl font-semibold">{$_("runner")}</h4> | ||||
| 				<Select | ||||
| 					containerClasses="rounded-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2" | ||||
| 					itemFilter={(label, filterText, option) => | ||||
| 						filterRunners(label, filterText, option)} | ||||
| 					items={runners} | ||||
| 					showChevron={true} | ||||
| 					placeholder={$_("search-for-runner-by-name-or-id")} | ||||
| 					noOptionsMessage={$_("no-runners-found")} | ||||
| 					on:select={(selectedValue) => { | ||||
| 						runnerinfo = selectedValue.detail.value; | ||||
| 						document.querySelector("#donation_amount_eur").focus(); | ||||
| 					}} | ||||
| 					on:clear={() => (runnerinfo = { id: 0, firstname: "", lastname: "" })} | ||||
| 				/> | ||||
| 			</div> | ||||
| 			<!-- {#if runnerinfo} | ||||
| 				<p class="mt-4 text-lg">Selected: {JSON.stringify(runnerinfo)}</p> | ||||
| 			{/if} --> | ||||
|  | ||||
| 			<!-- Amount Input --> | ||||
| 			<div> | ||||
|   | ||||
| @@ -10,6 +10,7 @@ | ||||
| 	export let toggleAriaLabel = "Toggle dropdown"; | ||||
| 	export let clearAriaLabel = "Clear selection"; | ||||
| 	export let filterFn = null; // Custom filter function | ||||
| 	export let autofocus = false; // Autofocus input | ||||
|  | ||||
| 	// Internal state | ||||
| 	let searchTerm = ""; | ||||
| @@ -21,6 +22,7 @@ | ||||
| 	let itemHeight = 40; // Fixed height for each option (in pixels) | ||||
| 	let visibleCount = 10; // Default number of items to render | ||||
| 	let focusedIndex = -1; // Track the focused option index (-1 means no focus) | ||||
| 	let inputElement; // Reference to input element | ||||
|  | ||||
| 	const dispatch = createEventDispatcher(); | ||||
|  | ||||
| @@ -69,7 +71,7 @@ | ||||
| 	function selectOption(option) { | ||||
| 		selected = option.value; | ||||
| 		isOpen = false; | ||||
| 		searchTerm = ""; | ||||
| 		searchTerm = option.label; | ||||
| 		focusedIndex = -1; | ||||
| 		dispatch("onSelected", option.value); | ||||
| 	} | ||||
| @@ -80,6 +82,7 @@ | ||||
| 		searchTerm = ""; | ||||
| 		focusedIndex = -1; | ||||
| 		dispatch("onSelected", null); | ||||
| 		dispatch("onClear"); | ||||
| 	} | ||||
|  | ||||
| 	// Toggle dropdown | ||||
| @@ -157,11 +160,14 @@ | ||||
| 		updateVisibleItems(); | ||||
| 	} | ||||
|  | ||||
| 	// Initialize container size observer | ||||
| 	// Initialize container size observer and autofocus | ||||
| 	onMount(() => { | ||||
| 		if (container) { | ||||
| 			const resizeObserver = new ResizeObserver(updateVisibleCount); | ||||
| 			resizeObserver.observe(container); | ||||
| 			if (autofocus && inputElement) { | ||||
| 				inputElement.focus(); | ||||
| 			} | ||||
| 			return () => resizeObserver.disconnect(); | ||||
| 		} | ||||
| 	}); | ||||
| @@ -186,6 +192,7 @@ | ||||
| 		<input | ||||
| 			type="text" | ||||
| 			bind:value={searchTerm} | ||||
| 			bind:this={inputElement} | ||||
| 			placeholder={getDisplayText()} | ||||
| 			class="w-full bg-transparent focus:outline-none {selected | ||||
| 				? 'text-black' | ||||
|   | ||||
		Reference in New Issue
	
	Block a user