Fluent Commerce Logo
Sign In

Add and Edit Customer Address by using custom UI component

How-to Guide

Author:

Siarhei Vaitsiakhovich

Changed on:

7 July 2024

Key Points

  • Address Validation: Ensure that the address entered by the user is valid and correctly formatted to avoid shipping issues.
  • Default Address: Allow customers to set a default address for a quicker checkout process.
  • Edit Capability: Provide an option for users to edit customer address details in case of errors or changes.
  • User Experience: Design the add and edit address process to be user-friendly and accessible, with clear instructions and error messages.

Steps

Step arrow right iconUse Case

To ensure a seamless experience for users managing customers' address information, the following use cases outline the process for adding and editing customer addresses:

  • Add a New Address: Customer can add a new address by filling out a form with their details. This form includes fields for the company name, street address, city, state, postal code, country, and timezone.
  • Set Default Addresses: After adding an address, the address will be used as default to streamline future checkouts.
  • Edit Existing Address: The user can edit the customer-saved address at any time. This is useful for correcting mistakes or updating the address information if they move.

Step arrow right iconSolution Approach

The feature can be implemented via the declaration of a custom mutation user actions

`createCustomerAddress`
and
`updateCustomerAddress`
in the manifest (see Page Component). Visibility of actions has to depend on customer address ('Add Customer Address' if customer address does not exist, otherwise - 'Edit Customer Address'). 

For a better user experience, part of the default mutation field components have to be overridden. List of fields to override:

  • Country
  • Timezone

Additionally, the fields have to be reordered to enhance the logical flow of the user interface, making it more intuitive for users to navigate and input their information efficiently. New fields order:

  • Reference (only for 'Add Customer Address' action)
  • Company Name
  • Street
  • City
  • State
  • Postcode
  • Region
  • Country
  • Timezone

To save data consistency, options for Timezone and Country selectors have to be loaded from settings. For 'Edit Customer Address' action, all fields have to be prefilled with current user information.

Step arrow right icon Technical Design Overview

To support the business solution design, the following technical areas need to be enhanced:

  • New custom UI component (by using Component SDK) -
    `SettingBaseStringSelector`
  • Declare settings to use it for Country and Timezone selectors
  • Update manifest to add new conditionally visible actions 'Add Customer Address' and 'Edit Customer Address' (for example on the Customer Details page)
  • Update localization files to modify field labels

Each of these tasks will be described below in steps.

Step arrow right iconUI Component: SettingBaseStringSelector

`SettingBaseStringSelector`
component can be used for use cases when a user has to have a combo box with options filled from the setting. On add and edit customer address drawers the component will be used to present Country and Timezone selectors.

Create a new file:

`SettingBaseStringSelector.tsx`
.

1const SettingBaseStringSelector: FC<FormFieldProps<any>> = (props) => {
2  const auth = useAuth();
3
4  const settingName = props.extensions?.settingName;
5  const [items, setItems] = useState<string[]>([]);
6  const [currentItem, setCurrentItem] = useState<string | undefined>(
7    props.value,
8  );
9
10  useEffect(() => {
11    if (settingName) {
12      getSettings(
13        { setting: settingName },
14        parseInt(auth.context.current.contextId),
15      ).then((value) => {
16        if (value.setting.status == 'ok') {
17          const list: string[] = [...value.setting.result.value];
18          if (props.value && !list.includes(props.value)) {
19            list.push(props.value);
20          }
21          setItems(list);
22        }
23      });
24    } else {
25      setItems([]);
26    }
27  }, [settingName]);
28
29  useEffect(() => {
30    if (currentItem) {
31      props.onChange(currentItem);
32    } else {
33      props.onChange(undefined);
34    }
35  }, [currentItem]);
36
37  const handleChange = (event: any) => {
38    setCurrentItem(event.target.value as string);
39  };
40
41  const handleOnBlur = () => {
42    props && props.onBlur && props.onBlur();
43  };
44
45  return (
46    <FormControl fullWidth error={!!props.error}>
47      <InputLabel id="string-select-label">{props.label}</InputLabel>
48      <Select
49        labelId="string-select-label"
50        id="string-select"
51        label={props.label}
52        onChange={handleChange}
53        onBlur={handleOnBlur}
54        value={currentItem}
55      >
56        {items.map((value, idx) => {
57          return (
58            <MenuItem key={idx} value={value} selected={currentItem === value}>
59              {value}
60            </MenuItem>
61          );
62        })}
63      </Select>
64      {props.error && <FormHelperText>{props.error}</FormHelperText>}
65    </FormControl>
66  );
67};
68
69export default SettingBaseStringSelector;

Language: typescript

Name: SettingBaseStringSelector.tsx

Description:

SettingBaseStringSelector component implementation example

1FieldRegistry.register(
2  ['settingBaseStringSelector'],
3  SettingBaseStringSelector,
4);

Language: typescript

Name: index.tsx

Description:

SettingBaseStringSelector field component registration

Step arrow right iconSetting: EDIT_LOCATION_COUNTRIES

`EDIT_LOCATION_COUNTRIES`
setting represents a list of countries available to select for customer address.

Name

EDIT_LOCATION_COUNTRIES

Value Type

JSON

Context

ACCOUNT or RETAILER

Context ID

0 or Retailer ID

JSON Value

[

    "Australia",

    "Canada",

    "France",

    "Germany",

    "United Kingdom",

    "United States"

]

Step arrow right iconSetting: EDIT_LOCATION_TIME_ZONES

`EDIT_LOCATION_TIME_ZONES`
setting represents a list of timezones available to select for customer address.

Name

