npm package: @getspot/spot-widget-vue2
Description: Vue 2 wrapper for Spot Widget
Latest version: 4.1.1

# @getspot/spot-widget-vue2

Vue 2 component wrapper for the Spot refund guarantee widget.

> **Note:** This Vue 2 wrapper uses types from [@getspot/spot-widget](https://www.npmjs.com/package/@getspot/spot-widget).

### Key Types
- `ApiConfig` - API configuration (environment, partnerId, customEndpoint)
- `QuoteRequestData` - Quote request data for single items or batch requests
- `SelectionData` - User selection data returned in callbacks
- `Quote` - Quote response data with pricing and terms
- `Theme` - Styling customization options

For complete type definitions, see the [@getspot/spot-widget documentation](https://www.npmjs.com/package/@getspot/spot-widget).

## Installation

```bash
npm install @getspot/spot-widget-vue2
```

## Quick Start

```vue
<template>
  <Vue2SpotWidget
    :api-config="{
      environment: 'production',
      partnerId: 'your-partner-id'
    }"
    :quote-request-data="quoteData"
    :show-table="true"
    :selection="'unselected'"
    @quote-retrieved="onQuoteRetrieved"
    @opt-in="onOptIn"
    @opt-out="onOptOut"
    @error="onError"
  />
</template>

<script>
import Vue2SpotWidget from '@getspot/spot-widget-vue2';

export default {
  components: {
    Vue2SpotWidget
  },
  
  data() {
    return {
      quoteData: {
        startDate: '2024-01-01T00:00:00Z',
        endDate: '2024-01-07T23:59:59Z',
        currencyCode: 'USD',
        eventType: 'Ski Trip',
        productType: 'Trip',
        productDuration: 'Trip',
        productPrice: 500,
        productId: 'ski-trip-2024',
        cartId: 'cart-123',
        productName: 'Aspen Ski Trip 2024'
      }
    };
  },

  methods: {
    onQuoteRetrieved(quote) {
      console.log('Quote retrieved:', quote);
    },

    onOptIn(data) {
      console.log('User opted in:', data);
      // Handle opt-in logic
    },

    onOptOut(data) {
      console.log('User opted out:', data);
      // Handle opt-out logic
    },

    onError(error) {
      console.error('Widget error:', error);
      // Handle errors
    }
  }
};
</script>
```

## TypeScript Support

This package includes TypeScript definitions for Vue 2. To use with TypeScript:

```vue
<template>
  <Vue2SpotWidget
    :api-config="apiConfig"
    :quote-request-data="quoteData"
    @opt-in="onOptIn"
    @opt-out="onOptOut"
    @error="onError"
  />
</template>

<script lang="ts">
import Vue from 'vue';
import Vue2SpotWidget from '@getspot/spot-widget-vue2';
import type { Quote, SelectionData, ApiConfig, QuoteRequestData } from '@getspot/spot-widget';

interface Data {
  apiConfig: ApiConfig;
  quoteData: QuoteRequestData;
}

export default Vue.extend({
  components: {
    Vue2SpotWidget
  },
  
  data(): Data {
    return {
      apiConfig: {
        environment: 'production',
        partnerId: 'your-partner-id'
      },
      quoteData: {
        startDate: '2024-01-01T00:00:00Z',
        endDate: '2024-01-07T23:59:59Z',
        currencyCode: 'USD',
        eventType: 'Test Event',
        productType: 'Trip',
        productDuration: 'Trip',
        productPrice: 100,
        productId: 'test-product',
        cartId: 'test-cart',
        productName: 'Test Product'
      }
    };
  },

  methods: {
    onOptIn(data: SelectionData) {
      console.log('User opted in:', data);
    },

    onOptOut(data: SelectionData) {
      console.log('User opted out:', data);
    },

    onError(error: Error) {
      console.error('Widget error:', error);
    }
  }
});
</script>
```

## Props

### Required Props

| Prop | Type | Description |
|------|------|-------------|
| `apiConfig` | `ApiConfig` | Configuration for the Spot API including environment and partner ID |
| `quoteRequestData` | `QuoteRequestData` | Quote request data containing product and cart information |

### Optional Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `showTable` | `boolean` | `true` | Whether to show the payout table |
| `selection` | `SelectionEnum` | `'unselected'` | Initial selection state for the widget |
| `theme` | `Theme` | `undefined` | Theme customization options for styling the widget |

## Events

The component emits the following events:

### @quote-retrieved

Emitted when a quote is successfully retrieved.

```vue
<Vue2SpotWidget @quote-retrieved="onQuoteRetrieved" />
```

**Payload:** `Quote` object

### @opt-in

Emitted when user opts in to the refund guarantee.

```vue
<Vue2SpotWidget @opt-in="onOptIn" />
```

**Payload:** `SelectionData` object with `status: 'QUOTE_ACCEPTED'`

### @opt-out

Emitted when user opts out of the refund guarantee.

```vue
<Vue2SpotWidget @opt-out="onOptOut" />
```

**Payload:** `SelectionData` object with `status: 'QUOTE_DECLINED'`

### @error

Emitted when an error occurs during quote retrieval.

```vue
<Vue2SpotWidget @error="onError" />
```

**Payload:** Error object with `message`, `status`, and `responseBody`

### @no-matching-quote

Emitted when no matching quote is found.

```vue
<Vue2SpotWidget @no-matching-quote="onNoMatchingQuote" />
```

**Payload:** Object with `status: 'NO_MATCHING_QUOTE'` and original request data

### @selection-change

Emitted when user changes their selection (opt-in or opt-out).

```vue
<Vue2SpotWidget @selection-change="onSelectionChange" />
```

**Payload:** `SelectionData` object

## Exposed Methods

You can access widget methods using template refs:

```vue
<template>
  <div>
    <Vue2SpotWidget
      ref="spotWidget"
      v-bind="widgetProps"
    />
    <button @click="updateQuote">Update Quote</button>
    <button @click="getSelection">Get Selection</button>
    <button @click="validateSelection">Validate Selection</button>
  </div>
</template>

<script>
import Vue2SpotWidget from '@getspot/spot-widget-vue2';

export default {
  components: {
    Vue2SpotWidget
  },

  methods: {
    async updateQuote() {
      const success = await this.$refs.spotWidget.updateQuote({
        // new quote data
      });
      console.log('Quote updated:', success);
    },

    getSelection() {
      const selection = this.$refs.spotWidget.getSelection();
      console.log('Current selection:', selection);
    },

    validateSelection() {
      const isValid = this.$refs.spotWidget.validateSelection();
      console.log('Selection is valid:', isValid);
    }
  }
};
</script>
```

### Available Methods

| Method | Return Type | Description |
|--------|-------------|-------------|
| `updateQuote(data)` | `Promise<boolean>` | Update the quote with new request data |
| `getSelection()` | `SelectionData \| null` | Get the current user selection |
| `validateSelection()` | `boolean` | Validate that the user has made a selection |
| `destroy()` | `void` | Destroy the widget instance and clean up resources |

## Configuration

### API Configuration

The `apiConfig` prop accepts the following options:

```typescript
{
  environment: 'production' | 'sandbox' | 'local',
  partnerId: string,
  customEndpoint?: string // Optional custom API endpoint
}
```

### Quote Request Data

#### Single Quote Format

```typescript
{
  startDate: string,        // ISO 8601 date string
  endDate: string,          // ISO 8601 date string  
  currencyCode: 'USD' | 'CAD' | 'AUD',
  eventType: string,        // e.g., "Ski Trip", "Concert"
  productType: 'Pass' | 'Trip' | 'Registration',
  productDuration: 'Daily' | 'Seasonal' | 'Trip' | 'Event',
  productPrice: number,     // Price in specified currency
  productId: string,        // Unique product identifier
  cartId: string,           // Cart identifier
  productName: string,      // Human-readable product name
  participantDescription?: string // Optional participant details
}
```

#### Batch Quote Format

For multiple items in a cart:

```typescript
{
  cartId: string,
  cartName: string,
  currencyCode: 'USD' | 'CAD' | 'AUD',
  items: Array<{
    // Same fields as single quote, minus cartId and currencyCode
    cartItemId?: string // Optional unique identifier for cart item
  }>
}
```

## Styling

Customize the widget appearance using the `theme` prop:

```vue
<template>
  <Vue2SpotWidget
    :theme="{
      primaryColor: '#007bff',
      borderRadius: '8px',
      fontFamily: 'Arial, sans-serif'
    }"
    v-bind="otherProps"
  />
</template>
```

## Error Handling

Always implement error handling for production use:

```vue
<template>
  <div>
    <Vue2SpotWidget
      v-bind="widgetProps"
      @error="handleError"
      @no-matching-quote="handleNoQuote"
    />
    <div v-if="errorMessage" class="error-message">
      {{ errorMessage }}
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      errorMessage: ''
    };
  },

  methods: {
    handleError(error) {
      console.error('Spot Widget Error:', error);
      
      // Show user-friendly message
      this.errorMessage = 'Unable to load refund options. Please try again.';
      
      // Track error in analytics
      if (window.analytics) {
        window.analytics.track('spot_widget_error', {
          message: error.message,
          status: error.status
        });
      }
    },

    handleNoQuote() {
      this.errorMessage = 'No refund guarantee available for this product.';
    }
  }
};
</script>
```

## Vue 2 Specific Notes

This package is specifically designed for Vue 2.x applications. Key differences from the Vue 3 version:

- Uses Vue 2 Options API syntax
- Compatible with Vue 2.6+ (requires Vue 2.7+ for full TypeScript support)
- Uses `beforeDestroy` lifecycle hook instead of `beforeUnmount`
- Function-based watchers instead of arrow functions for Vue 2 compatibility

## Compatibility

- **Vue**: 2.6+
- **TypeScript**: 4.x - 5.x (requires Vue 2.7+ for full TS support)
- **Node.js**: 16+

## Migration from Vue 2 to Vue 3

If you're migrating from Vue 2 to Vue 3, consider switching to `@getspot/spot-widget-vue` which is designed for Vue 3 and includes:

- Composition API support
- Better TypeScript integration
- Modern Vue 3 lifecycle hooks
- Enhanced performance

## License

See the main package for license information.

## Support

For support, please contact [support@getspot.com](mailto:support@getspot.com).