416 lines
15 KiB
PHP
416 lines
15 KiB
PHP
<?php
|
|
$google_map_api = 'AIzaSyD-1SOVhJXr6HREtfmMILvlmV-hml3nxUg';
|
|
?>
|
|
|
|
<div class="main-page" id="places-contact-maps">
|
|
<div class="container">
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="breadcrumbs">
|
|
<a href="/">Strona główna</a>
|
|
<span class="sep"><img src="/images/breadcrumbs-sep.svg"></span>
|
|
<a href="/kontakt">Kontakt</a>
|
|
<span class="sep"><img src="/images/breadcrumbs-sep.svg"></span>
|
|
<span class="last">Salony sprzedaży</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<section class="box-1" id="box-map-showrooms">
|
|
<div id="showrooms-sidebar">
|
|
<div id="showrooms-sidebar--header">
|
|
<form id="search-showrooms-form">
|
|
<input type="text" id="place" placeholder="wpisz miejscowość" />
|
|
<button type="submit">FILTRUJ</button>
|
|
</form>
|
|
</div>
|
|
<div id="showrooms-sidebar--body">
|
|
<div id="results-list"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="showrooms-data-box">
|
|
<div id="map" style="flex-grow: 1; height: 100%;"></div>
|
|
|
|
<div id="showroom-popup" class="showroom-card--popup">
|
|
<div class="showroom-card--popup-wrapper">
|
|
<div class="popup--head">
|
|
<p class="text">PUNKT SPRZEDAŻY</p>
|
|
<p>VIDOK Okna i Drzwi</p>
|
|
<span class="close-popup">×</span>
|
|
</div>
|
|
<div class="popup--body">
|
|
<div class="popup--body-info">
|
|
<div class="info-name"><p></p></div>
|
|
<div class="info-time">
|
|
<strong>Godziny otwarcia</strong><br/>
|
|
<div class="info-time--data"></div>
|
|
</div>
|
|
<div class="info-products">
|
|
<p>Dostępne produkty</p>
|
|
<ul>
|
|
|
|
</ul>
|
|
</div>
|
|
<div class="info-contact"></div>
|
|
</div>
|
|
<div class="popup--body-footer">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<script src="https://maps.googleapis.com/maps/api/js?key=<?php echo $google_map_api; ?>&libraries=places&callback=initMap" defer></script>
|
|
<script src="https://unpkg.com/@googlemaps/markerclusterer/dist/index.min.js"></script>
|
|
|
|
<script class="footer" type="text/javascript">
|
|
let showrooms = [];
|
|
const MAX_DISTANCE_KM = 100; // Promień wyszukiwania w kilometrach
|
|
let map, markerCluster;
|
|
let markers = [];
|
|
const mapPointIcon = "https://maps.google.com/mapfiles/ms/icons/yellow-dot.png";
|
|
|
|
/**
|
|
* Fetch showroom data from API
|
|
*/
|
|
const showroomsPromise = fetch('/api/kontakt-mapa')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
showrooms = (data && data.data) ? data.data : [];
|
|
return showrooms;
|
|
})
|
|
.catch(error => {
|
|
console.error('Error fetching showroom data:', error);
|
|
showrooms = [];
|
|
return showrooms;
|
|
});
|
|
|
|
|
|
/**
|
|
* Inicjalizacja mapy Google
|
|
*/
|
|
function initMap() {
|
|
|
|
const mapOptions = {
|
|
zoom: 6.62,
|
|
center: { lat: 52.068, lng: 19.479 },
|
|
mapTypeControl: false,
|
|
styles: getMapStyles() // Pobieranie stylów z osobnej funkcji
|
|
};
|
|
|
|
map = new google.maps.Map(document.getElementById("map"), mapOptions);
|
|
|
|
showroomsPromise.then(() => {
|
|
// Utworzenie markerów dla wszystkich salonów
|
|
renderMarkers();
|
|
|
|
// Inicjalizacja klastrów (grupowanie markerów)
|
|
if (typeof markerClusterer !== 'undefined') {
|
|
markerCluster = new markerClusterer.MarkerClusterer({ map, markers });
|
|
}
|
|
|
|
// Inicjalizacja wyszukiwarki
|
|
initSearchLogic();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Renderowanie markerów na mapie
|
|
*/
|
|
function renderMarkers() {
|
|
if (markerCluster) markerCluster.clearMarkers();
|
|
markers.forEach(m => m.setMap(null));
|
|
markers = [];
|
|
|
|
markers = showrooms.map((item) => {
|
|
const marker = new google.maps.Marker({
|
|
position: { lat: parseFloat(item.position.lat), lng: parseFloat(item.position.lng) },
|
|
title: item.city,
|
|
icon: mapPointIcon
|
|
});
|
|
|
|
marker.addListener("click", () => openShowroomPopup(item));
|
|
return marker;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Obsługa wyszukiwania i filtrowania
|
|
*/
|
|
function initSearchLogic() {
|
|
const input = document.getElementById("place");
|
|
if (!input) return;
|
|
|
|
const autocomplete = new google.maps.places.Autocomplete(input);
|
|
|
|
$('#search-showrooms-form').on('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
const place = autocomplete.getPlace();
|
|
|
|
if (place && place.geometry) {
|
|
handleLocationSelection(place.geometry.location);
|
|
} else {
|
|
const address = $(input).val();
|
|
if (address.length > 0) {
|
|
geocodeAddress(address);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Sprawdzanie URL "location" po ładowaniu strony
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
const locationParam = urlParams.get('location');
|
|
|
|
if (locationParam) {
|
|
// wypełniamy pole URL
|
|
input.value = locationParam;
|
|
geocodeAddress(locationParam);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Geokodowanie tekstu na współrzędne
|
|
*/
|
|
function geocodeAddress(address) {
|
|
const geocoder = new google.maps.Geocoder();
|
|
geocoder.geocode({ address: address }, (results, status) => {
|
|
if (status === "OK") {
|
|
handleLocationSelection(results[0].geometry.location);
|
|
} else {
|
|
console.error("Geocode failed: " + status);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Przetwarzanie wybranej lokalizacji
|
|
*/
|
|
function handleLocationSelection(location) {
|
|
map.setCenter(location);
|
|
map.setZoom(11);
|
|
|
|
updateSidebarList(location);
|
|
scrollToMap();
|
|
}
|
|
|
|
/**
|
|
* Aktualizacja listy salonów w panelu bocznym z uwzględnieniem promienia
|
|
*/
|
|
function updateSidebarList(location) {
|
|
const searchLat = location.lat();
|
|
const searchLng = location.lng();
|
|
const $resultsContainer = $('#results-list');
|
|
|
|
// 1. Czyszczenie kontenera
|
|
$resultsContainer.empty();
|
|
$('#results-list').parent().addClass('has-results');
|
|
|
|
// 2. Filtrowanie i obliczanie dystansu
|
|
let filtered = showrooms
|
|
.map(item => ({
|
|
...item,
|
|
distance: calculateDistance(searchLat, searchLng, item.position.lat, item.position.lng)
|
|
}))
|
|
.filter(item => item.distance <= MAX_DISTANCE_KM)
|
|
.sort((a, b) => {
|
|
const aIsSales = a.salon_type === 'sales' ? 0 : 1;
|
|
const bIsSales = b.salon_type === 'sales' ? 0 : 1;
|
|
|
|
if (aIsSales !== bIsSales) return aIsSales - bIsSales;
|
|
|
|
return a.distance - b.distance;
|
|
});
|
|
|
|
// 3. Sprawdzenie wyników
|
|
if (filtered.length === 0) {
|
|
$resultsContainer.append(`<div style="padding:20px; text-align:center;">Nie znaleziono salonów w promieniu ${MAX_DISTANCE_KM} km.</div>`);
|
|
return;
|
|
}
|
|
|
|
// 4. Dodawanie elementów za pomocą .append()
|
|
filtered.forEach(item => {
|
|
const $itemElement = sidebarItem(item);
|
|
$resultsContainer.append($itemElement);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Generuje bezpieczny i poprawny kod HTML dla pojedynczego elementu listy
|
|
*/
|
|
function sidebarItem(item) {
|
|
const lat = item.position.lat;
|
|
const lng = item.position.lng;
|
|
const distance = item.distance.toFixed(1);
|
|
|
|
const itemType = item.salon_type;
|
|
let itemTypeText = '';
|
|
|
|
switch (itemType) {
|
|
case 'sales':
|
|
itemTypeText = 'SALON SPRZEDAŻY';
|
|
break;
|
|
case 'partner':
|
|
itemTypeText = 'SALON PARTNERSKI';
|
|
break;
|
|
}
|
|
|
|
const $el = $(`
|
|
<div class="sidebar-item" data-lat="${lat}" data-lng="${lng}">
|
|
<div class="sidebar-item--wrapper">
|
|
<div class="item-type ${itemType}"><span>${itemTypeText}<\/span><\/div>
|
|
<div class="item-working-hours">
|
|
<strong>Godziny otwarcia:<\/strong><br/>
|
|
${item.opening_hours}
|
|
<\/div>
|
|
<div class="item-location">
|
|
<strong>${item.salon_name}<\/strong><br/>
|
|
${item.address}
|
|
<\/div>
|
|
<div class="item-contact">
|
|
${renderContacts(item.contact)}
|
|
<\/div>
|
|
<\/div>
|
|
<\/div>
|
|
`);
|
|
|
|
$el.on('click', () => openShowroomPopup(item));
|
|
|
|
return $el;
|
|
}
|
|
|
|
function renderContacts(item) {
|
|
if (item) {
|
|
let html = '<ul>';
|
|
|
|
if (Array.isArray(item.phones)) {
|
|
item.phones.forEach(phone => {
|
|
html += `
|
|
<li>
|
|
<img src="/upload/filemanager/icon/iphone.svg" alt="">
|
|
<a href="tel:${phone.replace(/\s+/g, '')}">${phone}<\/a>
|
|
<\/li>
|
|
`;
|
|
});
|
|
}
|
|
|
|
if (Array.isArray(item.emails)) {
|
|
item.emails.forEach(email => {
|
|
html += `
|
|
<li>
|
|
<img src="/upload/filemanager/icon/envelope.svg" alt="">
|
|
<a href="mailto:${email}">${email}<\/a>
|
|
<\/li>
|
|
`;
|
|
});
|
|
}
|
|
|
|
html += '</ul>';
|
|
return html;
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* Globalna obsługa kliknięcia w elementy listy (Event Delegation)
|
|
*/
|
|
$(document).on('click', '.sidebar-item', function() {
|
|
// Pobieramy współrzędne z atrybutów data-
|
|
const lat = $(this).data('lat');
|
|
const lng = $(this).data('lng');
|
|
|
|
$(this).addClass('active').siblings().removeClass('active');
|
|
|
|
if (lat && lng) {
|
|
focusOnMarker(lat, lng);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Wyświetlanie szczegółów salonu w popupie
|
|
*/
|
|
function openShowroomPopup(item) {
|
|
const $popup = $('#showroom-popup');
|
|
|
|
let itemType = item.salon_type;
|
|
let itemTypeText = '';
|
|
switch (itemType) {
|
|
case 'sales':
|
|
itemTypeText = 'SALON SPRZEDAŻY';
|
|
break;
|
|
case 'partner':
|
|
itemTypeText = 'SALON PARTNERSKI';
|
|
break;
|
|
}
|
|
|
|
console.log('item: ', item);
|
|
$popup.find('.popup--head').attr('data-type', itemType);
|
|
$popup.find('.popup--head p.text').html(itemTypeText);
|
|
$popup.find('.info-name').html(`<strong>${item.salon_name}<\/strong><br/>${item.address}`);
|
|
$popup.find('.info-time .info-time--data').html(item.opening_hours);
|
|
$popup.find('.info-contact').html(`
|
|
${renderContacts(item.contact)}
|
|
${item.button.url ? `<a href="${item.button.url}" class="showroom-contact-btn">${item.button.label || 'SKONTAKTUJ SIĘ Z NAMI'}</a>` : ''}
|
|
`);
|
|
$popup.find('.info-products ul').html(
|
|
item.products.map(product => `<li>${product.name}<img src="/${product.icon}"></li>`)
|
|
);
|
|
$popup.find('.popup--body-footer').empty().html(`
|
|
<div class="popup--body-footer--baner">
|
|
<img src="${item.banner_image}">
|
|
<\/div>
|
|
`);
|
|
$popup.addClass('active');
|
|
}
|
|
|
|
/**
|
|
* Funkcje pomocnicze (Nawigacja i Obliczenia)
|
|
*/
|
|
function focusOnMarker(lat, lng) {
|
|
map.setCenter({lat: parseFloat(lat), lng: parseFloat(lng)});
|
|
map.setZoom(14);
|
|
}
|
|
|
|
function scrollToMap() {
|
|
$('html, body').animate({
|
|
scrollTop: $("#box-map-showrooms").offset().top - 120
|
|
}, 500);
|
|
}
|
|
|
|
function calculateDistance(lat1, lon1, lat2, lon2) {
|
|
const R = 6371;
|
|
const dLat = (lat2 - lat1) * Math.PI / 180;
|
|
const dLon = (lon2 - lon1) * Math.PI / 180;
|
|
const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
|
|
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * Math.sin(dLon/2) * Math.sin(dLon/2);
|
|
return R * (2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)));
|
|
}
|
|
|
|
/**
|
|
* Style mapy (Greyscale)
|
|
*/
|
|
function getMapStyles() {
|
|
return [{"featureType":"all","elementType":"all","stylers":[{"saturation":"-100"}]},{"featureType":"administrative","elementType":"all","stylers":[{"saturation":"-100"}]},{"featureType":"landscape","elementType":"all","stylers":[{"saturation":"-100"}]},{"featureType":"landscape.man_made","elementType":"all","stylers":[{"visibility":"on"},{"saturation":"-100"},{"gamma":"1"}]},{"featureType":"poi","elementType":"all","stylers":[{"saturation":"-100"},{"visibility":"simplified"}]},{"featureType":"poi","elementType":"geometry.fill","stylers":[{"saturation":"-100"}]},{"featureType":"poi","elementType":"labels","stylers":[{"visibility":"simplified"}]},{"featureType":"poi","elementType":"labels.text.fill","stylers":[{"saturation":"-100"},{"weight":"6.61"},{"lightness":"0"},{"gamma":"1.5"}]},{"featureType":"poi","elementType":"labels.icon","stylers":[{"saturation":"-100"},{"gamma":"1.5"},{"weight":"0.01"}]},{"featureType":"road","elementType":"labels.icon","stylers":[{"saturation":"-100"}]},{"featureType":"road.highway","elementType":"all","stylers":[{"saturation":"-100"}]},{"featureType":"transit","elementType":"all","stylers":[{"saturation":"-100"}]},{"featureType":"transit","elementType":"labels.text","stylers":[{"saturation":"-100"}]},{"featureType":"transit","elementType":"labels.icon","stylers":[{"saturation":"-100"}]},{"featureType":"water","elementType":"all","stylers":[{"saturation":"-100"}]}];
|
|
}
|
|
|
|
/**
|
|
* Uruchomienie po załadowaniu DOM
|
|
*/
|
|
$(document).ready(function() {
|
|
$(document).on('click', '.close-popup', function() {
|
|
// $('#showroom-popup').fadeOut();
|
|
$('#showroom-popup').removeClass('active');
|
|
});
|
|
|
|
$('body').on('click', '.box-6 .box-info .box-info-right', function(e){
|
|
e.preventDefault()
|
|
|
|
$(this).toggleClass('active')
|
|
$('.box-6 .c-row-2').slideToggle()
|
|
})
|
|
});
|
|
</script>
|