From 58a2e0468fb951e3c7296c84316939be3b737a2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A5=D0=B0=D0=BB=D0=B8=D0=BC=D0=BE=D0=B2=20=D0=A0=D1=83?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D0=BC?= Date: Mon, 12 Jan 2026 00:13:32 +0300 Subject: [PATCH] Fix config view --- src/components/ConfigStep.tsx | 263 ++++++++++++++++++++++++---------- 1 file changed, 188 insertions(+), 75 deletions(-) diff --git a/src/components/ConfigStep.tsx b/src/components/ConfigStep.tsx index ca2950d..b71989e 100644 --- a/src/components/ConfigStep.tsx +++ b/src/components/ConfigStep.tsx @@ -1,6 +1,6 @@ -import React, { useEffect, useRef } from 'react'; +import React, { useEffect } from 'react'; import { AppConfig, PerforationPattern } from '../types'; -import { Settings2, Grid, Circle, Triangle, Hexagon, LayoutGrid } from 'lucide-react'; +import { Settings2, Box, Ruler, LayoutGrid, Circle, Hexagon, Triangle, Scan } from 'lucide-react'; interface Props { config: AppConfig; @@ -9,17 +9,17 @@ interface Props { export const ConfigStep: React.FC = ({ config, onChange }) => { - // Инициализация дефолтных значений, если их нет + // Инициализация дефолтных значений перфорации useEffect(() => { if (!config.perforation) { onChange({ ...config, - perforation: { enabled: false, pattern: 'hexagon', diameter: 8, spacing: 4 } + perforation: { enabled: false, pattern: 'hexagon', diameter: 8, spacing: 2 } }); } }, []); - const perf = config.perforation || { enabled: false, pattern: 'hexagon', diameter: 8, spacing: 4 }; + const perf = config.perforation || { enabled: false, pattern: 'hexagon', diameter: 8, spacing: 2 }; const updatePerf = (updates: Partial) => { onChange({ ...config, perforation: { ...perf, ...updates } }); @@ -29,41 +29,46 @@ export const ConfigStep: React.FC = ({ config, onChange }) => { onChange({ ...config, drawer: { ...config.drawer, [key]: value } }); }; - // --- RENDER PREVIEW (SVG) --- + // --- RENDER PREVIEW --- const renderPreview = () => { if (!perf.enabled) return
Перфорация выключена
; const size = perf.diameter; - const gap = Math.max(2, perf.spacing); // Минимальный зазор 2мм + const gap = Math.max(2, perf.spacing); const step = size + gap; - const W = 140; - const H = 100; + const W = 200; + const H = 120; const elements = []; - const rows = Math.floor(H / (step * 0.866)); // 0.866 для сот (sin 60) + // Приблизительный расчет для превью + const rows = Math.floor(H / (step * 0.866)); const cols = Math.floor(W / step); + const startX = (W - (cols * step)) / 2; + const startY = (H - (rows * step * 0.866)) / 2; + for(let j=0; j W - 10 || y > H - 10) continue; + if (x > W - size || y > H - size) continue; + + const color = "#3b82f6"; if (perf.pattern === 'circle') { - elements.push(); + elements.push(); } else if (perf.pattern === 'hexagon') { - // Рисуем шестиугольник const r = size / 2; const points = []; for (let k = 0; k < 6; k++) { const angle = (k * 60 + 30) * Math.PI / 180; points.push(`${x + r * Math.cos(angle)},${y + r * Math.sin(angle)}`); } - elements.push(); + elements.push(); } else if (perf.pattern === 'triangle') { const r = size / 2; const angleOffset = isOdd ? 180 : 0; @@ -72,100 +77,208 @@ export const ConfigStep: React.FC = ({ config, onChange }) => { const angle = (k * 120 - 90 + angleOffset) * Math.PI / 180; points.push(`${x + r * Math.cos(angle)},${y + r * Math.sin(angle)}`); } - elements.push(); + elements.push(); } } } return ( - + {elements} ); }; return ( -
- {/* 1. ГАБАРИТЫ */} -
-

1. Размеры ящика

-
-
- - updateDrawer('width', parseFloat(e.target.value))} className="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white focus:ring-2 focus:ring-primary outline-none mt-1"/> -
-
- - updateDrawer('depth', parseFloat(e.target.value))} className="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white focus:ring-2 focus:ring-primary outline-none mt-1"/> -
-
- - updateDrawer('height', parseFloat(e.target.value))} className="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white focus:ring-2 focus:ring-primary outline-none mt-1"/> -
-
-
+
+ + {/* ВЕРХНИЙ БЛОК: Размеры и Параметры печати */} +
+ + {/* 1. РАЗМЕРЫ */} +
+

