Stylizacja, zmiana mapy zasięgu
This commit is contained in:
@@ -9,7 +9,6 @@ const {
|
||||
ctas = []
|
||||
} = Astro.props;
|
||||
|
||||
// Automatyczne wczytanie wszystkich obrazów hero
|
||||
const images = import.meta.glob<{ default: ImageMetadata }>('/src/assets/hero/*.{png,jpg,jpeg,webp,avif}', {
|
||||
eager: true
|
||||
});
|
||||
@@ -44,7 +43,6 @@ const isLCP = true;
|
||||
)}
|
||||
|
||||
<div class="f-hero-inner">
|
||||
|
||||
{Array.isArray(title)
|
||||
? title.map(line => (
|
||||
<h1>{line}</h1>
|
||||
|
||||
@@ -7,7 +7,7 @@ const links = [
|
||||
{ name: "INTERNET I TELEWIZJA", href: "/internet-telewizja" },
|
||||
{ name: "TELEFON", href: "/telefon" },
|
||||
{ name: "ZASIĘG SIECI", href: "/mapa-zasiegu" },
|
||||
{ name: "KONTAKT", href: "/#contact" },
|
||||
{ name: "KONTAKT", href: "/kontakt" },
|
||||
{
|
||||
name: "BOK",
|
||||
href: "https://panel.fuz.pl/userpanel/auth",
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
---
|
||||
const { cities = [] } = Astro.props;
|
||||
|
||||
// sortujemy alfabetycznie
|
||||
const sorted = cities.sort((a: string, b: any) => a.localeCompare(b, "pl"));
|
||||
---
|
||||
|
||||
<div class="fuz-cities-box">
|
||||
<h4 class="fuz-cities-title">Miejscowości w zasięgu sieci światłowodowej i radiowej</h4>
|
||||
<h4 class="fuz-cities-title">Miejscowości w zasięgu sieci światłowodowej</h4>
|
||||
|
||||
<div class="fuz-cities-grid">
|
||||
{sorted.map((city: unknown) => (
|
||||
@@ -20,7 +18,6 @@ const sorted = cities.sort((a: string, b: any) => a.localeCompare(b, "pl"));
|
||||
|
||||
background: var(--f-background);
|
||||
color: var(--f-text);
|
||||
|
||||
padding: 16px;
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ const {
|
||||
description = "",
|
||||
showMarker = false,
|
||||
mode = "full",
|
||||
mapStyleId = "8e0a97af9476f2d3" // Google DEMO mapId (legalne, bez warningów)
|
||||
mapStyleId = "8e0a97af9476f2d3"
|
||||
} = Astro.props;
|
||||
|
||||
/** ID kontenera w DOM */
|
||||
@@ -119,9 +119,11 @@ const domId = `fuz-map-${Math.random().toString(36).slice(2)}`;
|
||||
if (title || desc) {
|
||||
const info = new InfoWindow({
|
||||
content: `
|
||||
<div class="fuz-map-infowindow">
|
||||
<strong>${title}</strong><br/>
|
||||
${desc}
|
||||
<div class="f-info-window">
|
||||
<div class="f-info-header">
|
||||
<div class="f-info-city">${title}</div>
|
||||
<div class="f-info-street">${desc}</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
});
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
---
|
||||
const { id, label } = Astro.props;
|
||||
---
|
||||
|
||||
<label class="flex items-center gap-2 cursor-pointer select-none text-sm">
|
||||
<input
|
||||
id={id}
|
||||
type="checkbox"
|
||||
class="h-4 w-4 rounded border-gray-400"
|
||||
onchange={id === "fiber-toggle"
|
||||
? "fiberRangeShow()"
|
||||
: "radioRangeShow()"}
|
||||
/>
|
||||
<span>{label}</span>
|
||||
</label>
|
||||
@@ -1,184 +1,125 @@
|
||||
---
|
||||
import yaml from "js-yaml";
|
||||
import fs from "fs";
|
||||
import MapGoogle from "../maps/MapGoogle.astro";
|
||||
// import "../../styles/contact.css";
|
||||
import MapGoogle from "../../components/maps/MapGoogle.astro";
|
||||
|
||||
const data = yaml.load(
|
||||
fs.readFileSync("./src/content/contact/contact.yaml", "utf8"),
|
||||
fs.readFileSync("./src/content/contact/contact.yaml", "utf8")
|
||||
);
|
||||
|
||||
const apiKey = import.meta.env.PUBLIC_GOOGLE_MAPS_KEY;
|
||||
const form = data.form;
|
||||
---
|
||||
|
||||
<section id="contact" class="f-section">
|
||||
<div class="f-contact-grid">
|
||||
<!-- Lewa kolumna -->
|
||||
<div class="f-contact-col-1">
|
||||
<h2>{data.title}</h2>
|
||||
<div class="f-contact-item" set:html={data.description} />
|
||||
</div>
|
||||
|
||||
<!-- Formularz -->
|
||||
<div class="f-contact-col-2">
|
||||
<h2>{data.contactFormTitle}</h2>
|
||||
<form id="contactForm" class="f-contact-form">
|
||||
<div class="f-contact-form-inner">
|
||||
<input
|
||||
type="text"
|
||||
name="firstName"
|
||||
placeholder={form.firstName.placeholder}
|
||||
class="f-input"
|
||||
required
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
name="lastName"
|
||||
placeholder={form.lastName.placeholder}
|
||||
class="f-input"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
placeholder={form.email.placeholder}
|
||||
class="f-input"
|
||||
required
|
||||
autocomplete="email"
|
||||
/>
|
||||
<input
|
||||
type="tel"
|
||||
name="phone"
|
||||
placeholder={form.phone.placeholder}
|
||||
class="f-input"
|
||||
required
|
||||
autocomplete="tel"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
name="subject"
|
||||
placeholder={form.subject.placeholder}
|
||||
class="f-input"
|
||||
required
|
||||
/>
|
||||
|
||||
<textarea
|
||||
name="message"
|
||||
rows={form.message.rows}
|
||||
placeholder={form.message.placeholder}
|
||||
class="f-input"
|
||||
required></textarea>
|
||||
|
||||
<label class="f-rodo">
|
||||
<input type="checkbox" name="rodo" required />
|
||||
<span>
|
||||
{form.rodo.label}
|
||||
<a
|
||||
href={form.rodo.policyLink}
|
||||
title={form.rodo.policyTitle}
|
||||
>{form.rodo.policyText}</a
|
||||
>.
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<button title={form.submit.title}>
|
||||
{form.submit.label}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<section id="kontakt" class="f-section">
|
||||
<div class="f-contact-grid">
|
||||
<!-- Kolumna lewa -->
|
||||
<div class="f-contact-col-1">
|
||||
<h2>{data.title}</h2>
|
||||
<div class="f-contact-item" set:html={data.description}></div>
|
||||
</div>
|
||||
|
||||
<div class="f-contact-map">
|
||||
<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 class="f-contact-col-2">
|
||||
<h2>{data.contactFormTitle}</h2>
|
||||
<form id="contactForm" class="f-contact-form">
|
||||
<div class="f-contact-form-inner">
|
||||
<input type="text" name="firstName" placeholder={form.firstName.placeholder} class="f-input" required />
|
||||
<input type="text" name="lastName" placeholder={form.lastName.placeholder} class="f-input" required />
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<input type="email" name="email" placeholder={form.email.placeholder} class="f-input" required autocomplete="email" />
|
||||
<input type="tel" name="phone" placeholder={form.phone.placeholder} class="f-input" required autocomplete="tel" />
|
||||
</div>
|
||||
|
||||
<input type="text" name="subject" placeholder={form.subject.placeholder} class="f-input" required />
|
||||
|
||||
<textarea name="message" rows={form.message.rows} placeholder={form.message.placeholder} class="f-input" required></textarea>
|
||||
|
||||
<label class="f-rodo">
|
||||
<input type="checkbox" name="rodo" required />
|
||||
<span>
|
||||
{form.rodo.label}
|
||||
<a href={form.rodo.policyLink} title={form.rodo.policyTitle}>{form.rodo.policyText}</a>.
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<button title={form.submit.title}>{form.submit.label}</button>
|
||||
</form>
|
||||
</div>
|
||||
<!-- TODO: Poprawić obslugę błedu wysyłania wiadomości by pojawiał sie toast i ulozyć css -->
|
||||
<div id="toast" class="f-toast"></div>
|
||||
</div>
|
||||
|
||||
<div class="f-contact-map">
|
||||
<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="f-toast"></div>
|
||||
</section>
|
||||
|
||||
<!-- ReCaptcha -->
|
||||
<script
|
||||
is:inline
|
||||
define:vars={{ siteKey: import.meta.env.PUBLIC_RECAPTCHA_SITE_KEY }}
|
||||
>
|
||||
window.FUZ_RECAPTCHA_KEY = siteKey;
|
||||
<!-- ReCaptcha v3 -->
|
||||
<script is:inline define:vars={{ siteKey: import.meta.env.PUBLIC_RECAPTCHA_SITE_KEY }}>
|
||||
window.FUZ_RECAPTCHA_KEY = siteKey;
|
||||
|
||||
const recaptchaScript = document.createElement("script");
|
||||
recaptchaScript.src =
|
||||
"https://www.google.com/recaptcha/api.js?render=" + siteKey;
|
||||
document.head.appendChild(recaptchaScript);
|
||||
const s = document.createElement("script");
|
||||
s.src = "https://www.google.com/recaptcha/api.js?render=" + siteKey;
|
||||
s.async = true;
|
||||
document.head.appendChild(s);
|
||||
</script>
|
||||
|
||||
|
||||
<script
|
||||
is:inline
|
||||
define:vars={{
|
||||
successMsg: JSON.stringify(form.submit.successMessage),
|
||||
errorMsg: JSON.stringify(form.submit.errorMessage),
|
||||
}}
|
||||
is:inline
|
||||
define:vars={{
|
||||
successMsg: form.successMessage,
|
||||
errorMsg: form.errorMessage
|
||||
}}
|
||||
>
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const form = document.getElementById("contactForm");
|
||||
const toast = document.getElementById("toast");
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const form = document.getElementById("contactForm");
|
||||
const toast = document.getElementById("toast");
|
||||
|
||||
if (!form) return;
|
||||
if (!form) return;
|
||||
|
||||
form.addEventListener("submit", async (e) => {
|
||||
if (!form.reportValidity()) return;
|
||||
form.addEventListener("submit", async (e) => {
|
||||
if (!form.reportValidity()) return;
|
||||
e.preventDefault();
|
||||
|
||||
e.preventDefault();
|
||||
const data = Object.fromEntries(new FormData(form).entries());
|
||||
data.rodo = form.rodo.checked;
|
||||
|
||||
const formData = new FormData(form);
|
||||
const token = await grecaptcha.execute(window.FUZ_RECAPTCHA_KEY, { action: "submit" });
|
||||
data.recaptcha = token;
|
||||
|
||||
const payload = Object.fromEntries(formData.entries());
|
||||
payload.rodo = formData.get("rodo") === "on";
|
||||
const resp = await fetch("/api/contact", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
const token = await grecaptcha.execute(window.FUZ_RECAPTCHA_KEY, {
|
||||
action: "submit",
|
||||
});
|
||||
payload.recaptcha = token;
|
||||
const json = await resp.json();
|
||||
|
||||
const resp = await fetch("/api/contact", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
showToast(json.ok ? successMsg : errorMsg, json.ok ? "success" : "error");
|
||||
|
||||
const json = await resp.json();
|
||||
showToast(
|
||||
json.ok ? JSON.parse(successMsg) : JSON.parse(errorMsg),
|
||||
json.ok ? "success" : "error",
|
||||
);
|
||||
|
||||
if (json.ok) form.reset();
|
||||
});
|
||||
|
||||
function showToast(message, type = "success") {
|
||||
toast.innerHTML = `
|
||||
<div class="fuz-toast-msg ${type}">
|
||||
${message}
|
||||
</div>
|
||||
`;
|
||||
toast.classList.remove("visible");
|
||||
void toast.offsetWidth;
|
||||
toast.classList.add("visible");
|
||||
setTimeout(() => {
|
||||
toast.classList.remove("visible");
|
||||
}, 3000);
|
||||
}
|
||||
if (json.ok) form.reset();
|
||||
});
|
||||
|
||||
function showToast(msg, type) {
|
||||
toast.innerHTML = `<div class="f-toast-msg ${type}">${msg}</div>`;
|
||||
toast.classList.remove("visible");
|
||||
void toast.offsetWidth;
|
||||
toast.classList.add("visible");
|
||||
|
||||
setTimeout(() => toast.classList.remove("visible"), 3000);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user