File size: 5,755 Bytes
3e30e4e
 
 
 
 
ef3e137
3e30e4e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ef3e137
 
3e30e4e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import React, { useEffect } from 'react';
import { useSearchParams } from 'react-router-dom';
import { Loader2, Zap } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import { APP_NAME, APP_TAGLINE } from '@/lib/branding';
import { useAuth } from '@/context/AuthContext';

export default function SignIn() {
    const { phase, googleOn } = useAuth();
    const [searchParams, setSearchParams] = useSearchParams();

    useEffect(() => {
        const err = searchParams.get('auth_error');
        if (!err) return;
        if (err === 'access_denied') {
            console.info('Google sign-in was cancelled.');
        } else if (err === 'invite_email_mismatch') {
            console.warn(
                'Invitation email does not match your Google account. Sign in with the invited address.'
            );
        } else {
            console.warn('Google sign-in error:', err);
        }
        const next = new URLSearchParams(searchParams);
        next.delete('auth_error');
        setSearchParams(next, { replace: true });
    }, [searchParams, setSearchParams]);

    const inviteParam = searchParams.get('invite');
    const googleHref = inviteParam
        ? `/api/auth/google?invite=${encodeURIComponent(inviteParam)}`
        : '/api/auth/google';

    if (phase === 'loading') {
        return (
            <div className="flex min-h-[100dvh] items-center justify-center bg-gradient-to-br from-slate-50 via-white to-violet-50">
                <Loader2 className="h-10 w-10 animate-spin text-violet-600" aria-label="Loading" />
            </div>
        );
    }

    if (phase === 'error') {
        return (
            <div className="flex min-h-[100dvh] items-center justify-center bg-gradient-to-br from-slate-50 via-white to-violet-50 px-4">
                <div className="max-w-md rounded-2xl border border-slate-200 bg-white p-8 text-center shadow-sm">
                    <p className="text-slate-700">Could not reach the server. Refresh and try again.</p>
                </div>
            </div>
        );
    }

    if (!googleOn) {
        return (
            <div className="flex min-h-[100dvh] items-center justify-center bg-gradient-to-br from-slate-50 via-white to-violet-50 px-4">
                <div className="max-w-md rounded-2xl border border-amber-200 bg-white p-8 text-center shadow-sm">
                    <p className="font-medium text-slate-800">Google sign-in is not configured</p>
                    <p className="mt-2 text-sm text-slate-600">
                        Set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET on the server to enable access.
                    </p>
                </div>
            </div>
        );
    }

    return (
        <div className="flex min-h-[100dvh] flex-col items-center justify-center bg-gradient-to-br from-slate-50 via-white to-violet-50 px-4 py-12">
            <div className="w-full max-w-md rounded-2xl border border-slate-200 bg-white p-8 shadow-lg shadow-violet-100/50 sm:p-10">
                <div className="mb-8 flex flex-col items-center text-center">
                    <div className="mb-4 flex h-14 w-14 items-center justify-center rounded-2xl bg-gradient-to-br from-violet-600 to-purple-600 shadow-lg shadow-violet-200">
                        <Zap className="h-7 w-7 text-white" aria-hidden />
                    </div>
                    <h1 className="text-2xl font-bold text-slate-800">{APP_NAME}</h1>
                    <p className="mt-2 text-sm text-slate-500">{APP_TAGLINE}</p>
                </div>

                <p className="mb-6 text-center text-slate-600">
                    Sign in with your Google account to access campaigns, contacts, leads, and deals.
                </p>

                {inviteParam ? (
                    <p className="mb-6 rounded-lg bg-violet-50 px-4 py-3 text-center text-sm text-violet-800">
                        You have a workspace invitation. Sign in with the email address that received the
                        invite.
                    </p>
                ) : null}

                <Button
                    asChild
                    size="lg"
                    className={cn(
                        'w-full gap-3 bg-white text-slate-800 border border-slate-200 shadow-sm',
                        'hover:bg-slate-50'
                    )}
                    variant="outline"
                >
                    <a href={googleHref} className="inline-flex items-center justify-center gap-3">
                        <GoogleMark className="h-5 w-5 shrink-0" />
                        <span>Sign in with Google</span>
                    </a>
                </Button>
            </div>
        </div>
    );
}

function GoogleMark({ className }) {
    return (
        <svg className={className} viewBox="0 0 24 24" aria-hidden>
            <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>
    );
}