import { Meta } from '@storybook/blocks';

<Meta title="Architecture/Services" />

# Services

Two helper services are included in the library to help with initializing components when
sending values to the Disciple.Tools API.

- [ApiService](#apiservice)
- [ComponentService](#componentservice)

## ApiService

This will provide a structured way to send and receive data with the standard Disciple.Tools API.

### Initialization

To initialize, instantiate the class while passing a WP nonce (for authentication) and the
root path of the WordPress API (if different than `wp-json`).

```javascript
const apiService = new ApiService(wpnonce);
```

### Utility Methods

A few utility methods are used internally to share logic among all the endpoint methods:

#### `makeRequest`

##### Arguments

| Name | Type | Description |
| ---- | ---- | ----------- |
| type | string | HTTP Method |
| url  | string | Either full URL to API endpoint or just the URL segment after base |
| data | object | Post data to send in body of request |
| base (optional) | Base of URL endpoint. Defaults to "dt/v1/" |

##### Return

Promise with body of response as JSON object.

#### `makeRequestOnPosts`

Specific use of `makeRequest` for all of the endpoints that are specific to a given post.
Sets the `base` argument and passes all of the rest through to `makeRequest`

`return this.makeRequest(type, url, data, 'dt-posts/v2/');`

### Endpoint Methods

Most standard endpoints that are needed for the web components have been implemented.
Those include (but may not be limited to):

- getPost
- createPost
- updatePost
- deletePost
- listPostsCompact
- getPostDuplicates
- getMultiSelectValues
- transferContact
- transferContactSummaryUpdate
- requestRecordAccess
- createComment
- updateComment
- deleteComment
- getComments
- toggle_comment_reaction
- getPostActivity
- getSingleActivity
- revertActivity
- getPostShares
- addPostShare
- removePostShare
- getFilters
- saveFilters
- deleteFilter
- searchUsers
- createUser
- advanced_search

See the [source code](https://github.com/DiscipleTools/disciple-tools-web-components/blob/master/src/services/apiService.js)
for details of all endpoints included.

Refer to [theme documentation](https://developers.disciple.tools/theme-core/api-posts)
for all of the available endpoints.

## ComponentService

The ComponentService helps to initialize the ApiService and hook up all change events for a given
page on Disciple.Tools. Once a post page is loaded in the theme, you just run the following
to setup all of the needed event listeners:

```javascript
const componentService = new ComponentService(postType, postId, nonce, apiRoot);
componentService.initialize();
```
The constructor will instantiate the ApiService for use within event listeners within
the service. The `initialize()` method will attach various event listeners. These
two methods should generally be the only methods needed in client scripts alongside
web components.

### Methods

#### `initialize()`
Convenience method to call two other service methods:

- If service has a `postId` (from the constructor), calls `enableAutoSave()`. This will connect change events to the API on the post detail screen.
- Calls `attachLoadEvents()` to connect `dt:get-data` events to API for fetching field options.

#### `attachLoadEvents(selector)`
For all components in `this.dynamicLoadComponents` (or overridden by `selector` parameter),
this will attach event listeners to the `dt:get-data` event that is dispatched by components
that have an autocomplete function or need a list of values from the API.

#### `enableAutoSave(selector)`
For all components in `this.autoSaveComponents` (or overridden by `selector` parameter),
this will attach event listeners to the `change` event that is dispatched by form
components and call the `handleChangeEvent()` function.

#### `handleChangeEvent(event)`
Calls the `convertValue()` function to convert the value of the component to the format
required by the API and then send the value to the API to be saved.

While saving, this sets the `loading` attribute and will set the `saved` or `error` attributes
on success or failure of the API request.

#### `convertValue(component, value, oldValue)`
Based on the name of the `component`, this transforms the value from the format returned
by the component to the format required by the API.

#### `convertApiValue(component, value)`
Based on the name of the `component`, this transforms the value from the format returned
by the API to the format required by the component.
