[WIP] Integrate local aggregated address search in AddressPicker

Added a `local-search` driver to support aggregated address fetching. Integrated the `getAddressesAggregated` function with `AddressPicker.vue` for dynamic search suggestions and abortable fetch requests.
This commit is contained in:
2025-08-15 01:08:56 +02:00
parent 5a284fe6cf
commit 845aa040cc
3 changed files with 66 additions and 2 deletions

View File

@@ -77,7 +77,7 @@ final readonly class AddressReferenceRepository implements ObjectRepository
$connection = $this->entityManager->getConnection(); $connection = $this->entityManager->getConnection();
$qb = $connection->createQueryBuilder(); $qb = $connection->createQueryBuilder();
$qb->select('var.street AS street', 'cmpc.id AS postcode_id', 'cmpc.code AS code', 'cmpc.label AS label', 'jsonb_object_agg(var.address_id, var.streetnumber ORDER BY var.row_number) AS positions') $qb->select('row_number() OVER () AS row_number','var.street AS street', 'cmpc.id AS postcode_id', 'cmpc.code AS code', 'cmpc.label AS label', 'jsonb_object_agg(var.address_id, var.streetnumber ORDER BY var.row_number) AS positions')
->from('view_chill_main_address_reference', 'var') ->from('view_chill_main_address_reference', 'var')
->innerJoin('var', 'chill_main_postal_code', 'cmpc', 'cmpc.id = var.postcode_id') ->innerJoin('var', 'chill_main_postal_code', 'cmpc', 'cmpc.id = var.postcode_id')
->groupBy('cmpc.id', 'var.street') ->groupBy('cmpc.id', 'var.street')

View File

@@ -1,6 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { Address } from "ChillMainAssets/types"; import { Address } from "ChillMainAssets/types";
import SearchBar from "ChillMainAssets/vuejs/AddressPicker/Component/SearchBar.vue"; import SearchBar from "ChillMainAssets/vuejs/AddressPicker/Component/SearchBar.vue";
import {
AddressAggregated,
getAddressesAggregated,
} from "ChillMainAssets/vuejs/AddressPicker/driver/local-search";
import { Ref, ref } from "vue";
interface AddressPickerProps { interface AddressPickerProps {
suggestions?: Address[]; suggestions?: Address[];
@@ -10,14 +15,43 @@ const props = withDefaults(defineProps<AddressPickerProps>(), {
suggestions: () => [], suggestions: () => [],
}); });
const onSearch = function (search: string) { const addresses: Ref<AddressAggregated[]> = ref([]);
let abortController: null | AbortController = null;
const onSearch = async function (search: string): Promise<void> {
if (null !== abortController) {
abortController.abort();
}
if ("" === search) {
addresses.value = [];
abortController = null;
return;
}
abortController = new AbortController();
console.log("onSearch", search); console.log("onSearch", search);
try {
addresses.value = await getAddressesAggregated(search, abortController);
} catch (e: unknown) {
if (e instanceof DOMException && e.name === "AbortError") {
console.log("search aborted for:", search);
return;
}
throw e;
}
}; };
</script> </script>
<template> <template>
<search-bar @search="onSearch"></search-bar> <search-bar @search="onSearch"></search-bar>
<p>test</p> <p>test</p>
<p v-for="a in addresses" :key="a.row_number">
{{ a.street }}, positions: {{ a.positions[0] }}
</p>
</template> </template>
<style scoped lang="scss"></style> <style scoped lang="scss"></style>

View File

@@ -0,0 +1,30 @@
export interface AddressAggregated {
row_number: number;
street: string;
postcode_id: number;
code: string;
label: string;
positions: Record<string, string>;
}
/**
* @throws {DOMException} when fetch is aborted, the property name is always equals to 'AbortError'
*/
export const getAddressesAggregated = async (
search: string,
abortController: AbortController,
): Promise<AddressAggregated[]> => {
const params = new URLSearchParams({ q: search });
let response = null;
response = await fetch(
`/api/1.0/main/address-reference/aggregated/search?${params}`,
{ signal: abortController.signal },
);
if (response.ok) {
return await response.json();
}
throw new Error(response.statusText);
};