PageSourceSearch

https://smartclinician.ai/register.html

html smartclinician.ai collected 2026-10-05 15:05:39 UTC 26,568 bytes, 773 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en">
3<head>
4    <meta charset="UTF-8">
5    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6    <title>Register - Smart Clinician</title>
7    <style>
8        * {
9            margin: 0;
10            padding: 0;
11            box-sizing: border-box;
12            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
13        }
14
15        body {
16            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17            min-height: 100vh;
18            display: flex;
19            align-items: center;
20            justify-content: center;
21            padding: 20px;
22        }
23
24        .container {
25            background: white;
26            border-radius: 20px;
27            box-shadow: 0 20px 60px rgba(0,0,0,0.3);
28            overflow: hidden;
29            max-width: 900px;
30            width: 100%;
31            display: grid;
32            grid-template-columns: 1fr 1fr;
33        }
34
35        .left-panel {
36            background: linear-gradient(135deg, #34a853 0%, #4caf50 100%);
37            color: white;
38            padding: 60px 40px;
39            display: flex;
40            flex-direction: column;
41            justify-content: center;
42        }
43
44        .logo {
45            display: flex;
46            align-items: center;
47            gap: 10px;
48            margin-bottom: 30px;
49        }
50
51        .logo a {
52            color: white;
53            text-decoration: none;
54        }
55
56        .logo-icon {
57            font-size: 40px;
58        }
59
60        .logo h1 {
61            font-size: 28px;
62            font-weight: 600;
63        }
64
65        .left-panel h2 {
66            font-size: 32px;
67            margin-bottom: 20px;
68            line-height: 1.3;
69        }
70
71        .left-panel p {
72            font-size: 16px;
73            line-height: 1.6;
74            opacity: 0.9;
75        }
76
77        .benefits {
78            margin-top: 30px;
79        }
80
81        .benefit {
82            display: flex;
83            align-items: center;
84            gap: 10px;
85            margin-bottom: 15px;
86        }
87
88        .benefit-icon {
89            font-size: 24px;
90        }
91
92        .right-panel {
93            padding: 60px 40px;
94        }
95
96        .form-header {
97            margin-bottom: 30px;
98        }
99
100        .form-header h2 {
101            font-size: 28px;
102            color: #202124;
103            margin-bottom: 10px;
104        }
105
106        .form-header p {
107            color: #5f6368;
108            font-size: 14px;
109        }
110
111        .form-row {
112            display: grid;
113            grid-template-columns: 1fr 1fr;
114            gap: 15px;
115        }
116
117        .form-group {
118            margin-bottom: 20px;
119        }
120
121        label {
122            display: block;
123            margin-bottom: 8px;
124            font-weight: 600;
125            color: #202124;
126            font-size: 14px;
127        }
128
129        input {
130            width: 100%;
131            padding: 12px 15px;
132            border: 2px solid #dadce0;
133            border-radius: 8px;
134            font-size: 14px;
135            transition: all 0.3s;
136        }
137
138        input:focus {
139            outline: none;
140            border-color: #34a853;
141            box-shadow: 0 0 0 3px rgba(52, 168, 83, 0.1);
142        }
143
144        .password-strength {
145            height: 4px;
146            background: #dadce0;
147            border-radius: 2px;
148            margin-top: 8px;
149            overflow: hidden;
150        }
151
152        .password-strength-bar {
153            height: 100%;
154            width: 0%;
155            transition: all 0.3s;
156        }
157
158        .weak { width: 33%; background: #ea4335; }
159        .medium { width: 66%; background: #fbbc04; }
160        .strong { width: 100%; background: #34a853; }
161
162        .btn {
163            width: 100%;
164            padding: 14px;
165            background: linear-gradient(135deg, #34a853 0%, #4caf50 100%);
166            color: white;
167            border: none;
168            border-radius: 8px;
169            font-size: 16px;
170            font-weight: 600;
171            cursor: pointer;
172            transition: all 0.3s;
173            margin-top: 10px;
174        }
175
176        .btn:hover {
177            transform: translateY(-2px);
178            box-shadow: 0 10px 20px rgba(52, 168, 83, 0.3);
179        }
180
181        .btn:disabled {
182            opacity: 0.6;
183            cursor: not-allowed;
184            transform: none;
185        }
186
187        .divider {
188            text-align: center;
189            margin: 25px 0;
190            color: #5f6368;
191            font-size: 14px;
192        }
193
194        .login-link {
195            text-align: center;
196            margin-top: 20px;
197            color: #5f6368;
198            font-size: 14px;
199        }
200
201        .login-link a {
202            color: #34a853;
203            text-decoration: none;
204            font-weight: 600;
205        }
206
207        .login-link a:hover {
208            text-decoration: underline;
209        }
210
211        .alert {
212            padding: 12px 15px;
213            border-radius: 8px;
214            margin-bottom: 20px;
215            font-size: 14px;
216        }
217
218        .alert-error {
219            background: #fce8e6;
220            color: #d93025;
221            border: 1px solid #d93025;
222        }
223
224        .alert-success {
225            background: #e6f4ea;
226            color: #1e8e3e;
227            border: 1px solid #1e8e3e;
228        }
229
230        /* Verification Modal */
231        .verification-modal {
232            display: none;
233            position: fixed;
234            top: 0;
235            left: 0;
236            width: 100%;
237            height: 100%;
238            background: rgba(0, 0, 0, 0.6);
239            z-index: 10000;
240            align-items: center;
241            justify-content: center;
242            animation: fadeIn 0.3s;
243        }
244
245        .verification-modal.show {
246            display: flex;
247        }
248
249        @keyframes fadeIn {
250            from { opacity: 0; }
251            to { opacity: 1; }
252        }
253
254        .verification-modal-content {
255            background: white;
256            border-radius: 20px;
257            padding: 40px;
258            max-width: 500px;
259            width: 90%;
260            box-shadow: 0 20px 60px rgba(0,0,0,0.3);
261            text-align: center;
262            animation: slideUp 0.3s;
263        }
264
265        @keyframes slideUp {
266            from {
267                transform: translateY(30px);
268                opacity: 0;
269            }
270            to {
271                transform: translateY(0);
272                opacity: 1;
273            }
274        }
275
276        .verification-icon {
277            font-size: 64px;
278            margin-bottom: 20px;
279        }
280
281        .verification-modal-content h2 {
282            color: #202124;
283            margin-bottom: 15px;
284            font-size: 28px;
285        }
286
287        .verification-modal-content p {
288            color: #5f6368;
289            line-height: 1.6;
290            margin-bottom: 10px;
291        }
292
293        .verification-email {
294            background: #f8f9fa;
295            padding: 15px;
296            border-radius: 8px;
297            margin: 20px 0;
298            font-weight: 600;
299            color: #1a73e8;
300            font-size: 16px;
301        }
302
303        .verification-steps {
304            text-align: left;
305            margin: 25px 0;
306            padding: 20px;
307            background: #f8f9fa;
308            border-radius: 8px;
309        }
310
311        .verification-steps li {
312            margin: 10px 0;
313            color: #5f6368;
314            line-height: 1.6;
315        }
316
317        .verification-modal-btn {
318            background: linear-gradient(135deg, #34a853 0%, #4caf50 100%);
319            color: white;
320            padding: 14px 30px;
321            border: none;
322            border-radius: 8px;
323            font-size: 16px;
324            font-weight: 600;
325            cursor: pointer;
326            margin-top: 20px;
327            transition: all 0.3s;
328            width: 100%;
329        }
330
331        .verification-modal-btn:hover {
332            transform: translateY(-2px);
333            box-shadow: 0 10px 20px rgba(52, 168, 83, 0.3);
334        }
335
336        .loading {
337            display: inline-block;
338            width: 14px;
339            height: 14px;
340            border: 2px solid white;
341            border-top-color: transparent;
342            border-radius: 50%;
343            animation: spin 0.8s linear infinite;
344            margin-right: 8px;
345        }
346
347        @keyframes spin {
348            to { transform: rotate(360deg); }
349        }
350
351        .disclaimer-box {
352            background: #fff3cd;
353            border: 2px solid #ffc107;
354            border-radius: 8px;
355            padding: 20px;
356            margin: 20px 0;
357        }
358
359        .disclaimer-content {
360            font-size: 13px;
361            color: #333;
362        }
363
364        .disclaimer-content h3 {
365            color: #f57c00;
366            font-size: 16px;
367            margin-bottom: 10px;
368            display: flex;
369            align-items: center;
370            gap: 8px;
371        }
372
373        .disclaimer-content p {
374            margin-bottom: 10px;
375            color: #666;
376        }
377
378        .disclaimer-content strong {
379            color: #333;
380        }
381
382        .checkbox-label {
383            display: flex;
384            gap: 12px;
385            align-items: flex-start;
386            cursor: pointer;
387            font-size: 13px;
388            line-height: 1.6;
389            color: #333;
390        }
391
392        .checkbox-label input[type="checkbox"] {
393            width: 20px;
394            height: 20px;
395            cursor: pointer;
396            flex-shrink: 0;
397            margin-top: 2px;
398        }
399
400        .checkbox-label span {
401            flex: 1;
402        }
403
404        @media (max-width: 768px) {
405            .container {
406                grid-template-columns: 1fr;
407            }
408
409            .left-panel {
410                display: none;
411            }
412
413            .right-panel {
414                padding: 40px 20px;
415            }
416
417            .form-row {
418                grid-template-columns: 1fr;
419            }
420        }
421    </style>
422</head>
423<body>
424    <div class="container">
425        <div class="left-panel">
426            <div class="logo">
427                <div class="logo-icon">🩺</div>
428                <h1><a href="index.html">Smart Clinician</a></h1>
429            </div>
430            <h2>Join thousands of healthcare professionals</h2>
431            <p>Start making smarter clinical decisions with AI-powered medical insights.</p>
432            <div class="benefits">
433                <div class="benefit">
434                    <div class="benefit-icon">✅</div>
435                    <div>Free tier with 5 cases per month</div>
436                </div>
437                <div class="benefit">
438                    <div class="benefit-icon">🚀</div>
439                    <div>Instant access to AI diagnosis</div>
440                </div>
441                <div class="benefit">
442                    <div class="benefit-icon">📚</div>
443                    <div>Evidence-based recommendations</div>
444                </div>
445                <div class="benefit">
446                    <div class="benefit-icon">💼</div>
447                    <div>Upgrade anytime to Professional</div>
448                </div>
449            </div>
450        </div>
451
452        <div class="right-panel">
453            <div class="form-header">
454                <h2>Create Account</h2>
455                <p>Start your 30-day free trial today</p>
456            </div>
457
458            <div id="alert"></div>
459
460            <form id="registerForm">
461                <div class="form-row">
462                    <div class="form-group">
463                        <label for="firstName">First Name</label>
464                        <input type="text" id="firstName" name="firstName" placeholder="John" required>
465                    </div>
466
467                    <div class="form-group">
468                        <label for="lastName">Last Name</label>
469                        <input type="text" id="lastName" name="lastName" placeholder="Doe" required>
470                    </div>
471                </div>
472
473                <div class="form-group">
474                    <label for="email">Email Address</label>
475                    <input type="email" id="email" name="email" placeholder="[email protected]" required>
476                </div>
477
478                <div class="form-group">
479                    <label for="username">Username</label>
480                    <input type="text" id="username" name="username" placeholder="Choose a unique username" required minlength="3" maxlength="30" pattern="[a-zA-Z0-9_-]+">
481                    <small style="display: block; margin-top: 5px; color: #666; font-size: 12px;">3-30 characters, letters, numbers, - and _ only</small>
482                </div>
483
484                <div class="form-group">
485                    <label for="password">Password</label>
486                    <input type="password" id="password" name="password" placeholder="Minimum 8 characters" required>
487                    <div class="password-strength">
488                        <div class="password-strength-bar" id="strengthBar"></div>
489                    </div>
490                </div>
491
492                <div class="form-group">
493                    <label for="confirmPassword">Confirm Password</label>
494                    <input type="password" id="confirmPassword" name="confirmPassword" placeholder="Re-enter password" required>
495                </div>
496
497                <div class="disclaimer-box">
498                    <div class="disclaimer-content">
499                        <h3>⚠️ Important Medical Disclaimer</h3>
500                        <p style="margin-top: 10px; line-height: 1.6;">
501                            <strong>Smart Clinician AI is a clinical decision support tool intended for guidance only.</strong> 
502                            The information provided by this system, including AI-generated diagnoses, treatment recommendations, 
503                            and medical guidance, is for <strong>informational and educational purposes only</strong>.
504                        </p>
505                        <p style="margin-top: 10px; line-height: 1.6;">
506                            This tool <strong>does not replace professional medical judgment</strong>, clinical examination, 
507                            or direct patient care. All recommendations must be verified by qualified healthcare professionals. 
508                            Healthcare providers remain fully responsible for all clinical decisions and patient care.
509                        </p>
510                        <p style="margin-top: 10px; line-height: 1.6;">
511                            This tool uses AI models trained on publicly available medical literature and is <strong>not affiliated 
512                            with, endorsed by, or licensed from UpToDate, PubMed, Cochrane, AHA/ACC, NICE, IDSA, ESC, or any other 
513                            medical organization</strong>.
514                        </p>
515                        <p style="margin-top: 10px; line-height: 1.6; font-weight: 600;">
516                            By using this service, you acknowledge that AI-generated content may contain errors and should 
517                            always be independently verified against current evidence-based guidelines and standards of care.
518                        </p>
519                    </div>
520                    <div class="form-group" style="margin-top: 15px;">
521                        <label class="checkbox-label">
522                            <input type="checkbox" id="disclaimerAcknowledgment" name="disclaimerAcknowledgment" required>
523                            <span>
524                                I acknowledge that I have read and understood the disclaimer above. I understand that this 
525                                tool is for guidance only and does not replace professional medical judgment.
526                            </span>
527                        </label>
528                    </div>
529                </div>
530
531                <button type="submit" class="btn" id="submitBtn">
532                    Create Account
533                </button>
534            </form>
535
536            <div class="divider">OR</div>
537
538            <div class="login-link">
539                Already have an account? <a href="login.html">Sign In</a>
540            </div>
541        </div>
542    </div>
543
544    <!-- Email Verification Modal -->
545    <div id="verificationModal" class="verification-modal">
546        <div class="verification-modal-content">
547            <div class="verification-icon">✉️</div>
548            <h2>Check Your Email!</h2>
549            <p>We've sent a verification email to:</p>
550            <div class="verification-email" id="verificationEmail">[email protected]</div>
551            <p>Please click the verification link in the email to activate your account.</p>
552            
553            <div class="verification-steps">
554                <h3 style="margin-bottom: 15px; color: #202124; font-size: 16px;">📋 Next Steps:</h3>
555                <ol style="padding-left: 20px;">
556                    <li>Check your email inbox (and spam folder)</li>
557                    <li>Click the verification link in the email</li>
558                    <li>Return to the login page to sign in</li>
559                </ol>
560            </div>
561
562            <p style="font-size: 13px; color: #999; margin-top: 20px;">
563                Didn't receive the email? Check your spam folder or contact support.
564            </p>
565
566            <button class="verification-modal-btn" onclick="closeVerificationModal()">
567                Got it! Take me to Login
568            </button>
569        </div>
570    </div>
571
572    
572<script>
573        // Use global API_URL if available, otherwise set it
574        if (typeof window.API_URL === 'undefined') {
575            window.API_URL = 'https://smartclinician.ai/api';
576        }
577        const form = document.getElementById('registerForm');
578        const submitBtn = document.getElementById('submitBtn');
579        const alertDiv = document.getElementById('alert');
580        const passwordInput = document.getElementById('password');
581        const strengthBar = document.getElementById('strengthBar');
582
583        // Password strength checker
584        passwordInput.addEventListener('input', (e) => {
585            const password = e.target.value;
586            let strength = 0;
587
588            if (password.length >= 8) strength++;
589            if (password.length >= 12) strength++;
590            if (/[a-z]/.test(password) && /[A-Z]/.test(password)) strength++;
591            if (/[0-9]/.test(password)) strength++;
592            if (/[^a-zA-Z0-9]/.test(password)) strength++;
593
594            strengthBar.className = 'password-strength-bar';
595            if (strength <= 2) {
596                strengthBar.classList.add('weak');
597            } else if (strength <= 4) {
598                strengthBar.classList.add('medium');
599            } else {
600                strengthBar.classList.add('strong');
601            }
602        });
603
604        form.addEventListener('submit', async (e) => {
605            e.preventDefault();
606            
607            const firstName = document.getElementById('firstName').value;
608            const lastName = document.getElementById('lastName').value;
609            const email = document.getElementById('email').value;
610            const username = document.getElementById('username').value;
611            const password = document.getElementById('password').value;
612            const confirmPassword = document.getElementById('confirmPassword').value;
613            const disclaimerAcknowledgment = document.getElementById('disclaimerAcknowledgment').checked;
614
615            // Validation
616            if (password !== confirmPassword) {
617                showAlert('Passwords do not match', 'error');
618                return;
619            }
620
621            if (password.length < 8) {
622                showAlert('Password must be at least 8 characters', 'error');
623                return;
624            }
625
626            if (!disclaimerAcknowledgment) {
627                showAlert('You must acknowledge the disclaimer to create an account', 'error');
628                return;
629            }
630
631            // Disable button and show loading
632            submitBtn.disabled = true;
633            submitBtn.innerHTML = '<span class="loading"></span>Creating account...';
634            alertDiv.innerHTML = '';
635
636            try {
637                const response = await fetch(`${API_URL}/auth/register`, {
638                    method: 'POST',
639                    headers: {
640                        'Content-Type': 'application/json'
641                    },
642                    body: JSON.stringify({ 
643                        firstName, 
644                        lastName, 
645                        email, 
646                        username, 
647                        password,
648                        disclaimerAcknowledged: disclaimerAcknowledgment
649                    })
650                });
651
652                const data = await response.json();
653
654                if (response.ok) {
655                    // Always reset button state on success
656                    submitBtn.disabled = false;
657                    submitBtn.innerHTML = 'Create Account';
658                    
659                    // CRITICAL: For new registrations, NEVER log in immediately
660                    // Always require email verification - this is the only safe path
661                    // Check for token first - if NO token exists, verification is required
662                    const hasToken = data.token && typeof data.token === 'string' && data.token.length > 0;
663                    const isVerified = data.user && data.user.emailVerified === true;
664                    const requiresVerification = data.requiresVerification === true || !hasToken || !isVerified;
665                    
666                    if (requiresVerification) {
667                        // Email verification REQUIRED - show modal and DO NOT log in
668                        // This is the expected and ONLY behavior for new registrations
669                        if (data.user && data.user.email) {
670                            showVerificationModal(data.user.email);
671                        } else {
672                            // Fallback if user data is missing
673                            showVerificationModal(data.email || email || 'your email');
674                        }
675                    } else if (hasToken && data.user && isVerified) {
676                        // ONLY allow login if ALL conditions are met:
677                        // 1. Token exists
678                        // 2. User data exists
679                        // 3. Email is verified
680                        // This should only happen for pre-verified accounts (very rare)
681                        // DISABLED: Even if token exists, require verification for new registrations
682                        console.warn('⚠️ Registration returned token but requiring verification anyway for security');
683                        // DO NOT store token - force verification
684                        showVerificationModal(data.user?.email || data.email || email || 'your email');
685                    } else {
686                        // Edge case - default to verification required
687                        console.warn('⚠️ Registration state unclear - defaulting to verification required');
688                        showVerificationModal(data.user?.email || data.email || email || 'your email');
689                    }
690                } else {
691                    // Registration failed
692                    showAlert(data.error || data.message || 'Registration failed. Please try again.', 'error');
693                    submitBtn.disabled = false;
694                    submitBtn.innerHTML = 'Create Account';
695                }
696            } catch (error) {
697                console.error('Registration error:', error);
698                showAlert('Network error. Please check your connection and try again.', 'error');
699                submitBtn.disabled = false;
700                submitBtn.innerHTML = 'Create Account';
701            }
702        });
703
704        function showAlert(message, type) {
705            alertDiv.innerHTML = `<div class="alert alert-${type}">${message}</div>`;
706        }
707
708        // Show verification modal
709        function showVerificationModal(email) {
710            const modal = document.getElementById('verificationModal');
711            const emailElement = document.getElementById('verificationEmail');
712            
713            if (emailElement) {
714                emailElement.textContent = email;
715            }
716            
717            if (modal) {
718                modal.classList.add('show');
719                // Prevent body scrolling when modal is open
720                document.body.style.overflow = 'hidden';
721            }
722        }
723
724        // Close verification modal and redirect to login
725        function closeVerificationModal() {
726            const modal = document.getElementById('verificationModal');
727            if (modal) {
728                modal.classList.remove('show');
729                document.body.style.overflow = '';
730                // Redirect to login page
731                window.location.href = 'login.html?message=' + encodeURIComponent('Please verify your email before logging in');
732            }
733        }
734
735        // Close modal when clicking outside
736        document.addEventListener('click', function(e) {
737            const modal = document.getElementById('verificationModal');
738            if (modal && e.target === modal) {
739                closeVerificationModal();
740            }
741        });
742
743        // Check if already logged in and verified
744        // IMPORTANT: Only redirect verified users - don't allow unverified users to skip verification
745        const existingToken = localStorage.getItem('token');
746        if (existingToken) {
747            // Verify user is actually verified before redirecting
748            fetch(`${API_URL}/auth/me`, {
749                headers: {
750                    'Authorization': `Bearer ${existingToken}`
751                }
752            })
753            .then(response => response.json())
754            .then(data => {
755                if (data.user && data.user.emailVerified === true) {
756                    // User is verified - allow redirect
757                    window.location.href = 'smartclinician.html';
758                } else {
759                    // User not verified - clear token and stay on registration page
760                    localStorage.removeItem('token');
761                    localStorage.removeItem('user');
762                }
763            })
764            .catch(() => {
765                // API call failed - clear invalid token
766                localStorage.removeItem('token');
767                localStorage.removeItem('user');
768            });
769        }
770    </script>
770
771</body>
772</html>
773

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.