199 lines
6.0 KiB
Plaintext
199 lines
6.0 KiB
Plaintext
---
|
|
import yaml from "js-yaml";
|
|
import fs from "fs";
|
|
import MapGoogle from "../maps/MapGoogle.astro";
|
|
import "../../styles/contact.css";
|
|
|
|
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;
|
|
---
|
|
|
|
<section id="contact" class="fuz-section">
|
|
<div class="fuz-contact-grid">
|
|
<!-- Lewa kolumna -->
|
|
<div class="space-y-6">
|
|
<h2 class="fuz-section-title">{data.title}</h2>
|
|
<div class="fuz-contact-description" set:html={data.description} />
|
|
</div>
|
|
|
|
<!-- Formularz -->
|
|
<div class="fuz-contact-box">
|
|
<h2 class="fuz-section-title">{data.contactFormTitle}</h2>
|
|
|
|
<form id="contactForm" class="fuz-contact-form">
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<input
|
|
type="text"
|
|
name="firstName"
|
|
placeholder={form.firstName.placeholder}
|
|
class="fuz-input"
|
|
required
|
|
/>
|
|
<input
|
|
type="text"
|
|
name="lastName"
|
|
placeholder={form.lastName.placeholder}
|
|
class="fuz-input"
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<input
|
|
type="email"
|
|
name="email"
|
|
placeholder={form.email.placeholder}
|
|
class="fuz-input"
|
|
required
|
|
autocomplete="email"
|
|
/>
|
|
<input
|
|
type="tel"
|
|
name="phone"
|
|
placeholder={form.phone.placeholder}
|
|
class="fuz-input"
|
|
required
|
|
autocomplete="tel"
|
|
/>
|
|
</div>
|
|
|
|
<input
|
|
type="text"
|
|
name="subject"
|
|
placeholder={form.subject.placeholder}
|
|
class="fuz-input"
|
|
required
|
|
/>
|
|
|
|
<textarea
|
|
name="message"
|
|
rows={form.message.rows}
|
|
placeholder={form.message.placeholder}
|
|
class="fuz-input"
|
|
required></textarea>
|
|
|
|
<label class="fuz-rodo">
|
|
<input
|
|
type="checkbox"
|
|
name="rodo"
|
|
class="mt-1 h-4 w-4"
|
|
required
|
|
/>
|
|
<span>
|
|
{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"
|
|
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"
|
|
mapStyleId={data.maps.mapId}
|
|
/>
|
|
</div>
|
|
|
|
<div id="toast" class="fuz-toast"></div>
|
|
</section>
|
|
|
|
<!-- ReCaptcha init -->
|
|
<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);
|
|
</script>
|
|
|
|
<!-- Formularz + toast -->
|
|
<script
|
|
is:inline
|
|
define:vars={{
|
|
successMsg: JSON.stringify(form.submit.successMessage),
|
|
errorMsg: JSON.stringify(form.submit.errorMessage),
|
|
}}
|
|
>
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
const form = document.getElementById("contactForm");
|
|
const toast = document.getElementById("toast");
|
|
|
|
if (!form) return; // Safety
|
|
|
|
form.addEventListener("submit", async (e) => {
|
|
if (!form.reportValidity()) return;
|
|
|
|
e.preventDefault();
|
|
|
|
const formData = new FormData(form);
|
|
|
|
const payload = Object.fromEntries(formData.entries());
|
|
payload.rodo = formData.get("rodo") === "on";
|
|
|
|
const token = await grecaptcha.execute(window.FUZ_RECAPTCHA_KEY, {
|
|
action: "submit",
|
|
});
|
|
payload.recaptcha = token;
|
|
|
|
const resp = await fetch("/api/contact", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify(payload),
|
|
});
|
|
|
|
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>
|
|
`;
|
|
// reset animacji
|
|
toast.classList.remove("visible");
|
|
void toast.offsetWidth; // magiczny hack forcing reflow
|
|
|
|
// pokaż
|
|
toast.classList.add("visible");
|
|
|
|
// ukryj po 3s
|
|
setTimeout(() => {
|
|
toast.classList.remove("visible");
|
|
}, 3000);
|
|
}
|
|
});
|
|
</script>
|