CoolFace
Modelpublic

Ashok75/base2

sourceHugging Facemitupdated 9mo agoView on Hugging Face
0likes13downloads
auth.html1790 linesDownload Raw Back to root
1<!DOCTYPE html>2<html lang="en" data-bs-theme="dark">3<head>4    <meta charset="UTF-8">5    <meta name="viewport" content="width=device-width, initial-scale=1.0">6    <title>GAKR AI - Login/Signup</title>7    <link rel="stylesheet" href="https://cdn.replit.com/agent/bootstrap-agent-dark-theme.min.css">8    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">9    <style>10         :root {11            --gakr-blue: #4285F4;12            --gakr-blue-dark: #1a73e8;13            --gakr-blue-light: #e8f0fe;14            --gakr-grey-text: #5f6368;15            --gakr-grey-hover-bg: rgba(95, 99, 104, 0.1);16         }17 18          :root[data-bs-theme="dark"] {19             --gakr-blue: #8ab4f8;20             --gakr-blue-dark: #669df6;21             --gakr-blue-light: rgba(138, 180, 248, 0.1);22             --gakr-grey-text: #bdc1c6;23             --gakr-grey-hover-bg: rgba(189, 193, 198, 0.1);24          }25 26        @import url('https://fonts.googleapis.com/css?family=Poppins:400,500,600,700&display=swap');27 28        * {29            margin: 0;30            padding: 0;31            box-sizing: border-box;32            font-family: 'Poppins', sans-serif;33        }34 35        html, body {36            display: flex;37            flex-direction: column;38            align-items: center;39            height: 100%;40            width: 100%;41            background: -webkit-linear-gradient(left, #003366,#004080,#0059b3 , #0073e6);42            color: var(--bs-body-color);43            padding-top: calc(64px + 5vh);44            padding-bottom: 5vh;45            min-height: 100vh;46            /* Allow space for modal overlay */47            position: relative;48        }49 50        ::selection {51            background: var(--gakr-blue);52            color: #fff;53        }54 55        .wrapper {56            overflow: hidden;57            max-width: 440px;58            width: 90%;59            background: var(--bs-body-bg);60            box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.5);61            padding: 30px;62            border-radius: 15px;63            margin-top: 10px;64            margin-bottom: 10px;65            z-index: 10; /* Ensure wrapper is below modal but above background */66        }67 68        .wrapper .title-text {69            display: flex;70            width: 200%;71        }72 73        .wrapper .title {74            width: 50%;75            font-size: 35px;76            font-weight: 600;77            text-align: center;78            transition: all 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);79            color: var(--bs-body-color);80        }81 82        .wrapper .slide-controls {83            position: relative;84            display: flex;85            height: 50px;86            width: 100%;87            overflow: hidden;88            margin: 30px 0 10px 0;89            justify-content: space-between;90            border: 1px solid var(--bs-border-color);91            border-radius: 15px;92        }93 94        .slide-controls .slide {95            height: 100%;96            width: 100%;97            color: var(--bs-body-color);98            font-size: 18px;99            font-weight: 500;100            text-align: center;101            line-height: 48px;102            cursor: pointer;103            z-index: 1;104            transition: all 0.6s ease;105        }106 107        .slide-controls label.signup{108            color: var(--bs-body-color);109        }110 111        .slide-controls .slider-tab {112            position: absolute;113            height: 100%;114            width: 50%;115            left: 0;116            z-index: 0;117            border-radius: 15px;118            background: var(--gakr-blue);119            transition: all 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);120        }121 122        input[type="radio"]{123          display: none;124        }125 126        #signup:checked ~ .slider-tab{127          left: 50%;128        }129        #signup:checked ~ label.signup{130          color: #fff;131          cursor: default;132          user-select: none;133        }134        #signup:checked ~ label.login{135          color: var(--bs-body-color);136        }137        #login:checked ~ label.signup{138          color: var(--bs-body-color);139        }140        #login:checked ~ label.login{141          color: #fff;142          cursor: default;143          user-select: none;144        }145 146        .wrapper .form-container {147            width: 100%;148            overflow: hidden;149        }150 151        .form-container .form-inner {152            display: flex;153            width: 200%;154        }155 156        .form-container .form-inner form {157            width: 50%;158            transition: all 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);159        }160 161        .form-inner form .field {162            height: 50px;163            width: 100%;164            margin-top: 20px;165            position: relative;166        }167 168         .form-inner form .field:has(+ .field.btn) {169              margin-bottom: 25px;170         }171 172        .form-inner form .field input{173            height: 100%;174            width: 100%;175            outline: none;176            padding-left: 15px;177            border-radius: 15px;178            border: 1px solid var(--bs-border-color);179            border-bottom-width: 2px;180            font-size: 17px;181            transition: all 0.3s ease;182            color: var(--bs-body-color);183            background-color: var(--bs-body-bg);184        }185 186        .form-inner form .field input.error {187             border-color: red;188        }189 190        .form-inner form .field input::placeholder{191            color: var(--bs-secondary-color);192            transition: all 0.3s ease;193        }194 195        form .field input:focus::placeholder{196            color: var(--gakr-blue);197        }198 199        .form-inner form .pass-link{200          margin-top: 5px;201            font-size: 0.9rem;202            text-align: right; /* Align to right */203        }204 205        .form-inner form .signup-link{206          text-align: center;207          margin-top: 30px;208            font-size: 0.9rem;209        }210 211        .form-inner form .pass-link a,212        .form-inner form .signup-link a{213            color: var(--gakr-blue);214            text-decoration: none;215            transition: color 0.2s ease-in-out;216        }217 218        .form-inner form .pass-link a:hover,219        form-inner form .signup-link a:hover{220          text-decoration: underline;221          color: var(--gakr-blue-dark);222        }223 224        form .btn {225            height: 50px;226            width: 100%;227            margin-top: 20px;228            border-radius: 15px;229            position: relative;230            overflow: hidden;231            background: none;232            transition: none;233        }234 235        form .btn input[type="submit"] {236            height: 100%;237            width: 100%;238            z-index: 1;239            position: relative;240            background: var(--gakr-blue);241            border: none;242            color: #fff;243            padding: 0;244            border-radius: 15px;245            font-size: 20px;246            font-weight: 500;247            cursor: pointer;248            transition: background-color 0.2s ease-in-out, transform 0.1s ease-in-out;249            display: flex;250            align-items: center;251            justify-content: center;252        }253 254        form .btn input[type="submit"]:hover {255            background-color: var(--gakr-blue-dark);256        }257 258        form .btn input[type="submit"]:active {259             transform: scale(0.98);260             transition: background-color 0s, transform 0.1s;261        }262 263        .error-message {264            color: red;265            font-size: 0.8rem;266            margin-top: 4px;267            position: absolute;268            bottom: -18px;269            left: 15px;270            white-space: nowrap;271        }272 273         .form-message {274            text-align: center;275            margin-top: 20px;276            font-size: 0.9rem;277            min-height: 1.2em;278         }279 280         .form-message.success {281            color: green;282         }283 284         .form-message.error {285            color: red;286         }287 288         .loading-spinner {289            display: inline-block;290            width: 18px;291            height: 18px;292            border: 3px solid rgba(255, 255, 255, .3);293            border-radius: 50%;294            border-top-color: #fff;295            animation: spin 1s ease-in-out infinite;296            margin-left: 10px;297            vertical-align: middle;298         }299 300         @keyframes spin {301           to { -webkit-transform: rotate(360deg); }302         }303 304         .form-inner form .btn input[type="submit"]:disabled {305            opacity: 0.7;306            cursor: not-allowed;307            position: relative;308         }309 310         /* --- Modal Styles --- */311         .modal-overlay {312            position: fixed;313            top: 0;314            left: 0;315            width: 100%;316            height: 100%;317            background-color: rgba(0, 0, 0, 0.6); /* Semi-transparent black overlay */318            display: flex;319            justify-content: center;320            align-items: center;321            z-index: 100; /* On top of everything */322            visibility: hidden; /* Hidden by default */323            opacity: 0;324            transition: visibility 0s, opacity 0.3s ease-in-out;325         }326 327         .modal-overlay.show {328            visibility: visible;329            opacity: 1;330         }331 332         .modal-content {333            background-color: var(--bs-body-bg);334            padding: 30px;335            border-radius: 15px;336            box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.7);337            text-align: center;338            max-width: 350px;339            width: 80%;340            transform: translateY(-20px); /* Slight animation on show */341            transition: transform 0.3s ease-in-out;342         }343 344         .modal-overlay.show .modal-content {345             transform: translateY(0);346         }347 348         .modal-message {349            font-size: 1.1rem;350            margin-bottom: 25px;351            color: var(--bs-body-color);352         }353         .modal-message p {354            margin-bottom: 10px; /* Spacing for paragraphs in modal message */355            line-height: 1.4;356         }357         .modal-message strong {358            font-size: 1.2rem; /* Heading for attempts message */359            display: block;360            margin-bottom: 15px;361         }362         .modal-message ul {363            list-style: none;364            padding: 0;365            margin-bottom: 20px;366         }367         .modal-message ul li {368            margin-bottom: 8px;369            font-size: 1rem;370         }371 372 373         .modal-button {374            background-color: var(--gakr-blue);375            color: #fff;376            border: none;377            padding: 10px 25px;378            border-radius: 10px;379            font-size: 1rem;380            cursor: pointer;381            transition: background-color 0.2s ease-in-out, transform 0.1s ease-in-out;382         }383 384         .modal-button:hover {385            background-color: var(--gakr-blue-dark);386         }387 388         .modal-button:active {389            transform: scale(0.98);390         }391         392         .modal-buttons-stacked {393            display: flex;394            flex-direction: column; /* Stack buttons vertically */395            gap: 10px;396            margin-top: 20px;397         }398 399         .modal-buttons-stacked .modal-button {400            width: 100%; /* Make buttons full width */401         }402 403         .modal-buttons-inline {404            display: flex;405            justify-content: space-between; /* Space them out */406            gap: 15px;407            margin-top: 20px;408         }409         .modal-buttons-inline .modal-button {410             flex-grow: 1; /* Allow buttons to grow to fill space */411             max-width: none; /* Override max-width from .modal-buttons */412         }413 414 415         /* Eye icon styles */416         .field .toggle-password {417            position: absolute;418            right: 15px;419            top: 50%;420            transform: translateY(-50%);421            cursor: pointer;422            color: var(--bs-secondary-color);423            font-size: 0.9rem;424         }425 426         .field .toggle-password:hover {427             color: var(--gakr-blue);428         }429 430         /* Added styles for Forgot/Reset Modals */431         .modal-form {432             text-align: left;433             margin-top: 20px;434         }435         .modal-form .field {436             margin-bottom: 15px;437             height: auto; /* Override default field height */438         }439         .modal-form label {440             display: block;441             margin-bottom: 5px;442             font-size: 0.9rem;443             color: var(--bs-body-color);444         }445         .otp-input-container {446             display: flex;447             gap: 5px;448             justify-content: center;449             margin-bottom: 10px;450         }451         .otp-digit {452             width: 40px;453             height: 40px;454             text-align: center;455             border: 1px solid var(--bs-border-color);456             border-radius: 5px;457             font-size: 1.2rem;458             background-color: var(--bs-body-bg);459             color: var(--bs-body-color);460         }461         .otp-digit:focus {462             border-color: var(--gakr-blue);463             outline: none;464         }465         .modal-form .error-message {466            position: static; /* Remove absolute positioning */467            margin-top: 5px;468            margin-left: 0;469            white-space: normal; /* Allow message to wrap */470         }471         .modal-buttons {472             display: flex;473             justify-content: center;474             gap: 15px;475             margin-top: 20px;476         }477         .modal-buttons button {478             width: 100%;479             max-width: 150px;480         }481 482        /* Header styles */483        .gakr-chat-header {484            padding: 0.75rem 1.5rem;485            display: flex;486            justify-content: space-between;487            align-items: center;488            border-bottom: 1px solid var(--bs-border-color);489            height: 64px;490            position: fixed;491            top: 0;492            left: 0;493            right: 0;494            width: 100%;495            background-color: var(--bs-body-bg);496            z-index: 10;497        }498 499        .gakr-logo-area {500            display: flex;501            align-items: center;502            gap: 0.75rem;503        }504 505        .gakr-brand-logo {506            width: 24px;507            height: 24px;508            display: flex;509            align-items: center;510            justify-content: center;511        }512 513        .gakr-brand-text {514            font-size: 1.25rem;515            font-weight: 500;516            color: var(--gakr-blue);517        }518 519        .gakr-nav-controls {520            display: flex;521            align-items: center;522        }523 524        .gakr-login-button {525            color: var(--gakr-blue);526            text-decoration: none;527            background: transparent;528            border: 1px solid var(--gakr-blue);529            padding: 0.5rem 1rem;530            border-radius: 50px;531            font-size: 0.9rem;532            transition: background-color 0.2s;533        }534 535        .gakr-login-button:hover {536            background-color: rgba(66, 133, 244, 0.1);537        }538 539        .gakr-profile-button {540            color: var(--gakr-blue);541            text-decoration: none;542            background: transparent;543            border: none;544            padding: 0.5rem 1rem;545            border-radius: 50px;546            font-size: 0.9rem;547            transition: background-color 0.2s;548            display: flex;549            align-items: center;550            gap: 0.5rem;551        }552 553        .gakr-profile-button:hover {554            background-color: rgba(66, 133, 244, 0.1);555        }556    </style>557</head>558<body>559    <header class="gakr-chat-header">560        <div class="gakr-logo-area">561            <a href="/" class="gakr-brand-logo">562                <i class="fas fa-robot" style="color: var(--gakr-blue);"></i>563            </a>564            <a href="/" class="gakr-brand-text" style="text-decoration: none;">GAKR AI</a>565        </div>566 567        <div class="gakr-nav-controls" id="authButtonContainer">568            <a href="/auth" class="gakr-login-button">Sign in / Register</a>569        </div>570    </header>571 572    <div class="wrapper">573        <div class="title-text">574            <div class="title login">Login Form</div>575            <div class="title signup">Signup Form</div>576        </div>577        <div class="form-container">578            <div class="slide-controls">579                <input type="radio" name="slide" id="login" checked>580                <input type="radio" name="slide" id="signup">581                <label for="login" class="slide login">Login</label>582                <label for="signup" class="slide signup">Signup</label>583                <div class="slider-tab"></div>584            </div>585            <div class="form-inner">586                <form action="#" class="login" id="loginForm">587                    <div class="field">588                        <input type="text" placeholder="Username or Email" required id="loginUsernameOrEmail" name="username_or_email">589                        <div class="error-message" id="loginUsernameOrEmailError"></div>590                    </div>591                    <div class="field">592                        <input type="password" placeholder="Password" required id="loginPassword" name="password">593                        <span class="toggle-password fa-solid fa-eye-slash"></span>594                        <div class="error-message" id="loginPasswordError"></div>595                    </div>596                    <div class="pass-link"><a href="#" id="forgotPasswordLink">Forgot password?</a></div>597                    <div class="field btn">598                        <input type="submit" value="Login">599                    </div>600                    <div class="signup-link">Not a member? <a href="">Signup now</a></div>601                </form>602                <form action="#" class="signup" id="signupForm">603                    <div class="field">604                        <input type="text" placeholder="Name" required id="signupName" name="name">605                        <div class="error-message" id="signupNameError"></div>606                    </div>607                    <div class="field">608                        <input type="text" placeholder="Email Address" required id="signupEmail" name="email">609                        <div class="error-message" id="signupEmailError"></div>610                    </div>611                    <div class="field">612                        <input type="password" placeholder="Password" required id="signupPassword" name="password">613                        <span class="toggle-password fa-solid fa-eye-slash"></span>614                        <div class="error-message" id="signupPasswordError"></div>615                    </div>616                    <div class="field">617                        <input type="password" placeholder="Confirm password" required id="signupConfirmPassword" name="confirm_password">618                        <span class="toggle-password fa-solid fa-eye-slash"></span>619                        <div class="error-message" id="signupConfirmPasswordError"></div>620                    </div>621                    <div class="field btn">622                        <input type="submit" value="Signup">623                    </div>624                </form>625            </div>626        </div>627        <div class="form-message" id="generalFormMessage"></div>628    </div>629 630    <div class="modal-overlay" id="customModal">631        <div class="modal-content">632            <div class="modal-message" id="modalMessage"></div>633            <div id="modalButtonsContainer" class="modal-buttons">634            </div>635        </div>636    </div>637 638    <div class="modal-overlay" id="forgotPasswordRequestModal">639        <div class="modal-content" style="max-width: 450px;">640            <h3 style="text-align: center; margin-bottom: 20px; color: var(--gakr-blue);">Reset Password</h3>641            <p class="modal-message" id="forgotModalMessage" style="text-align: center; margin-bottom: 25px;">Enter your registered email address to receive a password reset code.</p>642            643            <form id="forgotPasswordRequestForm" class="modal-form">644                <div class="field" style="margin-bottom: 30px;">645                    <label for="forgotEmail" style="display: block; margin-bottom: 8px; font-weight: 500; color: var(--bs-body-color);">Email Address:</label>646                    <input type="email" id="forgotEmail" name="email" required style="width: 100%; padding: 12px; border: 2px solid var(--bs-border-color); border-radius: 8px; font-size: 16px; background-color: var(--bs-body-bg); color: var(--bs-body-color);" placeholder="Enter your email">647                    <div class="error-message" id="forgotEmailError" style="margin-top: 8px;"></div>648                </div>649                <div class="modal-buttons-stacked">650                    <button type="submit" class="modal-button" id="forgotSubmitButton" style="width: 100%; padding: 12px; font-size: 16px;">Send Reset Code</button>651                    <button type="button" class="modal-button" id="forgotCancelButton" style="width: 100%; padding: 12px; font-size: 16px; background-color: var(--bs-secondary-color); margin-top: 10px;">Cancel</button>652                </div>653            </form>654 655            <div id="otpSection" style="display: none;">656                <h3 style="text-align: center; margin-bottom: 20px; color: var(--gakr-blue);">Enter Verification Code</h3>657                <p style="text-align: center; margin-bottom: 25px; color: var(--bs-secondary-color);">We've sent a 8-digit code to your email. Enter it below to continue.</p>658                <form id="verifyOtpForm" class="modal-form">659                    <div class="field" style="margin-bottom: 30px;">660                        <label style="display: block; margin-bottom: 15px; font-weight: 500; color: var(--bs-body-color); text-align: center;">Verification Code:</label>661                        <div class="otp-input-container" style="display: flex; justify-content: center; gap: 8px; margin-bottom: 10px;">662                            <input type="text" class="otp-digit" maxlength="1" pattern="\d" required style="width: 45px; height: 50px; text-align: center; font-size: 20px; font-weight: bold; border: 2px solid var(--bs-border-color); border-radius: 8px; background-color: var(--bs-body-bg); color: var(--bs-body-color);">663                            <input type="text" class="otp-digit" maxlength="1" pattern="\d" required style="width: 45px; height: 50px; text-align: center; font-size: 20px; font-weight: bold; border: 2px solid var(--bs-border-color); border-radius: 8px; background-color: var(--bs-body-bg); color: var(--bs-body-color);">664                            <input type="text" class="otp-digit" maxlength="1" pattern="\d" required style="width: 45px; height: 50px; text-align: center; font-size: 20px; font-weight: bold; border: 2px solid var(--bs-border-color); border-radius: 8px; background-color: var(--bs-body-bg); color: var(--bs-body-color);">665                            <input type="text" class="otp-digit" maxlength="1" pattern="\d" required style="width: 45px; height: 50px; text-align: center; font-size: 20px; font-weight: bold; border: 2px solid var(--bs-border-color); border-radius: 8px; background-color: var(--bs-body-bg); color: var(--bs-body-color);">666                            <input type="text" class="otp-digit" maxlength="1" pattern="\d" required style="width: 45px; height: 50px; text-align: center; font-size: 20px; font-weight: bold; border: 2px solid var(--bs-border-color); border-radius: 8px; background-color: var(--bs-body-bg); color: var(--bs-body-color);">667                            <input type="text" class="otp-digit" maxlength="1" pattern="\d" required style="width: 45px; height: 50px; text-align: center; font-size: 20px; font-weight: bold; border: 2px solid var(--bs-border-color); border-radius: 8px; background-color: var(--bs-body-bg); color: var(--bs-body-color);">668                            <input type="text" class="otp-digit" maxlength="1" pattern="\d" required style="width: 45px; height: 50px; text-align: center; font-size: 20px; font-weight: bold; border: 2px solid var(--bs-border-color); border-radius: 8px; background-color: var(--bs-body-bg); color: var(--bs-body-color);">669                            <input type="text" class="otp-digit" maxlength="1" pattern="\d" required style="width: 45px; height: 50px; text-align: center; font-size: 20px; font-weight: bold; border: 2px solid var(--bs-border-color); border-radius: 8px; background-color: var(--bs-body-bg); color: var(--bs-body-color);">670                        </div>671                        <input type="hidden" id="otpInput" name="otp">672                        <div class="error-message" id="otpError" style="text-align: center; margin-top: 10px;"></div>673                    </div>674                    <div class="modal-buttons-stacked">675                        <button type="submit" class="modal-button" id="verifyOtpButton" style="width: 100%; padding: 12px; font-size: 16px;">Verify Code</button>676                        <button type="button" class="modal-button" id="resendOtpButton" style="width: 100%; padding: 12px; font-size: 16px; margin-top: 10px;">Send Code Again</button>677                        <button type="button" class="modal-button" id="otpCancelButton" style="width: 100%; padding: 12px; font-size: 16px; background-color: var(--bs-secondary-color); margin-top: 10px;">Cancel</button>678                    </div>679                </form>680            </div>681        </div>682    </div>683 684    <div class="modal-overlay" id="resetPasswordModal">685        <div class="modal-content">686            <p class="modal-message">Enter your new password.</p>687            <form id="resetPasswordForm" class="modal-form">688                <div class="field">689                    <label for="resetEmail">Email:</label>690                    <input type="email" id="resetEmail" name="email" required readonly style="background-color: var(--bs-secondary-bg); cursor: not-allowed;">691                    <div class="error-message" id="resetEmailError"></div>692                </div>693                <div class="field">694                    <label for="newPassword">New Password:</label>695                    <input type="password" id="newPassword" name="new_password" required>696                    <span class="toggle-password fa-solid fa-eye-slash"></span>697                    <div class="error-message" id="newPasswordError"></div>698                </div>699                <div class="field">700                    <label for="confirmNewPassword">Confirm New Password:</label>701                    <input type="password" id="confirmNewPassword" name="confirm_new_password" required>702                    <span class="toggle-password fa-solid fa-eye-slash"></span>703                    <div class="error-message" id="confirmNewPasswordError"></div>704                </div>705                <div class="modal-buttons-stacked">706                    <button type="submit" class="modal-button" id="resetSubmitButton">Reset Password</button>707                    <button type="button" class="modal-button" id="resetCancelButton" style="background-color: var(--bs-secondary-color);">Cancel</button>708                </div>709            </form>710        </div>711    </div>712 713<script>714    document.addEventListener('DOMContentLoaded', function() {715        // --- Authentication Status Check ---716        function updateAuthButton() {717            const authButtonContainer = document.getElementById('authButtonContainer');718            const userIsLoggedIn = localStorage.getItem('isLoggedIn') === 'true';719 720            if (userIsLoggedIn) {721                authButtonContainer.innerHTML = `722                    <a href="/profile" class="gakr-profile-button">723                        <i class="fas fa-user-circle me-2"></i>Profile724                    </a>725                `;726                 const profileButton = authButtonContainer.querySelector('.gakr-profile-button');727                 if (profileButton) {728                     profileButton.addEventListener('click', function(event) {729                         console.log("Profile button clicked!");730                     });731                 }732            } else {733                authButtonContainer.innerHTML = `734                    <a href="/auth" class="gakr-login-button">Sign in / Register</a>735                `;736            }737        }738 739        updateAuthButton();740        window.addEventListener('focus', updateAuthButton);741        window.addEventListener('storage', updateAuthButton);742 743        const loginText = document.querySelector(".title-text .login");744        const loginFormDiv = document.querySelector("form.login");745        const signupLink = document.querySelector("form .signup-link a");746        const loginRadio = document.getElementById('login');747        const signupRadio = document.getElementById('signup');748 749        const loginForm = document.getElementById('loginForm');750        const signupForm = document.getElementById('signupForm');751 752        // Existing form inputs and error displays753        const loginUsernameOrEmailInput = document.getElementById('loginUsernameOrEmail');754        const loginPasswordInput = document.getElementById('loginPassword');755        const loginSubmitButton = loginForm ? loginForm.querySelector('input[type="submit"]') : null;756 757        const signupNameInput = document.getElementById('signupName');758        const signupEmailInput = document.getElementById('signupEmail');759        const signupPasswordInput = document.getElementById('signupPassword');760        const signupConfirmPasswordInput = document.getElementById('signupConfirmPassword');761        const signupSubmitButton = signupForm ? signupForm.querySelector('input[type="submit"]') : null;762 763        const loginUsernameOrEmailError = document.getElementById('loginUsernameOrEmailError');764        const loginPasswordError = document.getElementById('loginPasswordError');765 766        const signupNameError = document.getElementById('signupNameError');767        const signupEmailError = document.getElementById('signupEmailError');768        const signupPasswordError = document.getElementById('signupPasswordError');769        const signupConfirmPasswordError = document.getElementById('signupConfirmPasswordError');770 771        const generalFormMessage = document.getElementById('generalFormMessage');772 773        // Modal elements (main alert modal)774        const customModal = document.getElementById('customModal');775        const modalMessageDiv = document.getElementById('modalMessage');776        const modalButtonsContainer = document.getElementById('modalButtonsContainer');777 778        // OTP digit inputs779        const otpDigits = document.querySelectorAll('.otp-digit');780        otpDigits.forEach((input, index) => {781            input.addEventListener('input', function() {782                if (this.value.length === 1 && index < otpDigits.length - 1) {783                    otpDigits[index + 1].focus();784                }785            });786            input.addEventListener('keydown', function(e) {787                if (e.key === 'Backspace' && this.value === '' && index > 0) {788                    otpDigits[index - 1].focus();789                }790            });791        });792        const forgotPasswordLink = document.getElementById('forgotPasswordLink');793        const forgotPasswordRequestModal = document.getElementById('forgotPasswordRequestModal'); // The main overlay for forgot/otp794        const forgotModalMessage = document.getElementById('forgotModalMessage'); // Message within the forgot/otp modal795 796        // Elements for Step 1: Request Email797        const forgotPasswordRequestForm = document.getElementById('forgotPasswordRequestForm');798        const forgotEmailInput = document.getElementById('forgotEmail');799        const forgotEmailError = document.getElementById('forgotEmailError');800        const forgotSubmitButton = document.getElementById('forgotSubmitButton');801        const forgotCancelButton = document.getElementById('forgotCancelButton');802 803        // Elements for Step 2: Enter OTP804        const otpSection = document.getElementById('otpSection'); // The container for OTP input and buttons805        const verifyOtpForm = document.getElementById('verifyOtpForm');806        const otpInput = document.getElementById('otpInput');807        const otpError = document.getElementById('otpError');808        const verifyOtpButton = document.getElementById('verifyOtpButton');809        const resendOtpButton = document.getElementById('resendOtpButton');810        const otpCancelButton = document.getElementById('otpCancelButton');811 812        // Reset Password Modal elements (Step 3: New Password)813        const resetPasswordModal = document.getElementById('resetPasswordModal');814        const resetPasswordForm = document.getElementById('resetPasswordForm');815        const resetEmailInput = document.getElementById('resetEmail'); // Hidden but read-only email field816        const newPasswordInput = document.getElementById('newPassword');817        const confirmNewPasswordInput = document.getElementById('confirmNewPassword');818        const resetEmailError = document.getElementById('resetEmailError'); // Error for reset email (should be rare)819        const newPasswordError = document.getElementById('newPasswordError');820        const confirmNewPasswordError = document.getElementById('confirmNewPasswordError');821        const resetSubmitButton = document.getElementById('resetSubmitButton');822        const resetCancelButton = document.getElementById('resetCancelButton');823 824        // New: Login Attempt Counter825        let loginAttempts = 0;826        const MAX_LOGIN_ATTEMPTS = 3;827 828        // Stores the email across the forgot password/OTP/reset flow829        let currentForgotEmail = '';830 831        // Resend OTP cooldown variables832        let resendCooldown = 0;833        let resendInterval = null;834 835        // Function to start resend cooldown timer836        function startResendCooldown() {837            resendCooldown = 60; // 60 seconds838            resendOtpButton.disabled = true;839            resendOtpButton.textContent = `Send Again (60s)`;840            resendOtpButton.style.backgroundColor = 'var(--bs-secondary-color)'; // Gray during cooldown841 842            resendInterval = setInterval(() => {843                resendCooldown--;844                if (resendCooldown > 0) {845                    resendOtpButton.textContent = `Send Again (${resendCooldown}s)`;846                } else {847                    clearInterval(resendInterval);848                    resendInterval = null;849                    resendOtpButton.disabled = false;850                    resendOtpButton.textContent = 'Send Code Again';851                    resendOtpButton.style.backgroundColor = ''; // Reset to default (primary blue)852                }853            }, 1000);854        }855 856        // Function to clear all error messages and input error classes857        function clearErrors(formType = 'all') {858            if (formType === 'all' || formType === 'main') {859                document.querySelectorAll('.error-message').forEach(el => el.textContent = '');860                document.querySelectorAll('.form-inner form .field input').forEach(el => el.classList.remove('error'));861                if (generalFormMessage) {862                    generalFormMessage.textContent = '';863                    generalFormMessage.className = 'form-message';864                }865            }866            if (formType === 'all' || formType === 'forgot') {867                if (forgotEmailError) forgotEmailError.textContent = '';868                if (forgotEmailInput) forgotEmailInput.classList.remove('error');869                // Also clear the general forgotModalMessage when resetting for new flow870                if (forgotModalMessage) forgotModalMessage.innerHTML = 'Enter your registered email to request a password reset.';871            }872            if (formType === 'all' || formType === 'otp') {873                if (otpError) otpError.textContent = '';874                if (otpInput) otpInput.classList.remove('error');875            }876            if (formType === 'all' || formType === 'reset') {877                if (resetEmailError) resetEmailError.textContent = '';878                if (newPasswordError) newPasswordError.textContent = '';879                if (confirmNewPasswordError) confirmNewPasswordError.textContent = '';880                if (resetEmailInput) resetEmailInput.classList.remove('error');881                if (newPasswordInput) newPasswordInput.classList.remove('error');882                if (confirmNewPasswordInput) confirmNewPasswordInput.classList.remove('error');883            }884        }885 886        // Function to display general form-level message (below the forms)887        function displayFormMessage(message, type = 'info') {888            if (generalFormMessage) {889                generalFormMessage.textContent = message;890                generalFormMessage.className = 'form-message ' + type;891            }892        }893 894        // Universal modal display function895        function showCustomModal(modalElement) {896            modalElement.classList.add('show');897        }898 899        // Universal modal hide function900        function hideCustomModal(modalElement) {901            modalElement.classList.remove('show');902            clearErrors(); // Clear all errors when any modal is hidden903        }904 905        // Function to show a flexible custom modal (for general alerts/info)906        function showFlexibleModal(messageHTML, buttonsConfig, callback = null) {907            modalMessageDiv.innerHTML = messageHTML;908            modalButtonsContainer.innerHTML = ''; // Clear previous buttons909 910            if (buttonsConfig && buttonsConfig.length > 0) {911                const isInline = buttonsConfig.every(btn => !btn.newline);912                modalButtonsContainer.className = isInline ? 'modal-buttons-inline' : 'modal-buttons-stacked';913 914                buttonsConfig.forEach(btnConf => {915                    const button = document.createElement('button');916                    button.className = 'modal-button';917                    button.textContent = btnConf.text;918                    if (btnConf.style) {919                        button.style = btnConf.style;920                    }921                    button.onclick = function() {922                        hideCustomModal(customModal);923                        if (btnConf.action && typeof btnConf.action === 'function') {924                            btnConf.action();925                        }926                        if (callback && typeof callback === 'function') {927                            callback();928                        }929                    };930                    modalButtonsContainer.appendChild(button);931                });932            } else {933                const okButton = document.createElement('button');934                okButton.className = 'modal-button';935                okButton.textContent = 'OK';936                okButton.onclick = function() {937                    hideCustomModal(customModal);938                    if (callback && typeof callback === 'function') {939                        callback();940                    }941                };942                modalButtonsContainer.classList.remove('modal-buttons-inline', 'modal-buttons-stacked');943                modalButtonsContainer.classList.add('modal-buttons');944                modalButtonsContainer.appendChild(okButton);945            }946            showCustomModal(customModal);947        }948 949        // Slide logic950        function slideToSignup() {951            if (loginFormDiv && loginText) {952                loginFormDiv.style.marginLeft = "-50%";953                loginText.style.marginLeft = "-50%";954                clearErrors('main');955            }956        }957 958        function slideToLogin() {959            if (loginFormDiv && loginText) {960                loginFormDiv.style.marginLeft = "0%";961                loginText.style.marginLeft = "0%";962                clearErrors('main');963            }964        }965 966        // Event listeners for radio buttons and signup link967        if (signupRadio) {968            signupRadio.addEventListener('change', function() {969                if (this.checked) {970                    slideToSignup();971                }972            });973        }974 975        if (loginRadio) {976            loginRadio.addEventListener('change', function() {977                if (this.checked) {978                    slideToLogin();979                }980            });981        }982 983        if (signupLink && signupRadio) {984            signupLink.onclick = ((e) => {985                e.preventDefault();986                signupRadio.checked = true;987                slideToSignup();988            });989        }990 991        // Handle URL parameter for initial tab992        const urlParams = new URLSearchParams(window.location.search);993        const showSignup = urlParams.get('signup');994 995        if (showSignup === 'true') {996            if (signupRadio) {997                signupRadio.checked = true;998                slideToSignup();999            }1000        } else {1001            if (loginRadio) {1002                loginRadio.checked = true;1003                slideToLogin();1004            }1005        }1006 1007        // Function to toggle password visibility1008        function setupPasswordToggle(passwordInput, toggleIcon) {1009            if (passwordInput && toggleIcon) {1010                toggleIcon.addEventListener('click', function() {1011                    const type = passwordInput.getAttribute('type') === 'password' ? 'text' : 'password';1012                    passwordInput.setAttribute('type', type);1013                    this.classList.toggle('fa-eye');1014                    this.classList.toggle('fa-eye-slash');1015                });1016            }1017        }1018 1019        // Setup password toggles for all password fields1020        setupPasswordToggle(loginPasswordInput, document.querySelector('#loginForm .toggle-password'));1021        setupPasswordToggle(signupPasswordInput, document.querySelector('#signupForm #signupPassword + .toggle-password'));1022        setupPasswordToggle(signupConfirmPasswordInput, document.querySelector('#signupForm #signupConfirmPassword + .toggle-password'));1023        setupPasswordToggle(newPasswordInput, document.querySelector('#resetPasswordForm #newPassword + .toggle-password'));1024        setupPasswordToggle(confirmNewPasswordInput, document.querySelector('#resetPasswordForm #confirmNewPassword + .toggle-password'));1025 1026 1027        // Login Form Submission Handler1028        if (loginForm) {1029            loginForm.addEventListener('submit', async function(event) {1030                event.preventDefault();1031                clearErrors('main'); // Clear main form errors1032 1033                // Only proceed if login attempts are below limit1034                if (loginAttempts >= MAX_LOGIN_ATTEMPTS) {1035                    showLoginAttemptsLimitModal();1036                    return; // Stop submission1037                }1038 1039                let isValid = true;1040 1041                const usernameOrEmail = loginUsernameOrEmailInput.value.trim();1042                const password = loginPasswordInput.value.trim();1043 1044                if (usernameOrEmail === '') {1045                    isValid = false;1046                    loginUsernameOrEmailError.textContent = 'Username or Email is required';1047                    loginUsernameOrEmailInput.classList.add('error');1048                }1049                if (password === '') {1050                    isValid = false;1051                    loginPasswordError.textContent = 'Password is required';1052                    loginPasswordInput.classList.add('error');1053                }1054 1055                if (isValid) {1056                    // Check if user exists1057                    try {1058                        const checkResponse = await fetch('/api/check_user', {1059                            method: 'POST',1060                            headers: { 'Content-Type': 'application/json' },1061                            body: JSON.stringify({ identifier: usernameOrEmail })1062                        });1063                        const checkData = await checkResponse.json();1064                        if (!checkData.exists) {1065                            loginUsernameOrEmailError.textContent = 'User does not exist.';1066                            loginUsernameOrEmailInput.classList.add('error');1067                            return;1068                        }1069                    } catch (error) {1070                        console.error('Error checking user:', error);1071                        // Proceed anyway1072                    }1073                    submitFormData(event.target, loginSubmitButton, '/api/login', 'main');1074                }1075            });1076        }1077 1078        // Signup Form Submission Handler1079        if (signupForm) {1080            signupForm.addEventListener('submit', async function(event) {1081                event.preventDefault();1082                clearErrors('main');1083 1084                let isValid = true;1085 1086                const name = signupNameInput.value.trim();1087                const email = signupEmailInput.value.trim();1088                const password = signupPasswordInput.value.trim();1089                const confirmPassword = signupConfirmPasswordInput.value.trim();1090 1091                if (name === '') {1092                    isValid = false;1093                    signupNameError.textContent = 'Name is required';1094                    signupNameInput.classList.add('error');1095                }1096 1097                if (email === '') {1098                    isValid = false;1099                    signupEmailError.textContent = 'Email is required';1100                    signupEmailInput.classList.add('error');1101                } else if (!isValidEmail(email)) {1102                    isValid = false;1103                    signupEmailError.textContent = 'Enter a valid email address';1104                    signupEmailInput.classList.add('error');1105                }1106 1107                if (password === '') {1108                    isValid = false;1109                    signupPasswordError.textContent = 'Password is required';1110                    signupPasswordInput.classList.add('error');1111                } else if (password.length < 6) {1112                    isValid = false;1113                    signupPasswordError.textContent = 'Password must be at least 6 characters';1114                    signupPasswordInput.classList.add('error');1115                }1116 1117                if (confirmPassword === '') {1118                    isValid = false;1119                    signupConfirmPasswordError.textContent = 'Confirm password is required';1120                    signupConfirmPasswordInput.classList.add('error');1121                } else if (password !== confirmPassword) {1122                    isValid = false;1123                    signupConfirmPasswordError.textContent = 'Passwords do not match';1124                    signupConfirmPasswordInput.classList.add('error');1125                    signupPasswordInput.classList.add('error');1126                }1127 1128                if (isValid) {1129                    // Check if user already exists1130                    try {1131                        const checkResponse = await fetch('/api/check_user', {1132                            method: 'POST',1133                            headers: { 'Content-Type': 'application/json' },1134                            body: JSON.stringify({ identifier: email })1135                        });1136                        const checkData = await checkResponse.json();1137                        if (checkData.exists) {1138                            signupEmailError.textContent = 'Email already registered.';1139                            signupEmailInput.classList.add('error');1140                            return;1141                        }1142                    } catch (error) {1143                        console.error('Error checking user:', error);1144                        // Proceed anyway1145                    }1146                    submitFormData(event.target, signupSubmitButton, '/api/signup', 'main');1147                }1148            });1149        }1150 1151        // Forgot Password Link Handler (Initial Click)1152        if (forgotPasswordLink) {1153            forgotPasswordLink.addEventListener('click', function(event) {1154                event.preventDefault();1155                clearErrors('forgot'); // Clear errors for email request1156                clearErrors('otp'); // Clear errors for OTP section1157 1158                forgotPasswordRequestForm.reset(); // Clear email input1159                otpInput.value = ''; // Clear OTP input1160                // Reset the general message for the forgot password modal1161                forgotModalMessage.innerHTML = 'Enter your registered email to request a password reset.';1162 1163                // Show the email request form and hide the OTP section1164                forgotPasswordRequestForm.style.display = 'block';1165                if (otpSection) otpSection.style.display = 'none'; // Ensure OTP section is hidden initially1166 1167                // Reset modal size for email input1168                const modalContent = forgotPasswordRequestModal.querySelector('.modal-content');1169                if (modalContent) {1170                    modalContent.style.maxWidth = '450px';1171                }1172 1173                showCustomModal(forgotPasswordRequestModal);1174            });1175        }1176 1177        // Step 1: Forgot Password Request Form Submission Handler (Requests OTP)1178        if (forgotPasswordRequestForm) {1179            forgotPasswordRequestForm.addEventListener('submit', async function(event) {1180                event.preventDefault();1181                clearErrors('forgot'); // Clear errors specific to the email request form1182 1183                let isValid = true;1184                const email = forgotEmailInput.value.trim();1185 1186                if (email === '') {1187                    isValid = false;1188                    forgotEmailError.textContent = 'Email is required.';1189                    forgotEmailInput.classList.add('error');1190                } else if (!isValidEmail(email)) {1191                    isValid = false;1192                    forgotEmailError.textContent = 'Enter a valid email address.';1193                    forgotEmailInput.classList.add('error');1194                }1195 1196                if (isValid) {1197                    forgotSubmitButton.disabled = true;1198                    forgotSubmitButton.innerHTML = '<span class="loading-spinner"></span> Sending OTP...';1199 1200                    try {

Showing the first 1,200 of 1790 lines. Download the file for the rest.