# Google Places API Integration - Inštruktáž pre Claude

## Úloha
Pridaj na HTML stránku automatické načítavanie **Google hodnotenia** a **počtu recenzií** z Google Places API.

**DÔLEŽITÉ:** Tento kód používa **unikátne localStorage cache keys** (obsahujú BUSINESS_NAME) aby sa predišlo konfliktom ak máš viac stránok na rovnakej doméne. Každá stránka má svoj vlastný nezávislý cache.

---

## Požiadavky od užívateľa

Užívateľ ti poskytne:
1. **HTML súbor** stránky
2. **Google Places API kľúč** (začína `AIzaSy...`)
3. **Názov miesta** na vyhľadanie (napr. "Autoservis Vladimír Hrabárik Sereď")
4. **GPS súradnice** miesta (latitude, longitude)

---

## Krok 1: Nájdi elementy pre hodnotenie a recenzie

Vyhľadaj v HTML-ku `<span>` alebo iné elementy kde sa zobrazujú:
- Google hodnotenie (napr. `4.6★`)
- Počet Google recenzií (napr. `131`)

Pridaj im **ID** ak ich nemajú:

```html
<!-- PRED -->
<div>4.6★</div>
<div>131 recenzií</div>

<!-- PO -->
<div><span id="google-rating">4.6</span>★</div>
<div><span id="google-reviews">131</span> recenzií</div>
```

**Dôležité:**
- Hardcoded hodnoty ostávajú ako fallback (ak JavaScript nefunguje)
- ID musia byť presne: `google-rating` a `google-reviews`

---

## Krok 2: Pridaj JavaScript kód pred `</body>`

Vlož tento kód na koniec HTML-ky, **tesne pred** closing tag `</body>`:

