## Widget

You can find description of all methods and parameters [here](https://www.npmjs.com/package/@paydock/client-sdk#widget-simple-example)

A payment form where it is possible to enter card data/bank accounts and then receive a one-time
token for charges, subscriptions etc. This form can be customized, you can customize the fields and set styles.
It is possible in real-time to monitor the actions of user with widget and get information about payment-source using events.

## Widget simple example

### Container

```html
<div id="widget"></div>
```

You must create a container for the widget. Inside this tag, the widget will be initialized

### Initialization

```javascript
var widget = new paydock.HtmlWidget('#widget', 'publicKey');
widget.load();
```

```javascript
// ES2015 | TypeScript

import { HtmlWidget } from '@paydock/client-sdk';

var widget = new HtmlWidget('#widget', 'publicKey');
widget.load();
```

Then write only need 2 lines of code in js to initialize widget

### Full example

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>iframe {border: 0;width: 100%;height: 300px;}</style>
</head>
<body>
    <form id="paymentForm">
        <div id="widget"></div>
        <input name="payment_source_token" id="payment_source_token" type="hidden">
    </form>
    <script src="https://widget.paydock.com/sdk/latest/widget.umd.min.js" ></script>
    <script>
        var widget = new paydock.HtmlWidget('#widget', 'publicKey');
        widget.onFinishInsert('input[name="payment_source_token"]', 'payment_source');
        widget.load();
    </script>
</body>
</html>
```

## Widget advanced example

### Customization

```javascript
widget.setStyles({
  background_color: 'rgb(0, 0, 0)',
  border_color: 'yellow',
  text_color: '#FFFFAA',
  button_color: 'rgba(255, 255, 255, 0.9)',
  font_size: '20px'
 });
```

This example shows how you can customize to your needs and design

### Customization from html

```html
<div id="widget"
  widget-style="text-color: #FFFFAA; border-color: #yellow"
  title="Payment form"
  finish-text="Payment resource was successfully accepted"></div>
```

This example shows how you can set style and texts from html

### Settings

```javascript
widget.setRefId('id'); // your unique identifier to identify the data

widget.setFormFields(['phone', 'email']); // add additional fields for form of widget

widget.setSupportedCardIcons(['mastercard', 'visa']); // add icons of supported card types
```

This example shows how you can use a lot of other methods to settings your form

### Error handling

## Overview

Error events are emitted when an error occurs during widget operations. These events provide detailed information about the error, including its category, cause, and contextual details.

## Error Event Structure

### Base Properties

| Property | Type | Description |
|----------|------|-------------|
| `event` | `string` | Always set to `"error"` |
| `purpose` | `string` | Indicates the purpose of the action that triggered the error event (e.g., `"payment_source"`) |
| `message_source` | `string` | Source of the message (e.g., `"widget.paydock"`) |
| `ref_id` | `string` | Reference ID for the operation |
| `widget_id` | `string` | Unique identifier of the widget instance |
| `error` | `object` | Error object containing error information |

### Error Object Properties

The `error` object contains detailed information about the error:

| Property | Type | Description |
|----------|------|-------------|
| `category` | `string` | High-level error classification |
| `cause` | `string` | Specific error cause |
| `retryable` | `boolean` | Indicates if the operation can be retried |
| `details` | `object` | Additional error context |

## Error Categories

| Category | Description |
|----------|-------------|
| `configuration` | Configuration-related errors |
| `identity_access_management` | Authentication and authorization errors |
| `internal` | Internal system errors |
| `process` | Process and operation errors |
| `resource` | Resource-related errors |
| `validation` | Input validation errors |

## Error Causes

| Cause | Category | Description |
|-------|----------|-------------|
| `aborted` | `process` | Operation was aborted |
| `access_forbidden` | `identity` | Access to resource is forbidden |
| `already_exists` | `validation` | Resource already exists |
| `canceled` | `process` | Operation was canceled |
| `invalid_configuration` | `configuration` | Invalid widget configuration |
| `invalid_input` | `validation` | Invalid input provided |
| `not_found` | `resource` | Requested resource not found |
| `not_implemented` | `process` | Requested feature not implemented |
| `rate_limited` | `process` | Too many requests |
| `server_busy` | `process` | Server is too busy to handle request |
| `service_unreachable` | `process` | Unable to reach required service |
| `unauthorized` | `identity` | Authentication required |
| `unknown_error` | `internal` | Unexpected error occurred |
| `unprocessable_entity` | `validation` | Valid input but cannot be processed |

## Error Details Object

| Property | Type | Description |
|----------|------|-------------|
| `cause` | `string` | Matches the top-level error cause |
| `contextId` | `string` | Context identifier (usually matches widget_id) |
| `message` | `string` | Human-readable error message |
| `timestamp` | `string` | ISO 8601 timestamp of when the error occurred |

## Example

```javascript
widget.hideUiErrors(); // hide default UI errors and handle errors by listening to error events with widget.on('error')

widget.on('error', (error) => {
    console.log(error);
    // {
    //     "event": "error",
    //     "purpose": "payment_source",
    //     "message_source": "widget.paydock",
    //     "ref_id": "",
    //     "widget_id": "d4744f30-dcf5-168e-7f78-c8273a3401d4",
    //     "error": {
    //         "category": "process",
    //         "cause": "service_unreachable",
    //         "details": {
    //             "cause": "service_unreachable",
    //             "contextId": "d4744f30-dcf5-168e-7f78-c8273a3401d4",
    //             "message": "The service is not availabe",
    //             "timestamp": "2025-02-13T09:30:21.157Z"
    //         },
    //         "retryable": false
    //     }
    // }
});
```

## Handling Errors (Tips)

When handling errors, consider:

1. Check the `retryable` flag to determine if the operation can be retried
2. Use the `category` for high-level error handling logic
3. Use the `cause` for specific error handling cases
4. The `contextId` can be used for error tracking and debugging
5. The `timestamp` helps with error logging and debugging

### Full example

```html
<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
 <style>iframe {border: 0;width: 100%;height: 400px;}</style>
</head>
<body>
<form id="paymentForm">
    <div id="widget"
        widget-style="text-color: #FFFFAA; border-color: #yellow"
        title="Payment form"
        finish-text="Payment resource was successfully accepted">
    </div>

    <div 
        id="error" 
        style="
            display: none;
            max-width: 600px;
            margin: 16px auto;
            padding: 16px 20px;
            border-radius: 8px;
            background-color: #FEF2F2;
            border: 1px solid #FEE2E2;
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
            font-family: system-ui, -apple-system, sans-serif;
            color: #991B1B;
            line-height: 1.5;
            font-size: 14px;
        "
        title="error"
        >
        <div style="display: flex; align-items: flex-start; gap: 12px;">
            <div>
                <h4 style="margin: 0 0 4px 0; font-size: 14px; font-weight: 600;">Access Error</h4>
                <div id="error-message"></div>
            </div>
        </div>
    </div> 
</form>

<script src="https://widget.paydock.com/sdk/latest/widget.umd.js" ></script>
<script>
 var widget = new paydock.HtmlWidget('#widget', 'publicKey', 'gatewayId');

 widget.setSupportedCardIcons(['mastercard', 'visa']);
 widget.setFormFields(['phone', 'email']);
 widget.setRefId('custom-ref-id');
    widget.onFinishInsert('input[name="payment_source_token"]', 'payment_source');

    widget.on('error', ({ error }) => {
        document.getElementById('error-message').textContent = error.details.message;
        document.getElementById('error').style.display = 'block';
    });
 widget.load();
</script>

</body>
</html>
```
