593 lines
23 KiB
JavaScript
593 lines
23 KiB
JavaScript
// Демо-данные договоров аренды ОЦО ЮС
|
||
const DEMO_CONTRACTS = [
|
||
{
|
||
id: 1,
|
||
number: 'ДА-2026-001',
|
||
counterparty: 'ТОО "Алма-Ата Ритейл"',
|
||
bin: '203456789012',
|
||
branch: 'Алматы',
|
||
initiator: 'Иванова Мария Петровна',
|
||
object: 'Помещение офиса',
|
||
area: 120,
|
||
cadastral: '01:49:000123:456',
|
||
rate: 650000,
|
||
term: 24,
|
||
total: 15600000,
|
||
signer: 'Ахметов Ержан Болатович, Директор',
|
||
status: 'ai-review',
|
||
risks: ['high'],
|
||
riskDetails: [
|
||
{ level: 'high', text: 'Тариф не соответствует SAP (заявка: 650000, SAP: 720000)' },
|
||
{ level: 'medium', text: 'Отсутствие кадастрового паспорта в приложении' }
|
||
],
|
||
sapTariffDate: '14.09.2026',
|
||
sapTariffRate: 720000,
|
||
aiChecks: [
|
||
{ name: 'ГК РК Статья 403', passed: true, comment: 'Существенные условия указаны' },
|
||
{ name: 'Полномочия подписанта', passed: true, comment: 'Доверенность №123 от 01.01.2026 действительна' },
|
||
{ name: 'Тариф SAP', passed: false, comment: 'Ставка в заявке ниже актуального тарифа на 9.7%' },
|
||
{ name: 'Кадастровые данные', passed: false, comment: 'Номер указан, паспорт не приложен' }
|
||
],
|
||
date: '12.09.2026',
|
||
comment: ''
|
||
},
|
||
{
|
||
id: 2,
|
||
number: 'ДА-2026-002',
|
||
counterparty: 'ИП "Самат"',
|
||
bin: '198765432109',
|
||
branch: 'Астана',
|
||
initiator: 'Кузнецов Андрей Владимирович',
|
||
object: 'Торговая площадь',
|
||
area: 85,
|
||
cadastral: '02:11:000456:789',
|
||
rate: 480000,
|
||
term: 12,
|
||
total: 5760000,
|
||
signer: 'Саматов Самат Нурланович, ИП',
|
||
status: 'new',
|
||
risks: [],
|
||
riskDetails: [],
|
||
sapTariffDate: '14.09.2026',
|
||
sapTariffRate: 480000,
|
||
aiChecks: [
|
||
{ name: 'ГК РК Статья 403', passed: true, comment: 'Существенные условия указаны' },
|
||
{ name: 'Полномочия подписанта', passed: true, comment: 'ИП действует без доверенности' },
|
||
{ name: 'Тариф SAP', passed: true, comment: 'Ставка соответствует тарифу' },
|
||
{ name: 'Кадастровые данные', passed: true, comment: 'Паспорт приложен' }
|
||
],
|
||
date: '13.09.2026',
|
||
comment: ''
|
||
},
|
||
{
|
||
id: 3,
|
||
number: 'ДА-2026-003',
|
||
counterparty: 'АО "Каспий Банк"',
|
||
bin: '211234567890',
|
||
branch: 'Алматы',
|
||
initiator: 'Султанова Гульнара Ахметовна',
|
||
object: 'Помещение отделения',
|
||
area: 250,
|
||
cadastral: '01:49:000789:012',
|
||
rate: 1200000,
|
||
term: 36,
|
||
total: 43200000,
|
||
signer: 'Ибраев Нурлан Жуматович, Управляющий',
|
||
status: 'lawyer-check',
|
||
risks: ['medium'],
|
||
riskDetails: [
|
||
{ level: 'medium', text: 'Контрагентская версия содержит отклонения в пункте 5.2' }
|
||
],
|
||
sapTariffDate: '14.09.2026',
|
||
sapTariffRate: 1150000,
|
||
aiChecks: [
|
||
{ name: 'ГК РК Статья 403', passed: true, comment: 'Существенные условия указаны' },
|
||
{ name: 'Полномочия подписанта', passed: true, comment: 'Приказ №456 от 15.03.2025' },
|
||
{ name: 'Тариф SAP', passed: false, comment: 'Ставка выше тарифа на 4.3% (требуется обоснование)' },
|
||
{ name: 'Кадастровые данные', passed: true, comment: 'Все документы в порядке' }
|
||
],
|
||
diff: [
|
||
{ op: 'del', text: '5.2. Арендатор обязуется оплатить аренду до 10 числа текущего месяца' },
|
||
{ op: 'add', text: '5.2. Арендатор обязуется оплатить аренду до 15 числа текущего месяца' },
|
||
{ op: 'del', text: '7.1. Договор действует до 31.12.2028' },
|
||
{ op: 'add', text: '7.1. Договор действует до 30.06.2029 с автоматической пролонгацией' }
|
||
],
|
||
date: '10.09.2026',
|
||
comment: ''
|
||
},
|
||
{
|
||
id: 4,
|
||
number: 'ДА-2026-004',
|
||
counterparty: 'ТОО "СтройМаш"',
|
||
bin: '205678901234',
|
||
branch: 'Караганда',
|
||
initiator: 'Петров Сергей Михайлович',
|
||
object: 'Складское помещение',
|
||
area: 500,
|
||
cadastral: '',
|
||
rate: 350000,
|
||
term: 6,
|
||
total: 2100000,
|
||
signer: 'Куанышев Болатбек Асылбекович, Директор',
|
||
status: 'revision',
|
||
risks: ['high'],
|
||
riskDetails: [
|
||
{ level: 'high', text: 'Отсутствуют кадастровые данные объекта' }
|
||
],
|
||
sapTariffDate: '14.09.2026',
|
||
sapTariffRate: 380000,
|
||
aiChecks: [
|
||
{ name: 'ГК РК Статья 403', passed: true, comment: 'Существенные условия указаны' },
|
||
{ name: 'Полномочия подписанта', passed: true, comment: 'Доверенность №789 от 20.02.2026' },
|
||
{ name: 'Тариф SAP', passed: false, comment: 'Ставка ниже тарифа на 7.9%' },
|
||
{ name: 'Кадастровые данные', passed: false, comment: 'Данные отсутствуют' }
|
||
],
|
||
date: '08.09.2026',
|
||
comment: 'Запрошены кадастровые документы у инициатора'
|
||
},
|
||
{
|
||
id: 5,
|
||
number: 'ДА-2026-005',
|
||
counterparty: 'ТОО "Нур-СултанTrade"',
|
||
bin: '219876543210',
|
||
branch: 'Астана',
|
||
initiator: 'Омарова Айгуль Ержановна',
|
||
object: 'Офисное помещение',
|
||
area: 180,
|
||
cadastral: '02:11:001234:567',
|
||
rate: 900000,
|
||
term: 18,
|
||
total: 16200000,
|
||
signer: 'Жуманов Ермек Бауыржанович, Генеральный директор',
|
||
status: 'approved',
|
||
risks: [],
|
||
riskDetails: [],
|
||
sapTariffDate: '14.09.2026',
|
||
sapTariffRate: 900000,
|
||
aiChecks: [
|
||
{ name: 'ГК РК Статья 403', passed: true, comment: 'Существенные условия указаны' },
|
||
{ name: 'Полномочия подписанта', passed: true, comment: 'Устав подтверждает полномочия' },
|
||
{ name: 'Тариф SAP', passed: true, comment: 'Ставка соответствует тарифу' },
|
||
{ name: 'Кадастровые данные', passed: true, comment: 'Все документы приложены' }
|
||
],
|
||
date: '05.09.2026',
|
||
comment: 'Согласовано, отправлено на подпись'
|
||
},
|
||
{
|
||
id: 6,
|
||
number: 'ДА-2026-006',
|
||
counterparty: 'ИП "Алия"',
|
||
bin: '187654321098',
|
||
branch: 'Шымкент',
|
||
initiator: 'Турсумбаев Максат Алиевич',
|
||
object: 'Торговая точка',
|
||
area: 45,
|
||
cadastral: '03:22:002345:678',
|
||
rate: 220000,
|
||
term: 12,
|
||
total: 2640000,
|
||
signer: 'Каримова Алия Сериковна, ИП',
|
||
status: 'ai-review',
|
||
risks: ['low'],
|
||
riskDetails: [
|
||
{ level: 'low', text: 'Небольшие отклонения в формулировках' }
|
||
],
|
||
sapTariffDate: '14.09.2026',
|
||
sapTariffRate: 230000,
|
||
aiChecks: [
|
||
{ name: 'ГК РК Статья 403', passed: true, comment: 'Существенные условия указаны' },
|
||
{ name: 'Полномочия подписанта', passed: true, comment: 'ИП действует без доверенности' },
|
||
{ name: 'Тариф SAP', passed: false, comment: 'Ставка ниже тарифа на 4.3%' },
|
||
{ name: 'Кадастровые данные', passed: true, comment: 'Документы приложены' }
|
||
],
|
||
date: '14.09.2026',
|
||
comment: ''
|
||
},
|
||
{
|
||
id: 7,
|
||
number: 'ДА-2026-007',
|
||
counterparty: 'ТОО "Актобе-Инвест"',
|
||
bin: '213456789012',
|
||
branch: 'Актобе',
|
||
initiator: 'Жанбеков Руслан Кенжевич',
|
||
object: 'Производственное помещение',
|
||
area: 320,
|
||
cadastral: '04:33:003456:789',
|
||
rate: 580000,
|
||
term: 24,
|
||
total: 13920000,
|
||
signer: 'Алиев Серикжан Болатович, Директор',
|
||
status: 'approved',
|
||
risks: [],
|
||
riskDetails: [],
|
||
sapTariffDate: '14.09.2026',
|
||
sapTariffRate: 580000,
|
||
aiChecks: [
|
||
{ name: 'ГК РК Статья 403', passed: true, comment: 'Существенные условия указаны' },
|
||
{ name: 'Полномочия подписанта', passed: true, comment: 'Доверенность №321 от 10.01.2026' },
|
||
{ name: 'Тариф SAP', passed: true, comment: 'Ставка соответствует тарифу' },
|
||
{ name: 'Кадастровые данные', passed: true, comment: 'Все документы в порядке' }
|
||
],
|
||
date: '03.09.2026',
|
||
comment: 'Согласовано'
|
||
},
|
||
{
|
||
id: 8,
|
||
number: 'ДА-2026-008',
|
||
counterparty: 'ТОО "Байтерек-Строй"',
|
||
bin: '224567890123',
|
||
branch: 'Астана',
|
||
initiator: 'Ким Дмитрий Андреевич',
|
||
object: 'Офис',
|
||
area: 95,
|
||
cadastral: '',
|
||
rate: 520000,
|
||
term: 12,
|
||
total: 6240000,
|
||
signer: 'Ли Владимир Петрович, Генеральный директор',
|
||
status: 'revision',
|
||
risks: ['high'],
|
||
riskDetails: [
|
||
{ level: 'high', text: 'Нет кадастровых данных' },
|
||
{ level: 'medium', text: 'Срок аренды не соответствует стандарту' }
|
||
],
|
||
sapTariffDate: '14.09.2026',
|
||
sapTariffRate: 550000,
|
||
aiChecks: [
|
||
{ name: 'ГК РК Статья 403', passed: true, comment: 'Существенные условия указаны' },
|
||
{ name: 'Полномочия подписанта', passed: true, comment: 'Протокол №5 от 15.12.2025' },
|
||
{ name: 'Тариф SAP', passed: false, comment: 'Ставка ниже тарифа на 5.5%' },
|
||
{ name: 'Кадастровые данные', passed: false, comment: 'Отсутствуют' }
|
||
],
|
||
date: '11.09.2026',
|
||
comment: 'Ожидание кадастровых документов'
|
||
}
|
||
];
|
||
|
||
// Состояние приложения
|
||
let contracts = [];
|
||
let currentFilter = 'all';
|
||
let currentScreen = 'queue';
|
||
let selectedContract = null;
|
||
|
||
// Инициализация
|
||
function init() {
|
||
loadContracts();
|
||
renderQueue();
|
||
renderMetrics();
|
||
renderProblems();
|
||
renderRegistry();
|
||
setupNavigation();
|
||
setupFilters();
|
||
setupSearch();
|
||
setupForm();
|
||
setupThemeToggle();
|
||
}
|
||
|
||
// Загрузка данных из localStorage или демо
|
||
function loadContracts() {
|
||
const stored = localStorage.getItem('contracts');
|
||
if (stored) {
|
||
contracts = JSON.parse(stored);
|
||
} else {
|
||
contracts = JSON.parse(JSON.stringify(DEMO_CONTRACTS));
|
||
saveContracts();
|
||
}
|
||
}
|
||
|
||
// Сохранение в localStorage
|
||
function saveContracts() {
|
||
localStorage.setItem('contracts', JSON.stringify(contracts));
|
||
}
|
||
|
||
// Навигация
|
||
function setupNavigation() {
|
||
document.querySelectorAll('.kt-ai-nav-item').forEach(item => {
|
||
item.addEventListener('click', () => {
|
||
const screen = item.dataset.screen;
|
||
navigateTo(screen);
|
||
});
|
||
});
|
||
}
|
||
|
||
function navigateTo(screen) {
|
||
currentScreen = screen;
|
||
|
||
// Обновляем активный пункт меню
|
||
document.querySelectorAll('.kt-ai-nav-item').forEach(item => {
|
||
item.classList.toggle('active', item.dataset.screen === screen);
|
||
});
|
||
|
||
// Показываем экран
|
||
document.querySelectorAll('.screen').forEach(s => s.classList.remove('active'));
|
||
document.getElementById(`screen-${screen}`).classList.add('active');
|
||
|
||
// Обновляем заголовок
|
||
const titles = {
|
||
queue: { title: 'Очередь договоров', subtitle: 'Проверка и согласование договоров аренды' },
|
||
problems: { title: 'Проблемные заявки', subtitle: 'Требуют дозапроса данных у инициатора' },
|
||
registry: { title: 'Реестр договоров', subtitle: 'История всех договоров' },
|
||
new: { title: 'Новая заявка', subtitle: 'Создание заявки на договор аренды' },
|
||
contract: { title: 'Карточка договора', subtitle: 'Детальная информация' }
|
||
};
|
||
|
||
document.getElementById('page-title').textContent = titles[screen]?.title || 'Договоры аренды';
|
||
document.getElementById('page-subtitle').textContent = titles[screen]?.subtitle || '';
|
||
|
||
if (screen === 'queue') renderQueue();
|
||
if (screen === 'problems') renderProblems();
|
||
if (screen === 'registry') renderRegistry();
|
||
}
|
||
|
||
// Фильтры
|
||
function setupFilters() {
|
||
document.querySelectorAll('.kt-ai-filter-chip').forEach(chip => {
|
||
chip.addEventListener('click', () => {
|
||
document.querySelectorAll('.kt-ai-filter-chip').forEach(c => c.classList.remove('active'));
|
||
chip.classList.add('active');
|
||
currentFilter = chip.dataset.filter;
|
||
renderQueue();
|
||
});
|
||
});
|
||
}
|
||
|
||
function filterByStatus(status) {
|
||
document.querySelectorAll('.kt-ai-filter-chip').forEach(c => {
|
||
c.classList.toggle('active', c.dataset.filter === status);
|
||
});
|
||
currentFilter = status;
|
||
renderQueue();
|
||
navigateTo('queue');
|
||
}
|
||
|
||
// Поиск
|
||
function setupSearch() {
|
||
document.getElementById('search-input').addEventListener('input', (e) => {
|
||
renderQueue(e.target.value);
|
||
});
|
||
}
|
||
|
||
// Рендер очереди
|
||
function renderQueue(searchTerm = '') {
|
||
const tbody = document.getElementById('queue-table-body');
|
||
let filtered = contracts;
|
||
|
||
// Фильтр по статусу
|
||
if (currentFilter !== 'all') {
|
||
filtered = filtered.filter(c => c.status === currentFilter);
|
||
}
|
||
|
||
// Поиск
|
||
if (searchTerm) {
|
||
const term = searchTerm.toLowerCase();
|
||
filtered = filtered.filter(c =>
|
||
c.number.toLowerCase().includes(term) ||
|
||
c.counterparty.toLowerCase().includes(term) ||
|
||
c.branch.toLowerCase().includes(term)
|
||
);
|
||
}
|
||
|
||
tbody.innerHTML = filtered.map(c => `
|
||
<tr onclick="openContract(${c.id})">
|
||
<td style="font-weight: var(--kt-ai-weight-medium);">${c.number}</td>
|
||
<td>${c.counterparty}</td>
|
||
<td>${c.branch}</td>
|
||
<td>${formatMoney(c.total)}</td>
|
||
<td><span class="kt-ai-status-pill" data-status="${c.status}">${getStatusName(c.status)}</span></td>
|
||
<td>${c.risks.length > 0 ? `<span class="kt-ai-risk-flag ${c.risks[0]}">⚠ ${c.risks.length}</span>` : '<span style="color: var(--kt-ai-fg-muted);">—</span>'}</td>
|
||
<td style="color: var(--kt-ai-fg-muted);">${c.date}</td>
|
||
</tr>
|
||
`).join('');
|
||
}
|
||
|
||
// Рендер метрик
|
||
function renderMetrics() {
|
||
const total = contracts.length;
|
||
const pending = contracts.filter(c => ['new', 'ai-review', 'lawyer-check'].includes(c.status)).length;
|
||
const risks = contracts.filter(c => c.risks.some(r => r === 'high' || r === 'medium')).length;
|
||
|
||
document.getElementById('metric-total').textContent = total;
|
||
document.getElementById('metric-pending').textContent = pending;
|
||
document.getElementById('metric-risks').textContent = risks;
|
||
|
||
const highRisks = contracts.filter(c => c.risks.some(r => r === 'high')).length;
|
||
const banner = document.getElementById('banner-risk');
|
||
if (highRisks > 0) {
|
||
document.getElementById('risk-count').textContent = highRisks;
|
||
banner.classList.remove('hidden');
|
||
} else {
|
||
banner.classList.add('hidden');
|
||
}
|
||
}
|
||
|
||
// Рендер проблемных
|
||
function renderProblems() {
|
||
const tbody = document.getElementById('problems-table-body');
|
||
const problems = contracts.filter(c => c.status === 'revision' || (c.risks.length > 0 && c.risks.includes('high')));
|
||
|
||
tbody.innerHTML = problems.map(c => `
|
||
<tr onclick="openContract(${c.id})">
|
||
<td style="font-weight: var(--kt-ai-weight-medium);">${c.number}</td>
|
||
<td>${c.riskDetails[0]?.text || 'Неполные данные'}</td>
|
||
<td>${c.branch}</td>
|
||
<td style="color: var(--kt-ai-fg-muted);">${c.date}</td>
|
||
<td><button class="kt-ai-btn" data-variant="primary" onclick="event.stopPropagation(); sendReminder(${c.id})">Напомнить</button></td>
|
||
</tr>
|
||
`).join('');
|
||
}
|
||
|
||
// Рендер реестра
|
||
function renderRegistry() {
|
||
const tbody = document.getElementById('registry-table-body');
|
||
|
||
tbody.innerHTML = contracts.map(c => `
|
||
<tr onclick="openContract(${c.id})">
|
||
<td style="font-weight: var(--kt-ai-weight-medium);">${c.number}</td>
|
||
<td>${c.counterparty}</td>
|
||
<td>${c.object}</td>
|
||
<td>${formatMoney(c.total)}</td>
|
||
<td><span class="kt-ai-status-pill" data-status="${c.status}">${getStatusName(c.status)}</span></td>
|
||
<td style="color: var(--kt-ai-fg-muted); font-size: var(--kt-ai-text-xs);">${c.comment || 'Без изменений'}</td>
|
||
</tr>
|
||
`).join('');
|
||
}
|
||
|
||
// Открытие карточки договора
|
||
function openContract(id) {
|
||
const c = contracts.find(x => x.id === id);
|
||
if (!c) return;
|
||
|
||
selectedContract = c;
|
||
|
||
document.getElementById('contract-title').textContent = c.number;
|
||
document.getElementById('contract-status').setAttribute('data-status', c.status);
|
||
document.getElementById('contract-status').textContent = getStatusName(c.status);
|
||
|
||
document.getElementById('contract-counterparty').textContent = c.counterparty;
|
||
document.getElementById('contract-bin').textContent = c.bin;
|
||
document.getElementById('contract-branch').textContent = c.branch;
|
||
document.getElementById('contract-initiator').textContent = c.initiator;
|
||
|
||
document.getElementById('contract-object').textContent = c.object;
|
||
document.getElementById('contract-area').textContent = c.area + ' м²';
|
||
document.getElementById('contract-cadastral').textContent = c.cadastral || 'Не указан';
|
||
|
||
document.getElementById('contract-rate').textContent = formatMoney(c.rate);
|
||
document.getElementById('contract-term').textContent = c.term + ' мес';
|
||
document.getElementById('contract-total').textContent = formatMoney(c.total);
|
||
|
||
// SAP тариф
|
||
document.getElementById('sap-tariff-date').textContent = c.sapTariffDate;
|
||
document.getElementById('sap-tariff-rate').textContent = formatMoney(c.sapTariffRate);
|
||
const diff = c.rate - c.sapTariffRate;
|
||
const diffPercent = ((diff / c.sapTariffRate) * 100).toFixed(1);
|
||
document.getElementById('sap-diff').textContent = `${diff > 0 ? '+' : ''}${diffPercent}% (${diff > 0 ? 'выше' : 'ниже'})`;
|
||
|
||
// Проверки ИИ
|
||
const checksHtml = c.aiChecks.map(check => `
|
||
<div style="display: flex; gap: var(--kt-ai-space-2); align-items: flex-start; margin-bottom: var(--kt-ai-space-3);">
|
||
<span style="font-size: 16px;">${check.passed ? '✅' : '⚠️'}</span>
|
||
<div style="flex: 1;">
|
||
<div style="font-size: var(--kt-ai-text-sm); font-weight: var(--kt-ai-weight-medium);">${check.name}</div>
|
||
<div style="font-size: var(--kt-ai-text-xs); color: var(--kt-ai-fg-muted);">${check.comment}</div>
|
||
</div>
|
||
</div>
|
||
`).join('');
|
||
document.getElementById('ai-checks').innerHTML = checksHtml;
|
||
|
||
// Отклонения
|
||
const diffCard = document.getElementById('diff-card');
|
||
if (c.diff && c.diff.length > 0) {
|
||
diffCard.style.display = 'block';
|
||
document.getElementById('diff-content').innerHTML = c.diff.map(d =>
|
||
`<div class="line" data-op="${d.op}">${d.op === 'add' ? '+' : '-'} ${d.text}</div>`
|
||
).join('');
|
||
} else {
|
||
diffCard.style.display = 'none';
|
||
}
|
||
|
||
navigateTo('contract');
|
||
}
|
||
|
||
// Форма новой заявки
|
||
function setupForm() {
|
||
document.getElementById('new-contract-form').addEventListener('submit', (e) => {
|
||
e.preventDefault();
|
||
const form = e.target;
|
||
const formData = new FormData(form);
|
||
|
||
const newContract = {
|
||
id: contracts.length + 1,
|
||
number: `ДА-2026-${String(contracts.length + 1).padStart(3, '0')}`,
|
||
counterparty: formData.get('counterparty'),
|
||
bin: formData.get('bin'),
|
||
branch: formData.get('branch'),
|
||
initiator: formData.get('initiator'),
|
||
object: formData.get('object'),
|
||
area: Number(formData.get('area')),
|
||
cadastral: formData.get('cadastral'),
|
||
rate: Number(formData.get('rate')),
|
||
term: Number(formData.get('term')),
|
||
total: Number(formData.get('rate')) * Number(formData.get('term')),
|
||
signer: formData.get('signer'),
|
||
status: 'new',
|
||
risks: [],
|
||
riskDetails: [],
|
||
sapTariffDate: new Date().toLocaleDateString('ru-RU'),
|
||
sapTariffRate: Number(formData.get('rate')),
|
||
aiChecks: [],
|
||
date: new Date().toLocaleDateString('ru-RU'),
|
||
comment: formData.get('comment')
|
||
};
|
||
|
||
contracts.unshift(newContract);
|
||
saveContracts();
|
||
renderMetrics();
|
||
renderQueue();
|
||
renderRegistry();
|
||
|
||
form.reset();
|
||
alert('Заявка отправлена! ИИ-агент начнёт обработку в ближайшее время.');
|
||
navigateTo('queue');
|
||
});
|
||
}
|
||
|
||
// Переключение темы
|
||
function setupThemeToggle() {
|
||
const btn = document.getElementById('theme-toggle');
|
||
btn.addEventListener('click', () => {
|
||
const html = document.documentElement;
|
||
const isDark = html.getAttribute('data-theme') === 'dark';
|
||
html.setAttribute('data-theme', isDark ? 'light' : 'dark');
|
||
btn.textContent = isDark ? '🌙' : '☀️';
|
||
});
|
||
}
|
||
|
||
// Вспомогательные функции
|
||
function getStatusName(status) {
|
||
const names = {
|
||
'new': 'Новый',
|
||
'ai-review': 'ИИ проверка',
|
||
'lawyer-check': 'Проверка юриста',
|
||
'approved': 'Согласовано',
|
||
'revision': 'На доработке'
|
||
};
|
||
return names[status] || status;
|
||
}
|
||
|
||
function formatMoney(amount) {
|
||
return new Intl.NumberFormat('ru-RU', { style: 'currency', currency: 'KZT', maximumFractionDigits: 0 }).format(amount);
|
||
}
|
||
|
||
function sendReminder(id) {
|
||
alert('Напоминание отправлено инициатору через Лотус');
|
||
}
|
||
|
||
// Кнопки действий
|
||
document.getElementById('btn-approve')?.addEventListener('click', () => {
|
||
if (selectedContract) {
|
||
selectedContract.status = 'approved';
|
||
selectedContract.comment = 'Согласовано ' + new Date().toLocaleDateString('ru-RU');
|
||
saveContracts();
|
||
alert('Договор согласован и отправлен на подпись');
|
||
navigateTo('queue');
|
||
}
|
||
});
|
||
|
||
document.getElementById('btn-revision')?.addEventListener('click', () => {
|
||
if (selectedContract) {
|
||
selectedContract.status = 'revision';
|
||
selectedContract.comment = 'На доработке ' + new Date().toLocaleDateString('ru-RU');
|
||
saveContracts();
|
||
alert('Договор возвращён на доработку');
|
||
navigateTo('queue');
|
||
}
|
||
});
|
||
|
||
document.getElementById('btn-download')?.addEventListener('click', () => {
|
||
alert('Файл договора будет скачан. В рабочей версии — генерация Word через ИИ.');
|
||
});
|
||
|
||
// Запуск
|
||
init();
|