// Interactive price calculator const { useState, useMemo } = React; function Calculator() { const [partId, setPartId] = useState('val'); const [matId, setMatId] = useState('st45'); const [method, setMethod] = useState('stamp'); const [qty, setQty] = useState(10); const [dims, setDims] = useState({ L: 2000, D: 180, d: 140, B: 100, H: 60 }); const part = PART_TYPES.find((p) => p.id === partId); const mat = MATERIALS.find((m) => m.id === matId); // when part changes, reset dims to its placeholders React.useEffect(() => { setDims((d) => ({ ...d, ...part.placeholders })); }, [partId]); // eslint-disable-line const calc = useMemo(() => { // volume in mm³ → cm³ const vol_mm3 = part.volume(dims); const vol_cm3 = vol_mm3 / 1000; // mass in kg const mass_kg = (vol_cm3 * STEEL_DENSITY) / 1000; // price per unit const unit_price = mass_kg * BASE_PRICE_PER_KG * mat.mult * METHOD_MULT[method] * QTY_DISCOUNT(qty); // total const total = unit_price * qty; // band const low = total * (1 - ESTIMATE_BAND); const high = total * (1 + ESTIMATE_BAND); // sanity const valid = mass_kg > 0 && mass_kg <= 1250 && qty >= 1; let warning = null; if (mass_kg > 1250) warning = 'Превышен максимальный вес 1 250 кг — свяжитесь с нами для индивидуального расчёта.'; else if (mass_kg < 0.3) warning = 'Минимальный вес заготовки — 0,3 кг.'; return { mass_kg, unit_price, total, low, high, valid, warning }; }, [partId, matId, method, qty, dims, part]); const fmt = (n) => { if (!isFinite(n) || n <= 0) return '—'; return Math.round(n).toLocaleString('ru-RU').replace(/,/g, ' '); }; const setDim = (k, v) => setDims((d) => ({ ...d, [k]: Math.max(0, Number(v) || 0) })); const partIcon = (p) => p.drawing; return (
04 Калькулятор

Рассчитайте
стоимость поковки

Укажите тип детали, размеры, материал и тираж — мы покажем ориентировочный диапазон цены за партию. Точная стоимость с учётом оснастки, термообработки и логистики — после вашей заявки.

{/* ── FORM ── */}
{/* Part type */}
01 / Тип детали {part.name}
{PART_TYPES.map((p) => ( ))}
{/* Dimensions */}
02 / Размеры, мм {part.fields.map((f) => `${f}=${dims[f] || '—'}`).join(' · ')}
{part.fields.map((f) => { const [min, max] = part.limits[f]; return (
{f} · {min}–{max} setDim(f, e.target.value)} />
); })}
{/* Material */}
03 / Материал {mat.name}
{MATERIALS.map((m) => ( ))}
{/* Method */}
04 / Метод {method === 'stamp' ? 'Горячая штамповка' : 'Свободная ковка'}
{/* Quantity */}
05 / Тираж {qty} шт{' '} {QTY_DISCOUNT(qty) < 1 && ( · скидка −{Math.round((1 - QTY_DISCOUNT(qty)) * 100)}% )}
setQty(Math.max(1, Number(e.target.value) || 1))} />
{[1, 5, 10, 50, 100].map((n) => ( ))}
{/* ── RESULT ── */}
Расчёт В реальном времени
Расчётный вес единицы:{' '} {calc.mass_kg > 0 ? calc.mass_kg.toFixed(calc.mass_kg < 10 ? 2 : 1) : '—'} кг
Цена за единицу:{' '} {fmt(calc.unit_price)} ₽
Ориентировочная стоимость партии
{calc.valid ? ( <> {fmt(calc.low)}{fmt(calc.high)} ) : ( )}
{calc.warning ? ( {calc.warning} ) : ( <> Расчёт ориентировочный. Точная стоимость, скидки и сроки — по запросу. Оставьте сообщение в форме ниже, и мы пришлём коммерческое предложение в течение рабочего дня. )}
Объём{fmt(part.volume(dims) / 1000)} см³
Материал{mat.name} · ×{mat.mult.toFixed(2)}
Метод{method === 'stamp' ? 'Штамповка' : 'Ковка'} · ×{METHOD_MULT[method].toFixed(2)}
Тираж{qty} шт · ×{QTY_DISCOUNT(qty).toFixed(2)}
Получить точное КП +7 (4912) 93-27-71
); } window.Calculator = Calculator;