/** * App - точка входа и инициализация */ (function() { 'use strict'; function init() { window.aiAdapter = window.aiAdapter || {}; window.storage = window.storage || {}; window.matcher = window.matcher || {}; const savedState = window.storage.loadState(); if (savedState && savedState.schemaVersion) { window.ui.setState({ vacancyText: savedState.vacancyText || '', resumeText: savedState.resumeText || '', criteria: savedState.criteria || [], matchResults: savedState.matchResults || null, questions: savedState.questions || [] }); if (savedState.vacancyText) { const vacancyField = document.getElementById('vacancyText'); if (vacancyField) { vacancyField.value = savedState.vacancyText; } } if (savedState.resumeText) { const resumeField = document.getElementById('resumeText'); if (resumeField) { resumeField.value = savedState.resumeText; } } } window.ui.initUI(); setupAutoSave(); setupKeyboardNavigation(); console.log('HR Candidate Matcher запущен'); } function setupAutoSave() { setInterval(() => { const state = window.ui.getState(); const toSave = { vacancyText: state.vacancyText, resumeText: state.resumeText, criteria: state.criteria, matchResults: state.matchResults, questions: state.questions }; window.storage.saveState(toSave); }, 5000); document.getElementById('vacancyText')?.addEventListener('blur', () => { const state = window.ui.getState(); window.storage.saveState({ vacancyText: state.vacancyText }); }); document.getElementById('resumeText')?.addEventListener('blur', () => { const state = window.ui.getState(); window.storage.saveState({ resumeText: state.resumeText }); }); } function setupKeyboardNavigation() { document.addEventListener('keydown', (e) => { if (e.key === 'Escape') { const currentState = window.ui.getState().currentScreen; if (currentState === 'interview') { window.ui.navigateTo('match'); } else if (currentState === 'match') { window.ui.navigateTo('criteria'); } else if (currentState === 'criteria') { window.ui.navigateTo('input'); } } if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') { const currentState = window.ui.getState().currentScreen; if (currentState === 'input') { document.getElementById('btnExtract')?.click(); } else if (currentState === 'criteria') { document.getElementById('btnApplyCriteria')?.click(); } } if ((e.ctrlKey || e.metaKey) && e.key === 's') { e.preventDefault(); const state = window.ui.getState(); const saved = window.storage.saveState({ vacancyText: state.vacancyText, resumeText: state.resumeText, criteria: state.criteria, matchResults: state.matchResults, questions: state.questions }); if (saved) { window.ui.showNotification('Данные сохранены', 'success'); } else { window.ui.showNotification('Ошибка сохранения', 'error'); } } }); } function checkBrowserSupport() { const issues = []; if (!window.localStorage) { issues.push('localStorage недоступен'); } if (!window.navigator.clipboard) { console.warn('Clipboard API недоступен — копирование будет работать через выделение текста'); } if (!window.Blob) { issues.push('Blob не поддерживается — экспорт не будет работать'); } if (!window.URL) { issues.push('URL.createObjectURL не поддерживается — скачивание не будет работать'); } if (issues.length > 0) { console.warn('Проблемы с поддержкой браузера:', issues.join(', ')); window.ui.showNotification( 'Внимание: Некоторые функции могут работать нестабильно', 'error' ); } return issues.length === 0; } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { checkBrowserSupport(); init(); }); } else { checkBrowserSupport(); init(); } })();