feat(core): implement secure MVP core with dictionary search, auth, and CRUD
This commit is contained in:
@@ -0,0 +1,220 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Notes — Персональный тренажёр английского языка</title>
|
||||
<link rel="stylesheet" href="/static/css/style.css">
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>📖</text></svg>">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Login Modal / Screen -->
|
||||
<div id="auth-screen" class="auth-screen hidden">
|
||||
<div class="auth-card">
|
||||
<div class="auth-header">
|
||||
<div class="app-logo">📖</div>
|
||||
<h2>Вход в Notes</h2>
|
||||
<p>Персональный словарь и тренажёр языка</p>
|
||||
</div>
|
||||
<form id="login-form">
|
||||
<div class="form-group">
|
||||
<label for="username">Имя пользователя</label>
|
||||
<input type="text" id="username" autocomplete="username" required placeholder="admin" autofocus>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Пароль</label>
|
||||
<input type="password" id="password" autocomplete="current-password" required placeholder="••••••••">
|
||||
</div>
|
||||
<div id="auth-error" class="error-banner hidden"></div>
|
||||
<button type="submit" id="login-btn" class="btn btn-primary btn-block">Войти в систему</button>
|
||||
</form>
|
||||
<div class="auth-footer">
|
||||
<span>Защищённый контур: notes.qpid.pro</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Application UI -->
|
||||
<div id="app-container" class="app-container hidden">
|
||||
<!-- Top Navigation -->
|
||||
<header class="navbar">
|
||||
<div class="nav-brand">
|
||||
<span class="brand-icon">📖</span>
|
||||
<span class="brand-title">Notes</span>
|
||||
<span class="brand-sub">English Lexicon</span>
|
||||
</div>
|
||||
|
||||
<div class="nav-stats" id="nav-stats">
|
||||
<span class="stat-badge" title="Всего слов в словаре">Всего: <strong id="stat-total">0</strong></span>
|
||||
<span class="stat-badge stat-today" title="Добавлено сегодня">Сегодня: <strong id="stat-today">+0</strong></span>
|
||||
</div>
|
||||
|
||||
<div class="nav-actions">
|
||||
<button id="theme-toggle" class="icon-btn" title="Переключить тему">🌓</button>
|
||||
<div class="user-profile">
|
||||
<span id="user-display-name" class="user-badge">user</span>
|
||||
<button id="logout-btn" class="btn btn-sm btn-outline" title="Выйти из аккаунта">Выход</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="main-content">
|
||||
<!-- Search & Translation Section -->
|
||||
<section class="search-section">
|
||||
<div class="search-box-wrapper">
|
||||
<div class="search-input-box">
|
||||
<span class="search-icon">🔍</span>
|
||||
<input type="text" id="term-input" placeholder="Введите слово, фразовый глагол или предложение..." autocomplete="off" autofocus>
|
||||
<button id="clear-search-btn" class="clear-btn hidden" title="Очистить (Esc)">✕</button>
|
||||
<button id="translate-btn" class="btn btn-primary translate-action-btn">Перевести</button>
|
||||
</div>
|
||||
|
||||
<div class="hotkey-hints">
|
||||
<span class="hint-item"><kbd>Enter</kbd> перевод</span>
|
||||
<span class="hint-item"><kbd>Ctrl</kbd>+<kbd>Enter</kbd> сохранить</span>
|
||||
<span class="hint-item"><kbd>Esc</kbd> сброс</span>
|
||||
<span class="hint-item"><kbd>Space</kbd> / <kbd>🔊</kbd> озвучить</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Loader -->
|
||||
<div id="lookup-spinner" class="lookup-spinner hidden">
|
||||
<div class="spinner"></div>
|
||||
<span>Ищем толкование, произношение и перевод...</span>
|
||||
</div>
|
||||
|
||||
<!-- Live Result Card -->
|
||||
<div id="result-card" class="result-card hidden">
|
||||
<div class="result-header">
|
||||
<div class="term-title-row">
|
||||
<h2 id="res-term" class="res-term">reluctant</h2>
|
||||
<span id="res-phonetic" class="res-phonetic badge-pill">/rɪˈlʌktənt/</span>
|
||||
<span id="res-pos" class="res-pos badge-pill">Adjective</span>
|
||||
<button id="play-audio-btn" class="audio-btn" title="Прослушать произношение">
|
||||
🔊 <span class="audio-text">Слушать</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="res-definition-box" class="definition-box">
|
||||
<div class="def-label">Толкование (English):</div>
|
||||
<p id="res-definition" class="def-text"></p>
|
||||
</div>
|
||||
|
||||
<div class="card-edit-grid">
|
||||
<div class="field-group">
|
||||
<label for="edit-translation">Перевод на русский <span class="req">*</span></label>
|
||||
<input type="text" id="edit-translation" class="input-styled" placeholder="Основной перевод...">
|
||||
<div id="translation-suggestions" class="suggestions-chips"></div>
|
||||
</div>
|
||||
|
||||
<div class="field-group">
|
||||
<label for="edit-context">Контекстное предложение (где встретилось?)</label>
|
||||
<input type="text" id="edit-context" class="input-styled" placeholder="Например: The switch drops the frame if the VLAN ID is invalid.">
|
||||
</div>
|
||||
|
||||
<div class="field-row">
|
||||
<div class="field-group flex-2">
|
||||
<label for="edit-tags">Теги (через запятую)</label>
|
||||
<input type="text" id="edit-tags" class="input-styled" placeholder="general, phrasal-verb, networking">
|
||||
<div class="quick-tags" id="quick-tags-bar">
|
||||
<span class="tag-chip" data-tag="general">#general</span>
|
||||
<span class="tag-chip" data-tag="phrasal-verb">#phrasal-verb</span>
|
||||
<span class="tag-chip" data-tag="idiom">#idiom</span>
|
||||
<span class="tag-chip" data-tag="daily">#daily</span>
|
||||
<span class="tag-chip" data-tag="tech">#tech</span>
|
||||
<span class="tag-chip" data-tag="work">#work</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field-group flex-1">
|
||||
<label for="edit-notes">Заметка / Мнемоника</label>
|
||||
<input type="text" id="edit-notes" class="input-styled" placeholder="Ассоциация...">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="result-actions">
|
||||
<button id="save-card-btn" class="btn btn-success btn-lg">
|
||||
💾 Сохранить в словарь <span class="btn-subtext">(Ctrl + Enter)</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Vocabulary Notebook & History -->
|
||||
<section class="vocabulary-section">
|
||||
<div class="section-header">
|
||||
<div class="section-title-wrap">
|
||||
<h3>📚 Мой словарь</h3>
|
||||
<span id="cards-count-label" class="cards-count-label">(0 записей)</span>
|
||||
</div>
|
||||
|
||||
<div class="list-controls">
|
||||
<div class="search-mini-box">
|
||||
<input type="text" id="filter-input" placeholder="Фильтр по слову, переводу, контексту...">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Active Tags Filter -->
|
||||
<div id="tags-filter-bar" class="tags-filter-bar">
|
||||
<button class="filter-chip active" data-tag="">Все теги</button>
|
||||
</div>
|
||||
|
||||
<!-- Cards Grid/List -->
|
||||
<div id="cards-list" class="cards-list">
|
||||
<div class="empty-state" id="empty-state">
|
||||
<div class="empty-icon">🌱</div>
|
||||
<h4>Ваш словарь пока пуст</h4>
|
||||
<p>Введите первое слово или фразу в поле поиска выше и сохраните её!</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<!-- Edit Card Modal -->
|
||||
<div id="edit-modal" class="modal-backdrop hidden">
|
||||
<div class="modal-window">
|
||||
<div class="modal-header">
|
||||
<h3>Редактирование карточки</h3>
|
||||
<button id="close-modal-btn" class="icon-btn">✕</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input type="hidden" id="modal-card-id">
|
||||
<div class="form-group">
|
||||
<label>Слово / Фраза</label>
|
||||
<input type="text" id="modal-term" class="input-styled">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Перевод на русский</label>
|
||||
<input type="text" id="modal-translation" class="input-styled">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Контекстное предложение</label>
|
||||
<input type="text" id="modal-context" class="input-styled">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Теги</label>
|
||||
<input type="text" id="modal-tags" class="input-styled">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Заметки / Мнемоника</label>
|
||||
<input type="text" id="modal-notes" class="input-styled">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="modal-cancel-btn" class="btn btn-outline">Отмена</button>
|
||||
<button id="modal-save-btn" class="btn btn-primary">Сохранить изменения</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Audio Element for native streaming -->
|
||||
<audio id="global-audio-player" preload="none"></audio>
|
||||
|
||||
<script src="/static/js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user