feat: estimator reads prices from DB via usePricing
This commit is contained in:
@@ -1,20 +1,21 @@
|
||||
import React, { useState } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { Calculator } from 'lucide-react';
|
||||
import { usePricing } from '../hooks/usePricing';
|
||||
|
||||
const Estimator = () => {
|
||||
const [area, setArea] = useState(20); // in sq meters
|
||||
const [area, setArea] = useState(20);
|
||||
const [thickness, setThickness] = useState(200);
|
||||
const { prices, loading: pricesLoading } = usePricing();
|
||||
|
||||
// Цены за квадратный метр в зависимости от толщины пленки
|
||||
const costPerSqM = thickness === 200 ? 2000 : 3000;
|
||||
const costPerSqM = prices[thickness] ?? (thickness === 200 ? 2000 : 3000);
|
||||
const estimatedCost = area * costPerSqM;
|
||||
|
||||
return (
|
||||
<section id="estimator" style={{ backgroundColor: 'var(--bg-lighter)' }}>
|
||||
<div className="container">
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '50px', alignItems: 'center' }}>
|
||||
|
||||
|
||||
<div style={{ flex: '1 1 400px' }}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: -50 }}
|
||||
@@ -28,19 +29,19 @@ const Estimator = () => {
|
||||
<p style={{ color: 'var(--text-muted)', fontSize: '1.2rem', marginBottom: '40px', lineHeight: '1.6' }}>
|
||||
Рассчитайте примерную стоимость обеспечения безопасности вашего периметра. Окончательная стоимость определяется после профессионального осмотра объекта.
|
||||
</p>
|
||||
|
||||
|
||||
<div className="glass-panel" style={{ padding: '40px' }}>
|
||||
<div style={{ marginBottom: '35px' }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '15px' }}>
|
||||
<label style={{ fontWeight: 600, color: 'var(--text-main)', fontSize: '1.1rem' }}>Толщина пленки</label>
|
||||
</div>
|
||||
<select
|
||||
value={thickness}
|
||||
<select
|
||||
value={thickness}
|
||||
onChange={(e) => setThickness(parseInt(e.target.value))}
|
||||
style={{
|
||||
width: '100%', padding: '12px',
|
||||
background: 'var(--bg-lighter)',
|
||||
border: '2px solid var(--border-light)',
|
||||
style={{
|
||||
width: '100%', padding: '12px',
|
||||
background: 'var(--bg-lighter)',
|
||||
border: '2px solid var(--border-light)',
|
||||
borderRadius: '8px',
|
||||
color: 'var(--text-main)',
|
||||
fontSize: '1rem',
|
||||
@@ -48,8 +49,8 @@ const Estimator = () => {
|
||||
cursor: 'pointer'
|
||||
}}
|
||||
>
|
||||
<option value={200}>200 микрон (от 2000 ₽/м²)</option>
|
||||
<option value={300}>300 микрон (от 3000 ₽/м²)</option>
|
||||
<option value={200}>200 микрон (от {prices[200].toLocaleString('ru-RU')} ₽/м²)</option>
|
||||
<option value={300}>300 микрон (от {prices[300].toLocaleString('ru-RU')} ₽/м²)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -58,12 +59,12 @@ const Estimator = () => {
|
||||
<label style={{ fontWeight: 600, color: 'var(--text-main)', fontSize: '1.1rem' }}>Общая площадь (м²)</label>
|
||||
<span className="text-accent-blue" style={{ fontWeight: '800', fontSize: '1.2rem' }}>{area}</span>
|
||||
</div>
|
||||
<input
|
||||
type="range"
|
||||
min="5"
|
||||
max="500"
|
||||
<input
|
||||
type="range"
|
||||
min="5"
|
||||
max="500"
|
||||
step="5"
|
||||
value={area}
|
||||
value={area}
|
||||
onChange={(e) => setArea(parseInt(e.target.value))}
|
||||
style={{ width: '100%', accentColor: 'var(--accent-blue)', height: '8px', borderRadius: '4px' }}
|
||||
/>
|
||||
@@ -79,8 +80,8 @@ const Estimator = () => {
|
||||
transition={{ duration: 0.6, delay: 0.2, type: "spring" }}
|
||||
viewport={{ once: true }}
|
||||
className="glass-panel"
|
||||
style={{
|
||||
padding: '50px',
|
||||
style={{
|
||||
padding: '50px',
|
||||
textAlign: 'center',
|
||||
border: '2px solid rgba(14, 165, 233, 0.2)',
|
||||
boxShadow: '0 20px 50px rgba(14, 165, 233, 0.1)'
|
||||
@@ -92,20 +93,20 @@ const Estimator = () => {
|
||||
>
|
||||
<Calculator size={56} className="text-accent-blue" style={{ margin: '0 auto 25px' }} />
|
||||
</motion.div>
|
||||
|
||||
|
||||
<h3 style={{ fontSize: '1.3rem', color: 'var(--text-muted)', marginBottom: '15px' }}>Ориентировочная стоимость</h3>
|
||||
<div style={{ fontSize: '3.8rem', fontWeight: 800, fontFamily: 'var(--font-heading)', color: 'var(--text-main)', marginBottom: '20px' }}>
|
||||
{estimatedCost.toLocaleString('ru-RU')} ₽
|
||||
{pricesLoading ? '...' : estimatedCost.toLocaleString('ru-RU')} ₽
|
||||
</div>
|
||||
<p style={{ fontSize: '1rem', color: 'var(--text-muted)', marginBottom: '35px', lineHeight: '1.6' }}>
|
||||
Включает бронематериалы, специализированный монтаж и финальную проверку.
|
||||
</p>
|
||||
|
||||
<motion.a
|
||||
|
||||
<motion.a
|
||||
whileHover={{ scale: 1.05 }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
href="#contact"
|
||||
className="btn-primary"
|
||||
href="#contact"
|
||||
className="btn-primary"
|
||||
style={{ display: 'block', width: '100%', textAlign: 'center' }}
|
||||
>
|
||||
Запросить точный расчет
|
||||
|
||||
Reference in New Issue
Block a user