[WIP] Add postal code search integration to AddressPicker

Implemented `getPostalCodes` function in `local-search` driver and connected it with `AddressPicker.vue`. Introduced UI changes to display postal codes alongside addresses and ensured search requests are abortable.
This commit is contained in:
2025-08-16 00:08:03 +02:00
parent b16e6c4517
commit b1703a4187
2 changed files with 82 additions and 7 deletions

View File

@@ -3,7 +3,9 @@ import { Address } from "ChillMainAssets/types";
import SearchBar from "ChillMainAssets/vuejs/AddressPicker/Component/SearchBar.vue"; import SearchBar from "ChillMainAssets/vuejs/AddressPicker/Component/SearchBar.vue";
import { import {
AddressAggregated, AddressAggregated,
AssociatedPostalCode,
getAddressesAggregated, getAddressesAggregated,
getPostalCodes,
} from "ChillMainAssets/vuejs/AddressPicker/driver/local-search"; } from "ChillMainAssets/vuejs/AddressPicker/driver/local-search";
import { Ref, ref } from "vue"; import { Ref, ref } from "vue";
@@ -16,24 +18,35 @@ const props = withDefaults(defineProps<AddressPickerProps>(), {
}); });
const addresses: Ref<AddressAggregated[]> = ref([]); const addresses: Ref<AddressAggregated[]> = ref([]);
let abortController: null | AbortController = null; const postalCodes: Ref<AssociatedPostalCode[]> = ref([]);
let abortControllerSearchAddress: null | AbortController = null;
let abortControllerSearchPostalCode: null | AbortController = null;
const onSearch = async function (search: string): Promise<void> { const onSearch = async function (search: string): Promise<void> {
if (null !== abortController) { performSearchForAddress(search);
abortController.abort(); performSearchForPostalCode(search);
};
const performSearchForAddress = async (search: string): Promise<void> => {
if (null !== abortControllerSearchAddress) {
abortControllerSearchAddress.abort();
} }
if ("" === search) { if ("" === search) {
addresses.value = []; addresses.value = [];
abortController = null; abortControllerSearchAddress = null;
return; return;
} }
abortController = new AbortController(); abortControllerSearchAddress = new AbortController();
console.log("onSearch", search); console.log("onSearch", search);
try { try {
addresses.value = await getAddressesAggregated(search, abortController); addresses.value = await getAddressesAggregated(
search,
abortControllerSearchAddress,
);
abortControllerSearchAddress = null;
} catch (e: unknown) { } catch (e: unknown) {
if (e instanceof DOMException && e.name === "AbortError") { if (e instanceof DOMException && e.name === "AbortError") {
console.log("search aborted for:", search); console.log("search aborted for:", search);
@@ -44,6 +57,37 @@ const onSearch = async function (search: string): Promise<void> {
throw e; throw e;
} }
}; };
const performSearchForPostalCode = async (search: string): Promise<void> => {
if (null !== abortControllerSearchPostalCode) {
abortControllerSearchPostalCode.abort();
}
if ("" === search) {
addresses.value = [];
abortControllerSearchPostalCode = null;
return;
}
abortControllerSearchPostalCode = new AbortController();
console.log("onSearch", search);
try {
postalCodes.value = await getPostalCodes(
search,
abortControllerSearchPostalCode,
);
abortControllerSearchPostalCode = null;
} catch (e: unknown) {
if (e instanceof DOMException && e.name === "AbortError") {
console.log("search postal code aborted for:", search);
return;
}
throw e;
}
};
</script> </script>
<template> <template>
@@ -52,6 +96,7 @@ const onSearch = async function (search: string): Promise<void> {
<p v-for="a in addresses" :key="a.row_number"> <p v-for="a in addresses" :key="a.row_number">
{{ a.street }}, positions: {{ a.positions[0] }} {{ a.street }}, positions: {{ a.positions[0] }}
</p> </p>
<p v-for="pc in postalCodes" :key="pc.postcode_id">{{ pc }}</p>
</template> </template>
<style scoped lang="scss"></style> <style scoped lang="scss"></style>

View File

@@ -1,3 +1,5 @@
import { TranslatableString } from "ChillMainAssets/types";
export interface AddressAggregated { export interface AddressAggregated {
row_number: number; row_number: number;
street: string; street: string;
@@ -7,6 +9,15 @@ export interface AddressAggregated {
positions: Record<string, string>; positions: Record<string, string>;
} }
export interface AssociatedPostalCode {
postcode_id: number;
code: string;
label: string;
country_id: number;
country_code: string;
country_name: TranslatableString;
}
/** /**
* @throws {DOMException} when fetch is aborted, the property name is always equals to 'AbortError' * @throws {DOMException} when fetch is aborted, the property name is always equals to 'AbortError'
*/ */
@@ -14,7 +25,7 @@ export const getAddressesAggregated = async (
search: string, search: string,
abortController: AbortController, abortController: AbortController,
): Promise<AddressAggregated[]> => { ): Promise<AddressAggregated[]> => {
const params = new URLSearchParams({ q: search }); const params = new URLSearchParams({ q: search.trim() });
let response = null; let response = null;
response = await fetch( response = await fetch(
@@ -28,3 +39,22 @@ export const getAddressesAggregated = async (
throw new Error(response.statusText); throw new Error(response.statusText);
}; };
export const getPostalCodes = async (
search: string,
abortController: AbortController,
): Promise<AssociatedPostalCode[]> => {
const params = new URLSearchParams({ q: search.trim() });
let response = null;
response = await fetch(
`/api/1.0/main/address-reference/postal-code/search?${params}`,
{ signal: abortController.signal },
);
if (response.ok) {
return await response.json();
}
throw new Error(response.statusText);
};