287 lines
18 KiB
HTML
287 lines
18 KiB
HTML
<!doctype html>
|
||
<html lang="ru">
|
||
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover">
|
||
<meta name="robots" content="noindex, nofollow">
|
||
<meta name="theme-color" content="#05070a">
|
||
<title>Моя подписка</title>
|
||
<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=JetBrains+Mono:wght@400;500;600;700&family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||
<script src="./telegram-web-app.js"></script>
|
||
<link rel="stylesheet" href="./subscription_webapp.css">
|
||
</head>
|
||
|
||
<body>
|
||
<div id="loader" class="app-loader" data-i18n="loading">Загрузка...</div>
|
||
|
||
<main id="app" class="app hidden">
|
||
<header class="app-header">
|
||
<div class="app-header-title">
|
||
<img id="brand-logo" class="brand-logo hidden" data-brand-logo alt="" aria-hidden="true">
|
||
<div id="brand-title" class="brand-title" data-brand-title>Моя подписка</div>
|
||
</div>
|
||
<div class="app-header-actions">
|
||
<div class="user-menu">
|
||
<button id="user-chip" class="user-chip" type="button" aria-haspopup="true" aria-expanded="false" aria-controls="user-dropdown" onclick="toggleUserMenu()">
|
||
<img id="user-chip-avatar" class="user-chip-avatar" alt="" aria-hidden="true">
|
||
<span id="user-chip-name" class="user-chip-name">...</span>
|
||
<svg class="user-chip-caret" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" aria-hidden="true">
|
||
<path d="M297.4 470.6C309.9 483.1 330.2 483.1 342.7 470.6L534.7 278.6C547.2 266.1 547.2 245.8 534.7 233.3C522.2 220.8 501.9 220.8 489.4 233.3L320 402.7L150.6 233.4C138.1 220.9 117.8 220.9 105.3 233.4C92.8 245.9 92.8 266.2 105.3 278.7L297.3 470.7z"/>
|
||
</svg>
|
||
</button>
|
||
<div id="user-dropdown" class="user-dropdown hidden" role="menu">
|
||
<div class="user-dropdown-head">
|
||
<img id="user-dropdown-avatar" class="user-dropdown-avatar" alt="" aria-hidden="true">
|
||
<div class="user-dropdown-head-text">
|
||
<div id="user-dropdown-name" class="user-dropdown-name">...</div>
|
||
<div id="user-dropdown-sub" class="user-dropdown-sub"></div>
|
||
</div>
|
||
</div>
|
||
<div class="user-dropdown-rows">
|
||
<div class="user-dropdown-row" role="menuitem">
|
||
<span class="user-dropdown-row-label" data-i18n="email_label">Email</span>
|
||
<span id="user-dropdown-email-status" class="user-dropdown-row-status">...</span>
|
||
</div>
|
||
<div class="user-dropdown-row" role="menuitem">
|
||
<span class="user-dropdown-row-label" data-i18n="telegram_label">Telegram</span>
|
||
<span id="user-dropdown-telegram-status" class="user-dropdown-row-status">...</span>
|
||
</div>
|
||
</div>
|
||
<button class="user-dropdown-logout" type="button" role="menuitem" onclick="logout()">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" aria-hidden="true">
|
||
<path d="M224 160C241.7 160 256 145.7 256 128C256 110.3 241.7 96 224 96L160 96C107 96 64 139 64 192L64 448C64 501 107 544 160 544L224 544C241.7 544 256 529.7 256 512C256 494.3 241.7 480 224 480L160 480C142.3 480 128 465.7 128 448L128 192C128 174.3 142.3 160 160 160L224 160zM566.6 342.6C579.1 330.1 579.1 309.8 566.6 297.3L438.6 169.3C426.1 156.8 405.8 156.8 393.3 169.3C380.8 181.8 380.8 202.1 393.3 214.6L466.7 288L256 288C238.3 288 224 302.3 224 320C224 337.7 238.3 352 256 352L466.7 352L393.3 425.4C380.8 437.9 380.8 458.2 393.3 470.7C405.8 483.2 426.1 483.2 438.6 470.7L566.6 342.7z"/>
|
||
</svg>
|
||
<span data-i18n="logout">Выйти</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<section class="panel grid gap-[17px] p-[18px]">
|
||
<div id="sub-status" class="sub-status">
|
||
<span class="sub-status-dot" aria-hidden="true"></span>
|
||
<span id="sub-status-text" class="sub-status-text">...</span>
|
||
</div>
|
||
|
||
<div class="sub-countdown">
|
||
<div class="sub-countdown-row">
|
||
<span id="remaining" class="sub-countdown-value">...</span>
|
||
<span id="end-date-caption" class="sub-countdown-caption"></span>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="traffic-bar" class="traffic-bar" role="progressbar" aria-valuemin="0" aria-valuemax="100">
|
||
<div id="traffic-bar-fill" class="traffic-bar-fill"></div>
|
||
<span id="traffic" class="traffic-bar-value">...</span>
|
||
</div>
|
||
|
||
<div id="connect-actions">
|
||
<button id="connect-btn" class="btn-primary w-full" type="button" onclick="openConnectLink()" data-i18n="connect">Подключиться</button>
|
||
</div>
|
||
|
||
<div class="mt-0.5 border-t border-[var(--border)] pt-3.5">
|
||
<button id="extend-btn" class="btn-ghost w-full" type="button" onclick="togglePaymentFlow()" data-i18n="extend_subscription">Продлить подписку/Добавить дни</button>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="link-panel" class="panel hidden grid gap-3.5 p-[17px]">
|
||
<div class="panel-head">
|
||
<div>
|
||
<div id="link-panel-title" class="section-title" data-i18n="link_panel_title">Привяжите способ входа</div>
|
||
<div id="link-panel-caption" class="section-caption" data-i18n="link_panel_caption">Чтобы не терять доступ к кабинету</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="email-link-box" class="hidden grid gap-2">
|
||
<div class="link-cta-head">
|
||
<span class="link-cta-title" data-i18n="link_email_title">Привяжите email</span>
|
||
<span class="link-cta-caption" data-i18n="link_email_caption">Получайте код для входа на почту</span>
|
||
</div>
|
||
<div class="grid grid-cols-[minmax(0,1fr)_minmax(120px,auto)] gap-2">
|
||
<input id="email-link-input" class="input w-full" type="email" autocomplete="email" inputmode="email" placeholder="mail@example.com" data-placeholder-i18n="email_placeholder">
|
||
<button id="email-link-send-btn" class="btn" type="button" onclick="requestEmailLinkCode()" data-i18n="send_code">Отправить код</button>
|
||
</div>
|
||
<div id="email-link-code-row" class="hidden grid grid-cols-[minmax(0,1fr)_minmax(120px,auto)] gap-2">
|
||
<input id="email-link-code-input" class="input input-code w-full" type="text" inputmode="numeric" autocomplete="one-time-code" maxlength="6" placeholder="000000" data-placeholder-i18n="code_placeholder">
|
||
<button id="email-link-verify-btn" class="btn-primary" type="button" onclick="verifyEmailLinkCode()" data-i18n="confirm">Подтвердить</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="telegram-link-box" class="hidden grid gap-2">
|
||
<div class="link-cta-head">
|
||
<span class="link-cta-title" data-i18n="link_telegram_title">Привяжите Telegram</span>
|
||
<span class="link-cta-caption" data-i18n="link_telegram_caption">Входите одним нажатием через Telegram</span>
|
||
</div>
|
||
<div id="telegram-link-widget" class="telegram-login-widget" aria-live="polite"></div>
|
||
<div id="telegram-link-status" class="status-text hidden" aria-live="polite"></div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="grid min-w-0 grid-cols-2 gap-2">
|
||
<button class="btn w-full" type="button" onclick="openReferralModal()" data-i18n="referral_title">Пригласить друга</button>
|
||
<button class="btn w-full" type="button" onclick="openPromoModal()" data-i18n="promo_title">Промокод</button>
|
||
</section>
|
||
|
||
|
||
|
||
|
||
<a id="support-link" class="hidden mt-0.5 btn" href="#" target="_blank" rel="noopener" data-i18n="support">Поддержка</a>
|
||
<div id="legal-links-app" data-legal-links class="legal-links hidden">
|
||
<a class="legal-link max-[560px]:flex-[1_1_100%]" data-legal-key="privacyPolicyUrl" href="#" target="_blank" rel="noopener" data-i18n="privacy_policy">Политика конфиденциальности</a>
|
||
<a class="legal-link max-[560px]:flex-[1_1_100%]" data-legal-key="userAgreementUrl" href="#" target="_blank" rel="noopener" data-i18n="user_agreement">Пользовательское соглашение</a>
|
||
</div>
|
||
</main>
|
||
|
||
<div id="payment-modal" class="modal hidden" role="dialog" aria-modal="true" aria-labelledby="payment-title">
|
||
<button class="modal-backdrop" type="button" data-title-i18n="close_payment" aria-label="Закрыть оплату" onclick="closePaymentFlow()"></button>
|
||
<section id="payment-flow" class="panel-modal modal-card grid gap-3.5 p-4">
|
||
<div class="panel-head">
|
||
<div>
|
||
<div id="payment-title" class="section-title" data-i18n="payment_title">Оплата подписки</div>
|
||
<div class="section-caption" data-i18n="payment_caption">Выберите срок, способ оплаты и создайте платеж.</div>
|
||
</div>
|
||
<button class="icon-btn" type="button" data-title-i18n="close_payment" aria-label="Закрыть оплату" onclick="closePaymentFlow()">×</button>
|
||
</div>
|
||
|
||
<div class="grid grid-cols-3 gap-2" data-aria-i18n="payment_steps" aria-label="Шаги оплаты">
|
||
<div id="step-plan" class="step step-box">
|
||
<span class="step-num">01</span>
|
||
<span class="step-name" data-i18n="step_plan">Срок</span>
|
||
</div>
|
||
<div id="step-method" class="step step-box">
|
||
<span class="step-num">02</span>
|
||
<span class="step-name" data-i18n="step_method">Метод</span>
|
||
</div>
|
||
<div id="step-result" class="step step-box">
|
||
<span class="step-num">03</span>
|
||
<span class="step-name" data-i18n="step_result">Платеж</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="plan-step" class="grid gap-2.5">
|
||
<div class="section-label" data-i18n="select_period">Выберите срок</div>
|
||
<div id="plans" class="plans"></div>
|
||
<button id="to-methods-btn" class="btn-primary w-full" type="button" onclick="goToPaymentStep('method')" data-i18n="choose_payment_method">Выбрать способ оплаты</button>
|
||
</div>
|
||
|
||
<div id="method-step" class="hidden grid gap-2.5">
|
||
<div class="section-label" data-i18n="select_method">Выберите способ оплаты</div>
|
||
<div id="methods" class="methods"></div>
|
||
<div class="grid grid-cols-2 gap-2">
|
||
<button class="btn text-[var(--text-secondary)]" type="button" onclick="goToPaymentStep('plan')" data-i18n="back">Назад</button>
|
||
<button id="create-payment-btn" class="btn-primary" type="button" onclick="createPaymentFromSelection()" data-i18n="create_payment">Создать платеж</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="result-step" class="hidden grid gap-2.5">
|
||
<div class="section-label" data-i18n="payment_status">Статус платежа</div>
|
||
<div class="grid gap-2.5">
|
||
<div id="payment-message" class="notice"></div>
|
||
<button id="payment-open-btn" class="btn-primary w-full" type="button" onclick="openPaymentUrl()" data-i18n="open_payment">Открыть оплату</button>
|
||
<button id="payment-check-btn" class="btn w-full" type="button" onclick="checkPayment()" data-i18n="check_payment">Проверить оплату</button>
|
||
<button class="btn w-full text-[var(--text-secondary)]" type="button" onclick="goToPaymentStep('method')" data-i18n="choose_other_method">Выбрать другой способ</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
|
||
<div id="promo-modal" class="modal hidden" role="dialog" aria-modal="true" aria-labelledby="promo-title">
|
||
<button class="modal-backdrop" type="button" data-title-i18n="close" aria-label="Закрыть" onclick="closePromoModal()"></button>
|
||
<section id="promo-panel" class="panel-modal modal-card grid gap-3.5 p-[17px]">
|
||
<div class="panel-head">
|
||
<div>
|
||
<div id="promo-title" class="section-title" data-i18n="promo_title">Промокод</div>
|
||
<div class="section-caption" data-i18n="promo_caption">Введите код, чтобы начислить бонусные дни.</div>
|
||
</div>
|
||
<button class="icon-btn" type="button" data-title-i18n="close" aria-label="Закрыть" onclick="closePromoModal()">×</button>
|
||
</div>
|
||
<div class="grid grid-cols-[minmax(0,1fr)_minmax(120px,auto)] gap-2">
|
||
<input id="promo-code-input" class="input input-code w-full" type="text" autocomplete="off" inputmode="text" placeholder="PROMO2026" data-placeholder-i18n="promo_placeholder">
|
||
<button id="promo-apply-btn" class="btn-primary" type="button" onclick="applyPromoCode()" data-i18n="apply_promo">Применить</button>
|
||
</div>
|
||
<div id="promo-status" class="status-text hidden" aria-live="polite"></div>
|
||
</section>
|
||
</div>
|
||
|
||
<div id="referral-modal" class="modal modal--page hidden" role="dialog" aria-modal="true" aria-labelledby="referral-title">
|
||
<button class="modal-backdrop" type="button" data-title-i18n="close" aria-label="Закрыть" onclick="closeReferralModal()"></button>
|
||
<section id="referral-panel" class="panel-modal modal-card grid gap-3.5 p-[17px]"></section>
|
||
</div>
|
||
|
||
<div id="email-code-modal" class="modal auth-code-modal hidden" role="dialog" aria-modal="true" aria-labelledby="email-code-title" aria-describedby="email-code-caption">
|
||
<button class="modal-backdrop" type="button" data-title-i18n="close" aria-label="Закрыть" onclick="closeEmailLoginCodeModal()"></button>
|
||
<div class="relative z-[1] grid w-[min(100%,420px)] justify-items-stretch gap-2.5">
|
||
<section class="panel-modal modal-card grid gap-3.5 p-[18px]">
|
||
<div class="panel-head">
|
||
<div>
|
||
<div id="email-code-title" class="section-title" data-i18n="email_code_title">Подтвердите вход</div>
|
||
<div id="email-code-caption" class="section-caption" data-i18n="email_code_caption">Введите 6-значный код из письма.</div>
|
||
</div>
|
||
<button class="icon-btn" type="button" data-title-i18n="close" aria-label="Закрыть" onclick="closeEmailLoginCodeModal()">×</button>
|
||
</div>
|
||
|
||
<div class="metric rounded-[var(--radius-md)] grid-cols-[minmax(0,0.6fr)_minmax(0,1.4fr)]">
|
||
<div class="metric-label" data-i18n="email_label">Email</div>
|
||
<div id="email-code-address" class="metric-value">...</div>
|
||
</div>
|
||
|
||
<label class="relative block min-h-14 cursor-text">
|
||
<input id="email-login-code-input" class="otp-input" type="text" inputmode="numeric" autocomplete="one-time-code" maxlength="6" pattern="[0-9]*" data-aria-i18n="email_code_aria" aria-label="Код подтверждения">
|
||
<span class="otp-slots" aria-hidden="true">
|
||
<span id="email-code-slot-0"></span>
|
||
<span id="email-code-slot-1"></span>
|
||
<span id="email-code-slot-2"></span>
|
||
<span id="email-code-slot-3"></span>
|
||
<span id="email-code-slot-4"></span>
|
||
<span id="email-code-slot-5"></span>
|
||
</span>
|
||
</label>
|
||
|
||
<div id="email-code-status" class="status-text hidden" aria-live="polite"></div>
|
||
|
||
<div class="grid gap-2">
|
||
<button id="email-login-verify-btn" class="btn-primary w-full" type="button" onclick="verifyEmailLoginCode()" data-i18n="login">Войти</button>
|
||
</div>
|
||
</section>
|
||
<button id="email-login-resend-btn" class="code-modal-resend" type="button" onclick="resendEmailLoginCode()" data-i18n="resend_code">Отправить еще раз</button>
|
||
</div>
|
||
</div>
|
||
|
||
<section id="login" class="login login-layout">
|
||
<div class="panel-modal w-full grid gap-[17px] p-[18px] text-center">
|
||
<div class="login-head">
|
||
<img id="login-brand-logo" class="brand-logo brand-logo--lg hidden" data-brand-logo alt="" aria-hidden="true">
|
||
<div id="login-brand-title" class="login-brand-title" data-brand-title>Моя подписка</div>
|
||
</div>
|
||
<div class="auth-tabs-wrapper" role="tablist">
|
||
<button id="email-auth-tab" class="auth-tab active" type="button" onclick="setAuthMode('email')" data-i18n="email_login_tab">Email</button>
|
||
<button id="telegram-auth-tab" class="auth-tab" type="button" onclick="setAuthMode('telegram')" data-i18n="telegram_login_tab">Telegram</button>
|
||
</div>
|
||
<div id="email-login-pane" class="grid gap-2.5">
|
||
<div class="grid gap-2.5">
|
||
<input id="email-login-input" class="input w-full" type="email" autocomplete="email" inputmode="email" placeholder="mail@example.com" data-placeholder-i18n="email_placeholder">
|
||
<button id="email-login-send-btn" class="btn-primary w-full" type="button" onclick="requestEmailLoginCode()" data-i18n="send_code">Отправить код</button>
|
||
</div>
|
||
</div>
|
||
<div id="telegram-login-pane" class="hidden grid gap-2.5">
|
||
<div id="telegram-login-widget" class="telegram-login-widget" aria-live="polite"></div>
|
||
</div>
|
||
<div id="auth-status" class="status-text hidden" aria-live="polite"></div>
|
||
</div>
|
||
<div id="legal-links-login" data-legal-links class="legal-links hidden">
|
||
<a class="legal-link max-[560px]:flex-[1_1_100%]" data-legal-key="privacyPolicyUrl" href="#" target="_blank" rel="noopener" data-i18n="privacy_policy">Политика конфиденциальности</a>
|
||
<a class="legal-link max-[560px]:flex-[1_1_100%]" data-legal-key="userAgreementUrl" href="#" target="_blank" rel="noopener" data-i18n="user_agreement">Пользовательское соглашение</a>
|
||
</div>
|
||
</section>
|
||
|
||
<div id="toast" class="toast hidden" role="status" aria-live="polite"></div>
|
||
|
||
<!-- WEBAPP_CONFIG_SCRIPT -->
|
||
<script src="./subscription_webapp.js" defer></script>
|
||
</body>
|
||
</html>
|