Skip to content
This repository was archived by the owner on May 21, 2020. It is now read-only.
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions packages/core/rfcs/use-user-address-factory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# UseUserAddressFactory with Commerce Tools composable use case

## Motivation

We need to extend useUserAddress type to show and modify user addresses.
Also, some eCommerce platforms requires updating user entity with every address modification (for example: CommerceTools).

## Composable interface
```TS
export interface UseUserAddress<ADDRESS, SEARCH_PARAMS, ADDRESS_OPTIONS = unknown> {
addresses: ComputedProperty<ADDRESS[]>;
shippingAddresses: ComputedProperty<ADDRESS[]>;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we have multiple shipping addressess and billing addresses? Does every address have to be in a specific category?

billingAddresses: ComputedProperty<ADDRESS[]>;
loadAddresses: (params?: SEARCH_PARAMS) => Promise<void>;
addAddress: (address: ADDRESS, options?: ADDRESS_OPTIONS) => Promise<void>;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what are these options

updateAddress: (address: ADDRESS, options?: ADDRESS_OPTIONS) => Promise<void>;
Comment on lines +15 to +16

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
addAddress: (address: ADDRESS, options?: ADDRESS_OPTIONS) => Promise<void>;
updateAddress: (address: ADDRESS, options?: ADDRESS_OPTIONS) => Promise<void>;
saveAddress: (address: ADDRESS, options?: ADDRESS_OPTIONS) => Promise<void>;

deleteAddress: (address: ADDRESS, options?: ADDRESS_OPTIONS) => Promise<void>;
loading: ComputedProperty<boolean>;
}
```

## Factory params interface
```TS
// factory params schema
export type UseUserAddressFactoryParams<ADDRESS, SEARCH_PARAMS, ADDRESS_OPTIONS = unknown> = {
loadAddresses: (params?: SEARCH_PARAMS) => Promise<ADDRESS[]>;
getBillingAddresses: (addresses: ADDRESS[]) => ADDRESS[];
getShippingAddresses: (addresses: ADDRESS[]) => ADDRESS[];
addAddress: (address: ADDRESS, options?: ADDRESS_OPTIONS) => Promise<ADDRESS[]>;
updateAddress: (address: ADDRESS, options?: ADDRESS_OPTIONS) => Promise<ADDRESS[]>;
deleteAddress: (address: ADDRESS, options?: ADDRESS_OPTIONS) => Promise<ADDRESS[]>;
}
```

## Other changes requirements:
We need to add a possibility to update a user
```TS
// FACTORY INTERFACE
export interface UseUser
<
USER,
UPDATE_USER_PARAMS
> {
// ...leave all the stuff as they are now

// needed to add this:
setUser: (newUser: USER) => void;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't be a part of params, we have access to this object from the inside therefore we can just return this fn

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please take a look at @andrzejewsky RFC

}
```

```TS
// FACTORY IMPLEMENTATION
export function useUserFactory<USER, UPDATE_USER_PARAMS, REGISTER_USER_PARAMS extends { email: string; password: string }>(
factoryParams: UseUserFactoryParams<USER, UPDATE_USER_PARAMS, REGISTER_USER_PARAMS>
) {
// ...leave all the stuff as they are now

// needed to add this:
const setUser = (newUser: USER) => {
user.value = newUser;
};

return {
user: computed(() => user.value),
setUser, // required to be added
updateUser,
register,
login,
logout,
isAuthenticated,
changePassword,
refreshUser,
loading: computed(() => loading.value)
};
}
```

## Commerce Tools Integration
In order to integrate CT we need a user instance to update it. It's required, because addresses are being updated through user update endpoint.

Below example when adding an address:

### Factory params
```TS
import { setUser } from './useUser';

const factoryParams = {
addAddress: async (address) => {
const { user } = await apiAddAddress(address);

setUser(user);

return user.addresses;
}
};
```

### Factory content
```TS
export function useUserAddressFactory = (factoryParams) => {
const addresses: ref([]);
const loading: ref(false);

return function useUserAddress(): UseUserAddress<ADDRESS, SEARCH_PARAMS, ADDRESS_OPTIONS> {
const addAddress: async (address) => {
loading.value = true;
addresses.value = await factoryParams.addAddress(address);
loading.value = false;
}

// and other methods

return {
addresses: computed(() => addresses.value);
addAddress,
// ...And other stuff mentioned in interfaces section
}
}
};
```