<div class="flex flex-col gap-6 adjusted-marg-x-sm py-6 bg-white">
    <h1 class="h6">Trouver un point de vente près de chez moi</h1>
    <div class="flex gap-4">
        <div class="relative flex-1" x-data="SearchPlace()" @click.away="showPredictions = false">
            <div class="flex gap-3">
                <div class="relative flex-1">
                    <div class="input-wrapper input-wrapper-select relative flex items-center bg-white h-12 overflow-hidden">
                        <input x-ref="input" type="text" x-model="query" @focus="showPredictions = predictions.length > 0" placeholder="Adresse, code postal..." class="form-select w-full h-full pl-4 pr-12 text-neutral-900 text-base placeholder-neutral-500" />

                        <button type="button" @click="getLocation()" aria-label="géolocalisez-vous" class="absolute right-3 top-1/2 -translate-y-1/2  btn  btn-light  btn-solid  btn-size-md btn-only-icon">
                            <svg class=" shrink-0" width="24" height="24" stroke-width="1.5" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
                                <path d="M8 10C9.10457 10 10 9.10457 10 8C10 6.89543 9.10457 6 8 6C6.89543 6 6 6.89543 6 8C6 9.10457 6.89543 10 8 10Z" stroke="currentColor" stroke-width="1.5" fill="none" />
                                <path d="M8 13C10.7614 13 13 10.7614 13 8C13 5.23858 10.7614 3 8 3C5.23858 3 3 5.23858 3 8C3 10.7614 5.23858 13 8 13Z" stroke="currentColor" stroke-width="1.5" fill="none" />
                                <path d="M8 0.5V3" stroke="currentColor" stroke-width="1.5" fill="none" />
                                <path d="M0.5 8H3" stroke="currentColor" stroke-width="1.5" fill="none" />
                                <path d="M8 15.5V13" stroke="currentColor" stroke-width="1.5" fill="none" />
                                <path d="M15.5 8H13" stroke="currentColor" stroke-width="1.5" fill="none" />

                            </svg>

                        </button>
                    </div>

                    <div x-cloak x-show="showPredictions" class="absolute z-10 top-full left-0 right-0 mt-2 bg-white shadow-md dropdown-content w-full overflow-auto max-h-screen-40" x-transition>
                        <template x-for="prediction in predictions" :key="prediction.place_id">
                            <button @click="selectPlace(prediction)" class="dropdown-item cursor-pointer p-2 truncate text-left w-full">
                                <span x-text="prediction.structured_formatting.main_text + ', ' + prediction.structured_formatting.secondary_text" class="text-neutral-900"></span>
                            </button>
                        </template>

                    </div>
                </div>

                <button type="button" class=" btn  btn-dark  btn-outline  btn-size-md">
                    OK

                </button>
            </div>
        </div>
    </div>
</div>

