# All files / src/pages Login.tsx

0% Statements 0/114
0% Branches 0/1
0% Functions 0/1
0% Lines 0/114

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156

     import React, { useState, useEffect } from 'react';
    import { useNavigate, useLocation, useSearchParams } from 'react-router-dom';
    import { useAuth } from '../contexts/AuthContext';

    export default function Login() {
      const { user, authEnabled, providers, loading, login } = useAuth();
      const navigate = useNavigate();
      const location = useLocation();
      const [searchParams] = useSearchParams();
      const [error, setError] = useState<string | null>(null);

      const fromLocation = (location.state as any)?.from;
      const from = fromLocation
        ? `${fromLocation.pathname || '/'}${fromLocation.search || ''}`
        : '/';
      const errorParam = searchParams.get('error');

      useEffect(() => {
        // If auth is disabled, redirect to dashboard
        if (!authEnabled && !loading) {
          navigate(from, { replace: true });
        }

        // If user is already logged in, redirect
        if (user && !loading) {
          navigate(from, { replace: true });
        }

        // Handle OAuth error from URL
        if (errorParam) {
          setError(getErrorMessage(errorParam));
        }
      }, [user, authEnabled, loading, from, navigate, errorParam]);

      const getErrorMessage = (error: string): string => {
        const messages: Record<string, string> = {
          microsoft_auth_failed: 'Microsoft authentication failed. Please try again.',
          google_auth_failed: 'Google authentication failed. Please try again.',
          no_email: 'Unable to retrieve email from provider. Please try a different account.',
          duplicate_email: 'An account with this email already exists with a different provider.'
        };
        return messages[error] || 'Authentication failed. Please try again.';
      };

      if (loading) {
        return (
          <div className="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-gray-900">
            <div className="text-center">
              <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4"></div>
              <p className="text-gray-600 dark:text-gray-400">Loading...</p>
            </div>
          </div>
        );
      }

      return (
        <div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-indigo-100 dark:from-gray-900 dark:to-gray-800 px-4">
          <div className="max-w-md w-full space-y-8">
            {/* Logo/Title */}
            <div className="text-center">
              <h1 className="text-4xl font-bold text-gray-900 dark:text-white mb-2">
                🎲 Sports Dashboard
              </h1>
              <p className="text-gray-600 dark:text-gray-400">
                Track your sports bets and analyze performance
              </p>
            </div>

            {/* Login Card */}
            <div className="bg-white dark:bg-gray-800 rounded-lg shadow-xl p-8">
              <h2 className="text-2xl font-bold text-center text-gray-900 dark:text-white mb-6">
                Sign in to continue
              </h2>

              {/* Error Message */}
              {error && (
                <div className="mb-6 p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg">
                  <div className="flex items-start">
                    <svg className="w-5 h-5 text-red-600 dark:text-red-400 mt-0.5 mr-3" fill="currentColor" viewBox="0 0 20 20">
                      <path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clipRule="evenodd" />
                    </svg>
                    <p className="text-sm text-red-800 dark:text-red-300">{error}</p>
                  </div>
                </div>
              )}

              {/* Login Buttons */}
              <div className="space-y-3">
                {providers.microsoft && (
                  <button
                    onClick={() => login('microsoft', from)}
                    className="w-full flex items-center justify-center px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg shadow-sm text-sm font-medium text-gray-700 dark:text-gray-200 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 transition-colors"
                  >
                    <svg className="w-5 h-5 mr-3" viewBox="0 0 23 23" fill="none">
                      <path d="M0 0h10.92v10.92H0V0z" fill="#f25022"/>
                      <path d="M12.08 0H23v10.92H12.08V0z" fill="#00a4ef"/>
                      <path d="M0 12.08h10.92V23H0V12.08z" fill="#7fba00"/>
                      <path d="M12.08 12.08H23V23H12.08V12.08z" fill="#ffb900"/>
                    </svg>
                    Sign in with Microsoft
                  </button>
                )}

                {providers.google && (
                  <button
                    onClick={() => login('google', from)}
                    className="w-full flex items-center justify-center px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg shadow-sm text-sm font-medium text-gray-700 dark:text-gray-200 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 transition-colors"
                  >
                    <svg className="w-5 h-5 mr-3" viewBox="0 0 24 24">
                      <path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/>
                      <path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/>
                      <path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/>
                      <path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/>
                    </svg>
                    Sign in with Google
                  </button>
                )}

                {!providers.microsoft && !providers.google && (
                  <div className="text-center py-4">
                    <p className="text-gray-500 dark:text-gray-400 text-sm">
                      No authentication providers configured
                    </p>
                    <p className="text-gray-400 dark:text-gray-500 text-xs mt-2">
                      Contact your administrator to set up OAuth2
                    </p>
                  </div>
                )}
              </div>

              {/* Help Text */}
              <div className="mt-6 text-center">
                <p className="text-xs text-gray-500 dark:text-gray-400">
                  By signing in, you agree to our Terms of Service and Privacy Policy
                </p>
              </div>
            </div>

            {/* Footer Info */}
            <div className="text-center text-sm text-gray-600 dark:text-gray-400">
              <p>Need help? Check the{' '}
                <a
                  href="https://github.com/WFord26/BetTrack/blob/main/dashboard/docs/AUTH_SETUP.md"
                  target="_blank"
                  rel="noreferrer"
                  className="text-blue-600 dark:text-blue-400 hover:underline"
                >
                  authentication setup guide
                </a>
              </p>
            </div>
          </div>
        </div>
      );
    }