/* global React */ const { useState: useStateQ, useEffect: useEffectQ, useMemo: useMemoQ } = React; /* questions strictly per brief — Email removed from channel options */ const QUESTIONS = [ { id: "experience", title: "Есть ли у вас опыт инвестирования?", options: [ "Да, есть опыт", "Частично", "Нет, только знакомлюсь", "Пока просто интересуюсь", ], }, { id: "long_term", title: "Интересуют ли вас долгосрочные решения?", options: [ "Да, рассматриваю долгосрочно", "Скорее да", "Скорее нет", "Пока не определился(ась)", ], }, { id: "consult", title: "Рассматриваете ли вы консультацию?", options: [ "Да, хотелось бы получить", "Возможно, нужна дополнительная информация", "Сначала хочу прочитать материалы", "Не сейчас", ], }, { id: "channel", title: "Как вам удобнее получить информацию?", options: [ "Звонок", "Telegram", "WhatsApp", ], }, ]; const CHANNEL_INDEX = QUESTIONS.findIndex(q => q.id === "channel"); /* phone mask: +7 (XXX) XXX-XX-XX */ function formatPhoneQ(raw) { const digits = raw.replace(/\D/g, "").slice(0, 11); let d = digits; if (d.length > 0) { if (d[0] === "8") d = "7" + d.slice(1); if (d[0] !== "7") d = "7" + d; d = d.slice(0, 11); } if (d.length === 0) return ""; let out = "+7"; if (d.length > 1) out += " (" + d.slice(1, 4); if (d.length >= 4) out += ") " + d.slice(4, 7); if (d.length >= 7) out += "-" + d.slice(7, 9); if (d.length >= 9) out += "-" + d.slice(9, 11); return out; } /* "@username" or "+7 phone" — Telegram-flexible */ function formatTelegramQ(raw) { const trimmed = raw.trim(); if (trimmed.startsWith("@")) { return "@" + trimmed.slice(1).replace(/[^A-Za-z0-9_]/g, "").slice(0, 32); } if (/^[A-Za-z]/.test(trimmed)) { return "@" + trimmed.replace(/[^A-Za-z0-9_]/g, "").slice(0, 32); } return formatPhoneQ(raw); } /* validation per channel */ function validateContact(channel, value) { const v = (value || "").trim(); if (!v) return "Укажите контакт"; if (channel === 1) { if (v.startsWith("@")) { if (v.length < 6) return "Минимум 5 символов после @"; return null; } if (v.replace(/\D/g, "").length < 11) return "Введите @username или номер полностью"; return null; } if (v.replace(/\D/g, "").length < 11) return "Введите номер полностью"; return null; } function QuizOverlay({ onClose, onOpenPrivacy }) { // 0..3 = questions, 4 = form const [step, setStep] = useStateQ(0); const [answers, setAnswers] = useStateQ({}); const [name, setName] = useStateQ(""); const [contact, setContact] = useStateQ(""); const [err, setErr] = useStateQ({}); const [submitting, setSubmitting] = useStateQ(false); const totalSteps = QUESTIONS.length + 1; // 4 q + form const progress = step >= totalSteps ? 100 : Math.round((step / totalSteps) * 100); const currentQ = step < QUESTIONS.length ? QUESTIONS[step] : null; const currentAnswer = currentQ ? answers[currentQ.id] : null; // selected channel index (0=call, 1=telegram, 2=whatsapp); default = call const channel = answers["channel"] ?? 0; const channelMeta = useMemoQ(() => { if (channel === 1) { return { label: "Telegram", sub: "@username или номер телефона", placeholder: "@username или +7 (___) ___-__-__", inputMode: "text", autocomplete: "off", formatter: formatTelegramQ, }; } if (channel === 2) { return { label: "WhatsApp", sub: "Номер для сообщения в WhatsApp", placeholder: "+7 (___) ___-__-__", inputMode: "tel", autocomplete: "tel", formatter: formatPhoneQ, }; } return { label: "Телефон", sub: "Для звонка в рабочее время", placeholder: "+7 (___) ___-__-__", inputMode: "tel", autocomplete: "tel", formatter: formatPhoneQ, }; }, [channel]); // reset contact value if user goes back and picks another channel useEffectQ(() => { setContact(""); setErr(e => ({ ...e, contact: undefined })); }, [channel]); useEffectQ(() => { function onKey(e) { if (e.key === "Escape") onClose(); if (e.key === "Enter" && currentQ && currentAnswer != null) next(); } window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }); function pick(qid, idx) { setAnswers(a => ({ ...a, [qid]: idx })); setTimeout(() => setStep(s => Math.min(s + 1, totalSteps)), 260); } function next() { if (step < totalSteps) setStep(s => s + 1); } function back() { setStep(s => Math.max(0, s - 1)); } function validate() { const e = {}; if (!name.trim() || name.trim().length < 2) e.name = "Укажите имя"; const cErr = validateContact(channel, contact); if (cErr) e.contact = cErr; setErr(e); return Object.keys(e).length === 0; } function submit() { if (!validate()) return; setSubmitting(true); // Классическая HTML-форма (WAF-friendly): собираем скрытую
и // сабмитим нативно — обычный POST на submit.php, PHP пишет CSV + email // и редиректит на success.html. const form = document.createElement("form"); form.method = "POST"; form.action = "submit.php"; form.style.display = "none"; const addField = (n, v) => { const inp = document.createElement("input"); inp.type = "hidden"; inp.name = n; inp.value = v; form.appendChild(inp); }; addField("source", "offer_page"); addField("name", name.trim()); const trimmedContact = contact.trim(); const isTelegramUsername = channel === 1 && trimmedContact.startsWith("@"); if (isTelegramUsername) { addField("telegram", trimmedContact); addField("phone", ""); // контакт — Telegram-ник, телефона нет } else { const cleanPhone = trimmedContact.replace(/\D/g, ""); addField("phone", cleanPhone); if (channel === 1) addField("telegram", cleanPhone); } document.body.appendChild(form); form.submit(); } return (
e.stopPropagation()}> {/* head */}
{Math.min(step + 1, totalSteps)} / {totalSteps}
{/* body */} {currentQ ? (
Вопрос {step + 1} из {QUESTIONS.length}

{currentQ.title}

{currentQ.options.map((opt, i) => { const checked = currentAnswer === i; return ( ); })}
) : ( /* form step — contact field adapts to chosen channel */
Последний шаг

Оставьте контакт

Свяжемся через {channelMeta.label}{" "} и поделимся информационными материалами по теме рынка золота.

Имя { setName(e.target.value); if (err.name) setErr({...err, name: undefined}); }} placeholder="Как к вам обращаться"/> {err.name && {err.name}}
{channelMeta.label} { setContact(channelMeta.formatter(e.target.value)); if (err.contact) setErr({...err, contact: undefined}); }} placeholder={channelMeta.placeholder}/> {channelMeta.sub} {err.contact && {err.contact}}
Нажимая кнопку, пользователь соглашается с обработкой персональных данных согласно  { e.preventDefault(); onOpenPrivacy && onOpenPrivacy(); }} style={{ color: "var(--ink-2)", borderBottom: "1px solid var(--line)", textDecoration: "none" }}> политике конфиденциальности . Материалы носят информационный характер и не являются индивидуальной инвестиционной рекомендацией.
)} {/* foot */}
{step > 0 && ( )} {currentQ ? ( ) : ( )}
); } /* ───────── Privacy / Terms modal ───────── */ function LegalModal({ kind, onClose }) { useEffectQ(() => { function onKey(e) { if (e.key === "Escape") onClose(); } window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [onClose]); const isPrivacy = kind === "privacy"; return (
e.stopPropagation()} role="dialog" aria-modal="true">
Документ

{isPrivacy ? "Политика конфиденциальности" : "Пользовательское соглашение"}

{isPrivacy ? (

ООО «ГОЛДРА» · ИНН 9705190653 · ОГРН 1237700048850
Редакция от {new Date().getFullYear()} г.

1. Общие положения

Настоящая Политика определяет порядок обработки персональных данных физических лиц (далее — «Пользователь»), оставивших свои контактные данные через сайт ООО «GOLDRA» (далее — «Оператор»), и соответствует требованиям Федерального закона от 27.07.2006 № 152-ФЗ «О персональных данных».

2. Состав обрабатываемых данных

Оператор обрабатывает следующие персональные данные, предоставленные Пользователем добровольно:

  • имя;
  • номер телефона или идентификатор в мессенджере;
  • ответы Пользователя на вопросы опроса.

3. Цели обработки

  • обратная связь с Пользователем по оставленной заявке;
  • подготовка информационных материалов по запросу Пользователя;
  • информирование об услугах Оператора в рамках темы запроса.

4. Правовые основания

Согласие Пользователя, выраженное путём отправки формы; статья 6 ФЗ № 152-ФЗ.

5. Сроки и хранение

Данные хранятся не дольше, чем этого требует цель обработки, но не более 1 года с момента последнего обращения. По истечении срока данные обезличиваются или удаляются.

6. Передача третьим лицам

Оператор не передаёт персональные данные третьим лицам, за исключением случаев, прямо предусмотренных законодательством РФ, а также сервисов, обеспечивающих техническую работу сайта (хостинг, аналитика, IP-телефония) на условиях конфиденциальности.

7. Права Пользователя

Пользователь вправе отозвать согласие, потребовать уточнения, блокировки или удаления своих персональных данных, направив запрос на адрес info@goldra.ru. Запрос рассматривается в срок до 30 дней.

8. Cookies и аналитика

Сайт может использовать файлы cookie и счётчики веб-аналитики для оценки посещаемости. Эти данные обезличены и не позволяют идентифицировать Пользователя без дополнительных сведений.

9. Контакты Оператора

По всем вопросам обработки персональных данных — info@goldra.ru.

10. Информационный дисклеймер

Материалы сайта носят исключительно информационный характер и не являются индивидуальной инвестиционной рекомендацией. Оператор не принимает денежные средства, не осуществляет доверительное управление и не гарантирует получение дохода. Инвестиции связаны с рисками, в том числе с риском потери средств.

) : (

ООО «ГОЛДРА» · ИНН 9705190653 · ОГРН 1237700048850
Редакция от {new Date().getFullYear()} г.

1. Термины

«Сайт» — информационный ресурс ООО «ГОЛДРА». «Пользователь» — физическое лицо, использующее Сайт. «Оператор» — ООО «GOLDRA».

2. Назначение сайта

Сайт предназначен для предоставления информационных и справочных материалов по теме рынка золота и инвестиций. Сайт не является торговой платформой, не осуществляет приём денежных средств и не управляет средствами Пользователей.

3. Информационный характер материалов

Все материалы носят исключительно информационный характер и не являются индивидуальной инвестиционной рекомендацией в смысле Федерального закона № 39-ФЗ «О рынке ценных бумаг». Оператор не гарантирует получение дохода и не несёт ответственности за решения, принятые Пользователем самостоятельно.

4. Использование Сайта

Пользователь обязуется использовать Сайт добросовестно, не нарушать законодательство РФ и права третьих лиц. Запрещены автоматизированный сбор данных, попытки нарушить работу Сайта и иные действия, противоречащие назначению ресурса.

5. Заявки и обратная связь

Отправляя заявку через форму на Сайте, Пользователь подтверждает достоверность указанных данных и соглашается с Политикой конфиденциальности. Оператор связывается с Пользователем для предоставления запрошенных информационных материалов.

6. Ограничение ответственности

Оператор не несёт ответственности за возможные убытки, возникшие у Пользователя в связи с самостоятельным принятием решений на основании информации, размещённой на Сайте. Инвестиции связаны с рисками, в том числе с риском потери средств.

7. Изменения соглашения

Оператор вправе вносить изменения в настоящее Соглашение. Актуальная редакция размещается на Сайте. Продолжая использование Сайта, Пользователь соглашается с действующей редакцией.

8. Контакты

Для связи с Оператором — info@goldra.ru.

)}
); } Object.assign(window, { QuizOverlay, LegalModal });