diff --git a/frontend/components/CalculatorNav.tsx b/frontend/components/CalculatorNav.tsx index 003e612..6fb7698 100644 --- a/frontend/components/CalculatorNav.tsx +++ b/frontend/components/CalculatorNav.tsx @@ -44,11 +44,11 @@ export default function CalculatorNav() { }; return ( -
-

- Выберите калькулятор: +
+

+ 🔄 Переключить калькулятор:

-
+
{calculators.map((calc) => { const isActive = pathname === `/${calc.id}`; @@ -56,19 +56,24 @@ export default function CalculatorNav() { ); })}
+

+ Нажмите на кнопку выше, чтобы переключиться между калькуляторами +

); } diff --git a/frontend/components/CostBlock.tsx b/frontend/components/CostBlock.tsx new file mode 100644 index 0000000..5cb4020 --- /dev/null +++ b/frontend/components/CostBlock.tsx @@ -0,0 +1,24 @@ +// components/CostBlock.tsx +// Блок отображения промежуточной стоимости + +type CostBlockProps = { + title: string; + value: number; + highlight?: boolean; +}; + +export default function CostBlock({ title, value, highlight = false }: CostBlockProps) { + return ( +
+ {title}: {value.toFixed(1)} руб +
+ ); +} + diff --git a/frontend/components/DynamicCalculator.tsx b/frontend/components/DynamicCalculator.tsx index 85c2b9c..a1bfbe9 100644 --- a/frontend/components/DynamicCalculator.tsx +++ b/frontend/components/DynamicCalculator.tsx @@ -9,6 +9,7 @@ import { getCalculator } from '@/lib/calculators'; import { submitCalculator } from '@/lib/api'; import FormField from './FormField'; import CalculatorNav from './CalculatorNav'; +import CostBlock from './CostBlock'; import type { Calculator } from '@/types/calculator'; interface DynamicCalculatorProps { @@ -175,7 +176,21 @@ export default function DynamicCalculator({ calculatorType }: DynamicCalculatorP // Обработка отправки формы const handleSubmit = async (e: FormEvent) => { e.preventDefault(); - if (!chatId) { + + // Получаем chat_id из разных источников + let currentChatId = chatId; + if (!currentChatId && typeof window !== 'undefined') { + const params = new URLSearchParams(window.location.search); + currentChatId = params.get('chat_id'); + if (!currentChatId && typeof Storage !== 'undefined') { + currentChatId = sessionStorage.getItem('chat_id'); + } + if (currentChatId) { + setChatId(currentChatId); + } + } + + if (!currentChatId) { alert('❗ Не найден chat_id. Откройте калькулятор через Telegram-бота.'); return; } @@ -218,7 +233,7 @@ export default function DynamicCalculator({ calculatorType }: DynamicCalculatorP // Отправка на backend const response = await submitCalculator( calculatorType, - chatId, + currentChatId!, submitData, photoFile ); @@ -273,55 +288,141 @@ export default function DynamicCalculator({ calculatorType }: DynamicCalculatorP Калькулятор: {calculator.name}

- {/* Основные поля (без группы) */} - {groupedFields.general && ( -
- {groupedFields.general.map((field) => ( - updateField(field.name, value)} + {/* Специфичная структура для мыла с промежуточными стоимостями */} + {calculator.id === 'soap' && ( + <> + {/* Название мыла */} + f.name === 'soapName')!} + value={formData.soapName || ''} + onChange={(value) => updateField('soapName', value)} + /> + + {/* Фото */} +
+ + {photoFile && ( + Предпросмотр мыла + )} + + {/* Блок «Основа» */} +
+ f.name === 'weight')!} + value={formData.weight || ''} + onChange={(value) => updateField('weight', value)} + /> + f.name === 'basePrice')!} + value={formData.basePrice || ''} + onChange={(value) => updateField('basePrice', value)} + /> +
+ + + {/* Блок «Отдушка» */} +
+ f.name === 'aromaPrice')!} + value={formData.aromaPrice || ''} + onChange={(value) => updateField('aromaPrice', value)} + /> + f.name === 'aromaWeight')!} + value={formData.aromaWeight || ''} + onChange={(value) => updateField('aromaWeight', value)} + /> +
+ + + {/* Блок «Пигмент» */} +
+ f.name === 'pigmentPrice')!} + value={formData.pigmentPrice || ''} + onChange={(value) => updateField('pigmentPrice', value)} + /> + f.name === 'pigmentWeight')!} + value={formData.pigmentWeight || ''} + onChange={(value) => updateField('pigmentWeight', value)} + /> +
+ + + {/* Блок «Форма» */} + f.name === 'moldPrice')!} + value={formData.moldPrice || ''} + onChange={(value) => updateField('moldPrice', value)} + /> + + + {/* Блок «Упаковка» */} +
+ f.name === 'box')!} + value={formData.box || ''} + onChange={(value) => updateField('box', value)} + /> + f.name === 'filler')!} + value={formData.filler || ''} + onChange={(value) => updateField('filler', value)} + /> + f.name === 'ribbon')!} + value={formData.ribbon || ''} + onChange={(value) => updateField('ribbon', value)} + /> + f.name === 'labelValue')!} + value={formData.labelValue || ''} + onChange={(value) => updateField('labelValue', value)} + /> +
+ + + + + {/* Блок «Наценка и цена 100 г» */} +
+ f.name === 'markup')!} + value={formData.markup || ''} + onChange={(value) => updateField('markup', value)} + /> +
+ + + )} - {/* Поля с фото */} - - {photoFile && ( - Предпросмотр - )} - - {/* Группированные поля (например, упаковка) */} - {Object.entries(groupedFields) - .filter(([group]) => group !== 'general') - .map(([group, fields]) => ( -
-

- {group === 'packaging' ? 'Упаковка' : group} -

-
- {fields.map((field) => ( + {/* Универсальная структура для других калькуляторов */} + {calculator.id !== 'soap' && ( + <> + {/* Основные поля (без группы) */} + {groupedFields.general && ( +
+ {groupedFields.general.map((field) => ( ))}
-
- ))} + )} - {/* Блоки с результатами расчёта */} -
- {Object.entries(result) - .filter(([key]) => key !== 'total') - .map(([key, value]) => ( -
- {formatResultLabel(key)}: {value.toFixed(1)} ₽ -
- ))} -
- Итого себестоимость: {result.total.toFixed(1)} ₽ -
-
- Итоговая цена с наценкой: {finalPrice.toFixed(1)} ₽ -
- {weight > 0 && ( -
- Цена за 100 г: {pricePer100g.toFixed(1)} ₽ + {/* Поля с фото */} + + {photoFile && ( + Предпросмотр + )} + + {/* Группированные поля */} + {Object.entries(groupedFields) + .filter(([group]) => group !== 'general') + .map(([group, fields]) => ( +
+

+ {group === 'packaging' ? 'Упаковка' : group} +

+
+ {fields.map((field) => ( + updateField(field.name, value)} + /> + ))} +
+
+ ))} + + {/* Блоки с результатами расчёта */} +
+ {Object.entries(result) + .filter(([key]) => key !== 'total') + .map(([key, value]) => ( + + ))} + + + {weight > 0 && ( + + )}
- )} -
+ + )} {/* Кнопка отправки */}