Files
online-energieausweis/src/components/PlzSuche.svelte
Robert Jagtiani bc1b2cef90 Formular
2024-12-10 01:59:35 +01:00

79 lines
1.8 KiB
Svelte

<script lang="ts">
import Label from "./Label.svelte";
import { client } from "src/trpc";
import type { inferProcedureOutput } from "@trpc/server";
import type { AppRouter } from "@ibcornelsen/api";
export let name: string;
export let readonly: boolean = false;
export let city: string | null | undefined;
export let zip: string | null = "";
let hideZipDropdown: boolean = true;
let zipCodes: inferProcedureOutput<AppRouter["v1"]["postleitzahlen"]> = [];
async function fetchZipCodeInformation() {
if (!zip || (zip.length < 2)) {
return
}
try {
const result = await client.v1.postleitzahlen.query({ plz: zip });
if (result.length > 0) {
zipCodes = result;
hideZipDropdown = false;
}
} catch(e) {
console.error(e);
}
}
function clickOutside(element: HTMLElement, callbackFunction: () => any) {
function onClick(event: MouseEvent) {
if (!element.contains(event.target as HTMLElement)) {
callbackFunction();
}
}
document.body.addEventListener('click', onClick);
return {
destroy() {
document.body.removeEventListener('click', onClick);
}
}
}
</script>
<div class="relative" use:clickOutside={() => {
hideZipDropdown = true;
}}>
<input
name={name}
id={name}
type="text"
required
readonly={readonly}
bind:value={zip}
on:input={fetchZipCodeInformation}
on:focus={() => {
if (zipCodes.length > 0) {
hideZipDropdown = false
}
}}
maxlength="5"
/>
<div data-test="plz-container" class="absolute top-[calc(100%+4px)] left-0 w-full bg-white py-2 shadow-md rounded-lg" hidden={hideZipDropdown}>
{#each zipCodes as zipCode}
<div class="hover:bg-gray-100 cursor-pointer px-2 py-0.5" tabindex="-1" on:click={() => {
zip = zipCode.plz;
city = zipCode.stadt;
hideZipDropdown = true;
}}>{zipCode.plz}, {zipCode.stadt}</div>
{/each}
</div>
</div>