@xouteiro/auth_npm 1.0.7 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +282 -30
- package/dist/index.mjs +282 -30
- package/package.json +1 -1
- package/src/components/LoginOnly.jsx +81 -18
- package/src/components/LoginRegisterFlow.jsx +103 -9
- package/src/components/LogoutButton.jsx +50 -5
- package/src/components/RegisterOnly.jsx +97 -30
@@ -2,76 +2,170 @@ import React, { useState } from 'react';
|
|
2
2
|
import { signInWithEmail } from '../login';
|
3
3
|
import { registerWithEmail } from '../register';
|
4
4
|
|
5
|
+
const boxStyle = {
|
6
|
+
maxWidth: 380,
|
7
|
+
margin: '40px auto',
|
8
|
+
padding: 32,
|
9
|
+
borderRadius: 14,
|
10
|
+
boxShadow: '0 2px 16px rgba(0,0,0,0.09)',
|
11
|
+
background: '#fff',
|
12
|
+
fontFamily: 'sans-serif',
|
13
|
+
};
|
14
|
+
|
15
|
+
const tabStyle = (active) => ({
|
16
|
+
flex: 1,
|
17
|
+
padding: 12,
|
18
|
+
border: 'none',
|
19
|
+
borderBottom: active ? '3px solid #0070f3' : '3px solid #eee',
|
20
|
+
background: 'none',
|
21
|
+
fontWeight: active ? 700 : 400,
|
22
|
+
color: active ? '#0070f3' : '#444',
|
23
|
+
cursor: 'pointer',
|
24
|
+
outline: 'none',
|
25
|
+
});
|
26
|
+
|
27
|
+
const inputStyle = {
|
28
|
+
width: '100%',
|
29
|
+
padding: 10,
|
30
|
+
margin: '10px 0',
|
31
|
+
borderRadius: 6,
|
32
|
+
border: '1px solid #ddd',
|
33
|
+
fontSize: 16,
|
34
|
+
};
|
35
|
+
|
36
|
+
const buttonStyle = {
|
37
|
+
width: '100%',
|
38
|
+
padding: 12,
|
39
|
+
borderRadius: 6,
|
40
|
+
border: 'none',
|
41
|
+
background: '#0070f3',
|
42
|
+
color: '#fff',
|
43
|
+
fontWeight: 600,
|
44
|
+
fontSize: 16,
|
45
|
+
marginTop: 10,
|
46
|
+
cursor: 'pointer',
|
47
|
+
};
|
48
|
+
|
49
|
+
const messageStyle = (success) => ({
|
50
|
+
margin: '12px 0',
|
51
|
+
color: success ? '#0a0' : '#d32f2f',
|
52
|
+
background: success ? '#eafbe7' : '#fdeaea',
|
53
|
+
padding: 8,
|
54
|
+
borderRadius: 6,
|
55
|
+
textAlign: 'center',
|
56
|
+
fontSize: 15,
|
57
|
+
});
|
58
|
+
|
5
59
|
export default function LoginRegisterFlow() {
|
6
60
|
const [mode, setMode] = useState('login');
|
7
61
|
const [identifier, setIdentifier] = useState('');
|
8
62
|
const [password, setPassword] = useState('');
|
9
63
|
const [username, setUsername] = useState('');
|
10
64
|
const [phone, setPhone] = useState('');
|
11
|
-
const [
|
65
|
+
const [message, setMessage] = useState(null);
|
66
|
+
const [success, setSuccess] = useState(false);
|
67
|
+
|
68
|
+
const resetFields = () => {
|
69
|
+
setIdentifier('');
|
70
|
+
setPassword('');
|
71
|
+
setUsername('');
|
72
|
+
setPhone('');
|
73
|
+
setMessage(null);
|
74
|
+
setSuccess(false);
|
75
|
+
};
|
12
76
|
|
13
77
|
const handleLogin = async (e) => {
|
14
78
|
e.preventDefault();
|
79
|
+
setMessage(null);
|
80
|
+
setSuccess(false);
|
15
81
|
const { error } = await signInWithEmail(identifier, password);
|
16
|
-
|
82
|
+
if (error) {
|
83
|
+
setMessage(error.message || 'Login failed');
|
84
|
+
setSuccess(false);
|
85
|
+
} else {
|
86
|
+
setMessage('Login successful!');
|
87
|
+
setSuccess(true);
|
88
|
+
setTimeout(resetFields, 1200);
|
89
|
+
}
|
17
90
|
};
|
18
91
|
|
19
92
|
const handleRegister = async (e) => {
|
20
93
|
e.preventDefault();
|
94
|
+
setMessage(null);
|
95
|
+
setSuccess(false);
|
21
96
|
const { error } = await registerWithEmail(identifier, password, username, phone);
|
22
|
-
|
97
|
+
if (error) {
|
98
|
+
setMessage(error.message || 'Registration failed');
|
99
|
+
setSuccess(false);
|
100
|
+
} else {
|
101
|
+
setMessage('Registration successful! Please check your email to confirm.');
|
102
|
+
setSuccess(true);
|
103
|
+
setTimeout(resetFields, 2000);
|
104
|
+
}
|
23
105
|
};
|
24
106
|
|
25
107
|
return (
|
26
|
-
<div>
|
27
|
-
<
|
28
|
-
|
108
|
+
<div style={boxStyle}>
|
109
|
+
<div style={{ display: 'flex', marginBottom: 24 }}>
|
110
|
+
<button style={tabStyle(mode === 'login')} onClick={() => { setMode('login'); setMessage(null); }}>Login</button>
|
111
|
+
<button style={tabStyle(mode === 'register')} onClick={() => { setMode('register'); setMessage(null); }}>Register</button>
|
112
|
+
</div>
|
29
113
|
{mode === 'login' ? (
|
30
114
|
<form onSubmit={handleLogin}>
|
31
115
|
<input
|
116
|
+
style={inputStyle}
|
32
117
|
type="text"
|
33
118
|
placeholder="Email, phone, or username"
|
34
119
|
value={identifier}
|
35
120
|
onChange={e => setIdentifier(e.target.value)}
|
121
|
+
required
|
36
122
|
/>
|
37
123
|
<input
|
124
|
+
style={inputStyle}
|
38
125
|
type="password"
|
39
126
|
placeholder="Password"
|
40
127
|
value={password}
|
41
128
|
onChange={e => setPassword(e.target.value)}
|
129
|
+
required
|
42
130
|
/>
|
43
|
-
<button type="submit">Login</button>
|
131
|
+
<button style={buttonStyle} type="submit">Login</button>
|
44
132
|
</form>
|
45
133
|
) : (
|
46
134
|
<form onSubmit={handleRegister}>
|
47
135
|
<input
|
136
|
+
style={inputStyle}
|
48
137
|
type="text"
|
49
138
|
placeholder="Email"
|
50
139
|
value={identifier}
|
51
140
|
onChange={e => setIdentifier(e.target.value)}
|
141
|
+
required
|
52
142
|
/>
|
53
143
|
<input
|
144
|
+
style={inputStyle}
|
54
145
|
type="password"
|
55
146
|
placeholder="Password"
|
56
147
|
value={password}
|
57
148
|
onChange={e => setPassword(e.target.value)}
|
149
|
+
required
|
58
150
|
/>
|
59
151
|
<input
|
152
|
+
style={inputStyle}
|
60
153
|
type="text"
|
61
154
|
placeholder="Username (optional)"
|
62
155
|
value={username}
|
63
156
|
onChange={e => setUsername(e.target.value)}
|
64
157
|
/>
|
65
158
|
<input
|
159
|
+
style={inputStyle}
|
66
160
|
type="text"
|
67
161
|
placeholder="Phone (optional)"
|
68
162
|
value={phone}
|
69
163
|
onChange={e => setPhone(e.target.value)}
|
70
164
|
/>
|
71
|
-
<button type="submit">Register</button>
|
165
|
+
<button style={buttonStyle} type="submit">Register</button>
|
72
166
|
</form>
|
73
167
|
)}
|
74
|
-
{
|
168
|
+
{message && <div style={messageStyle(success)}>{message}</div>}
|
75
169
|
</div>
|
76
170
|
);
|
77
171
|
}
|
@@ -1,18 +1,63 @@
|
|
1
1
|
import React, { useState } from 'react';
|
2
2
|
import { logout } from '../logout';
|
3
3
|
|
4
|
+
const boxStyle = {
|
5
|
+
maxWidth: 350,
|
6
|
+
margin: '24px auto',
|
7
|
+
padding: 20,
|
8
|
+
borderRadius: 10,
|
9
|
+
boxShadow: '0 2px 12px rgba(0,0,0,0.08)',
|
10
|
+
background: '#fff',
|
11
|
+
fontFamily: 'sans-serif',
|
12
|
+
textAlign: 'center',
|
13
|
+
};
|
14
|
+
|
15
|
+
const buttonStyle = {
|
16
|
+
padding: '10px 28px',
|
17
|
+
borderRadius: 6,
|
18
|
+
border: 'none',
|
19
|
+
background: '#0070f3',
|
20
|
+
color: '#fff',
|
21
|
+
fontWeight: 600,
|
22
|
+
fontSize: 16,
|
23
|
+
cursor: 'pointer',
|
24
|
+
};
|
25
|
+
|
26
|
+
const messageStyle = (success) => ({
|
27
|
+
margin: '12px 0',
|
28
|
+
color: success ? '#0a0' : '#d32f2f',
|
29
|
+
background: success ? '#eafbe7' : '#fdeaea',
|
30
|
+
padding: 8,
|
31
|
+
borderRadius: 6,
|
32
|
+
textAlign: 'center',
|
33
|
+
fontSize: 15,
|
34
|
+
});
|
35
|
+
|
4
36
|
export default function LogoutButton() {
|
5
|
-
const [
|
37
|
+
const [message, setMessage] = useState(null);
|
38
|
+
const [success, setSuccess] = useState(false);
|
6
39
|
|
7
40
|
const handleLogout = async () => {
|
41
|
+
setMessage(null);
|
42
|
+
setSuccess(false);
|
8
43
|
const { error } = await logout();
|
9
|
-
|
44
|
+
if (error) {
|
45
|
+
setMessage(error.message || 'Logout failed');
|
46
|
+
setSuccess(false);
|
47
|
+
} else {
|
48
|
+
setMessage('Logout successful!');
|
49
|
+
setSuccess(true);
|
50
|
+
setTimeout(() => {
|
51
|
+
setMessage(null);
|
52
|
+
setSuccess(false);
|
53
|
+
}, 1500);
|
54
|
+
}
|
10
55
|
};
|
11
56
|
|
12
57
|
return (
|
13
|
-
<div>
|
14
|
-
<button onClick={handleLogout}>Logout</button>
|
15
|
-
{
|
58
|
+
<div style={boxStyle}>
|
59
|
+
<button style={buttonStyle} onClick={handleLogout}>Logout</button>
|
60
|
+
{message && <div style={messageStyle(success)}>{message}</div>}
|
16
61
|
</div>
|
17
62
|
);
|
18
63
|
}
|
@@ -1,47 +1,114 @@
|
|
1
1
|
import React, { useState } from 'react';
|
2
2
|
import { registerWithEmail } from '../register';
|
3
3
|
|
4
|
+
const boxStyle = {
|
5
|
+
maxWidth: 350,
|
6
|
+
margin: '40px auto',
|
7
|
+
padding: 28,
|
8
|
+
borderRadius: 12,
|
9
|
+
boxShadow: '0 2px 12px rgba(0,0,0,0.08)',
|
10
|
+
background: '#fff',
|
11
|
+
fontFamily: 'sans-serif',
|
12
|
+
};
|
13
|
+
|
14
|
+
const inputStyle = {
|
15
|
+
width: '100%',
|
16
|
+
padding: 10,
|
17
|
+
margin: '10px 0',
|
18
|
+
borderRadius: 6,
|
19
|
+
border: '1px solid #ddd',
|
20
|
+
fontSize: 16,
|
21
|
+
};
|
22
|
+
|
23
|
+
const buttonStyle = {
|
24
|
+
width: '100%',
|
25
|
+
padding: 12,
|
26
|
+
borderRadius: 6,
|
27
|
+
border: 'none',
|
28
|
+
background: '#0070f3',
|
29
|
+
color: '#fff',
|
30
|
+
fontWeight: 600,
|
31
|
+
fontSize: 16,
|
32
|
+
marginTop: 10,
|
33
|
+
cursor: 'pointer',
|
34
|
+
};
|
35
|
+
|
36
|
+
const messageStyle = (success) => ({
|
37
|
+
margin: '12px 0',
|
38
|
+
color: success ? '#0a0' : '#d32f2f',
|
39
|
+
background: success ? '#eafbe7' : '#fdeaea',
|
40
|
+
padding: 8,
|
41
|
+
borderRadius: 6,
|
42
|
+
textAlign: 'center',
|
43
|
+
fontSize: 15,
|
44
|
+
});
|
45
|
+
|
4
46
|
export default function RegisterOnly() {
|
5
47
|
const [email, setEmail] = useState('');
|
6
48
|
const [password, setPassword] = useState('');
|
7
49
|
const [username, setUsername] = useState('');
|
8
50
|
const [phone, setPhone] = useState('');
|
9
|
-
const [
|
51
|
+
const [message, setMessage] = useState(null);
|
52
|
+
const [success, setSuccess] = useState(false);
|
10
53
|
|
11
54
|
const handleRegister = async (e) => {
|
12
55
|
e.preventDefault();
|
56
|
+
setMessage(null);
|
57
|
+
setSuccess(false);
|
13
58
|
const { error } = await registerWithEmail(email, password, username, phone);
|
14
|
-
|
59
|
+
if (error) {
|
60
|
+
setMessage(error.message || 'Registration failed');
|
61
|
+
setSuccess(false);
|
62
|
+
} else {
|
63
|
+
setMessage('Registration successful! Please check your email to confirm.');
|
64
|
+
setSuccess(true);
|
65
|
+
setTimeout(() => {
|
66
|
+
setEmail('');
|
67
|
+
setPassword('');
|
68
|
+
setUsername('');
|
69
|
+
setPhone('');
|
70
|
+
setMessage(null);
|
71
|
+
setSuccess(false);
|
72
|
+
}, 2000);
|
73
|
+
}
|
15
74
|
};
|
16
75
|
|
17
76
|
return (
|
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
|
-
|
77
|
+
<div style={boxStyle}>
|
78
|
+
<form onSubmit={handleRegister}>
|
79
|
+
<input
|
80
|
+
style={inputStyle}
|
81
|
+
type="text"
|
82
|
+
placeholder="Email"
|
83
|
+
value={email}
|
84
|
+
onChange={e => setEmail(e.target.value)}
|
85
|
+
required
|
86
|
+
/>
|
87
|
+
<input
|
88
|
+
style={inputStyle}
|
89
|
+
type="password"
|
90
|
+
placeholder="Password"
|
91
|
+
value={password}
|
92
|
+
onChange={e => setPassword(e.target.value)}
|
93
|
+
required
|
94
|
+
/>
|
95
|
+
<input
|
96
|
+
style={inputStyle}
|
97
|
+
type="text"
|
98
|
+
placeholder="Username (optional)"
|
99
|
+
value={username}
|
100
|
+
onChange={e => setUsername(e.target.value)}
|
101
|
+
/>
|
102
|
+
<input
|
103
|
+
style={inputStyle}
|
104
|
+
type="text"
|
105
|
+
placeholder="Phone (optional)"
|
106
|
+
value={phone}
|
107
|
+
onChange={e => setPhone(e.target.value)}
|
108
|
+
/>
|
109
|
+
<button style={buttonStyle} type="submit">Register</button>
|
110
|
+
</form>
|
111
|
+
{message && <div style={messageStyle(success)}>{message}</div>}
|
112
|
+
</div>
|
46
113
|
);
|
47
114
|
}
|