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>
545 lines
48 KiB
HTML
545 lines
48 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>v8 · Админка SaaS — Лидерра (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; --st-fail:#6C60C4;
|
||
--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;
|
||
--imp-red: #B94837;
|
||
}
|
||
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 {
|
||
outline:2px solid var(--accent); outline-offset:2px; border-radius:var(--r-sm);
|
||
}
|
||
|
||
/* Review-only state switcher */
|
||
.review-bar { position:sticky; top:0; z-index:100; background:var(--side-bg); padding:10px 16px; display:flex; align-items:center; gap:14px; border-bottom:1px solid #1A3A30; flex-wrap:wrap; }
|
||
.review-bar .label { font-size:11px; font-weight:600; letter-spacing:0.06em; color:#7A8C87; font-family:var(--font-mono); }
|
||
.review-bar .tabs { display:flex; gap:2px; flex-wrap:wrap; }
|
||
.review-bar .tab { height:26px; padding:0 12px; border:none; background:transparent; color:#B1C2BD; font-family:inherit; font-size:12px; font-weight:500; cursor:pointer; border-radius:4px; }
|
||
.review-bar .tab:hover { background:#0A2A22; color:#fff; }
|
||
.review-bar .tab.active { background:#fff; color:#012019; }
|
||
|
||
/* Impersonation banner — only visible on tenant-card-imp */
|
||
.imp-banner {
|
||
background: var(--imp-red); color: #fff;
|
||
padding: 9px 24px;
|
||
display: flex; align-items: center; gap: 12px; justify-content: space-between;
|
||
font-size: 12.5px;
|
||
position: sticky; top: 47px; z-index: 90;
|
||
}
|
||
.imp-banner svg { width: 14px; height: 14px; }
|
||
.imp-banner strong { font-weight: 600; }
|
||
.imp-banner button {
|
||
height: 24px; padding: 0 10px;
|
||
border: 1px solid rgba(255,255,255,0.30);
|
||
background: rgba(255,255,255,0.10);
|
||
color: #fff;
|
||
font-family: inherit; font-size: 11px; font-weight: 500;
|
||
border-radius: 4px; cursor: pointer;
|
||
}
|
||
.imp-banner button:hover { background: rgba(255,255,255,0.18); }
|
||
|
||
/* App shell — same Forest with admin variation */
|
||
.app { display:grid; grid-template-columns:232px 1fr; min-height:calc(100vh - 47px); }
|
||
.side { background:var(--side-bg); border-right:1px solid var(--side-border); padding:18px 12px 24px; position:sticky; top:47px; height:calc(100vh - 47px); overflow-y:auto; color:var(--side-text); }
|
||
.brand { display:flex; align-items:center; gap:10px; padding:6px 8px 4px; 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); }
|
||
.brand-sub { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0.08em; color: var(--side-icon-act); padding: 0 8px 16px; font-weight: 600; }
|
||
.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); cursor: pointer; }
|
||
.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:47px; 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; }
|
||
.crumb a { cursor:pointer; }
|
||
.crumb a:hover { color:var(--ink); }
|
||
.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; }
|
||
|
||
.content { padding:24px 28px 60px; flex:1; max-width: 1700px; margin: 0 auto; width:100%; }
|
||
.page-h { display:flex; align-items:flex-end; justify-content:space-between; margin-bottom:18px; gap:16px; flex-wrap: wrap; }
|
||
.page-title { font-size:26px; font-weight:600; font-variation-settings:'opsz' 26; letter-spacing:-0.02em; line-height:1.1; margin:0 0 6px; }
|
||
.page-meta { font-size:12.5px; color:var(--ink-3); display:flex; gap:14px; align-items:center; flex-wrap:wrap; }
|
||
.page-meta .num { font-family:var(--font-mono); font-feature-settings:'tnum'; color:var(--ink-2); font-weight:500; }
|
||
.page-meta .sep { color:var(--ink-disabled); }
|
||
|
||
.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; }
|
||
|
||
/* SSO login screen */
|
||
.sso-shell { min-height:calc(100vh - 47px); display:grid; grid-template-columns:1fr 1fr; }
|
||
.sso-brand { background:var(--side-bg); color:#fff; padding:56px 60px; display:flex; flex-direction:column; justify-content:space-between; }
|
||
.sso-brand .head { display:flex; align-items:center; gap:10px; font-weight:600; font-size:16px; }
|
||
.sso-brand .head .mark { width:24px; height:24px; border-radius:5px; background:#fff; display:inline-flex; align-items:center; justify-content:center; overflow:hidden; }
|
||
.sso-brand .head .mark svg { width:100%; height:100%; }
|
||
.sso-brand .head .dot { color:var(--side-icon-act); }
|
||
.sso-brand .head .admin-tag { font-family:var(--font-mono); font-size:10px; letter-spacing:0.06em; padding:2px 6px; border-radius:3px; background:var(--imp-red); color:#fff; margin-left:auto; font-weight:600; }
|
||
.sso-brand .body { font-size:30px; font-weight:500; font-variation-settings:'opsz' 28; letter-spacing:-0.02em; line-height:1.2; max-width:440px; }
|
||
.sso-brand .body em { color: var(--side-icon-act); font-style: normal; }
|
||
.sso-brand .foot { font-size:12px; color:#7A8C87; font-family:var(--font-mono); }
|
||
.sso-form { background:var(--bg); display:flex; align-items:center; justify-content:center; padding:40px 32px; }
|
||
.sso-card { width:100%; max-width:380px; display:flex; flex-direction:column; gap:18px; }
|
||
.sso-card h1 { font-size:24px; font-weight:600; font-variation-settings:'opsz' 24; letter-spacing:-0.018em; margin:0 0 6px; line-height:1.2; }
|
||
.sso-card p { font-size:12.5px; color:var(--ink-3); line-height:1.5; margin:0; }
|
||
.sso-button {
|
||
display:flex; align-items:center; justify-content:center; gap:8px;
|
||
width:100%;
|
||
height:48px; padding:0 18px;
|
||
border:1px solid var(--ink); border-radius:var(--r-sm);
|
||
background:var(--ink); color:#fff;
|
||
font-size:13.5px; font-weight:500;
|
||
cursor:pointer; font-family:inherit;
|
||
letter-spacing:-0.005em;
|
||
}
|
||
.sso-button:hover { background:#000; }
|
||
.sso-button .y-ico {
|
||
width:20px; height:20px;
|
||
background:#FF0000; color:#fff;
|
||
border-radius:50%;
|
||
display:inline-flex; align-items:center; justify-content:center;
|
||
font-weight:700; font-size:11px;
|
||
font-family:Inter,sans-serif;
|
||
}
|
||
.sso-fallback { font-size:11.5px; color:var(--ink-3); text-align:center; }
|
||
.sso-fallback a { color:var(--accent); font-weight:500; }
|
||
.sso-fallback a:hover { text-decoration:underline; }
|
||
|
||
/* Tenants table */
|
||
.t-controls { display:flex; align-items:center; gap:10px; margin-bottom:14px; flex-wrap:wrap; }
|
||
.search-input { display:inline-flex; align-items:center; gap:8px; flex:1; min-width:240px; height:34px; padding:0 12px; border:1px solid var(--hairline); border-radius:var(--r-sm); background:var(--surface); }
|
||
.search-input svg { width:13px; height:13px; color:var(--ink-3); }
|
||
.search-input input { flex:1; min-width:0; border:none; outline:none; background:none; font-family:inherit; font-size:13px; color:var(--ink); }
|
||
.search-input input::placeholder { color:var(--ink-3); }
|
||
.fbtn { height:34px; padding:0 12px; border:1px solid var(--hairline); border-radius:var(--r-sm); background:var(--surface); font-family:inherit; font-size:12px; color:var(--ink-2); cursor:pointer; display:inline-flex; align-items:center; gap:6px; }
|
||
.fbtn:hover { border-color:var(--ink-disabled); }
|
||
.fbtn svg { width:12px; height:12px; color:var(--ink-3); }
|
||
|
||
.tbl-wrap { background:var(--surface); border:1px solid var(--hairline); border-radius:var(--r-md); overflow:hidden; }
|
||
.tbl { width:100%; border-collapse:collapse; font-size:12.5px; }
|
||
.tbl thead th { text-align:left; font-size:10.5px; font-weight:600; color:var(--ink-2); padding:10px 14px; background:var(--sunken); border-bottom:1px solid var(--hairline); white-space:nowrap; letter-spacing:0.005em; }
|
||
.tbl thead th.num { text-align:right; }
|
||
.tbl tbody tr { border-bottom:1px solid var(--hairline-soft); cursor:pointer; }
|
||
.tbl tbody tr:last-child { border-bottom:none; }
|
||
.tbl tbody tr:hover { background:var(--sunken); }
|
||
.tbl tbody td { padding:10px 14px; vertical-align:middle; }
|
||
.tbl .t-name { font-weight:500; color:var(--ink); }
|
||
.tbl .t-name .sub { display:block; font-size:11px; color:var(--ink-3); margin-top:2px; font-family:var(--font-mono); font-feature-settings:'tnum'; }
|
||
.tbl .t-balance, .tbl .t-today, .tbl .t-mr { font-family:var(--font-mono); font-feature-settings:'tnum'; text-align:right; }
|
||
.tbl .t-balance.low { color:var(--st-new); font-weight:500; }
|
||
.tbl .t-since { font-family:var(--font-mono); font-feature-settings:'tnum'; font-size:11px; color:var(--ink-3); white-space:nowrap; }
|
||
|
||
.chip { display:inline-flex; align-items:center; gap:6px; font-size:11.5px; font-weight:500; }
|
||
.chip .dot { width:6px; height:6px; border-radius:50%; position:relative; }
|
||
.chip .dot::after { content:''; position:absolute; inset:-1px; border-radius:50%; border:1px solid rgba(10,19,25,0.10); }
|
||
.chip-active .dot { background:var(--st-quote); }
|
||
.chip-trial .dot { background:var(--st-paid); }
|
||
.chip-overdue .dot { background:var(--st-new); }
|
||
.chip-suspended .dot { background:var(--ink-disabled); }
|
||
|
||
/* Tenant card */
|
||
.tc-row { display:grid; grid-template-columns:1fr 360px; gap:16px; }
|
||
.tc-main { display:flex; flex-direction:column; gap:14px; }
|
||
.tc-aside { display:flex; flex-direction:column; gap:14px; }
|
||
.tc-head {
|
||
background:var(--surface); border:1px solid var(--hairline);
|
||
border-radius:var(--r-md); padding:22px 24px;
|
||
}
|
||
.tc-name { font-size:24px; font-weight:600; font-variation-settings:'opsz' 24; letter-spacing:-0.018em; margin:0 0 6px; }
|
||
.tc-meta { font-size:12.5px; color:var(--ink-3); display:flex; gap:12px; flex-wrap:wrap; }
|
||
.tc-meta .id { font-family:var(--font-mono); color:var(--accent); font-weight:600; }
|
||
.tc-meta .sep { color:var(--ink-disabled); }
|
||
.tc-actions { display:flex; gap:8px; margin-top:14px; flex-wrap:wrap; }
|
||
.tc-actions .imp { background:var(--imp-red); color:#fff; border-color:var(--imp-red); }
|
||
.tc-actions .imp:hover { background:#8E2516; border-color:#8E2516; }
|
||
|
||
.tc-section { background:var(--surface); border:1px solid var(--hairline); border-radius:var(--r-md); padding:18px 22px; }
|
||
.tc-section h2 { font-size:13px; font-weight:600; color:var(--ink-3); letter-spacing:0.005em; text-transform:uppercase; margin:0 0 12px; }
|
||
|
||
.kv-grid { display:grid; grid-template-columns:120px 1fr; gap:9px 14px; font-size:13px; }
|
||
.kv-grid .k { color:var(--ink-3); font-size:12px; }
|
||
.kv-grid .v { color:var(--ink); }
|
||
.kv-grid .v.mono { font-family:var(--font-mono); font-feature-settings:'tnum'; font-size:12px; }
|
||
|
||
.adj-form { display:grid; grid-template-columns:120px 1fr auto; gap:8px; align-items:center; margin-bottom:8px; }
|
||
.adj-form .input { height:34px; padding:0 10px; border:1px solid var(--hairline); border-radius:var(--r-sm); font-family:var(--font-mono); font-size:13px; }
|
||
|
||
.timeline-mini { display:flex; flex-direction:column; gap:12px; padding-left:16px; position:relative; }
|
||
.timeline-mini::before { content:''; position:absolute; left:5px; top:6px; bottom:6px; width:1px; background:var(--hairline); }
|
||
.tm-item { position:relative; }
|
||
.tm-item::before { content:''; position:absolute; left:-16px; top:4px; width:9px; height:9px; border-radius:50%; background:var(--surface); border:1.5px solid var(--ink-disabled); }
|
||
.tm-item.acc::before { background:var(--accent); border-color:var(--accent); }
|
||
.tm-item.warn::before { background:var(--st-call); border-color:var(--st-call); }
|
||
.tm-item.dang::before { background:var(--st-new); border-color:var(--st-new); }
|
||
.tm-when { font-family:var(--font-mono); font-size:10.5px; color:var(--ink-3); }
|
||
.tm-text { font-size:12px; color:var(--ink); margin-top:2px; line-height:1.45; }
|
||
|
||
/* Incidents */
|
||
.inc-row { display:grid; grid-template-columns:auto 100px 1fr 120px auto; gap:14px; padding:11px 18px; border-bottom:1px solid var(--hairline-soft); align-items:center; font-size:12.5px; }
|
||
.inc-row:last-child { border-bottom:none; }
|
||
.inc-row:hover { background:var(--sunken); cursor:pointer; }
|
||
.inc-id { font-family:var(--font-mono); font-feature-settings:'tnum'; font-size:11px; color:var(--accent); font-weight:500; }
|
||
.inc-when { font-family:var(--font-mono); font-feature-settings:'tnum'; font-size:11.5px; color:var(--ink-3); }
|
||
.inc-title { color:var(--ink); }
|
||
.inc-title .scope { display:block; font-size:11px; color:var(--ink-3); margin-top:2px; }
|
||
.inc-tenant { font-size:11.5px; color:var(--ink-2); }
|
||
.inc-sev { padding:2px 8px; border-radius:100px; font-size:10.5px; font-weight:600; letter-spacing:0.04em; font-family:var(--font-mono); }
|
||
.inc-sev.high { background:#FFE7E2; color:#8E2516; }
|
||
.inc-sev.med { background:#FFF4DD; color:#7B4D00; }
|
||
.inc-sev.low { background:var(--accent-tint); color:var(--accent-deep); }
|
||
|
||
/* System cards */
|
||
.sys-grid { display:grid; grid-template-columns:repeat(3, 1fr); gap:14px; }
|
||
.sys-card { background:var(--surface); border:1px solid var(--hairline); border-radius:var(--r-md); padding:18px 20px; cursor:pointer; }
|
||
.sys-card:hover { border-color:var(--ink-disabled); }
|
||
.sys-card .sc-h { display:flex; align-items:center; gap:10px; margin-bottom:8px; }
|
||
.sys-card .sc-ico { width:30px; height:30px; border-radius:var(--r-sm); background:var(--bg); display:inline-flex; align-items:center; justify-content:center; color:var(--accent); }
|
||
.sys-card .sc-ico svg { width:14px; height:14px; stroke-width:1.7; }
|
||
.sys-card .sc-name { font-size:14px; font-weight:600; letter-spacing:-0.012em; color:var(--ink); }
|
||
.sys-card .sc-desc { font-size:12px; color:var(--ink-3); line-height:1.45; }
|
||
.sys-card .sc-meta { font-size:11px; color:var(--ink-3); margin-top:10px; font-family:var(--font-mono); font-feature-settings:'tnum'; letter-spacing:-0.005em; }
|
||
.sys-card .sc-meta strong { color:var(--ink-2); font-weight:500; }
|
||
|
||
.tab-page { display:none; }
|
||
.tab-page.active { display:contents; }
|
||
|
||
@media (max-width:1100px) {
|
||
.app { grid-template-columns:56px 1fr; }
|
||
.side { padding:14px 6px; }
|
||
.brand-sub, .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; }
|
||
.tc-row { grid-template-columns:1fr; }
|
||
.sys-grid { grid-template-columns:repeat(2, 1fr); }
|
||
.sso-shell { grid-template-columns:1fr; }
|
||
.sso-brand { padding:32px 24px; min-height:200px; }
|
||
}
|
||
@media (max-width:768px) {
|
||
.app { grid-template-columns:1fr; }
|
||
.side { display:none; }
|
||
.topbar .crumb span:first-child { display:none; }
|
||
.sys-grid { grid-template-columns:1fr; }
|
||
.tbl thead { display:none; }
|
||
.tbl, .tbl tbody, .tbl tr, .tbl td { display:block; width:100%; }
|
||
.tbl tbody tr { padding:12px; border:1px solid var(--hairline-soft); border-radius:var(--r-sm); margin-bottom:8px; }
|
||
.tbl tbody td { padding:3px 0; border:none; }
|
||
.inc-row { grid-template-columns:1fr; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<nav class="review-bar" aria-label="Состояние админ-экрана (только для review)">
|
||
<span class="label">PREVIEW · ADMIN</span>
|
||
<div class="tabs" role="tablist">
|
||
<button type="button" class="tab active" data-tab="login" role="tab" aria-selected="true">SSO Вход</button>
|
||
<button type="button" class="tab" data-tab="tenants" role="tab" aria-selected="false">Тенанты</button>
|
||
<button type="button" class="tab" data-tab="tenant-card" role="tab" aria-selected="false">Карточка тенанта</button>
|
||
<button type="button" class="tab" data-tab="impersonation" role="tab" aria-selected="false">Импersonation-режим</button>
|
||
<button type="button" class="tab" data-tab="incidents" role="tab" aria-selected="false">Инциденты</button>
|
||
<button type="button" class="tab" data-tab="system" role="tab" aria-selected="false">Система</button>
|
||
</div>
|
||
</nav>
|
||
|
||
<!-- ===== ADMIN/LOGIN — SSO ===== -->
|
||
<section id="page-login" class="tab-page active">
|
||
<div class="sso-shell">
|
||
<aside class="sso-brand" aria-label="Брендинг">
|
||
<div class="head">
|
||
<span class="mark"><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>Лидерра<span class="dot">.</span></span>
|
||
<span class="admin-tag">ADMIN</span>
|
||
</div>
|
||
<div class="body">Операторская <em>SaaS-инструмент</em>.<br>Управление тенантами, биллингом, инцидентами.</div>
|
||
<div class="foot">v8 Forest · ограниченный доступ · все действия логируются в saas_admin_audit_log</div>
|
||
</aside>
|
||
<main class="sso-form">
|
||
<div class="sso-card">
|
||
<h1>Вход в админку</h1>
|
||
<p>SSO через Yandex 360 — основной путь. 2FA-fallback в крайнем случае.</p>
|
||
<button type="button" class="sso-button">
|
||
<span class="y-ico">Я</span>
|
||
Войти через Yandex 360
|
||
</button>
|
||
<div style="display:flex;align-items:center;gap:12px;margin:4px 0;color:var(--ink-3);font-size:11px"><span style="flex:1;height:1px;background:var(--hairline)"></span>или<span style="flex:1;height:1px;background:var(--hairline)"></span></div>
|
||
<button type="button" class="btn" style="height:42px;justify-content:center;width:100%">
|
||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
|
||
Локальный пароль + 2FA
|
||
</button>
|
||
<div class="sso-fallback">
|
||
Лимит 5 попыток / 15 минут · capture после 2 неудач · email при новом устройстве. <a href="#">Документация</a>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== ADMIN/TENANTS — list ===== -->
|
||
<section id="page-tenants" class="tab-page">
|
||
<div class="app">
|
||
<aside class="side" aria-label="Главное меню">
|
||
<div class="brand">
|
||
<span class="brand-mark"><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>Лидерра<span class="brand-dot">.</span></span>
|
||
</div>
|
||
<div class="brand-sub">ADMIN</div>
|
||
<nav class="nav">
|
||
<div class="nav-item active"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/></svg><span class="nav-text">Тенанты</span><span class="nav-count">142</span></div>
|
||
<div class="nav-item"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><rect x="3" y="6" width="18" height="13" rx="1"/></svg><span class="nav-text">Биллинг</span></div>
|
||
<div class="nav-item"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/></svg><span class="nav-text">Инциденты</span><span class="nav-count">3</span></div>
|
||
<div class="nav-item"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/></svg><span class="nav-text">Система</span></div>
|
||
</nav>
|
||
</aside>
|
||
<div class="main">
|
||
<div class="topbar">
|
||
<div class="crumb"><span>Админка</span><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M9 18l6-6-6-6"/></svg><strong>Тенанты</strong></div>
|
||
<div class="topbar-spacer"></div>
|
||
<span class="user-chip"><span class="ava">АО</span><span class="uname">Админ Оператор</span></span>
|
||
</div>
|
||
<main class="content">
|
||
<header class="page-h">
|
||
<div>
|
||
<h1 class="page-title">Тенанты</h1>
|
||
<div class="page-meta">
|
||
<span><span class="num">142</span> всего</span><span class="sep">·</span>
|
||
<span><span class="num">128</span> активны</span><span class="sep">·</span>
|
||
<span><span class="num">9</span> trial</span><span class="sep">·</span>
|
||
<span><span class="num">5</span> просрочка</span><span class="sep">·</span>
|
||
<span>выручка месяц <span class="num">1 248 600 ₽</span></span>
|
||
</div>
|
||
</div>
|
||
<div style="display:flex;gap:8px"><button type="button" class="btn"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7,10 12,15 17,10"/></svg>Экспорт</button></div>
|
||
</header>
|
||
<div class="t-controls">
|
||
<label class="search-input"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg><input type="search" placeholder="ИНН, юр. лицо, email админа…" aria-label="Поиск тенантов"></label>
|
||
<button type="button" class="fbtn"><span style="color:var(--ink-3)">Статус:</span><strong>Все</strong><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M6 9l6 6 6-6"/></svg></button>
|
||
<button type="button" class="fbtn"><span style="color:var(--ink-3)">Тариф:</span><strong>Все</strong><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M6 9l6 6 6-6"/></svg></button>
|
||
<button type="button" class="fbtn"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M22 3H2l8 9.46V19l4 2v-8.54L22 3z"/></svg>Ещё</button>
|
||
</div>
|
||
<div class="tbl-wrap">
|
||
<table class="tbl">
|
||
<thead><tr><th scope="col">Тенант</th><th scope="col">Статус</th><th scope="col">Тариф</th><th class="num" scope="col">Баланс ₽</th><th class="num" scope="col">Желаем×факт сегодня</th><th class="num" scope="col">MRR</th><th scope="col">Активность</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="t-name">Окна Москва ООО<span class="sub">ИНН 7724444444</span></td><td><span class="chip chip-active"><span class="dot"></span>Активен</span></td><td>Команда</td><td class="t-balance">14 250</td><td class="t-today">12 × 11</td><td class="t-mr">990</td><td class="t-since">28 мин назад</td></tr>
|
||
<tr><td class="t-name">Натяжные потолки СПб<span class="sub">ИНН 7805123456</span></td><td><span class="chip chip-active"><span class="dot"></span>Активен</span></td><td>Команда</td><td class="t-balance">38 100</td><td class="t-today">8 × 14</td><td class="t-mr">990</td><td class="t-since">14 мин назад</td></tr>
|
||
<tr><td class="t-name">Кухни на заказ Екб<span class="sub">ИНН 6671987654</span></td><td><span class="chip chip-active"><span class="dot"></span>Активен</span></td><td>Pro</td><td class="t-balance">112 800</td><td class="t-today">5 × 6</td><td class="t-mr">2 990</td><td class="t-since">1 ч назад</td></tr>
|
||
<tr><td class="t-name">Ремонт под ключ<span class="sub">ИНН 5024333222</span></td><td><span class="chip chip-trial"><span class="dot"></span>Trial · 4 дня</span></td><td>Trial</td><td class="t-balance">450</td><td class="t-today">3 × 0</td><td class="t-mr" style="color:var(--ink-3)">—</td><td class="t-since">3 ч назад</td></tr>
|
||
<tr><td class="t-name">Двери Премиум<span class="sub">ИНН 7732111000</span></td><td><span class="chip chip-overdue"><span class="dot"></span>Просрочка 3 дня</span></td><td>Команда</td><td class="t-balance low">−1 200</td><td class="t-today">0 × 0</td><td class="t-mr">990</td><td class="t-since">2 дня</td></tr>
|
||
<tr><td class="t-name">Оконные системы РФ<span class="sub">ИНН 7707654321</span></td><td><span class="chip chip-suspended"><span class="dot"></span>Приостановлен</span></td><td>Start</td><td class="t-balance" style="color:var(--ink-disabled)">0</td><td class="t-today">0 × 0</td><td class="t-mr" style="color:var(--ink-3)">—</td><td class="t-since">7 дней</td></tr>
|
||
<tr><td class="t-name">Кухонная мебель Спб<span class="sub">ИНН 7813222333</span></td><td><span class="chip chip-active"><span class="dot"></span>Активен</span></td><td>Enterprise</td><td class="t-balance">486 200</td><td class="t-today">28 × 31</td><td class="t-mr">9 990</td><td class="t-since">8 мин назад</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== ADMIN/TENANT-CARD ===== -->
|
||
<section id="page-tenant-card" class="tab-page">
|
||
<div class="app">
|
||
<aside class="side"><div class="brand"><span class="brand-mark"><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>Лидерра<span class="brand-dot">.</span></span></div><div class="brand-sub">ADMIN</div><nav class="nav"><div class="nav-item active"><svg class="nav-icon" 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"/></svg><span class="nav-text">Тенанты</span><span class="nav-count">142</span></div><div class="nav-item"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><rect x="3" y="6" width="18" height="13" rx="1"/></svg><span class="nav-text">Биллинг</span></div><div class="nav-item"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/></svg><span class="nav-text">Инциденты</span><span class="nav-count">3</span></div><div class="nav-item"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/></svg><span class="nav-text">Система</span></div></nav></aside>
|
||
<div class="main">
|
||
<div class="topbar">
|
||
<div class="crumb"><span>Админка</span><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M9 18l6-6-6-6"/></svg><a>Тенанты</a><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M9 18l6-6-6-6"/></svg><strong>Окна Москва ООО</strong></div>
|
||
<div class="topbar-spacer"></div>
|
||
<span class="user-chip"><span class="ava">АО</span><span class="uname">Админ Оператор</span></span>
|
||
</div>
|
||
<main class="content">
|
||
<div class="tc-row">
|
||
<div class="tc-main">
|
||
<header class="tc-head">
|
||
<h1 class="tc-name">Окна Москва ООО</h1>
|
||
<div class="tc-meta">
|
||
<span class="id">#TNT-0042</span>
|
||
<span>ИНН 7724444444 / КПП 772401001</span>
|
||
<span class="sep">·</span>
|
||
<span>с 12.04.2026 (3 недели)</span>
|
||
<span class="sep">·</span>
|
||
<span><span class="chip chip-active"><span class="dot"></span>Активен</span></span>
|
||
</div>
|
||
<div class="tc-actions">
|
||
<button type="button" class="btn"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M12 20h9M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4z"/></svg>Редактировать</button>
|
||
<button type="button" class="btn"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7,10 12,15 17,10"/></svg>Корректировать баланс</button>
|
||
<button type="button" class="btn imp"><svg 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" class="btn btn-danger"><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>Удалить (152-ФЗ)</button>
|
||
</div>
|
||
</header>
|
||
<section class="tc-section">
|
||
<h2>Профиль</h2>
|
||
<div class="kv-grid">
|
||
<span class="k">Юр. лицо</span><span class="v">ООО «Окна Москва»</span>
|
||
<span class="k">Юр. адрес</span><span class="v">115093, Москва, ул. Большая Серпуховская, 32 стр. 1, оф. 405</span>
|
||
<span class="k">Расчётный счёт</span><span class="v mono">40702810400000000123 · ПАО «Сбербанк»</span>
|
||
<span class="k">Email админа</span><span class="v">ivan.petrov@example.ru</span>
|
||
<span class="k">Телефон</span><span class="v mono">+7 (495) 482-91-22</span>
|
||
<span class="k">Тариф</span><span class="v">Команда (990 ₽/мес) · автопродление</span>
|
||
<span class="k">Активные проекты</span><span class="v mono">3 / 10</span>
|
||
<span class="k">Менеджеры</span><span class="v mono">4</span>
|
||
</div>
|
||
</section>
|
||
<section class="tc-section">
|
||
<h2>Корректировка баланса</h2>
|
||
<div class="adj-form">
|
||
<input type="text" class="input" placeholder="Сумма" value="+ 5 000">
|
||
<input type="text" class="input" placeholder="Причина (обязательно)" value="Возврат по обращению ticket-2841: ошибка дублирования лида">
|
||
<button type="button" class="btn btn-primary">Применить</button>
|
||
</div>
|
||
<div style="font-size:11px;color:var(--ink-3);margin-top:6px">Запись в saas_admin_audit_log будет создана автоматически. Действие обратимо в течение 24 часов.</div>
|
||
</section>
|
||
</div>
|
||
<aside class="tc-aside">
|
||
<section class="tc-section">
|
||
<h2>Баланс и активность</h2>
|
||
<div class="kv-grid">
|
||
<span class="k">Баланс ₽</span><span class="v mono" style="color:var(--accent);font-weight:600">14 250 ₽</span>
|
||
<span class="k">Лидов запас</span><span class="v mono">285</span>
|
||
<span class="k">Желаем сегодня</span><span class="v mono">12</span>
|
||
<span class="k">Факт сегодня</span><span class="v mono">11</span>
|
||
<span class="k">MRR</span><span class="v mono">990 ₽</span>
|
||
<span class="k">LTV (3 нед.)</span><span class="v mono">2 970 ₽</span>
|
||
</div>
|
||
</section>
|
||
<section class="tc-section">
|
||
<h2>Журнал действий</h2>
|
||
<div class="timeline-mini">
|
||
<div class="tm-item warn"><div class="tm-when">07.05 · 14:48</div><div class="tm-text">Админ <strong>Иван Оператор</strong> вошёл как клиент (impersonation, 4 мин)</div></div>
|
||
<div class="tm-item acc"><div class="tm-when">06.05 · 22:06</div><div class="tm-text">Пополнение через ЮKassa: + 10 000 ₽</div></div>
|
||
<div class="tm-item dang"><div class="tm-when">04.05 · 16:42</div><div class="tm-text">Попытка пополнения через банковский перевод — отклонено</div></div>
|
||
<div class="tm-item"><div class="tm-when">12.04 · 09:32</div><div class="tm-text">Регистрация · trial 7 дней</div></div>
|
||
</div>
|
||
</section>
|
||
</aside>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== IMPERSONATION MODE ===== -->
|
||
<section id="page-impersonation" class="tab-page">
|
||
<div class="imp-banner" role="status">
|
||
<span style="display:inline-flex;align-items:center;gap:8px">
|
||
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.7"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12" y2="17"/></svg>
|
||
<strong>IMPERSONATION</strong>
|
||
<span style="opacity:0.85">Вы вошли как <strong>Окна Москва ООО / Иван Петров</strong> · действия логируются как admin · 04:32</span>
|
||
</span>
|
||
<button type="button">Выйти из режима</button>
|
||
</div>
|
||
<div class="app">
|
||
<aside class="side" aria-label="Главное меню">
|
||
<div class="brand"><span class="brand-mark"><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>Лидерра<span class="brand-dot">.</span></span></div>
|
||
<nav class="nav">
|
||
<div class="nav-eyebrow">Работа</div>
|
||
<div class="nav-item active"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><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></div>
|
||
<div class="nav-item"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M3 6h18M6 12h12M9 18h6"/></svg><span class="nav-text">Сделки</span><span class="nav-count">247</span></div>
|
||
<div class="nav-item"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><rect x="3" y="3" width="6" height="18"/></svg><span class="nav-text">Канбан</span></div>
|
||
</nav>
|
||
</aside>
|
||
<div class="main">
|
||
<div class="topbar"><div class="crumb"><strong>Дашборд</strong> <span style="color:var(--imp-red);font-weight:600;font-size:11.5px;font-family:var(--font-mono)">· через клиента</span></div><div class="topbar-spacer"></div><span class="user-chip"><span class="ava" style="background:var(--imp-red)">АО</span><span class="uname">Админ → ИП</span></span></div>
|
||
<main class="content"><header class="page-h"><div><h1 class="page-title">Доброе утро, Иван</h1><div class="page-meta"><span><span class="num" style="color:var(--accent);font-weight:600">+3</span> новых лида с утра</span></div></div></header>
|
||
<p style="font-size:13px;color:var(--ink-3);line-height:1.6;max-width:600px">Это дашборд клиента в режиме <strong style="color:var(--imp-red)">impersonation</strong>. Все действия фиксируются в saas_admin_audit_log с пометкой импersonator + причина (обязательно при входе). Выход из режима через красный баннер вверху.</p>
|
||
</main>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== INCIDENTS ===== -->
|
||
<section id="page-incidents" class="tab-page">
|
||
<div class="app">
|
||
<aside class="side"><div class="brand"><span class="brand-mark"><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>Лидерра<span class="brand-dot">.</span></span></div><div class="brand-sub">ADMIN</div><nav class="nav"><div class="nav-item"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle cx="9" cy="7" r="4"/></svg><span class="nav-text">Тенанты</span></div><div class="nav-item"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><rect x="3" y="6" width="18" height="13" rx="1"/></svg><span class="nav-text">Биллинг</span></div><div class="nav-item active"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/></svg><span class="nav-text">Инциденты</span><span class="nav-count">3</span></div><div class="nav-item"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/></svg><span class="nav-text">Система</span></div></nav></aside>
|
||
<div class="main">
|
||
<div class="topbar"><div class="crumb"><span>Админка</span><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M9 18l6-6-6-6"/></svg><strong>Журнал инцидентов</strong></div><div class="topbar-spacer"></div><span class="user-chip"><span class="ava">АО</span><span class="uname">Админ Оператор</span></span></div>
|
||
<main class="content">
|
||
<header class="page-h"><div><h1 class="page-title">Журнал инцидентов</h1><div class="page-meta"><span><span class="num">3</span> открытых</span><span class="sep">·</span><span><span class="num">87</span> за последние 30 дней</span><span class="sep">·</span><span>read-only для compliance</span></div></div></header>
|
||
<div class="tbl-wrap">
|
||
<div class="inc-row" style="background:var(--sunken);font-size:10.5px;font-weight:600;color:var(--ink-2);padding:10px 18px;border-bottom:1px solid var(--hairline)"><span>ID</span><span>Когда</span><span>Описание</span><span>Тенант</span><span>Severity</span></div>
|
||
<div class="inc-row"><span class="inc-id">INC-0034</span><span class="inc-when">07.05 · 14:23</span><span class="inc-title">Webhook timeout 5 раз подряд<span class="scope">endpoint /api/lead-in · TG-бот тенанта</span></span><span class="inc-tenant">Окна Москва ООО</span><span class="inc-sev high">HIGH</span></div>
|
||
<div class="inc-row"><span class="inc-id">INC-0033</span><span class="inc-when">07.05 · 09:14</span><span class="inc-title">SMS-шлюз timeout > 400ms<span class="scope">SMSC.RU деградация · 96.4%</span></span><span class="inc-tenant">Все тенанты</span><span class="inc-sev med">MED</span></div>
|
||
<div class="inc-row"><span class="inc-id">INC-0032</span><span class="inc-when">06.05 · 22:48</span><span class="inc-title">Дублирование лида<span class="scope">Я.Директ webhook прислал дубль за 18 секунд</span></span><span class="inc-tenant">Натяжные потолки СПб</span><span class="inc-sev low">LOW</span></div>
|
||
<div class="inc-row"><span class="inc-id">INC-0031</span><span class="inc-when">06.05 · 16:01</span><span class="inc-title">Failed Stripe payment retry<span class="scope">3 попытки за 7 дней · перевод в manual</span></span><span class="inc-tenant">Двери Премиум</span><span class="inc-sev med">MED</span></div>
|
||
<div class="inc-row"><span class="inc-id">INC-0030</span><span class="inc-when">05.05 · 11:32</span><span class="inc-title">RLS bypass attempt<span class="scope">tenant_id mismatch на /api/deals — отбито</span></span><span class="inc-tenant">Кухни на заказ Екб</span><span class="inc-sev high">HIGH</span></div>
|
||
<div class="inc-row"><span class="inc-id">INC-0029</span><span class="inc-when">05.05 · 08:22</span><span class="inc-title">Бэкап БД задержка<span class="scope">snapshot задержался на 38 минут — без потерь</span></span><span class="inc-tenant">Все тенанты</span><span class="inc-sev low">LOW</span></div>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== SYSTEM ===== -->
|
||
<section id="page-system" class="tab-page">
|
||
<div class="app">
|
||
<aside class="side"><div class="brand"><span class="brand-mark"><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>Лидерра<span class="brand-dot">.</span></span></div><div class="brand-sub">ADMIN</div><nav class="nav"><div class="nav-item"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle cx="9" cy="7" r="4"/></svg><span class="nav-text">Тенанты</span></div><div class="nav-item"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><rect x="3" y="6" width="18" height="13" rx="1"/></svg><span class="nav-text">Биллинг</span></div><div class="nav-item"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/></svg><span class="nav-text">Инциденты</span><span class="nav-count">3</span></div><div class="nav-item active"><svg class="nav-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/></svg><span class="nav-text">Система</span></div></nav></aside>
|
||
<div class="main">
|
||
<div class="topbar"><div class="crumb"><span>Админка</span><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M9 18l6-6-6-6"/></svg><strong>Система</strong></div><div class="topbar-spacer"></div><span class="user-chip"><span class="ava">АО</span><span class="uname">Админ Оператор</span></span></div>
|
||
<main class="content">
|
||
<header class="page-h"><div><h1 class="page-title">Системные настройки</h1><div class="page-meta"><span>super_admin доступ</span><span class="sep">·</span><span>все изменения логируются</span></div></div></header>
|
||
<div class="sys-grid">
|
||
<button type="button" class="sys-card"><div class="sc-h"><span class="sc-ico"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="M12 1v6M12 17v6M4.22 4.22l4.24 4.24M15.54 15.54l4.24 4.24M1 12h6M17 12h6M4.22 19.78l4.24-4.24M15.54 8.46l4.24-4.24"/></svg></span><span class="sc-name">system_settings</span></div><div class="sc-desc">Глобальные параметры платформы: лимиты, таймауты, фичефлаги</div><div class="sc-meta"><strong>27</strong> параметров · обновлено 3 часа назад</div></button>
|
||
<button type="button" class="sys-card"><div class="sc-h"><span class="sc-ico"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M12 2L2 7l10 5 10-5-10-5z"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/></svg></span><span class="sc-name">tariff_plans</span></div><div class="sc-desc">Тарифы Start/Basic/Pro/Enterprise — цена, лимиты, фичи</div><div class="sc-meta"><strong>4</strong> тарифа · последнее изменение 21.04</div></button>
|
||
<button type="button" class="sys-card"><div class="sc-h"><span class="sc-ico"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M3 7v13h18V7M3 7l3-4h12l3 4M3 7h18"/></svg></span><span class="sc-name">legal_entities</span></div><div class="sc-desc">Юр. лица оператора — для счетов и УПД</div><div class="sc-meta"><strong>1</strong> активно · ИП Сидоров А.А.</div></button>
|
||
<button type="button" class="sys-card"><div class="sc-h"><span class="sc-ico"><svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><rect x="3" y="6" width="18" height="13" rx="1"/><path d="M3 10h18M7 15h3"/></svg></span><span class="sc-name">payment_gateways</span></div><div class="sc-desc">ЮKassa, Stripe, банковский перевод — статус и комиссии</div><div class="sc-meta"><strong>3</strong> активных · ЮKassa primary</div></button>
|
||
<button type="button" class="sys-card"><div class="sc-h"><span class="sc-ico"><svg 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></span><span class="sc-name">webhook_log</span></div><div class="sc-desc">Все outbound и inbound webhook-события за 30 дней</div><div class="sc-meta"><strong>284 612</strong> событий · 99.97% uptime</div></button>
|
||
<button type="button" class="sys-card"><div class="sc-h"><span class="sc-ico"><svg 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></span><span class="sc-name">auth_log</span></div><div class="sc-desc">Все вход/выход события — клиенты, админы, impersonation</div><div class="sc-meta"><strong>4 821</strong> событий за 7 дней</div></button>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<script>
|
||
const tabs = Array.from(document.querySelectorAll('.review-bar .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 === 'page-' + id));
|
||
}
|
||
tabs.forEach(t => t.addEventListener('click', () => setTab(t.dataset.tab)));
|
||
</script>
|
||
</body>
|
||
</html>
|