> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rocky.global/llms.txt
> Use this file to discover all available pages before exploring further.

# GOOGLE MAPS ERROR HANDLING

# Google Maps Error Handling Documentation

## Overview

This document describes the robust error handling implementation for Google Maps API integration on public event pages. The solution ensures that event pages load successfully even when Google Maps API is unavailable or fails to load.

## Problem Statement

Previously, when the Google Maps API failed to load or was slow to initialize, the public event page would encounter JavaScript errors that could block page functionality:

* `Uncaught TypeError: Cannot read properties of undefined (reading 'addDomListener')`
* `Uncaught TypeError: google.maps.LatLng is not a constructor`

These errors prevented the event page from loading correctly and resulted in a poor user experience.

## Solution

### 1. Strict API Validation

**Location:** `resources/views/visual-aspect/show-public.blade.php`

The `initMap()` function now performs strict validation before attempting to initialize the map:

```javascript theme={null}
function initMap() {
    // Check if Google Maps API core constructors are present
    if (typeof google === 'undefined' || typeof google.maps === 'undefined' ||
        typeof google.maps.Map === 'undefined' || typeof google.maps.LatLng === 'undefined') {
        // Show non-blocking error message
        var errorEl = document.getElementById('google-map-error');
        if (errorEl) {
            errorEl.classList.remove('d-none');
        }
        return;
    }
    // ... continue with map initialization
}
```

**Key Points:**

* Validates presence of `google`, `google.maps`, `google.maps.Map`, and `google.maps.LatLng`
* Does not attempt initialization if core constructors are missing
* Displays user-friendly error message instead of throwing exceptions

### 2. Exception Handling

All map creation and marker placement operations are wrapped in try-catch blocks:

```javascript theme={null}
var map;
try {
    map = new google.maps.Map(mapContainer, mapOptions);
} catch (err) {
    var errorElInit = document.getElementById('google-map-error');
    if (errorElInit) {
        errorElInit.classList.remove('d-none');
    }
    return;
}
```

This prevents uncaught exceptions from breaking the page.

### 3. Non-Blocking Error UI

**HTML Addition:**

```html theme={null}
<div id="google-map-error" class="alert alert-warning mt-2 d-none" role="alert" aria-live="polite">
    {{ __('event.map_unavailable', ['default' => 'Map temporarily unavailable. The event information is still available below.']) }}
</div>
```

**Features:**

* Hidden by default (`d-none` class)
* Revealed when map fails to load
* Non-blocking: event information remains accessible
* Accessibility-friendly with `role="alert"` and `aria-live="polite"`

### 4. Enhanced Polling Mechanism

**Location:** `resources/views/visual-aspect/show-public.blade.php`

```javascript theme={null}
function waitForGoogleMaps() {
    if (typeof google !== 'undefined' && typeof google.maps !== 'undefined' && typeof google.maps.Map !== 'undefined') {
        initMap();
    } else {
        // Listen for custom Google Maps loaded event
        window.addEventListener('google-maps-loaded', function() {
            initMap();
        }, { once: true });

        // Fallback: check periodically for Google Maps to load
        var checkInterval = setInterval(function() {
            if (typeof google !== 'undefined' && typeof google.maps !== 'undefined' && typeof google.maps.Map !== 'undefined') {
                clearInterval(checkInterval);
                initMap();
            }
        }, 100);

        // Stop checking after 10 seconds
        setTimeout(function() {
            clearInterval(checkInterval);
            // If still not loaded, reveal error but keep page functional
            var errorElTimeout = document.getElementById('google-map-error');
            if (errorElTimeout && (typeof google === 'undefined' || typeof google.maps === 'undefined' || typeof google.maps.Map === 'undefined')) {
                errorElTimeout.classList.remove('d-none');
            }
        }, 10000);
    }
}
```

**Features:**

* Multiple detection strategies (immediate, event-based, polling)
* 10-second timeout with graceful degradation
* Error message display after timeout
* Page remains fully functional regardless of map status

### 5. Safe Stub for script.min.js

**Location:** `resources/views/layouts/events.blade.php`

