ATProto forum built with ESAV
1import React, { useState, useRef, useEffect } from 'react';
2import { useAuth } from '@/providers/OAuthProvider';
3interface AuthButtonProps {
4 compact?: boolean;
5}
6
7export default function Login({ compact = false }: AuthButtonProps) {
8 // 1. Get state and functions from the new OAuth context
9 const { status, startLogin, logout } = useAuth();
10
11 // State for the handle input and the dropdown visibility
12 const [handle, setHandle] = useState('');
13 const [showLoginForm, setShowLoginForm] = useState(false);
14 const formRef = useRef<HTMLDivElement>(null);
15
16 useEffect(() => {
17 // This logic for closing the dropdown on outside click is still useful
18 function handleClickOutside(event: MouseEvent) {
19 if (formRef.current && !formRef.current.contains(event.target as Node)) {
20 setShowLoginForm(false);
21 }
22 }
23 if (showLoginForm) {
24 document.addEventListener('mousedown', handleClickOutside);
25 }
26 return () => {
27 document.removeEventListener('mousedown', handleClickOutside);
28 };
29 }, [showLoginForm]);
30
31 // Handle the form submission
32 const handleLogin = async (e: React.FormEvent) => {
33 e.preventDefault();
34 if (!handle.trim()) {
35 alert('Please enter your handle (e.g., name.example.com)');
36 return;
37 }
38 // This will redirect the user, so no need to manage loading states here
39 await startLogin(handle);
40 };
41
42 // Render loading state if the provider is initializing
43 if (status === 'loading') {
44 return (
45 <div className="flex items-center justify-center p-6 text-gray-500 dark:text-gray-400">
46 Loading...
47 </div>
48 );
49 }
50
51 // If logged in, show a logout button
52 if (status === 'signedIn') {
53 const buttonClass = compact
54 ? "text-sm bg-gray-600 hover:bg-gray-700 text-white rounded px-3 py-1 font-medium transition-colors"
55 : "bg-gray-600 hover:bg-gray-700 text-white rounded px-6 py-2 font-semibold text-base transition-colors";
56
57 const loggedInContent = (
58 <button onClick={logout} className={buttonClass}>
59 Log out
60 </button>
61 );
62
63 if (compact) {
64 return loggedInContent;
65 }
66
67 return (
68 <div className="p-6 bg-gray-100 dark:bg-gray-900 rounded-xl shadow border border-gray-200 dark:border-gray-800 mt-6 mx-4">
69 <div className="flex flex-col items-center justify-center text-center">
70 <p className="text-lg font-semibold mb-6 text-gray-800 dark:text-gray-100">You are logged in!</p>
71 {loggedInContent}
72 </div>
73 </div>
74 );
75 }
76
77 // If logged out, show a login button/form
78 const loginButtonClass = compact
79 ? "text-sm bg-gray-600 hover:bg-gray-700 text-white rounded px-3 py-1 font-medium transition-colors"
80 : "bg-gray-600 hover:bg-gray-700 text-white rounded px-6 py-2 font-semibold text-base transition-colors mt-2";
81
82 const loginForm = (
83 <form onSubmit={handleLogin} className={`flex flex-col gap-${compact ? '3' : '4'}`}>
84 <p className="text-sm text-gray-500 dark:text-gray-400 mb-2">
85 Login with your AT Protocol (Bluesky) handle
86 </p>
87 <input
88 type="text"
89 placeholder="name.example.com"
90 value={handle}
91 onChange={e => setHandle(e.target.value)}
92 className="px-3 py-2 rounded border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 text-base focus:outline-none focus:ring-2 focus:ring-blue-500"
93 autoComplete="webauthn" // Hint for password managers
94 />
95 <button type="submit" className={loginButtonClass}>
96 Sign In
97 </button>
98 </form>
99 );
100
101 if (compact) {
102 return (
103 <div className="relative" ref={formRef}>
104 <button
105 onClick={() => setShowLoginForm(!showLoginForm)}
106 className={loginButtonClass}
107 >
108 Log in
109 </button>
110 {showLoginForm && (
111 <div className="absolute top-full right-0 mt-2 w-80 bg-white dark:bg-gray-900 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 p-4 z-50">
112 {loginForm}
113 </div>
114 )}
115 </div>
116 );
117 }
118
119 return (
120 <div className="p-6 bg-gray-100 dark:bg-gray-900 rounded-xl shadow border border-gray-200 dark:border-gray-800 mt-6 mx-4">
121 {loginForm}
122 </div>
123 );
124}