@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/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 React2, { useState as useState7, useMemo as useMemo3 } from "react";
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 { useState as useState2, useEffect as useEffect2, useRef } from "react";
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 jsx2, jsxs } from "react/jsx-runtime";
212
- var LoginForm = ({ config, onScreenChange, onExternalNavigate, onLoginSuccess, onError, redirectUrl = "/", searchParams, crudify: crudify3 }) => {
213
- const [username, setUsername] = useState2("");
214
- const [password, setPassword] = useState2("");
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
- const redirectParam = searchParams.get("redirect");
224
- if (redirectParam) {
225
- try {
226
- const decodedPath = decodeURIComponent(redirectParam);
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
- useEffect2(() => {
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 getSafeErrorTranslation = (errorCode) => {
780
+ const translateError = (parsedError) => {
243
781
  const possibleKeys = [
244
- `errors.auth.${errorCode}`,
245
- `errors.data.${errorCode}`,
246
- `errors.system.${errorCode}`,
247
- `errors.${errorCode}`,
248
- `login.${errorCode.toLowerCase()}`
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
- setHelperTextEmail(t("login.usernameRequired"));
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
- setHelperTextPassword(t("login.passwordRequired"));
802
+ if (!state.formData.password.trim()) {
803
+ setFieldError("password", t("login.passwordRequired"));
266
804
  return;
267
805
  }
268
- setErrors([]);
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
- console.error("Login error:", error);
292
- setErrors([t("error.unknown")]);
827
+ const parsedErrors = handleCrudifyError(error);
828
+ const translatedErrors = parsedErrors.map(translateError);
829
+ setFieldError("global", translatedErrors);
293
830
  if (onError) {
294
- onError(typeof error === "string" ? error : t("error.unknown"));
831
+ onError(translatedErrors.join(", "));
295
832
  }
296
833
  }
297
834
  };
298
835
  const handleLoginError = (response) => {
299
- if (response.data?.response) {
300
- const { data: errorMessage, status, fieldsWarning } = response.data.response;
301
- if (fieldsWarning) {
302
- if (fieldsWarning.username) setHelperTextEmail(fieldsWarning.username[0]);
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
- setErrors([typeof errorMessage === "string" ? errorMessage : t("error.unknown")]);
841
+ const currentGlobalErrors = state.errors.global || [];
842
+ setFieldError("global", [...currentGlobalErrors, translateError(error)]);
314
843
  }
315
- } else if (response.errors) {
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__ */ jsx2(
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__ */ jsx2(
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) => setUsername(e.target.value),
382
- error: !!helperTextEmail,
383
- helperText: helperTextEmail,
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__ */ jsx2(
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__ */ jsx2(
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) => setPassword(e.target.value),
412
- error: !!helperTextPassword,
413
- helperText: helperTextPassword,
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__ */ jsx2(Box, { sx: { display: "flex", justifyContent: "flex-end", alignItems: "center" }, children: /* @__PURE__ */ jsx2(
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
- const params = searchParams ? Object.fromEntries(searchParams.entries()) : void 0;
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__ */ jsx2(Button, { disabled: loading, type: "submit", fullWidth: true, variant: "contained", color: "primary", sx: { mt: 1, mb: 2 }, children: loading ? /* @__PURE__ */ jsx2(CircularProgress, { size: 20 }) : t("login.loginButton") })
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__ */ jsx2(Box, { children: errors.length > 0 && errors.map((error, index) => /* @__PURE__ */ jsx2(Alert, { variant: "filled", sx: { mt: 2 }, severity: "error", children: /* @__PURE__ */ jsx2("div", { children: error }) }, index)) }),
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__ */ jsx2(
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 jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
464
- var ForgotPasswordForm = ({ onScreenChange, onError, crudify: crudify3 }) => {
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 errorMessages = [];
500
- if (response.data?.response?.status === "TOO_MANY_REQUESTS") {
501
- errorMessages.push(t("errors.auth.TOO_MANY_REQUESTS"));
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
- console.error("Forgot password error:", error);
522
- setErrors([t("error.unknown")]);
1025
+ const parsedErrors = handleCrudifyError(error);
1026
+ const translatedErrors = parsedErrors.map(translateError);
1027
+ setErrors(translatedErrors);
523
1028
  if (onError) {
524
- onError(typeof error === "string" ? error : t("error.unknown"));
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
- console.log("\u{1F4E7} Rendering SUCCESS state:", { emailSent, codeAlreadyExists });
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__ */ jsx3(Typography2, { variant: "h5", component: "h1", sx: { mb: 1, fontWeight: 600 }, children: codeAlreadyExists ? t("forgotPassword.codeAlreadyExistsMessage") : t("forgotPassword.emailSentMessage") }),
558
- /* @__PURE__ */ jsx3(Typography2, { variant: "body2", sx: { color: codeAlreadyExists ? "success.main" : "grey.600" }, children: codeAlreadyExists ? t("forgotPassword.checkEmailInstructions") : t("forgotPassword.checkEmailInstructions") })
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__ */ jsx3(Button2, { type: "button", onClick: handleGoToCheckCode, fullWidth: true, variant: "contained", color: "primary", sx: { mt: 2, mb: 2 }, children: t("forgotPassword.enterCodeLink") }),
561
- /* @__PURE__ */ jsx3(Box2, { sx: { display: "flex", justifyContent: "center", alignItems: "center" }, children: /* @__PURE__ */ jsx3(Link2, { sx: { cursor: "pointer" }, onClick: handleBack, variant: "body2", color: "secondary", children: t("common.back") }) })
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__ */ jsx3(Typography2, { variant: "h5", component: "h1", sx: { mb: 1, fontWeight: 600 }, children: t("forgotPassword.title") }),
569
- /* @__PURE__ */ jsx3(Typography2, { variant: "body2", sx: { color: "grey.600" }, children: t("forgotPassword.instructions") })
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__ */ jsx3(
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__ */ jsx3(
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__ */ jsx3(Button2, { disabled: loading, type: "button", onClick: handleSubmit, fullWidth: true, variant: "contained", color: "primary", sx: { mt: 2, mb: 2 }, children: loading ? /* @__PURE__ */ jsx3(CircularProgress2, { size: 20 }) : t("forgotPassword.sendCodeButton") }),
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__ */ jsx3(Link2, { sx: { cursor: "pointer" }, onClick: handleBack, variant: "body2", color: "secondary", children: t("common.back") }),
603
- /* @__PURE__ */ jsx3(Typography2, { variant: "body2", sx: { color: "grey.400" }, children: "\u2022" }),
604
- /* @__PURE__ */ jsx3(Link2, { sx: { cursor: "pointer" }, onClick: handleGoToCheckCode, variant: "body2", color: "secondary", children: t("login.alreadyHaveCodeLink") })
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__ */ jsx3(Box2, { children: errors.length > 0 && errors.map((error, index) => /* @__PURE__ */ jsx3(Alert2, { variant: "filled", sx: { mt: 2 }, severity: "error", children: error }, index)) })
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 useEffect3 } from "react";
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 jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
616
- var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess, crudify: crudify3 }) => {
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
- useEffect3(() => {
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
- useEffect3(() => {
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
- console.log("\u274C Code validation failed:", response);
734
- console.log("\u274C Full error details:", {
735
- success: response.success,
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
- console.error("Code validation error:", error);
764
- setErrors([t("resetPassword.invalidCode")]);
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 errorMessages = [];
821
- if (response.data?.response?.status === "TOO_MANY_REQUESTS") {
822
- errorMessages.push(t("errors.auth.TOO_MANY_REQUESTS"));
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
- console.error("Reset password error:", error);
869
- setErrors([t("error.unknown")]);
1280
+ const parsedErrors = handleCrudifyError(error);
1281
+ const translatedErrors = parsedErrors.map(translateError);
1282
+ setErrors(translatedErrors);
870
1283
  if (onError) {
871
- onError(typeof error === "string" ? error : t("error.unknown"));
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__ */ jsx4(Box3, { sx: { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "300px" }, children: /* @__PURE__ */ jsx4(CircularProgress3, {}) });
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__ */ jsx4(Box3, { children: errors.length > 0 && errors.map((error, index) => /* @__PURE__ */ jsx4(Alert3, { variant: "filled", sx: { mt: 2 }, severity: "error", children: error }, index)) });
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__ */ jsx4(Typography3, { variant: "h5", component: "h1", sx: { mb: 1, fontWeight: 600 }, children: t("resetPassword.title") }),
893
- /* @__PURE__ */ jsx4(Typography3, { variant: "body2", sx: { color: "grey.600" }, children: t("resetPassword.instructions") })
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__ */ jsx4(
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__ */ jsx4(
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__ */ jsx4(
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__ */ jsx4(
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__ */ jsx4(Button3, { disabled: loading, type: "button", onClick: handleSubmit, fullWidth: true, variant: "contained", color: "primary", sx: { mt: 2, mb: 2 }, children: loading ? /* @__PURE__ */ jsx4(CircularProgress3, { size: 20 }) : t("resetPassword.resetPasswordButton") }),
954
- /* @__PURE__ */ jsx4(Box3, { sx: { display: "flex", justifyContent: "center", alignItems: "center" }, children: /* @__PURE__ */ jsx4(Link3, { sx: { cursor: "pointer" }, onClick: handleBack, variant: "body2", color: "secondary", children: t("common.back") }) })
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__ */ jsx4(Box3, { children: errors.length > 0 && errors.map((error, index) => /* @__PURE__ */ jsx4(Alert3, { variant: "filled", sx: { mt: 2 }, severity: "error", children: error }, index)) })
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 useEffect4 } from "react";
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 jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
965
- var CheckCodeForm = ({ onScreenChange, onError, searchParams, crudify: crudify3 }) => {
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
- useEffect4(() => {
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 errorMessages = [];
1005
- if (response.data?.response?.status === "TOO_MANY_REQUESTS") {
1006
- errorMessages.push(t("errors.auth.TOO_MANY_REQUESTS"));
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
- console.error("Check code error:", error);
1028
- setErrors([t("error.unknown")]);
1440
+ const parsedErrors = handleCrudifyError(error);
1441
+ const translatedErrors = parsedErrors.map(translateError);
1442
+ setErrors(translatedErrors);
1029
1443
  setLoading(false);
1030
1444
  if (onError) {
1031
- onError(typeof error === "string" ? error : t("error.unknown"));
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__ */ jsx5(Typography4, { variant: "h5", component: "h1", sx: { mb: 1, fontWeight: 600 }, children: t("checkCode.title") }),
1046
- /* @__PURE__ */ jsx5(Typography4, { variant: "body2", sx: { color: "grey.600" }, children: t("checkCode.instructions") })
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__ */ jsx5(
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__ */ jsx5(
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__ */ jsx5(
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__ */ jsx5(CircularProgress4, { size: 20 }) : t("checkCode.verifyButton")
1504
+ children: loading ? /* @__PURE__ */ jsx7(CircularProgress4, { size: 20 }) : t("checkCode.verifyButton")
1091
1505
  }
1092
1506
  ),
1093
- /* @__PURE__ */ jsx5(Box4, { sx: { display: "flex", justifyContent: "center", alignItems: "center" }, children: /* @__PURE__ */ jsx5(Link4, { sx: { cursor: "pointer" }, onClick: handleBack, variant: "body2", color: "secondary", children: t("common.back") }) })
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__ */ jsx5(Box4, { children: errors.length > 0 && errors.map((error, index) => /* @__PURE__ */ jsx5(Alert4, { sx: { mt: 2 }, severity: "error", children: error }, index)) })
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/hooks/useCrudifyLogin.ts
1101
- import { useMemo as useMemo2, useEffect as useEffect5, useState as useState6 } from "react";
1102
- import crudify from "@nocios/crudify-browser";
1103
-
1104
- // src/components/CrudifyLogin/utils/cookies.ts
1105
- var getCookie = (name) => {
1106
- const match = document.cookie.match(new RegExp("(^|;)\\s*" + name + "=([^;]+)"));
1107
- return match ? match[2] : null;
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
- var globalInitPromise = null;
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
- useEffect5(() => {
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 { Fragment as Fragment5, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
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
- initialScreen = "login",
1256
- redirectUrl = "/",
1257
- autoReadFromCookies = true
1588
+ redirectUrl = "/"
1258
1589
  }) => {
1259
1590
  const { t } = useTranslation();
1260
- const [currentScreen, setCurrentScreen] = useState7(initialScreen);
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
- setCurrentScreen(screen2);
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__ */ jsx6(ForgotPasswordForm_default, { ...commonProps });
1605
+ return /* @__PURE__ */ jsx9(ForgotPasswordForm_default, { ...commonProps });
1346
1606
  case "checkCode":
1347
- return /* @__PURE__ */ jsx6(CheckCodeForm_default, { ...commonProps, searchParams });
1607
+ return /* @__PURE__ */ jsx9(CheckCodeForm_default, { ...commonProps });
1348
1608
  case "resetPassword":
1349
- return /* @__PURE__ */ jsx6(
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__ */ jsx6(
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__ */ jsxs5(Fragment5, { children: [
1371
- /* @__PURE__ */ jsx6(Box5, { sx: { display: "flex", justifyContent: "center", mb: 3 }, children: /* @__PURE__ */ jsx6(
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: finalConfig.logo || "/nocios-default.png",
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
- finalConfig.appName && /* @__PURE__ */ jsx6(
1388
- Typography5,
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: finalConfig.colors?.primaryColor || "#1066BA"
1653
+ color: state.config.colors?.primaryColor || "#1066BA"
1396
1654
  },
1397
- children: finalConfig.appName
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
- return /* @__PURE__ */ jsx6(
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__ */ jsx6(CrudifyLoginInternal, { config, ...props })
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 useState8, useEffect as useEffect6, useCallback, useRef as useRef2 } from "react";
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] = useState8(null);
1470
- const [loading, setLoading] = useState8(false);
1471
- const [error, setError] = useState8(null);
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
- if (err.name === "AbortError") {
1786
+ const error2 = err;
1787
+ if (error2.name === "AbortError") {
1518
1788
  return;
1519
1789
  }
1520
- console.error("Error loading user profile:", err);
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
- useEffect6(() => {
1812
+ useEffect7(() => {
1544
1813
  if (autoFetch) {
1545
1814
  refreshProfile();
1546
1815
  }
1547
1816
  }, [autoFetch, refreshProfile]);
1548
- useEffect6(() => {
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,