This repository has been archived on 2026-11-14. You can view files and clone it, but cannot push or open issues or pull requests.
korabayev/executive-os/index.html
korabayev 8d92862d8b Add MVP implementations for Atlas AI Wealth and ExecutiveOS AI
Two product MVPs based on iterations of PRD.md / TRD.md:

1. Atlas AI Wealth (initial TRD: portfolio/cashflow/forecasting platform)
   - backend/  FastAPI + SQLAlchemy + SQLite: XLSX/CSV parser with
     fuzzy header matching, rule-based transaction classifier,
     analytics engine (TWR via Modified Dietz, Newton IRR,
     moving-avg cost, allocation, cashflow), AI Copilot stub.
   - frontend/ Next.js 14 + TS + Tailwind: Dashboard, Portfolio,
     Transactions, Cash Flow, Upload screens; SWR data fetching.
   - index.html / app.js / data.js / styles.css  vanilla zero-build
     version of the same MVP using mock data.

2. ExecutiveOS AI (revised TRD: AI Chief of Staff for Lotus Notes)
   - executive-os/  vanilla HTML+CSS+JS PWA: Daily Briefing,
     Priority Inbox, Approvals, Escalations, AI Search, AI Copilot.
   - Mock dataset with 18 emails (P1-P3, 8 categories, AI scoring,
     SLA tracking, recommendations).
   - Russian UI. Service Worker + manifest for offline install.

Docs:
   - README.md  run instructions + TRD coverage table for both MVPs
   - README.korabayev.md  preserved original onboarding doc
2026-05-22 13:13:41 +05:00

194 lines
7.6 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ExecutiveOS AI — Помощник для руководителя (Lotus)</title>
<link rel="manifest" href="manifest.webmanifest" />
<link rel="icon" type="image/svg+xml" href="icon.svg" />
<link rel="apple-touch-icon" href="icon.svg" />
<meta name="theme-color" content="#7bb7ff" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="ExecutiveOS" />
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<header class="topbar">
<div class="brand">
<span class="logo-dot"></span>
<span><strong>ExecutiveOS</strong> <span class="muted">AI</span></span>
</div>
<nav class="nav" id="nav">
<button data-route="briefing" class="active">Брифинг</button>
<button data-route="inbox">Входящие</button>
<button data-route="approvals">Согласования</button>
<button data-route="escalations">Эскалации</button>
<button data-route="search">AI-поиск</button>
</nav>
<div class="user">
<span id="online-dot" class="status-dot"></span>
<span class="mono">ceo@acme.corp</span>
<span class="muted small">· HCL Notes</span>
<button id="btn-install" class="btn-ghost install-btn" hidden>↓ Установить</button>
</div>
</header>
<main id="view"></main>
<!-- Брифинг -->
<template id="tpl-briefing">
<section>
<div class="row spread wrap">
<div>
<h1>Ежедневный брифинг</h1>
<div class="muted small" id="brief-date"></div>
</div>
<div class="row gap">
<button id="btn-refresh" class="btn-ghost">↻ Синхронизация с Lotus</button>
<button id="btn-mark-read" class="btn-ghost">Отметить все просмотренными</button>
</div>
</div>
<div class="kpi-grid">
<div class="card kpi"><div class="kpi-label">Критических непрочитанных</div><div class="kpi-value danger" data-k="critical"></div></div>
<div class="card kpi"><div class="kpi-label">Ожидают решения</div><div class="kpi-value warn" data-k="pending"></div></div>
<div class="card kpi"><div class="kpi-label">К Совету директоров</div><div class="kpi-value" data-k="board"></div></div>
<div class="card kpi"><div class="kpi-label">Нарушений SLA</div><div class="kpi-value danger" data-k="sla"></div></div>
</div>
<div class="grid-2-1">
<div class="card">
<div class="kpi-label">Сводка дня</div>
<div id="brief-summary" class="briefing"></div>
</div>
<div class="card">
<div class="kpi-label">Топ-3 приоритета</div>
<ol id="brief-top3" class="priorities"></ol>
</div>
</div>
<div class="card">
<div class="kpi-label">AI-копилот</div>
<div class="copilot">
<div class="row gap">
<input id="cp-input" placeholder="«Что требует моей подписи?», «Покажи просроченные»…" />
<button id="cp-ask" class="btn-primary">Спросить</button>
</div>
<div id="cp-suggest" class="chips"></div>
<div id="cp-answer" class="answer"></div>
</div>
</div>
</section>
</template>
<!-- Входящие -->
<template id="tpl-inbox">
<section>
<h1>Приоритетные входящие</h1>
<div class="card row gap wrap">
<input id="inbox-search" placeholder="Поиск по теме, отправителю, тексту…" />
<select id="inbox-cat">
<option value="">Все категории</option>
</select>
<select id="inbox-pri">
<option value="">Все приоритеты</option>
<option value="P1">P1 — Критический</option>
<option value="P2">P2 — Высокий</option>
<option value="P3">P3 — Обычный</option>
</select>
<label class="row gap small"><input type="checkbox" id="inbox-unread" /> <span>Только непрочитанные</span></label>
</div>
<div id="inbox-list" class="email-list"></div>
</section>
</template>
<!-- Согласования -->
<template id="tpl-approvals">
<section>
<div class="row spread wrap">
<h1>Ожидают согласования</h1>
<div class="muted small">AI оценил риск и предложил действие. Решение всегда за вами.</div>
</div>
<div id="appr-list" class="approval-list"></div>
</section>
</template>
<!-- Эскалации -->
<template id="tpl-escalations">
<section>
<h1>Монитор эскалаций</h1>
<div class="card">
<table class="data">
<thead><tr>
<th>Возраст</th><th>Тема</th><th>От кого</th><th>Должность</th>
<th class="r">SLA</th><th>Статус</th>
</tr></thead>
<tbody id="esc-rows"></tbody>
</table>
</div>
</section>
</template>
<!-- Поиск -->
<template id="tpl-search">
<section>
<h1>AI-поиск по корпоративной почте</h1>
<div class="card stack">
<div class="row gap">
<input id="srch-input" placeholder="Семантический поиск по письмам, согласованиям, материалам Совета…" />
<button id="srch-go" class="btn-primary">Найти</button>
</div>
<div class="chips" id="srch-suggest"></div>
</div>
<div id="srch-results" class="email-list"></div>
</section>
</template>
<script src="data.js"></script>
<script src="app.js"></script>
<script>
// ---- PWA: регистрация Service Worker ----
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker.register("./sw.js")
.then(reg => console.log("[PWA] SW registered:", reg.scope))
.catch(err => console.error("[PWA] SW error:", err));
});
}
// ---- Install prompt ----
let deferredPrompt = null;
const installBtn = document.getElementById("btn-install");
window.addEventListener("beforeinstallprompt", (e) => {
e.preventDefault();
deferredPrompt = e;
installBtn.hidden = false;
});
installBtn.addEventListener("click", async () => {
if (!deferredPrompt) return;
deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
console.log("[PWA] install outcome:", outcome);
deferredPrompt = null;
installBtn.hidden = true;
});
window.addEventListener("appinstalled", () => {
installBtn.hidden = true;
console.log("[PWA] installed");
});
// ---- Online/offline индикатор ----
const dot = document.getElementById("online-dot");
function updateOnline() {
const online = navigator.onLine;
dot.classList.toggle("offline", !online);
dot.title = online ? "Online — Lotus синхронизирован" : "Offline — данные из кэша";
}
window.addEventListener("online", updateOnline);
window.addEventListener("offline", updateOnline);
updateOnline();
</script>
</body>
</html>