```html
    <script>
        // Google Places API Integration (NEW REST API)
        // Automatically updates rating and reviews once per day
        // ============================================
        (function() {
            console.log('[YourBusiness] 🚀 Script sa spúšťa...');
            
            // === KONFIGURÁCIA - VYPLŇ TIETO HODNOTY ===
            const API_KEY = 'AIzaSy...'; // Google Places API kľúč
            const SEARCH_QUERY = 'Názov vášho miesta'; // Presný názov pre vyhľadanie
            const BUSINESS_NAME = 'YourBusiness'; // Krátky názov pre logy (napr. 'Hrabarik')
            
            // GPS súradnice vášho miesta
            const GPS_LATITUDE = 48.2793593;
            const GPS_LONGITUDE = 17.7243325;
            const GPS_RADIUS = 100; // radius v metroch
            
            // Cache nastavenia
            const CACHE_KEY = 'google_places_data_' + BUSINESS_NAME.toLowerCase(); // Unikátny key pre túto stránku
            const CACHE_TIME_KEY = 'google_places_cache_time_' + BUSINESS_NAME.toLowerCase(); // Unikátny key pre túto stránku
            const CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hodín
            // ==========================================
            
            console.log(`[${BUSINESS_NAME}] 📋 Konfigurácia:`);
            console.log(`[${BUSINESS_NAME}]    🔑 API Key: ${API_KEY.substring(0, 20)}...`);
            console.log(`[${BUSINESS_NAME}]    🔍 Query: "${SEARCH_QUERY}"`);

            function updateGoogleData(rating, reviews) {
                const ratingEl = document.getElementById('google-rating');
                const reviewsEl = document.getElementById('google-reviews');
                
                console.log(`[${BUSINESS_NAME}] 🔍 Hľadám elementy...`);
                console.log(`[${BUSINESS_NAME}] Rating element:`, ratingEl ? '✅ Nájdený' : '❌ Nenájdený');
                console.log(`[${BUSINESS_NAME}] Reviews element:`, reviewsEl ? '✅ Nájdený' : '❌ Nenájdený');
                
                if (ratingEl) {
                    ratingEl.textContent = rating.toFixed(1);
                    console.log(`[${BUSINESS_NAME}] ✅ Rating aktualizovaný na: ${rating.toFixed(1)}`);
                } else {
                    console.error(`[${BUSINESS_NAME}] ❌ Nemôžem aktualizovať rating - element nenájdený!`);
                }
                
                if (reviewsEl) {
                    reviewsEl.textContent = reviews;
                    console.log(`[${BUSINESS_NAME}] ✅ Reviews aktualizované na: ${reviews}`);
                } else {
                    console.error(`[${BUSINESS_NAME}] ❌ Nemôžem aktualizovať reviews - element nenájdený!`);
                }
                
                console.log(`[${BUSINESS_NAME}] ✅ Google dáta aktualizované: ${rating}★ ${reviews} recenzií`);
            }

            function checkCache() {
                // Check for force refresh parameter
                const urlParams = new URLSearchParams(window.location.search);
                if (urlParams.get('refresh') === '1') {
                    console.log(`[${BUSINESS_NAME}] 🔄 Force refresh aktivovaný - vymazávam cache`);
                    localStorage.removeItem(CACHE_KEY);
                    localStorage.removeItem(CACHE_TIME_KEY);
                    return false;
                }

                const cached = localStorage.getItem(CACHE_KEY);
                const cacheTime = localStorage.getItem(CACHE_TIME_KEY);
                
                if (cached && cacheTime) {
                    const age = Date.now() - parseInt(cacheTime);
                    
                    if (age < CACHE_DURATION) {
                        try {
                            const data = JSON.parse(cached);
                            updateGoogleData(data.rating, data.userRatingCount);
                            console.log(`[${BUSINESS_NAME}] 📦 Použité cachované dáta (${Math.round(age/1000/60/60)}h staré)`);
                            return true;
                        } catch (e) {
                            console.error(`[${BUSINESS_NAME}] ⚠️ Chybné cache dáta`);
                        }
                    }
                }
                return false;
            }

            function saveCache(rating, reviews) {
                const data = { rating, userRatingCount: reviews };
                localStorage.setItem(CACHE_KEY, JSON.stringify(data));
                localStorage.setItem(CACHE_TIME_KEY, Date.now().toString());
                console.log(`[${BUSINESS_NAME}] 💾 Dáta uložené do cache (platné 24h)`);
            }

            async function searchAndFetchDetails(apiKey, query) {
                console.log(`[${BUSINESS_NAME}] 🔍 Vyhľadávam miesto...`);

                try {
                    const searchUrl = 'https://places.googleapis.com/v1/places:searchText';
                    
                    console.log(`[${BUSINESS_NAME}] 📍 Search URL: ${searchUrl}`);
                    console.log(`[${BUSINESS_NAME}] 📝 Query: "${query}"`);
                    console.log(`[${BUSINESS_NAME}] 🔑 API Key: ${apiKey.substring(0, 20)}...`);
                    
                    const requestBody = {
                        textQuery: query,
                        locationBias: {
                            circle: {
                                center: {
                                    latitude: GPS_LATITUDE,
                                    longitude: GPS_LONGITUDE
                                },
                                radius: GPS_RADIUS
                            }
                        }
                    };
                    
                    console.log(`[${BUSINESS_NAME}] 📤 Posielam request...`);
                    
                    const searchResponse = await fetch(searchUrl, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'X-Goog-Api-Key': apiKey,
                            'X-Goog-FieldMask': 'places.id,places.displayName,places.formattedAddress'
                        },
                        body: JSON.stringify(requestBody)
                    });

                    console.log(`[${BUSINESS_NAME}] 📊 Search response status: ${searchResponse.status} ${searchResponse.statusText}`);

                    if (!searchResponse.ok) {
                        const errorData = await searchResponse.json();
                        console.error(`[${BUSINESS_NAME}] ❌ Search Error (HTTP ${searchResponse.status}):`, errorData);
                        if (errorData.error) {
                            console.error(`[${BUSINESS_NAME}] 💡 Error message:`, errorData.error.message);
                            console.error(`[${BUSINESS_NAME}] 💡 Error status:`, errorData.error.status);
                        }
                        return;
                    }

                    const searchData = await searchResponse.json();
                    console.log(`[${BUSINESS_NAME}] 📦 Search data received:`, searchData);
                    
                    const placesCount = searchData.places?.length || 0;
                    console.log(`[${BUSINESS_NAME}] ✅ Nájdené ${placesCount} miest`);

                    if (placesCount === 0) {
                        console.error(`[${BUSINESS_NAME}] ⚠️ Žiadne miesta nenájdené`);
                        return;
                    }

                    const foundPlace = searchData.places[0];
                    console.log(`[${BUSINESS_NAME}] 📍 Našlo: ${foundPlace.displayName?.text || foundPlace.displayName}`);
                    console.log(`[${BUSINESS_NAME}] 🆔 Place ID: ${foundPlace.id}`);
                    
                    // Now fetch full details with rating
                    await fetchPlaceDetails(apiKey, foundPlace.id);

                } catch (error) {
                    console.error(`[${BUSINESS_NAME}] ❌ Search error: ${error.message}`);
                    console.error(`[${BUSINESS_NAME}] ❌ Stack trace:`, error.stack);
                }
            }

            async function fetchPlaceDetails(apiKey, placeId) {
                console.log(`[${BUSINESS_NAME}] 📡 Načítavam detaily miesta...`);

                try {
                    const url = `https://places.googleapis.com/v1/places/${placeId}`;
                    
                    console.log(`[${BUSINESS_NAME}] 📍 Details URL: ${url}`);
                    console.log(`[${BUSINESS_NAME}] 🔑 API Key: ${apiKey.substring(0, 20)}...`);
                    console.log(`[${BUSINESS_NAME}] 📤 Posielam details request...`);
                    
                    const response = await fetch(url, {
                        method: 'GET',
                        headers: {
                            'Content-Type': 'application/json',
                            'X-Goog-Api-Key': apiKey,
                            'X-Goog-FieldMask': 'id,displayName,formattedAddress,rating,userRatingCount,googleMapsUri'
                        }
                    });

                    console.log(`[${BUSINESS_NAME}] 📊 Details response status: ${response.status} ${response.statusText}`);

                    if (!response.ok) {
                        const errorData = await response.json();
                        console.error(`[${BUSINESS_NAME}] ❌ Details Error (HTTP ${response.status}):`, errorData);
                        if (errorData.error) {
                            console.error(`[${BUSINESS_NAME}] 💡 Error message:`, errorData.error.message);
                            console.error(`[${BUSINESS_NAME}] 💡 Error status:`, errorData.error.status);
                        }
                        return;
                    }

                    const data = await response.json();
                    console.log(`[${BUSINESS_NAME}] 📦 Details data received:`, data);
                    console.log(`[${BUSINESS_NAME}] ✅ Dáta úspešne načítané!`);
                    console.log(`[${BUSINESS_NAME}]    📍 Názov: ${data.displayName?.text || data.displayName}`);
                    console.log(`[${BUSINESS_NAME}]    ⭐ Hodnotenie: ${data.rating}`);
                    console.log(`[${BUSINESS_NAME}]    💬 Recenzie: ${data.userRatingCount}`);

                    updateGoogleData(data.rating, data.userRatingCount);
                    saveCache(data.rating, data.userRatingCount);

                } catch (error) {
                    console.error(`[${BUSINESS_NAME}] ❌ Details error: ${error.message}`);
                    console.error(`[${BUSINESS_NAME}] ❌ Stack trace:`, error.stack);
                }
            }

            async function fetchGoogleData() {
                console.log(`[${BUSINESS_NAME}] 🚀 Načítavam dáta z Google Places API...`);
                await searchAndFetchDetails(API_KEY, SEARCH_QUERY);
            }

            // Initialize: Check cache first, fetch if needed
            // Wait for DOM to be ready before accessing elements
            if (document.readyState === 'loading') {
                document.addEventListener('DOMContentLoaded', function() {
                    console.log(`[${BUSINESS_NAME}] 🎬 DOM pripravený`);
                    if (!checkCache()) {
                        fetchGoogleData();
                    }
                });
            } else {
                // DOM already loaded
                console.log(`[${BUSINESS_NAME}] 🎬 DOM už načítaný`);
                if (!checkCache()) {
                    fetchGoogleData();
                }
            }
        })();
    </script>