A minimal stub is created before loading `script.min.js` to prevent errors from `addDomListener` calls:

```javascript theme={null}
(function() {
    try {
        // Only create a minimal stub for the event namespace to avoid breaking addDomListener calls
        if (typeof window.google === 'undefined') {
            window.google = {};
        }
        if (typeof window.google.maps === 'undefined') {
            window.google.maps = {};
        }
        if (typeof window.google.maps.event === 'undefined') {
            window.google.maps.event = {
                addDomListener: function() {
                    // No-op until real Google Maps loads
                }
            };
        }
    } catch (e) {
        // Silently handle errors
    }
})();
```

**Important:**

* Only stubs the `event` namespace, not constructors
* Prevents premature initialization attempts
* Does not interfere with validation checks in `initMap()`
* Allows legacy scripts to call `addDomListener` safely

## User Experience

### When Google Maps Loads Successfully

* Map displays normally with event location marker
* No error messages shown
* Full interactive map functionality

### When Google Maps Fails to Load

* Event page loads completely and remains functional
* Warning message appears in map container: "Map temporarily unavailable. The event information is still available below."
* All event information, pricing, and booking functionality remain accessible
* No JavaScript errors in console
* Page does not break or hang

## Localization

The error message supports localization through Laravel's translation system:

**Key:** `event.map_unavailable`

**Default:** "Map temporarily unavailable. The event information is still available below."

To customize the message, add the key to your language files:

```php theme={null}
// lang/en/event.php
'map_unavailable' => 'Map temporarily unavailable. The event information is still available below.',

// lang/es/event.php
'map_unavailable' => 'Mapa temporalmente no disponible. La información del evento sigue disponible a continuación.',
```

## Files Modified

1. **resources/views/visual-aspect/show-public.blade.php**
   * Enhanced `initMap()` with strict validation
   * Added try-catch blocks around map creation
   * Added error message UI element
   * Enhanced `waitForGoogleMaps()` with timeout handling

2. **resources/views/layouts/events.blade.php**
   * Added minimal safe stub for `google.maps.event.addDomListener`
   * Wrapped stub in IIFE for isolation
   * Positioned before `script.min.js` load

## Testing Scenarios

### Manual Testing

1. **Normal Load:** Open event page with normal internet connection
   * Expected: Map loads and displays correctly

2. **Slow Connection:** Throttle network to simulate slow API load
   * Expected: Page loads, polling continues, map appears when API ready

3. **API Blocked:** Block `maps.googleapis.com` in browser
   * Expected: Page loads, error message appears after 10s, page remains functional

4. **API Error:** Simulate API key error (403)
   * Expected: Page loads, error message appears, booking remains accessible

### Browser Console Tests

```javascript theme={null}
// Test 1: Verify stub exists before API loads
console.log(typeof google.maps.event.addDomListener); // Should be 'function'

// Test 2: Verify error handling
// (Block API and wait 10s)
document.getElementById('google-map-error').classList.contains('d-none'); // Should be false

// Test 3: Verify page functionality
// All other page elements should be interactive
```

## Performance Impact

* **Negligible:** Polling runs every 100ms for max 10 seconds
* **Memory:** Minimal overhead from stub and event listeners
* **UX:** No noticeable delay in page load time

## Accessibility

* Error message uses `role="alert"` for screen reader announcement
* `aria-live="polite"` ensures non-intrusive notification
* Map container maintains `min-height: 260px` to prevent layout shift

## Future Improvements

1. Add retry mechanism with exponential backoff
2. Implement static map fallback image
3. Add analytics tracking for map load failures
4. Consider Progressive Web App (PWA) offline map caching

## Related Issues

* Fixes: Google Maps blocking public event page load
* Prevents: `TypeError: Cannot read properties of undefined (reading 'addDomListener')`
* Prevents: `TypeError: google.maps.LatLng is not a constructor`

## Commit Reference

**Commit:** `fix: robust Google Maps loading with non-blocking fallback`

**Branch:** `feature/869az6wak`

**Date:** October 28, 2025

***

**Last Updated:** October 28, 2025\
**Author:** Development Team\
**Status:** Implemented and Deployed