<script>
    function SearchPlace() {
        return {
            query: '',
            lastSelectedQuery: '',
            autocomplete: null,
            geocoder: null,
            predictions: [],
            showPredictions: false,
            selectedPlace: null,
            isLocating: false,
            async init() {
                try {
                    const {
                        AutocompleteService
                    } = await google.maps.importLibrary("places");
                    this.autocomplete = new AutocompleteService();
                    this.geocoder = new google.maps.Geocoder();
                    this.getLocation(false);
                    this.$watch('query', this.debounce(this.handleQueryChange, 300));
                } catch (error) {
                    console.error('Erreur chargement Google Places :', error);
                }
            },
            handleQueryChange(value) {
                if (value === this.lastSelectedQuery) {
                    console.log("lastSelectedQuery OK")
                    return;
                }
                console.log("value", value)
                if (value.length > 2) {
                    console.log("getPredictions OK")
                    this.getPredictions(value);
                } else {
                    console.log("clearPredictions OK")
                    this.clearPredictions();
                }
            },
            async getPredictions(input) {
                try {
                    const response = await this.autocomplete.getPlacePredictions({
                        input,
                        types: ['(regions)'],
                    });
                    this.predictions = response.predictions;
                    console.log(this.predictions.length > 0)
                    this.showPredictions = this.predictions.length > 0;
                } catch (error) {
                    console.error('Erreur predictions :', error);
                }
            },
            async selectPlace(prediction) {
                try {
                    const response = await this.geocoder.geocode({
                        placeId: prediction.place_id
                    });
                    const result = response.results[0];
                    const location = result.geometry.location;
                    const components = result.address_components;
                    let postalCode = components.find(c => c.types.includes('postal_code'))?.long_name;
                    const city = components.find(c => c.types.includes('locality'))?.long_name ||
                        components.find(c => c.types.includes('postal_town'))?.long_name ||
                        components.find(c => c.types.includes('administrative_area_level_3'))?.long_name ||
                        components.find(c => c.types.includes('administrative_area_level_2'))?.long_name;
                    const country = components.find(c => c.types.includes('country'))?.long_name;
                    // Fallback 1: Try to extract postal code from formatted address
                    if (!postalCode && result.formatted_address) {
                        const match = result.formatted_address.match(/\b\d{5}\b/);
                        if (match) postalCode = match[0];
                    }
                    const parts = [];
                    if (postalCode) parts.push(postalCode);
                    if (city) parts.push(city);
                    if (country) parts.push(country);
                    this.query = parts.join(', ');
                    this.lastSelectedQuery = this.query;
                    this.$store.locator.setMapCenter(location.lat(), location.lng(), 12);
                    this.clearPredictions();
                    this.$nextTick(() => {
                        this.$refs.input?.blur();
                    });
                } catch (error) {
                    console.error('Erreur géolocalisation :', error);
                }
            },
            getLocation(showError = true) {
                if (!navigator.geolocation) {
                    showError && alert('La géolocalisation n\'est pas supportée par ce navigateur.');
                    return;
                }
                this.isLocating = true;
                navigator.geolocation.getCurrentPosition(
                    (position) => {
                        const {
                            latitude,
                            longitude
                        } = position.coords || {};
                        if (!latitude || !longitude) {
                            console.warn('Coordonnées GPS vides.');
                            this.isLocating = false;
                            return;
                        }
                        Alpine.store('locator').setMapCenter(latitude, longitude, 12);
                        this.isLocating = false;
                    },
                    (error) => {
                        this.isLocating = false;
                        if (!showError) return;
                        const messages = {
                            1: "Veuillez autoriser la géolocalisation dans les paramètres du navigateur.",
                            2: "Votre position n'est pas disponible actuellement.",
                            3: "La demande de géolocalisation a expiré."
                        };
                        alert(messages[error.code] || "Erreur de géolocalisation inconnue.");
                    }, {
                        enableHighAccuracy: true,
                        timeout: 3000,
                        maximumAge: 30000
                    }
                );
            },
            clearPredictions() {
                this.showPredictions = false;
                this.predictions = [];
            },
            debounce(func, delay) {
                let timeout;
                return (...args) => {
                    clearTimeout(timeout);
                    timeout = setTimeout(() => func.apply(this, args), delay);
                };
            }
        }
    }
</script>
<div class="flex flex-col gap-6 adjusted-marg-x-sm py-6 bg-white">
    <h1 class="h6">Trouver un point de vente près de chez moi</h1>
    <div class="flex gap-4">
        <div class="relative flex-1" x-data="SearchPlace()" @click.away="showPredictions = false">
            <div class="flex gap-3">
                <div class="relative flex-1">
                    <div class="input-wrapper input-wrapper-select relative flex items-center bg-white h-12 overflow-hidden">
                        <input
                            x-ref="input"
                            type="text"
                            x-model="query"
                            @focus="showPredictions = predictions.length > 0"
                            placeholder="Adresse, code postal..."
                            class="form-select w-full h-full pl-4 pr-12 text-neutral-900 text-base placeholder-neutral-500"
                        />

                        {% render "@template-button" with {
                            label: "géolocalisez-vous",
                            color: "light",
                            type: "solid",
                            size: "md",
                            icon_type: 'only-icon',
                            icon: {
                                name:"heroicons--location"
                            },
                            custom_button_attrs:[
                                {
                                    'name': '@click',
                                    'value': 'getLocation()'
                                }
                            ],
                            button_class: 'absolute right-3 top-1/2 -translate-y-1/2'
                        } %}
                    </div>

                    <div
                        x-cloak
                        x-show="showPredictions"
                        class="absolute z-10 top-full left-0 right-0 mt-2 bg-white shadow-md dropdown-content w-full overflow-auto max-h-screen-40"
                        x-transition
                    >
                        <template x-for="prediction in predictions" :key="prediction.place_id">
                            <button
                                    @click="selectPlace(prediction)"
                                    class="dropdown-item cursor-pointer p-2 truncate text-left w-full"
                            >
                            <span
                                    x-text="prediction.structured_formatting.main_text + ', ' + prediction.structured_formatting.secondary_text"
                                    class="text-neutral-900"
                            ></span>
                            </button>
                        </template>

                    </div>
                </div>

                {% render "@template-button" with {
                    label: "OK",
                    color: "dark",
                    type: "outline",
                    size: "md",
                } %}
            </div>
        </div>
    </div>