</body>
</html>
```

---

## Krok 3: Vyplň konfiguračné hodnoty

V hornej časti scriptu nájdeš sekciu `KONFIGURÁCIA`. Vyplň tieto hodnoty podľa informácií od užívateľa:

```javascript
// === KONFIGURÁCIA - VYPLŇ TIETO HODNOTY ===
const API_KEY = 'AIzaSyB5pR6jFr4M2qaYhd2SwH3IAFbIkTBWtjk'; // Od užívateľa
const SEARCH_QUERY = 'Autoservis Vladimír Hrabárik Sereď'; // Od užívateľa
const BUSINESS_NAME = 'Hrabarik'; // Krátky názov pre debug logy (DÔLEŽITÉ: musí byť unikátny)

// GPS súradnice
const GPS_LATITUDE = 48.2793593;  // Od užívateľa
const GPS_LONGITUDE = 17.7243325; // Od užívateľa
const GPS_RADIUS = 100; // Obvykle nechaj 100m
```

**⚠️ BUSINESS_NAME je KĽÚČOVÝ:**
- Používa sa v cache keys: `google_places_data_hrabarik` a `google_places_cache_time_hrabarik`
- Musí byť **unikátny pre každú stránku** na rovnakej doméne
- Príklady dobrých názvov: `'Hrabarik'`, `'AutoservisBA'`, `'PizzeriaMario'`
- **Nepoužívaj rovnaké názvy** pre rôzne stránky (inak budú zdieľať cache)

---

## Krok 4: Overenie

Po pridaní kódu:

1. **Skontroluj syntax** - žiadne chýbajúce `</script>` alebo `</body>` tagy
2. **Ulož súbor**
3. **Vráť užívateľovi upravený HTML**

---

## Ako funguje tento kód?

### Automatická aktualizácia (24h cache):
1. **Prvé načítanie** → volá Google Places API
2. **Ďalšie návštevy (24h)** → používa cachované dáta
3. **Po 24 hodinách** → znovu volá API a obnoví cache

### Force refresh:
Užívateľ môže vynútiť obnovenie pridaním `?refresh=1` na koniec URL:
```
https://example.com/index.html?refresh=1
```

### Debug logy v konzole:
```
[YourBusiness] 🚀 Script sa spúšťa...
[YourBusiness] 📋 Konfigurácia:
[YourBusiness]    🔑 API Key: AIzaSyA0KEY3tfh91t0i...
[YourBusiness]    🔍 Query: "Autoservis Vladimír Hrabárik Sereď"
[YourBusiness] 🎬 DOM pripravený
[YourBusiness] 🚀 Načítavam dáta z Google Places API...
[YourBusiness] 🔍 Vyhľadávam miesto...
[YourBusiness] 📍 Search URL: https://places.googleapis.com/v1/places:searchText
[YourBusiness] 📝 Query: "Autoservis Vladimír Hrabárik Sereď"
[YourBusiness] 📤 Posielam request...
[YourBusiness] 📊 Search response status: 200 OK
[YourBusiness] 📦 Search data received: {...}
[YourBusiness] ✅ Nájdené 1 miest
[YourBusiness] 📍 Našlo: Autoservis Vladimír Hrabárik Sereď
[YourBusiness] 🆔 Place ID: places/ChIJ...
[YourBusiness] 📡 Načítavam detaily miesta...
[YourBusiness] 📍 Details URL: https://places.googleapis.com/v1/places/...
[YourBusiness] 📤 Posielam details request...
[YourBusiness] 📊 Details response status: 200 OK
[YourBusiness] 📦 Details data received: {...}
[YourBusiness] ✅ Dáta úspešne načítané!
[YourBusiness]    📍 Názov: Autoservis Vladimír Hrabárik Sereď
[YourBusiness]    ⭐ Hodnotenie: 4.6
[YourBusiness]    💬 Recenzie: 131
[YourBusiness] 🔍 Hľadám elementy...
[YourBusiness] Rating element: ✅ Nájdený
[YourBusiness] Reviews element: ✅ Nájdený
[YourBusiness] ✅ Rating aktualizovaný na: 4.6
[YourBusiness] ✅ Reviews aktualizované na: 131
[YourBusiness] ✅ Google dáta aktualizované: 4.6★ 131 recenzií
[YourBusiness] 💾 Dáta uložené do cache (platné 24h)
```

### Network requesty:
V Chrome DevTools → Network tab → Filter "places.googleapis.com" uvidíš:
- `POST https://places.googleapis.com/v1/places:searchText` (search)
- `GET https://places.googleapis.com/v1/places/{placeId}` (details)

