/* global React, ReactDOM, Header, Footer, HomePage, CatalogPage, DeliveryPage, ContactsPage, TweaksPanel, TweakSection, TweakRadio, TweakColor, useTweaks */ const { useState, useEffect } = React; const DEFAULTS = /*EDITMODE-BEGIN*/{ "palette": ["#0b1a2e", "#1f4b8e", "#f6a623"], "gridCols": "3" }/*EDITMODE-END*/; // Palettes — each provides primary blue family + accent. // Identified by the swatch array (first hex); TweakColor stores the array as value. const PALETTES = [ { label: 'Cobalt + Amber', swatches: ['#0b1a2e', '#1f4b8e', '#f6a623'], vars: { '--deep': '#0b1a2e', '--deep-2': '#102544', '--mid': '#1f4b8e', '--mid-2': '#2b6ed0', '--soft': '#eaf1fb', '--amber': '#f6a623', '--amber-2': '#d98f12', }, }, { label: 'Graphite + Copper', swatches: ['#171a1e', '#2f3640', '#e07a39'], vars: { '--deep': '#171a1e', '--deep-2': '#23272f', '--mid': '#2f3640', '--mid-2': '#4a5260', '--soft': '#eef0f2', '--amber': '#e07a39', '--amber-2': '#b85f25', }, }, { label: 'Steel + Saffron', swatches: ['#1a2638', '#3a5a7a', '#e8a73a'], vars: { '--deep': '#1a2638', '--deep-2': '#243349', '--mid': '#3a5a7a', '--mid-2': '#5078a0', '--soft': '#edf3f7', '--amber': '#e8a73a', '--amber-2': '#c08620', }, }, { label: 'Forge + Rust', swatches: ['#0f1a14', '#1f4338', '#d2502a'], vars: { '--deep': '#0f1a14', '--deep-2': '#162b22', '--mid': '#1f4338', '--mid-2': '#2e6555', '--soft': '#ebf2ee', '--amber': '#d2502a', '--amber-2': '#a83d1c', }, }, ]; function findPalette(value) { if (!Array.isArray(value)) return PALETTES[0]; return PALETTES.find(p => p.swatches[0].toLowerCase() === value[0].toLowerCase()) || PALETTES[0]; } function applyPalette(value) { const p = findPalette(value); const root = document.documentElement; Object.entries(p.vars).forEach(([k, v]) => root.style.setProperty(k, v)); } function App() { const [page, setPage] = useState(() => { const h = (window.location.hash || '').replace('#', ''); return ['home', 'catalog', 'delivery', 'contacts'].includes(h) ? h : 'home'; }); const [tweaks, setTweak] = useTweaks(DEFAULTS); // SEO: обновляем title и meta description при смене страницы useEffect(() => { const SEO = { home: { title: 'Метизы оптом в Красноярске и крае — болты, гайки, крепёж | СтройТехноУниверсал', desc: 'Оптовые поставки метизов в Красноярске: болты, гайки, шайбы, анкеры, дюбели, саморезы. Более 5000 позиций на складе. Отгрузка в день заказа. Доставка по всему Красноярскому краю. НДС, сертификаты, работа с юрлицами и ИП.' }, catalog: { title: 'Каталог метизов и крепежа оптом в Красноярске — СтройТехноУниверсал', desc: 'Полный каталог метизов оптом: болты, гайки, шайбы, шпильки, анкеры, дюбели, саморезы, заклёпки, сетка, цепи. DIN, ГОСТ, классы прочности 4.8–12.9. Нержавеющий крепёж А2/А4. Склад в Красноярске.' }, delivery: { title: 'Доставка метизов по Красноярску и Красноярскому краю — СтройТехноУниверсал', desc: 'Доставка метизов оптом: самовывоз со склада в Красноярске, доставка по городу собственным транспортом, отгрузка в Норильск, Канск, Ачинск, Лесосибирск через ПЭК, СДЭК, Деловые Линии. Оплата безнал с НДС и наличными.' }, contacts: { title: 'Контакты и реквизиты СтройТехноУниверсал — метизы оптом в Красноярске', desc: 'Контакты оптового поставщика метизов в Красноярске: телефон +7 (391) 215-30-02, WhatsApp, адрес склада ул. Сопочная 36. Реквизиты ООО СтройТехноУниверсал: ИНН 2463121704, ОГРН 1203400019513.' }, }; const s = SEO[page] || SEO.home; document.title = s.title; // Отправляем хит в Яндекс.Метрику при смене страницы if (typeof window.ym === 'function') { window.ym(109421325, 'hit', window.location.href, { title: s.title }); } let metaDesc = document.querySelector('meta[name="description"]'); if (!metaDesc) { metaDesc = document.createElement('meta'); metaDesc.name = 'description'; document.head.appendChild(metaDesc); } metaDesc.content = s.desc; }, [page]); // Apply palette on change useEffect(() => { applyPalette(tweaks.palette); }, [tweaks.palette]); // hash routing const navigate = (p) => { setPage(p); history.replaceState(null, '', `#${p}`); window.scrollTo({ top: 0, behavior: 'instant' }); }; useEffect(() => { const onHash = () => { const h = (window.location.hash || '').replace('#', ''); if (['home', 'catalog', 'delivery', 'contacts'].includes(h)) setPage(h); }; window.addEventListener('hashchange', onHash); return () => window.removeEventListener('hashchange', onHash); }, []); const PageComp = { home: , catalog: , delivery: , contacts: , }[page]; return (
{PageComp}
setTweak('palette', v)} options={PALETTES.map(p => p.swatches)} /> setTweak('gridCols', v)} options={['3', '4', 'list']} />
); } const root = ReactDOM.createRoot(document.getElementById('root')); root.render();