887abf444e
Получен handoff-пакет liderra_v8_handoff/ от дизайнера Платона (kpd9363@gmail.com) от 07.05.2026 — v8 Forest. Заказчик 08.05 решил применить только в части дизайна, имени, логотипа. Функционал, состав страниц и правила (CTO-11, click-wrap, SSO break-glass, 14 статусов воронки) — без изменений (источник — ТЗ v8.5/schema v8.5). Что сделано: - Массовая замена Лидпоток→Лидерра (с учётом падежей: Лидерры/Лидерре) в 33 файлах (449 вхождений) — все .md/.sql/.json/.toml/.yml/.txt/.html, кроме исторических упоминаний внутри liderra_v8_handoff/ - Удалён docs/brandbook.md v1.1 — заменён на BRANDBOOK_v2.md из handoff - Скопированы 13 концептов liderra_v8_handoff/concepts/v8_*.html в web/v8/. Удалены старые web/01-login.html, 02-dashboard.html, 03-deals.html, index.html (палитра v1.1 deprecated) - CLAUDE.md v1.0→v1.1: §0 (BRANDBOOK_v2 + DEVELOPER_HANDOFF в источниках), §2 (палитра Forest, Inter+JBM, Lucide), §5 п.6 (anti-pattern Inter снят — в Forest Inter наш основной шрифт), §6 (13 концептов в web/v8/) - Реестр Открытые_вопросы_v8_3.md v1.12→v1.13: добавлена запись о ребрендинге + 4 точечных расхождений handoff vs ТЗ (статусы воронки, click-wrap чекбоксы, SSO fallback, axe violations) - package.json/package-lock.json: name lidpotok→liderra 4 расхождения handoff vs ТЗ (НЕ применены, источник истины — ТЗ/schema): 1. 14 «обобщённых» статусов в BRANDBOOK_v2 §3.6 ≠ 14 slug'ов в schema.sql:2076 (совпадает 2 из 14: «Переговоры», «Оплачено»). Источник — schema/ТЗ §6.4 (реселлерская модель из аудита crm.bp-gr.ru, 6 системных + 8 настраиваемых статусов). 2. 3-й click-wrap в v8_login.html («маркетинг-опционально») ≠ ТЗ §1.5/§4.1 («согласие на ПДн», обязательное, OPEN-Ж-3). 3. SSO в v8_admin.html («локальный 2FA fallback») ≠ ТЗ OPEN-И-13 (break-glass super_admin, локальный 2FA выключен). 4. Заявление «axe-core 4.10.2 — 0 violations» в README handoff — локально Pa11y 9.1.1 + axe нашёл 81 violation на 10/13 HTML (преимущественно color-contrast на декоративных separator'ах с --ink-disabled). Чисто: settings/errors/palette_options. Что НЕ включено в коммит: - лендинг/TZ_landing_v1_0.md — untracked, не моя работа в этой сессии - .tmp/ — gitignored Что осталось (для следующих сессий): - Возможное переименование GitHub-репо CoralMinister/lidpotok → liderra (отдельное решение заказчика) - Опционально: обратная связь Платону по 4 расхождениям handoff vs ТЗ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
405 lines
34 KiB
HTML
405 lines
34 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>v8 · Настройки — Лидерра (Forest)</title>
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||
<link href="https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,400;14..32,500;14..32,600;14..32,700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
||
<style>
|
||
*, *::before, *::after { box-sizing: border-box; }
|
||
html, body { margin: 0; padding: 0; }
|
||
:root {
|
||
--bg:#F6F3EC; --surface:#FFFDFA; --sunken:#F0EDE4;
|
||
--hairline:#D9D5CD; --hairline-soft:#E8E3D6;
|
||
--ink:#081319; --ink-2:#343C41; --ink-3:#66635C; --ink-disabled:#92907B;
|
||
--accent:#0F6E56; --accent-tint:#E1EEEA; --accent-deep:#084635;
|
||
--side-bg:#012019; --side-text:#B1C2BD; --side-text-2:#7A8C87;
|
||
--side-active:#13382F; --side-icon:#5C7A72; --side-icon-act:#32C8A9;
|
||
--side-hover:#0A2A22; --side-border:#1A3A30;
|
||
--st-paid:#007EB8; --st-quote:#008A4D; --st-call:#9A6700; --st-new:#B94837;
|
||
--r-xs:4px; --r-sm:6px; --r-md:10px; --r-lg:14px;
|
||
--font-ui:'Inter',system-ui,sans-serif;
|
||
--font-mono:'JetBrains Mono',ui-monospace,monospace;
|
||
}
|
||
body { background:var(--bg); color:var(--ink); font-family:var(--font-ui); font-feature-settings:'cv11','ss01'; -webkit-font-smoothing:antialiased; font-variation-settings:'opsz' 14; min-height:100vh; }
|
||
button { font-family:inherit; }
|
||
a { color:inherit; text-decoration:none; }
|
||
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, [tabindex]:focus-visible {
|
||
outline:2px solid var(--accent); outline-offset:2px; border-radius:var(--r-sm);
|
||
}
|
||
.skip-link { position:absolute; top:-40px; left:12px; background:var(--ink); color:#fff; padding:9px 16px; z-index:200; font-weight:600; border-radius:var(--r-sm); }
|
||
.skip-link:focus { top:12px; }
|
||
|
||
/* Shell */
|
||
.app { display:grid; grid-template-columns:232px 1fr; min-height:100vh; }
|
||
.side { background:var(--side-bg); border-right:1px solid var(--side-border); padding:18px 12px 24px; position:sticky; top:0; height:100vh; overflow-y:auto; color:var(--side-text); }
|
||
.brand { display:flex; align-items:center; gap:10px; padding:6px 8px 18px; font-weight:600; font-size:14.5px; letter-spacing:-0.01em; font-variation-settings:'opsz' 18; color:#FFF; }
|
||
.brand-mark { width:22px; height:22px; border-radius:var(--r-xs); background:#FFF; display:inline-flex; align-items:center; justify-content:center; flex-shrink:0; overflow:hidden; }
|
||
.brand-mark svg { width:100%; height:100%; display:block; }
|
||
.brand-dot { color:var(--side-icon-act); }
|
||
.nav { display:flex; flex-direction:column; gap:1px; }
|
||
.nav-eyebrow { font-size:11px; font-weight:500; letter-spacing:0.01em; color:var(--side-text-2); padding:14px 10px 6px; }
|
||
.nav-item { display:flex; align-items:center; gap:10px; height:32px; padding:0 10px; border-radius:var(--r-sm); font-size:13px; color:var(--side-text); }
|
||
.nav-item:hover { background:var(--side-hover); color:#FFF; }
|
||
.nav-item.active { background:var(--side-active); color:#FFF; font-weight:500; }
|
||
.nav-item.active .nav-icon { color:var(--side-icon-act); }
|
||
.nav-icon { width:15px; height:15px; flex-shrink:0; color:var(--side-icon); stroke-width:1.6; }
|
||
.nav-item:hover .nav-icon { color:#FFF; }
|
||
.nav-text { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
||
.nav-count { font-family:var(--font-mono); font-size:10.5px; font-weight:500; font-feature-settings:'tnum'; background:rgba(255,255,255,0.10); color:var(--side-text); padding:2px 6px; border-radius:4px; }
|
||
.main { display:flex; flex-direction:column; min-width:0; }
|
||
.topbar { height:48px; border-bottom:1px solid var(--hairline); background:var(--surface); padding:0 24px; display:flex; align-items:center; gap:12px; position:sticky; top:0; z-index:50; }
|
||
.crumb { font-size:12.5px; color:var(--ink-3); display:flex; align-items:center; gap:8px; }
|
||
.crumb strong { color:var(--ink); font-weight:500; }
|
||
.crumb svg { width:11px; height:11px; color:var(--ink-3); opacity:0.5; }
|
||
.topbar-spacer { flex:1; }
|
||
.user-chip { display:inline-flex; align-items:center; gap:8px; height:30px; padding:0 10px 0 4px; border-radius:100px; border:1px solid var(--hairline); background:var(--surface); }
|
||
.user-chip .ava { width:22px; height:22px; border-radius:50%; background:var(--ink); color:#fff; display:inline-flex; align-items:center; justify-content:center; font-size:9.5px; font-weight:600; }
|
||
.user-chip .uname { font-size:12px; color:var(--ink); font-weight:500; }
|
||
|
||
/* Page */
|
||
.content { display:grid; grid-template-columns:200px 1fr; gap:28px; padding:24px 28px 80px; max-width:1500px; margin:0 auto; }
|
||
.page-h { grid-column:1 / -1; display:flex; align-items:flex-end; justify-content:space-between; margin-bottom:6px; gap:16px; }
|
||
.page-title { font-size:28px; font-weight:600; font-variation-settings:'opsz' 28; letter-spacing:-0.02em; line-height:1.1; margin:0 0 6px; }
|
||
.page-meta { font-size:12.5px; color:var(--ink-3); }
|
||
|
||
/* Settings tab rail (left) */
|
||
.tab-rail { display:flex; flex-direction:column; gap:1px; position:sticky; top:64px; align-self:start; }
|
||
.tab-rail .rail-eyebrow { font-size:10.5px; font-weight:500; letter-spacing:0.06em; text-transform:uppercase; color:var(--ink-3); padding:10px 12px 6px; font-family:var(--font-mono); }
|
||
.tab-rail button { display:flex; align-items:center; gap:9px; padding:8px 12px; border:none; background:transparent; font-family:inherit; font-size:13px; color:var(--ink-2); cursor:pointer; border-radius:var(--r-sm); text-align:left; letter-spacing:-0.005em; }
|
||
.tab-rail button:hover { background:var(--sunken); color:var(--ink); }
|
||
.tab-rail button.active { background:var(--ink); color:#fff; font-weight:500; }
|
||
.tab-rail button.active .ico { color:var(--side-icon-act); }
|
||
.tab-rail button .ico { width:14px; height:14px; color:var(--ink-3); flex-shrink:0; stroke-width:1.7; }
|
||
.tab-rail button:hover .ico { color:var(--ink); }
|
||
|
||
/* Settings tab content */
|
||
.tab-content { display:flex; flex-direction:column; gap:14px; min-width:0; }
|
||
|
||
.section { background:var(--surface); border:1px solid var(--hairline); border-radius:var(--r-md); padding:22px 24px; }
|
||
.section-h { display:flex; align-items:flex-start; justify-content:space-between; gap:16px; margin-bottom:16px; flex-wrap:wrap; }
|
||
.section-h h2 { font-size:16px; font-weight:600; font-variation-settings:'opsz' 18; letter-spacing:-0.012em; margin:0 0 4px; }
|
||
.section-h .desc { font-size:12.5px; color:var(--ink-3); line-height:1.5; max-width:520px; }
|
||
.section-h .h-action { white-space:nowrap; }
|
||
|
||
.field { display:flex; flex-direction:column; gap:6px; margin-bottom:14px; }
|
||
.field:last-child { margin-bottom:0; }
|
||
.field label { font-size:11.5px; font-weight:500; color:var(--ink-2); letter-spacing:-0.005em; }
|
||
.field .hint { font-size:11.5px; color:var(--ink-3); margin-top:2px; line-height:1.4; }
|
||
.input, .select {
|
||
height:36px; padding:0 12px;
|
||
border:1px solid var(--hairline); border-radius:var(--r-sm);
|
||
background:var(--surface); font-family:inherit; font-size:13px;
|
||
color:var(--ink); outline:none; letter-spacing:-0.005em;
|
||
}
|
||
.input.mono { font-family:var(--font-mono); font-feature-settings:'tnum'; letter-spacing:0; }
|
||
.input:focus, .select:focus { border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-tint); }
|
||
.field-row { display:grid; grid-template-columns:1fr 1fr; gap:12px; margin-bottom:14px; }
|
||
.field-row .field { margin-bottom: 0; }
|
||
|
||
.btn { display:inline-flex; align-items:center; gap:7px; height:34px; padding:0 14px; border-radius:var(--r-sm); border:1px solid var(--hairline); background:var(--surface); font-size:12.5px; font-weight:500; color:var(--ink); cursor:pointer; font-family:inherit; letter-spacing:-0.005em; }
|
||
.btn:hover { border-color:var(--ink-disabled); background:var(--sunken); }
|
||
.btn-primary { background:var(--accent); color:#fff; border-color:var(--accent); }
|
||
.btn-primary:hover { background:var(--accent-deep); border-color:var(--accent-deep); }
|
||
.btn-danger { color:var(--st-new); }
|
||
.btn-danger:hover { background:#FFE7E2; border-color:var(--st-new); color:#8E2516; }
|
||
.btn svg { width:13px; height:13px; stroke-width:1.7; }
|
||
|
||
/* Toggle switch */
|
||
.toggle { display:flex; align-items:center; justify-content:space-between; gap:14px; padding:11px 14px; background:var(--bg); border:1px solid var(--hairline-soft); border-radius:var(--r-sm); margin-bottom:6px; }
|
||
.toggle:last-child { margin-bottom: 0; }
|
||
.toggle .t-label { font-size:13px; color:var(--ink); font-weight:500; letter-spacing:-0.005em; }
|
||
.toggle .t-desc { font-size:11.5px; color:var(--ink-3); margin-top:2px; line-height:1.4; }
|
||
.toggle .switch { position:relative; width:36px; height:20px; flex-shrink:0; }
|
||
.toggle .switch input { opacity:0; width:0; height:0; position:absolute; }
|
||
.toggle .switch .slider { position:absolute; inset:0; background:var(--ink-disabled); border-radius:100px; transition:background 120ms ease; cursor:pointer; }
|
||
.toggle .switch .slider::before { content:''; position:absolute; left:2px; top:2px; width:16px; height:16px; background:#fff; border-radius:50%; transition:transform 120ms ease; }
|
||
.toggle .switch input:checked + .slider { background:var(--accent); }
|
||
.toggle .switch input:checked + .slider::before { transform:translateX(16px); }
|
||
.toggle .switch input:focus-visible + .slider { outline:2px solid var(--accent); outline-offset:2px; }
|
||
|
||
/* Avatar uploader */
|
||
.avatar-up { display:flex; align-items:center; gap:14px; }
|
||
.avatar-up .ava-big {
|
||
width:64px; height:64px; border-radius:50%;
|
||
background: var(--ink); color:#fff;
|
||
display:inline-flex; align-items:center; justify-content:center;
|
||
font-size:22px; font-weight:600; letter-spacing:0.02em;
|
||
flex-shrink:0; position:relative;
|
||
}
|
||
.avatar-up .ava-big::after { content:''; position:absolute; inset:0; border-radius:50%; border:1px solid rgba(10,19,25,0.14); }
|
||
|
||
/* API tokens table */
|
||
.token-table { width:100%; border-collapse:collapse; font-size:12.5px; }
|
||
.token-table thead th { text-align:left; font-size:10.5px; font-weight:600; color:var(--ink-2); padding:8px 0; border-bottom:1px solid var(--hairline-soft); letter-spacing:0.005em; }
|
||
.token-table thead th.num { text-align:right; }
|
||
.token-table tbody td { padding:10px 0; border-bottom:1px solid var(--hairline-soft); vertical-align:middle; }
|
||
.token-table tbody tr:last-child td { border-bottom:none; }
|
||
.token-table .t-name { font-weight:500; color:var(--ink); }
|
||
.token-table .t-name .scope { font-family:var(--font-mono); font-size:10px; color:var(--ink-3); display:block; margin-top:2px; letter-spacing:-0.005em; }
|
||
.token-table .t-token { font-family:var(--font-mono); font-feature-settings:'tnum'; font-size:11.5px; color:var(--ink-2); }
|
||
.token-table .t-when { font-family:var(--font-mono); font-feature-settings:'tnum'; font-size:11px; color:var(--ink-3); white-space:nowrap; }
|
||
.token-table .row-action { width:24px; height:24px; border:none; background:none; color:var(--ink-3); border-radius:4px; cursor:pointer; display:inline-flex; align-items:center; justify-content:center; }
|
||
.token-table .row-action:hover { background:rgba(10,19,25,0.06); color:var(--st-new); }
|
||
.token-table .row-action svg { width:13px; height:13px; }
|
||
|
||
.tab-page { display:none; }
|
||
.tab-page.active { display:contents; }
|
||
|
||
@media (max-width:1100px) {
|
||
.app { grid-template-columns:56px 1fr; }
|
||
.side { padding:14px 6px; }
|
||
.brand .brand-text, .nav-eyebrow, .nav-text, .nav-item:not(.active) .nav-count { display:none; }
|
||
.nav-item { justify-content:center; padding:0; }
|
||
.topbar { padding:0 16px; }
|
||
.content { padding:18px 18px 60px; grid-template-columns:170px 1fr; gap:20px; }
|
||
}
|
||
@media (max-width:768px) {
|
||
.app { grid-template-columns:1fr; }
|
||
.side { display:none; }
|
||
.topbar .crumb span:first-child { display:none; }
|
||
.content { grid-template-columns:1fr; gap:16px; }
|
||
.tab-rail { position:static; flex-direction:row; flex-wrap:wrap; gap:4px; padding-bottom:8px; }
|
||
.tab-rail .rail-eyebrow { display:none; }
|
||
.tab-rail button { padding:7px 10px; }
|
||
.field-row { grid-template-columns:1fr; }
|
||
.page-h { flex-direction:column; align-items:flex-start; gap:10px; }
|
||
.section { padding:16px 16px; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<a href="#main" class="skip-link">К контенту</a>
|
||
<div class="app">
|
||
<aside class="side" aria-label="Главное меню">
|
||
<div class="brand">
|
||
<span class="brand-mark" aria-hidden="true"><svg viewBox="0 0 48 48"><path d="M16 14 L16 34 L32 34" stroke="#012019" stroke-width="4.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="32" cy="34" r="3.5" fill="#0F6E56"/></svg></span>
|
||
<span class="brand-text">Лидерра<span class="brand-dot">.</span></span>
|
||
</div>
|
||
<nav class="nav">
|
||
<div class="nav-eyebrow">Работа</div>
|
||
<a class="nav-item" href="#"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg><span class="nav-text">Дашборд</span></a>
|
||
<a class="nav-item" href="#"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 6h18M6 12h12M9 18h6"/></svg><span class="nav-text">Сделки</span><span class="nav-count">247</span></a>
|
||
<a class="nav-item" href="#"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="3" width="6" height="18"/></svg><span class="nav-text">Канбан</span></a>
|
||
<a class="nav-item" href="#"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 6v6l4 2"/><circle cx="12" cy="12" r="9"/></svg><span class="nav-text">Напоминания</span><span class="nav-count">12</span></a>
|
||
<div class="nav-eyebrow">Финансы</div>
|
||
<a class="nav-item" href="#"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="6" width="18" height="13" rx="1"/></svg><span class="nav-text">Биллинг</span></a>
|
||
<a class="nav-item" href="#"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 12h18M3 6h18M3 18h18"/></svg><span class="nav-text">Отчёты</span></a>
|
||
<div class="nav-eyebrow">Команда</div>
|
||
<a class="nav-item" href="#"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><circle cx="9" cy="7" r="4"/></svg><span class="nav-text">Менеджеры</span><span class="nav-count">4</span></a>
|
||
<a class="nav-item active" href="#" aria-current="page"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg><span class="nav-text">Настройки</span></a>
|
||
</nav>
|
||
</aside>
|
||
|
||
<div class="main">
|
||
<div class="topbar">
|
||
<div class="crumb"><span>Рабочая область</span><svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M9 18l6-6-6-6"/></svg><strong>Настройки</strong></div>
|
||
<div class="topbar-spacer"></div>
|
||
<button type="button" class="user-chip" aria-label="Профиль · Иван Петров"><span class="ava" aria-hidden="true">ИП</span><span class="uname">Иван П.</span></button>
|
||
</div>
|
||
|
||
<main id="main" class="content">
|
||
|
||
<header class="page-h">
|
||
<div>
|
||
<h1 class="page-title">Настройки</h1>
|
||
<div class="page-meta">тенант <strong style="color:var(--ink-2);font-weight:500">Окна Москва ООО</strong> · 4 менеджера · тариф «Команда»</div>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- Tab rail (left column) -->
|
||
<nav class="tab-rail" role="tablist" aria-label="Разделы настроек">
|
||
<span class="rail-eyebrow">Личное</span>
|
||
<button type="button" class="active" role="tab" data-tab="profile" aria-selected="true"><svg class="ico" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle cx="12" cy="7" r="4"/><path d="M2 21v-2a4 4 0 0 1 4-4h12a4 4 0 0 1 4 4v2"/></svg>Профиль</button>
|
||
<button type="button" role="tab" data-tab="security" aria-selected="false"><svg class="ico" fill="none" stroke="currentColor" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>Безопасность</button>
|
||
<span class="rail-eyebrow">Тенант</span>
|
||
<button type="button" role="tab" data-tab="projects" aria-selected="false"><svg class="ico" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M3 7v13h18V7M3 7l3-4h12l3 4M3 7h18M9 11h6"/></svg>Проекты</button>
|
||
<button type="button" role="tab" data-tab="team" aria-selected="false"><svg class="ico" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle cx="9" cy="7" r="4"/><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>Команда</button>
|
||
<button type="button" role="tab" data-tab="api" aria-selected="false"><svg class="ico" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M21 2L13 10M16 2h5v5"/><path d="M21 13v5a2 2 0 0 1-2 2h-14a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5"/></svg>API и Webhook</button>
|
||
<button type="button" role="tab" data-tab="integrations" aria-selected="false"><svg class="ico" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle cx="6" cy="18" r="3"/><circle cx="18" cy="6" r="3"/><path d="M6 15V9a3 3 0 0 1 3-3h3M18 9v6a3 3 0 0 1-3 3h-3"/></svg>Интеграции</button>
|
||
<span class="rail-eyebrow">Тонкости</span>
|
||
<button type="button" role="tab" data-tab="hours" aria-selected="false"><svg class="ico" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>Тихие часы</button>
|
||
<button type="button" role="tab" data-tab="notifications" aria-selected="false"><svg class="ico" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M18 8a6 6 0 1 0-12 0c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>Уведомления</button>
|
||
</nav>
|
||
|
||
<!-- Tab content -->
|
||
<div class="tab-content">
|
||
|
||
<!-- ===== ПРОФИЛЬ ===== -->
|
||
<section id="tab-profile" class="tab-page active" aria-labelledby="profile-h">
|
||
<article class="section">
|
||
<div class="section-h">
|
||
<div>
|
||
<h2 id="profile-h">Профиль аккаунта</h2>
|
||
<div class="desc">Эта информация используется при заключении договоров и в подписи писем.</div>
|
||
</div>
|
||
</div>
|
||
<div class="avatar-up">
|
||
<span class="ava-big" aria-hidden="true">ИП</span>
|
||
<div style="display:flex;flex-direction:column;gap:6px">
|
||
<div style="display:flex;gap:6px"><button type="button" class="btn">Загрузить фото</button><button type="button" class="btn btn-danger">Удалить</button></div>
|
||
<div style="font-size:11.5px;color:var(--ink-3)">PNG/JPG до 2MB · квадратное · минимум 256×256</div>
|
||
</div>
|
||
</div>
|
||
<div style="height:18px"></div>
|
||
<div class="field-row">
|
||
<div class="field"><label for="p-fname">Имя</label><input class="input" id="p-fname" type="text" value="Иван"></div>
|
||
<div class="field"><label for="p-lname">Фамилия</label><input class="input" id="p-lname" type="text" value="Петров"></div>
|
||
</div>
|
||
<div class="field-row">
|
||
<div class="field"><label for="p-email">Email</label><input class="input" id="p-email" type="email" value="ivan.petrov@example.ru"></div>
|
||
<div class="field"><label for="p-phone">Телефон</label><input class="input mono" id="p-phone" type="tel" value="+7 (916) 482-91-22"></div>
|
||
</div>
|
||
<div class="field"><label for="p-role">Роль в компании</label><input class="input" id="p-role" type="text" value="Старший менеджер" placeholder="Опционально"></div>
|
||
<div style="display:flex;gap:8px;margin-top:8px"><button type="button" class="btn btn-primary">Сохранить</button><button type="button" class="btn">Отменить</button></div>
|
||
</article>
|
||
|
||
<article class="section">
|
||
<div class="section-h">
|
||
<div>
|
||
<h2>Реквизиты юр. лица</h2>
|
||
<div class="desc">Для счетов и УПД. Обновляется в админке оператором — самостоятельно не редактируется.</div>
|
||
</div>
|
||
</div>
|
||
<div class="field-row">
|
||
<div class="field"><label>Юр. лицо</label><div style="font-size:13px;color:var(--ink);font-weight:500;letter-spacing:-0.005em">ООО «Окна Москва»</div></div>
|
||
<div class="field"><label>ИНН / КПП</label><div style="font-family:var(--font-mono);font-feature-settings:'tnum';font-size:12.5px;color:var(--ink-2)">7724444444 / 772401001</div></div>
|
||
</div>
|
||
<div class="field-row">
|
||
<div class="field"><label>Юр. адрес</label><div style="font-size:12.5px;color:var(--ink-2);line-height:1.5">115093, Москва, ул. Большая Серпуховская, 32 стр. 1, оф. 405</div></div>
|
||
<div class="field"><label>Расчётный счёт</label><div style="font-family:var(--font-mono);font-size:12px;color:var(--ink-2)">40702810400000000123 · ПАО «Сбербанк»</div></div>
|
||
</div>
|
||
</article>
|
||
|
||
<article class="section">
|
||
<div class="section-h">
|
||
<div>
|
||
<h2 style="color:var(--st-new)">Удалить аккаунт</h2>
|
||
<div class="desc">Все ваши проекты, сделки, история и баланс будут <strong style="color:var(--ink-2);font-weight:500">безвозвратно удалены</strong> по 152-ФЗ. Восстановление невозможно.</div>
|
||
</div>
|
||
<button type="button" class="btn btn-danger">Удалить мой аккаунт</button>
|
||
</div>
|
||
</article>
|
||
</section>
|
||
|
||
<!-- ===== БЕЗОПАСНОСТЬ ===== -->
|
||
<section id="tab-security" class="tab-page" aria-labelledby="security-h">
|
||
<article class="section">
|
||
<div class="section-h">
|
||
<div>
|
||
<h2 id="security-h">Пароль</h2>
|
||
<div class="desc">Замена пароля каждые 90 дней не обязательна, но рекомендуется. Минимум 8 символов, оценка через zxcvbn.</div>
|
||
</div>
|
||
</div>
|
||
<div class="field"><label for="s-old">Текущий пароль</label><input class="input" id="s-old" type="password" placeholder="••••••••"></div>
|
||
<div class="field-row">
|
||
<div class="field"><label for="s-new">Новый пароль</label><input class="input" id="s-new" type="password" placeholder="Минимум 8 символов"></div>
|
||
<div class="field"><label for="s-conf">Повторите</label><input class="input" id="s-conf" type="password" placeholder=""></div>
|
||
</div>
|
||
<div style="display:flex;gap:8px;margin-top:8px"><button type="button" class="btn btn-primary">Сменить пароль</button></div>
|
||
</article>
|
||
|
||
<article class="section">
|
||
<div class="section-h">
|
||
<div>
|
||
<h2>Двухфакторная аутентификация</h2>
|
||
<div class="desc">2FA через приложение-аутентификатор (Google Authenticator, Authy, Яндекс.Ключ). Включена на всех тарифах.</div>
|
||
</div>
|
||
<button type="button" class="btn">Скачать резервные коды</button>
|
||
</div>
|
||
<div class="toggle">
|
||
<div>
|
||
<div class="t-label">Двухфакторная защита включена</div>
|
||
<div class="t-desc">Привязано к Yandex.Ключ · последний вход подтверждён 28 минут назад</div>
|
||
</div>
|
||
<label class="switch"><input type="checkbox" checked aria-label="2FA"><span class="slider" aria-hidden="true"></span></label>
|
||
</div>
|
||
</article>
|
||
|
||
<article class="section">
|
||
<div class="section-h">
|
||
<div>
|
||
<h2>Активные сессии</h2>
|
||
<div class="desc">Если видите подозрительный вход — закройте сессию и смените пароль.</div>
|
||
</div>
|
||
<button type="button" class="btn">Закрыть все, кроме текущей</button>
|
||
</div>
|
||
<table class="token-table" aria-label="Активные сессии">
|
||
<thead><tr><th>Устройство</th><th>IP / город</th><th class="num">Активна</th><th></th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="t-name">macOS · Safari 17 <span class="scope">Текущая сессия</span></td><td class="t-token">93.184.216.34 · Москва</td><td class="t-when">сейчас</td><td></td></tr>
|
||
<tr><td class="t-name">iOS · Safari Mobile</td><td class="t-token">94.51.21.108 · Москва</td><td class="t-when">3 ч назад</td><td><button type="button" class="row-action" aria-label="Закрыть сессию"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M18 6 6 18M6 6l12 12"/></svg></button></td></tr>
|
||
<tr><td class="t-name">Windows · Chrome 121</td><td class="t-token">85.142.39.18 · Санкт-Петербург</td><td class="t-when">вчера</td><td><button type="button" class="row-action" aria-label="Закрыть сессию"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M18 6 6 18M6 6l12 12"/></svg></button></td></tr>
|
||
</tbody>
|
||
</table>
|
||
</article>
|
||
</section>
|
||
|
||
<!-- ===== API И WEBHOOK ===== -->
|
||
<section id="tab-api" class="tab-page" aria-labelledby="api-h">
|
||
<article class="section">
|
||
<div class="section-h">
|
||
<div>
|
||
<h2 id="api-h">API-токены</h2>
|
||
<div class="desc">Для outbound webhook и интеграций. Все токены хранятся как <code style="font-family:var(--font-mono);font-size:11.5px;background:var(--sunken);padding:1px 4px;border-radius:3px">type="password"</code> — открытое значение видно только при создании.</div>
|
||
</div>
|
||
<button type="button" class="btn btn-primary"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Новый токен</button>
|
||
</div>
|
||
<table class="token-table" aria-label="API-токены">
|
||
<thead><tr><th>Имя · scope</th><th>Маска</th><th class="num">Создан</th><th></th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="t-name">Webhook prod <span class="scope">leads:read · deals:write</span></td><td class="t-token">lpk_••••••e91k</td><td class="t-when">12.04.2026</td><td><button type="button" class="row-action" aria-label="Удалить токен"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/></svg></button></td></tr>
|
||
<tr><td class="t-name">Я.Директ интеграция <span class="scope">leads:read</span></td><td class="t-token">lpk_••••••3xqz</td><td class="t-when">28.03.2026</td><td><button type="button" class="row-action" aria-label="Удалить токен"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/></svg></button></td></tr>
|
||
<tr><td class="t-name">Тестовый <span class="scope">leads:read · deals:read</span></td><td class="t-token">lpk_••••••9btv</td><td class="t-when">15.02.2026</td><td><button type="button" class="row-action" aria-label="Удалить токен"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/></svg></button></td></tr>
|
||
</tbody>
|
||
</table>
|
||
</article>
|
||
|
||
<article class="section">
|
||
<div class="section-h">
|
||
<div>
|
||
<h2>Webhook эндпоинты</h2>
|
||
<div class="desc">URL ваших систем, куда мы отправим лиды/события сделок. Подпись HMAC SHA-256 в заголовке X-Liderra-Sign.</div>
|
||
</div>
|
||
<button type="button" class="btn btn-primary"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>Новый эндпоинт</button>
|
||
</div>
|
||
<table class="token-table" aria-label="Webhook эндпоинты">
|
||
<thead><tr><th>URL · события</th><th>Статус (24ч)</th><th class="num">Последний</th><th></th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="t-name">https://crm.example.ru/webhook/leads <span class="scope">lead.created · lead.updated</span></td><td><span style="display:inline-flex;align-items:center;gap:6px;font-size:11px"><span style="width:7px;height:7px;border-radius:50%;background:var(--st-quote)"></span>OK · 99.97% / 412</span></td><td class="t-when">3 мин назад</td><td><button type="button" class="row-action" aria-label="Удалить"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/></svg></button></td></tr>
|
||
<tr><td class="t-name">https://bitrix.example.ru/api/lead-in <span class="scope">lead.created</span></td><td><span style="display:inline-flex;align-items:center;gap:6px;font-size:11px"><span style="width:7px;height:7px;border-radius:50%;background:var(--st-call)"></span>деградация · 96.4%</span></td><td class="t-when">12 мин назад</td><td><button type="button" class="row-action" aria-label="Удалить"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/></svg></button></td></tr>
|
||
</tbody>
|
||
</table>
|
||
</article>
|
||
</section>
|
||
|
||
<!-- остальные tab-page заглушки чтобы переключатель работал, но не выводим контент -->
|
||
<section id="tab-projects" class="tab-page"><article class="section"><h2>Проекты</h2><p style="color:var(--ink-3);font-size:13px;margin:0;line-height:1.5">Список проектов с фильтрами, архивированием, массовыми операциями. <em>Контент в следующих итерациях.</em></p></article></section>
|
||
<section id="tab-team" class="tab-page"><article class="section"><h2>Команда</h2><p style="color:var(--ink-3);font-size:13px;margin:0;line-height:1.5">Менеджеры тенанта, приглашение по email + magic-link 24ч для подрядчиков. <em>Контент в следующих итерациях.</em></p></article></section>
|
||
<section id="tab-integrations" class="tab-page"><article class="section"><h2>Интеграции</h2><p style="color:var(--ink-3);font-size:13px;margin:0;line-height:1.5">amoCRM (спринт 14–15), Bitrix24 / RetailCRM в Post-MVP. <em>Контент в следующих итерациях.</em></p></article></section>
|
||
<section id="tab-hours" class="tab-page"><article class="section"><h2>Тихие часы</h2><p style="color:var(--ink-3);font-size:13px;margin:0;line-height:1.5">start_hour / end_hour 0..23, минимум 3 часа, общий timezone тенанта. <em>Контент в следующих итерациях.</em></p></article></section>
|
||
<section id="tab-notifications" class="tab-page"><article class="section"><h2>Уведомления</h2><p style="color:var(--ink-3);font-size:13px;margin:0;line-height:1.5">Push, email, Telegram-канал команды. <em>Контент в следующих итерациях.</em></p></article></section>
|
||
|
||
</div>
|
||
</main>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
const tabs = Array.from(document.querySelectorAll('.tab-rail [role="tab"]'));
|
||
const pages = Array.from(document.querySelectorAll('.tab-page'));
|
||
function setTab(id) {
|
||
tabs.forEach(t => {
|
||
const isA = t.dataset.tab === id;
|
||
t.classList.toggle('active', isA);
|
||
t.setAttribute('aria-selected', isA ? 'true' : 'false');
|
||
});
|
||
pages.forEach(p => p.classList.toggle('active', p.id === 'tab-' + id));
|
||
}
|
||
tabs.forEach(t => t.addEventListener('click', () => setTab(t.dataset.tab)));
|
||
</script>
|
||
</body>
|
||
</html>
|