---

## API požiadavky na Google Cloud Console

API kľúč musí mať povolené:
1. **Places API (New)** - nie starý "Places API"
2. **HTTP referrer restrictions** - musí obsahovať doménu stránky

Príklad nastavenia v Google Cloud Console:
```
Application restrictions: HTTP referrers
Website restrictions:
  - https://example.com/*
  - https://*.example.com/*
  - http://example.com/*
  - http://*.example.com/*

API restrictions:
  ✅ Places API (New)
```

---

## Časté problémy a riešenia

### 1. HTTP 403 Permission Denied
**Problém:** API kľúč nemá povolenú doménu  
**Riešenie:** Pridaj doménu do HTTP referrer whitelist v Google Cloud Console

### 2. HTTP 400 Invalid Argument
**Problém:** Nesprávny formát requestu alebo Place ID  
**Riešenie:** Skontroluj GPS súradnice a vyhľadávací dotaz

### 3. Elementy nenájdené
**Problém:** `google-rating` alebo `google-reviews` ID neexistujú  
**Riešenie:** Pridaj ID do HTML elementov

### 4. Network requesty sa nezobrazujú
**Problém:** JavaScript sa nespustil alebo cache blokuje  
**Riešenie:** Otvor stránku s `?refresh=1` parametrom

### 5. CORS error
**Problém:** Google Places API blokuje kvôli CORS  
**Riešenie:** Toto by sa nemalo stať s Places API (New), skontroluj API kľúč

