Przegląd Widget'a Listy
Główne zalety:
- Minimalistyczny design: Zajmuje mało miejsca, doskonały dla sidebara
- Brak zależności: Nie wymaga dodatkowych bibliotek jak Leaflet
- Mobile-first: Zoptymalizowany dla urządzeń mobilnych
- Sortowanie automatyczne: Sklepy sortowane według odległości
- Akcje użytkownika: Kopiowanie adresu, nawigacja, kontakt
Funkcjonalności Widget'a
Sortowanie wg Odległości
Automatyczne sortowanie sklepów od najbliższych do najdalszych z wyświetlaniem precyzyjnej odległości w km.
Pełne Informacje
Nazwa sklepu, pełny adres, numer telefonu, godziny otwarcia oraz dostępne zakresy świadczeń NFZ.
Interaktywne Akcje
Jednym kliknięciem: kopiowanie adresu, otwieranie nawigacji GPS, dzwonienie lub wysyłanie email.
Responsywny Design
Automatyczne dostosowanie układu do rozmiaru ekranu z zachowaniem czytelności na wszystkich urządzeniach.
Filtrowanie NFZ
Możliwość filtrowania według konkretnego zakresu świadczeń: aparaty słuchowe, ortopedia, środki pomocnicze.
Motywy Kolorystyczne
4 gotowe motywy dostosowane do różnych stylów stron: Default, Medical, Light i Dark.
Demonstracja na Żywo
Przetestuj widget listy w działaniu. Wybierz motyw kolorystyczny i zobacz jak prezentuje się lista sklepów medycznych.
Wybierz motyw:
Default
Standardowy motyw eZWM
Medical
Motyw medyczny
Light
Jasny motyw
Dark
Ciemny motyw
Przewodnik Integracji
Załaduj eZWM Shops Loader
W przeciwieństwie do widget'a mapy, lista sklepów nie wymaga biblioteki Leaflet. Wystarczy jeden skrypt:
<-- Dodaj przed zamknięciem </body> --> <script src="https://ecommerce.ezwm.pl/widgets/ezwm-shops-loader.js"></script>
Przygotuj Kontener HTML
Utwórz element HTML, w którym zostanie wyrenderowana lista sklepów:
<div id="medical-shops-list" style="width: 100%; height: 400px; overflow-y: auto;">
<!-- Loader podczas ładowania -->
<div class="shops-loading" style="display: flex; align-items: center; justify-content: center; height: 100%; background: #f8f9fa;">
<i class="fas fa-spinner fa-spin fa-2x text-primary"></i>
<span class="ms-2">Ładowanie sklepów...</span>
</div>
</div>
Inicjalizuj Widget
Wywołaj metodę ładowania listy z parametrami konfiguracyjnymi:
<script>
// Podstawowa inicjalizacja
EZWMShopsLoader.loadShopsList('medical-shops-list', {
latitude: 50.0647, // Kraków
longitude: 19.9449,
theme: 'default',
promieniWyszukiwania: 20, // km
limitSklepow: 10
});
// Zaawansowana inicjalizacja z geolokalizacją
document.addEventListener('DOMContentLoaded', function() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
function(position) {
// Sukces - użyj lokalizacji użytkownika
EZWMShopsLoader.loadShopsList('medical-shops-list', {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
theme: 'medical',
zakresSwiadczenia: 'PO', // tylko produkty ortopedyczne
promieniWyszukiwania: 30,
limitSklepow: 8
});
},
function(error) {
// Fallback dla błędów geolokalizacji
console.warn('Geolocation error:', error);
EZWMShopsLoader.loadShopsList('medical-shops-list', {
latitude: 52.2297, // Warszawa jako backup
longitude: 21.0122,
theme: 'light',
promieniWyszukiwania: 25,
limitSklepow: 12
});
},
{ timeout: 5000, enableHighAccuracy: false }
);
} else {
// Brak obsługi geolokalizacji
EZWMShopsLoader.loadShopsList('medical-shops-list', {
latitude: 50.0647,
longitude: 19.9449
});
}
});
</script>
Opcje Konfiguracji
| Parametr | Typ | Domyślnie | Opis | Przykład |
|---|---|---|---|---|
latitude |
number | wymagane | Szerokość geograficzna punktu wyszukiwania (-90 do 90) | 50.0647 |
longitude |
number | wymagane | Długość geograficzna punktu wyszukiwania (-180 do 180) | 19.9449 |
theme |
string | 'default' |
Motyw kolorystyczny: 'default', 'medical', 'light', 'dark' | 'medical' |
promieniWyszukiwania |
number | 20 |
Promień wyszukiwania w kilometrach (1-100) | 30 |
limitSklepow |
number | 10 |
Maksymalna liczba sklepów do wyświetlenia (1-50) | 15 |
zakresSwiadczenia |
string|null | null |
Filtr zakresu NFZ: 'AS', 'PO', 'SP', 'SO' lub null (wszystkie) | 'AS' |
showDistance |
boolean | true |
Czy wyświetlać odległość do sklepu | false |
showPhone |
boolean | true |
Czy wyświetlać numer telefonu | false |
enableActions |
boolean | true |
Czy włączyć akcje użytkownika (nawigacja, kopiowanie) | false |
Zakresy Świadczeń NFZ
Platforma obsługuje wszystkie główne zakresy świadczeń medycznych refundowanych przez NFZ. Każdy sklep może oferować jeden lub więcej zakresów.
AS Aparaty Słuchowe
Przykładowe produkty:
- Aparaty słuchowe zauszne
- Aparaty słuchowe douszne
- Aparaty słuchowe wszczepiane
- Akcesoria do aparatów słuchowych
PO Przedmioty Ortopedyczne
Przykładowe produkty:
- Buty ortopedyczne
- Wkładki ortopedyczne
- Ortezy kończyn
- Protezy kończyn
SP Środki Pomocnicze
Przykładowe produkty:
- Wózki inwalidzkie
- Kule i laski
- Chodziki i balkoniki
- Sprzęt rehabilitacyjny
SO Szkła Okularowe
Przykładowe produkty:
- Szkła okularowe korekcyjne
- Szkła progresywne
- Szkła specjalistyczne
- Oprawy okularowe
zakresSwiadczenia jako null
aby wyświetlić wszystkie sklepy niezależnie od oferowanych zakresów.
Przykłady Zastosowań
Sidebar na Stronie Medycznej
Kompaktowa lista sklepów w sidebarze strony internetowej placówki medycznej lub apteki. Pacjenci mogą szybko znaleźć najbliższe punkty sprzedaży wyrobów medycznych.
Dashboard Administratora
Panel administracyjny systemu CRM z szybkim podglądem partnerów handlowych w okolicy. Możliwość filtrowania według zakresu współpracy.
Aplikacja Mobilna
Lista sklepów w aplikacji mobilnej dla pacjentów. Optymalizowana dla małych ekranów z intuicyjnymi akcjami dotyk.
Uzupełnienie Widget'a Mapy
Lista szczegółów jako uzupełnienie interaktywnej mapy. Użytkownicy mogą przeglądać informacje o sklepach w wygodnej formie tekstowej.
Wersja do Druku
Lista sklepów przygotowana do wydruku dla pacjentów. Czytelny format z wszystkimi niezbędnymi informacjami kontaktowymi.
Newsletter i Email
Osadzenie listy sklepów in newsletterach lub automatycznych emailach dla pacjentów. Możliwość personalizacji według lokalizacji odbiorcy.
Przykłady Zaawansowanej Integracji
Przykład 1: Widget z dynamicznym filtrowaniem
<div class="filters-container mb-3">
<select id="scope-filter" class="form-select">
<option value="">Wszystkie zakresy NFZ</option>
<option value="AS">Aparaty słuchowe</option>
<option value="PO">Produkty ortopedyczne</option>
<option value="SP">Środki pomocnicze</option>
<option value="SO">Szkła okularowe</option>
</select>
<input type="range" id="radius-slider" min="5" max="100" value="20" class="form-range">
<span id="radius-display">20 km</span>
</div>
<div id="dynamic-shops-list" style="height: 500px;"></div>
<script>
const baseConfig = {
latitude: 50.0647,
longitude: 19.9449,
theme: 'medical'
};
let currentConfig = { ...baseConfig };
// Funkcja odświeżania listy
function refreshShopsList() {
EZWMShopsLoader.loadShopsList('dynamic-shops-list', currentConfig);
}
// Obsługa zmiany zakresu NFZ
document.getElementById('scope-filter').addEventListener('change', function(e) {
currentConfig.zakresSwiadczenia = e.target.value || null;
refreshShopsList();
});
// Obsługa zmiany promienia
document.getElementById('radius-slider').addEventListener('input', function(e) {
const radius = parseInt(e.target.value);
currentConfig.promieniWyszukiwania = radius;
document.getElementById('radius-display').textContent = radius + ' km';
// Debounce dla lepszej wydajności
clearTimeout(window.radiusTimeout);
window.radiusTimeout = setTimeout(refreshShopsList, 500);
});
// Inicjalizacja
refreshShopsList();
</script>
Przykład 2: Synchronizacja z widget'em mapy
<div class="row">
<div class="col-md-8">
<div id="synchronized-map" style="height: 400px;"></div>
</div>
<div class="col-md-4">
<div id="synchronized-list" style="height: 400px;"></div>
</div>
</div>
<script>
const syncConfig = {
latitude: 50.0647,
longitude: 19.9449,
theme: 'medical',
promieniWyszukiwania: 25,
limitSklepow: 15
};
// Załaduj oba widgety z tą samą konfiguracją
Promise.all([
EZWMMapLoader.loadMap('synchronized-map', syncConfig),
EZWMShopsLoader.loadShopsList('synchronized-list', syncConfig)
]).then(() => {
console.log('Oba widgety zostały załadowane i zsynchronizowane');
});
// Funkcja do aktualizacji obu widgetów jednocześnie
function updateBothWidgets(newConfig) {
const finalConfig = { ...syncConfig, ...newConfig };
EZWMMapLoader.loadMap('synchronized-map', finalConfig);
EZWMShopsLoader.loadShopsList('synchronized-list', finalConfig);
}
// Przykład użycia - zmiana lokalizacji dla obu widgetów
function changeLocation(lat, lng) {
updateBothWidgets({
latitude: lat,
longitude: lng
});
}
</script>
Przykład 3: Widget z cache'owaniem i optymalizacją
<div id="cached-shops-list" style="height: 400px;"></div>
<button id="refresh-btn" class="btn btn-primary mt-2">Odśwież dane</button>
<script>
class ShopsListManager {
constructor(containerId) {
this.containerId = containerId;
this.cache = new Map();
this.cacheTimeout = 5 * 60 * 1000; // 5 minut
}
generateCacheKey(config) {
return JSON.stringify({
lat: config.latitude.toFixed(4),
lng: config.longitude.toFixed(4),
radius: config.promieniWyszukiwania,
scope: config.zakresSwiadczenia,
limit: config.limitSklepow
});
}
async loadShops(config) {
const cacheKey = this.generateCacheKey(config);
const cached = this.cache.get(cacheKey);
// Sprawdź cache
if (cached && (Date.now() - cached.timestamp) < this.cacheTimeout) {
console.log('Używam danych z cache');
return cached.success;
}
// Załaduj świeże dane
console.log('Ładuję świeże dane...');
const success = await EZWMShopsLoader.loadShopsList(this.containerId, config);
// Zapisz w cache
this.cache.set(cacheKey, {
success: success,
timestamp: Date.now()
});
return success;
}
clearCache() {
this.cache.clear();
console.log('Cache wyczyszczony');
}
}
// Użycie
const shopsManager = new ShopsListManager('cached-shops-list');
const config = {
latitude: 50.0647,
longitude: 19.9449,
theme: 'default',
promieniWyszukiwania: 20,
limitSklepow: 12
};
// Załaduj dane (z cache lub świeże)
shopsManager.loadShops(config);
// Przycisk odświeżania
document.getElementById('refresh-btn').addEventListener('click', function() {
shopsManager.clearCache();
shopsManager.loadShops(config);
});
</script>