Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"/> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"/> | |
| <title>Verify Email OTP — AI Medical Intelligence Pipeline</title> | |
| <!-- Favicon --> | |
| <link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='favicon.ico') }}" /> | |
| <link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('static', filename='favicon-192.png') }}" /> | |
| <link rel="apple-touch-icon" sizes="180x180" href="{{ url_for('static', filename='apple-touch-icon.png') }}" /> | |
| <meta name="description" content="Verify your email with one-time password."/> | |
| <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:wght@400;500;600;700;800&display=swap" rel="stylesheet"/> | |
| <link rel="stylesheet" href="{{ url_for('static', filename='css/base.css') }}"/> | |
| <link rel="stylesheet" href="{{ url_for('static', filename='css/auth.css') }}"/> | |
| </head> | |
| <body> | |
| <div class="auth-page"> | |
| <aside class="auth-brand"> | |
| <div class="auth-brand-logo"> | |
| <div class="auth-brand-icon"> | |
| <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <path d="M22 12h-4l-3 9L9 3l-3 9H2"/> | |
| </svg> | |
| </div> | |
| <span class="auth-brand-name">AI Medical Intelligence Pipeline</span> | |
| </div> | |
| <div class="auth-headline"> | |
| <h2>Check Your <span class="grad">Email</span></h2> | |
| <p>We sent a 6-digit code to your inbox. Enter it below to verify your identity and activate your account.</p> | |
| </div> | |
| <ul class="auth-features"> | |
| <li><span class="feat-icon">1</span>Open the email from the AI Medical Intelligence Pipeline</li> | |
| <li><span class="feat-icon">2</span>Copy the 6-digit code</li> | |
| <li><span class="feat-icon">3</span>Enter it here — valid for 10 minutes</li> | |
| </ul> | |
| </aside> | |
| <main class="auth-form-panel"> | |
| <div class="auth-card"> | |
| <div class="auth-card-header"> | |
| <h2>Enter your verification code</h2> | |
| <p>Sent to <strong>{{ email or 'your registered email' }}</strong></p> | |
| </div> | |
| {# --- Notice banners rendered from URL param (cookie-free) --- #} | |
| {% set notice = request.args.get('notice', '') %} | |
| {% if notice == 'otp_sent' %} | |
| <div class="alert alert-success">✅ Registration successful. A verification code was sent to your email.</div> | |
| {% elif notice == 'otp_resent' %} | |
| <div class="alert alert-success">✅ A fresh verification code was sent to your email.</div> | |
| {% elif notice == 'otp_email_failed' %} | |
| <div class="alert alert-info">⚠️ Account created, but the email could not be sent. Please use "Resend code" below.</div> | |
| {% elif notice == 'invalid_digits' %} | |
| <div class="alert alert-error">Please enter the full 6-digit code.</div> | |
| {% elif notice == 'invalid_code' %} | |
| <div class="alert alert-error">Invalid or expired code. Please try again or request a new one.</div> | |
| {% endif %} | |
| {# --- Legacy flash messages (still shown for local dev) --- #} | |
| {% with messages = get_flashed_messages(with_categories=true) %} | |
| {% if messages %} | |
| <div class="auth-alerts"> | |
| {% for category, message in messages %} | |
| <div class="alert alert-{{ category }}">{{ message }}</div> | |
| {% endfor %} | |
| </div> | |
| {% endif %} | |
| {% endwith %} | |
| <form method="POST" class="auth-form" id="otpForm" | |
| action="{{ url_for('auth.verify_otp', purpose=purpose, email=email, otp_token=otp_token) }}"> | |
| {# Carry the token in a hidden input so it survives the POST #} | |
| <input type="hidden" name="otp_token" value="{{ otp_token }}"/> | |
| <input type="hidden" name="otp" id="otpCombined"/> | |
| <div class="otp-grid" style="display:grid;grid-template-columns:repeat(6,1fr);gap:10px;"> | |
| <input type="text" inputmode="numeric" maxlength="1" name="d1" class="otp-digit" autocomplete="off" required/> | |
| <input type="text" inputmode="numeric" maxlength="1" name="d2" class="otp-digit" autocomplete="off" required/> | |
| <input type="text" inputmode="numeric" maxlength="1" name="d3" class="otp-digit" autocomplete="off" required/> | |
| <input type="text" inputmode="numeric" maxlength="1" name="d4" class="otp-digit" autocomplete="off" required/> | |
| <input type="text" inputmode="numeric" maxlength="1" name="d5" class="otp-digit" autocomplete="off" required/> | |
| <input type="text" inputmode="numeric" maxlength="1" name="d6" class="otp-digit" autocomplete="off" required/> | |
| </div> | |
| <button type="submit" class="btn-auth-submit" style="margin-top:16px;">Verify & Activate Account</button> | |
| </form> | |
| <form method="POST" action="{{ url_for('auth.resend_otp') }}" style="margin-top:12px;"> | |
| <input type="hidden" name="otp_token" value="{{ otp_token }}"/> | |
| <input type="hidden" name="email" value="{{ email }}"/> | |
| <input type="hidden" name="purpose" value="{{ purpose }}"/> | |
| <button type="submit" class="btn-auth-submit" style="background:#0f1b31;border:1px solid #2a3f68;">Didn't receive it? Resend code</button> | |
| </form> | |
| <div class="auth-footer"> | |
| Wrong account? <a href="{{ url_for('auth.login') }}">Back to sign in</a> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <script src="{{ url_for('static', filename='js/verify-otp.js') }}" defer></script> | |
| </body> | |
| </html> | |