EDIT_LOCATION_TIME_ZONES

Value Type

JSON

Context

ACCOUNT or RETAILER

Context ID

0 or Retailer ID

JSON Value

[

    "GMT",

    "UTC",

    "ECT",

    "EET",

    "ACT",

    "AET",

    "HST",

    "AST",

    "PST",

    "PNT",

    "MST",

    "CST",

    "EST",

    "IET",

    "PRT",

    "CNT"

]

Step arrow right iconManifest changes

`Add and Edit Customer Address`
feature implies the usage of two excluding actions:
`Add Customer Address`
and
`Edit Customer Address`
. Both actions have to be declared as mutation user actions
`createCustomerAddress`
and
`updateCustomerAddress`
with using field
`condition`
to set an exclusive visibility condition (see Page Component).
`Add Customer Address`
and
`Edit Customer Address`
user actions can be added to any page which load customer information as page data. In the example Customer details page was used.

1{
2    "type": "mutation",
3    "label": "Add Customer Address",
4    "name": "createCustomerAddress",
5    "condition": "{{eq customerAddresses.edges.length 0}}",
6    "filter": {
7        "type": "exclude",
8        "names": [
9            "latitude",
10            "longitude"
11        ]
12    },
13    "overrides": {
14        "ref": {
15            "sortPrefix": 11
16        },
17        "companyName": {
18            "sortPrefix": 12
19        },
20        "street": {
21            "sortPrefix": 13
22        },
23        "city": {
24            "sortPrefix": 14
25        },
26        "state": {
27            "sortPrefix": 15
28        },
29        "postcode": {
30            "sortPrefix": 16
31        },
32        "region": {
33            "sortPrefix": 17
34        },
35        "country": {
36            "sortPrefix": 18,
37            "component": "settingBaseStringSelector",
38            "extensions": {
39                "settingName": "EDIT_LOCATION_COUNTRIES"
40            }
41        },
42        "timeZone": {
43            "sortPrefix": 19,
44            "component": "settingBaseStringSelector",
45            "extensions": {
46                "settingName": "EDIT_LOCATION_TIME_ZONES"
47            }
48        },
49        "name": {
50            "component": "input",
51            "sortPrefix": 20,
52            "options": [
53                {
54                    "label": "Customer Name",
55                    "value": "{{customerById.firstName}} {{customerById.lastName}}"
56                }
57            ]
58        }
59    }
60},
61{
62    "type": "mutation",
63    "label": "Edit Customer Address",
64    "name": "updateCustomerAddress",
65    "condition": "{{gt customerAddresses.edges.length 0}}",
66    "filter": {
67        "type": "exclude",
68        "names": [
69            "name",
70            "latitude",
71            "longitude"
72        ]
73    },
74    "args": {
75        "id": "{{customerAddresses.edges.0.node.id}}"
76    },
77    "overrides": {
78        "companyName": {
79            "sortPrefix": 12
80        },
81        "street": {
82            "sortPrefix": 13
83        },
84        "city": {
85            "sortPrefix": 14
86        },
87        "state": {
88            "sortPrefix": 15
89        },
90        "postcode": {
91            "sortPrefix": 16
92        },
93        "region": {
94            "sortPrefix": 17
95        },
96        "country": {
97            "sortPrefix": 18,
98            "component": "settingBaseStringSelector",
99            "extensions": {
100                "settingName": "EDIT_LOCATION_COUNTRIES"
101            }
102        },
103        "timeZone": {
104            "sortPrefix": 19,
105            "component": "settingBaseStringSelector",
106            "extensions": {
107                "settingName": "EDIT_LOCATION_TIME_ZONES"
108            }
109        },
110        "name": {
111            "component": "input",
112            "sortPrefix": 20,
113            "options": [
114                {
115                    "label": "Customer Name",
116                    "value": "{{customerById.firstName}} {{customerById.lastName}}"
117                }
118            ]
119        }
120    }
121}
122
123

Language: json

Name: Add and Edit Customer Address actions

Description:

Add and Edit Customer Address mutation user actions declaration example. Property

`sortPrefix`
is used to configure the order of fields on drawers 

Step arrow right iconUpdate Language Setting

Localization of fields is done by creating localization entries for mutation fields according to name convention (see Languages and Localisation, chapter 'Adding new Mutation Actions').

1{
2  "translation": {
3    "fc.gql.customerAddress.ref": "Ref",
4    "fc.gql.customerAddress.companyName": "Company Name",
5    "fc.gql.customerAddress.street": "Street",
6    "fc.gql.customerAddress.city": "City",
7    "fc.gql.customerAddress.state": "State",
8    "fc.gql.customerAddress.postcode": "Postcode",
9    "fc.gql.customerAddress.region": "Region",
10    "fc.gql.customerAddress.country": "Country",
11    "fc.gql.customerAddress.timeZone": "Timezone"
12  }
13}

Language: json

Name: New localization entries

Description:

Example of mutation field labels localisation with using name convention

Step arrow right iconResult

After all steps,

`Add Customer Address`
and
`Edit Customer Address`
actions have to be available on the page.

`Add Customer Address`
action:

No alt providedNo alt provided

`Edit Customer Address`
action:

No alt providedNo alt provided

Step arrow right iconRelated Sources

Copyright © 2024 Fluent Retail Pty Ltd (trading as Fluent Commerce). All rights reserved. No materials on this docs.fluentcommerce.com site may be used in any way and/or for any purpose without prior written authorisation from Fluent Commerce. Current customers and partners shall use these materials strictly in accordance with the terms and conditions of their written agreements with Fluent Commerce or its affiliates.

Fluent Logo