Dodanie title 2/2, Poprawki w ładowaniu map Google, poprwka w linach modal dla title

This commit is contained in:
dm
2025-11-23 07:11:17 +01:00
parent e4f47a06a0
commit 65d16575f2
25 changed files with 259 additions and 153 deletions

View File

@@ -49,7 +49,7 @@ const footer = yaml.load(
{
footer.services.map((item: any) => (
<li>
<a href={item.url} class="fuz-footer-link">
<a href={item.url} class="fuz-footer-link" title={item.title}>
{item.name}
</a>
</li>

View File

@@ -1,5 +1,9 @@
---
import "../../styles/map-google.css";
/**
* PARAMETRY MAPY
*/
const {
apiKey,
lat,
@@ -8,106 +12,127 @@ const {
title = "",
description = "",
showMarker = false,
mode = "full", // "full" mapa na całą sekcję, wszystko inne => karta
mode = "full",
mapStyleId = "8e0a97af9476f2d3" // Google DEMO mapId (legalne, bez warningów)
} = Astro.props;
const mapId = `fuz-map-${Math.random().toString(36).slice(2)}`;
/** ID kontenera w DOM */
const domId = `fuz-map-${Math.random().toString(36).slice(2)}`;
---
<!-- Kontener na mapę -->
<div
id={mapId}
class={mode === "full"
? "fuz-map--full"
: mode === "contact"
? "fuz-map--contact"
: "fuz-map--card"}
id={domId}
class={
mode === "full"
? "fuz-map--full"
: mode === "contact"
? "fuz-map--contact"
: "fuz-map--card"
}
data-lat={lat}
data-lon={lon}
data-zoom={zoom}
data-title={title}
data-desc={description}
data-showmarker={showMarker}
>
</div>
/></div>
<script is:inline define:vars={{ apiKey, mapId }}>
(function () {
// Funkcja inicjująca JEDNĄ konkretną mapę
function initSingleMap() {
const el = document.getElementById(mapId);
if (!el || !window.google || !google.maps) return;
<script is:inline define:vars={{ apiKey, domId, mapStyleId }}>
/**
* ⭐ FINALNY GOOGLE MAPS API LOADER 2025 ⭐
* ------------------------------------------
* - Bez callbacków
* - Bez deprecated Marker
* - Zgodny z importLibrary()
* - Zero warningów o async / mapId
* - Stabilny w Astro (Vite SSR + SPA)
*/
const lat = Number(el.dataset.lat);
const lon = Number(el.dataset.lon);
const zoom = Number(el.dataset.zoom);
const title = el.dataset.title || "";
const desc = el.dataset.desc || "";
const showMarker = el.dataset.showmarker === "true";
(function () {
const map = new google.maps.Map(el, {
zoom,
center: { lat, lng: lon },
mapTypeControl: false,
fullscreenControl: false,
streetViewControl: false,
scrollwheel: false,
zoomControl: true,
/** Ładowanie Google Maps API — stabilna wersja */
async function loadGoogleMaps(apiKey) {
// Jeśli już załadowane
if (window.google?.maps) return window.google.maps;
// Jeśli trwa ładowanie — użyj tego samego Promise
if (!window._GOOGLE_MAPS_LOADING) {
window._GOOGLE_MAPS_LOADING = new Promise((resolve, reject) => {
const script = document.createElement("script");
script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&v=weekly`;
script.async = true;
script.defer = true;
script.onerror = () => reject("Google Maps API failed to load");
script.onload = () => resolve(window.google.maps);
document.head.appendChild(script);
});
}
return window._GOOGLE_MAPS_LOADING;
}
/** ★ Inicjalizacja pojedynczej mapy */
async function initMap() {
const el = document.getElementById(domId);
if (!el) return;
/** 1. Ładujemy API */
const maps = await loadGoogleMaps(apiKey);
/** 2. importLibrary — NOWE Google API 2025 */
const { Map } = await maps.importLibrary("maps");
const { AdvancedMarkerElement } = await maps.importLibrary("marker");
const { InfoWindow } = await maps.importLibrary("maps");
/** 3. Dane konfiguracyjne mapy z data-* */
const lat = Number(el.dataset.lat);
const lon = Number(el.dataset.lon);
const zoom = Number(el.dataset.zoom);
const title = el.dataset.title || "";
const desc = el.dataset.desc || "";
const showMarker = el.dataset.showmarker === "true";
/** 4. Tworzymy mapę z nowym mapId */
const map = new Map(el, {
center: { lat, lng: lon },
zoom,
mapId: mapStyleId, // ★★ wymagane 2024+ ★★
mapTypeControl: false,
fullscreenControl: false,
streetViewControl: false,
scrollwheel: false,
zoomControl: true,
});
/** Zapamiętanie referencji */
window.fuzMaps = window.fuzMaps || {};
window.fuzMaps[domId] = map;
/** 5. Marker 2025 (AdvancedMarkerElement) */
if (showMarker) {
const marker = new AdvancedMarkerElement({
map,
position: { lat, lng: lon }
});
// Zapamiętujemy mapę globalnie (np. dla KML / markerów z zewnątrz)
if (!window.fuzMaps) window.fuzMaps = {};
window.fuzMaps[mapId] = map;
if (showMarker) {
const marker = new google.maps.Marker({
position: { lat, lng: lon },
map,
if (title || desc) {
const info = new InfoWindow({
content: `
<div class="fuz-map-infowindow">
<strong>${title}</strong><br/>
${desc}
</div>
`
});
if (title) {
const info = new google.maps.InfoWindow({
content: `
<div class="fuz-map-infowindow">
<strong>${title}</strong><br/>
${desc}
</div>
`,
});
info.open(map, marker);
}
info.open({ map, anchor: marker });
}
}
}
// 1) Jeśli Google Maps JUŻ załadowane → inicjuj od razu
if (window.google && window.google.maps) {
initSingleMap();
return;
}
/** Start po załadowaniu DOM */
document.addEventListener("DOMContentLoaded", initMap);
// 2) Jeżeli jeszcze NIE ma Google Maps → przygotuj kolejkę
if (!window.FUZ_GOOGLE_MAPS_LOADER) {
window.FUZ_GOOGLE_MAPS_LOADER = true;
window.FUZ_GOOGLE_MAPS_QUEUE = [];
window.FUZ_initGoogleMaps = function () {
// Wołana przez &callback=FUZ_initGoogleMaps
(window.FUZ_GOOGLE_MAPS_QUEUE || []).forEach((fn) => {
try {
fn();
} catch (e) {
console.error(e);
}
});
window.FUZ_GOOGLE_MAPS_QUEUE = [];
};
const s = document.createElement("script");
s.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&callback=FUZ_initGoogleMaps`;
s.async = true;
document.head.appendChild(s);
}
// 3) Dodaj tę mapę do kolejki, żeby odpaliła się po załadowaniu SDK
window.FUZ_GOOGLE_MAPS_QUEUE.push(initSingleMap);
})();
})();
</script>

View File

@@ -8,11 +8,11 @@ const data = yaml.load(
fs.readFileSync("./src/content/contact/contact.yaml", "utf8"),
);
const apiKey = import.meta.env.PUBLIC_GOOGLE_MAPS_KEY;
const form = data.form;
---
<!-- TODO: Obrobić wysyłanie maila przez api -->
<section id="contact" class="fuz-section">
<!-- GRID 2 kolumny -->
<div class="fuz-contact-grid">
<!-- Lewa kolumna -->
<div class="space-y-6">
@@ -29,14 +29,14 @@ const apiKey = import.meta.env.PUBLIC_GOOGLE_MAPS_KEY;
<input
type="text"
name="firstName"
placeholder="Imię"
placeholder={form.firstName.placeholder}
class="fuz-input"
required
/>
<input
type="text"
name="lastName"
placeholder="Nazwisko"
placeholder={form.lastName.placeholder}
class="fuz-input"
required
/>
@@ -46,31 +46,33 @@ const apiKey = import.meta.env.PUBLIC_GOOGLE_MAPS_KEY;
<input
type="email"
name="email"
placeholder="Email"
placeholder={form.email.placeholder}
class="fuz-input"
required
autocomplete="email"
/>
<input
type="tel"
name="phone"
placeholder="Telefon"
placeholder={form.phone.placeholder}
class="fuz-input"
required
autocomplete="tel"
/>
</div>
<input
type="text"
name="subject"
placeholder="Temat wiadomości"
placeholder={form.subject.placeholder}
class="fuz-input"
required
/>
<textarea
rows="5"
name="message"
placeholder="Treść wiadomości"
rows={form.message.rows}
placeholder={form.message.placeholder}
class="fuz-input"
required></textarea>
@@ -82,31 +84,33 @@ const apiKey = import.meta.env.PUBLIC_GOOGLE_MAPS_KEY;
required
/>
<span>
Wyrażam zgodę na przetwarzanie moich danych osobowych
zgodnie z
<a href="/polityka-prywatnosci">polityką prywatności</a
{form.rodo.label}
<a href={form.rodo.policyLink} title={form.rodo.policyTitle}>{form.rodo.policyText}</a
>.
</span>
</label>
<button class="btn btn-outline w-full py-3 text-lg">
Wyślij wiadomość →
<button
class="btn btn-outline w-full py-3 text-lg"
title={form.submit.title}
>
{form.submit.label}
</button>
</form>
</div>
</div>
<div class="fuz-contact-map-wrapper">
<MapGoogle
apiKey={apiKey}
lat={data.lat}
lon={data.lng}
zoom={16}
title={data.markerTitle}
description={data.markerAddress}
showMarker={true}
mode="contact"
/>
<MapGoogle
apiKey={apiKey}
lat={data.lat}
lon={data.lng}
zoom={16}
title={data.markerTitle}
description={data.markerAddress}
showMarker={true}
mode="contact"
mapStyleId={data.maps.mapId} />
</div>
<div id="toast" class="fuz-toast hidden"></div>

View File

@@ -25,7 +25,7 @@ const reverse = index % 2 === 1;
{section.button && (
<div class="mt-8 flex justify-center">
<a href={section.button.url} class="btn btn-outline">
<a href={section.button.url} class="btn btn-outline" title={section.button.title}>
{section.button.text}
</a>
</div>

View File

@@ -1,5 +1,5 @@
---
import IframeChannelSwitcher from "../../islands/ChannelSwitcher.jsx";
import ChannelSwitcher from "../../islands/ChannelSwitcher.jsx";
const { section } = Astro.props;
---
@@ -14,7 +14,7 @@ const { section } = Astro.props;
<div class="fuz-markdown mb-10" set:html={section.html} />
)}
<IframeChannelSwitcher client:load sets={section.iframe_sets} />
<ChannelSwitcher client:load sets={section.iframe_sets} title={section.title} />
</div>
</section>