# Address Component

The Address component manages delivery location for availability checking and accurate pricing throughout the SDK.

## Overview

The Address component:
- Provides location input via Google Places integration
- Allows manual address entry
- Stores location for cart/checkout
- Enables location-based pricing
- Determines product availability
- Supports fulfillment type selection

## How It Works

The address component is **embedded in the product component by default**. Users set their address when viewing products, and this address is used throughout the cart and checkout flow.

### Automatic Address Prompting

When a user tries to add a product to cart without setting an address:

1. Address input drawer opens automatically
2. User enters their address
3. Address is saved
4. Add-to-cart action resumes automatically

No additional code needed - this is handled automatically.

## Standalone Usage

Use the standalone address component when you need a dedicated address selection page:

```javascript
const client = await Elements('YOUR_API_KEY', { env: 'production' });

await client.injectAddressElement('address-container', {
  onAddressSet: (address) => {
    console.log('Address set:', address);
  }
});
```

```html
<div id="address-container"></div>
```

## Address Actions

### Set Address via Google Places ID

The recommended method - provides accurate geocoding:

```javascript
await window.LiquidCommerce.elements.actions.address.setAddressByPlacesId('ChIJOwg_06VPwokRYv534QaPC8g');
```

**How to get a Places ID:**

Visit [Google Place IDs](https://developers.google.com/maps/documentation/places/web-service/place-id#find-id) for details on obtaining a Places ID.

### Set Address Manually

For custom address flows without Google Places:

```javascript
await window.LiquidCommerce.elements.actions.address.setAddressManually(
  {
    one: '123 Main Street',
    two: 'Apt 4',         // Optional
    city: 'New York',
    state: 'NY',
    zip: '10001'
  },
  {
    latitude: 40.7128,
    longitude: -74.0060
  }
);
```

**Requirements:**
- `one`: Street address (required)
- `two`: Apartment, suite, etc. (optional)
- `city`: City name (required)
- `state`: Two-letter state code (required)
- `zip`: ZIP/postal code (required)
- `latitude`: Number between -90 and 90 (required)
- `longitude`: Number between -180 and 180 (required)

### Get Address Details

Retrieve the current address:

```javascript
const addressData = window.LiquidCommerce.elements.actions.address.getDetails();

console.log(addressData);
// {
//   id: 'ChIJ...',
//   address: {
//     one: '123 Main Street',
//     two: 'Apt 4',
//     city: 'New York',
//     state: 'NY',
//     zip: '10001'
//   },
//   coordinates: {
//     latitude: 40.7128,
//     longitude: -74.0060
//   },
//   formattedAddress: '123 Main Street, Apt 4, New York, NY 10001'
// }

// Returns null if no address is set
```

### Clear Address

Remove the current address:

```javascript
await window.LiquidCommerce.elements.actions.address.clear();
```

This will:
- Clear stored address
- Trigger address prompts on next cart action
- Update all components that depend on location

## Events

### Address Updated

Fired when a new address is set:

```javascript
window.addEventListener('lce:actions.address_updated', (event) => {
  const { address, coordinates, formattedAddress } = event.detail.data;
  
  console.log('New address:', formattedAddress);
  console.log('Coordinates:', coordinates);
});
```

### Address Cleared

Fired when address is removed:

```javascript
window.addEventListener('lce:actions.address_cleared', (event) => {
  console.log('Address has been cleared');
});
```

### Address Failed

Fired when address setting fails:

```javascript
window.addEventListener('lce:actions.address_failed', (event) => {
  const { error } = event.detail.data;
  console.error('Address error:', error);
});
```

## Customization

### Theme Configuration

Customize address component appearance:

```javascript
const client = await Elements('YOUR_API_KEY', {
  env: 'production',
  customTheme: {
    address: {
      theme: {
        backgroundColor: '#ffffff'
      }
    }
  }
});
```

## Use Cases

### Dedicated Location Page

Create a dedicated page for address selection:

```html
<!DOCTYPE html>
<html>
<head>
  <title>Set Delivery Location</title>
  <script
    defer
    data-liquid-commerce-elements
    data-token="YOUR_API_KEY"
    data-env="production"
    type="text/javascript"
    src="https://elements.reservebar-worker.workers.dev/all/elements.js"
  ></script>
</head>
<body>
  <h1>Where should we deliver?</h1>
  <div id="address"></div>
  
  <script>
    window.addEventListener('lce:actions.client_ready', async () => {
      await window.LiquidCommerce.elements.injectAddressElement('address');
    });
    
    window.addEventListener('lce:actions.address_updated', () => {
      // Redirect to product page after address is set
      window.location.href = '/products';
    });
  </script>
</body>
</html>
```

### Custom Address Input with Validation

```javascript
document.getElementById('save-address-btn').addEventListener('click', async () => {
  const address = {
    one: document.getElementById('street').value,
    two: document.getElementById('apt').value,
    city: document.getElementById('city').value,
    state: document.getElementById('state').value,
    zip: document.getElementById('zip').value
  };
  
  // Get coordinates from your geocoding service
  const coords = await geocodeAddress(address);
  
  try {
    await window.LiquidCommerce.elements.actions.address.setAddressManually(address, coords);
    showSuccessMessage('Address saved!');
  } catch (error) {
    showErrorMessage('Invalid address');
  }
});
```

### Pre-fill Address from User Account

```javascript
// After user logs in, set their saved address
window.addEventListener('lce:actions.client_ready', async () => {
  if (userIsLoggedIn && !currentAddressSet) {
    await window.LiquidCommerce.elements.actions.address.setAddressManually(
      user.savedAddress,
      user.savedCoordinates
    );
  }
});
```

### Location-Based Product Filtering

```javascript
window.addEventListener('lce:actions.address_updated', async (event) => {
  const { coordinates } = event.detail.data;
  
  // Fetch products available in this location
  const availableProducts = await fetch('/api/products', {
    method: 'POST',
    body: JSON.stringify({ latitude: coordinates.latitude, longitude: coordinates.longitude })
  }).then(r => r.json());
  
  // Update UI with available products
  displayProducts(availableProducts);
});
```

### Multi-Location Switcher

```javascript
const locations = [
  { name: 'Home', placesId: 'ChIJ...' },
  { name: 'Work', placesId: 'ChIJ...' },
  { name: 'Mom\'s House', placesId: 'ChIJ...' }
];

document.getElementById('location-select').addEventListener('change', async (e) => {
  const selectedLocation = locations[e.target.value];
  
  await window.LiquidCommerce.elements.actions.address.setAddressByPlacesId(
    selectedLocation.placesId
  );
  
  showNotification(`Switched to ${selectedLocation.name}`);
});
```

## Address Persistence

### Storage

Addresses are stored in:
- SDK internal store
- LocalStorage (for persistence)
- Session (until explicitly cleared)

### Lifespan

Addresses persist:
- Across page refreshes
- Across browser sessions
- Until explicitly cleared by user or code

### Privacy

Addresses are:
- Stored locally in the browser
- Not sent to external servers except for availability checking
- Cleared when user logs out (if you implement logout handling)

## Best Practices

### Request Early

Set address as early as possible in the user flow:

```javascript
// On homepage or landing page
window.addEventListener('lce:actions.client_ready', () => {
  const currentAddress = window.LiquidCommerce.elements.actions.address.getDetails();
  
  if (!currentAddress) {
    // Show address prompt
    showAddressPrompt();
  }
});
```

### Provide Context

Explain why you need the address:

```html
<div class="address-explainer">
  <h2>Where should we deliver?</h2>
  <p>We need your location to show available products and accurate pricing.</p>
  <div id="address"></div>
</div>
```

### Validate Manually Entered Addresses

When using manual address entry, validate before setting:

```javascript
async function setAddress(address, coords) {
  // Validate format
  if (!address.one || !address.city || !address.state || !address.zip) {
    throw new Error('Missing required address fields');
  }
  
  // Validate state code
  if (address.state.length !== 2) {
    throw new Error('State must be 2-letter code');
  }
  
  // Validate ZIP
  if (!/^\d{5}(-\d{4})?$/.test(address.zip)) {
    throw new Error('Invalid ZIP code');
  }
  
  // Validate coordinates
  if (coords.latitude < -90 || coords.latitude > 90) {
    throw new Error('Invalid latitude');
  }
  
  if (coords.longitude < -180 || coords.longitude > 180) {
    throw new Error('Invalid longitude');
  }
  
  // Set address
  await window.LiquidCommerce.elements.actions.address.setAddressManually(address, coords);
}
```

### Handle Errors Gracefully

```javascript
try {
  await window.LiquidCommerce.elements.actions.address.setAddressByPlacesId(placesId);
} catch (error) {
  console.error('Failed to set address:', error);
  
  // Show user-friendly error
  showError('Unable to set that address. Please try again or enter manually.');
  
  // Fall back to manual entry
  showManualAddressForm();
}
```
## Troubleshooting

### Address Not Persisting

1. Check localStorage is not disabled
2. Verify no errors in console
3. Ensure `clear()` is not being called unintentionally
4. Check that address was set successfully (no errors thrown)

### Products Not Updating After Address Change

1. Products should automatically rerender when address changes
2. Check console for errors
3. Verify address was actually set (not just input changed)
4. Try manually rerendering product components

### Invalid Address Errors

1. Ensure all required fields are provided
2. Verify coordinates are within valid ranges
3. Check state code is 2 letters
4. Validate ZIP code format
5. Use Places ID method for most accurate results

## See Also

- [Product Component](./product-component.md) - Uses address for availability
- [Cart Component](./cart-component.md) - Requires address for adding items
- [Actions API](../api/actions/address-actions.md) - Address actions reference
- [Events](./events.md) - All available events