</div>

<script>
	function SearchPlace() {
		return {
			query: '',
			lastSelectedQuery: '',
			autocomplete: null,
			geocoder: null,
			predictions: [],
			showPredictions: false,
			selectedPlace: null,
			isLocating: false,

            async init() {
				try {
					const { AutocompleteService } = await google.maps.importLibrary("places");
					this.autocomplete = new AutocompleteService();
					this.geocoder = new google.maps.Geocoder();

                    this.getLocation(false);

					this.$watch('query', this.debounce(this.handleQueryChange, 300));
				} catch (error) {
					console.error('Erreur chargement Google Places :', error);
				}
			},

			handleQueryChange(value) {
				if (value === this.lastSelectedQuery) {
                    console.log("lastSelectedQuery OK")
					return;
				}
                console.log("value", value)

				if (value.length > 2) {
                    console.log("getPredictions OK")
					this.getPredictions(value);
				} else {
                    console.log("clearPredictions OK")
					this.clearPredictions();
				}
			},

			async getPredictions(input) {
				try {
					const response = await this.autocomplete.getPlacePredictions({
						input,
                        types: ['(regions)'],
					});

					this.predictions = response.predictions;
                    console.log(this.predictions.length > 0)
					this.showPredictions = this.predictions.length > 0;
				} catch (error) {
					console.error('Erreur predictions :', error);
				}
			},

            async selectPlace(prediction) {
                try {
                    const response = await this.geocoder.geocode({ placeId: prediction.place_id });
                    const result = response.results[0];

                    const location = result.geometry.location;
                    const components = result.address_components;

                    let postalCode = components.find(c => c.types.includes('postal_code'))?.long_name;

                    const city = components.find(c => c.types.includes('locality'))?.long_name
                        || components.find(c => c.types.includes('postal_town'))?.long_name
                        || components.find(c => c.types.includes('administrative_area_level_3'))?.long_name
                        || components.find(c => c.types.includes('administrative_area_level_2'))?.long_name;

                    const country = components.find(c => c.types.includes('country'))?.long_name;

                    // Fallback 1: Try to extract postal code from formatted address
                    if (!postalCode && result.formatted_address) {
                        const match = result.formatted_address.match(/\b\d{5}\b/);
                        if (match) postalCode = match[0];
                    }

                    const parts = [];
                    if (postalCode) parts.push(postalCode);
                    if (city) parts.push(city);
                    if (country) parts.push(country);

                    this.query = parts.join(', ');
                    this.lastSelectedQuery = this.query;

                    this.$store.locator.setMapCenter(location.lat(), location.lng(), 12);
                    this.clearPredictions();

                    this.$nextTick(() => {
                        this.$refs.input?.blur();
                    });
                } catch (error) {
                    console.error('Erreur géolocalisation :', error);
                }
            },

            getLocation(showError = true) {
                if (!navigator.geolocation) {
                    showError && alert('La géolocalisation n\'est pas supportée par ce navigateur.');
                    return;
                }

                this.isLocating = true;

                navigator.geolocation.getCurrentPosition(
                    (position) => {
                        const { latitude, longitude } = position.coords || {};
                        if (!latitude || !longitude) {
                            console.warn('Coordonnées GPS vides.');
                            this.isLocating = false;
                            return;
                        }

                        Alpine.store('locator').setMapCenter(latitude, longitude, 12);
                        this.isLocating = false;
                    },
                    (error) => {
                        this.isLocating = false;
                        if (!showError) return;

                        const messages = {
                            1: "Veuillez autoriser la géolocalisation dans les paramètres du navigateur.",
                            2: "Votre position n'est pas disponible actuellement.",
                            3: "La demande de géolocalisation a expiré."
                        };

                        alert(messages[error.code] || "Erreur de géolocalisation inconnue.");
                    },
                    {
                        enableHighAccuracy: true,
                        timeout: 3000,
                        maximumAge: 30000
                    }
                );
            },

            clearPredictions() {
				this.showPredictions = false;
				this.predictions = [];
			},

			debounce(func, delay) {
				let timeout;
				return (...args) => {
					clearTimeout(timeout);
					timeout = setTimeout(() => func.apply(this, args), delay);
				};
			}
		}
	}
</script>
{
  "title": "Trouver un point de vente près de chez moi",
  "searchPlaceholder": "Adresse, code postal",
  "buttonLabel": "Ok",
  "detailsLabel": "Détails",
  "openLabel": "Ouvert",
  "closedLabel": "Fermé",
  "untilLabel": "jusqu'à",
  "noResults": "Aucun résultat trouvé"
}

No notes defined.