+ 1. Размеры +

+ +
+
+

Внутренние размеры ящика

+
+
+ +
+ updateDrawer('width', parseFloat(e.target.value))} className="w-full bg-slate-800 border border-slate-700 rounded-lg pl-4 pr-12 py-2.5 text-white focus:ring-2 focus:ring-blue-500/50 outline-none transition-all font-mono"/> + MM +
+
+
+ +
+ updateDrawer('depth', parseFloat(e.target.value))} className="w-full bg-slate-800 border border-slate-700 rounded-lg pl-4 pr-12 py-2.5 text-white focus:ring-2 focus:ring-blue-500/50 outline-none transition-all font-mono"/> + MM +
+
+
+ +
+ updateDrawer('height', parseFloat(e.target.value))} className="w-full bg-slate-800 border border-slate-700 rounded-lg pl-4 pr-12 py-2.5 text-white focus:ring-2 focus:ring-blue-500/50 outline-none transition-all font-mono"/> + MM +
+
+
+
+
+
- {/* 2. ПЕРФОРАЦИЯ */} -
-
-

2. Перфорация (узоры)

-
- {perf.enabled ? 'Включено' : 'Выключено'} + {/* 2. ПАРАМЕТРЫ ПЕЧАТИ */} +
+

+ Параметры печати +

+ +
+ + {/* Wall Thickness */} +
+
+ Толщина стенок + {config.wallThickness} мм +
+ onChange({...config, wallThickness: parseFloat(e.target.value)})} + className="w-full h-1.5 bg-slate-700 rounded-lg appearance-none cursor-pointer accent-blue-500" + /> +
+ 0.84.0 +
+
+ + {/* Corner Radius */} +
+
+ Радиус скругления + {config.cornerRadius} мм +
+ onChange({...config, cornerRadius: parseFloat(e.target.value)})} + className="w-full h-1.5 bg-slate-700 rounded-lg appearance-none cursor-pointer accent-purple-500" + /> +
+ 020 +
+
+ + {/* Tolerance */} +
+
+ Зазор (Tolerance) + {config.printerTolerance} мм +
+ onChange({...config, printerTolerance: parseFloat(e.target.value)})} + className="w-full h-1.5 bg-slate-700 rounded-lg appearance-none cursor-pointer accent-yellow-500" + /> +
+ 0.01.0 +
+
+ +
+
+
+ + {/* НИЖНИЙ БЛОК: ПЕРФОРАЦИЯ */} +
+
+

+ 2. Перфорация (узоры) +

+
+ {perf.enabled ? 'Включено' : 'Выключено'}
-
- {/* Controls */} -
+
+ {/* Настройки */} +
+ + {/* Тип узора */}
- -
- - - + +
+ + +
-
+ {/* Ползунки параметров */} +
+ {/* Diameter */}
- - updatePerf({ diameter: Math.min(12, parseFloat(e.target.value)) })} className="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white mt-1"/> +
+ Диаметр отверстий + {perf.diameter} мм +
+ updatePerf({ diameter: parseFloat(e.target.value) })} + className="w-full h-1.5 bg-slate-700 rounded-lg appearance-none cursor-pointer accent-blue-500" + /> +
+ 2 мм12 мм +
+ + {/* Spacing */}
- - updatePerf({ spacing: Math.max(2, parseFloat(e.target.value)) })} className="w-full bg-slate-800 border border-slate-700 rounded-lg px-3 py-2 text-white mt-1"/> +
+ Зазор (между отверстиями) + {perf.spacing} мм +
+ updatePerf({ spacing: parseFloat(e.target.value) })} + className="w-full h-1.5 bg-slate-700 rounded-lg appearance-none cursor-pointer accent-blue-500" + /> +
+ 2 мм10 мм +
{/* Preview */} -
- Предпросмотр - {renderPreview()} +
+
+ + Масштаб условен +
+
+
+ {renderPreview()} +
+
- {/* 3. ПРОЧЕЕ */} -
-

Дополнительно

-
-
- - onChange({...config, wallThickness: parseFloat(e.target.value)})} className="bg-slate-800 border border-slate-700 rounded px-2 py-1 text-sm w-20 text-gray-300"/> -
-
- - onChange({...config, cornerRadius: parseFloat(e.target.value)})} className="bg-slate-800 border border-slate-700 rounded px-2 py-1 text-sm w-20 text-gray-300"/> -
-
-
); }; \ No newline at end of file