Save
This commit is contained in:
341
templates_user/pages/salony-sprzedazy.php
Normal file
341
templates_user/pages/salony-sprzedazy.php
Normal file
@@ -0,0 +1,341 @@
|
||||
<?php
|
||||
$google_map_api = 'AIzaSyD-1SOVhJXr6HREtfmMILvlmV-hml3nxUg';
|
||||
?>
|
||||
|
||||
<div class="main-page" id="places-contact-maps">
|
||||
<section class="box-1" id="box-map-showrooms" style="position: relative; display: flex; height: 700px;">
|
||||
<div id="showrooms-sidebar">
|
||||
<div id="results-list">
|
||||
<!-- <p>Wpisz miasto</p> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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"><p></p></div>
|
||||
<div class="info-products">
|
||||
<p>Dostępne produkty</p>
|
||||
<img src="" alt="">
|
||||
</div>
|
||||
<div class="info-contact"><p></p></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
|
||||
*/
|
||||
fetch('/api/kontakt-mapa')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
showrooms = data.data;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching showroom data:', error);
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
// 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() {
|
||||
console.log(showrooms);
|
||||
|
||||
markers = showrooms.map((item) => {
|
||||
console.log('item: ', 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);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) => 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 = 'SALON SPRZEDAŻY';
|
||||
|
||||
console.log('item: ', item);
|
||||
|
||||
const $el = `
|
||||
<div class="sidebar-item" data-lat="${lat}" data-lng="${lng}">
|
||||
<div class="sidebar-item--wrapper">
|
||||
<div class="item-type"><span>${itemType}<\/span><\/div>
|
||||
<div class="item-working-hours">
|
||||
<p>
|
||||
${item.data_popup.time}
|
||||
<\/p>
|
||||
<\/div>
|
||||
<div class="item-location">
|
||||
<p>
|
||||
${item.data.text}
|
||||
<\/p>
|
||||
<\/div>
|
||||
<div class="item-contact">
|
||||
<ul>
|
||||
${renderContacts(item)}
|
||||
<\/ul>
|
||||
<\/div>
|
||||
<\/div>
|
||||
<\/div>
|
||||
`;
|
||||
|
||||
return $el;
|
||||
}
|
||||
|
||||
function renderContacts(item) {
|
||||
if (item.contact) {
|
||||
let html = '';
|
||||
|
||||
if (Array.isArray(item.contact.phone)) {
|
||||
item.contact.phone.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.contact.email)) {
|
||||
item.contact.email.forEach(email => {
|
||||
html += `
|
||||
<li>
|
||||
<img src="/upload/filemanager/icon/envelope.svg" alt="">
|
||||
<a href="mailto:${email}">${email}<\/a>
|
||||
<\/li>
|
||||
`;
|
||||
});
|
||||
}
|
||||
|
||||
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');
|
||||
$popup.find('.info-name p').html(item.data_popup.text);
|
||||
$popup.find('.info-time p').html(item.data_popup.time);
|
||||
$popup.find('.info-contact p').html(item.data_popup.contact);
|
||||
$popup.find('.info-products img').attr('src', item.data_popup.products);
|
||||
// $popup.fadeIn();
|
||||
$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() {
|
||||
if (typeof google !== 'undefined') {
|
||||
initMap();
|
||||
}
|
||||
|
||||
$(document).on('click', '.close-popup', function() {
|
||||
// $('#showroom-popup').fadeOut();
|
||||
$('#showroom-popup').removeClass('active');
|
||||
});
|
||||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
$('body').on('click', '.box-6 .box-info .box-info-right', function(e){
|
||||
e.preventDefault()
|
||||
|
||||
$(this).toggleClass('active')
|
||||
$('.box-6 .c-row-2').slideToggle()
|
||||
})
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user