[WIP] refactorization to show details of an address

This commit is contained in:
2025-08-18 13:14:10 +02:00
parent b1a7680b5e
commit 279901ac93
17 changed files with 341 additions and 84 deletions

View File

@@ -45,6 +45,7 @@
"webpack-cli": "^5.0.1" "webpack-cli": "^5.0.1"
}, },
"dependencies": { "dependencies": {
"@fragaria/address-formatter": "^6.6.1",
"@fullcalendar/core": "^6.1.4", "@fullcalendar/core": "^6.1.4",
"@fullcalendar/daygrid": "^6.1.4", "@fullcalendar/daygrid": "^6.1.4",
"@fullcalendar/interaction": "^6.1.4", "@fullcalendar/interaction": "^6.1.4",

View File

@@ -97,7 +97,9 @@ final readonly class AddressReferenceRepository implements AddressReferenceRepos
$result = $qb->executeQuery(); $result = $qb->executeQuery();
return $result->iterateAssociative(); foreach ($result->iterateAssociative() as $row) {
yield [...$row, 'positions' => json_decode($row['positions'], true, 512, JSON_THROW_ON_ERROR)];
}
} }
/** /**

View File

@@ -74,6 +74,7 @@ export interface Postcode {
name: string; name: string;
code: string; code: string;
center: Point; center: Point;
country: Country;
} }
export interface Point { export interface Point {
@@ -89,6 +90,28 @@ export interface Country {
export type AddressRefStatus = "match" | "to_review" | "reviewed"; export type AddressRefStatus = "match" | "to_review" | "reviewed";
/**
* An interface to create an address
*/
export interface AddressCreation {
confidential: boolean;
isNoAddress: boolean;
street: string;
streetNumber: string;
postcode: Postcode;
point: Point; // [number, number]; // [longitude, latitude]
addressReference: AddressReference;
validFrom: DateTime|null;
floor: string;
corridor: string;
steps: string;
flat: string;
buildingName: string;
distribution: string;
extra: string;
}
export interface Address { export interface Address {
type: "address"; type: "address";
address_id: number; address_id: number;
@@ -107,7 +130,7 @@ export interface Address {
confidential: boolean; confidential: boolean;
lines: string[]; lines: string[];
addressReference: AddressReference | null; addressReference: AddressReference | null;
validFrom: DateTime; validFrom: DateTime | null; // TODO there is no null for validFrom
validTo: DateTime | null; validTo: DateTime | null;
point: Point | null; point: Point | null;
refStatus: AddressRefStatus; refStatus: AddressRefStatus;

View File

@@ -19,7 +19,7 @@ const closeModal = () => {
</script> </script>
<template> <template>
<modal v-if="showModal" :modal-dialog-class="modalDialogClasses" @close="closeModal"> <modal v-if="showModal" :hide-footer="false" :modal-dialog-class="modalDialogClasses" @close="closeModal">
<template v-slot:header>TODO</template> <template v-slot:header>TODO</template>
<template v-slot:body> <template v-slot:body>
<AddressPicker></AddressPicker> <AddressPicker></AddressPicker>

View File

@@ -1,13 +1,15 @@
<script setup lang="ts"> <script setup lang="ts">
import { Address } from "ChillMainAssets/types"; import {Address, AddressReference} 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, AssociatedPostalCode, fetchAddressReference,
getAddressesAggregated, getAddressesAggregated,
getPostalCodes, 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";
import AddressAggregatedList from "ChillMainAssets/vuejs/AddressPicker/Component/AddressAggregatedList.vue";
import AddressDetailsForm from "ChillMainAssets/vuejs/AddressPicker/Component/AddressDetailsForm.vue";
interface AddressPickerProps { interface AddressPickerProps {
suggestions?: Address[]; suggestions?: Address[];
@@ -19,14 +21,23 @@ const props = withDefaults(defineProps<AddressPickerProps>(), {
const addresses: Ref<AddressAggregated[]> = ref([]); const addresses: Ref<AddressAggregated[]> = ref([]);
const postalCodes: Ref<AssociatedPostalCode[]> = ref([]); const postalCodes: Ref<AssociatedPostalCode[]> = ref([]);
const searchTokens: Ref<string[]> = ref([]);
const addressReference: Ref<AddressReference|null> = ref(null);
let abortControllerSearchAddress: null | AbortController = null; let abortControllerSearchAddress: null | AbortController = null;
let abortControllerSearchPostalCode: null | AbortController = null; let abortControllerSearchPostalCode: null | AbortController = null;
const onSearch = async function (search: string): Promise<void> { const onSearch = async function (search: string): Promise<void> {
performSearchForAddress(search); performSearchForAddress(search);
performSearchForPostalCode(search); performSearchForPostalCode(search);
searchTokens.value = [search];
}; };
const onPickPosition = async (id: string) => {
console.log('Pick Position', id);
addressReference.value = await fetchAddressReference(id);
}
const performSearchForAddress = async (search: string): Promise<void> => { const performSearchForAddress = async (search: string): Promise<void> => {
if (null !== abortControllerSearchAddress) { if (null !== abortControllerSearchAddress) {
abortControllerSearchAddress.abort(); abortControllerSearchAddress.abort();
@@ -92,11 +103,20 @@ const performSearchForPostalCode = async (search: string): Promise<void> => {
<template> <template>
<search-bar @search="onSearch"></search-bar> <search-bar @search="onSearch"></search-bar>
<p>test</p> <div class="address-pick-content">
<p v-for="a in addresses" :key="a.row_number"> <div>
{{ a.street }}, positions: {{ a.positions[0] }} <address-aggregated-list :addresses="addresses" :search-tokens="searchTokens" @pick-position="(id) => onPickPosition(id)"></address-aggregated-list>
</p> </div>
<p v-for="pc in postalCodes" :key="pc.postcode_id">{{ pc }}</p> <div v-if="addressReference !== null">
<address-details-form :address="addressReference"></address-details-form>
</div>
</div>
</template> </template>
<style scoped lang="scss"></style> <style scoped lang="scss">
.address-pick-content {
display: flex;
flex-direction: row;
}
</style>

View File

@@ -0,0 +1,25 @@
<script setup lang="ts">
import {AddressAggregated} from "ChillMainAssets/vuejs/AddressPicker/driver/local-search";
import AddressAggregatedListItem from "ChillMainAssets/vuejs/AddressPicker/Component/AddressAggregatedListItem.vue";
interface AddressAggregatedListProps {
addresses: AddressAggregated[];
searchTokens: string[];
}
const props = defineProps<AddressAggregatedListProps>();
const emit = defineEmits<{
pickPosition: [id: string]
}>();
</script>
<template>
<template v-for="a in props.addresses" :key="a.row_number">
<address-aggregated-list-item :address="a" :search-tokens="props.searchTokens" @pick-position="(id) => emit('pickPosition', id)"></address-aggregated-list-item>
</template>
</template>
<style scoped lang="scss">
</style>

View File

@@ -0,0 +1,82 @@
<script setup lang="ts">
import {AddressAggregated} from "ChillMainAssets/vuejs/AddressPicker/driver/local-search";
import {computed, ref} from "vue";
interface AddressAggregatedListItemProps {
address: AddressAggregated;
searchTokens: string[];
}
const props = defineProps<AddressAggregatedListItemProps>();
const emit = defineEmits<{
pickPosition: [id: string]
}>();
const showAllPositions = ref<boolean>(false);
const positionsToShow = computed((): Record<string, string> => {
const obj: Record<string, any> = {};
let count = 0;
for (const [id, position] of Object.entries(props.address.positions)) {
obj[id] = position;
count++;
if (count >= 10 && !showAllPositions.value) {
break;
}
}
return obj;
})
const needToShowMorePosition = computed(() => {
return Object.keys(props.address.positions).length > 10;
})
const onClickButton = (id: string) => {
console.log('onClickButton', id);
emit('pickPosition', id);
}
const displayAllPositions = () => {
showAllPositions.value = true;
}
</script>
<template>
<div>
<div class="street">
<span>{{ props.address.street }}</span>
</div>
<div class="postcode">
<span>{{ props.address.code }}</span> <span>{{ address.label }}</span>
</div>
<div class="positions">
<ul>
<li v-for="(position, id) in positionsToShow" :key="id" >
<button type="button" @click="onClickButton(id)" >
{{ position }}
</button>
</li>
<li v-if="needToShowMorePosition">
<button @click="displayAllPositions">show all</button>
</li>
</ul>
</div>
</div>
</template>
<style scoped lang="scss">
.street {
font-variant: small-caps;
font-weight: bold;
}
.postcode {
font-variant: small-caps;
}
.positions ul {
list-style-type: none;
li {
display: inline-block;
margin-right: 2px;
}
}
</style>

View File

@@ -0,0 +1,27 @@
<script setup lang="ts">
import {AddressReference} from "ChillMainAssets/types";
import {computed} from "vue";
import {addressReferenceToAddress} from "ChillMainAssets/vuejs/AddressPicker/helper";
import AddressDetailsContent from "ChillMainAssets/vuejs/_components/AddressDetails/AddressDetailsContent.vue";
export interface AddressDetailsFormProps {
address: AddressReference;
}
const props = defineProps<AddressDetailsFormProps>();
const address = computed(() => addressReferenceToAddress(props.address));
</script>
<template>
<div>
FORM
</div>
<div>
<address-details-content :address="address"></address-details-content>
</div>
</template>
<style scoped lang="scss">
</style>

View File

@@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { ADDRESS_PICKER_SEARCH_FOR_ADDRESSES, trans } from 'translator';
const emits = defineEmits<{ const emits = defineEmits<{
search: [search: string]; search: [search: string];
}>(); }>();
@@ -25,7 +26,14 @@ const onInput = function (event: InputEvent) {
</script> </script>
<template> <template>
<input type="search" @input="onInput" /> <div class="input-group mb-3">
<span class="input-group-text">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-search" viewBox="0 0 16 16">
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001q.044.06.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1 1 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0"/>
</svg>
</span>
<input type="search" class="form-control" @input="onInput" :placeholder="trans(ADDRESS_PICKER_SEARCH_FOR_ADDRESSES)" />
</div>
</template> </template>
<style scoped lang="scss"></style> <style scoped lang="scss"></style>

View File

@@ -1,4 +1,4 @@
import { TranslatableString } from "ChillMainAssets/types"; import {AddressReference, TranslatableString} from "ChillMainAssets/types";
export interface AddressAggregated { export interface AddressAggregated {
row_number: number; row_number: number;
@@ -58,3 +58,12 @@ export const getPostalCodes = async (
throw new Error(response.statusText); throw new Error(response.statusText);
}; };
export const fetchAddressReference = async (id: string): Promise<AddressReference> => {
const response = await fetch(`/api/1.0/main/address-reference/${id}.json`);
if (response.ok) {
return await response.json();
}
throw new Error(response.statusText);
}

View File

@@ -0,0 +1,21 @@
import {Address, AddressCreation, AddressReference} from "ChillMainAssets/types";
export const addressReferenceToAddress = (reference: AddressReference): AddressCreation => {
return {
street: reference.street,
streetNumber: reference.streetNumber,
postcode: reference.postcode,
floor: "",
corridor: "",
steps: "",
flat: "",
buildingName: "",
distribution: "",
extra: "",
confidential: false,
addressReference: reference,
point: reference.point,
isNoAddress: false,
validFrom: null,
}
}

View File

@@ -4,24 +4,27 @@
:show-button-details="false" :show-button-details="false"
></address-render-box> ></address-render-box>
<address-details-ref-matching <address-details-ref-matching
v-if="isAddress(props.address)"
:address="props.address" :address="props.address"
@update-address="onUpdateAddress" @update-address="onUpdateAddress"
></address-details-ref-matching> ></address-details-ref-matching>
<address-details-map :address="props.address"></address-details-map> <address-details-map :address="props.address"></address-details-map>
<address-details-geographical-layers <address-details-geographical-layers
v-if="isAddress(props.address)"
:address="props.address" :address="props.address"
></address-details-geographical-layers> ></address-details-geographical-layers>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { Address } from "../../../types"; import {Address, AddressCreation} from "../../../types";
import AddressDetailsMap from "./Parts/AddressDetailsMap.vue"; import AddressDetailsMap from "./Parts/AddressDetailsMap.vue";
import AddressRenderBox from "../Entity/AddressRenderBox.vue"; import AddressRenderBox from "../Entity/AddressRenderBox.vue";
import AddressDetailsGeographicalLayers from "./Parts/AddressDetailsGeographicalLayers.vue"; import AddressDetailsGeographicalLayers from "./Parts/AddressDetailsGeographicalLayers.vue";
import AddressDetailsRefMatching from "./Parts/AddressDetailsRefMatching.vue"; import AddressDetailsRefMatching from "./Parts/AddressDetailsRefMatching.vue";
import {isAddress} from "ChillMainAssets/vuejs/_components/AddressDetails/helper";
interface AddressModalContentProps { interface AddressModalContentProps {
address: Address; address: Address|AddressCreation;
} }
const props = defineProps<AddressModalContentProps>(); const props = defineProps<AddressModalContentProps>();

View File

@@ -22,14 +22,15 @@ import { onMounted, ref } from "vue";
import "leaflet/dist/leaflet.css"; import "leaflet/dist/leaflet.css";
import markerIconPng from "leaflet/dist/images/marker-icon.png"; import markerIconPng from "leaflet/dist/images/marker-icon.png";
import L, { LatLngExpression, LatLngTuple } from "leaflet"; import L, { LatLngExpression, LatLngTuple } from "leaflet";
import { Address, Point } from "../../../../types"; import {Address, AddressCreation, Point} from "../../../../types";
import {buildAddressLines, getAddressPoint} from "ChillMainAssets/vuejs/_components/AddressDetails/helper";
const lonLatForLeaflet = (point: Point): LatLngTuple => { const lonLatForLeaflet = (point: Point): LatLngTuple => {
return [point.coordinates[1], point.coordinates[0]]; return [point.coordinates[1], point.coordinates[0]];
}; };
export interface MapProps { export interface MapProps {
address: Address; address: Address|AddressCreation;
} }
const props = defineProps<MapProps>(); const props = defineProps<MapProps>();
@@ -65,37 +66,39 @@ onMounted(() => {
} }
}); });
const makeUrlGoogleMap = (address: Address): string => { const makeUrlGoogleMap = (address: Address|AddressCreation): string => {
const params = new URLSearchParams(); const params = new URLSearchParams();
params.append("api", "1"); params.append("api", "1");
if (address.point !== null && address.addressReference !== null) { const point = getAddressPoint(address);
if (point !== null && address.addressReference !== null) {
params.append( params.append(
"query", "query",
`${address.point.coordinates[1]} ${address.point.coordinates[0]}`, `${point.coordinates[1]} ${point.coordinates[0]}`,
); );
} else { } else {
params.append("query", address.lines.join(", ")); params.append("query", buildAddressLines(address).join(", "));
} }
return `https://www.google.com/maps/search/?${params.toString()}`; return `https://www.google.com/maps/search/?${params.toString()}`;
}; };
const makeUrlOsm = (address: Address): string => { const makeUrlOsm = (address: Address|AddressCreation): string => {
if (address.point !== null && address.addressReference !== null) { const point = getAddressPoint(address);
if (point !== null && address.addressReference !== null) {
const params = new URLSearchParams(); const params = new URLSearchParams();
params.append("mlat", `${address.point.coordinates[1]}`); params.append("mlat", `${point.coordinates[1]}`);
params.append("mlon", `${address.point.coordinates[0]}`); params.append("mlon", `${point.coordinates[0]}`);
const hashParams = new URLSearchParams(); const hashParams = new URLSearchParams();
hashParams.append( hashParams.append(
"map", "map",
`18/${address.point.coordinates[1]}/${address.point.coordinates[0]}`, `18/${point.coordinates[1]}/${point.coordinates[0]}`,
); );
return `https://www.openstreetmap.org/?${params.toString()}#${hashParams.toString()}`; return `https://www.openstreetmap.org/?${params.toString()}#${hashParams.toString()}`;
} }
const params = new URLSearchParams(); const params = new URLSearchParams();
params.append("query", address.lines.join(", ")); params.append("query", buildAddressLines(address).join(", "));
return `https://www.openstreetmap.org/search?${params.toString()}`; return `https://www.openstreetmap.org/search?${params.toString()}`;
}; };

View File

@@ -0,0 +1,46 @@
import {Address, AddressCreation, Point} from "ChillMainAssets/types";
import addressFormatter, {Input} from "@fragaria/address-formatter";
/**
* Checks if the given object is of type Address by verifying the existence
* of the `lines` property and confirming that it is an array of strings.
*
* @param {AddressCreation | Address} obj - The object to check.
* @return {boolean} Returns true if the object is of type Address, otherwise false.
*/
export function isAddress(obj: AddressCreation | Address): obj is Address {
return (obj as any).lines !== undefined && Array.isArray((obj as any).lines);
}
function buildAddressFormatterObject(address: AddressCreation): Input {
return {
city: address.postcode.name,
postcode: address.postcode.code,
countryCode: address.postcode.country.code,
street: address.street,
houseNumber: address.streetNumber,
};
}
export const buildAddressLines = (address: AddressCreation|Address): string[] => {
if (isAddress(address)) {
return address.lines;
}
const lines = addressFormatter.format(buildAddressFormatterObject(address), {output: 'array', countryCode: address.addressReference.postcode.country.code });
console.log('lines:', lines);
return lines;
}
export const buildAddressText = (address: AddressCreation|Address): string => {
return buildAddressLines(address).join(' - ');
}
export const getAddressPoint = (address: AddressCreation|Address): Point|null => {
if (isAddress(address)) {
return address.point;
}
return address.addressReference?.point;
}

View File

@@ -4,14 +4,14 @@
<div v-if="isConfidential"> <div v-if="isConfidential">
<confidential :position-btn-far="true"> <confidential :position-btn-far="true">
<template #confidential-content> <template #confidential-content>
<div v-if="isMultiline === true"> <div v-if="isMultiline">
<p <p
v-for="(l, i) in address.lines" v-for="(l, i) in buildAddressLines(address)"
:key="`line-${i}`" :key="`line-${i}`"
> >
{{ l }} {{ l }}
</p> </p>
<p v-if="showButtonDetails"> <p v-if="showButtonDetails && isAddress(address) ">
<address-details-button <address-details-button
:address_id="address.address_id" :address_id="address.address_id"
:address_ref_status="address.refStatus" :address_ref_status="address.refStatus"
@@ -19,8 +19,8 @@
</p> </p>
</div> </div>
<div v-else> <div v-else>
<p v-if="'' !== address.text" class="street"> <p v-if="'' !== buildAddressText(address)" class="street">
{{ address.text }} {{ buildAddressText(address) }}
</p> </p>
<p <p
v-if="null !== address.postcode" v-if="null !== address.postcode"
@@ -29,8 +29,8 @@
{{ address.postcode.code }} {{ address.postcode.code }}
{{ address.postcode.name }} {{ address.postcode.name }}
</p> </p>
<p v-if="null !== address.country" class="country"> <p v-if="null !== address.postcode" class="country">
{{ localizeString(address.country.name) }} {{ localizeString(address.postcode.country.name) }}
</p> </p>
</div> </div>
</template> </template>
@@ -38,11 +38,11 @@
</div> </div>
<div v-if="!isConfidential"> <div v-if="!isConfidential">
<div v-if="isMultiline === true"> <div v-if="isMultiline">
<p v-for="(l, i) in address.lines" :key="`line-${i}`"> <p v-for="(l, i) in buildAddressLines(address)" :key="`line-${i}`">
{{ l }} {{ l }}
</p> </p>
<p v-if="showButtonDetails"> <p v-if="showButtonDetails && isAddress(address) ">
<address-details-button <address-details-button
:address_id="address.address_id" :address_id="address.address_id"
:address_ref_status="address.refStatus" :address_ref_status="address.refStatus"
@@ -50,9 +50,9 @@
</p> </p>
</div> </div>
<div v-else> <div v-else>
<p v-if="address.text" class="street"> <p v-if="'' !== buildAddressText(address)" class="street">
{{ address.text }} {{ buildAddressText(address)}}
<template v-if="showButtonDetails"> <template v-if="showButtonDetails && isAddress(address) ">
<address-details-button <address-details-button
:address_id="address.address_id" :address_id="address.address_id"
:address_ref_status="address.refStatus" :address_ref_status="address.refStatus"
@@ -63,68 +63,49 @@
</div> </div>
</component> </component>
<div v-if="useDatePane === true" class="address-more"> <div v-if="useDatePane" class="address-more">
<div v-if="address.validFrom"> <div v-if="address.validFrom">
<span class="validFrom"> <span class="validFrom">
<b>{{ trans(ADDRESS_VALID_FROM) }}</b <b>{{ trans(ADDRESS_VALID_FROM) }}</b
>: {{ $d(address.validFrom.date) }} >: {{ address.validFrom?.datetime8601 }}
</span> </span>
</div> </div>
<div v-if="address.validTo"> <div v-if="isAddress(address) && address.validTo !== null">
<span class="validTo"> <span class="validTo">
<b>{{ trans(ADDRESS_VALID_TO) }}</b <b>{{ trans(ADDRESS_VALID_TO) }}</b
>: {{ $d(address.validTo.date) }} >: {{ address.validTo?.datetime8601 }}
</span> </span>
</div> </div>
</div> </div>
</component> </component>
</template> </template>
<script> <script setup lang="ts">
import { computed } from "vue";
import Confidential from "ChillMainAssets/vuejs/_components/Confidential.vue"; import Confidential from "ChillMainAssets/vuejs/_components/Confidential.vue";
import AddressDetailsButton from "ChillMainAssets/vuejs/_components/AddressDetails/AddressDetailsButton.vue"; import AddressDetailsButton from "ChillMainAssets/vuejs/_components/AddressDetails/AddressDetailsButton.vue";
import { trans, ADDRESS_VALID_FROM, ADDRESS_VALID_TO } from "translator"; import { trans, ADDRESS_VALID_FROM, ADDRESS_VALID_TO } from "translator";
import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper"; import { localizeString } from "ChillMainAssets/lib/localizationHelper/localizationHelper";
import {Address, AddressCreation} from "ChillMainAssets/types";
import {isAddress, buildAddressLines, buildAddressText} from "ChillMainAssets/vuejs/_components/AddressDetails/helper";
export default { const props = withDefaults(
name: "AddressRenderBox", defineProps<{
methods: { localizeString }, address: Address|AddressCreation;
components: { isMultiline?: boolean;
Confidential, useDatePane?: boolean;
AddressDetailsButton, showButtonDetails?: boolean;
}, }>(),
props: { {
address: { isMultiline: true,
type: Object, useDatePane: false,
}, showButtonDetails: true,
isMultiline: { }
default: true, );
type: Boolean,
}, const component = computed(() => (props.isMultiline ? "div" : "span"));
useDatePane: { const multiline = computed(() => (props.isMultiline ? "multiline" : ""));
default: false, const isConfidential = computed(() => Boolean(props.address?.confidential));
type: Boolean,
},
showButtonDetails: {
default: true,
type: Boolean,
},
},
setup() {
return { trans, ADDRESS_VALID_FROM, ADDRESS_VALID_TO };
},
computed: {
component() {
return this.isMultiline === true ? "div" : "span";
},
multiline() {
return this.isMultiline === true ? "multiline" : "";
},
isConfidential() {
return this.address.confidential;
},
},
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@@ -66,6 +66,7 @@ class AddressNormalizer implements ContextAwareNormalizerInterface, NormalizerAw
'name' => $address->getPostCode()->getName(), 'name' => $address->getPostCode()->getName(),
'code' => $address->getPostCode()->getCode(), 'code' => $address->getPostCode()->getCode(),
'center' => $address->getPostcode()->getCenter(), 'center' => $address->getPostcode()->getCenter(),
'country' => $this->normalizer->normalize($address->getPostCode()->getCountry(), $format, [AbstractNormalizer::GROUPS => ['read']]),
], ],
'country' => [ 'country' => [
'id' => $address->getPostCode()->getCountry()->getId(), 'id' => $address->getPostCode()->getCountry()->getId(),

View File

@@ -181,6 +181,11 @@ address more:
buildingName: résidence buildingName: résidence
extra: "" extra: ""
distribution: cedex distribution: cedex
address_picker:
# placeholder
Search for addresses: Chercher des adresses
Create a new address: Créer une nouvelle adresse Create a new address: Créer une nouvelle adresse
Create an address: Créer une adresse Create an address: Créer une adresse
Update address: Modifier l'adresse Update address: Modifier l'adresse