Files
mkd/components/legal/ComplianceCheck.tsx

852 lines
48 KiB
TypeScript
Raw Permalink Normal View History

2026-02-04 00:17:04 +05:00
import React, { useState } from 'react';
// FIX: Added missing ChevronRight import
import { Search, ShieldCheck, AlertTriangle, Info, ShieldAlert, CheckCircle2, History, ChevronRight, Loader2, X, FileText, Phone, Mail } from 'lucide-react';
import { authFetch } from '../../services/apiClient';
interface LicenseItem {
number?: string;
series?: string;
validFrom?: number;
validTo?: number;
activities?: string[];
issueAuthority?: string;
}
interface CounterpartyCheckResult {
inn: string;
kpp?: string;
ogrn?: string;
name: string;
shortName?: string;
type: string;
status: string;
registrationDate?: string;
liquidationDate?: string;
address?: string;
okved?: string;
okveds?: any[];
management?: {
name: string;
post?: string;
};
finance?: {
taxSystem?: string;
income?: number;
revenue?: number;
expense?: number;
debt?: number;
penalty?: number;
year?: number;
};
authorities?: any;
phones?: any[];
emails?: any[];
employeeCount?: number;
capital?: { type?: string; value?: number };
smb?: { category?: string; issueDate?: number };
licenses?: LicenseItem[];
addressInvalidity?: any;
foundersInvalidity?: Array<{ name?: string; invalidity?: any }>;
managersInvalidity?: Array<{ name?: string; post?: string; invalidity?: any }>;
managementDisqualified?: boolean;
riskLevel: 'low' | 'medium' | 'high';
riskReasons: string[];
checkedDate: string;
rawData?: any;
}
export const ComplianceCheck: React.FC = () => {
const [inn, setInn] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [checkResult, setCheckResult] = useState<CounterpartyCheckResult | null>(null);
const [checkedCounterparties, setCheckedCounterparties] = useState<any[]>([]);
const [loadingHistory, setLoadingHistory] = useState(true);
const [selectedReport, setSelectedReport] = useState<any | null>(null);
const [showReportModal, setShowReportModal] = useState(false);
// Загружаем историю проверок при монтировании компонента
React.useEffect(() => {
loadHistory();
}, []);
const loadHistory = async () => {
try {
setLoadingHistory(true);
const response = await authFetch('/api/legal/counterparties');
if (response.ok) {
const data = await response.json();
setCheckedCounterparties(data);
}
} catch (error) {
console.error('Error loading history:', error);
} finally {
setLoadingHistory(false);
}
};
const handleCheck = async () => {
if (!inn.trim()) {
setError('Введите ИНН организации');
return;
}
setLoading(true);
setError(null);
setCheckResult(null);
try {
const response = await authFetch('/api/legal/check-counterparty', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ inn: inn.trim() })
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error || 'Ошибка при проверке контрагента');
}
const result = await response.json();
setCheckResult(result);
// Обновляем историю проверок
await loadHistory();
} catch (err) {
console.error('Error checking counterparty:', err);
setError(err instanceof Error ? err.message : 'Ошибка при проверке контрагента');
} finally {
setLoading(false);
}
};
const handleKeyPress = (e: React.KeyboardEvent) => {
if (e.key === 'Enter') {
handleCheck();
}
};
return (
<div className="space-y-6 animate-fade-in">
{/* Search Tool */}
<div className="bg-slate-900 rounded-[2.5rem] p-8 text-white shadow-xl relative overflow-hidden">
<ShieldCheck className="absolute -bottom-4 -right-4 w-48 h-48 opacity-10 rotate-12" />
<div className="relative z-10 max-w-lg">
<h3 className="text-2xl font-black mb-2">Проверка контрагента</h3>
<p className="text-xs text-slate-400 font-medium mb-6">Автоматическая сверка по базам ФНС через DaData API.</p>
<div className="flex gap-2">
<input
type="text"
placeholder="Введите ИНН организации (10 или 12 цифр)..."
value={inn}
onChange={(e) => {
setInn(e.target.value.replace(/\D/g, ''));
setError(null);
}}
onKeyPress={handleKeyPress}
className="flex-1 px-5 py-3 bg-white/10 border border-white/20 rounded-2xl text-sm outline-none focus:ring-2 focus:ring-primary-500 transition-all placeholder:text-slate-500"
maxLength={12}
/>
<button
onClick={handleCheck}
disabled={loading || !inn.trim()}
className="bg-white text-slate-900 px-6 py-3 rounded-2xl font-black text-xs uppercase tracking-widest hover:bg-slate-100 transition-all active:scale-95 shadow-lg disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
>
{loading ? (
<>
<Loader2 className="w-4 h-4 animate-spin" />
Проверка...
</>
) : (
'Проверить'
)}
</button>
</div>
{error && (
<div className="mt-4 p-3 bg-red-500/20 border border-red-500/50 rounded-xl text-red-200 text-sm">
{error}
</div>
)}
</div>
</div>
{/* Check Result */}
{checkResult && (
<div className="bg-white rounded-[2rem] border border-slate-200 shadow-lg p-6">
<div className="flex justify-between items-start mb-4">
<div className="flex items-center gap-4">
<div className={`p-4 rounded-2xl ${
checkResult.riskLevel === 'high' ? 'bg-red-50 text-red-600' :
checkResult.riskLevel === 'medium' ? 'bg-amber-50 text-amber-600' :
'bg-emerald-50 text-emerald-600'
}`}>
{checkResult.riskLevel === 'high' ? <ShieldAlert className="w-7 h-7" /> :
checkResult.riskLevel === 'medium' ? <AlertTriangle className="w-7 h-7" /> :
<CheckCircle2 className="w-7 h-7" />}
</div>
<div>
<h4 className="font-black text-slate-800 text-lg leading-tight">{checkResult.name}</h4>
<p className="text-xs text-slate-500 mt-1">
ИНН: {checkResult.inn}
{checkResult.kpp && ` • КПП: ${checkResult.kpp}`}
{checkResult.ogrn && ` • ОГРН: ${checkResult.ogrn}`}
</p>
</div>
</div>
<button
onClick={() => setCheckResult(null)}
className="p-2 text-slate-400 hover:text-slate-600"
>
<X className="w-5 h-5" />
</button>
</div>
<div className="space-y-4">
{/* Risk Level */}
<div className={`p-4 rounded-xl border-2 ${
checkResult.riskLevel === 'high' ? 'bg-red-50 border-red-200' :
checkResult.riskLevel === 'medium' ? 'bg-amber-50 border-amber-200' :
'bg-emerald-50 border-emerald-200'
}`}>
<div className="flex items-center justify-between mb-2">
<span className="text-sm font-black text-slate-800">Уровень риска:</span>
<span className={`text-sm font-black uppercase ${
checkResult.riskLevel === 'high' ? 'text-red-600' :
checkResult.riskLevel === 'medium' ? 'text-amber-600' :
'text-emerald-600'
}`}>
{checkResult.riskLevel === 'high' ? 'Высокий риск' :
checkResult.riskLevel === 'medium' ? 'Средний риск' :
'Благонадежен'}
</span>
</div>
{checkResult.riskReasons.length > 0 && (
<ul className="text-xs text-slate-700 mt-2 space-y-1">
{checkResult.riskReasons.map((reason, idx) => (
<li key={idx} className="flex items-start gap-2">
<span className="text-red-500 mt-0.5"></span>
<span>{reason}</span>
</li>
))}
</ul>
)}
</div>
{/* Status */}
<div className="grid grid-cols-2 gap-4">
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-1">Статус</p>
<p className="text-sm font-bold text-slate-800">
{checkResult.status === 'ACTIVE' ? 'Действующая' :
checkResult.status === 'LIQUIDATED' ? 'Ликвидирована' :
checkResult.status === 'LIQUIDATING' ? 'Ликвидируется' :
checkResult.status === 'BANKRUPT' ? 'Банкрот' :
checkResult.status === 'REORGANIZING' ? 'Реорганизуется' :
checkResult.status}
</p>
</div>
{checkResult.registrationDate && (
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-1">Дата регистрации</p>
<p className="text-sm font-bold text-slate-800">
{new Date(checkResult.registrationDate).toLocaleDateString('ru-RU')}
</p>
</div>
)}
</div>
{/* Address */}
{checkResult.address && (
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-1">Адрес</p>
<p className="text-sm text-slate-700">{checkResult.address}</p>
</div>
)}
{/* Finance */}
{checkResult.finance && (
<div className="bg-slate-50 rounded-xl p-4">
<p className="text-xs font-black text-slate-500 uppercase mb-3">Финансовые показатели</p>
<div className="grid grid-cols-2 gap-4 text-sm">
{checkResult.finance.revenue && (
<div>
<p className="text-slate-500">Выручка ({checkResult.finance.year})</p>
<p className="font-bold text-slate-800">
{checkResult.finance.revenue.toLocaleString('ru-RU')}
</p>
</div>
)}
{checkResult.finance.income && (
<div>
<p className="text-slate-500">Доходы ({checkResult.finance.year})</p>
<p className="font-bold text-slate-800">
{checkResult.finance.income.toLocaleString('ru-RU')}
</p>
</div>
)}
{checkResult.finance.debt && checkResult.finance.debt > 0 && (
<div>
<p className="text-red-600">Недоимки</p>
<p className="font-bold text-red-600">
{checkResult.finance.debt.toLocaleString('ru-RU')}
</p>
</div>
)}
{checkResult.finance.penalty && checkResult.finance.penalty > 0 && (
<div>
<p className="text-red-600">Штрафы</p>
<p className="font-bold text-red-600">
{checkResult.finance.penalty.toLocaleString('ru-RU')}
</p>
</div>
)}
</div>
</div>
)}
{/* Management */}
{checkResult.management && (
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-1">Руководитель</p>
<p className="text-sm text-slate-700">
{checkResult.management.name}
{checkResult.management.post && `${checkResult.management.post}`}
</p>
</div>
)}
{/* OKVED */}
{checkResult.okved && (
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-1">Основной ОКВЭД</p>
<p className="text-sm text-slate-700">
{checkResult.okved} {checkResult.okveds?.find(o => o.main)?.name || ''}
</p>
</div>
)}
{/* Capital */}
{checkResult.capital != null && checkResult.capital.value != null && (
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-1">Уставный капитал</p>
<p className="text-sm font-bold text-slate-800">
{checkResult.capital.value.toLocaleString('ru-RU')}
{checkResult.capital.type && <span className="text-slate-500 font-normal ml-1">({checkResult.capital.type})</span>}
</p>
</div>
)}
{/* SMB */}
{checkResult.smb?.category && (
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-1">Категория МСП</p>
<p className="text-sm text-slate-700">
{checkResult.smb.category === 'MICRO' ? 'Микропредприятие' :
checkResult.smb.category === 'SMALL' ? 'Малое' :
checkResult.smb.category === 'MEDIUM' ? 'Среднее' : checkResult.smb.category}
{checkResult.smb.issueDate && (
<span className="text-slate-500 text-xs ml-1">
(реестр с {new Date(checkResult.smb.issueDate).toLocaleDateString('ru-RU')})
</span>
)}
</p>
</div>
)}
{/* Licenses */}
{checkResult.licenses && checkResult.licenses.length > 0 && (
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-1">Лицензии</p>
<ul className="text-sm text-slate-700 space-y-1">
{checkResult.licenses.map((lic, idx) => {
const validTo = lic.validTo ? new Date(lic.validTo).getTime() : null;
const expired = validTo != null && validTo < Date.now();
return (
<li key={idx} className={expired ? 'text-amber-600' : ''}>
{lic.number && <span className="font-medium">{lic.number}</span>}
{lic.validTo && (
<span className="ml-1">
{expired ? 'истекла' : 'до'} {new Date(lic.validTo).toLocaleDateString('ru-RU')}
</span>
)}
{lic.activities?.length ? `${lic.activities.join(', ')}` : ''}
</li>
);
})}
</ul>
</div>
)}
{/* Management disqualified */}
{checkResult.managementDisqualified && (
<div className="p-3 bg-red-50 border border-red-200 rounded-xl">
<p className="text-xs font-black text-red-600 uppercase mb-1">Руководитель дисквалифицирован</p>
<p className="text-sm text-red-700">Директор не имеет права заключать сделки</p>
</div>
)}
{/* Invalidity details */}
{(checkResult.addressInvalidity || (checkResult.foundersInvalidity && checkResult.foundersInvalidity.length > 0) || (checkResult.managersInvalidity && checkResult.managersInvalidity.length > 0)) && (
<div className="p-3 bg-amber-50 border border-amber-200 rounded-xl">
<p className="text-xs font-black text-amber-700 uppercase mb-1">Недостоверные сведения</p>
<ul className="text-xs text-amber-800 space-y-0.5">
{checkResult.addressInvalidity && <li> Адрес признан недостоверным (ФНС)</li>}
{checkResult.foundersInvalidity?.length ? <li> Сведения об учредителях недостоверны</li> : null}
{checkResult.managersInvalidity?.length ? <li> Сведения о руководителе недостоверны</li> : null}
</ul>
</div>
)}
</div>
</div>
)}
{/* Check History */}
<div className="space-y-4">
<div className="flex justify-between items-center px-1">
<h3 className="font-black text-slate-500 text-[10px] uppercase tracking-[0.2em]">История проверок</h3>
<button
onClick={loadHistory}
className="text-[10px] font-black text-primary-600 uppercase hover:underline"
>
Обновить
</button>
</div>
{loadingHistory ? (
<div className="flex items-center justify-center py-8">
<Loader2 className="w-5 h-5 animate-spin text-slate-400" />
</div>
) : checkedCounterparties.length === 0 ? (
<div className="bg-white p-8 rounded-xl border border-slate-200 text-center">
<p className="text-slate-400">История проверок пуста</p>
<p className="text-xs text-slate-500 mt-2">Проверьте контрагента, чтобы добавить запись в историю</p>
</div>
) : (
checkedCounterparties.map(cp => {
const isHighRisk = cp.riskLevel === 'high';
const isMediumRisk = cp.riskLevel === 'medium';
return (
<div key={cp.id} className="bg-white p-5 rounded-[2rem] border border-slate-200 shadow-sm flex flex-col md:flex-row justify-between gap-6 hover:shadow-md transition-all group">
<div className="flex items-center gap-4">
<div className={`p-4 rounded-2xl ${isHighRisk ? 'bg-red-50 text-red-600' : isMediumRisk ? 'bg-amber-50 text-amber-600' : 'bg-emerald-50 text-emerald-600'}`}>
{isHighRisk ? <ShieldAlert className="w-7 h-7" /> : isMediumRisk ? <AlertTriangle className="w-7 h-7" /> : <CheckCircle2 className="w-7 h-7" />}
</div>
<div>
<h4 className="font-black text-slate-800 text-base leading-tight">{cp.name}</h4>
<p className="text-[10px] text-slate-400 font-bold uppercase mt-1">
ИНН: {cp.inn} Проверен: {cp.checkedDate ? new Date(cp.checkedDate).toLocaleDateString('ru-RU') : 'Не указано'}
</p>
</div>
</div>
<div className="flex items-center justify-between md:justify-end gap-6 border-t md:border-t-0 border-slate-100 pt-4 md:pt-0">
<div className="text-right">
<p className={`text-[10px] font-black uppercase tracking-widest ${isHighRisk ? 'text-red-500' : isMediumRisk ? 'text-amber-500' : 'text-emerald-500'}`}>
{isHighRisk ? 'Высокий риск' : isMediumRisk ? 'Средний риск' : 'Благонадежен'}
</p>
<button
onClick={async () => {
try {
const response = await authFetch(`/api/legal/counterparties/${cp.id}`);
if (response.ok) {
const report = await response.json();
setSelectedReport(report);
setShowReportModal(true);
}
} catch (error) {
console.error('Error loading report:', error);
}
}}
className="text-[10px] font-black text-primary-600 uppercase mt-1 hover:underline"
>
Подробный отчет
</button>
</div>
<div className="w-10 h-10 rounded-full bg-slate-50 flex items-center justify-center text-slate-300 group-hover:text-primary-500 transition-colors cursor-pointer"
onClick={async () => {
try {
const response = await authFetch(`/api/legal/counterparties/${cp.id}`);
if (response.ok) {
const report = await response.json();
setSelectedReport(report);
setShowReportModal(true);
}
} catch (error) {
console.error('Error loading report:', error);
}
}}
>
<ChevronRight className="w-6 h-6"/>
</div>
</div>
</div>
);
}))}
</div>
<div className="flex items-center gap-3 p-4 bg-blue-50 rounded-2xl border border-blue-100">
<Info className="w-5 h-5 text-blue-500 flex-shrink-0" />
<p className="text-[11px] text-blue-700 leading-snug font-medium">
Система автоматически блокирует создание договоров с контрагентами, имеющими статус «Высокий риск» до ручного подтверждения Директором.
</p>
</div>
{/* Report Modal */}
{showReportModal && selectedReport && (
<ReportModal
report={selectedReport}
onClose={() => {
setShowReportModal(false);
setSelectedReport(null);
}}
/>
)}
</div>
);
};
// Report Modal Component
interface ReportModalProps {
report: any;
onClose: () => void;
}
const ReportModal: React.FC<ReportModalProps> = ({ report, onClose }) => {
return (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4 overflow-y-auto">
<div className="bg-white rounded-2xl p-6 max-w-4xl w-full max-h-[90vh] overflow-y-auto">
<div className="flex justify-between items-center mb-6">
<h3 className="text-xl font-black text-slate-800">Детальный отчет о проверке</h3>
<button onClick={onClose} className="p-2 text-slate-400 hover:text-slate-600">
<X className="w-5 h-5" />
</button>
</div>
<div className="space-y-6">
{/* Header Info */}
<div className="bg-slate-50 rounded-xl p-4">
<h4 className="text-lg font-black text-slate-800 mb-2">{report.name}</h4>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-4 text-sm">
<div>
<p className="text-slate-500 text-xs">ИНН</p>
<p className="font-bold text-slate-800">{report.inn}</p>
</div>
{report.kpp && (
<div>
<p className="text-slate-500 text-xs">КПП</p>
<p className="font-bold text-slate-800">{report.kpp}</p>
</div>
)}
{report.ogrn && (
<div>
<p className="text-slate-500 text-xs">ОГРН</p>
<p className="font-bold text-slate-800">{report.ogrn}</p>
</div>
)}
<div>
<p className="text-slate-500 text-xs">Дата проверки</p>
<p className="font-bold text-slate-800">
{new Date(report.checkedDate).toLocaleString('ru-RU')}
</p>
</div>
</div>
</div>
{/* Risk Level */}
<div className={`p-4 rounded-xl border-2 ${
report.riskLevel === 'high' ? 'bg-red-50 border-red-200' :
report.riskLevel === 'medium' ? 'bg-amber-50 border-amber-200' :
'bg-emerald-50 border-emerald-200'
}`}>
<div className="flex items-center justify-between mb-2">
<span className="text-sm font-black text-slate-800">Уровень риска:</span>
<span className={`text-sm font-black uppercase ${
report.riskLevel === 'high' ? 'text-red-600' :
report.riskLevel === 'medium' ? 'text-amber-600' :
'text-emerald-600'
}`}>
{report.riskLevel === 'high' ? 'Высокий риск' :
report.riskLevel === 'medium' ? 'Средний риск' :
'Благонадежен'}
</span>
</div>
{report.riskReasons && report.riskReasons.length > 0 && (
<ul className="text-xs text-slate-700 mt-2 space-y-1">
{report.riskReasons.map((reason: string, idx: number) => (
<li key={idx} className="flex items-start gap-2">
<span className="text-red-500 mt-0.5"></span>
<span>{reason}</span>
</li>
))}
</ul>
)}
</div>
{/* Status and Dates */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-1">Статус</p>
<p className="text-sm font-bold text-slate-800">
{report.status === 'ACTIVE' ? 'Действующая' :
report.status === 'LIQUIDATED' ? 'Ликвидирована' :
report.status === 'LIQUIDATING' ? 'Ликвидируется' :
report.status === 'BANKRUPT' ? 'Банкрот' :
report.status === 'REORGANIZING' ? 'Реорганизуется' :
report.status}
</p>
</div>
{report.registrationDate && (
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-1">Дата регистрации</p>
<p className="text-sm font-bold text-slate-800">
{new Date(report.registrationDate).toLocaleDateString('ru-RU')}
</p>
</div>
)}
{report.liquidationDate && (
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-1">Дата ликвидации</p>
<p className="text-sm font-bold text-red-600">
{new Date(report.liquidationDate).toLocaleDateString('ru-RU')}
</p>
</div>
)}
</div>
{/* Address */}
{report.address && (
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-1">Адрес</p>
<p className="text-sm text-slate-700">{report.address}</p>
</div>
)}
{/* Management */}
{report.managementName && (
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-1">Руководитель</p>
<p className="text-sm text-slate-700">
{report.managementName}
{report.managementPost && `${report.managementPost}`}
</p>
</div>
)}
{/* OKVED */}
{report.okved && (
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-1">Основной ОКВЭД</p>
<p className="text-sm text-slate-700">
{report.okved} {report.okveds?.find((o: any) => o.main)?.name || ''}
</p>
</div>
)}
{/* Finance */}
{report.finance && (
<div className="bg-slate-50 rounded-xl p-4">
<p className="text-xs font-black text-slate-500 uppercase mb-3">Финансовые показатели</p>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 text-sm">
{report.finance.revenue !== undefined && report.finance.revenue !== null && (
<div>
<p className="text-slate-500">Выручка ({report.finance.year})</p>
<p className="font-bold text-slate-800">
{report.finance.revenue.toLocaleString('ru-RU')}
</p>
</div>
)}
{report.finance.income !== undefined && report.finance.income !== null && (
<div>
<p className="text-slate-500">Доходы ({report.finance.year})</p>
<p className="font-bold text-slate-800">
{report.finance.income.toLocaleString('ru-RU')}
</p>
</div>
)}
{report.finance.expense !== undefined && report.finance.expense !== null && (
<div>
<p className="text-slate-500">Расходы ({report.finance.year})</p>
<p className="font-bold text-slate-800">
{report.finance.expense.toLocaleString('ru-RU')}
</p>
</div>
)}
{report.finance.debt !== undefined && report.finance.debt !== null && report.finance.debt > 0 && (
<div>
<p className="text-red-600">Недоимки</p>
<p className="font-bold text-red-600">
{report.finance.debt.toLocaleString('ru-RU')}
</p>
</div>
)}
{report.finance.penalty !== undefined && report.finance.penalty !== null && report.finance.penalty > 0 && (
<div>
<p className="text-red-600">Штрафы</p>
<p className="font-bold text-red-600">
{report.finance.penalty.toLocaleString('ru-RU')}
</p>
</div>
)}
{report.finance.taxSystem && (
<div>
<p className="text-slate-500">Система налогообложения</p>
<p className="font-bold text-slate-800">{report.finance.taxSystem}</p>
</div>
)}
</div>
</div>
)}
{/* Authorities */}
{report.authorities && (
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-2">Государственные органы</p>
<div className="space-y-2 text-sm">
{report.authorities.ftsRegistration && (
<div className="bg-slate-50 rounded-lg p-3">
<p className="font-bold text-slate-800">ИФНС регистрации</p>
<p className="text-slate-600">{report.authorities.ftsRegistration.name}</p>
{report.authorities.ftsRegistration.address && (
<p className="text-xs text-slate-500 mt-1">{report.authorities.ftsRegistration.address}</p>
)}
</div>
)}
{report.authorities.ftsReport && (
<div className="bg-slate-50 rounded-lg p-3">
<p className="font-bold text-slate-800">ИФНС отчётности</p>
<p className="text-slate-600">{report.authorities.ftsReport.name}</p>
</div>
)}
</div>
</div>
)}
{/* Phones and Emails */}
{(report.phones?.length > 0 || report.emails?.length > 0) && (
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-2">Контакты</p>
<div className="space-y-2 text-sm">
{report.phones?.map((phone: any, idx: number) => (
<div key={idx} className="flex items-center gap-2">
<Phone className="w-4 h-4 text-slate-400" />
<span className="text-slate-700">{phone.value || phone}</span>
</div>
))}
{report.emails?.map((email: any, idx: number) => (
<div key={idx} className="flex items-center gap-2">
<Mail className="w-4 h-4 text-slate-400" />
<span className="text-slate-700">{email.value || email}</span>
</div>
))}
</div>
</div>
)}
{/* Employee Count */}
{report.employeeCount && (
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-1">Среднесписочная численность</p>
<p className="text-sm font-bold text-slate-800">{report.employeeCount} человек</p>
</div>
)}
{/* Capital */}
{report.capital != null && report.capital.value != null && (
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-1">Уставный капитал</p>
<p className="text-sm font-bold text-slate-800">
{report.capital.value.toLocaleString('ru-RU')}
{report.capital.type && <span className="text-slate-500 font-normal ml-1">({report.capital.type})</span>}
</p>
</div>
)}
{/* SMB */}
{report.smb?.category && (
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-1">Категория МСП</p>
<p className="text-sm text-slate-700">
{report.smb.category === 'MICRO' ? 'Микропредприятие' :
report.smb.category === 'SMALL' ? 'Малое' :
report.smb.category === 'MEDIUM' ? 'Среднее' : report.smb.category}
{report.smb.issueDate && (
<span className="text-slate-500 text-xs ml-1">
(реестр с {new Date(report.smb.issueDate).toLocaleDateString('ru-RU')})
</span>
)}
</p>
</div>
)}
{/* Licenses */}
{report.licenses && report.licenses.length > 0 && (
<div className="bg-slate-50 rounded-xl p-4">
<p className="text-xs font-black text-slate-500 uppercase mb-2">Лицензии</p>
<ul className="text-sm text-slate-700 space-y-2">
{report.licenses.map((lic: { number?: string; validTo?: number; validFrom?: number; activities?: string[] }, idx: number) => {
const validTo = lic.validTo ? new Date(lic.validTo).getTime() : null;
const expired = validTo != null && validTo < Date.now();
return (
<li key={idx} className={expired ? 'text-amber-600' : ''}>
{lic.number && <span className="font-bold">{lic.number}</span>}
{lic.validFrom && (
<span className="ml-1 text-slate-500">с {new Date(lic.validFrom).toLocaleDateString('ru-RU')}</span>
)}
{lic.validTo && (
<span className="ml-1">
{expired ? 'истекла' : 'до'} {new Date(lic.validTo).toLocaleDateString('ru-RU')}
</span>
)}
{lic.activities?.length ? (
<p className="text-xs text-slate-600 mt-0.5">{lic.activities.join(', ')}</p>
) : null}
</li>
);
})}
</ul>
</div>
)}
{/* Management disqualified */}
{report.managementDisqualified && (
<div className="p-4 bg-red-50 border-2 border-red-200 rounded-xl">
<p className="text-xs font-black text-red-600 uppercase mb-1">Руководитель дисквалифицирован</p>
<p className="text-sm text-red-700">Директор не имеет права заключать сделки</p>
</div>
)}
{/* Invalidity details */}
{(report.addressInvalidity || (report.foundersInvalidity && report.foundersInvalidity.length > 0) || (report.managersInvalidity && report.managersInvalidity.length > 0)) && (
<div className="p-4 bg-amber-50 border-2 border-amber-200 rounded-xl">
<p className="text-xs font-black text-amber-700 uppercase mb-2">Недостоверные сведения</p>
<ul className="text-sm text-amber-800 space-y-1">
{report.addressInvalidity && <li> Адрес признан недостоверным (ФНС)</li>}
{report.foundersInvalidity?.length ? <li> Сведения об учредителях недостоверны</li> : null}
{report.managersInvalidity?.length ? <li> Сведения о руководителе недостоверны</li> : null}
</ul>
</div>
)}
{/* Notes */}
{report.notes && (
<div>
<p className="text-xs font-black text-slate-500 uppercase mb-1">Примечания</p>
<p className="text-sm text-slate-700 bg-slate-50 p-3 rounded-lg">{report.notes}</p>
</div>
)}
</div>
<div className="mt-6 flex justify-end">
<button
onClick={onClose}
className="px-6 py-2.5 bg-primary-600 text-white rounded-xl text-xs font-black uppercase hover:bg-primary-700 transition-colors"
>
Закрыть
</button>
</div>
</div>
</div>
);
};