# Custom transaction status page

The `preo-transaction-status` custom element provides a seamless way to display transaction status after payment processing. It automatically polls for transaction updates and emits events that you can use to display appropriate UI to your users.

## Overview

When customers complete a payment through Preo checkout, they are redirected to a transaction status page. The `preo-transaction-status` element handles:

- Automatic polling with exponential backoff
- Provider status verification
- Event emission for different transaction states
- Retry logic with smart fallbacks

## Basic Usage

```html
<preo-transaction-status transaction-id="tr_123456789" />
```

## Required Attributes

- **`transaction-id`**: The unique transaction identifier (typically from URL parameters like `?tid=`, `?invoice=`, or `?s=`)

## Optional Attributes

- **`sdk-id`**: Your Preo SDK identifier in the format `environment:cluster:tenant:event`. When provided, enables:
  - Analytics tracking through the Preo Analytics component
  - Event-specific configuration
  - Custom API endpoints

> **Note**: Starting from version 0.6.0, `sdk-id` is optional. If not provided, the component will use the default Preo API endpoint.

## Events

The component emits the following events that you can listen to:

### `onTransactionStatusChange`

Fired whenever the transaction status changes or is checked.

```javascript
document.addEventListener('onTransactionStatusChange', (event) => {
  const { transaction, isWaitingForFinalConfirmation } = event.detail[0];

  switch (transaction.status) {
    case 'pending':
    case 'started':
      // Show "processing" UI
      break;
    case 'provider_confirmed':
      // Show "almost there" UI
      break;
    case 'completed':
      // Show success UI
      break;
    case 'fail':
      // Show error UI
      break;
  }
});
```

### `onTransactionCompleted`

Fired only when the transaction is successfully completed. This is emitted through the global event system.

```javascript
window.addEventListener('onTransactionCompleted', (event) => {
  const { transaction, user, token } = event.detail;
  // Handle successful transaction
  // Save user data, redirect, etc.
});
```

## Transaction Statuses

- **`pending`/`started`**: Transaction is being processed
- **`provider_confirmed`**: Payment provider confirmed the payment, but backend is still processing
- **`completed`**: Transaction successfully completed
- **`fail`**: Transaction failed or couldn't be verified

## Implementation Examples

### Nuxt 3

1. Add the script to `nuxt.config.ts`:

```typescript
export default defineNuxtConfig({
  app: {
    head: {
      script: [{
        src: 'https://edge.preo.cloud/c/components@latest/components.umd.js',
        defer: true
      }]
    }
  },
  vue: {
    compilerOptions: {
      isCustomElement: (tag) => tag.startsWith('preo-')
    }
  }
})
```

2. Create a transaction status page:

```vue
<template>
  <div class="transaction-status">
    <div v-if="status === 'pending' || status === 'started'">
      <h2>Processing your order...</h2>
      <p>We're verifying your payment details...</p>
    </div>

    <div v-else-if="status === 'provider_confirmed'">
      <h2>Almost there!</h2>
      <p>Your payment has been confirmed and we're finalizing your order.</p>
    </div>

    <div v-else-if="status === 'completed'">
      <h2>Thank you for your purchase!</h2>
      <p>Your order has been confirmed.</p>
    </div>

    <div v-else-if="status === 'fail'">
      <h2>Something went wrong</h2>
      <p>We're having trouble completing your order. Please contact support.</p>
    </div>

    <preo-transaction-status
      :transaction-id="transactionId"
      @onTransactionStatusChange="handleStatusChange"
    />
  </div>
</template>

<script setup>
const route = useRoute()
const status = ref('pending')

const transactionId = computed(() =>
  route.query.tid || route.query.invoice || route.query.s || ''
)

const handleStatusChange = (event) => {
  const data = event.detail[0]
  if (data.transaction) {
    status.value = data.transaction.status

    // Handle completed transactions
    if (data.transaction.status === 'completed' && data.user) {
      // Save user data, update auth state, etc.
      console.log('Transaction completed', data)
    }
  }
}

onMounted(() => {
  document.addEventListener('onTransactionStatusChange', handleStatusChange)
})

onUnmounted(() => {
  document.removeEventListener('onTransactionStatusChange', handleStatusChange)
})
</script>
```

### Next.js

1. Add the script to your layout or page:

