Files
vidok.com/templates_user/pages/salony-sprzedazy.php
2026-01-29 13:51:24 +01:00

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">&times;</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>