ContactSection add, zmiany w MapGoogle
This commit is contained in:
11
.env.example
11
.env.example
@@ -1,11 +1,16 @@
|
||||
# Public URL of the website
|
||||
PUBLIC_SITE_URL=https://www.fuz.dariuszm.eu
|
||||
|
||||
# Google Maps
|
||||
PUBLIC_GOOGLE_MAPS_KEY=
|
||||
PUBLIC_GOOGLE_MAPS_KEY=AIzaSyDbUU6gvHCQilHyBEWL31FIM4D9-HuvgQw
|
||||
PUBLIC_RECAPTCHA_SITE_KEY=6Ld0ixIsAAAAAJdeOdzRy0Wd1TR-Xg6n7GMFxe4x
|
||||
|
||||
# Contact form API
|
||||
FORMS_ENDPOINT=TEST
|
||||
|
||||
# Astro SSR
|
||||
NODE_ENV=production
|
||||
|
||||
# Smtp
|
||||
SMTP_HOST=smtp.webio.pl
|
||||
SMTP_PORT=465
|
||||
SMTP_USER=admin@fuz.hostingasp.pl
|
||||
SMTP_PASS=Janeczek@12
|
||||
@@ -8,7 +8,7 @@ const links = [
|
||||
{ name: "INTERNET RADIOWY", href: "/internet-radiowy" },
|
||||
{ name: "TELEFON", href: "/telefon" },
|
||||
{ name: "ZASIĘG SIECI", href: "/mapa-zasiegu" },
|
||||
{ name: "KONTAKT", href: "/kontakt" }
|
||||
{ name: "KONTAKT", href: "/#contact" }
|
||||
];
|
||||
---
|
||||
|
||||
|
||||
79
src/components/maps/MapGoogle.astro
Normal file
79
src/components/maps/MapGoogle.astro
Normal file
@@ -0,0 +1,79 @@
|
||||
---
|
||||
const {
|
||||
apiKey,
|
||||
lat,
|
||||
lon,
|
||||
zoom = 15,
|
||||
title = "",
|
||||
description = "",
|
||||
} = Astro.props;
|
||||
import "../../styles/map-google.css";
|
||||
---
|
||||
|
||||
<div class="fuz-map-wrapper">
|
||||
<div
|
||||
id="fuz-map-google"
|
||||
class="fuz-map-google"
|
||||
data-lat={lat}
|
||||
data-lon={lon}
|
||||
data-title={title}
|
||||
data-description={description}
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<!-- TODO: Popracować nad wygladem markera -->
|
||||
<script is:inline>
|
||||
window.initFuzGoogleMap = function () {
|
||||
const el = document.getElementById("fuz-map-google");
|
||||
if (!el) return;
|
||||
|
||||
const lat = Number(el.dataset.lat);
|
||||
const lon = Number(el.dataset.lon);
|
||||
const title = el.dataset.title || "";
|
||||
const desc = el.dataset.description || "";
|
||||
|
||||
const map = new google.maps.Map(el, {
|
||||
zoom: Number(`{{zoom}}`) || 15,
|
||||
center: { lat, lng: lon },
|
||||
mapTypeControl: false,
|
||||
scrollwheel: false,
|
||||
zoomControl: true,
|
||||
streetViewControl: false,
|
||||
});
|
||||
|
||||
const infowindow = new google.maps.InfoWindow({
|
||||
content: `<div class="fuz-map-infowindow"><b>${title}</b><br/>${desc}</div>`,
|
||||
});
|
||||
|
||||
const marker = new google.maps.Marker({
|
||||
position: { lat, lng: lon },
|
||||
map,
|
||||
title,
|
||||
});
|
||||
|
||||
marker.addListener("click", () => {
|
||||
infowindow.open({
|
||||
map,
|
||||
anchor: marker,
|
||||
shouldFocus: false,
|
||||
});
|
||||
});
|
||||
|
||||
// auto-open popup on load
|
||||
setTimeout(() => {
|
||||
infowindow.open({
|
||||
map,
|
||||
anchor: marker,
|
||||
shouldFocus: false,
|
||||
});
|
||||
}, 100);
|
||||
|
||||
// Light fade-in
|
||||
el.classList.add("loaded");
|
||||
};
|
||||
</script>
|
||||
|
||||
<script
|
||||
async
|
||||
src={`https://maps.googleapis.com/maps/api/js?key=${apiKey}&callback=initFuzGoogleMap`}
|
||||
></script>
|
||||
173
src/components/sections/SectionContact.astro
Normal file
173
src/components/sections/SectionContact.astro
Normal file
@@ -0,0 +1,173 @@
|
||||
---
|
||||
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;
|
||||
---
|
||||
<!-- 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">
|
||||
<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="Imię"
|
||||
class="fuz-input"
|
||||
required
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
name="lastName"
|
||||
placeholder="Nazwisko"
|
||||
class="fuz-input"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
placeholder="Email"
|
||||
class="fuz-input"
|
||||
required
|
||||
/>
|
||||
<input
|
||||
type="tel"
|
||||
name="phone"
|
||||
placeholder="Telefon"
|
||||
class="fuz-input"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
name="subject"
|
||||
placeholder="Temat wiadomości"
|
||||
class="fuz-input"
|
||||
required
|
||||
/>
|
||||
|
||||
<textarea
|
||||
rows="5"
|
||||
name="message"
|
||||
placeholder="Treść wiadomości"
|
||||
class="fuz-input"
|
||||
required></textarea>
|
||||
|
||||
<label class="fuz-rodo">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="rodo"
|
||||
class="mt-1 h-4 w-4"
|
||||
required
|
||||
/>
|
||||
<span>
|
||||
Wyrażam zgodę na przetwarzanie moich danych osobowych
|
||||
zgodnie z
|
||||
<a href="/polityka-prywatnosci">polityką prywatności</a
|
||||
>.
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<button class="btn btn-outline w-full py-3 text-lg">
|
||||
Wyślij wiadomość →
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- GOOGLE MAPS -->
|
||||
<MapGoogle
|
||||
apiKey={apiKey}
|
||||
lat={data.lat}
|
||||
lon={data.lng}
|
||||
zoom={16}
|
||||
title={data.markerTitle}
|
||||
description={data.markerAddress}
|
||||
/>
|
||||
|
||||
<div id="toast" class="fuz-toast hidden"></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>
|
||||
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 ? "Wiadomość wysłana!" : "Błąd podczas wysyłania.",
|
||||
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("hidden");
|
||||
setTimeout(() => toast.classList.add("hidden"), 3000);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
19
src/content/contact/contact.yaml
Normal file
19
src/content/contact/contact.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
title: SKONTAKTUJ SIĘ Z NAMI
|
||||
description: |
|
||||
<h3>FUZ ADAM ROJEK</h3>
|
||||
<h4>ul. Świętojańska 46 07-200 Wyszków</h4>
|
||||
<h4>✆ +48 606 369 650</h4>
|
||||
<h4>☏ (29) 643 80 55</h4>
|
||||
<h4>✉ biuro@fuz.pl</h4>
|
||||
|
||||
<p>
|
||||
Zapraszamy do naszego biura ! Na miejscu udzielimy niezbędnych informacji oraz pomożemy Ci wybrać ofertę najlepiej dopasowaną do Twoich potrzeb i możliwości. W przypadku jakichkolwiek wątpliwości służymy pomocą i rzetelną informacją.
|
||||
Możesz skontaktować się z nami również telefonicznie czy mailowo - odpowiemy najszybciej jak to możliwe.
|
||||
Biuro jest czynne od poniedziałku do piątku w godzinach <strong>9:00-17:00</strong>
|
||||
</p>
|
||||
|
||||
lat: 52.597388
|
||||
lng: 21.456797
|
||||
markerTitle: "FUZ Adam Rojek"
|
||||
markerAddress: ul. Świętojańska 46</br>07-200 Wyszków
|
||||
contactFormTitle: Pisząc wiadomość ...
|
||||
@@ -2,6 +2,7 @@
|
||||
import DefaultLayout from "../layouts/DefaultLayout.astro";
|
||||
import Hero from "../components/hero/Hero.astro";
|
||||
import SectionRenderer from "../components/sections/SectionRenderer.astro"
|
||||
import SectionContact from "../components/sections/SectionContact.astro";
|
||||
|
||||
import yaml from "js-yaml";
|
||||
import fs from "fs";
|
||||
@@ -13,4 +14,5 @@ const hero = yaml.load(fs.readFileSync("./src/content/home/hero.yaml", "utf8"));
|
||||
<DefaultLayout seo={seo}>
|
||||
<Hero {...hero} />
|
||||
<SectionRenderer src="./src/content/site/site.section.yaml" />
|
||||
<SectionContact />
|
||||
</DefaultLayout>
|
||||
|
||||
@@ -4,4 +4,8 @@
|
||||
@import "./hero.css";
|
||||
@import "./buttons.css";
|
||||
@import "./sections.css";
|
||||
@import "./markdown.css";
|
||||
@import "./markdown.css";
|
||||
|
||||
.grecaptcha-badge {
|
||||
display: none !important;
|
||||
}
|
||||
@@ -36,3 +36,54 @@
|
||||
.btn-ghost:hover {
|
||||
background-color: var(--btn-ghost-hover-bg);
|
||||
}
|
||||
|
||||
.fuz-input {
|
||||
width: 100%;
|
||||
padding: 0.75rem 1rem; /* bardziej eleganckie */
|
||||
border-radius: 0.75rem;
|
||||
|
||||
/* Kolory z theme.css */
|
||||
background-color: var(--fuz-bg);
|
||||
color: var(--fuz-text);
|
||||
border: 1px solid var(--fuz-border, #d1d5db); /* fallback dla bezpieczeństwa */
|
||||
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.06);
|
||||
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
/* Hover odcien zależny od border, nie od Tailwind */
|
||||
.fuz-input:hover {
|
||||
border-color: var(--fuz-text);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
/* Placeholder — używa fuz-text ale jaśniejszy */
|
||||
.fuz-input::placeholder {
|
||||
color: color-mix(in srgb, var(--fuz-text) 40%, transparent);
|
||||
}
|
||||
|
||||
/* Focus — używa accent */
|
||||
.fuz-input:focus {
|
||||
outline: none;
|
||||
border-color: var(--fuz-accent);
|
||||
box-shadow: 0 0 0 3px color-mix(in srgb, var(--fuz-accent) 40%, transparent);
|
||||
}
|
||||
|
||||
/* Error */
|
||||
.fuz-input-error {
|
||||
border-color: #ff4d4f !important;
|
||||
box-shadow: 0 0 0 3px rgba(255, 77, 79, 0.3) !important;
|
||||
}
|
||||
|
||||
/* Disabled */
|
||||
.fuz-input:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
background-color: color-mix(in srgb, var(--fuz-bg) 80%, #888);
|
||||
}
|
||||
|
||||
/* Textarea */
|
||||
textarea.fuz-input {
|
||||
resize: none;
|
||||
}
|
||||
|
||||
55
src/styles/contact.css
Normal file
55
src/styles/contact.css
Normal file
@@ -0,0 +1,55 @@
|
||||
.fuz-contact-grid {
|
||||
@apply grid md:grid-cols-2 gap-10 items-start max-w-7xl mx-auto;
|
||||
}
|
||||
|
||||
.fuz-contact-box {
|
||||
|
||||
background-color: var(--fuz-bg);
|
||||
color: var(--fuz-text);
|
||||
}
|
||||
|
||||
.fuz-contact-description h3 {
|
||||
@apply text-xl font-semibold mb-2;
|
||||
color: var(--fuz-text);
|
||||
}
|
||||
|
||||
.fuz-contact-description h4 {
|
||||
@apply text-xl font-semibold mb-1;
|
||||
color: var(--fuz-text);
|
||||
}
|
||||
|
||||
.fuz-contact-description p {
|
||||
@apply text-xl mt-4;
|
||||
color: var(--fuz-text);
|
||||
}
|
||||
|
||||
.fuz-contact-form {
|
||||
@apply space-y-2;
|
||||
}
|
||||
|
||||
/* --- RODO --- */
|
||||
.fuz-rodo {
|
||||
@apply flex items-start gap-3 text-sm;
|
||||
color: var(--fuz-text);
|
||||
}
|
||||
|
||||
/* --- TOAST --- */
|
||||
|
||||
.fuz-toast {
|
||||
@apply fixed top-5 right-5 z-[9999];
|
||||
}
|
||||
|
||||
.fuz-toast-msg {
|
||||
@apply px-5 py-3 rounded-xl shadow-lg;
|
||||
color: var(--fuz-accent-text);
|
||||
}
|
||||
|
||||
/* SUKCES = accent */
|
||||
.fuz-toast-msg.success {
|
||||
background-color: var(--fuz-accent);
|
||||
}
|
||||
|
||||
/* ERROR — czerwony zostaje, bo to wyjątek */
|
||||
.fuz-toast-msg.error {
|
||||
background-color: #ff4d4f;
|
||||
}
|
||||
55
src/styles/map-google.css
Normal file
55
src/styles/map-google.css
Normal file
@@ -0,0 +1,55 @@
|
||||
.fuz-map-wrapper {
|
||||
@apply max-w-7xl mx-auto mt-16;
|
||||
}
|
||||
|
||||
.fuz-map-container {
|
||||
@apply w-full h-[400px] rounded-xl shadow-lg;
|
||||
}
|
||||
|
||||
.fuz-map-google {
|
||||
@apply w-full h-[450px] rounded-xl overflow-hidden relative;
|
||||
background: linear-gradient(90deg, #e0e0e0 0px, #f5f5f5 40px, #e0e0e0 80px);
|
||||
background-size: 200% 100%;
|
||||
animation: mapSkeleton 1.5s infinite;
|
||||
opacity: 0;
|
||||
transition: opacity 0.6s ease;
|
||||
}
|
||||
|
||||
@keyframes mapSkeleton {
|
||||
from {
|
||||
background-position: 200% 0;
|
||||
}
|
||||
|
||||
to {
|
||||
background-position: -200% 0;
|
||||
}
|
||||
}
|
||||
|
||||
.fuz-map-google.loaded {
|
||||
animation: none;
|
||||
background: transparent;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.fuz-map-google {
|
||||
@apply h-[300px];
|
||||
}
|
||||
}
|
||||
|
||||
.fuz-map-infowindow {
|
||||
/* background: var(--fuz-bg); */
|
||||
color: var(--fuz-text);
|
||||
@apply ml-1 mr-6 text-lg leading-snug ;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.gm-style-iw-d {
|
||||
padding-top: 2px !important;
|
||||
padding-bottom: 6px !important;
|
||||
}
|
||||
|
||||
.gm-style-iw-c {
|
||||
padding-top: 2px !important;
|
||||
padding-bottom: 2px !important;
|
||||
}
|
||||
Reference in New Issue
Block a user