fix: strip city, state, postcode, country from addressStreet1 after place selection
https://sonarly.com/issue/17527?type=bug When a user selects an address from Google Place Autocomplete suggestions, the full autocomplete text (including city, state, zip, and country) is set as the Address 1 value, resulting in duplicate information across fields. Fix: **Backend changes:** 1. `sanitize-place-details-results.util.ts`: Added extraction of `street_number` and `route` types from Google's `address_components`. These are combined into a single `street` field (e.g., "123 Main St") and added to the `AddressFields` type. The combination uses `[streetNumber, route].filter(Boolean).join(' ')` to handle cases where only one component exists. 2. `place-details-result.dto.ts`: Added `street` as a new nullable field to the GraphQL `PlaceDetailsResult` type, making it available to frontend queries. **Frontend changes:** 3. `geo-map-appolo.api.ts`: Added `street` to the `GET_PLACE_DETAILS_QUERY` GraphQL query so the frontend requests this field from the backend. 4. `placeApi.ts`: Added `street` as an optional field to the `PlaceDetailsResult` TypeScript type. 5. `useAddressAutocomplete.ts`: Changed `addressStreet1` assignment to prefer `placeData.street` (the clean, parsed street address from Google) over the raw autocomplete text. The fallback chain preserves backward compatibility: `placeData.street || addressStreet1 || internalValue.addressStreet1`. **Test:** 6. `useAddressAutocomplete.test.tsx`: Added a test that verifies when `placeData.street` is "123 Main St" and the autocomplete text was "123 Main St, Springfield, IL 62704, USA", the `addressStreet1` is set to just "123 Main St" (the clean street value).
This commit is contained in:
@@ -22,6 +22,7 @@ export const GET_AUTOCOMPLETE_QUERY = gql`
|
||||
export const GET_PLACE_DETAILS_QUERY = gql`
|
||||
query GetAddressDetails($placeId: String!, $token: String!) {
|
||||
getAddressDetails(placeId: $placeId, token: $token) {
|
||||
street
|
||||
state
|
||||
postcode
|
||||
city
|
||||
|
||||
@@ -13,6 +13,7 @@ export type PlaceAutocompleteResult = {
|
||||
};
|
||||
|
||||
export type PlaceDetailsResult = {
|
||||
street?: string;
|
||||
state?: string;
|
||||
postcode?: string;
|
||||
city?: string;
|
||||
|
||||
+48
@@ -254,6 +254,54 @@ describe('useAddressAutocomplete', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should use street from place details instead of full autocomplete text', async () => {
|
||||
const mockOnChange = jest.fn();
|
||||
const mockPlaceData = {
|
||||
street: '123 Main St',
|
||||
city: 'Springfield',
|
||||
state: 'IL',
|
||||
country: 'US',
|
||||
postcode: '62704',
|
||||
location: { lat: 39.7817, lng: -89.6501 },
|
||||
};
|
||||
|
||||
mockGetPlaceDetailsData.mockResolvedValue(mockPlaceData);
|
||||
mockFindCountryNameByCountryCode.mockReturnValue('United States');
|
||||
|
||||
const { result } = renderHook(() => useAddressAutocomplete(mockOnChange));
|
||||
|
||||
const internalValue = {
|
||||
addressStreet1: '123 Main St, Springfield, IL 62704, USA',
|
||||
addressStreet2: null,
|
||||
addressCity: null,
|
||||
addressState: null,
|
||||
addressCountry: null,
|
||||
addressPostcode: null,
|
||||
addressLat: null,
|
||||
addressLng: null,
|
||||
};
|
||||
|
||||
await act(async () => {
|
||||
await result.current.autoFillInputsFromPlaceDetails(
|
||||
'place123',
|
||||
'token123',
|
||||
'123 Main St, Springfield, IL 62704, USA',
|
||||
internalValue,
|
||||
);
|
||||
});
|
||||
|
||||
expect(mockOnChange).toHaveBeenCalledWith({
|
||||
addressStreet1: '123 Main St',
|
||||
addressStreet2: null,
|
||||
addressCity: 'Springfield',
|
||||
addressState: 'IL',
|
||||
addressCountry: 'United States',
|
||||
addressPostcode: '62704',
|
||||
addressLat: 39.7817,
|
||||
addressLng: -89.6501,
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle address autocomplete with country and isFieldCity parameters', async () => {
|
||||
mockGetPlaceAutocompleteData.mockResolvedValue([
|
||||
{ text: 'Boston, MA', placeId: 'place1' },
|
||||
|
||||
@@ -80,7 +80,10 @@ export const useAddressAutocomplete = (
|
||||
const countryName = findCountryNameByCountryCode(placeData?.country);
|
||||
|
||||
const updatedAddress = {
|
||||
addressStreet1: addressStreet1 || (internalValue?.addressStreet1 ?? ''),
|
||||
addressStreet1:
|
||||
placeData?.street ||
|
||||
addressStreet1 ||
|
||||
(internalValue?.addressStreet1 ?? ''),
|
||||
addressStreet2: internalValue?.addressStreet2 ?? null,
|
||||
addressCity: placeData?.city || (internalValue?.addressCity ?? null),
|
||||
addressState: placeData?.state || (internalValue?.addressState ?? null),
|
||||
|
||||
+3
@@ -11,6 +11,9 @@ export class LocationDTO {
|
||||
|
||||
@ObjectType('PlaceDetailsResult')
|
||||
export class PlaceDetailsResultDTO {
|
||||
@Field({ nullable: true })
|
||||
street?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
state?: string;
|
||||
|
||||
|
||||
+16
@@ -4,6 +4,7 @@ export type AddressComponent = {
|
||||
types: string[];
|
||||
};
|
||||
export type AddressFields = {
|
||||
street?: string;
|
||||
state?: string;
|
||||
postcode?: string;
|
||||
city?: string;
|
||||
@@ -22,9 +23,20 @@ export const sanitizePlaceDetailsResults = (
|
||||
|
||||
const address: AddressFields = {};
|
||||
|
||||
let streetNumber = '';
|
||||
let route = '';
|
||||
|
||||
for (const AddressComponent of AddressComponents) {
|
||||
for (const type of AddressComponent.types) {
|
||||
switch (type) {
|
||||
case 'street_number':
|
||||
streetNumber = AddressComponent.long_name;
|
||||
break;
|
||||
|
||||
case 'route':
|
||||
route = AddressComponent.long_name;
|
||||
break;
|
||||
|
||||
case 'postal_code': {
|
||||
address.postcode =
|
||||
AddressComponent.long_name + (address.postcode ?? '');
|
||||
@@ -72,6 +84,10 @@ export const sanitizePlaceDetailsResults = (
|
||||
}
|
||||
}
|
||||
}
|
||||
if (streetNumber || route) {
|
||||
address.street = [streetNumber, route].filter(Boolean).join(' ');
|
||||
}
|
||||
|
||||
address.location = location;
|
||||
|
||||
return address;
|
||||
|
||||
Reference in New Issue
Block a user