// Footer + quote modal + legal modal.
const { Icon: CIcon, Input } = window.ArmaekDesignSystem_06a5c5;
function Footer({ onLegal }) {
const { lang } = window.ArmaekI18n.useLang();
const t = window.ArmaekI18n.STR[lang];
const colTitle = {
fontFamily: 'var(--font-display)', textTransform: 'uppercase', letterSpacing: 'var(--tracking-wide)',
fontSize: 'var(--text-xs)', color: 'var(--accent-bright)', marginBottom: 16,
};
// Order follows the page: services, portfolio, process, why us, contact.
const siteMap = [
['#domov', t.nav.home],
['#sluzby-detail', t.nav.services],
['#portfolio', t.nav.portfolio],
['#proces', t.nav.process],
['#preco', t.nav.about],
['#kontakt', t.nav.contact],
];
return (
);
}
/* Inquiries are delivered to this mailbox via FormSubmit (no backend needed). */
const INQUIRY_ENDPOINT = 'https://formsubmit.co/ajax/' + (((window.ARMAEK_OVERRIDES || {}).email) || 'office@armaek.com');
function QuoteModal({ open, onClose }) {
const { lang } = window.ArmaekI18n.useLang();
const t = window.ArmaekI18n.STR[lang].modal;
const [sent, setSent] = React.useState(false);
const [sending, setSending] = React.useState(false);
const [sendErr, setSendErr] = React.useState(false);
const [ab, setAb] = React.useState([4, 3]);
const [spamErr, setSpamErr] = React.useState(false);
const spamRef = React.useRef(null);
const hpRef = React.useRef(null);
const newAb = () => [2 + Math.floor(Math.random() * 7), 1 + Math.floor(Math.random() * 8)];
React.useEffect(() => {
if (open) {
setSent(false); setSending(false); setSendErr(false); setSpamErr(false); setAb(newAb());
document.body.style.overflow = 'hidden';
} else document.body.style.overflow = '';
return () => { document.body.style.overflow = ''; };
}, [open]);
React.useEffect(() => {
const onKey = (e) => { if (e.key === 'Escape') onClose(); };
window.addEventListener('keydown', onKey); return () => window.removeEventListener('keydown', onKey);
}, [onClose]);
if (!open) return null;
const submit = (e) => {
e.preventDefault();
if (sending) return;
if (hpRef.current && hpRef.current.value) { setSent(true); return; } // honeypot: swallow bots
// Read the answer straight from the DOM — no state-sync loopholes.
const val = spamRef.current ? spamRef.current.value.trim() : '';
if (!/^[0-9]+$/.test(val) || Number(val) !== ab[0] + ab[1]) {
setSpamErr(true);
setAb(newAb());
if (spamRef.current) spamRef.current.value = '';
return;
}
const fd = new FormData(e.currentTarget);
const payload = {
Organizacja: fd.get('organizacja') || '',
'Osoba kontaktowa': fd.get('osoba') || '',
'E-mail': fd.get('email') || '',
Zapytanie: fd.get('zapytanie') || '',
_subject: 'Zapytanie ofertowe — armaek.com',
_template: 'table',
_captcha: 'false',
};
setSending(true); setSendErr(false);
fetch(INQUIRY_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
body: JSON.stringify(payload),
})
.then((r) => { if (!r.ok) throw new Error('send failed'); setSent(true); })
.catch(() => setSendErr(true))
.finally(() => setSending(false));
};
const spamField = {
width: '100%', boxSizing: 'border-box', fontFamily: 'var(--font-body)', fontSize: 'var(--text-sm)',
color: 'var(--text-body)', background: 'var(--surface-inset)',
border: `1px solid ${spamErr ? 'var(--danger)' : 'var(--border-hairline)'}`,
borderRadius: 'var(--radius-sm)', padding: '13px 14px', outline: 'none',
};
return (
e.stopPropagation()} className="surface" style={{ width: 'min(560px,100%)', maxHeight: '90vh', overflowY: 'auto',
borderColor: 'var(--border-gold)', boxShadow: 'var(--shadow-lg)', padding: 36, position: 'relative' }}>
{sent ? (
) : (
<>
{t.kicker}
{t.title}
>
)}
);
}
/* Legal documents (privacy / terms) — full text, scrollable. */
function LegalModal({ open, onClose }) {
const { lang } = window.ArmaekI18n.useLang();
const t = window.ArmaekI18n.STR[lang];
React.useEffect(() => {
if (open) document.body.style.overflow = 'hidden'; else document.body.style.overflow = '';
return () => { document.body.style.overflow = ''; };
}, [open]);
React.useEffect(() => {
const onKey = (e) => { if (e.key === 'Escape') onClose(); };
window.addEventListener('keydown', onKey); return () => window.removeEventListener('keydown', onKey);
}, [onClose]);
if (!open) return null;
const title = open === 'privacy' ? t.legal.privacy : t.legal.terms;
const sections = open === 'privacy' ? t.legal.privacyBody : t.legal.termsBody;
return (
e.stopPropagation()} className="surface" style={{ width: 'min(680px,100%)', maxHeight: '85vh',
display: 'flex', flexDirection: 'column',
borderColor: 'var(--border-gold)', boxShadow: 'var(--shadow-lg)', position: 'relative', overflow: 'hidden' }}>
{title}
{sections.map(([h, body]) => (
))}
);
}
/* ---- Cookie consent (bottom right) ----
Consent is stored for 24 h; Google Analytics loads only after acceptance.
Set GA_MEASUREMENT_ID to enable analytics (e.g. 'G-XXXXXXXXXX'). */
const GA_MEASUREMENT_ID = '';
const CONSENT_KEY = 'armaek-consent';
const CONSENT_TTL = 24 * 60 * 60 * 1000;
function loadAnalytics() {
if (!GA_MEASUREMENT_ID || document.getElementById('ga-gtag')) return;
const s = document.createElement('script');
s.id = 'ga-gtag'; s.async = true;
s.src = 'https://www.googletagmanager.com/gtag/js?id=' + GA_MEASUREMENT_ID;
document.head.appendChild(s);
window.dataLayer = window.dataLayer || [];
window.gtag = function () { window.dataLayer.push(arguments); };
window.gtag('js', new Date());
window.gtag('config', GA_MEASUREMENT_ID, { anonymize_ip: true });
}
function CookieConsent({ onLegal }) {
const { lang } = window.ArmaekI18n.useLang();
const t = window.ArmaekI18n.STR[lang].cookies;
const [show, setShow] = React.useState(false);
React.useEffect(() => {
try {
const raw = localStorage.getItem(CONSENT_KEY);
if (raw) {
const { choice, ts } = JSON.parse(raw);
if (Date.now() - ts < CONSENT_TTL) {
if (choice === 'accepted') loadAnalytics();
return; // decided within the last 24 h — stay quiet
}
}
} catch (e) {}
setShow(true);
}, []);
if (!show) return null;
const decide = (choice) => {
try { localStorage.setItem(CONSENT_KEY, JSON.stringify({ choice, ts: Date.now() })); } catch (e) {}
if (choice === 'accepted') loadAnalytics();
setShow(false); // declined visitors keep browsing, just without analytics
};
const accept = () => decide('accepted');
const decline = () => decide('declined');
return (
{t.text}
);
}
window.ContactParts = { Footer, QuoteModal, LegalModal, CookieConsent };