### 6. ⚠️ Dáta sa menia keď zmením inú stránku
**Problém:** Dve stránky na rovnakej doméne používajú rovnaký `BUSINESS_NAME`  
**Riešenie:** Každá stránka musí mať **unikátny** `BUSINESS_NAME`. Napríklad:
- Stránka 1: `const BUSINESS_NAME = 'Hrabarik';` → cache: `google_places_data_hrabarik`
- Stránka 2: `const BUSINESS_NAME = 'AutoservisBA';` → cache: `google_places_data_autoservisba`
- Test stránka: `const BUSINESS_NAME = 'Test';` → cache: `google_places_data_test`

---

## Príklad použitia

**Užívateľ pošle:**
- HTML súbor: `index.html`
- API kľúč: `AIzaSyB5pR6jFr4M2qaYhd2SwH3IAFbIkTBWtjk`
- Názov: `Autoservis Vladimír Hrabárik Sereď`
- GPS: `48.2793593, 17.7243325`

**Ty urobíš:**
1. Nájdeš hodnotenie a recenzie v HTML
2. Pridáš im `id="google-rating"` a `id="google-reviews"`
3. Pridáš JavaScript kód pred `</body>`
4. Vyplníš konfiguráciu v kóde:
   - `API_KEY` - od užívateľa
   - `SEARCH_QUERY` - od užívateľa
   - `BUSINESS_NAME` - vytvoríš **unikátny** identifikátor (napr. `'Hrabarik'`)
   - `GPS_LATITUDE` a `GPS_LONGITUDE` - od užívateľa
5. Vrátiš upravený HTML

**Výsledok:**
- Stránka automaticky načíta aktuálne hodnotenie a recenzie z Google
- Cache na 24h šetrí API kvótu
- Debug logy v konzole ukazujú všetko čo sa deje
- Hardcoded hodnoty zostávajú ako fallback

---

## Poznámky

- **Max 1 API volanie za 24h** vďaka cache systému
- **Podrobné logy** pre debugging
- **Error handling** pre všetky možné chyby
- **Force refresh** pomocou `?refresh=1` URL parametru
- **Fallback hodnoty** v HTML ak JavaScript zlyhá
- **Unikátne cache keys** pomocou `BUSINESS_NAME` zabraňujú konfliktom medzi stránkami na rovnakej doméne
- **localStorage** je izolovaný per doména (nie per stránka), preto je `BUSINESS_NAME` kritický pre správnu funkciu
