Files
drivers_bot/web/index.html
2026-05-12 19:45:08 +09:00

441 lines
19 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" />
<meta name="theme-color" content="#16806a" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="Гараж" />
<title>Гараж</title>
<link rel="manifest" href="/manifest.webmanifest" />
<link rel="stylesheet" href="/static/styles.css" />
<script src="https://telegram.org/js/telegram-web-app.js"></script>
</head>
<body class="auth-required">
<div class="auth-overlay" id="authOverlay">
<div class="auth-panel">
<p class="eyebrow">Drivers</p>
<h1>Гараж</h1>
<p id="authMessage">Это приложение открывается через Telegram-бота. Откройте Mini App из Telegram.</p>
<div id="telegramLoginSlot" class="telegram-login-slot"></div>
<a id="telegramLoginLink" class="telegram-login-link hidden" href="#" target="_blank" rel="noreferrer">Открыть бота</a>
</div>
</div>
<main class="shell">
<header class="topbar">
<div>
<p class="eyebrow">Drivers</p>
<h1>Гараж</h1>
</div>
<div class="top-actions">
<button class="icon-btn" id="refreshBtn" title="Обновить" aria-label="Обновить"></button>
<button class="icon-btn" id="menuBtn" title="Меню" aria-label="Меню"></button>
</div>
</header>
<section class="hero-grid">
<div class="summary-card">
<span>Автомобиль</span>
<strong id="selectedCarTitle">Не выбран</strong>
<small id="selectedCarMeta">Добавь авто или выбери из списка</small>
</div>
<div class="summary-card accent">
<span>Расходы</span>
<strong id="summaryTotal">0</strong>
<small>топливо, сервис и ремонты</small>
</div>
<div class="summary-card blue">
<span>Средний расход</span>
<strong id="summaryConsumption">-</strong>
<small>л/100 км по полным данным</small>
</div>
</section>
<section class="layout">
<aside class="panel reveal">
<div class="section-head">
<h2>Автомобили</h2>
<button class="ghost-btn" id="addCarQuickBtn">+</button>
</div>
<div id="cars" class="cars"></div>
</aside>
<section class="workspace reveal">
<section class="progress-strip">
<div>
<span>Профиль учета</span>
<strong id="scoreTitle">Старт</strong>
</div>
<div class="progress-track"><span id="scoreBar"></span></div>
<small id="scoreHint">Добавь авто и первую запись, чтобы видеть точные отчеты</small>
</section>
<div class="status-bar" id="statusBar" aria-live="polite">Готов к работе</div>
<section class="report-bar">
<div>
<p class="eyebrow">Отчет</p>
<h2>Стоимость владения</h2>
</div>
<div class="period-controls">
<select id="periodPreset" aria-label="Период отчета">
<option value="all">Весь срок</option>
<option value="month">Месяц</option>
<option value="day">День</option>
<option value="quarter">Квартал</option>
<option value="year">Год</option>
<option value="custom">Свой период</option>
</select>
<input id="periodFrom" type="date" aria-label="Дата начала" />
<input id="periodTo" type="date" aria-label="Дата окончания" />
</div>
</section>
<div class="stats" id="stats"></div>
<section class="quick-actions">
<button class="action-card active" data-action="fuel">
<span>Заправка</span>
<strong>30 сек</strong>
</button>
<button class="action-card" data-action="service">
<span>Сервис</span>
<strong>ТО / ремонт</strong>
</button>
<button class="action-card" data-action="scan">
<span>Разбор чека</span>
<strong>Текст</strong>
</button>
</section>
<section class="charts">
<div class="chart-card">
<div class="section-head">
<h2>Динамика расходов</h2>
</div>
<canvas id="expensesChart" width="720" height="260"></canvas>
</div>
<div class="chart-card compact">
<div class="section-head">
<h2>Структура</h2>
</div>
<canvas id="splitChart" width="280" height="260"></canvas>
</div>
</section>
<form id="fuelForm" class="entry-form quick-form">
<label>
Дата
<input name="entry_date" type="date" required />
</label>
<label>
Одометр, км
<input name="odometer" type="number" min="0" required />
</label>
<label>
Литры
<input name="liters" type="number" min="0" step="0.001" required />
</label>
<label>
Цена за литр
<input name="price_per_liter" type="number" min="0" step="0.01" required />
</label>
<label>
АЗС
<select name="station">
<option value="">Не выбрано</option>
<option>Shell</option>
<option>Lukoil</option>
<option>Gazprom</option>
<option>Rosneft</option>
<option>Neste</option>
</select>
</label>
<label class="check">
<input name="is_full_tank" type="checkbox" checked />
Полный бак
</label>
<button type="submit">Сохранить заправку</button>
</form>
<form id="serviceForm" class="entry-form hidden">
<label>
Дата
<input name="entry_date" type="date" required />
</label>
<label>
Одометр, км
<input name="odometer" type="number" min="0" />
</label>
<label>
Тип
<select name="service_type">
<option value="maintenance">Обслуживание</option>
<option value="repair">Ремонт</option>
<option value="fluid">Жидкости</option>
<option value="tire">Шины</option>
<option value="inspection">Осмотр</option>
<option value="insurance">Страховка</option>
<option value="tax">Налог</option>
<option value="other">Другое</option>
</select>
</label>
<label>
Что сделано
<input name="title" placeholder="Замена масла" required />
</label>
<div class="preset-row">
<button type="button" data-service-title="Замена масла" data-service-type="maintenance">Масло</button>
<button type="button" data-service-title="Шиномонтаж" data-service-type="tire">Шины</button>
<button type="button" data-service-title="Диагностика" data-service-type="inspection">Осмотр</button>
</div>
<label>
Стоимость
<input name="total_cost" type="number" min="0" step="0.01" required />
</label>
<label>
Исполнитель
<input name="vendor" placeholder="СТО / магазин" />
</label>
<label>
Следующая дата
<input name="next_due_date" type="date" />
</label>
<label>
Следующий пробег
<input name="next_due_odometer" type="number" min="0" />
</label>
<button type="submit">Сохранить запись</button>
</form>
</section>
</section>
</main>
<div class="drawer hidden" id="userDrawer">
<div class="drawer-panel">
<div class="section-head">
<h2>Меню</h2>
<button class="icon-btn" id="closeMenuBtn" aria-label="Закрыть">×</button>
</div>
<button class="menu-row" id="openCarFormBtn">Добавить автомобиль</button>
<button class="menu-row" id="openCarProfileBtn">Параметры автомобиля</button>
<button class="menu-row" id="openSettingsBtn">Локаль и валюта</button>
<button class="menu-row" id="openNotificationsBtn">Уведомления</button>
<button class="menu-row" id="openConfirmationsBtn">Запросы на подтверждение</button>
<button class="menu-row" id="openConnectedServicesBtn">Подключенные автосервисы</button>
<button class="menu-row" id="openServicePanelBtn">Панель СТО</button>
<button class="menu-row" id="openScanBtn">Разобрать чек</button>
<section class="drawer-section hidden" id="settingsSection">
<h2>Настройки</h2>
<form id="settingsForm" class="grid-form drawer-form">
<label>
Язык
<select name="locale" id="localeSelect">
<option value="ru">Русский</option>
<option value="en">English</option>
<option value="ko">한국어</option>
</select>
</label>
<label>
Валюта
<select name="currency" id="currencySelect">
<option value="RUB">RUB ₽</option>
<option value="USD">USD $</option>
<option value="EUR">EUR €</option>
<option value="KRW">KRW ₩</option>
<option value="KZT">KZT ₸</option>
</select>
</label>
<button type="submit">Сохранить настройки</button>
</form>
</section>
<section class="drawer-section hidden" id="notificationsSection">
<h2>Уведомления</h2>
<div class="tip-card" id="notificationStatus">Напомним о ТО, страховке и регулярном внесении пробега.</div>
<button type="button" class="wide-btn" id="enableNotificationsBtn">Включить уведомления</button>
</section>
<section class="drawer-section hidden" id="confirmationsSection">
<h2>Запросы на подтверждение</h2>
<div class="tip-card">Здесь будут визиты СТО и изменения данных авто, которые ждут твоего решения.</div>
<div id="confirmationRequests" class="stack-list"></div>
</section>
<section class="drawer-section hidden" id="connectedServicesSection">
<h2>Подключенные автосервисы</h2>
<div class="tip-card">Автосервис видит машину только после твоего разрешения или в рамках визита.</div>
<div id="connectedServices" class="stack-list"></div>
</section>
<section class="drawer-section hidden" id="servicePanelSection">
<h2>Панель СТО</h2>
<form id="serviceCenterForm" class="grid-form drawer-form">
<label>
Название СТО
<input name="display_name" placeholder="Smart Service" required />
</label>
<label>
Юридическое название
<input name="legal_name" placeholder="ООО Smart Service" />
</label>
<label>
Страна
<input name="country" maxlength="2" placeholder="KR" />
</label>
<label>
Город
<input name="city" placeholder="Seoul" />
</label>
<label>
Адрес
<input name="address" />
</label>
<label>
Телефон
<input name="phone" />
</label>
<label>
Регистрационный номер
<input name="business_registration_number" />
</label>
<button type="submit">Создать СТО</button>
</form>
<div id="serviceCentersList" class="stack-list"></div>
</section>
<section class="drawer-section" id="carFormSection">
<h2>Новое авто</h2>
<form id="carForm" class="grid-form drawer-form">
<label>
Название авто
<input name="name" placeholder="Toyota Camry" required />
</label>
<label>
Марка
<select name="make" id="makeSelect" required></select>
</label>
<label>
Модель
<select name="model" id="modelSelect" required></select>
</label>
<label>
Комплектация
<select name="trim" id="trimSelect"></select>
</label>
<div class="catalog-preview" id="catalogPreview">
<strong>Выбери модель</strong>
<span>Покажем кузов, топливо, привод и годы выпуска.</span>
</div>
<label>
Год
<input name="year" type="number" min="1900" max="2100" />
</label>
<label>
Тип топлива
<select name="fuel_type" id="fuelTypeSelect">
<option value="">Авто</option>
<option value="gasoline">Бензин</option>
<option value="diesel">Дизель</option>
<option value="hybrid">Гибрид</option>
<option value="electric">Электро</option>
</select>
</label>
<button type="submit">Добавить авто</button>
</form>
</section>
<section class="drawer-section hidden" id="carProfileSection">
<h2>Параметры авто</h2>
<div class="tip-card" id="carProfileHint">Выбери автомобиль, чтобы настроить жидкости, расход и сервисные нормы.</div>
<form id="carProfileForm" class="grid-form drawer-form">
<label>
Тип топлива
<select name="fuel_type">
<option value="">Не задано</option>
<option value="gasoline">Бензин</option>
<option value="diesel">Дизель</option>
<option value="hybrid">Гибрид</option>
<option value="electric">Электро</option>
</select>
</label>
<label>
Нормальный расход, л/100 км
<input name="target_consumption_l_per_100km" type="number" min="0" step="0.01" placeholder="8.50" />
</label>
<label>
Бак, л
<input name="fuel_tank_volume_l" type="number" min="0" step="0.01" placeholder="60" />
</label>
<label>
Моторное масло
<input name="engine_oil_type" placeholder="5W-30 API SP" />
</label>
<label>
Объем масла, л
<input name="engine_oil_volume_l" type="number" min="0" step="0.01" placeholder="4.50" />
</label>
<label>
Трансмиссионная жидкость
<input name="transmission_fluid_type" placeholder="ATF WS / DCTF / CVT" />
</label>
<label>
Объем трансмиссии, л
<input name="transmission_fluid_volume_l" type="number" min="0" step="0.01" placeholder="7.20" />
</label>
<label>
Антифриз
<input name="coolant_type" placeholder="G12+ / LLC" />
</label>
<label>
Тормозная жидкость
<input name="brake_fluid_type" placeholder="DOT 4" />
</label>
<label>
Давление перед, bar
<input name="tire_pressure_front_bar" type="number" min="0" step="0.01" placeholder="2.30" />
</label>
<label>
Давление зад, bar
<input name="tire_pressure_rear_bar" type="number" min="0" step="0.01" placeholder="2.20" />
</label>
<button type="submit">Сохранить параметры</button>
</form>
</section>
</div>
</div>
<div class="scan-modal hidden" id="scanModal">
<div class="scan-panel">
<div class="section-head">
<h2>Разбор чека</h2>
<button class="icon-btn" id="closeScanBtn" aria-label="Закрыть">×</button>
</div>
<form id="ocrForm" class="scan-form">
<div class="scan-actions">
<button type="button" class="ghost-btn" id="scanCameraBtn">Сфотографировать</button>
<button type="button" class="ghost-btn" id="scanFileBtn">Выбрать файл</button>
</div>
<input id="receiptCameraInput" class="hidden-file" type="file" accept="image/*" capture="environment" />
<input id="receiptFileInput" class="hidden-file" type="file" accept="image/*,.pdf,.txt" />
<div id="receiptFileName" class="file-hint">Файл не выбран</div>
<button type="submit">Разобрать текст</button>
</form>
<div id="ocrResult" class="tip-card">Сейчас разбираем текстовые чеки. OCR по фото будет подключен отдельно.</div>
</div>
</div>
<div class="report-sheet hidden" id="reportSheet">
<div class="sheet-panel">
<div class="section-head">
<h2 id="reportTitle">Отчет</h2>
<button class="icon-btn" id="closeReportBtn" aria-label="Закрыть">×</button>
</div>
<div id="reportBody"></div>
</div>
</div>
<div class="toast hidden" id="toast" role="status" aria-live="polite"></div>
<script src="/static/app.js"></script>
</body>
</html>