import React, { useState, useEffect } from 'react'; import { Building, District } from '../../types'; import { backendApi } from '../../services/apiClient'; import { Calculator, Equal, Ruler, Edit3 } from 'lucide-react'; interface InvoiceDistributionProps { purposeType: 'building' | 'district'; selectedBuildingIds: string[]; selectedDistrictIds: string[]; totalAmount: number; distributionMethod: 'equal' | 'by_area' | 'manual' | null; distributionData: Record; onDistributionChange: (method: 'equal' | 'by_area' | 'manual', data: Record) => void; } export const InvoiceDistribution: React.FC = ({ purposeType, selectedBuildingIds, selectedDistrictIds, totalAmount, distributionMethod, distributionData, onDistributionChange }) => { const [buildings, setBuildings] = useState([]); const [districts, setDistricts] = useState([]); const [loading, setLoading] = useState(true); const [method, setMethod] = useState<'equal' | 'by_area' | 'manual'>(distributionMethod || 'equal'); const [manualAmounts, setManualAmounts] = useState>(distributionData || {}); useEffect(() => { fetchData(); }, []); useEffect(() => { if (method && totalAmount > 0) { calculateDistribution(); } }, [method, totalAmount, selectedBuildingIds, selectedDistrictIds, buildings]); const fetchData = async () => { try { setLoading(true); const [buildingsData, districtsData] = await Promise.all([ backendApi.getBuildings(), backendApi.getDistricts() ]); setBuildings(buildingsData); setDistricts(districtsData); } catch (err) { console.error('Error fetching data:', err); } finally { setLoading(false); } }; const calculateDistribution = () => { if (method === 'equal') { const items = purposeType === 'building' ? selectedBuildingIds : selectedDistrictIds; const count = items.length; if (count === 0) return; const amountPerItem = totalAmount / count; const rounded = Math.floor(amountPerItem * 100) / 100; const remainder = totalAmount - (rounded * count); const data: Record = {}; items.forEach((id, index) => { data[id] = rounded + (index === 0 ? remainder : 0); }); onDistributionChange('equal', data); setManualAmounts(data); } else if (method === 'by_area' && purposeType === 'building') { // Распределение по площади const selectedBuildings = buildings.filter(b => selectedBuildingIds.includes(b.id)); const totalArea = selectedBuildings.reduce((sum, b) => { const area = b.passport?.general?.totalArea || 0; return sum + area; }, 0); if (totalArea === 0) { // Если площади нет, распределяем поровну calculateDistribution(); return; } const data: Record = {}; selectedBuildings.forEach(building => { const area = building.passport?.general?.totalArea || 0; const proportion = area / totalArea; data[building.id] = Math.round(totalAmount * proportion * 100) / 100; }); // Корректируем остаток на первый элемент const sum = Object.values(data).reduce((s, v) => s + v, 0); const remainder = totalAmount - sum; if (remainder !== 0 && selectedBuildings.length > 0) { data[selectedBuildings[0].id] = (data[selectedBuildings[0].id] || 0) + remainder; } onDistributionChange('by_area', data); setManualAmounts(data); } else if (method === 'manual') { // Для ручного ввода просто обновляем данные onDistributionChange('manual', manualAmounts); } }; const handleManualAmountChange = (id: string, amount: number) => { const newAmounts = { ...manualAmounts, [id]: amount }; setManualAmounts(newAmounts); onDistributionChange('manual', newAmounts); }; const getItemName = (id: string): string => { if (purposeType === 'building') { const building = buildings.find(b => b.id === id); return building?.passport?.address || id; } else { const district = districts.find(d => d.id === id); return district?.name || id; } }; const getItemArea = (id: string): number => { if (purposeType === 'building') { const building = buildings.find(b => b.id === id); return building?.passport?.general?.totalArea || 0; } return 0; }; if (loading) { return
Загрузка...
; } const items = purposeType === 'building' ? selectedBuildingIds : selectedDistrictIds; const currentSum = Object.values(manualAmounts).reduce((sum, val) => sum + val, 0); const difference = totalAmount - currentSum; return (

Распределение суммы

{/* Выбор метода распределения */}
{purposeType === 'building' && ( )}
{/* Таблица распределения */}
{items.map(id => (

{getItemName(id)}

{method === 'by_area' && purposeType === 'building' && (

Площадь: {getItemArea(id).toLocaleString('ru-RU')} м²

)}
{ const value = parseFloat(e.target.value) || 0; handleManualAmountChange(id, value); }} disabled={method !== 'manual'} className="w-32 px-2 py-1 text-sm border border-slate-300 rounded focus:outline-none focus:ring-2 focus:ring-primary-500 disabled:bg-slate-100 disabled:text-slate-500" step="0.01" min="0" />
))}
{/* Итого и разница */}
Итого распределено: {currentSum.toLocaleString('ru-RU', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} ₽
Общая сумма: {totalAmount.toLocaleString('ru-RU', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} ₽
{Math.abs(difference) > 0.01 && (
0 ? 'text-red-600' : 'text-emerald-600' }`}> Разница: {difference > 0 ? '+' : ''}{difference.toLocaleString('ru-RU', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} ₽
)}
); };