@nocios/crudify-ui 1.0.70 → 1.0.71
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/README.md +375 -0
- package/dist/index.d.mts +144 -16
- package/dist/index.d.ts +144 -16
- package/dist/index.js +874 -591
- package/dist/index.mjs +815 -539
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -3,8 +3,7 @@ import { default as default2 } from "@nocios/crudify-browser";
|
|
|
3
3
|
export * from "@nocios/crudify-browser";
|
|
4
4
|
|
|
5
5
|
// src/components/CrudifyLogin/index.tsx
|
|
6
|
-
import
|
|
7
|
-
import { Box as Box5, Typography as Typography5 } from "@mui/material";
|
|
6
|
+
import { Box as Box6, Typography as Typography6 } from "@mui/material";
|
|
8
7
|
|
|
9
8
|
// src/components/CrudifyLogin/context/I18nProvider.tsx
|
|
10
9
|
import { createContext, useContext, useMemo } from "react";
|
|
@@ -94,8 +93,290 @@ var useTranslation = () => {
|
|
|
94
93
|
return context;
|
|
95
94
|
};
|
|
96
95
|
|
|
96
|
+
// src/components/CrudifyLogin/context/CrudifyProvider.tsx
|
|
97
|
+
import { createContext as createContext2, useContext as useContext2, useEffect as useEffect2, useState as useState2 } from "react";
|
|
98
|
+
import crudify from "@nocios/crudify-browser";
|
|
99
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
100
|
+
var CrudifyContext = createContext2(void 0);
|
|
101
|
+
var CrudifyProvider = ({ config, children }) => {
|
|
102
|
+
const [isLoading, setIsLoading] = useState2(true);
|
|
103
|
+
const [error, setError] = useState2(null);
|
|
104
|
+
const [isInitialized, setIsInitialized] = useState2(false);
|
|
105
|
+
const [initializationKey, setInitializationKey] = useState2("");
|
|
106
|
+
useEffect2(() => {
|
|
107
|
+
if (!config.publicApiKey) {
|
|
108
|
+
setError("No publicApiKey provided");
|
|
109
|
+
setIsLoading(false);
|
|
110
|
+
setIsInitialized(false);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const currentKey = `${config.publicApiKey}-${config.env}`;
|
|
114
|
+
if (currentKey === initializationKey && isInitialized) {
|
|
115
|
+
setIsLoading(false);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const initializeCrudify = async () => {
|
|
119
|
+
setIsLoading(true);
|
|
120
|
+
setError(null);
|
|
121
|
+
setIsInitialized(false);
|
|
122
|
+
try {
|
|
123
|
+
crudify.config(config.env || "prod");
|
|
124
|
+
await crudify.init(config.publicApiKey, "none");
|
|
125
|
+
if (typeof crudify.transaction === "function" && typeof crudify.login === "function") {
|
|
126
|
+
setIsInitialized(true);
|
|
127
|
+
setInitializationKey(currentKey);
|
|
128
|
+
} else {
|
|
129
|
+
throw new Error("Crudify methods not properly initialized");
|
|
130
|
+
}
|
|
131
|
+
} catch (err) {
|
|
132
|
+
const errorMessage = err instanceof Error ? err.message : "Failed to initialize Crudify";
|
|
133
|
+
setError(errorMessage);
|
|
134
|
+
setIsInitialized(false);
|
|
135
|
+
} finally {
|
|
136
|
+
setIsLoading(false);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
initializeCrudify();
|
|
140
|
+
}, [config.publicApiKey, config.env, initializationKey, isInitialized]);
|
|
141
|
+
const value = {
|
|
142
|
+
crudify: isInitialized ? crudify : null,
|
|
143
|
+
isLoading,
|
|
144
|
+
error,
|
|
145
|
+
isInitialized
|
|
146
|
+
};
|
|
147
|
+
return /* @__PURE__ */ jsx2(CrudifyContext.Provider, { value, children });
|
|
148
|
+
};
|
|
149
|
+
var useCrudify = () => {
|
|
150
|
+
const context = useContext2(CrudifyContext);
|
|
151
|
+
if (context === void 0) {
|
|
152
|
+
throw new Error("useCrudify must be used within a CrudifyProvider");
|
|
153
|
+
}
|
|
154
|
+
return context;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
// src/components/CrudifyLogin/context/LoginStateProvider.tsx
|
|
158
|
+
import { createContext as createContext3, useContext as useContext3, useReducer, useEffect as useEffect3 } from "react";
|
|
159
|
+
|
|
160
|
+
// src/components/CrudifyLogin/utils/cookies.ts
|
|
161
|
+
var getCookie = (name) => {
|
|
162
|
+
const match = document.cookie.match(new RegExp("(^|;)\\s*" + name + "=([^;]+)"));
|
|
163
|
+
return match ? match[2] : null;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// src/components/CrudifyLogin/context/LoginStateProvider.tsx
|
|
167
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
168
|
+
var initialState = {
|
|
169
|
+
currentScreen: "login",
|
|
170
|
+
searchParams: {},
|
|
171
|
+
formData: {
|
|
172
|
+
username: "",
|
|
173
|
+
password: "",
|
|
174
|
+
email: "",
|
|
175
|
+
code: "",
|
|
176
|
+
newPassword: "",
|
|
177
|
+
confirmPassword: ""
|
|
178
|
+
},
|
|
179
|
+
loading: false,
|
|
180
|
+
errors: {
|
|
181
|
+
global: []
|
|
182
|
+
},
|
|
183
|
+
emailSent: false,
|
|
184
|
+
codeAlreadyExists: false,
|
|
185
|
+
codeValidated: false,
|
|
186
|
+
fromCodeVerification: false,
|
|
187
|
+
config: {}
|
|
188
|
+
};
|
|
189
|
+
function loginStateReducer(state, action) {
|
|
190
|
+
switch (action.type) {
|
|
191
|
+
case "SET_SCREEN":
|
|
192
|
+
return {
|
|
193
|
+
...state,
|
|
194
|
+
currentScreen: action.payload.screen,
|
|
195
|
+
searchParams: action.payload.params || state.searchParams,
|
|
196
|
+
// Clear form errors when changing screens
|
|
197
|
+
errors: { global: [] }
|
|
198
|
+
};
|
|
199
|
+
case "SET_SEARCH_PARAMS":
|
|
200
|
+
return {
|
|
201
|
+
...state,
|
|
202
|
+
searchParams: action.payload
|
|
203
|
+
};
|
|
204
|
+
case "UPDATE_FORM_DATA":
|
|
205
|
+
return {
|
|
206
|
+
...state,
|
|
207
|
+
formData: {
|
|
208
|
+
...state.formData,
|
|
209
|
+
...action.payload
|
|
210
|
+
},
|
|
211
|
+
// Clear related errors when updating form data
|
|
212
|
+
errors: {
|
|
213
|
+
...state.errors,
|
|
214
|
+
...Object.keys(action.payload).reduce((acc, key) => ({
|
|
215
|
+
...acc,
|
|
216
|
+
[key]: void 0
|
|
217
|
+
}), {})
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
case "SET_LOADING":
|
|
221
|
+
return {
|
|
222
|
+
...state,
|
|
223
|
+
loading: action.payload
|
|
224
|
+
};
|
|
225
|
+
case "SET_ERRORS":
|
|
226
|
+
return {
|
|
227
|
+
...state,
|
|
228
|
+
errors: {
|
|
229
|
+
...state.errors,
|
|
230
|
+
...action.payload
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
case "CLEAR_ERRORS":
|
|
234
|
+
return {
|
|
235
|
+
...state,
|
|
236
|
+
errors: { global: [] }
|
|
237
|
+
};
|
|
238
|
+
case "SET_EMAIL_SENT":
|
|
239
|
+
return {
|
|
240
|
+
...state,
|
|
241
|
+
emailSent: action.payload
|
|
242
|
+
};
|
|
243
|
+
case "SET_CODE_ALREADY_EXISTS":
|
|
244
|
+
return {
|
|
245
|
+
...state,
|
|
246
|
+
codeAlreadyExists: action.payload
|
|
247
|
+
};
|
|
248
|
+
case "SET_CODE_VALIDATED":
|
|
249
|
+
return {
|
|
250
|
+
...state,
|
|
251
|
+
codeValidated: action.payload
|
|
252
|
+
};
|
|
253
|
+
case "SET_FROM_CODE_VERIFICATION":
|
|
254
|
+
return {
|
|
255
|
+
...state,
|
|
256
|
+
fromCodeVerification: action.payload
|
|
257
|
+
};
|
|
258
|
+
case "RESET_FORM":
|
|
259
|
+
return {
|
|
260
|
+
...state,
|
|
261
|
+
formData: initialState.formData,
|
|
262
|
+
errors: { global: [] },
|
|
263
|
+
loading: false,
|
|
264
|
+
emailSent: false,
|
|
265
|
+
codeAlreadyExists: false,
|
|
266
|
+
codeValidated: false,
|
|
267
|
+
fromCodeVerification: false
|
|
268
|
+
};
|
|
269
|
+
case "INIT_CONFIG":
|
|
270
|
+
return {
|
|
271
|
+
...state,
|
|
272
|
+
config: action.payload
|
|
273
|
+
};
|
|
274
|
+
default:
|
|
275
|
+
return state;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
var LoginStateContext = createContext3(void 0);
|
|
279
|
+
var LoginStateProvider = ({
|
|
280
|
+
children,
|
|
281
|
+
initialScreen = "login",
|
|
282
|
+
config: providedConfig,
|
|
283
|
+
autoReadFromCookies = true
|
|
284
|
+
}) => {
|
|
285
|
+
const [state, dispatch] = useReducer(loginStateReducer, {
|
|
286
|
+
...initialState,
|
|
287
|
+
currentScreen: initialScreen
|
|
288
|
+
});
|
|
289
|
+
useEffect3(() => {
|
|
290
|
+
const buildFinalConfig = () => {
|
|
291
|
+
let cookieConfig = {};
|
|
292
|
+
if (autoReadFromCookies) {
|
|
293
|
+
try {
|
|
294
|
+
const encodedLogo = getCookie("logo");
|
|
295
|
+
if (encodedLogo) {
|
|
296
|
+
const decodedLogo = decodeURIComponent(encodedLogo);
|
|
297
|
+
if (decodedLogo.startsWith("http")) {
|
|
298
|
+
cookieConfig.logo = decodedLogo;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
const colorsCookie = getCookie("colors");
|
|
302
|
+
if (colorsCookie) {
|
|
303
|
+
const decodedColorsString = decodeURIComponent(colorsCookie);
|
|
304
|
+
const parsedColors = JSON.parse(decodedColorsString);
|
|
305
|
+
cookieConfig.colors = { primaryColor: "#1066BA", ...parsedColors };
|
|
306
|
+
} else {
|
|
307
|
+
cookieConfig.colors = { primaryColor: "#1066BA" };
|
|
308
|
+
}
|
|
309
|
+
} catch (e) {
|
|
310
|
+
console.error("Error reading configuration from cookies:", e);
|
|
311
|
+
cookieConfig.colors = { primaryColor: "#1066BA" };
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return {
|
|
315
|
+
publicApiKey: providedConfig?.publicApiKey,
|
|
316
|
+
env: providedConfig?.env,
|
|
317
|
+
appName: providedConfig?.appName,
|
|
318
|
+
logo: providedConfig?.logo || cookieConfig.logo,
|
|
319
|
+
colors: { ...cookieConfig.colors, ...providedConfig?.colors },
|
|
320
|
+
loginActions: providedConfig?.loginActions
|
|
321
|
+
};
|
|
322
|
+
};
|
|
323
|
+
dispatch({ type: "INIT_CONFIG", payload: buildFinalConfig() });
|
|
324
|
+
}, [providedConfig, autoReadFromCookies]);
|
|
325
|
+
useEffect3(() => {
|
|
326
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
327
|
+
const paramsObject = {};
|
|
328
|
+
urlParams.forEach((value2, key) => {
|
|
329
|
+
paramsObject[key] = value2;
|
|
330
|
+
});
|
|
331
|
+
if (Object.keys(paramsObject).length > 0) {
|
|
332
|
+
dispatch({ type: "SET_SEARCH_PARAMS", payload: paramsObject });
|
|
333
|
+
}
|
|
334
|
+
if (initialScreen === "checkCode" && paramsObject.email) {
|
|
335
|
+
dispatch({
|
|
336
|
+
type: "UPDATE_FORM_DATA",
|
|
337
|
+
payload: { email: paramsObject.email, code: paramsObject.code || "" }
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
if (initialScreen === "resetPassword" && paramsObject.link) {
|
|
341
|
+
dispatch({ type: "SET_SEARCH_PARAMS", payload: paramsObject });
|
|
342
|
+
}
|
|
343
|
+
}, [initialScreen]);
|
|
344
|
+
const setScreen = (screen2, params) => {
|
|
345
|
+
dispatch({ type: "SET_SCREEN", payload: { screen: screen2, params } });
|
|
346
|
+
};
|
|
347
|
+
const updateFormData = (data) => {
|
|
348
|
+
dispatch({ type: "UPDATE_FORM_DATA", payload: data });
|
|
349
|
+
};
|
|
350
|
+
const setFieldError = (field, error) => {
|
|
351
|
+
dispatch({ type: "SET_ERRORS", payload: { [field]: error } });
|
|
352
|
+
};
|
|
353
|
+
const clearErrors = () => {
|
|
354
|
+
dispatch({ type: "CLEAR_ERRORS" });
|
|
355
|
+
};
|
|
356
|
+
const setLoading = (loading) => {
|
|
357
|
+
dispatch({ type: "SET_LOADING", payload: loading });
|
|
358
|
+
};
|
|
359
|
+
const value = {
|
|
360
|
+
state,
|
|
361
|
+
dispatch,
|
|
362
|
+
setScreen,
|
|
363
|
+
updateFormData,
|
|
364
|
+
setFieldError,
|
|
365
|
+
clearErrors,
|
|
366
|
+
setLoading
|
|
367
|
+
};
|
|
368
|
+
return /* @__PURE__ */ jsx3(LoginStateContext.Provider, { value, children });
|
|
369
|
+
};
|
|
370
|
+
var useLoginState = () => {
|
|
371
|
+
const context = useContext3(LoginStateContext);
|
|
372
|
+
if (context === void 0) {
|
|
373
|
+
throw new Error("useLoginState must be used within a LoginStateProvider");
|
|
374
|
+
}
|
|
375
|
+
return context;
|
|
376
|
+
};
|
|
377
|
+
|
|
97
378
|
// src/components/CrudifyLogin/Forms/LoginForm.tsx
|
|
98
|
-
import {
|
|
379
|
+
import { useEffect as useEffect4, useRef } from "react";
|
|
99
380
|
import { Typography, TextField, Button, Box, CircularProgress, Alert, Link } from "@mui/material";
|
|
100
381
|
|
|
101
382
|
// src/components/CrudifyLogin/utils/secureStorage.ts
|
|
@@ -207,45 +488,302 @@ var SecureStorage = class {
|
|
|
207
488
|
var secureSessionStorage = new SecureStorage("sessionStorage");
|
|
208
489
|
var secureLocalStorage = new SecureStorage("localStorage");
|
|
209
490
|
|
|
491
|
+
// src/utils/errorHandler.ts
|
|
492
|
+
var ERROR_CODES = {
|
|
493
|
+
// Authentication Errors
|
|
494
|
+
INVALID_CREDENTIALS: "INVALID_CREDENTIALS",
|
|
495
|
+
UNAUTHORIZED: "UNAUTHORIZED",
|
|
496
|
+
INVALID_API_KEY: "INVALID_API_KEY",
|
|
497
|
+
USER_NOT_FOUND: "USER_NOT_FOUND",
|
|
498
|
+
USER_NOT_ACTIVE: "USER_NOT_ACTIVE",
|
|
499
|
+
NO_PERMISSION: "NO_PERMISSION",
|
|
500
|
+
// Data Errors
|
|
501
|
+
ITEM_NOT_FOUND: "ITEM_NOT_FOUND",
|
|
502
|
+
NOT_FOUND: "NOT_FOUND",
|
|
503
|
+
IN_USE: "IN_USE",
|
|
504
|
+
// Validation Errors
|
|
505
|
+
FIELD_ERROR: "FIELD_ERROR",
|
|
506
|
+
BAD_REQUEST: "BAD_REQUEST",
|
|
507
|
+
INVALID_EMAIL: "INVALID_EMAIL",
|
|
508
|
+
INVALID_CODE: "INVALID_CODE",
|
|
509
|
+
// System Errors
|
|
510
|
+
INTERNAL_SERVER_ERROR: "INTERNAL_SERVER_ERROR",
|
|
511
|
+
DATABASE_CONNECTION_ERROR: "DATABASE_CONNECTION_ERROR",
|
|
512
|
+
INVALID_CONFIGURATION: "INVALID_CONFIGURATION",
|
|
513
|
+
UNKNOWN_OPERATION: "UNKNOWN_OPERATION",
|
|
514
|
+
// Rate Limiting
|
|
515
|
+
TOO_MANY_REQUESTS: "TOO_MANY_REQUESTS",
|
|
516
|
+
// Network Errors
|
|
517
|
+
NETWORK_ERROR: "NETWORK_ERROR",
|
|
518
|
+
TIMEOUT_ERROR: "TIMEOUT_ERROR"
|
|
519
|
+
};
|
|
520
|
+
var ERROR_SEVERITY_MAP = {
|
|
521
|
+
// Authentication - warning (user can fix)
|
|
522
|
+
[ERROR_CODES.INVALID_CREDENTIALS]: "warning",
|
|
523
|
+
[ERROR_CODES.UNAUTHORIZED]: "warning",
|
|
524
|
+
[ERROR_CODES.INVALID_API_KEY]: "error",
|
|
525
|
+
[ERROR_CODES.USER_NOT_FOUND]: "warning",
|
|
526
|
+
[ERROR_CODES.USER_NOT_ACTIVE]: "warning",
|
|
527
|
+
[ERROR_CODES.NO_PERMISSION]: "warning",
|
|
528
|
+
// Data - info (might be expected)
|
|
529
|
+
[ERROR_CODES.ITEM_NOT_FOUND]: "info",
|
|
530
|
+
[ERROR_CODES.NOT_FOUND]: "info",
|
|
531
|
+
[ERROR_CODES.IN_USE]: "warning",
|
|
532
|
+
// Validation - warning (user input issue)
|
|
533
|
+
[ERROR_CODES.FIELD_ERROR]: "warning",
|
|
534
|
+
[ERROR_CODES.BAD_REQUEST]: "warning",
|
|
535
|
+
[ERROR_CODES.INVALID_EMAIL]: "warning",
|
|
536
|
+
[ERROR_CODES.INVALID_CODE]: "warning",
|
|
537
|
+
// System - error (server issue)
|
|
538
|
+
[ERROR_CODES.INTERNAL_SERVER_ERROR]: "error",
|
|
539
|
+
[ERROR_CODES.DATABASE_CONNECTION_ERROR]: "error",
|
|
540
|
+
[ERROR_CODES.INVALID_CONFIGURATION]: "error",
|
|
541
|
+
[ERROR_CODES.UNKNOWN_OPERATION]: "error",
|
|
542
|
+
// Rate limiting - warning with higher duration
|
|
543
|
+
[ERROR_CODES.TOO_MANY_REQUESTS]: "warning",
|
|
544
|
+
// Network - error
|
|
545
|
+
[ERROR_CODES.NETWORK_ERROR]: "error",
|
|
546
|
+
[ERROR_CODES.TIMEOUT_ERROR]: "error"
|
|
547
|
+
};
|
|
548
|
+
function parseApiError(response) {
|
|
549
|
+
const errors = [];
|
|
550
|
+
try {
|
|
551
|
+
const apiResponse = response;
|
|
552
|
+
if (apiResponse.data && typeof apiResponse.data === "object") {
|
|
553
|
+
const responseData = apiResponse.data;
|
|
554
|
+
if (responseData.response) {
|
|
555
|
+
const { status, fieldsWarning } = responseData.response;
|
|
556
|
+
if (fieldsWarning && typeof fieldsWarning === "object") {
|
|
557
|
+
Object.entries(fieldsWarning).forEach(([field, messages]) => {
|
|
558
|
+
if (Array.isArray(messages) && messages.length > 0) {
|
|
559
|
+
errors.push({
|
|
560
|
+
code: ERROR_CODES.FIELD_ERROR,
|
|
561
|
+
message: messages[0],
|
|
562
|
+
severity: "warning",
|
|
563
|
+
field
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
if (status && typeof status === "string") {
|
|
569
|
+
const errorCode = status;
|
|
570
|
+
if (ERROR_SEVERITY_MAP[errorCode]) {
|
|
571
|
+
errors.push({
|
|
572
|
+
code: errorCode,
|
|
573
|
+
message: getErrorMessage(errorCode),
|
|
574
|
+
severity: ERROR_SEVERITY_MAP[errorCode]
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
if (apiResponse.errors) {
|
|
581
|
+
if (typeof apiResponse.errors === "string") {
|
|
582
|
+
errors.push({
|
|
583
|
+
code: ERROR_CODES.BAD_REQUEST,
|
|
584
|
+
message: apiResponse.errors,
|
|
585
|
+
severity: "warning"
|
|
586
|
+
});
|
|
587
|
+
} else if (typeof apiResponse.errors === "object") {
|
|
588
|
+
const errorObj = apiResponse.errors;
|
|
589
|
+
Object.entries(errorObj).forEach(([field, messages]) => {
|
|
590
|
+
if (Array.isArray(messages) && messages.length > 0) {
|
|
591
|
+
if (field === "_error") {
|
|
592
|
+
messages.forEach((msg) => {
|
|
593
|
+
const errorCode = typeof msg === "string" && isValidErrorCode(msg) ? msg : ERROR_CODES.BAD_REQUEST;
|
|
594
|
+
errors.push({
|
|
595
|
+
code: errorCode,
|
|
596
|
+
message: typeof msg === "string" ? msg : getErrorMessage(errorCode),
|
|
597
|
+
severity: ERROR_SEVERITY_MAP[errorCode] || "warning"
|
|
598
|
+
});
|
|
599
|
+
});
|
|
600
|
+
} else if (field === "_graphql") {
|
|
601
|
+
messages.forEach((msg) => {
|
|
602
|
+
if (typeof msg === "string") {
|
|
603
|
+
const errorCode = isValidErrorCode(msg) ? msg : ERROR_CODES.BAD_REQUEST;
|
|
604
|
+
errors.push({
|
|
605
|
+
code: errorCode,
|
|
606
|
+
message: getErrorMessage(errorCode),
|
|
607
|
+
severity: ERROR_SEVERITY_MAP[errorCode] || "warning"
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
});
|
|
611
|
+
} else {
|
|
612
|
+
errors.push({
|
|
613
|
+
code: ERROR_CODES.FIELD_ERROR,
|
|
614
|
+
message: typeof messages[0] === "string" ? messages[0] : "Validation error",
|
|
615
|
+
severity: "warning",
|
|
616
|
+
field
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
if (errors.length === 0 && apiResponse.success === false) {
|
|
624
|
+
errors.push({
|
|
625
|
+
code: ERROR_CODES.BAD_REQUEST,
|
|
626
|
+
message: "Request failed",
|
|
627
|
+
severity: "warning"
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
} catch (error) {
|
|
631
|
+
errors.push({
|
|
632
|
+
code: ERROR_CODES.INTERNAL_SERVER_ERROR,
|
|
633
|
+
message: "Failed to parse error response",
|
|
634
|
+
severity: "error",
|
|
635
|
+
details: { originalError: error }
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
return errors.length > 0 ? errors : [{
|
|
639
|
+
code: ERROR_CODES.INTERNAL_SERVER_ERROR,
|
|
640
|
+
message: "Unknown error occurred",
|
|
641
|
+
severity: "error"
|
|
642
|
+
}];
|
|
643
|
+
}
|
|
644
|
+
function parseTransactionError(response) {
|
|
645
|
+
try {
|
|
646
|
+
const transactionResponse = response;
|
|
647
|
+
if (transactionResponse.data && Array.isArray(transactionResponse.data)) {
|
|
648
|
+
const errors = [];
|
|
649
|
+
transactionResponse.data.forEach((item, index) => {
|
|
650
|
+
if (item.response?.status === "TOO_MANY_REQUESTS") {
|
|
651
|
+
errors.push({
|
|
652
|
+
code: ERROR_CODES.TOO_MANY_REQUESTS,
|
|
653
|
+
message: getErrorMessage(ERROR_CODES.TOO_MANY_REQUESTS),
|
|
654
|
+
severity: "warning",
|
|
655
|
+
details: { transactionIndex: index }
|
|
656
|
+
});
|
|
657
|
+
} else if (!item.response || item.response.status !== "OK") {
|
|
658
|
+
errors.push({
|
|
659
|
+
code: ERROR_CODES.BAD_REQUEST,
|
|
660
|
+
message: "Transaction failed",
|
|
661
|
+
severity: "warning",
|
|
662
|
+
details: { transactionIndex: index, response: item.response }
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
});
|
|
666
|
+
return errors;
|
|
667
|
+
}
|
|
668
|
+
return parseApiError(response);
|
|
669
|
+
} catch (error) {
|
|
670
|
+
return [{
|
|
671
|
+
code: ERROR_CODES.INTERNAL_SERVER_ERROR,
|
|
672
|
+
message: "Failed to parse transaction error",
|
|
673
|
+
severity: "error",
|
|
674
|
+
details: { originalError: error }
|
|
675
|
+
}];
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
function isValidErrorCode(code) {
|
|
679
|
+
return Object.values(ERROR_CODES).includes(code);
|
|
680
|
+
}
|
|
681
|
+
function getErrorMessage(code) {
|
|
682
|
+
const messages = {
|
|
683
|
+
[ERROR_CODES.INVALID_CREDENTIALS]: "Invalid email or password",
|
|
684
|
+
[ERROR_CODES.UNAUTHORIZED]: "You are not authorized to perform this action",
|
|
685
|
+
[ERROR_CODES.INVALID_API_KEY]: "Invalid API key",
|
|
686
|
+
[ERROR_CODES.USER_NOT_FOUND]: "User not found",
|
|
687
|
+
[ERROR_CODES.USER_NOT_ACTIVE]: "User account is not active",
|
|
688
|
+
[ERROR_CODES.NO_PERMISSION]: "You do not have permission to perform this action",
|
|
689
|
+
[ERROR_CODES.ITEM_NOT_FOUND]: "Item not found",
|
|
690
|
+
[ERROR_CODES.NOT_FOUND]: "Resource not found",
|
|
691
|
+
[ERROR_CODES.IN_USE]: "Resource is currently in use",
|
|
692
|
+
[ERROR_CODES.FIELD_ERROR]: "Validation error",
|
|
693
|
+
[ERROR_CODES.BAD_REQUEST]: "Invalid request",
|
|
694
|
+
[ERROR_CODES.INVALID_EMAIL]: "Please enter a valid email address",
|
|
695
|
+
[ERROR_CODES.INVALID_CODE]: "Invalid or expired code",
|
|
696
|
+
[ERROR_CODES.INTERNAL_SERVER_ERROR]: "Internal server error",
|
|
697
|
+
[ERROR_CODES.DATABASE_CONNECTION_ERROR]: "Database connection error",
|
|
698
|
+
[ERROR_CODES.INVALID_CONFIGURATION]: "Invalid configuration",
|
|
699
|
+
[ERROR_CODES.UNKNOWN_OPERATION]: "Unknown operation",
|
|
700
|
+
[ERROR_CODES.TOO_MANY_REQUESTS]: "Too many requests. Please try again later.",
|
|
701
|
+
[ERROR_CODES.NETWORK_ERROR]: "Network error. Please check your connection.",
|
|
702
|
+
[ERROR_CODES.TIMEOUT_ERROR]: "Request timed out. Please try again."
|
|
703
|
+
};
|
|
704
|
+
return messages[code] || "An unknown error occurred";
|
|
705
|
+
}
|
|
706
|
+
function parseJavaScriptError(error) {
|
|
707
|
+
if (error instanceof Error) {
|
|
708
|
+
if (error.name === "AbortError") {
|
|
709
|
+
return {
|
|
710
|
+
code: ERROR_CODES.TIMEOUT_ERROR,
|
|
711
|
+
message: "Request was cancelled",
|
|
712
|
+
severity: "info"
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
if (error.message.includes("NetworkError") || error.message.includes("Failed to fetch")) {
|
|
716
|
+
return {
|
|
717
|
+
code: ERROR_CODES.NETWORK_ERROR,
|
|
718
|
+
message: getErrorMessage(ERROR_CODES.NETWORK_ERROR),
|
|
719
|
+
severity: "error"
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
return {
|
|
723
|
+
code: ERROR_CODES.INTERNAL_SERVER_ERROR,
|
|
724
|
+
message: error.message || "An unexpected error occurred",
|
|
725
|
+
severity: "error",
|
|
726
|
+
details: { originalError: error }
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
return {
|
|
730
|
+
code: ERROR_CODES.INTERNAL_SERVER_ERROR,
|
|
731
|
+
message: "An unknown error occurred",
|
|
732
|
+
severity: "error",
|
|
733
|
+
details: { originalError: error }
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
function handleCrudifyError(error) {
|
|
737
|
+
if (error instanceof Error) {
|
|
738
|
+
return [parseJavaScriptError(error)];
|
|
739
|
+
}
|
|
740
|
+
if (typeof error === "object" && error !== null) {
|
|
741
|
+
const response = error;
|
|
742
|
+
if (response.data && Array.isArray(response.data)) {
|
|
743
|
+
return parseTransactionError(error);
|
|
744
|
+
}
|
|
745
|
+
return parseApiError(error);
|
|
746
|
+
}
|
|
747
|
+
return [{
|
|
748
|
+
code: ERROR_CODES.INTERNAL_SERVER_ERROR,
|
|
749
|
+
message: "An unknown error occurred",
|
|
750
|
+
severity: "error",
|
|
751
|
+
details: { originalError: error }
|
|
752
|
+
}];
|
|
753
|
+
}
|
|
754
|
+
|
|
210
755
|
// src/components/CrudifyLogin/Forms/LoginForm.tsx
|
|
211
|
-
import { Fragment, jsx as
|
|
212
|
-
var LoginForm = ({
|
|
213
|
-
const
|
|
214
|
-
const
|
|
215
|
-
const [loading, setLoading] = useState2(false);
|
|
216
|
-
const [errors, setErrors] = useState2([]);
|
|
217
|
-
const [helperTextEmail, setHelperTextEmail] = useState2(null);
|
|
218
|
-
const [helperTextPassword, setHelperTextPassword] = useState2(null);
|
|
756
|
+
import { Fragment, jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
757
|
+
var LoginForm = ({ onScreenChange, onExternalNavigate, onLoginSuccess, onError, redirectUrl = "/" }) => {
|
|
758
|
+
const { crudify: crudify3 } = useCrudify();
|
|
759
|
+
const { state, updateFormData, setFieldError, clearErrors, setLoading } = useLoginState();
|
|
219
760
|
const { t } = useTranslation();
|
|
220
761
|
const usernameInputRef = useRef(null);
|
|
221
762
|
const getRedirectUrl = () => {
|
|
222
|
-
if (searchParams) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
if (decodedPath.startsWith("/") && !decodedPath.startsWith("//")) {
|
|
228
|
-
return decodedPath;
|
|
229
|
-
}
|
|
230
|
-
} catch (error) {
|
|
763
|
+
if (state.searchParams.redirect) {
|
|
764
|
+
try {
|
|
765
|
+
const decodedPath = decodeURIComponent(state.searchParams.redirect);
|
|
766
|
+
if (decodedPath.startsWith("/") && !decodedPath.startsWith("//")) {
|
|
767
|
+
return decodedPath;
|
|
231
768
|
}
|
|
769
|
+
} catch (error) {
|
|
232
770
|
}
|
|
233
771
|
}
|
|
234
772
|
return redirectUrl || "/";
|
|
235
773
|
};
|
|
236
|
-
|
|
774
|
+
useEffect4(() => {
|
|
237
775
|
const timer = setTimeout(() => {
|
|
238
776
|
if (usernameInputRef.current) usernameInputRef.current.focus();
|
|
239
777
|
}, 100);
|
|
240
778
|
return () => clearTimeout(timer);
|
|
241
779
|
}, []);
|
|
242
|
-
const
|
|
780
|
+
const translateError = (parsedError) => {
|
|
243
781
|
const possibleKeys = [
|
|
244
|
-
`errors.auth.${
|
|
245
|
-
`errors.data.${
|
|
246
|
-
`errors.system.${
|
|
247
|
-
`errors.${
|
|
248
|
-
`login.${
|
|
782
|
+
`errors.auth.${parsedError.code}`,
|
|
783
|
+
`errors.data.${parsedError.code}`,
|
|
784
|
+
`errors.system.${parsedError.code}`,
|
|
785
|
+
`errors.${parsedError.code}`,
|
|
786
|
+
`login.${parsedError.code.toLowerCase()}`
|
|
249
787
|
];
|
|
250
788
|
for (const key of possibleKeys) {
|
|
251
789
|
const translated = t(key);
|
|
@@ -253,27 +791,25 @@ var LoginForm = ({ config, onScreenChange, onExternalNavigate, onLoginSuccess, o
|
|
|
253
791
|
return translated;
|
|
254
792
|
}
|
|
255
793
|
}
|
|
256
|
-
return t("error.unknown");
|
|
794
|
+
return parsedError.message || t("error.unknown");
|
|
257
795
|
};
|
|
258
796
|
const handleLogin = async () => {
|
|
259
|
-
if (loading) return;
|
|
260
|
-
if (!username.trim()) {
|
|
261
|
-
|
|
797
|
+
if (state.loading) return;
|
|
798
|
+
if (!state.formData.username.trim()) {
|
|
799
|
+
setFieldError("username", t("login.usernameRequired"));
|
|
262
800
|
return;
|
|
263
801
|
}
|
|
264
|
-
if (!password.trim()) {
|
|
265
|
-
|
|
802
|
+
if (!state.formData.password.trim()) {
|
|
803
|
+
setFieldError("password", t("login.passwordRequired"));
|
|
266
804
|
return;
|
|
267
805
|
}
|
|
268
|
-
|
|
269
|
-
setHelperTextEmail(null);
|
|
270
|
-
setHelperTextPassword(null);
|
|
806
|
+
clearErrors();
|
|
271
807
|
setLoading(true);
|
|
272
808
|
try {
|
|
273
809
|
if (!crudify3) {
|
|
274
810
|
throw new Error("Crudify not initialized");
|
|
275
811
|
}
|
|
276
|
-
const response = await crudify3.login(username, password);
|
|
812
|
+
const response = await crudify3.login(state.formData.username, state.formData.password);
|
|
277
813
|
setLoading(false);
|
|
278
814
|
if (response.success) {
|
|
279
815
|
secureSessionStorage.setToken(response.data.token);
|
|
@@ -288,62 +824,31 @@ var LoginForm = ({ config, onScreenChange, onExternalNavigate, onLoginSuccess, o
|
|
|
288
824
|
}
|
|
289
825
|
} catch (error) {
|
|
290
826
|
setLoading(false);
|
|
291
|
-
|
|
292
|
-
|
|
827
|
+
const parsedErrors = handleCrudifyError(error);
|
|
828
|
+
const translatedErrors = parsedErrors.map(translateError);
|
|
829
|
+
setFieldError("global", translatedErrors);
|
|
293
830
|
if (onError) {
|
|
294
|
-
onError(
|
|
831
|
+
onError(translatedErrors.join(", "));
|
|
295
832
|
}
|
|
296
833
|
}
|
|
297
834
|
};
|
|
298
835
|
const handleLoginError = (response) => {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
if (
|
|
302
|
-
|
|
303
|
-
if (fieldsWarning.password) setHelperTextPassword(fieldsWarning.password[0]);
|
|
304
|
-
} else if (status === "INVALID_CREDENTIALS") {
|
|
305
|
-
const translatedError = getSafeErrorTranslation(status);
|
|
306
|
-
setErrors([translatedError]);
|
|
307
|
-
} else if (status === "TOO_MANY_REQUESTS") {
|
|
308
|
-
const translatedError = getSafeErrorTranslation(status);
|
|
309
|
-
setErrors([translatedError]);
|
|
310
|
-
} else if (status) {
|
|
311
|
-
setErrors([getSafeErrorTranslation(status)]);
|
|
836
|
+
const parsedErrors = handleCrudifyError(response);
|
|
837
|
+
parsedErrors.forEach((error) => {
|
|
838
|
+
if (error.field) {
|
|
839
|
+
setFieldError(error.field, translateError(error));
|
|
312
840
|
} else {
|
|
313
|
-
|
|
841
|
+
const currentGlobalErrors = state.errors.global || [];
|
|
842
|
+
setFieldError("global", [...currentGlobalErrors, translateError(error)]);
|
|
314
843
|
}
|
|
315
|
-
}
|
|
316
|
-
const errors2 = response.errors;
|
|
317
|
-
if (typeof errors2 === "string") {
|
|
318
|
-
setErrors([errors2]);
|
|
319
|
-
} else if (typeof errors2 === "object") {
|
|
320
|
-
const hasUsernameError = errors2.username && errors2.username.length > 0;
|
|
321
|
-
const hasPasswordError = errors2.password && errors2.password.length > 0;
|
|
322
|
-
if (hasUsernameError || hasPasswordError) {
|
|
323
|
-
if (hasUsernameError) setHelperTextEmail(errors2.username[0]);
|
|
324
|
-
if (hasPasswordError) setHelperTextPassword(errors2.password[0]);
|
|
325
|
-
} else if (errors2._error && errors2._error.length > 0) {
|
|
326
|
-
const errorMessage = errors2._error[0];
|
|
327
|
-
if (typeof errorMessage === "string" && errorMessage.match(/^[A-Z_]+$/)) {
|
|
328
|
-
const translatedError = getSafeErrorTranslation(errorMessage);
|
|
329
|
-
setErrors([translatedError]);
|
|
330
|
-
} else setErrors([errorMessage]);
|
|
331
|
-
} else if (errors2._graphql && errors2._graphql[0] === "INVALID_CREDENTIALS") {
|
|
332
|
-
setErrors([getSafeErrorTranslation("INVALID_CREDENTIALS")]);
|
|
333
|
-
} else {
|
|
334
|
-
setErrors([t("error.unknown")]);
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
} else {
|
|
338
|
-
setErrors([t("error.unknown")]);
|
|
339
|
-
}
|
|
844
|
+
});
|
|
340
845
|
};
|
|
341
846
|
const handleSubmit = (e) => {
|
|
342
847
|
e.preventDefault();
|
|
343
848
|
handleLogin();
|
|
344
849
|
};
|
|
345
850
|
const handleKeyDown = (e) => {
|
|
346
|
-
if (e.key === "Enter" && !loading) {
|
|
851
|
+
if (e.key === "Enter" && !state.loading) {
|
|
347
852
|
e.preventDefault();
|
|
348
853
|
handleLogin();
|
|
349
854
|
}
|
|
@@ -359,7 +864,7 @@ var LoginForm = ({ config, onScreenChange, onExternalNavigate, onLoginSuccess, o
|
|
|
359
864
|
sx: { width: "100%", display: "flex", flexDirection: "column", gap: 2 },
|
|
360
865
|
children: [
|
|
361
866
|
/* @__PURE__ */ jsxs(Box, { sx: { mb: 1 }, children: [
|
|
362
|
-
/* @__PURE__ */
|
|
867
|
+
/* @__PURE__ */ jsx4(
|
|
363
868
|
Typography,
|
|
364
869
|
{
|
|
365
870
|
variant: "body2",
|
|
@@ -369,18 +874,18 @@ var LoginForm = ({ config, onScreenChange, onExternalNavigate, onLoginSuccess, o
|
|
|
369
874
|
children: t("login.usernameOrEmailLabel")
|
|
370
875
|
}
|
|
371
876
|
),
|
|
372
|
-
/* @__PURE__ */
|
|
877
|
+
/* @__PURE__ */ jsx4(
|
|
373
878
|
TextField,
|
|
374
879
|
{
|
|
375
880
|
fullWidth: true,
|
|
376
881
|
id: "email",
|
|
377
882
|
name: "email",
|
|
378
883
|
type: "email",
|
|
379
|
-
value: username,
|
|
380
|
-
disabled: loading,
|
|
381
|
-
onChange: (e) =>
|
|
382
|
-
error: !!
|
|
383
|
-
helperText:
|
|
884
|
+
value: state.formData.username,
|
|
885
|
+
disabled: state.loading,
|
|
886
|
+
onChange: (e) => updateFormData({ username: e.target.value }),
|
|
887
|
+
error: !!state.errors.username,
|
|
888
|
+
helperText: state.errors.username,
|
|
384
889
|
autoComplete: "email",
|
|
385
890
|
placeholder: t("login.usernameOrEmailPlaceholder"),
|
|
386
891
|
inputRef: usernameInputRef,
|
|
@@ -389,7 +894,7 @@ var LoginForm = ({ config, onScreenChange, onExternalNavigate, onLoginSuccess, o
|
|
|
389
894
|
)
|
|
390
895
|
] }),
|
|
391
896
|
/* @__PURE__ */ jsxs(Box, { sx: { mb: 1 }, children: [
|
|
392
|
-
/* @__PURE__ */
|
|
897
|
+
/* @__PURE__ */ jsx4(
|
|
393
898
|
Typography,
|
|
394
899
|
{
|
|
395
900
|
variant: "body2",
|
|
@@ -399,51 +904,50 @@ var LoginForm = ({ config, onScreenChange, onExternalNavigate, onLoginSuccess, o
|
|
|
399
904
|
children: t("login.passwordLabel")
|
|
400
905
|
}
|
|
401
906
|
),
|
|
402
|
-
/* @__PURE__ */
|
|
907
|
+
/* @__PURE__ */ jsx4(
|
|
403
908
|
TextField,
|
|
404
909
|
{
|
|
405
910
|
fullWidth: true,
|
|
406
911
|
id: "password",
|
|
407
912
|
name: "password",
|
|
408
913
|
type: "password",
|
|
409
|
-
value: password,
|
|
410
|
-
disabled: loading,
|
|
411
|
-
onChange: (e) =>
|
|
412
|
-
error: !!
|
|
413
|
-
helperText:
|
|
914
|
+
value: state.formData.password,
|
|
915
|
+
disabled: state.loading,
|
|
916
|
+
onChange: (e) => updateFormData({ password: e.target.value }),
|
|
917
|
+
error: !!state.errors.password,
|
|
918
|
+
helperText: state.errors.password,
|
|
414
919
|
autoComplete: "current-password",
|
|
415
920
|
placeholder: t("login.passwordPlaceholder"),
|
|
416
921
|
required: true
|
|
417
922
|
}
|
|
418
923
|
)
|
|
419
924
|
] }),
|
|
420
|
-
config.loginActions?.includes("forgotPassword") && /* @__PURE__ */
|
|
925
|
+
state.config.loginActions?.includes("forgotPassword") && /* @__PURE__ */ jsx4(Box, { sx: { display: "flex", justifyContent: "flex-end", alignItems: "center" }, children: /* @__PURE__ */ jsx4(
|
|
421
926
|
Link,
|
|
422
927
|
{
|
|
423
928
|
sx: { cursor: "pointer" },
|
|
424
929
|
onClick: () => {
|
|
425
|
-
|
|
426
|
-
onScreenChange?.("forgotPassword", params);
|
|
930
|
+
onScreenChange?.("forgotPassword", state.searchParams);
|
|
427
931
|
},
|
|
428
932
|
variant: "body2",
|
|
429
933
|
color: "secondary",
|
|
430
934
|
children: t("login.forgotPasswordLink")
|
|
431
935
|
}
|
|
432
936
|
) }),
|
|
433
|
-
/* @__PURE__ */
|
|
937
|
+
/* @__PURE__ */ jsx4(Button, { disabled: state.loading, type: "submit", fullWidth: true, variant: "contained", color: "primary", sx: { mt: 1, mb: 2 }, children: state.loading ? /* @__PURE__ */ jsx4(CircularProgress, { size: 20 }) : t("login.loginButton") })
|
|
434
938
|
]
|
|
435
939
|
}
|
|
436
940
|
),
|
|
437
|
-
/* @__PURE__ */
|
|
438
|
-
config.loginActions?.includes("createUser") && /* @__PURE__ */ jsxs(Typography, { variant: "body2", align: "center", sx: { color: "text.secondary", mt: 3 }, children: [
|
|
941
|
+
/* @__PURE__ */ jsx4(Box, { children: state.errors.global && state.errors.global.length > 0 && state.errors.global.map((error, index) => /* @__PURE__ */ jsx4(Alert, { variant: "filled", sx: { mt: 2 }, severity: "error", children: /* @__PURE__ */ jsx4("div", { children: error }) }, index)) }),
|
|
942
|
+
state.config.loginActions?.includes("createUser") && /* @__PURE__ */ jsxs(Typography, { variant: "body2", align: "center", sx: { color: "text.secondary", mt: 3 }, children: [
|
|
439
943
|
t("login.noAccountPrompt"),
|
|
440
944
|
" ",
|
|
441
|
-
/* @__PURE__ */
|
|
945
|
+
/* @__PURE__ */ jsx4(
|
|
442
946
|
Link,
|
|
443
947
|
{
|
|
444
948
|
sx: { cursor: "pointer" },
|
|
445
949
|
onClick: () => {
|
|
446
|
-
const searchString = searchParams ? `?${searchParams.toString()}` : "";
|
|
950
|
+
const searchString = Object.keys(state.searchParams).length > 0 ? `?${new URLSearchParams(state.searchParams).toString()}` : "";
|
|
447
951
|
const signupUrl = `/public/users/create${searchString}`;
|
|
448
952
|
onExternalNavigate?.(signupUrl);
|
|
449
953
|
},
|
|
@@ -460,8 +964,9 @@ var LoginForm_default = LoginForm;
|
|
|
460
964
|
// src/components/CrudifyLogin/Forms/ForgotPasswordForm.tsx
|
|
461
965
|
import { useState as useState3 } from "react";
|
|
462
966
|
import { Typography as Typography2, TextField as TextField2, Button as Button2, Box as Box2, CircularProgress as CircularProgress2, Alert as Alert2, Link as Link2 } from "@mui/material";
|
|
463
|
-
import { Fragment as Fragment2, jsx as
|
|
464
|
-
var ForgotPasswordForm = ({ onScreenChange, onError
|
|
967
|
+
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
968
|
+
var ForgotPasswordForm = ({ onScreenChange, onError }) => {
|
|
969
|
+
const { crudify: crudify3 } = useCrudify();
|
|
465
970
|
const [email, setEmail] = useState3("");
|
|
466
971
|
const [loading, setLoading] = useState3(false);
|
|
467
972
|
const [errors, setErrors] = useState3([]);
|
|
@@ -469,6 +974,22 @@ var ForgotPasswordForm = ({ onScreenChange, onError, crudify: crudify3 }) => {
|
|
|
469
974
|
const [emailSent, setEmailSent] = useState3(false);
|
|
470
975
|
const [codeAlreadyExists, setCodeAlreadyExists] = useState3(false);
|
|
471
976
|
const { t } = useTranslation();
|
|
977
|
+
const translateError = (parsedError) => {
|
|
978
|
+
const possibleKeys = [
|
|
979
|
+
`errors.auth.${parsedError.code}`,
|
|
980
|
+
`errors.data.${parsedError.code}`,
|
|
981
|
+
`errors.system.${parsedError.code}`,
|
|
982
|
+
`errors.${parsedError.code}`,
|
|
983
|
+
`forgotPassword.${parsedError.code.toLowerCase()}`
|
|
984
|
+
];
|
|
985
|
+
for (const key of possibleKeys) {
|
|
986
|
+
const translated = t(key);
|
|
987
|
+
if (translated !== key) {
|
|
988
|
+
return translated;
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
return parsedError.message || t("error.unknown");
|
|
992
|
+
};
|
|
472
993
|
const validateEmail = (email2) => {
|
|
473
994
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
474
995
|
return emailRegex.test(email2);
|
|
@@ -496,32 +1017,16 @@ var ForgotPasswordForm = ({ onScreenChange, onError, crudify: crudify3 }) => {
|
|
|
496
1017
|
setEmailSent(true);
|
|
497
1018
|
}
|
|
498
1019
|
} else {
|
|
499
|
-
const
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
} else if (response.errors) {
|
|
503
|
-
if (response.errors._error) {
|
|
504
|
-
const errors2 = response.errors._error;
|
|
505
|
-
const translatedErrors = errors2.map((error) => {
|
|
506
|
-
if (error === "TOO_MANY_REQUESTS") {
|
|
507
|
-
return t("errors.auth.TOO_MANY_REQUESTS");
|
|
508
|
-
}
|
|
509
|
-
return error;
|
|
510
|
-
});
|
|
511
|
-
errorMessages.push(...translatedErrors);
|
|
512
|
-
} else {
|
|
513
|
-
errorMessages.push(t("error.unknown"));
|
|
514
|
-
}
|
|
515
|
-
} else {
|
|
516
|
-
errorMessages.push(t("error.unknown"));
|
|
517
|
-
}
|
|
518
|
-
setErrors(errorMessages);
|
|
1020
|
+
const parsedErrors = handleCrudifyError(response);
|
|
1021
|
+
const translatedErrors = parsedErrors.map(translateError);
|
|
1022
|
+
setErrors(translatedErrors);
|
|
519
1023
|
}
|
|
520
1024
|
} catch (error) {
|
|
521
|
-
|
|
522
|
-
|
|
1025
|
+
const parsedErrors = handleCrudifyError(error);
|
|
1026
|
+
const translatedErrors = parsedErrors.map(translateError);
|
|
1027
|
+
setErrors(translatedErrors);
|
|
523
1028
|
if (onError) {
|
|
524
|
-
onError(
|
|
1029
|
+
onError(translatedErrors.join(", "));
|
|
525
1030
|
}
|
|
526
1031
|
} finally {
|
|
527
1032
|
setLoading(false);
|
|
@@ -531,45 +1036,38 @@ var ForgotPasswordForm = ({ onScreenChange, onError, crudify: crudify3 }) => {
|
|
|
531
1036
|
onScreenChange?.("login");
|
|
532
1037
|
};
|
|
533
1038
|
const handleGoToCheckCode = () => {
|
|
534
|
-
console.log("\u{1F680} handleGoToCheckCode called:", { email, emailSent, codeAlreadyExists });
|
|
535
1039
|
if (emailSent || codeAlreadyExists) {
|
|
536
|
-
console.log("\u2705 Navigating from success state");
|
|
537
1040
|
onScreenChange?.("checkCode", { email });
|
|
538
1041
|
return;
|
|
539
1042
|
}
|
|
540
1043
|
if (!email) {
|
|
541
|
-
console.log("\u274C Email required");
|
|
542
1044
|
setHelperTextEmail(t("forgotPassword.emailRequired"));
|
|
543
1045
|
return;
|
|
544
1046
|
}
|
|
545
1047
|
if (!validateEmail(email)) {
|
|
546
|
-
console.log("\u274C Invalid email");
|
|
547
1048
|
setHelperTextEmail(t("forgotPassword.invalidEmail"));
|
|
548
1049
|
return;
|
|
549
1050
|
}
|
|
550
|
-
console.log("\u2705 Navigating with valid email");
|
|
551
1051
|
onScreenChange?.("checkCode", { email });
|
|
552
1052
|
};
|
|
553
1053
|
if (emailSent || codeAlreadyExists) {
|
|
554
|
-
|
|
555
|
-
return /* @__PURE__ */ jsx3(Fragment2, { children: /* @__PURE__ */ jsxs2(Box2, { sx: { width: "100%", display: "flex", flexDirection: "column", gap: 2, textAlign: "center" }, children: [
|
|
1054
|
+
return /* @__PURE__ */ jsx5(Fragment2, { children: /* @__PURE__ */ jsxs2(Box2, { sx: { width: "100%", display: "flex", flexDirection: "column", gap: 2, textAlign: "center" }, children: [
|
|
556
1055
|
/* @__PURE__ */ jsxs2(Box2, { sx: { mb: 2 }, children: [
|
|
557
|
-
/* @__PURE__ */
|
|
558
|
-
/* @__PURE__ */
|
|
1056
|
+
/* @__PURE__ */ jsx5(Typography2, { variant: "h5", component: "h1", sx: { mb: 1, fontWeight: 600 }, children: codeAlreadyExists ? t("forgotPassword.codeAlreadyExistsMessage") : t("forgotPassword.emailSentMessage") }),
|
|
1057
|
+
/* @__PURE__ */ jsx5(Typography2, { variant: "body2", sx: { color: codeAlreadyExists ? "success.main" : "grey.600" }, children: codeAlreadyExists ? t("forgotPassword.checkEmailInstructions") : t("forgotPassword.checkEmailInstructions") })
|
|
559
1058
|
] }),
|
|
560
|
-
/* @__PURE__ */
|
|
561
|
-
/* @__PURE__ */
|
|
1059
|
+
/* @__PURE__ */ jsx5(Button2, { type: "button", onClick: handleGoToCheckCode, fullWidth: true, variant: "contained", color: "primary", sx: { mt: 2, mb: 2 }, children: t("forgotPassword.enterCodeLink") }),
|
|
1060
|
+
/* @__PURE__ */ jsx5(Box2, { sx: { display: "flex", justifyContent: "center", alignItems: "center" }, children: /* @__PURE__ */ jsx5(Link2, { sx: { cursor: "pointer" }, onClick: handleBack, variant: "body2", color: "secondary", children: t("common.back") }) })
|
|
562
1061
|
] }) });
|
|
563
1062
|
}
|
|
564
|
-
console.log("\u{1F4DD} Rendering FORM state");
|
|
565
1063
|
return /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
566
1064
|
/* @__PURE__ */ jsxs2(Box2, { component: "form", noValidate: true, sx: { width: "100%", display: "flex", flexDirection: "column", gap: 2 }, children: [
|
|
567
1065
|
/* @__PURE__ */ jsxs2(Box2, { sx: { mb: 2 }, children: [
|
|
568
|
-
/* @__PURE__ */
|
|
569
|
-
/* @__PURE__ */
|
|
1066
|
+
/* @__PURE__ */ jsx5(Typography2, { variant: "h5", component: "h1", sx: { mb: 1, fontWeight: 600 }, children: t("forgotPassword.title") }),
|
|
1067
|
+
/* @__PURE__ */ jsx5(Typography2, { variant: "body2", sx: { color: "grey.600" }, children: t("forgotPassword.instructions") })
|
|
570
1068
|
] }),
|
|
571
1069
|
/* @__PURE__ */ jsxs2(Box2, { sx: { mb: 1 }, children: [
|
|
572
|
-
/* @__PURE__ */
|
|
1070
|
+
/* @__PURE__ */ jsx5(
|
|
573
1071
|
Typography2,
|
|
574
1072
|
{
|
|
575
1073
|
variant: "body2",
|
|
@@ -579,7 +1077,7 @@ var ForgotPasswordForm = ({ onScreenChange, onError, crudify: crudify3 }) => {
|
|
|
579
1077
|
children: t("forgotPassword.emailLabel")
|
|
580
1078
|
}
|
|
581
1079
|
),
|
|
582
|
-
/* @__PURE__ */
|
|
1080
|
+
/* @__PURE__ */ jsx5(
|
|
583
1081
|
TextField2,
|
|
584
1082
|
{
|
|
585
1083
|
fullWidth: true,
|
|
@@ -597,23 +1095,24 @@ var ForgotPasswordForm = ({ onScreenChange, onError, crudify: crudify3 }) => {
|
|
|
597
1095
|
}
|
|
598
1096
|
)
|
|
599
1097
|
] }),
|
|
600
|
-
/* @__PURE__ */
|
|
1098
|
+
/* @__PURE__ */ jsx5(Button2, { disabled: loading, type: "button", onClick: handleSubmit, fullWidth: true, variant: "contained", color: "primary", sx: { mt: 2, mb: 2 }, children: loading ? /* @__PURE__ */ jsx5(CircularProgress2, { size: 20 }) : t("forgotPassword.sendCodeButton") }),
|
|
601
1099
|
/* @__PURE__ */ jsxs2(Box2, { sx: { display: "flex", justifyContent: "center", alignItems: "center", gap: 2 }, children: [
|
|
602
|
-
/* @__PURE__ */
|
|
603
|
-
/* @__PURE__ */
|
|
604
|
-
/* @__PURE__ */
|
|
1100
|
+
/* @__PURE__ */ jsx5(Link2, { sx: { cursor: "pointer" }, onClick: handleBack, variant: "body2", color: "secondary", children: t("common.back") }),
|
|
1101
|
+
/* @__PURE__ */ jsx5(Typography2, { variant: "body2", sx: { color: "grey.400" }, children: "\u2022" }),
|
|
1102
|
+
/* @__PURE__ */ jsx5(Link2, { sx: { cursor: "pointer" }, onClick: handleGoToCheckCode, variant: "body2", color: "secondary", children: t("login.alreadyHaveCodeLink") })
|
|
605
1103
|
] })
|
|
606
1104
|
] }),
|
|
607
|
-
/* @__PURE__ */
|
|
1105
|
+
/* @__PURE__ */ jsx5(Box2, { children: errors.length > 0 && errors.map((error, index) => /* @__PURE__ */ jsx5(Alert2, { variant: "filled", sx: { mt: 2 }, severity: "error", children: error }, index)) })
|
|
608
1106
|
] });
|
|
609
1107
|
};
|
|
610
1108
|
var ForgotPasswordForm_default = ForgotPasswordForm;
|
|
611
1109
|
|
|
612
1110
|
// src/components/CrudifyLogin/Forms/ResetPasswordForm.tsx
|
|
613
|
-
import { useState as useState4, useEffect as
|
|
1111
|
+
import { useState as useState4, useEffect as useEffect5 } from "react";
|
|
614
1112
|
import { Typography as Typography3, TextField as TextField3, Button as Button3, Box as Box3, CircularProgress as CircularProgress3, Alert as Alert3, Link as Link3 } from "@mui/material";
|
|
615
|
-
import { Fragment as Fragment3, jsx as
|
|
616
|
-
var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
|
|
1113
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1114
|
+
var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess }) => {
|
|
1115
|
+
const { crudify: crudify3 } = useCrudify();
|
|
617
1116
|
const [newPassword, setNewPassword] = useState4("");
|
|
618
1117
|
const [confirmPassword, setConfirmPassword] = useState4("");
|
|
619
1118
|
const [loading, setLoading] = useState4(false);
|
|
@@ -628,12 +1127,26 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
|
|
|
628
1127
|
const [pendingValidation, setPendingValidation] = useState4(null);
|
|
629
1128
|
const [isValidating, setIsValidating] = useState4(false);
|
|
630
1129
|
const { t } = useTranslation();
|
|
631
|
-
|
|
1130
|
+
const translateError = (parsedError) => {
|
|
1131
|
+
const possibleKeys = [
|
|
1132
|
+
`errors.auth.${parsedError.code}`,
|
|
1133
|
+
`errors.data.${parsedError.code}`,
|
|
1134
|
+
`errors.system.${parsedError.code}`,
|
|
1135
|
+
`errors.${parsedError.code}`,
|
|
1136
|
+
`resetPassword.${parsedError.code.toLowerCase()}`
|
|
1137
|
+
];
|
|
1138
|
+
for (const key of possibleKeys) {
|
|
1139
|
+
const translated = t(key);
|
|
1140
|
+
if (translated !== key) {
|
|
1141
|
+
return translated;
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
return parsedError.message || t("error.unknown");
|
|
1145
|
+
};
|
|
1146
|
+
useEffect5(() => {
|
|
632
1147
|
if (!searchParams) {
|
|
633
|
-
console.log("\u{1F504} No searchParams yet, waiting...");
|
|
634
1148
|
return;
|
|
635
1149
|
}
|
|
636
|
-
console.log("\u{1F504} Processing searchParams:", searchParams.toString());
|
|
637
1150
|
if (searchParams) {
|
|
638
1151
|
const fromCodeVerificationParam = searchParams.get("fromCodeVerification");
|
|
639
1152
|
const emailParam = searchParams.get("email");
|
|
@@ -652,54 +1165,31 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
|
|
|
652
1165
|
const decodedLink = decodeURIComponent(linkParam);
|
|
653
1166
|
const [linkCode, linkEmail] = decodedLink.split("/");
|
|
654
1167
|
if (linkCode && linkEmail && linkCode.length === 6) {
|
|
655
|
-
console.log("\u{1F517} Reset link detected:", { linkCode, linkEmail });
|
|
656
1168
|
setCode(linkCode);
|
|
657
1169
|
setEmail(linkEmail);
|
|
658
1170
|
setFromCodeVerification(false);
|
|
659
|
-
console.log("\u23F3 Setting pending validation for reset link");
|
|
660
1171
|
setPendingValidation({ email: linkEmail, code: linkCode });
|
|
661
1172
|
return;
|
|
662
1173
|
}
|
|
663
1174
|
} catch (error) {
|
|
664
|
-
console.error("Failed to parse reset link:", error);
|
|
665
1175
|
}
|
|
666
1176
|
}
|
|
667
1177
|
if (emailParam && codeParam) {
|
|
668
1178
|
setEmail(emailParam);
|
|
669
1179
|
setCode(codeParam);
|
|
670
1180
|
setFromCodeVerification(false);
|
|
671
|
-
console.log("\u23F3 Setting pending validation for direct params");
|
|
672
1181
|
setPendingValidation({ email: emailParam, code: codeParam });
|
|
673
1182
|
return;
|
|
674
1183
|
}
|
|
675
1184
|
}
|
|
676
|
-
console.log("\u274C No valid reset parameters found");
|
|
677
1185
|
setErrors([t("resetPassword.invalidCode")]);
|
|
678
1186
|
setValidatingCode(false);
|
|
679
1187
|
setTimeout(() => onScreenChange?.("forgotPassword"), 3e3);
|
|
680
1188
|
}, [searchParams, crudify3, t, onScreenChange]);
|
|
681
|
-
|
|
682
|
-
console.log("\u{1F504} Pending validation useEffect triggered:", {
|
|
683
|
-
crudify: !!crudify3,
|
|
684
|
-
pendingValidation,
|
|
685
|
-
crudifyType: typeof crudify3,
|
|
686
|
-
crudifyKeys: crudify3 ? Object.keys(crudify3) : null
|
|
687
|
-
});
|
|
1189
|
+
useEffect5(() => {
|
|
688
1190
|
if (crudify3 && pendingValidation && !isValidating) {
|
|
689
|
-
console.log("\u{1F680} Crudify verified ready! Executing pending validation:", pendingValidation);
|
|
690
|
-
console.log("\u{1F50D} Crudify object details:", {
|
|
691
|
-
hasTransaction: typeof crudify3.transaction === "function",
|
|
692
|
-
hasLogin: typeof crudify3.login === "function",
|
|
693
|
-
crudifyInstance: crudify3
|
|
694
|
-
});
|
|
695
1191
|
setIsValidating(true);
|
|
696
1192
|
const validateCode = async (emailToValidate, codeToValidate) => {
|
|
697
|
-
console.log("\u{1F50D} Validating reset code:", { emailToValidate, codeToValidate });
|
|
698
|
-
console.log("\u{1F4CB} Pre-validation crudify check:", {
|
|
699
|
-
crudify: !!crudify3,
|
|
700
|
-
transaction: typeof crudify3?.transaction,
|
|
701
|
-
crudifyString: crudify3?.toString?.()
|
|
702
|
-
});
|
|
703
1193
|
try {
|
|
704
1194
|
const data = [
|
|
705
1195
|
{
|
|
@@ -707,61 +1197,26 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
|
|
|
707
1197
|
data: { email: emailToValidate, codePassword: codeToValidate }
|
|
708
1198
|
}
|
|
709
1199
|
];
|
|
710
|
-
console.log("\u{1F4E4} Sending validation request:", data);
|
|
711
|
-
console.log("\u{1F3AF} About to call crudify.transaction...");
|
|
712
1200
|
const response = await crudify3.transaction(data);
|
|
713
|
-
console.log("\u{1F4E5} Validation response:", response);
|
|
714
|
-
console.log("\u{1F4E5} Raw response type:", typeof response);
|
|
715
|
-
console.log("\u{1F4E5} Response keys:", Object.keys(response));
|
|
716
|
-
if (response.data) {
|
|
717
|
-
console.log("\u{1F4E5} Response.data type:", typeof response.data);
|
|
718
|
-
console.log("\u{1F4E5} Response.data content:", response.data);
|
|
719
|
-
}
|
|
720
1201
|
if (response.data && Array.isArray(response.data)) {
|
|
721
|
-
console.log("\u{1F50D} Checking array response data:", response.data);
|
|
722
1202
|
const validationResult = response.data[0];
|
|
723
1203
|
if (validationResult && validationResult.response && validationResult.response.status === "OK") {
|
|
724
|
-
console.log("\u2705 Code validation successful (from array data)");
|
|
725
1204
|
setCodeValidated(true);
|
|
726
1205
|
return;
|
|
727
1206
|
}
|
|
728
1207
|
}
|
|
729
1208
|
if (response.success) {
|
|
730
|
-
console.log("\u2705 Code validation successful");
|
|
731
1209
|
setCodeValidated(true);
|
|
732
1210
|
} else {
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
data: response.data,
|
|
737
|
-
errors: response.errors,
|
|
738
|
-
errorCode: response.errorCode,
|
|
739
|
-
fieldsWarning: response.fieldsWarning
|
|
740
|
-
});
|
|
741
|
-
if (response.data?.response?.status === "TOO_MANY_REQUESTS") {
|
|
742
|
-
setErrors([t("errors.auth.TOO_MANY_REQUESTS")]);
|
|
743
|
-
} else {
|
|
744
|
-
let errorMessage = t("resetPassword.invalidCode");
|
|
745
|
-
if (response.errors?._error) {
|
|
746
|
-
const error = response.errors._error[0];
|
|
747
|
-
if (error === "TOO_MANY_REQUESTS") {
|
|
748
|
-
errorMessage = t("errors.auth.TOO_MANY_REQUESTS");
|
|
749
|
-
} else {
|
|
750
|
-
const errorMsg = error?.toLowerCase() || "";
|
|
751
|
-
if (errorMsg.includes("expired")) {
|
|
752
|
-
errorMessage = t("resetPassword.codeExpiredOrInvalid");
|
|
753
|
-
} else if (errorMsg.includes("invalid")) {
|
|
754
|
-
errorMessage = t("resetPassword.invalidCode");
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
|
-
setErrors([errorMessage]);
|
|
759
|
-
}
|
|
1211
|
+
const parsedErrors = handleCrudifyError(response);
|
|
1212
|
+
const translatedErrors = parsedErrors.map(translateError);
|
|
1213
|
+
setErrors(translatedErrors);
|
|
760
1214
|
setTimeout(() => onScreenChange?.("forgotPassword"), 3e3);
|
|
761
1215
|
}
|
|
762
1216
|
} catch (error) {
|
|
763
|
-
|
|
764
|
-
|
|
1217
|
+
const parsedErrors = handleCrudifyError(error);
|
|
1218
|
+
const translatedErrors = parsedErrors.map(translateError);
|
|
1219
|
+
setErrors(translatedErrors);
|
|
765
1220
|
setTimeout(() => onScreenChange?.("forgotPassword"), 3e3);
|
|
766
1221
|
} finally {
|
|
767
1222
|
setValidatingCode(false);
|
|
@@ -817,58 +1272,16 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
|
|
|
817
1272
|
onResetSuccess?.();
|
|
818
1273
|
}, 1e3);
|
|
819
1274
|
} else {
|
|
820
|
-
const
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
} else if (response.errors?._transaction) {
|
|
824
|
-
const transactionErrors = response.errors._transaction;
|
|
825
|
-
if (Array.isArray(transactionErrors) && transactionErrors.length > 0) {
|
|
826
|
-
const firstError = transactionErrors[0];
|
|
827
|
-
let errorMsg = "";
|
|
828
|
-
if (typeof firstError === "string") {
|
|
829
|
-
try {
|
|
830
|
-
const parsed = JSON.parse(firstError);
|
|
831
|
-
if (parsed?.response?.message) {
|
|
832
|
-
errorMsg = parsed.response.message.toLowerCase();
|
|
833
|
-
}
|
|
834
|
-
} catch {
|
|
835
|
-
errorMsg = firstError.toLowerCase();
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
if (errorMsg.includes("expired")) {
|
|
839
|
-
errorMessages.push(t("resetPassword.codeExpiredOrInvalid"));
|
|
840
|
-
} else if (errorMsg.includes("invalid")) {
|
|
841
|
-
errorMessages.push(t("resetPassword.invalidCode"));
|
|
842
|
-
} else {
|
|
843
|
-
errorMessages.push(t("error.unknown"));
|
|
844
|
-
}
|
|
845
|
-
} else {
|
|
846
|
-
errorMessages.push(t("error.unknown"));
|
|
847
|
-
}
|
|
848
|
-
} else if (response.errors?._error) {
|
|
849
|
-
const error = response.errors._error[0];
|
|
850
|
-
if (error === "TOO_MANY_REQUESTS") {
|
|
851
|
-
errorMessages.push(t("errors.auth.TOO_MANY_REQUESTS"));
|
|
852
|
-
} else {
|
|
853
|
-
const errorMsg = error?.toLowerCase() || "";
|
|
854
|
-
if (errorMsg.includes("expired")) {
|
|
855
|
-
errorMessages.push(t("resetPassword.codeExpiredOrInvalid"));
|
|
856
|
-
} else if (errorMsg.includes("invalid")) {
|
|
857
|
-
errorMessages.push(t("resetPassword.invalidCode"));
|
|
858
|
-
} else {
|
|
859
|
-
errorMessages.push(error || t("error.unknown"));
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
} else {
|
|
863
|
-
errorMessages.push(t("error.unknown"));
|
|
864
|
-
}
|
|
865
|
-
setErrors(errorMessages);
|
|
1275
|
+
const parsedErrors = handleCrudifyError(response);
|
|
1276
|
+
const translatedErrors = parsedErrors.map(translateError);
|
|
1277
|
+
setErrors(translatedErrors);
|
|
866
1278
|
}
|
|
867
1279
|
} catch (error) {
|
|
868
|
-
|
|
869
|
-
|
|
1280
|
+
const parsedErrors = handleCrudifyError(error);
|
|
1281
|
+
const translatedErrors = parsedErrors.map(translateError);
|
|
1282
|
+
setErrors(translatedErrors);
|
|
870
1283
|
if (onError) {
|
|
871
|
-
onError(
|
|
1284
|
+
onError(translatedErrors.join(", "));
|
|
872
1285
|
}
|
|
873
1286
|
}
|
|
874
1287
|
setLoading(false);
|
|
@@ -881,19 +1294,19 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
|
|
|
881
1294
|
}
|
|
882
1295
|
};
|
|
883
1296
|
if (validatingCode) {
|
|
884
|
-
return /* @__PURE__ */
|
|
1297
|
+
return /* @__PURE__ */ jsx6(Box3, { sx: { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "300px" }, children: /* @__PURE__ */ jsx6(CircularProgress3, {}) });
|
|
885
1298
|
}
|
|
886
1299
|
if (!codeValidated) {
|
|
887
|
-
return /* @__PURE__ */
|
|
1300
|
+
return /* @__PURE__ */ jsx6(Box3, { children: errors.length > 0 && errors.map((error, index) => /* @__PURE__ */ jsx6(Alert3, { variant: "filled", sx: { mt: 2 }, severity: "error", children: error }, index)) });
|
|
888
1301
|
}
|
|
889
1302
|
return /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
890
1303
|
/* @__PURE__ */ jsxs3(Box3, { component: "form", noValidate: true, sx: { width: "100%", display: "flex", flexDirection: "column", gap: 2 }, children: [
|
|
891
1304
|
/* @__PURE__ */ jsxs3(Box3, { sx: { mb: 2 }, children: [
|
|
892
|
-
/* @__PURE__ */
|
|
893
|
-
/* @__PURE__ */
|
|
1305
|
+
/* @__PURE__ */ jsx6(Typography3, { variant: "h5", component: "h1", sx: { mb: 1, fontWeight: 600 }, children: t("resetPassword.title") }),
|
|
1306
|
+
/* @__PURE__ */ jsx6(Typography3, { variant: "body2", sx: { color: "grey.600" }, children: t("resetPassword.instructions") })
|
|
894
1307
|
] }),
|
|
895
1308
|
/* @__PURE__ */ jsxs3(Box3, { sx: { mb: 1 }, children: [
|
|
896
|
-
/* @__PURE__ */
|
|
1309
|
+
/* @__PURE__ */ jsx6(
|
|
897
1310
|
Typography3,
|
|
898
1311
|
{
|
|
899
1312
|
variant: "body2",
|
|
@@ -903,7 +1316,7 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
|
|
|
903
1316
|
children: t("resetPassword.newPasswordLabel")
|
|
904
1317
|
}
|
|
905
1318
|
),
|
|
906
|
-
/* @__PURE__ */
|
|
1319
|
+
/* @__PURE__ */ jsx6(
|
|
907
1320
|
TextField3,
|
|
908
1321
|
{
|
|
909
1322
|
fullWidth: true,
|
|
@@ -922,7 +1335,7 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
|
|
|
922
1335
|
)
|
|
923
1336
|
] }),
|
|
924
1337
|
/* @__PURE__ */ jsxs3(Box3, { sx: { mb: 1 }, children: [
|
|
925
|
-
/* @__PURE__ */
|
|
1338
|
+
/* @__PURE__ */ jsx6(
|
|
926
1339
|
Typography3,
|
|
927
1340
|
{
|
|
928
1341
|
variant: "body2",
|
|
@@ -932,7 +1345,7 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
|
|
|
932
1345
|
children: t("resetPassword.confirmPasswordLabel")
|
|
933
1346
|
}
|
|
934
1347
|
),
|
|
935
|
-
/* @__PURE__ */
|
|
1348
|
+
/* @__PURE__ */ jsx6(
|
|
936
1349
|
TextField3,
|
|
937
1350
|
{
|
|
938
1351
|
fullWidth: true,
|
|
@@ -950,26 +1363,43 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
|
|
|
950
1363
|
}
|
|
951
1364
|
)
|
|
952
1365
|
] }),
|
|
953
|
-
/* @__PURE__ */
|
|
954
|
-
/* @__PURE__ */
|
|
1366
|
+
/* @__PURE__ */ jsx6(Button3, { disabled: loading, type: "button", onClick: handleSubmit, fullWidth: true, variant: "contained", color: "primary", sx: { mt: 2, mb: 2 }, children: loading ? /* @__PURE__ */ jsx6(CircularProgress3, { size: 20 }) : t("resetPassword.resetPasswordButton") }),
|
|
1367
|
+
/* @__PURE__ */ jsx6(Box3, { sx: { display: "flex", justifyContent: "center", alignItems: "center" }, children: /* @__PURE__ */ jsx6(Link3, { sx: { cursor: "pointer" }, onClick: handleBack, variant: "body2", color: "secondary", children: t("common.back") }) })
|
|
955
1368
|
] }),
|
|
956
|
-
/* @__PURE__ */
|
|
1369
|
+
/* @__PURE__ */ jsx6(Box3, { children: errors.length > 0 && errors.map((error, index) => /* @__PURE__ */ jsx6(Alert3, { variant: "filled", sx: { mt: 2 }, severity: "error", children: error }, index)) })
|
|
957
1370
|
] });
|
|
958
1371
|
};
|
|
959
1372
|
var ResetPasswordForm_default = ResetPasswordForm;
|
|
960
1373
|
|
|
961
1374
|
// src/components/CrudifyLogin/Forms/CheckCodeForm.tsx
|
|
962
|
-
import { useState as useState5, useEffect as
|
|
1375
|
+
import { useState as useState5, useEffect as useEffect6 } from "react";
|
|
963
1376
|
import { Typography as Typography4, TextField as TextField4, Button as Button4, Box as Box4, CircularProgress as CircularProgress4, Alert as Alert4, Link as Link4 } from "@mui/material";
|
|
964
|
-
import { Fragment as Fragment4, jsx as
|
|
965
|
-
var CheckCodeForm = ({ onScreenChange, onError, searchParams
|
|
1377
|
+
import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1378
|
+
var CheckCodeForm = ({ onScreenChange, onError, searchParams }) => {
|
|
1379
|
+
const { crudify: crudify3 } = useCrudify();
|
|
966
1380
|
const [code, setCode] = useState5("");
|
|
967
1381
|
const [loading, setLoading] = useState5(false);
|
|
968
1382
|
const [errors, setErrors] = useState5([]);
|
|
969
1383
|
const [helperTextCode, setHelperTextCode] = useState5(null);
|
|
970
1384
|
const [email, setEmail] = useState5("");
|
|
971
1385
|
const { t } = useTranslation();
|
|
972
|
-
|
|
1386
|
+
const translateError = (parsedError) => {
|
|
1387
|
+
const possibleKeys = [
|
|
1388
|
+
`errors.auth.${parsedError.code}`,
|
|
1389
|
+
`errors.data.${parsedError.code}`,
|
|
1390
|
+
`errors.system.${parsedError.code}`,
|
|
1391
|
+
`errors.${parsedError.code}`,
|
|
1392
|
+
`checkCode.${parsedError.code.toLowerCase()}`
|
|
1393
|
+
];
|
|
1394
|
+
for (const key of possibleKeys) {
|
|
1395
|
+
const translated = t(key);
|
|
1396
|
+
if (translated !== key) {
|
|
1397
|
+
return translated;
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
return parsedError.message || t("error.unknown");
|
|
1401
|
+
};
|
|
1402
|
+
useEffect6(() => {
|
|
973
1403
|
const emailParam = searchParams?.get("email");
|
|
974
1404
|
if (emailParam) {
|
|
975
1405
|
setEmail(emailParam);
|
|
@@ -1001,34 +1431,18 @@ var CheckCodeForm = ({ onScreenChange, onError, searchParams, crudify: crudify3
|
|
|
1001
1431
|
if (response.success) {
|
|
1002
1432
|
onScreenChange?.("resetPassword", { email, code, fromCodeVerification: "true" });
|
|
1003
1433
|
} else {
|
|
1004
|
-
const
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
} else if (response.errors) {
|
|
1008
|
-
if (response.errors._error) {
|
|
1009
|
-
const errors2 = response.errors._error;
|
|
1010
|
-
const translatedErrors = errors2.map((error) => {
|
|
1011
|
-
if (error === "TOO_MANY_REQUESTS") {
|
|
1012
|
-
return t("errors.auth.TOO_MANY_REQUESTS");
|
|
1013
|
-
}
|
|
1014
|
-
return error;
|
|
1015
|
-
});
|
|
1016
|
-
errorMessages.push(...translatedErrors);
|
|
1017
|
-
} else {
|
|
1018
|
-
errorMessages.push(t("error.unknown"));
|
|
1019
|
-
}
|
|
1020
|
-
} else {
|
|
1021
|
-
errorMessages.push(t("checkCode.verifyError"));
|
|
1022
|
-
}
|
|
1023
|
-
setErrors(errorMessages);
|
|
1434
|
+
const parsedErrors = handleCrudifyError(response);
|
|
1435
|
+
const translatedErrors = parsedErrors.map(translateError);
|
|
1436
|
+
setErrors(translatedErrors);
|
|
1024
1437
|
setLoading(false);
|
|
1025
1438
|
}
|
|
1026
1439
|
} catch (error) {
|
|
1027
|
-
|
|
1028
|
-
|
|
1440
|
+
const parsedErrors = handleCrudifyError(error);
|
|
1441
|
+
const translatedErrors = parsedErrors.map(translateError);
|
|
1442
|
+
setErrors(translatedErrors);
|
|
1029
1443
|
setLoading(false);
|
|
1030
1444
|
if (onError) {
|
|
1031
|
-
onError(
|
|
1445
|
+
onError(translatedErrors.join(", "));
|
|
1032
1446
|
}
|
|
1033
1447
|
}
|
|
1034
1448
|
};
|
|
@@ -1042,11 +1456,11 @@ var CheckCodeForm = ({ onScreenChange, onError, searchParams, crudify: crudify3
|
|
|
1042
1456
|
return /* @__PURE__ */ jsxs4(Fragment4, { children: [
|
|
1043
1457
|
/* @__PURE__ */ jsxs4(Box4, { component: "form", noValidate: true, sx: { width: "100%", display: "flex", flexDirection: "column", gap: 2 }, children: [
|
|
1044
1458
|
/* @__PURE__ */ jsxs4(Box4, { sx: { mb: 2 }, children: [
|
|
1045
|
-
/* @__PURE__ */
|
|
1046
|
-
/* @__PURE__ */
|
|
1459
|
+
/* @__PURE__ */ jsx7(Typography4, { variant: "h5", component: "h1", sx: { mb: 1, fontWeight: 600 }, children: t("checkCode.title") }),
|
|
1460
|
+
/* @__PURE__ */ jsx7(Typography4, { variant: "body2", sx: { color: "grey.600" }, children: t("checkCode.instructions") })
|
|
1047
1461
|
] }),
|
|
1048
1462
|
/* @__PURE__ */ jsxs4(Box4, { sx: { mb: 1 }, children: [
|
|
1049
|
-
/* @__PURE__ */
|
|
1463
|
+
/* @__PURE__ */ jsx7(
|
|
1050
1464
|
Typography4,
|
|
1051
1465
|
{
|
|
1052
1466
|
variant: "body2",
|
|
@@ -1056,7 +1470,7 @@ var CheckCodeForm = ({ onScreenChange, onError, searchParams, crudify: crudify3
|
|
|
1056
1470
|
children: t("checkCode.codeLabel")
|
|
1057
1471
|
}
|
|
1058
1472
|
),
|
|
1059
|
-
/* @__PURE__ */
|
|
1473
|
+
/* @__PURE__ */ jsx7(
|
|
1060
1474
|
TextField4,
|
|
1061
1475
|
{
|
|
1062
1476
|
fullWidth: true,
|
|
@@ -1077,7 +1491,7 @@ var CheckCodeForm = ({ onScreenChange, onError, searchParams, crudify: crudify3
|
|
|
1077
1491
|
}
|
|
1078
1492
|
)
|
|
1079
1493
|
] }),
|
|
1080
|
-
/* @__PURE__ */
|
|
1494
|
+
/* @__PURE__ */ jsx7(
|
|
1081
1495
|
Button4,
|
|
1082
1496
|
{
|
|
1083
1497
|
disabled: loading || code.length !== 6,
|
|
@@ -1087,33 +1501,60 @@ var CheckCodeForm = ({ onScreenChange, onError, searchParams, crudify: crudify3
|
|
|
1087
1501
|
variant: "contained",
|
|
1088
1502
|
color: "primary",
|
|
1089
1503
|
sx: { mt: 2, mb: 2 },
|
|
1090
|
-
children: loading ? /* @__PURE__ */
|
|
1504
|
+
children: loading ? /* @__PURE__ */ jsx7(CircularProgress4, { size: 20 }) : t("checkCode.verifyButton")
|
|
1091
1505
|
}
|
|
1092
1506
|
),
|
|
1093
|
-
/* @__PURE__ */
|
|
1507
|
+
/* @__PURE__ */ jsx7(Box4, { sx: { display: "flex", justifyContent: "center", alignItems: "center" }, children: /* @__PURE__ */ jsx7(Link4, { sx: { cursor: "pointer" }, onClick: handleBack, variant: "body2", color: "secondary", children: t("common.back") }) })
|
|
1094
1508
|
] }),
|
|
1095
|
-
/* @__PURE__ */
|
|
1509
|
+
/* @__PURE__ */ jsx7(Box4, { children: errors.length > 0 && errors.map((error, index) => /* @__PURE__ */ jsx7(Alert4, { sx: { mt: 2 }, severity: "error", children: error }, index)) })
|
|
1096
1510
|
] });
|
|
1097
1511
|
};
|
|
1098
1512
|
var CheckCodeForm_default = CheckCodeForm;
|
|
1099
1513
|
|
|
1100
|
-
// src/components/CrudifyLogin/
|
|
1101
|
-
import {
|
|
1102
|
-
import
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1514
|
+
// src/components/CrudifyLogin/components/CrudifyInitializer.tsx
|
|
1515
|
+
import { Box as Box5, CircularProgress as CircularProgress5, Alert as Alert5, Typography as Typography5 } from "@mui/material";
|
|
1516
|
+
import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1517
|
+
var CrudifyInitializer = ({
|
|
1518
|
+
children,
|
|
1519
|
+
fallback
|
|
1520
|
+
}) => {
|
|
1521
|
+
const { isLoading, error, isInitialized } = useCrudify();
|
|
1522
|
+
const { t } = useTranslation();
|
|
1523
|
+
if (isLoading) {
|
|
1524
|
+
return fallback || /* @__PURE__ */ jsxs5(
|
|
1525
|
+
Box5,
|
|
1526
|
+
{
|
|
1527
|
+
sx: {
|
|
1528
|
+
display: "flex",
|
|
1529
|
+
flexDirection: "column",
|
|
1530
|
+
alignItems: "center",
|
|
1531
|
+
justifyContent: "center",
|
|
1532
|
+
minHeight: "200px",
|
|
1533
|
+
gap: 2
|
|
1534
|
+
},
|
|
1535
|
+
children: [
|
|
1536
|
+
/* @__PURE__ */ jsx8(CircularProgress5, {}),
|
|
1537
|
+
/* @__PURE__ */ jsx8(Typography5, { variant: "body2", color: "text.secondary", children: t("login.initializing") !== "login.initializing" ? t("login.initializing") : "Initializing..." })
|
|
1538
|
+
]
|
|
1539
|
+
}
|
|
1540
|
+
);
|
|
1541
|
+
}
|
|
1542
|
+
if (error) {
|
|
1543
|
+
return /* @__PURE__ */ jsx8(Alert5, { severity: "error", sx: { mt: 2 }, children: /* @__PURE__ */ jsxs5(Typography5, { variant: "body2", children: [
|
|
1544
|
+
t("login.initializationError") !== "login.initializationError" ? t("login.initializationError") : "Initialization error",
|
|
1545
|
+
": ",
|
|
1546
|
+
error
|
|
1547
|
+
] }) });
|
|
1548
|
+
}
|
|
1549
|
+
if (!isInitialized) {
|
|
1550
|
+
return /* @__PURE__ */ jsx8(Alert5, { severity: "warning", sx: { mt: 2 }, children: /* @__PURE__ */ jsx8(Typography5, { variant: "body2", children: t("login.notInitialized") !== "login.notInitialized" ? t("login.notInitialized") : "System not initialized" }) });
|
|
1551
|
+
}
|
|
1552
|
+
return /* @__PURE__ */ jsx8(Fragment5, { children });
|
|
1108
1553
|
};
|
|
1109
1554
|
|
|
1110
1555
|
// src/components/CrudifyLogin/hooks/useCrudifyLogin.ts
|
|
1111
|
-
|
|
1112
|
-
var isGloballyInitialized = false;
|
|
1113
|
-
var lastApiKey = "";
|
|
1114
|
-
var lastEnv = "";
|
|
1556
|
+
import { useMemo as useMemo2 } from "react";
|
|
1115
1557
|
var useCrudifyLogin = (config, _options = {}) => {
|
|
1116
|
-
const [isInitialized, setIsInitialized] = useState6(false);
|
|
1117
1558
|
const finalConfig = useMemo2(() => {
|
|
1118
1559
|
const publicApiKey = config.publicApiKey || getCookie("publicApiKey") || null;
|
|
1119
1560
|
const rawEnv = config.env || getCookie("environment") || "prod";
|
|
@@ -1134,244 +1575,61 @@ var useCrudifyLogin = (config, _options = {}) => {
|
|
|
1134
1575
|
loginActions
|
|
1135
1576
|
};
|
|
1136
1577
|
}, [config]);
|
|
1137
|
-
|
|
1138
|
-
console.log("\u{1F527} useCrudifyLogin useEffect triggered:", {
|
|
1139
|
-
publicApiKey: !!finalConfig.publicApiKey,
|
|
1140
|
-
env: finalConfig.env,
|
|
1141
|
-
hasPublicApiKey: !!finalConfig.publicApiKey,
|
|
1142
|
-
isGloballyInitialized,
|
|
1143
|
-
lastApiKey: lastApiKey ? lastApiKey.substring(0, 10) + "..." : "none",
|
|
1144
|
-
lastEnv
|
|
1145
|
-
});
|
|
1146
|
-
if (!finalConfig.publicApiKey) {
|
|
1147
|
-
console.log("\u274C No publicApiKey, skipping crudify initialization");
|
|
1148
|
-
setIsInitialized(false);
|
|
1149
|
-
return;
|
|
1150
|
-
}
|
|
1151
|
-
const currentApiKey = finalConfig.publicApiKey;
|
|
1152
|
-
const currentEnv = finalConfig.env;
|
|
1153
|
-
if (isGloballyInitialized && lastApiKey === currentApiKey && lastEnv === currentEnv) {
|
|
1154
|
-
console.log("\u2705 Crudify already initialized with same config, reusing");
|
|
1155
|
-
setIsInitialized(true);
|
|
1156
|
-
return;
|
|
1157
|
-
}
|
|
1158
|
-
const initializeCrudify = async () => {
|
|
1159
|
-
if (globalInitPromise) {
|
|
1160
|
-
console.log("\u23F3 Waiting for existing initialization to complete");
|
|
1161
|
-
try {
|
|
1162
|
-
await globalInitPromise;
|
|
1163
|
-
setIsInitialized(isGloballyInitialized);
|
|
1164
|
-
return;
|
|
1165
|
-
} catch (error) {
|
|
1166
|
-
console.error("\u274C Previous initialization failed:", error);
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
globalInitPromise = (async () => {
|
|
1170
|
-
try {
|
|
1171
|
-
console.log("\u2699\uFE0F Configuring crudify with env:", currentEnv);
|
|
1172
|
-
crudify.config(currentEnv);
|
|
1173
|
-
console.log("\u{1F680} Initializing crudify with publicApiKey:", currentApiKey.substring(0, 10) + "...");
|
|
1174
|
-
await crudify.init(currentApiKey, "none");
|
|
1175
|
-
console.log("\u{1F9EA} Testing crudify initialization...");
|
|
1176
|
-
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1177
|
-
if (typeof crudify.transaction === "function" && typeof crudify.login === "function") {
|
|
1178
|
-
console.log("\u2705 Crudify initialization verified and ready");
|
|
1179
|
-
isGloballyInitialized = true;
|
|
1180
|
-
lastApiKey = currentApiKey;
|
|
1181
|
-
lastEnv = currentEnv;
|
|
1182
|
-
} else {
|
|
1183
|
-
console.log("\u274C Crudify methods not properly initialized");
|
|
1184
|
-
isGloballyInitialized = false;
|
|
1185
|
-
}
|
|
1186
|
-
console.log("\u{1F50D} Crudify state after init:", {
|
|
1187
|
-
hasTransaction: typeof crudify.transaction === "function",
|
|
1188
|
-
hasLogin: typeof crudify.login === "function",
|
|
1189
|
-
isGloballyInitialized,
|
|
1190
|
-
crudifyObject: crudify
|
|
1191
|
-
});
|
|
1192
|
-
} catch (error) {
|
|
1193
|
-
console.error("\u274C Error initializing crudify:", error);
|
|
1194
|
-
isGloballyInitialized = false;
|
|
1195
|
-
throw error;
|
|
1196
|
-
}
|
|
1197
|
-
})();
|
|
1198
|
-
try {
|
|
1199
|
-
await globalInitPromise;
|
|
1200
|
-
setIsInitialized(isGloballyInitialized);
|
|
1201
|
-
} catch (error) {
|
|
1202
|
-
setIsInitialized(false);
|
|
1203
|
-
} finally {
|
|
1204
|
-
globalInitPromise = null;
|
|
1205
|
-
}
|
|
1206
|
-
};
|
|
1207
|
-
initializeCrudify();
|
|
1208
|
-
}, [finalConfig.publicApiKey, finalConfig.env]);
|
|
1209
|
-
const crudifyMethods = useMemo2(() => {
|
|
1210
|
-
console.log("\u{1F504} crudifyMethods useMemo triggered:", {
|
|
1211
|
-
publicApiKey: !!finalConfig.publicApiKey,
|
|
1212
|
-
isInitialized,
|
|
1213
|
-
isGloballyInitialized,
|
|
1214
|
-
crudifyLogin: typeof crudify.login,
|
|
1215
|
-
crudifyTransaction: typeof crudify.transaction
|
|
1216
|
-
});
|
|
1217
|
-
if (!finalConfig.publicApiKey || !isInitialized || !isGloballyInitialized) {
|
|
1218
|
-
console.log("\u274C Crudify not ready:", {
|
|
1219
|
-
publicApiKey: !!finalConfig.publicApiKey,
|
|
1220
|
-
isInitialized,
|
|
1221
|
-
isGloballyInitialized
|
|
1222
|
-
});
|
|
1223
|
-
return null;
|
|
1224
|
-
}
|
|
1225
|
-
const methods = {
|
|
1226
|
-
login: async (identifier, password) => {
|
|
1227
|
-
console.log("\u{1F517} Wrapper login called, isGloballyInitialized:", isGloballyInitialized);
|
|
1228
|
-
return await crudify.login(identifier, password);
|
|
1229
|
-
},
|
|
1230
|
-
transaction: async (data, options) => {
|
|
1231
|
-
console.log("\u{1F517} Wrapper transaction called, isGloballyInitialized:", isGloballyInitialized);
|
|
1232
|
-
return await crudify.transaction(data, options);
|
|
1233
|
-
}
|
|
1234
|
-
};
|
|
1235
|
-
console.log("\u2705 Returning ready crudifyMethods:", {
|
|
1236
|
-
hasLogin: typeof methods.login === "function",
|
|
1237
|
-
hasTransaction: typeof methods.transaction === "function",
|
|
1238
|
-
isInitialized,
|
|
1239
|
-
isGloballyInitialized,
|
|
1240
|
-
methods
|
|
1241
|
-
});
|
|
1242
|
-
return methods;
|
|
1243
|
-
}, [finalConfig.publicApiKey, isInitialized, isGloballyInitialized]);
|
|
1244
|
-
return { crudify: crudifyMethods };
|
|
1578
|
+
return { config: finalConfig };
|
|
1245
1579
|
};
|
|
1246
1580
|
|
|
1247
1581
|
// src/components/CrudifyLogin/index.tsx
|
|
1248
|
-
import {
|
|
1582
|
+
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1249
1583
|
var CrudifyLoginInternal = ({
|
|
1250
|
-
config: providedConfig,
|
|
1251
1584
|
onScreenChange,
|
|
1252
1585
|
onExternalNavigate,
|
|
1253
1586
|
onLoginSuccess,
|
|
1254
1587
|
onError,
|
|
1255
|
-
|
|
1256
|
-
redirectUrl = "/",
|
|
1257
|
-
autoReadFromCookies = true
|
|
1588
|
+
redirectUrl = "/"
|
|
1258
1589
|
}) => {
|
|
1259
1590
|
const { t } = useTranslation();
|
|
1260
|
-
const
|
|
1261
|
-
const [searchParams, setSearchParams] = useState7();
|
|
1262
|
-
console.log("\u{1F504} CrudifyLoginInternal RENDER:", { currentScreen, initialScreen });
|
|
1263
|
-
React2.useEffect(() => {
|
|
1264
|
-
const urlParams = new URLSearchParams(window.location.search);
|
|
1265
|
-
if (initialScreen === "checkCode") {
|
|
1266
|
-
const email = urlParams.get("email");
|
|
1267
|
-
const code = urlParams.get("code");
|
|
1268
|
-
console.log("\u{1F517} CheckCode link detected:", { email, code });
|
|
1269
|
-
if (email) {
|
|
1270
|
-
setSearchParams(urlParams);
|
|
1271
|
-
}
|
|
1272
|
-
}
|
|
1273
|
-
if (initialScreen === "resetPassword") {
|
|
1274
|
-
const link = urlParams.get("link");
|
|
1275
|
-
console.log("\u{1F517} ResetPassword link detected:", { link });
|
|
1276
|
-
if (link) {
|
|
1277
|
-
setSearchParams(urlParams);
|
|
1278
|
-
}
|
|
1279
|
-
}
|
|
1280
|
-
}, [initialScreen]);
|
|
1281
|
-
const finalConfig = useMemo3(() => {
|
|
1282
|
-
let cookieConfig = {};
|
|
1283
|
-
if (autoReadFromCookies) {
|
|
1284
|
-
try {
|
|
1285
|
-
let logoValue;
|
|
1286
|
-
let appColorsValue = { primaryColor: "#1066BA" };
|
|
1287
|
-
try {
|
|
1288
|
-
const encodedLogo = getCookie("logo");
|
|
1289
|
-
if (encodedLogo) {
|
|
1290
|
-
const decodedLogo = decodeURIComponent(encodedLogo);
|
|
1291
|
-
if (decodedLogo.startsWith("http")) logoValue = decodedLogo;
|
|
1292
|
-
}
|
|
1293
|
-
} catch (e) {
|
|
1294
|
-
console.warn("Could not decode logo from cookie, using default.", e);
|
|
1295
|
-
}
|
|
1296
|
-
try {
|
|
1297
|
-
const colorsCookie = getCookie("colors");
|
|
1298
|
-
if (colorsCookie) {
|
|
1299
|
-
const decodedColorsString = decodeURIComponent(colorsCookie);
|
|
1300
|
-
const parsedColors = JSON.parse(decodedColorsString);
|
|
1301
|
-
appColorsValue = { ...appColorsValue, ...parsedColors };
|
|
1302
|
-
}
|
|
1303
|
-
} catch (e) {
|
|
1304
|
-
console.error("Failed to parse colors from cookie, using defaults.", e);
|
|
1305
|
-
}
|
|
1306
|
-
cookieConfig = {
|
|
1307
|
-
logo: logoValue,
|
|
1308
|
-
colors: appColorsValue
|
|
1309
|
-
};
|
|
1310
|
-
} catch (e) {
|
|
1311
|
-
console.error("Error reading configuration from cookies:", e);
|
|
1312
|
-
}
|
|
1313
|
-
}
|
|
1314
|
-
return {
|
|
1315
|
-
publicApiKey: providedConfig?.publicApiKey,
|
|
1316
|
-
env: providedConfig?.env,
|
|
1317
|
-
appName: providedConfig?.appName,
|
|
1318
|
-
logo: providedConfig?.logo || cookieConfig.logo,
|
|
1319
|
-
colors: { ...cookieConfig.colors, ...providedConfig?.colors },
|
|
1320
|
-
loginActions: providedConfig?.loginActions
|
|
1321
|
-
};
|
|
1322
|
-
}, [providedConfig, autoReadFromCookies]);
|
|
1323
|
-
const { crudify: crudify3 } = useCrudifyLogin(finalConfig);
|
|
1591
|
+
const { state, setScreen } = useLoginState();
|
|
1324
1592
|
const handleScreenChange = (screen2, params) => {
|
|
1325
|
-
|
|
1326
|
-
if (params) {
|
|
1327
|
-
setSearchParams(new URLSearchParams(params));
|
|
1328
|
-
} else {
|
|
1329
|
-
setSearchParams(void 0);
|
|
1330
|
-
}
|
|
1593
|
+
setScreen(screen2, params);
|
|
1331
1594
|
onScreenChange?.(screen2, params);
|
|
1332
1595
|
};
|
|
1333
1596
|
const renderCurrentForm = () => {
|
|
1334
|
-
console.log("\u{1F3A8} renderCurrentForm for screen:", currentScreen);
|
|
1335
1597
|
const commonProps = {
|
|
1336
|
-
config: finalConfig,
|
|
1337
1598
|
onScreenChange: handleScreenChange,
|
|
1338
1599
|
onExternalNavigate,
|
|
1339
1600
|
onError,
|
|
1340
|
-
redirectUrl
|
|
1341
|
-
crudify: crudify3
|
|
1601
|
+
redirectUrl
|
|
1342
1602
|
};
|
|
1343
|
-
switch (currentScreen) {
|
|
1603
|
+
switch (state.currentScreen) {
|
|
1344
1604
|
case "forgotPassword":
|
|
1345
|
-
return /* @__PURE__ */
|
|
1605
|
+
return /* @__PURE__ */ jsx9(ForgotPasswordForm_default, { ...commonProps });
|
|
1346
1606
|
case "checkCode":
|
|
1347
|
-
return /* @__PURE__ */
|
|
1607
|
+
return /* @__PURE__ */ jsx9(CheckCodeForm_default, { ...commonProps });
|
|
1348
1608
|
case "resetPassword":
|
|
1349
|
-
return /* @__PURE__ */
|
|
1609
|
+
return /* @__PURE__ */ jsx9(
|
|
1350
1610
|
ResetPasswordForm_default,
|
|
1351
1611
|
{
|
|
1352
1612
|
...commonProps,
|
|
1353
|
-
searchParams,
|
|
1354
1613
|
onResetSuccess: () => {
|
|
1355
1614
|
handleScreenChange("login");
|
|
1356
1615
|
}
|
|
1357
1616
|
}
|
|
1358
1617
|
);
|
|
1359
1618
|
default:
|
|
1360
|
-
return /* @__PURE__ */
|
|
1619
|
+
return /* @__PURE__ */ jsx9(
|
|
1361
1620
|
LoginForm_default,
|
|
1362
1621
|
{
|
|
1363
1622
|
...commonProps,
|
|
1364
|
-
searchParams,
|
|
1365
1623
|
onLoginSuccess
|
|
1366
1624
|
}
|
|
1367
1625
|
);
|
|
1368
1626
|
}
|
|
1369
1627
|
};
|
|
1370
|
-
return /* @__PURE__ */
|
|
1371
|
-
/* @__PURE__ */
|
|
1628
|
+
return /* @__PURE__ */ jsxs6(CrudifyInitializer, { children: [
|
|
1629
|
+
/* @__PURE__ */ jsx9(Box6, { sx: { display: "flex", justifyContent: "center", mb: 3 }, children: /* @__PURE__ */ jsx9(
|
|
1372
1630
|
"img",
|
|
1373
1631
|
{
|
|
1374
|
-
src:
|
|
1632
|
+
src: state.config.logo || "/nocios-default.png",
|
|
1375
1633
|
alt: t("login.logoAlt"),
|
|
1376
1634
|
style: {
|
|
1377
1635
|
width: "100%",
|
|
@@ -1384,17 +1642,17 @@ var CrudifyLoginInternal = ({
|
|
|
1384
1642
|
}
|
|
1385
1643
|
}
|
|
1386
1644
|
) }),
|
|
1387
|
-
|
|
1388
|
-
|
|
1645
|
+
state.config.appName && /* @__PURE__ */ jsx9(
|
|
1646
|
+
Typography6,
|
|
1389
1647
|
{
|
|
1390
1648
|
variant: "h6",
|
|
1391
1649
|
component: "h1",
|
|
1392
1650
|
sx: {
|
|
1393
1651
|
textAlign: "center",
|
|
1394
1652
|
mb: 2,
|
|
1395
|
-
color:
|
|
1653
|
+
color: state.config.colors?.primaryColor || "#1066BA"
|
|
1396
1654
|
},
|
|
1397
|
-
children:
|
|
1655
|
+
children: state.config.appName
|
|
1398
1656
|
}
|
|
1399
1657
|
),
|
|
1400
1658
|
renderCurrentForm()
|
|
@@ -1405,22 +1663,33 @@ var CrudifyLogin = ({
|
|
|
1405
1663
|
translationsUrl,
|
|
1406
1664
|
language = "en",
|
|
1407
1665
|
config = {},
|
|
1666
|
+
initialScreen = "login",
|
|
1667
|
+
autoReadFromCookies = true,
|
|
1408
1668
|
...props
|
|
1409
1669
|
}) => {
|
|
1410
|
-
|
|
1670
|
+
const { config: finalConfig } = useCrudifyLogin(config);
|
|
1671
|
+
return /* @__PURE__ */ jsx9(
|
|
1411
1672
|
I18nProvider,
|
|
1412
1673
|
{
|
|
1413
1674
|
translations,
|
|
1414
1675
|
translationsUrl,
|
|
1415
1676
|
language,
|
|
1416
|
-
children: /* @__PURE__ */
|
|
1677
|
+
children: /* @__PURE__ */ jsx9(CrudifyProvider, { config: finalConfig, children: /* @__PURE__ */ jsx9(
|
|
1678
|
+
LoginStateProvider,
|
|
1679
|
+
{
|
|
1680
|
+
config,
|
|
1681
|
+
initialScreen,
|
|
1682
|
+
autoReadFromCookies,
|
|
1683
|
+
children: /* @__PURE__ */ jsx9(CrudifyLoginInternal, { config, ...props })
|
|
1684
|
+
}
|
|
1685
|
+
) })
|
|
1417
1686
|
}
|
|
1418
1687
|
);
|
|
1419
1688
|
};
|
|
1420
1689
|
var CrudifyLogin_default = CrudifyLogin;
|
|
1421
1690
|
|
|
1422
1691
|
// src/hooks/useUserProfile.ts
|
|
1423
|
-
import { useState as
|
|
1692
|
+
import { useState as useState6, useEffect as useEffect7, useCallback, useRef as useRef2 } from "react";
|
|
1424
1693
|
import crudify2 from "@nocios/crudify-browser";
|
|
1425
1694
|
|
|
1426
1695
|
// src/utils/jwtUtils.ts
|
|
@@ -1466,9 +1735,9 @@ var isTokenExpired = (token) => {
|
|
|
1466
1735
|
// src/hooks/useUserProfile.ts
|
|
1467
1736
|
var useUserProfile = (options = {}) => {
|
|
1468
1737
|
const { autoFetch = true, retryOnError = false, maxRetries = 3 } = options;
|
|
1469
|
-
const [userProfile, setUserProfile] =
|
|
1470
|
-
const [loading, setLoading] =
|
|
1471
|
-
const [error, setError] =
|
|
1738
|
+
const [userProfile, setUserProfile] = useState6(null);
|
|
1739
|
+
const [loading, setLoading] = useState6(false);
|
|
1740
|
+
const [error, setError] = useState6(null);
|
|
1472
1741
|
const abortControllerRef = useRef2(null);
|
|
1473
1742
|
const mountedRef = useRef2(true);
|
|
1474
1743
|
const requestIdRef = useRef2(0);
|
|
@@ -1514,11 +1783,11 @@ var useUserProfile = (options = {}) => {
|
|
|
1514
1783
|
}
|
|
1515
1784
|
} catch (err) {
|
|
1516
1785
|
if (currentRequestId === requestIdRef.current && mountedRef.current) {
|
|
1517
|
-
|
|
1786
|
+
const error2 = err;
|
|
1787
|
+
if (error2.name === "AbortError") {
|
|
1518
1788
|
return;
|
|
1519
1789
|
}
|
|
1520
|
-
|
|
1521
|
-
const shouldRetry = retryOnError && retryCountRef.current < maxRetries && (err.message?.includes("Network Error") || err.message?.includes("Failed to fetch"));
|
|
1790
|
+
const shouldRetry = retryOnError && retryCountRef.current < maxRetries && (error2.message?.includes("Network Error") || error2.message?.includes("Failed to fetch"));
|
|
1522
1791
|
if (shouldRetry) {
|
|
1523
1792
|
retryCountRef.current++;
|
|
1524
1793
|
setTimeout(() => {
|
|
@@ -1540,12 +1809,12 @@ var useUserProfile = (options = {}) => {
|
|
|
1540
1809
|
}
|
|
1541
1810
|
}
|
|
1542
1811
|
}, [retryOnError, maxRetries]);
|
|
1543
|
-
|
|
1812
|
+
useEffect7(() => {
|
|
1544
1813
|
if (autoFetch) {
|
|
1545
1814
|
refreshProfile();
|
|
1546
1815
|
}
|
|
1547
1816
|
}, [autoFetch, refreshProfile]);
|
|
1548
|
-
|
|
1817
|
+
useEffect7(() => {
|
|
1549
1818
|
mountedRef.current = true;
|
|
1550
1819
|
return () => {
|
|
1551
1820
|
mountedRef.current = false;
|
|
@@ -1565,11 +1834,18 @@ var useUserProfile = (options = {}) => {
|
|
|
1565
1834
|
};
|
|
1566
1835
|
export {
|
|
1567
1836
|
CrudifyLogin_default as CrudifyLogin,
|
|
1837
|
+
ERROR_CODES,
|
|
1838
|
+
ERROR_SEVERITY_MAP,
|
|
1568
1839
|
default2 as crudify,
|
|
1569
1840
|
decodeJwtSafely,
|
|
1570
1841
|
getCookie,
|
|
1571
1842
|
getCurrentUserEmail,
|
|
1843
|
+
getErrorMessage,
|
|
1844
|
+
handleCrudifyError,
|
|
1572
1845
|
isTokenExpired,
|
|
1846
|
+
parseApiError,
|
|
1847
|
+
parseJavaScriptError,
|
|
1848
|
+
parseTransactionError,
|
|
1573
1849
|
secureLocalStorage,
|
|
1574
1850
|
secureSessionStorage,
|
|
1575
1851
|
useCrudifyLogin,
|