```typescript
import Script from 'next/script'

export default function TransactionLayout({ children }) {
  return (
    <>
      <Script
        src="https://edge.preo.cloud/c/components@latest/components.umd.js"
        strategy="afterInteractive"
      />
      {children}
    </>
  )
}
```

2. Create a transaction status page:

```typescript
'use client'

import { useSearchParams } from 'next/navigation'
import { useEffect, useState, useRef } from 'react'

declare global {
  namespace JSX {
    interface IntrinsicElements {
      'preo-transaction-status': React.DetailedHTMLProps<
        React.HTMLAttributes<HTMLElement> & {
          'transaction-id': string
          'sdk-id'?: string
        },
        HTMLElement
      >
    }
  }
}

export default function TransactionStatusPage() {
  const searchParams = useSearchParams()
  const [status, setStatus] = useState('pending')
  const elementRef = useRef(null)

  const transactionId = searchParams.get('tid') ||
                       searchParams.get('invoice') ||
                       searchParams.get('s') || ''

  useEffect(() => {
    const handleStatusChange = (event: CustomEvent) => {
      const data = event.detail[0]
      if (data.transaction) {
        setStatus(data.transaction.status)

        if (data.transaction.status === 'completed') {
          // Handle successful transaction
          console.log('Transaction completed', data)
        }
      }
    }

    document.addEventListener('onTransactionStatusChange', handleStatusChange)

    return () => {
      document.removeEventListener('onTransactionStatusChange', handleStatusChange)
    }
  }, [])

  return (
    <div className="transaction-status">
      {(status === 'pending' || status === 'started') && (
        <div>
          <h2>Processing your order...</h2>
          <p>We're verifying your payment details...</p>
        </div>
      )}

      {status === 'provider_confirmed' && (
        <div>
          <h2>Almost there!</h2>
          <p>Your payment has been confirmed and we're finalizing your order.</p>
        </div>
      )}

      {status === 'completed' && (
        <div>
          <h2>Thank you for your purchase!</h2>
          <p>Your order has been confirmed.</p>
        </div>
      )}

      {status === 'fail' && (
        <div>
          <h2>Something went wrong</h2>
          <p>We're having trouble completing your order. Please contact support.</p>
        </div>
      )}

      <preo-transaction-status
        ref={elementRef}
        transaction-id={transactionId}
      />
    </div>
  )
}
```

## Advanced Configuration

### With SDK ID (Full Analytics)

When you need analytics tracking and event-specific configuration:

```html
<preo-transaction-status
  transaction-id="tr_123456789"
  sdk-id="prod:eu:tenant:event">
</preo-transaction-status>
```

### Custom Retry Logic

The component uses the following retry strategy by default:
- 5 retry attempts with delays: 5s, 7s, 10s, 12s, 10s
- After 5 failed attempts, checks with the payment provider directly
- If provider confirms but backend hasn't received it (HTTP 202), waits 10s for final confirmation

### Handling Analytics

The component automatically emits analytics events when transactions are completed. To integrate with your analytics:

```javascript
window.addEventListener('onTransactionCompleted', (event) => {
  const { transaction, user, transactionId } = event.detail;

  // Google Analytics
  gtag('event', 'purchase', {
    transaction_id: transactionId,
    value: transaction.total,
    currency: transaction.currency
  });

  // Facebook Pixel
  fbq('track', 'Purchase', {
    value: transaction.total,
    currency: transaction.currency
  });

  // Google Tag Manager
  dataLayer.push({
    'event': 'purchase',
    'ecommerce': {
      'transaction_id': transactionId,
      'value': transaction.total,
      'currency': transaction.currency
    }
  });
});
```

## Troubleshooting

### Component Not Working

1. Ensure the Preo components script is loaded before the element is used
2. Check that custom elements are allowed in your framework (see framework-specific configs above)
3. Verify the `transaction-id` is correct and not empty

### Events Not Firing

1. Make sure you're listening to the correct event names
2. Remember that `onTransactionStatusChange` is emitted on `document`, while `onTransactionCompleted` is on `window`
3. Check browser console for any errors

### Status Stuck on "Processing"

This usually means:
- The transaction ID is invalid
- Network issues preventing API calls
- The transaction is genuinely taking longer to process

## Version Compatibility

- Requires `@preo-live/components` version 0.5.0 or higher
- `sdk-id` is optional starting from version 0.6.0
- Works with all modern browsers that support Custom Elements
- For older browsers, include the Custom Elements polyfill
