@ebubekirylmaz/link-test 1.2.42 → 1.2.44
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/package.json +1 -1
- package/src/widgets/Login/CognitoLogin.jsx +275 -73
package/package.json
CHANGED
|
@@ -1,22 +1,63 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Box,
|
|
3
|
+
Button,
|
|
4
|
+
Card,
|
|
5
|
+
IconButton,
|
|
6
|
+
InputAdornment,
|
|
7
|
+
Stack,
|
|
8
|
+
TextField,
|
|
9
|
+
Typography,
|
|
10
|
+
alpha,
|
|
11
|
+
} from "@mui/material";
|
|
12
|
+
import {
|
|
13
|
+
EmailOutlined,
|
|
14
|
+
LockOutlined,
|
|
15
|
+
MarkEmailReadOutlined,
|
|
16
|
+
Visibility,
|
|
17
|
+
VisibilityOff,
|
|
18
|
+
} from "@mui/icons-material";
|
|
19
|
+
import { confirmSignup, getTokens, login, signup } from "./amplifyAuth";
|
|
20
|
+
|
|
1
21
|
import config from "../../config/config";
|
|
22
|
+
import { publish } from "@nucleoidai/react-event";
|
|
2
23
|
import { storage } from "@nucleoidjs/webstorage";
|
|
3
24
|
import { useNavigate } from "react-router-dom";
|
|
4
|
-
import { useSnackbar } from "notistack";
|
|
5
25
|
import { useState } from "react";
|
|
6
26
|
|
|
7
|
-
|
|
8
|
-
|
|
27
|
+
const inputSx = {
|
|
28
|
+
"& .MuiOutlinedInput-root": {
|
|
29
|
+
fontSize: "1rem",
|
|
30
|
+
"& input": { py: 1.5 },
|
|
31
|
+
"&:hover fieldset": { borderColor: "primary.main" },
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const primaryButtonSx = {
|
|
36
|
+
py: 1.5,
|
|
37
|
+
fontSize: "1rem",
|
|
38
|
+
fontWeight: 600,
|
|
39
|
+
textTransform: "none",
|
|
40
|
+
borderRadius: 1.5,
|
|
41
|
+
boxShadow: (theme) =>
|
|
42
|
+
`0 8px 16px ${alpha(theme.palette.primary.main, 0.24)}`,
|
|
43
|
+
transition: "all 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
|
|
44
|
+
"&:hover": {
|
|
45
|
+
transform: "translateY(-2px)",
|
|
46
|
+
boxShadow: (theme) =>
|
|
47
|
+
`0 12px 24px ${alpha(theme.palette.primary.main, 0.32)}`,
|
|
48
|
+
},
|
|
49
|
+
"&:active": { transform: "translateY(0px)" },
|
|
50
|
+
};
|
|
9
51
|
|
|
10
52
|
export default function CognitoLogin() {
|
|
11
53
|
const [mode, setMode] = useState("login");
|
|
12
54
|
|
|
13
|
-
const [username, setUsername] = useState("");
|
|
14
55
|
const [email, setEmail] = useState("");
|
|
15
56
|
const [password, setPassword] = useState("");
|
|
16
57
|
const [code, setCode] = useState("");
|
|
58
|
+
const [showPassword, setShowPassword] = useState(false);
|
|
17
59
|
|
|
18
60
|
const navigate = useNavigate();
|
|
19
|
-
const { enqueueSnackbar } = useSnackbar();
|
|
20
61
|
|
|
21
62
|
const { appId } = config();
|
|
22
63
|
|
|
@@ -50,100 +91,261 @@ export default function CognitoLogin() {
|
|
|
50
91
|
navigate("/");
|
|
51
92
|
} catch (e) {
|
|
52
93
|
console.error("Login error:", e);
|
|
53
|
-
|
|
94
|
+
publish("GLOBAL_MESSAGE_POSTED", {
|
|
95
|
+
status: true,
|
|
96
|
+
message: e.message || "Login failed",
|
|
97
|
+
severity: "error",
|
|
98
|
+
});
|
|
54
99
|
}
|
|
55
100
|
};
|
|
56
101
|
|
|
57
102
|
const handleSignup = async () => {
|
|
58
103
|
try {
|
|
59
104
|
await signup(email, password, password);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
105
|
+
publish("GLOBAL_MESSAGE_POSTED", {
|
|
106
|
+
status: true,
|
|
107
|
+
message:
|
|
108
|
+
"Signup successful! Please check your email for the confirmation code.",
|
|
109
|
+
severity: "success",
|
|
110
|
+
});
|
|
64
111
|
setMode("confirm");
|
|
65
112
|
} catch (e) {
|
|
66
|
-
|
|
113
|
+
publish("GLOBAL_MESSAGE_POSTED", {
|
|
114
|
+
status: true,
|
|
115
|
+
message: e.message || "Signup failed",
|
|
116
|
+
severity: "error",
|
|
117
|
+
});
|
|
67
118
|
}
|
|
68
119
|
};
|
|
69
120
|
|
|
70
121
|
const handleConfirm = async () => {
|
|
71
122
|
try {
|
|
72
123
|
await confirmSignup(email, code);
|
|
73
|
-
|
|
74
|
-
|
|
124
|
+
publish("GLOBAL_MESSAGE_POSTED", {
|
|
125
|
+
status: true,
|
|
126
|
+
message: "Account confirmed! You can now log in.",
|
|
127
|
+
severity: "success",
|
|
75
128
|
});
|
|
76
129
|
setMode("login");
|
|
77
130
|
} catch (e) {
|
|
78
|
-
|
|
131
|
+
publish("GLOBAL_MESSAGE_POSTED", {
|
|
132
|
+
status: true,
|
|
133
|
+
message: e.message || "Confirmation failed",
|
|
134
|
+
severity: "error",
|
|
135
|
+
});
|
|
79
136
|
}
|
|
80
137
|
};
|
|
81
138
|
|
|
139
|
+
const titles = {
|
|
140
|
+
login: { heading: "Sign in", sub: "Welcome back! Enter your credentials." },
|
|
141
|
+
signup: {
|
|
142
|
+
heading: "Create account",
|
|
143
|
+
sub: "Sign up to get started for free.",
|
|
144
|
+
},
|
|
145
|
+
confirm: {
|
|
146
|
+
heading: "Verify your email",
|
|
147
|
+
sub: "Enter the confirmation code sent to your inbox.",
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const passwordAdornment = (
|
|
152
|
+
<InputAdornment position="end">
|
|
153
|
+
<IconButton
|
|
154
|
+
onClick={() => setShowPassword(!showPassword)}
|
|
155
|
+
edge="end"
|
|
156
|
+
size="small"
|
|
157
|
+
tabIndex={-1}
|
|
158
|
+
>
|
|
159
|
+
{showPassword ? <VisibilityOff /> : <Visibility />}
|
|
160
|
+
</IconButton>
|
|
161
|
+
</InputAdornment>
|
|
162
|
+
);
|
|
163
|
+
|
|
82
164
|
return (
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
165
|
+
<Box
|
|
166
|
+
sx={{
|
|
167
|
+
minHeight: "100vh",
|
|
168
|
+
display: "flex",
|
|
169
|
+
alignItems: "center",
|
|
170
|
+
justifyContent: "center",
|
|
171
|
+
px: 2,
|
|
172
|
+
background: (theme) =>
|
|
173
|
+
`linear-gradient(135deg, ${alpha(theme.palette.primary.lighter, 0.4)} 0%, ${alpha(theme.palette.background.default, 1)} 60%)`,
|
|
174
|
+
}}
|
|
175
|
+
>
|
|
176
|
+
<Card
|
|
177
|
+
sx={{
|
|
178
|
+
width: "100%",
|
|
179
|
+
maxWidth: 440,
|
|
180
|
+
py: { xs: 5, md: 7 },
|
|
181
|
+
px: { xs: 3, md: 5 },
|
|
182
|
+
borderRadius: 3,
|
|
183
|
+
boxShadow: (theme) =>
|
|
184
|
+
`0 0 2px ${alpha(theme.palette.grey[500], 0.16)}, 0 24px 48px -4px ${alpha(theme.palette.grey[500], 0.16)}`,
|
|
185
|
+
}}
|
|
186
|
+
>
|
|
187
|
+
<Box
|
|
188
|
+
sx={{
|
|
189
|
+
mb: 4,
|
|
190
|
+
display: "flex",
|
|
191
|
+
flexDirection: "column",
|
|
192
|
+
alignItems: "center",
|
|
193
|
+
textAlign: "center",
|
|
194
|
+
}}
|
|
195
|
+
>
|
|
196
|
+
<Box
|
|
197
|
+
sx={{
|
|
198
|
+
width: 56,
|
|
199
|
+
height: 56,
|
|
200
|
+
borderRadius: 2,
|
|
201
|
+
display: "flex",
|
|
202
|
+
alignItems: "center",
|
|
203
|
+
justifyContent: "center",
|
|
204
|
+
mb: 2.5,
|
|
205
|
+
bgcolor: (theme) => alpha(theme.palette.primary.main, 0.1),
|
|
206
|
+
color: "primary.main",
|
|
207
|
+
}}
|
|
208
|
+
>
|
|
209
|
+
{mode === "confirm" ? (
|
|
210
|
+
<MarkEmailReadOutlined sx={{ fontSize: 28 }} />
|
|
211
|
+
) : (
|
|
212
|
+
<LockOutlined sx={{ fontSize: 28 }} />
|
|
213
|
+
)}
|
|
214
|
+
</Box>
|
|
105
215
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
)}
|
|
216
|
+
<Typography variant="h4" fontWeight={700} gutterBottom>
|
|
217
|
+
{titles[mode].heading}
|
|
218
|
+
</Typography>
|
|
219
|
+
<Typography variant="body2" color="text.secondary">
|
|
220
|
+
{titles[mode].sub}
|
|
221
|
+
</Typography>
|
|
222
|
+
</Box>
|
|
114
223
|
|
|
115
|
-
{
|
|
224
|
+
<Stack spacing={2.5}>
|
|
116
225
|
<TextField
|
|
117
|
-
label="
|
|
118
|
-
value={
|
|
119
|
-
onChange={(e) =>
|
|
226
|
+
label="Email"
|
|
227
|
+
value={email}
|
|
228
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
229
|
+
fullWidth
|
|
230
|
+
InputProps={{
|
|
231
|
+
startAdornment: (
|
|
232
|
+
<InputAdornment position="start">
|
|
233
|
+
<EmailOutlined
|
|
234
|
+
sx={{ color: "text.secondary", fontSize: 22 }}
|
|
235
|
+
/>
|
|
236
|
+
</InputAdornment>
|
|
237
|
+
),
|
|
238
|
+
}}
|
|
239
|
+
sx={inputSx}
|
|
120
240
|
/>
|
|
121
|
-
)}
|
|
122
241
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
242
|
+
{mode === "signup" && (
|
|
243
|
+
<TextField
|
|
244
|
+
type={showPassword ? "text" : "password"}
|
|
245
|
+
label="Password"
|
|
246
|
+
value={password}
|
|
247
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
248
|
+
fullWidth
|
|
249
|
+
InputProps={{
|
|
250
|
+
startAdornment: (
|
|
251
|
+
<InputAdornment position="start">
|
|
252
|
+
<LockOutlined
|
|
253
|
+
sx={{ color: "text.secondary", fontSize: 22 }}
|
|
254
|
+
/>
|
|
255
|
+
</InputAdornment>
|
|
256
|
+
),
|
|
257
|
+
endAdornment: passwordAdornment,
|
|
258
|
+
}}
|
|
259
|
+
sx={inputSx}
|
|
260
|
+
/>
|
|
261
|
+
)}
|
|
262
|
+
|
|
263
|
+
{mode !== "confirm" && (
|
|
264
|
+
<TextField
|
|
265
|
+
type={showPassword ? "text" : "password"}
|
|
266
|
+
label="Password"
|
|
267
|
+
value={password}
|
|
268
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
269
|
+
fullWidth
|
|
270
|
+
InputProps={{
|
|
271
|
+
startAdornment: (
|
|
272
|
+
<InputAdornment position="start">
|
|
273
|
+
<LockOutlined
|
|
274
|
+
sx={{ color: "text.secondary", fontSize: 22 }}
|
|
275
|
+
/>
|
|
276
|
+
</InputAdornment>
|
|
277
|
+
),
|
|
278
|
+
endAdornment: passwordAdornment,
|
|
279
|
+
}}
|
|
280
|
+
sx={inputSx}
|
|
281
|
+
/>
|
|
282
|
+
)}
|
|
283
|
+
|
|
284
|
+
{mode === "confirm" && (
|
|
285
|
+
<TextField
|
|
286
|
+
label="Confirmation Code"
|
|
287
|
+
value={code}
|
|
288
|
+
onChange={(e) => setCode(e.target.value)}
|
|
289
|
+
fullWidth
|
|
290
|
+
sx={inputSx}
|
|
291
|
+
/>
|
|
292
|
+
)}
|
|
293
|
+
|
|
294
|
+
{mode === "login" && (
|
|
295
|
+
<Stack spacing={1.5} pt={0.5}>
|
|
296
|
+
<Button
|
|
297
|
+
variant="contained"
|
|
298
|
+
onClick={handleLogin}
|
|
299
|
+
size="large"
|
|
300
|
+
fullWidth
|
|
301
|
+
sx={primaryButtonSx}
|
|
302
|
+
>
|
|
303
|
+
Sign in
|
|
304
|
+
</Button>
|
|
305
|
+
<Button
|
|
306
|
+
onClick={() => setMode("signup")}
|
|
307
|
+
fullWidth
|
|
308
|
+
sx={{ textTransform: "none", fontWeight: 500 }}
|
|
309
|
+
>
|
|
310
|
+
Create an account
|
|
311
|
+
</Button>
|
|
312
|
+
</Stack>
|
|
313
|
+
)}
|
|
314
|
+
|
|
315
|
+
{mode === "signup" && (
|
|
316
|
+
<Stack spacing={1.5} pt={0.5}>
|
|
317
|
+
<Button
|
|
318
|
+
variant="contained"
|
|
319
|
+
onClick={handleSignup}
|
|
320
|
+
size="large"
|
|
321
|
+
fullWidth
|
|
322
|
+
sx={primaryButtonSx}
|
|
323
|
+
>
|
|
324
|
+
Sign Up
|
|
325
|
+
</Button>
|
|
326
|
+
<Button
|
|
327
|
+
onClick={() => setMode("login")}
|
|
328
|
+
fullWidth
|
|
329
|
+
sx={{ textTransform: "none", fontWeight: 500 }}
|
|
330
|
+
>
|
|
331
|
+
Back to login
|
|
332
|
+
</Button>
|
|
333
|
+
</Stack>
|
|
334
|
+
)}
|
|
335
|
+
|
|
336
|
+
{mode === "confirm" && (
|
|
337
|
+
<Button
|
|
338
|
+
variant="contained"
|
|
339
|
+
onClick={handleConfirm}
|
|
340
|
+
size="large"
|
|
341
|
+
fullWidth
|
|
342
|
+
sx={{ ...primaryButtonSx, mt: 0.5 }}
|
|
343
|
+
>
|
|
344
|
+
Confirm
|
|
136
345
|
</Button>
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
{mode === "confirm" && (
|
|
142
|
-
<Button variant="contained" onClick={handleConfirm}>
|
|
143
|
-
Confirm
|
|
144
|
-
</Button>
|
|
145
|
-
)}
|
|
146
|
-
</Stack>
|
|
147
|
-
</>
|
|
346
|
+
)}
|
|
347
|
+
</Stack>
|
|
348
|
+
</Card>
|
|
349
|
+
</Box>
|
|
148
350
|
);
|
|
149
351
|
}
|