Stylizacja strony dokumenty, czyszczenie informacji z wyboru opcji do kontaktu po wyslaniu, odswieżeniu

This commit is contained in:
dm
2025-12-15 14:16:33 +01:00
parent 3cc0887dca
commit 3713d50bca
7 changed files with 189 additions and 174 deletions

View File

@@ -18,104 +18,108 @@ const form = data.form;
---
<DefaultLayout seo={seo}>
<section class="f-section">
<div class="f-section-grid md:grid-cols-2 gap-10 items-start">
<div>
<h2 class="f-section-title">{data.title}</h2>
<div class="f-contact-item" set:html={data.description} />
<section class="f-section">
<div class="f-section-grid md:grid-cols-2 gap-10 items-start">
<div>
<h2 class="f-section-title">{data.title}</h2>
<div class="f-contact-item" set:html={data.description} />
</div>
<div>
<h2 class="f-section-title">{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-1 sm: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
type="submit"
class="btn btn-primary w-full py-3"
title={form.submit.title}
>
{form.submit.label}
</button>
</form>
</div>
</div>
<div>
<h2 class="f-section-title">{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-1 sm: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
<div class="mt-10">
<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}
/>
<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 type="submit" class="btn btn-primary w-full py-3" title={form.submit.title}>
{form.submit.label}
</button>
</form>
</div>
</div>
</div>
<div class="mt-10">
<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>
<div id="toast" class="f-toast"></div>
<div id="toast" class="f-toast"></div>
<input type="hidden" name="offerConfig" id="offerConfig" />
</section>
<input type="hidden" name="offerConfig" id="offerConfig" />
</section>
<!-- ReCaptcha v3 -->
<script
@@ -182,63 +186,72 @@ const form = data.form;
// ----------
const LS_KEY = "fuz_offer_config_v1";
const SS_INJECTED_KEY = "fuz_offer_injected_v1";
function formatOfferSummary(o) {
if (!o || !o.pkg) return "";
function clearOfferDraft() {
try {
localStorage.removeItem(LS_KEY);
sessionStorage.removeItem(SS_INJECTED_KEY);
const lines = [];
lines.push(`Wybrana oferta: ${o.pkg.name} (${o.totals?.base ?? 0} ${o.totals?.currencyLabel ?? ""})`);
const hidden = document.getElementById("offerConfig");
if (hidden) hidden.value = "";
} catch {}
}
if (o.decoder) lines.push(`Dekoder: ${o.decoder.name} (+${o.decoder.price} ${o.totals?.currencyLabel ?? ""})`);
if (o.phone) lines.push(`Telefon: ${o.phone.name} (+${o.phone.price} ${o.totals?.currencyLabel ?? ""})`);
function hydrateOfferIntoForm() {
try {
if (sessionStorage.getItem(SS_INJECTED_KEY) === "1") return;
if (Array.isArray(o.tvAddons) && o.tvAddons.length) {
lines.push("Pakiety TV:");
o.tvAddons.forEach((x) => {
const term = x.term ? `, ${x.term}` : "";
lines.push(`- ${x.nazwa} x${x.qty} (${x.unit} ${o.totals?.currencyLabel ?? ""}${term})`);
});
}
const raw = localStorage.getItem(LS_KEY);
if (!raw) return;
if (Array.isArray(o.addons) && o.addons.length) {
lines.push("Dodatki:");
o.addons.forEach((x) =>
lines.push(`- ${x.nazwa} x${x.qty} (${x.unit} ${o.totals?.currencyLabel ?? ""})`),
);
}
const payload = JSON.parse(raw);
lines.push(`RAZEM: ${o.totals?.total ?? 0} ${o.totals?.currencyLabel ?? ""}`);
return lines.join("\n");
}
const msg = document.querySelector('textarea[name="message"]');
const subject = document.querySelector('input[name="subject"]');
const hidden = document.getElementById("offerConfig");
function hydrateOfferIntoForm() {
try {
const raw = localStorage.getItem(LS_KEY);
if (!raw) return;
const offerText =
typeof payload?.message === "string" && payload.message.trim()
? payload.message
: null;
const payload = JSON.parse(raw);
const msg = document.querySelector('textarea[name="message"]');
const subject = document.querySelector('input[name="subject"]');
if (!offerText) return;
const offerText =
typeof payload?.message === "string" && payload.message.trim()
? payload.message
: null;
if (subject && !subject.value) {
subject.value = `Zapytanie: ${payload?.pkg?.name || "Oferta"}`;
}
if (!offerText) return;
if (msg) {
const marker = "Wybrana oferta:";
const alreadyHas = msg.value && msg.value.includes(marker);
if (!alreadyHas) {
msg.value = (msg.value ? msg.value + "\n\n" : "") + offerText;
}
}
if (subject && !subject.value) {
subject.value = `Zapytanie: ${payload?.pkg?.name || "Oferta"}`;
}
if (hidden) hidden.value = offerText;
if (msg) {
msg.value = (msg.value ? msg.value + "\n\n" : "") + offerText;
}
} catch {}
}
sessionStorage.setItem(SS_INJECTED_KEY, "1");
} catch {}
}
hydrateOfferIntoForm();
hydrateOfferIntoForm();
function onSubmitSuccessCleanup() {
clearOfferDraft();
}
function onLeaveCleanup() {
clearOfferDraft();
}
window.addEventListener("pagehide", onLeaveCleanup);
window.addEventListener("beforeunload", onLeaveCleanup);
if (json.ok) {
form.reset();
onSubmitSuccessCleanup();
}
// ----------
});
</script>