@mesob/auth-react 0.0.3 → 0.0.5
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/components/auth/auth-card.js +11 -0
- package/dist/components/auth/auth-card.js.map +1 -0
- package/dist/components/{auth-page-layout.d.ts → auth/auth-page-layout.d.ts} +2 -1
- package/dist/components/{auth-page-layout.js → auth/auth-page-layout.js} +16 -3
- package/dist/components/auth/auth-page-layout.js.map +1 -0
- package/dist/components/{countdown.js → auth/countdown.js} +8 -4
- package/dist/components/auth/countdown.js.map +1 -0
- package/dist/components/{forgot-password.d.ts → auth/forgot-password.d.ts} +1 -1
- package/dist/components/{forgot-password.js → auth/forgot-password.js} +7 -4
- package/dist/components/auth/forgot-password.js.map +1 -0
- package/dist/components/{pages → auth/pages}/forgot-password-page.js +94 -28
- package/dist/components/auth/pages/forgot-password-page.js.map +1 -0
- package/dist/components/{pages → auth/pages}/reset-password-page.d.ts +2 -1
- package/dist/components/{pages → auth/pages}/reset-password-page.js +111 -42
- package/dist/components/auth/pages/reset-password-page.js.map +1 -0
- package/dist/components/{pages → auth/pages}/sign-in-page.js +130 -30
- package/dist/components/auth/pages/sign-in-page.js.map +1 -0
- package/dist/components/{pages → auth/pages}/sign-up-page.d.ts +2 -1
- package/dist/components/{pages → auth/pages}/sign-up-page.js +93 -29
- package/dist/components/auth/pages/sign-up-page.js.map +1 -0
- package/dist/components/{pages → auth/pages}/verify-email-page.d.ts +2 -1
- package/dist/components/{pages → auth/pages}/verify-email-page.js +131 -61
- package/dist/components/auth/pages/verify-email-page.js.map +1 -0
- package/dist/components/{pages → auth/pages}/verify-phone-page.d.ts +2 -1
- package/dist/components/{pages → auth/pages}/verify-phone-page.js +136 -63
- package/dist/components/auth/pages/verify-phone-page.js.map +1 -0
- package/dist/components/{reset-password-form.d.ts → auth/reset-password-form.d.ts} +3 -2
- package/dist/components/{reset-password-form.js → auth/reset-password-form.js} +17 -15
- package/dist/components/auth/reset-password-form.js.map +1 -0
- package/dist/components/{sign-in.js → auth/sign-in.js} +43 -6
- package/dist/components/auth/sign-in.js.map +1 -0
- package/dist/components/{sign-up.js → auth/sign-up.js} +4 -4
- package/dist/components/auth/sign-up.js.map +1 -0
- package/dist/components/{verification-form.d.ts → auth/verification-form.d.ts} +2 -1
- package/dist/components/{verification-form.js → auth/verification-form.js} +33 -33
- package/dist/components/auth/verification-form.js.map +1 -0
- package/dist/handle-error-H0iqQxJ5.d.ts +6 -0
- package/dist/index.d.ts +49 -15
- package/dist/index.js +304 -142
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/components/auth-card.js +0 -11
- package/dist/components/auth-card.js.map +0 -1
- package/dist/components/auth-page-layout.js.map +0 -1
- package/dist/components/countdown.js.map +0 -1
- package/dist/components/forgot-password.js.map +0 -1
- package/dist/components/pages/forgot-password-page.js.map +0 -1
- package/dist/components/pages/reset-password-page.js.map +0 -1
- package/dist/components/pages/sign-in-page.js.map +0 -1
- package/dist/components/pages/sign-up-page.js.map +0 -1
- package/dist/components/pages/verify-email-page.js.map +0 -1
- package/dist/components/pages/verify-phone-page.js.map +0 -1
- package/dist/components/reset-password-form.js.map +0 -1
- package/dist/components/sign-in.js.map +0 -1
- package/dist/components/sign-up.js.map +0 -1
- package/dist/components/verification-form.js.map +0 -1
- /package/dist/components/{auth-card.d.ts → auth/auth-card.d.ts} +0 -0
- /package/dist/components/{countdown.d.ts → auth/countdown.d.ts} +0 -0
- /package/dist/components/{pages → auth/pages}/forgot-password-page.d.ts +0 -0
- /package/dist/components/{pages → auth/pages}/sign-in-page.d.ts +0 -0
- /package/dist/components/{sign-in.d.ts → auth/sign-in.d.ts} +0 -0
- /package/dist/components/{sign-up.d.ts → auth/sign-up.d.ts} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
// src/components/pages/verify-phone-page.tsx
|
|
3
|
+
// src/components/auth/pages/verify-phone-page.tsx
|
|
4
4
|
import { useTranslations as useTranslations3 } from "next-intl";
|
|
5
5
|
import { useState as useState3 } from "react";
|
|
6
6
|
|
|
@@ -37,40 +37,95 @@ var AuthError = class extends Error {
|
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
// src/constants/auth.error.codes.ts
|
|
40
|
-
var
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
40
|
+
var AUTH_ERROR_MAPPING = {
|
|
41
|
+
USER_NOT_FOUND: {
|
|
42
|
+
title: "Account Not Found",
|
|
43
|
+
description: "We could not find an account with that identifier. Please check your spelling or sign up."
|
|
44
|
+
},
|
|
45
|
+
INVALID_PASSWORD: {
|
|
46
|
+
title: "Invalid Password",
|
|
47
|
+
description: "The password you entered is incorrect. Please try again."
|
|
48
|
+
},
|
|
49
|
+
USER_EXISTS: {
|
|
50
|
+
title: "Account Already Exists",
|
|
51
|
+
description: "An account with this identifier already exists. Please sign in instead."
|
|
52
|
+
},
|
|
53
|
+
VERIFICATION_EXPIRED: {
|
|
54
|
+
title: "Verification Expired",
|
|
55
|
+
description: "The verification code or link has expired. Please request a new one."
|
|
56
|
+
},
|
|
57
|
+
VERIFICATION_MISMATCH: {
|
|
58
|
+
title: "Invalid Code",
|
|
59
|
+
description: "The verification code you entered is invalid. Please double-check and try again."
|
|
60
|
+
},
|
|
61
|
+
VERIFICATION_NOT_FOUND: {
|
|
62
|
+
title: "Verification Not Found",
|
|
63
|
+
description: "We could not find a pending verification request. Please restart the process."
|
|
64
|
+
},
|
|
65
|
+
TOO_MANY_ATTEMPTS: {
|
|
66
|
+
title: "Too Many Attempts",
|
|
67
|
+
description: "You have made too many requests recently. Please wait a moment before trying again."
|
|
68
|
+
},
|
|
69
|
+
REQUIRES_VERIFICATION: {
|
|
70
|
+
title: "Verification Required",
|
|
71
|
+
description: "You need to verify your account before you can continue. Please check your email or phone."
|
|
72
|
+
},
|
|
73
|
+
UNAUTHORIZED: {
|
|
74
|
+
title: "Unauthorized",
|
|
75
|
+
description: "You are not authorized to perform this action. Please sign in again."
|
|
76
|
+
},
|
|
77
|
+
ACCESS_DENIED: {
|
|
78
|
+
title: "Access Denied",
|
|
79
|
+
description: "You do not have permission to access this resource. Please contact support if you believe this is an error."
|
|
80
|
+
},
|
|
81
|
+
HAS_NO_PASSWORD: {
|
|
82
|
+
title: "No Password Set",
|
|
83
|
+
description: "Your account does not have a password set (e.g. social login). Please sign in with your provider or reset your password."
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
var validCodes = Object.keys(AUTH_ERROR_MAPPING);
|
|
53
87
|
|
|
54
88
|
// src/utils/handle-error.ts
|
|
55
89
|
var handleError = (err, setError, t) => {
|
|
56
90
|
if (err instanceof AuthError) {
|
|
57
|
-
let
|
|
58
|
-
if (err.code) {
|
|
59
|
-
|
|
91
|
+
let errorCode = "";
|
|
92
|
+
if (err.code && validCodes.includes(err.code)) {
|
|
93
|
+
errorCode = err.code;
|
|
60
94
|
} else if (err.message) {
|
|
61
95
|
const messageUpper = err.message.toUpperCase().trim();
|
|
62
96
|
if (validCodes.includes(messageUpper)) {
|
|
63
|
-
|
|
97
|
+
errorCode = messageUpper;
|
|
64
98
|
}
|
|
65
99
|
}
|
|
66
|
-
|
|
100
|
+
if (errorCode && AUTH_ERROR_MAPPING[errorCode]) {
|
|
101
|
+
const mapping = AUTH_ERROR_MAPPING[errorCode];
|
|
102
|
+
setError({
|
|
103
|
+
title: mapping.title,
|
|
104
|
+
description: mapping.description
|
|
105
|
+
});
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
setError({
|
|
109
|
+
title: t("errors.fallback"),
|
|
110
|
+
// or 'Error'
|
|
111
|
+
description: err.message || t("errors.fallback")
|
|
112
|
+
});
|
|
67
113
|
} else {
|
|
68
|
-
|
|
114
|
+
const message = err instanceof Error ? err.message : t("errors.fallback");
|
|
115
|
+
setError({
|
|
116
|
+
title: "Error",
|
|
117
|
+
description: message
|
|
118
|
+
});
|
|
69
119
|
}
|
|
70
120
|
};
|
|
71
121
|
|
|
72
|
-
// src/components/auth-page-layout.tsx
|
|
73
|
-
import {
|
|
122
|
+
// src/components/auth/auth-page-layout.tsx
|
|
123
|
+
import {
|
|
124
|
+
Alert,
|
|
125
|
+
AlertDescription,
|
|
126
|
+
AlertTitle
|
|
127
|
+
} from "@mesob/ui/components/alert";
|
|
128
|
+
import { IconAlertCircle } from "@tabler/icons-react";
|
|
74
129
|
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
75
130
|
var AuthPageLayout = ({
|
|
76
131
|
title,
|
|
@@ -80,6 +135,10 @@ var AuthPageLayout = ({
|
|
|
80
135
|
footer,
|
|
81
136
|
logoImage
|
|
82
137
|
}) => {
|
|
138
|
+
const errorContent = error ? (
|
|
139
|
+
// biome-ignore lint/style/noNestedTernary: <explanation>
|
|
140
|
+
typeof error === "string" ? { title: "Error", description: error } : error
|
|
141
|
+
) : null;
|
|
83
142
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
84
143
|
/* @__PURE__ */ jsx2("div", { className: "flex size-8 mb-6 w-full items-center justify-center rounded-md", children: /* @__PURE__ */ jsx2("img", { src: logoImage || "", alt: "Jiret", width: 42, height: 42 }) }),
|
|
85
144
|
/* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
@@ -87,12 +146,16 @@ var AuthPageLayout = ({
|
|
|
87
146
|
description && /* @__PURE__ */ jsx2("p", { className: "mt-2 text-sm text-muted-foreground", children: description })
|
|
88
147
|
] }),
|
|
89
148
|
children,
|
|
90
|
-
|
|
149
|
+
errorContent && /* @__PURE__ */ jsxs(Alert, { variant: "destructive", children: [
|
|
150
|
+
/* @__PURE__ */ jsx2(IconAlertCircle, { className: "h-4 w-4" }),
|
|
151
|
+
/* @__PURE__ */ jsx2(AlertTitle, { children: errorContent.title }),
|
|
152
|
+
/* @__PURE__ */ jsx2(AlertDescription, { children: errorContent.description })
|
|
153
|
+
] }),
|
|
91
154
|
/* @__PURE__ */ jsx2("div", { className: "mt-2 w-full", children: footer && /* @__PURE__ */ jsx2("div", { className: "w-full text-center text-sm text-muted-foreground", children: footer }) })
|
|
92
155
|
] });
|
|
93
156
|
};
|
|
94
157
|
|
|
95
|
-
// src/components/verification-form.tsx
|
|
158
|
+
// src/components/auth/verification-form.tsx
|
|
96
159
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
97
160
|
import { Button as Button2 } from "@mesob/ui/components/button";
|
|
98
161
|
import {
|
|
@@ -107,16 +170,18 @@ import {
|
|
|
107
170
|
InputOTPGroup,
|
|
108
171
|
InputOTPSlot
|
|
109
172
|
} from "@mesob/ui/components/input-otp";
|
|
173
|
+
import { Spinner as Spinner2 } from "@mesob/ui/components/spinner";
|
|
110
174
|
import { useTranslations as useTranslations2 } from "next-intl";
|
|
111
175
|
import { useMemo } from "react";
|
|
112
176
|
import { useForm } from "react-hook-form";
|
|
113
177
|
import { z } from "zod";
|
|
114
178
|
|
|
115
|
-
// src/components/countdown.tsx
|
|
179
|
+
// src/components/auth/countdown.tsx
|
|
116
180
|
import { Button } from "@mesob/ui/components/button";
|
|
181
|
+
import { Spinner } from "@mesob/ui/components/spinner";
|
|
117
182
|
import { useTranslations } from "next-intl";
|
|
118
183
|
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
119
|
-
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
184
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
120
185
|
var Countdown = ({
|
|
121
186
|
initialSeconds = 60,
|
|
122
187
|
onResend,
|
|
@@ -153,19 +218,22 @@ var Countdown = ({
|
|
|
153
218
|
if (seconds > 0) {
|
|
154
219
|
return /* @__PURE__ */ jsx3(Button, { variant: "ghost", disabled: true, children: t("resendIn", { seconds }) });
|
|
155
220
|
}
|
|
156
|
-
return /* @__PURE__ */
|
|
221
|
+
return /* @__PURE__ */ jsxs2(
|
|
157
222
|
Button,
|
|
158
223
|
{
|
|
159
224
|
variant: "ghost",
|
|
160
225
|
onClick: handleResend,
|
|
161
226
|
disabled: isResending || resending,
|
|
162
|
-
children:
|
|
227
|
+
children: [
|
|
228
|
+
isResending || resending && /* @__PURE__ */ jsx3(Spinner, {}),
|
|
229
|
+
t("resend")
|
|
230
|
+
]
|
|
163
231
|
}
|
|
164
232
|
);
|
|
165
233
|
};
|
|
166
234
|
|
|
167
|
-
// src/components/verification-form.tsx
|
|
168
|
-
import { jsx as jsx4, jsxs as
|
|
235
|
+
// src/components/auth/verification-form.tsx
|
|
236
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
169
237
|
var VerificationForm = ({
|
|
170
238
|
onSubmit,
|
|
171
239
|
onResend,
|
|
@@ -184,38 +252,30 @@ var VerificationForm = ({
|
|
|
184
252
|
code: ""
|
|
185
253
|
}
|
|
186
254
|
});
|
|
187
|
-
|
|
188
|
-
const valid = await form.trigger("code");
|
|
189
|
-
if (valid) {
|
|
190
|
-
await onSubmit({ code: value });
|
|
191
|
-
}
|
|
192
|
-
};
|
|
193
|
-
return /* @__PURE__ */ jsx4(Form, { ...form, children: /* @__PURE__ */ jsxs2("form", { className: "space-y-4", children: [
|
|
255
|
+
return /* @__PURE__ */ jsx4(Form, { ...form, children: /* @__PURE__ */ jsxs3("form", { className: "space-y-4", children: [
|
|
194
256
|
/* @__PURE__ */ jsx4(
|
|
195
257
|
FormField,
|
|
196
258
|
{
|
|
197
259
|
control: form.control,
|
|
198
260
|
name: "code",
|
|
199
|
-
render: ({ field }) => /* @__PURE__ */
|
|
261
|
+
render: ({ field }) => /* @__PURE__ */ jsxs3(FormItem, { children: [
|
|
200
262
|
/* @__PURE__ */ jsx4(FormControl, { children: /* @__PURE__ */ jsx4("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx4(
|
|
201
263
|
InputOTP,
|
|
202
264
|
{
|
|
203
265
|
maxLength: 6,
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
/* @__PURE__ */ jsx4(InputOTPSlot, { index:
|
|
214
|
-
/* @__PURE__ */ jsx4(InputOTPSlot, { index:
|
|
215
|
-
/* @__PURE__ */ jsx4(InputOTPSlot, { index:
|
|
216
|
-
/* @__PURE__ */ jsx4(InputOTPSlot, { index:
|
|
217
|
-
/* @__PURE__ */ jsx4(InputOTPSlot, { index: 4 }),
|
|
218
|
-
/* @__PURE__ */ jsx4(InputOTPSlot, { index: 5 })
|
|
266
|
+
id: "otp",
|
|
267
|
+
required: true,
|
|
268
|
+
value: field.value ?? "",
|
|
269
|
+
onChange: field.onChange,
|
|
270
|
+
onBlur: field.onBlur,
|
|
271
|
+
containerClassName: "gap-4 justify-center mb-2 flex items-center",
|
|
272
|
+
children: /* @__PURE__ */ jsxs3(InputOTPGroup, { className: "gap-3 *:data-[slot=input-otp-slot]:h-12 *:data-[slot=input-otp-slot]:w-12 *:data-[slot=input-otp-slot]:rounded-md *:data-[slot=input-otp-slot]:border *:data-[slot=input-otp-slot]:text-xl", children: [
|
|
273
|
+
/* @__PURE__ */ jsx4(InputOTPSlot, { className: "h-12", index: 0 }),
|
|
274
|
+
/* @__PURE__ */ jsx4(InputOTPSlot, { className: "h-12", index: 1 }),
|
|
275
|
+
/* @__PURE__ */ jsx4(InputOTPSlot, { className: "h-12", index: 2 }),
|
|
276
|
+
/* @__PURE__ */ jsx4(InputOTPSlot, { className: "h-12", index: 3 }),
|
|
277
|
+
/* @__PURE__ */ jsx4(InputOTPSlot, { className: "h-12", index: 4 }),
|
|
278
|
+
/* @__PURE__ */ jsx4(InputOTPSlot, { className: "h-12", index: 5 })
|
|
219
279
|
] })
|
|
220
280
|
}
|
|
221
281
|
) }) }),
|
|
@@ -223,9 +283,9 @@ var VerificationForm = ({
|
|
|
223
283
|
] })
|
|
224
284
|
}
|
|
225
285
|
),
|
|
226
|
-
/* @__PURE__ */
|
|
286
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex justify-between items-center", children: [
|
|
227
287
|
/* @__PURE__ */ jsx4(Countdown, { onResend, resending: isLoading }),
|
|
228
|
-
/* @__PURE__ */
|
|
288
|
+
/* @__PURE__ */ jsxs3(
|
|
229
289
|
Button2,
|
|
230
290
|
{
|
|
231
291
|
type: "button",
|
|
@@ -235,14 +295,17 @@ var VerificationForm = ({
|
|
|
235
295
|
})();
|
|
236
296
|
},
|
|
237
297
|
disabled: isLoading || form.watch("code").length !== 6,
|
|
238
|
-
children:
|
|
298
|
+
children: [
|
|
299
|
+
isLoading && /* @__PURE__ */ jsx4(Spinner2, {}),
|
|
300
|
+
t("form.confirm")
|
|
301
|
+
]
|
|
239
302
|
}
|
|
240
303
|
)
|
|
241
304
|
] })
|
|
242
305
|
] }) });
|
|
243
306
|
};
|
|
244
307
|
|
|
245
|
-
// src/components/pages/verify-phone-page.tsx
|
|
308
|
+
// src/components/auth/pages/verify-phone-page.tsx
|
|
246
309
|
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
247
310
|
var VerifyPhonePage = ({
|
|
248
311
|
verificationId,
|
|
@@ -251,7 +314,8 @@ var VerifyPhonePage = ({
|
|
|
251
314
|
onNavigate,
|
|
252
315
|
linkComponent: Link,
|
|
253
316
|
links,
|
|
254
|
-
logoImage
|
|
317
|
+
logoImage,
|
|
318
|
+
redirectUrl
|
|
255
319
|
}) => {
|
|
256
320
|
const t = useTranslations3("Auth.verification");
|
|
257
321
|
const common = useTranslations3("Common");
|
|
@@ -262,7 +326,10 @@ var VerifyPhonePage = ({
|
|
|
262
326
|
const signInLink = links?.signIn || "/auth/sign-in";
|
|
263
327
|
const handleSubmit = async (values) => {
|
|
264
328
|
if (!verificationId) {
|
|
265
|
-
setError(
|
|
329
|
+
setError({
|
|
330
|
+
title: t("errors.fallback"),
|
|
331
|
+
description: t("errors.fallback")
|
|
332
|
+
});
|
|
266
333
|
return;
|
|
267
334
|
}
|
|
268
335
|
setIsLoading(true);
|
|
@@ -275,11 +342,11 @@ var VerifyPhonePage = ({
|
|
|
275
342
|
});
|
|
276
343
|
if (res && "user" in res && "session" in res && res.session) {
|
|
277
344
|
setAuth(res);
|
|
278
|
-
onNavigate("/
|
|
345
|
+
onNavigate(redirectUrl || "/");
|
|
279
346
|
return;
|
|
280
347
|
}
|
|
281
348
|
await refresh();
|
|
282
|
-
onNavigate("/
|
|
349
|
+
onNavigate(redirectUrl || "/");
|
|
283
350
|
} catch (err) {
|
|
284
351
|
handleError(err, setError, t);
|
|
285
352
|
} finally {
|
|
@@ -291,7 +358,10 @@ var VerifyPhonePage = ({
|
|
|
291
358
|
try {
|
|
292
359
|
const targetPhone = context === "sign-up" ? phone : null;
|
|
293
360
|
if (!targetPhone) {
|
|
294
|
-
setError(
|
|
361
|
+
setError({
|
|
362
|
+
title: t("errors.fallback"),
|
|
363
|
+
description: t("phone.missingPhone")
|
|
364
|
+
});
|
|
295
365
|
return;
|
|
296
366
|
}
|
|
297
367
|
const res = await client.requestPhoneOtp({ phone: targetPhone, context });
|
|
@@ -301,7 +371,10 @@ var VerifyPhonePage = ({
|
|
|
301
371
|
);
|
|
302
372
|
return;
|
|
303
373
|
}
|
|
304
|
-
setError(
|
|
374
|
+
setError({
|
|
375
|
+
title: t("errors.fallback"),
|
|
376
|
+
description: t("phone.resendFailed")
|
|
377
|
+
});
|
|
305
378
|
} catch (err) {
|
|
306
379
|
handleError(err, setError, t);
|
|
307
380
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/auth/pages/verify-phone-page.tsx","../../../../src/context/auth-provider.tsx","../../../../src/client.ts","../../../../src/constants/auth.error.codes.ts","../../../../src/utils/handle-error.ts","../../../../src/components/auth/auth-page-layout.tsx","../../../../src/components/auth/verification-form.tsx","../../../../src/components/auth/countdown.tsx"],"sourcesContent":["'use client';\n\nimport { useTranslations } from 'next-intl';\nimport type { ComponentProps } from 'react';\nimport { useState } from 'react';\nimport { useAuth } from '../../../context/auth-provider';\nimport type { AuthResponse } from '../../../types';\nimport type { AuthErrorContent } from '../../../utils/handle-error';\nimport { handleError } from '../../../utils/handle-error';\n\nimport { AuthPageLayout } from '../auth-page-layout';\nimport { VerificationForm } from '../verification-form';\n\ntype VerifyPhonePageProps = {\n locale?: string;\n verificationId: string;\n context: 'sign-in' | 'sign-up';\n phone?: string;\n onNavigate: (path: string) => void;\n linkComponent?: React.ComponentType<ComponentProps<'a'> & { href: string }>;\n links?: {\n signIn?: string;\n };\n logoImage?: string;\n redirectUrl?: string;\n};\nexport const VerifyPhonePage = ({\n verificationId,\n context,\n phone = '',\n onNavigate,\n linkComponent: Link,\n links,\n logoImage,\n redirectUrl,\n}: VerifyPhonePageProps) => {\n const t = useTranslations('Auth.verification');\n const common = useTranslations('Common');\n const footer = useTranslations('Auth.forgotPassword.footer');\n const { client, refresh, setAuth } = useAuth();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthErrorContent | null>(null);\n\n const signInLink = links?.signIn || '/auth/sign-in';\n\n const handleSubmit = async (values: { code: string }) => {\n if (!verificationId) {\n setError({\n title: t('errors.fallback'),\n description: t('errors.fallback'),\n });\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const res = await client.verifyPhoneOtp({\n verificationId,\n code: values.code,\n context,\n });\n if (res && 'user' in res && 'session' in res && res.session) {\n setAuth(res as AuthResponse);\n onNavigate(redirectUrl || '/');\n return;\n }\n await refresh();\n onNavigate(redirectUrl || '/');\n } catch (err) {\n handleError(err, setError, t);\n } finally {\n setIsLoading(false);\n }\n };\n\n const handleResend = async () => {\n setError(null);\n try {\n const targetPhone = context === 'sign-up' ? phone : null;\n if (!targetPhone) {\n setError({\n title: t('errors.fallback'),\n description: t('phone.missingPhone'),\n });\n return;\n }\n const res = await client.requestPhoneOtp({ phone: targetPhone, context });\n if (res && 'verificationId' in res && res.verificationId) {\n onNavigate(\n `/auth/verify-phone?context=${context}&verificationId=${res.verificationId}&phone=${targetPhone}`,\n );\n return;\n }\n setError({\n title: t('errors.fallback'),\n description: t('phone.resendFailed'),\n });\n } catch (err) {\n handleError(err, setError, t);\n }\n };\n\n if (!verificationId) {\n return (\n <AuthPageLayout\n title={common('invalidLinkTitle')}\n description={common('invalidLinkDescription')}\n footer={\n Link ? (\n <Link href={signInLink} className=\"text-primary hover:underline\">\n {footer('backToSignIn')}\n </Link>\n ) : (\n <a\n href={signInLink}\n onClick={(e) => {\n e.preventDefault();\n onNavigate(signInLink);\n }}\n className=\"text-primary hover:underline\"\n >\n {footer('backToSignIn')}\n </a>\n )\n }\n >\n <div />\n </AuthPageLayout>\n );\n }\n\n return (\n <AuthPageLayout\n title={t('phone.title')}\n description={t('phone.description', {\n target: phone || t('phone.missingPhone'),\n })}\n error={error}\n logoImage={logoImage}\n footer={\n Link ? (\n <Link href={signInLink} className=\"text-primary hover:underline\">\n {footer('backToSignIn')}\n </Link>\n ) : (\n <a\n href={signInLink}\n onClick={(e) => {\n e.preventDefault();\n onNavigate(signInLink);\n }}\n className=\"text-primary hover:underline\"\n >\n {footer('backToSignIn')}\n </a>\n )\n }\n >\n <VerificationForm\n verificationId={verificationId}\n onSubmit={handleSubmit}\n onResend={handleResend}\n isLoading={isLoading}\n error={error}\n />\n </AuthPageLayout>\n );\n};\n","'use client';\n\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport type { AuthClient } from '../client';\nimport type { AuthResponse, Session, User } from '../types';\n\ntype AuthContextValue = {\n user: User | null;\n session: Session | null;\n loading: boolean;\n error: Error | null;\n client: AuthClient;\n refresh: () => Promise<void>;\n setAuth: (data: AuthResponse) => void;\n};\n\nconst AuthContext = createContext<AuthContextValue | null>(null);\n\nexport const useAuth = () => {\n const context = useContext(AuthContext);\n if (!context) {\n throw new Error('useAuth must be used within AuthProvider');\n }\n return context;\n};\n\ntype AuthProviderProps = {\n client: AuthClient;\n children: ReactNode;\n};\n\nexport const AuthProvider = ({ client, children }: AuthProviderProps) => {\n const [user, setUser] = useState<User | null>(null);\n const [session, setSession] = useState<Session | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const refresh = useCallback(async () => {\n try {\n setLoading(true);\n setError(null);\n const data = await client.getSession();\n setUser(data.user);\n setSession(data.session);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error('Failed to fetch session'),\n );\n setUser(null);\n setSession(null);\n } finally {\n setLoading(false);\n }\n }, [client]);\n\n const setAuth = useCallback((data: AuthResponse) => {\n setUser(data.user);\n setSession(data.session);\n setError(null);\n setLoading(false);\n }, []);\n\n useEffect(() => {\n refresh();\n }, [refresh]);\n\n return (\n <AuthContext.Provider\n value={{\n user,\n session,\n loading,\n error,\n client,\n refresh,\n setAuth,\n }}\n >\n {children}\n </AuthContext.Provider>\n );\n};\n","import type {\n AuthErrorCode,\n AuthErrorResponse,\n AuthResponse,\n PendingAccountChangeResponse,\n SessionResponse,\n User,\n VerificationResponse,\n} from './types';\n\n// Backend returns error code in 'error' field (AUTH_ERRORS values)\n// or in 'code' field, message in 'message' or 'error' field\nconst validErrorCodes: readonly AuthErrorCode[] = [\n 'USER_NOT_FOUND',\n 'INVALID_PASSWORD',\n 'USER_EXISTS',\n 'VERIFICATION_EXPIRED',\n 'VERIFICATION_MISMATCH',\n 'VERIFICATION_NOT_FOUND',\n 'TOO_MANY_ATTEMPTS',\n 'REQUIRES_VERIFICATION',\n 'UNAUTHORIZED',\n 'ACCESS_DENIED',\n 'HAS_NO_PASSWORD',\n] as const;\n\nexport class AuthError extends Error {\n code?: AuthErrorCode;\n status?: number;\n details?: Record<string, unknown>;\n\n constructor(\n message: string,\n code?: AuthErrorCode,\n status?: number,\n details?: Record<string, unknown>,\n ) {\n super(message);\n this.name = 'AuthError';\n this.code = code;\n this.status = status;\n this.details = details;\n }\n}\n\nexport type AuthClientConfig = {\n baseURL: string;\n};\n\nexport class AuthClient {\n private baseURL: string;\n\n constructor(config: AuthClientConfig) {\n this.baseURL = config.baseURL.replace(/\\/$/, '');\n }\n\n private async request<T>(\n endpoint: string,\n options: RequestInit = {},\n ): Promise<T> {\n const url = `${this.baseURL}${endpoint}`;\n const response = await fetch(url, {\n ...options,\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n });\n if (!response.ok) {\n const text = await response.text();\n let errorData: AuthErrorResponse;\n try {\n errorData = JSON.parse(text);\n } catch {\n errorData = { error: 'Unknown error', message: text };\n }\n\n // Extract error code from code, error, or message field\n // Backend returns error codes in 'error' field (e.g., { error: 'INVALID_PASSWORD' })\n const potentialCode =\n errorData.code ||\n (typeof errorData.error === 'string' ? errorData.error : null) ||\n (typeof errorData.message === 'string' ? errorData.message : null);\n const upperCode = potentialCode?.toUpperCase().trim();\n const errorCode =\n upperCode && validErrorCodes.includes(upperCode as AuthErrorCode)\n ? (upperCode as AuthErrorCode)\n : undefined;\n const errorMessage =\n errorData.message || errorData.error || 'Request failed';\n\n throw new AuthError(\n errorMessage,\n errorCode as AuthErrorCode | undefined,\n response.status,\n errorData.details,\n );\n }\n\n const data = await response.json();\n return data;\n }\n\n signUpWithEmail(data: {\n email: string;\n password: string;\n fullName: string;\n handle?: string;\n }): Promise<AuthResponse | VerificationResponse> {\n return this.request<AuthResponse | VerificationResponse>('/sign-up', {\n method: 'POST',\n body: JSON.stringify({\n email: data.email,\n password: data.password,\n fullName: data.fullName,\n handle: data.handle,\n }),\n });\n }\n\n signUpWithPhone(data: {\n phone: string;\n password: string;\n fullName: string;\n handle?: string;\n }): Promise<AuthResponse | VerificationResponse> {\n return this.request<AuthResponse | VerificationResponse>('/sign-up', {\n method: 'POST',\n body: JSON.stringify({\n phone: data.phone,\n password: data.password,\n fullName: data.fullName,\n handle: data.handle,\n }),\n });\n }\n\n checkUser(data: { identifier: string }): Promise<{ exists: boolean }> {\n return this.request<{ exists: boolean }>('/check-user', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n signInWithPassword(data: {\n identifier: string;\n password: string;\n }): Promise<AuthResponse | VerificationResponse> {\n return this.request<AuthResponse | VerificationResponse>('/sign-in', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n signOut(): Promise<{ message: string }> {\n return this.request<{ message: string }>('/sign-out', {\n method: 'POST',\n });\n }\n\n requestEmailVerification(data?: {\n email?: string;\n }): Promise<{ verificationId: string }> {\n return this.request<{ verificationId: string }>(\n '/email/verification/request',\n {\n method: 'POST',\n body: JSON.stringify(data || {}),\n },\n );\n }\n\n verifyEmail(data: {\n verificationId: string;\n code: string;\n }): Promise<AuthResponse> {\n return this.request<AuthResponse>('/email/verification/confirm', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n resendVerification(_verificationId: string): Promise<{\n verificationId: string;\n }> {\n // For email, request new verification\n return this.requestEmailVerification();\n }\n\n requestPhoneOtp(data: {\n phone: string;\n context: 'sign-up' | 'sign-in' | 'change-phone';\n }): Promise<{ verificationId: string }> {\n return this.request<{ verificationId: string }>(\n '/phone/verification/request',\n {\n method: 'POST',\n body: JSON.stringify(data),\n },\n );\n }\n\n verifyPhoneOtp(data: {\n verificationId: string;\n code: string;\n context: 'sign-up' | 'sign-in' | 'change-phone';\n }): Promise<\n AuthResponse | { user: User | null; session: null; verified: boolean }\n > {\n return this.request('/phone/verification/confirm', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n forgotPassword(data: { identifier: string }): Promise<{\n message: string;\n }> {\n return this.request<{ message: string }>('/password/forgot', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n resetPassword(data: {\n verificationId: string;\n code: string;\n password: string;\n }): Promise<AuthResponse> {\n return this.request<AuthResponse>('/password/reset', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n verifyPassword(data: { password: string }): Promise<{ message: string }> {\n return this.request<{ message: string }>('/password/verify', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n changePassword(data: {\n currentPassword: string;\n newPassword: string;\n }): Promise<{ message: string }> {\n return this.request<{ message: string }>('/password/change', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n getSession(): Promise<SessionResponse> {\n return this.request<SessionResponse>('/session', {\n method: 'GET',\n });\n }\n\n getPendingAccountChange(): Promise<PendingAccountChangeResponse> {\n return this.request<PendingAccountChangeResponse>(\n '/account-change/pending',\n {\n method: 'GET',\n },\n );\n }\n\n updateProfile(data: { fullName?: string }): Promise<{ user: User }> {\n return this.request<{ user: User }>('/profile', {\n method: 'PUT',\n body: JSON.stringify(data),\n });\n }\n\n updateEmail(data: { email: string }): Promise<{ user: User }> {\n return this.request<{ user: User }>('/profile/email', {\n method: 'PUT',\n body: JSON.stringify(data),\n });\n }\n\n updatePhone(data: { phone: string }): Promise<{ user: User }> {\n return this.request<{ user: User }>('/profile/phone', {\n method: 'PUT',\n body: JSON.stringify(data),\n });\n }\n}\n","export const AUTH_ERROR_MAPPING: Record<\n string,\n { title: string; description: string }\n> = {\n USER_NOT_FOUND: {\n title: 'Account Not Found',\n description:\n 'We could not find an account with that identifier. Please check your spelling or sign up.',\n },\n INVALID_PASSWORD: {\n title: 'Invalid Password',\n description: 'The password you entered is incorrect. Please try again.',\n },\n USER_EXISTS: {\n title: 'Account Already Exists',\n description:\n 'An account with this identifier already exists. Please sign in instead.',\n },\n VERIFICATION_EXPIRED: {\n title: 'Verification Expired',\n description:\n 'The verification code or link has expired. Please request a new one.',\n },\n VERIFICATION_MISMATCH: {\n title: 'Invalid Code',\n description:\n 'The verification code you entered is invalid. Please double-check and try again.',\n },\n VERIFICATION_NOT_FOUND: {\n title: 'Verification Not Found',\n description:\n 'We could not find a pending verification request. Please restart the process.',\n },\n TOO_MANY_ATTEMPTS: {\n title: 'Too Many Attempts',\n description:\n 'You have made too many requests recently. Please wait a moment before trying again.',\n },\n REQUIRES_VERIFICATION: {\n title: 'Verification Required',\n description:\n 'You need to verify your account before you can continue. Please check your email or phone.',\n },\n UNAUTHORIZED: {\n title: 'Unauthorized',\n description:\n 'You are not authorized to perform this action. Please sign in again.',\n },\n ACCESS_DENIED: {\n title: 'Access Denied',\n description:\n 'You do not have permission to access this resource. Please contact support if you believe this is an error.',\n },\n HAS_NO_PASSWORD: {\n title: 'No Password Set',\n description:\n 'Your account does not have a password set (e.g. social login). Please sign in with your provider or reset your password.',\n },\n};\n\nexport const validCodes = Object.keys(AUTH_ERROR_MAPPING);\n","import type { _Translator } from 'next-intl';\nimport { AuthError } from '../client';\nimport { AUTH_ERROR_MAPPING, validCodes } from '../constants/auth.error.codes';\n\nexport type AuthErrorContent = {\n title: string;\n description: string;\n};\n\nexport const handleError = (\n err: any,\n setError: (error: AuthErrorContent | null) => void,\n t: _Translator<Record<string, any>, string>,\n) => {\n if (err instanceof AuthError) {\n let errorCode = '';\n\n if (err.code && validCodes.includes(err.code)) {\n errorCode = err.code;\n } else if (err.message) {\n const messageUpper = err.message.toUpperCase().trim();\n if (validCodes.includes(messageUpper)) {\n errorCode = messageUpper;\n }\n }\n\n if (errorCode && AUTH_ERROR_MAPPING[errorCode]) {\n const mapping = AUTH_ERROR_MAPPING[errorCode];\n // Try to translate the description if a key exists, otherwise use English fallback\n // Since mapping.description is English text, we might want to check if there is a translation key\n // But for now, let's use the provided English mapping or try to find a translation if the key matches 'errors.code'\n\n // We can try to lookup translation, if it returns the key (or fallback), we might prefer the mapping text (which is nice English).\n // However, usually we prefer translation.\n // Let's rely on the mapping text primarily as per the request to \"Generate a description and title...\".\n // But if we want i18n support, we should probably add keys.\n // Given the prompt \"Generate a description... for each error code... and display\",\n // I will prioritize the static mapping I just created, but allows future i18n improvement.\n\n setError({\n title: mapping.title,\n description: mapping.description,\n });\n return;\n }\n\n // Fallback for AuthError without known code\n setError({\n title: t('errors.fallback'), // or 'Error'\n description: err.message || t('errors.fallback'),\n });\n } else {\n // Generic error\n const message = err instanceof Error ? err.message : t('errors.fallback');\n setError({\n title: 'Error',\n description: message,\n });\n }\n};\n","'use client';\n\nimport {\n Alert,\n AlertDescription,\n AlertTitle,\n} from '@mesob/ui/components/alert';\nimport { IconAlertCircle } from '@tabler/icons-react';\nimport type { ReactNode } from 'react';\nimport type { AuthErrorContent } from '../../utils/handle-error';\n\ntype AuthPageLayoutProps = {\n title: string;\n description?: string;\n children: ReactNode;\n error?: AuthErrorContent | string | null;\n footer?: ReactNode;\n logoImage?: string;\n};\n\nexport const AuthPageLayout = ({\n title,\n description,\n children,\n error,\n footer,\n logoImage,\n}: AuthPageLayoutProps) => {\n const errorContent: AuthErrorContent | null = error\n ? // biome-ignore lint/style/noNestedTernary: <explanation>\n typeof error === 'string'\n ? { title: 'Error', description: error }\n : error\n : null;\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex size-8 mb-6 w-full items-center justify-center rounded-md\">\n {/** biome-ignore lint/performance/noImgElement: logo image */}\n <img src={logoImage || ''} alt=\"Jiret\" width={42} height={42} />\n </div>\n <div className=\"text-center\">\n <h1 className=\"text-2xl font-bold tracking-tight\">{title}</h1>\n {description && (\n <p className=\"mt-2 text-sm text-muted-foreground\">{description}</p>\n )}\n </div>\n\n {children}\n\n {errorContent && (\n <Alert variant=\"destructive\">\n <IconAlertCircle className=\"h-4 w-4\" />\n <AlertTitle>{errorContent.title}</AlertTitle>\n <AlertDescription>{errorContent.description}</AlertDescription>\n </Alert>\n )}\n <div className=\"mt-2 w-full\">\n {footer && (\n <div className=\"w-full text-center text-sm text-muted-foreground\">\n {footer}\n </div>\n )}\n </div>\n </div>\n );\n};\n","'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Button } from '@mesob/ui/components/button';\nimport {\n Form,\n FormControl,\n FormField,\n FormItem,\n FormMessage,\n} from '@mesob/ui/components/form';\nimport {\n InputOTP,\n InputOTPGroup,\n InputOTPSlot,\n} from '@mesob/ui/components/input-otp';\nimport { Spinner } from '@mesob/ui/components/spinner';\nimport { useTranslations } from 'next-intl';\nimport { useMemo } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { z } from 'zod';\nimport type { AuthErrorContent } from '../../utils/handle-error';\nimport { Countdown } from './countdown';\n\ntype VerificationFormValues = {\n code: string;\n};\n\ntype VerificationFormProps = {\n verificationId: string;\n onSubmit: (values: VerificationFormValues) => Promise<void> | void;\n onResend: () => Promise<void> | void;\n isLoading?: boolean;\n error?: AuthErrorContent | string | null;\n};\n\nexport const VerificationForm = ({\n onSubmit,\n onResend,\n isLoading = false,\n}: VerificationFormProps) => {\n const t = useTranslations('Auth.verification');\n const verificationSchema = useMemo(\n () =>\n z.object({\n code: z.string().length(6, t('form.codeLength')),\n }),\n [t],\n );\n const form = useForm<VerificationFormValues>({\n resolver: zodResolver(verificationSchema),\n defaultValues: {\n code: '',\n },\n });\n\n return (\n <Form {...form}>\n <form className=\"space-y-4\">\n <FormField\n control={form.control}\n name=\"code\"\n render={({ field }) => (\n <FormItem>\n <FormControl>\n <div className=\"flex justify-center\">\n <InputOTP\n maxLength={6}\n id=\"otp\"\n required\n value={field.value ?? ''}\n onChange={field.onChange}\n onBlur={field.onBlur}\n containerClassName=\"gap-4 justify-center mb-2 flex items-center\"\n >\n <InputOTPGroup className=\"gap-3 *:data-[slot=input-otp-slot]:h-12 *:data-[slot=input-otp-slot]:w-12 *:data-[slot=input-otp-slot]:rounded-md *:data-[slot=input-otp-slot]:border *:data-[slot=input-otp-slot]:text-xl\">\n <InputOTPSlot className=\"h-12\" index={0} />\n <InputOTPSlot className=\"h-12\" index={1} />\n <InputOTPSlot className=\"h-12\" index={2} />\n <InputOTPSlot className=\"h-12\" index={3} />\n <InputOTPSlot className=\"h-12\" index={4} />\n <InputOTPSlot className=\"h-12\" index={5} />\n </InputOTPGroup>\n </InputOTP>\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n <div className=\"flex justify-between items-center\">\n <Countdown onResend={onResend} resending={isLoading} />\n <Button\n type=\"button\"\n onClick={() => {\n form.handleSubmit(async (values) => {\n await onSubmit(values);\n })();\n }}\n disabled={isLoading || form.watch('code').length !== 6}\n >\n {isLoading && <Spinner />}\n {t('form.confirm')}\n </Button>\n </div>\n </form>\n </Form>\n );\n};\n","'use client';\n\nimport { Button } from '@mesob/ui/components/button';\nimport { Spinner } from '@mesob/ui/components/spinner';\nimport { useTranslations } from 'next-intl';\nimport { useEffect, useState } from 'react';\n\ntype CountdownProps = {\n initialSeconds?: number;\n onResend: () => Promise<void> | void;\n resending?: boolean;\n};\n\nexport const Countdown = ({\n initialSeconds = 60,\n onResend,\n resending = false,\n}: CountdownProps) => {\n const t = useTranslations('Common');\n const [seconds, setSeconds] = useState(initialSeconds);\n const [isResending, setIsResending] = useState(false);\n\n useEffect(() => {\n if (seconds <= 0) {\n return;\n }\n\n const timer = setInterval(() => {\n setSeconds((prev) => {\n if (prev <= 1) {\n clearInterval(timer);\n return 0;\n }\n return prev - 1;\n });\n }, 1000);\n\n return () => clearInterval(timer);\n }, [seconds]);\n\n const handleResend = async () => {\n setIsResending(true);\n try {\n await onResend();\n setSeconds(initialSeconds);\n } catch (_error) {\n // Error handling is done by parent\n } finally {\n setIsResending(false);\n }\n };\n\n if (seconds > 0) {\n return (\n <Button variant=\"ghost\" disabled>\n {t('resendIn', { seconds })}\n </Button>\n );\n }\n\n return (\n <Button\n variant=\"ghost\"\n onClick={handleResend}\n disabled={isResending || resending}\n >\n {isResending || (resending && <Spinner />)}\n {t('resend')}\n </Button>\n );\n};\n"],"mappings":"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","names":["useTranslations","useState","jsx","Button","Spinner","useTranslations","useEffect","useState","jsx","jsxs","jsx","jsxs","useTranslations","Button","Spinner","jsx","useTranslations","useState"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { A as AuthErrorContent } from '../../handle-error-H0iqQxJ5.js';
|
|
2
3
|
|
|
3
4
|
type ResetPasswordFormValues = {
|
|
4
5
|
code: string;
|
|
@@ -9,8 +10,8 @@ type ResetPasswordFormProps = {
|
|
|
9
10
|
verificationId: string;
|
|
10
11
|
onSubmit: (values: ResetPasswordFormValues) => Promise<void> | void;
|
|
11
12
|
isLoading?: boolean;
|
|
12
|
-
error?: string | null;
|
|
13
|
+
error?: AuthErrorContent | string | null;
|
|
13
14
|
};
|
|
14
|
-
declare const ResetPasswordForm: ({
|
|
15
|
+
declare const ResetPasswordForm: ({ onSubmit, isLoading, }: ResetPasswordFormProps) => react_jsx_runtime.JSX.Element;
|
|
15
16
|
|
|
16
17
|
export { ResetPasswordForm };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
// src/components/reset-password-form.tsx
|
|
3
|
+
// src/components/auth/reset-password-form.tsx
|
|
4
4
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
5
5
|
import { Button } from "@mesob/ui/components/button";
|
|
6
6
|
import {
|
|
@@ -17,17 +17,16 @@ import {
|
|
|
17
17
|
InputOTPGroup,
|
|
18
18
|
InputOTPSlot
|
|
19
19
|
} from "@mesob/ui/components/input-otp";
|
|
20
|
-
import {
|
|
20
|
+
import { Spinner } from "@mesob/ui/components/spinner";
|
|
21
|
+
import { IconEye, IconEyeOff } from "@tabler/icons-react";
|
|
21
22
|
import { useTranslations } from "next-intl";
|
|
22
23
|
import { useMemo, useState } from "react";
|
|
23
24
|
import { useForm } from "react-hook-form";
|
|
24
25
|
import { z } from "zod";
|
|
25
26
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
26
27
|
var ResetPasswordForm = ({
|
|
27
|
-
verificationId,
|
|
28
28
|
onSubmit,
|
|
29
|
-
isLoading = false
|
|
30
|
-
error
|
|
29
|
+
isLoading = false
|
|
31
30
|
}) => {
|
|
32
31
|
const t = useTranslations("Auth.resetPassword");
|
|
33
32
|
const [showPassword, setShowPassword] = useState(false);
|
|
@@ -61,13 +60,13 @@ var ResetPasswordForm = ({
|
|
|
61
60
|
name: "code",
|
|
62
61
|
render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
|
|
63
62
|
/* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(FormLabel, { children: t("form.codeLabel") }) }),
|
|
64
|
-
/* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(InputOTP, { maxLength: 6, ...field, children: /* @__PURE__ */ jsxs(InputOTPGroup, { children: [
|
|
65
|
-
/* @__PURE__ */ jsx(InputOTPSlot, { index: 0 }),
|
|
66
|
-
/* @__PURE__ */ jsx(InputOTPSlot, { index: 1 }),
|
|
67
|
-
/* @__PURE__ */ jsx(InputOTPSlot, { index: 2 }),
|
|
68
|
-
/* @__PURE__ */ jsx(InputOTPSlot, { index: 3 }),
|
|
69
|
-
/* @__PURE__ */ jsx(InputOTPSlot, { index: 4 }),
|
|
70
|
-
/* @__PURE__ */ jsx(InputOTPSlot, { index: 5 })
|
|
63
|
+
/* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx("div", { className: "flex mt-2 justify-center", children: /* @__PURE__ */ jsx(InputOTP, { maxLength: 6, ...field, containerClassName: "gap-4", children: /* @__PURE__ */ jsxs(InputOTPGroup, { className: "gap-3 *:data-[slot=input-otp-slot]:h-12 *:data-[slot=input-otp-slot]:w-12 *:data-[slot=input-otp-slot]:rounded-md *:data-[slot=input-otp-slot]:border *:data-[slot=input-otp-slot]:text-xl", children: [
|
|
64
|
+
/* @__PURE__ */ jsx(InputOTPSlot, { className: "h-12", index: 0 }),
|
|
65
|
+
/* @__PURE__ */ jsx(InputOTPSlot, { className: "h-12", index: 1 }),
|
|
66
|
+
/* @__PURE__ */ jsx(InputOTPSlot, { className: "h-12", index: 2 }),
|
|
67
|
+
/* @__PURE__ */ jsx(InputOTPSlot, { className: "h-12", index: 3 }),
|
|
68
|
+
/* @__PURE__ */ jsx(InputOTPSlot, { className: "h-12", index: 4 }),
|
|
69
|
+
/* @__PURE__ */ jsx(InputOTPSlot, { className: "h-12", index: 5 })
|
|
71
70
|
] }) }) }) }),
|
|
72
71
|
/* @__PURE__ */ jsx(FormMessage, {})
|
|
73
72
|
] })
|
|
@@ -95,7 +94,7 @@ var ResetPasswordForm = ({
|
|
|
95
94
|
type: "button",
|
|
96
95
|
onClick: () => setShowPassword(!showPassword),
|
|
97
96
|
className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
|
|
98
|
-
children: showPassword ? /* @__PURE__ */ jsx(
|
|
97
|
+
children: showPassword ? /* @__PURE__ */ jsx(IconEyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(IconEye, { className: "h-4 w-4" })
|
|
99
98
|
}
|
|
100
99
|
)
|
|
101
100
|
] }) }),
|
|
@@ -125,7 +124,7 @@ var ResetPasswordForm = ({
|
|
|
125
124
|
type: "button",
|
|
126
125
|
onClick: () => setShowPassword(!showPassword),
|
|
127
126
|
className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
|
|
128
|
-
children: showPassword ? /* @__PURE__ */ jsx(
|
|
127
|
+
children: showPassword ? /* @__PURE__ */ jsx(IconEyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(IconEye, { className: "h-4 w-4" })
|
|
129
128
|
}
|
|
130
129
|
)
|
|
131
130
|
] }) }),
|
|
@@ -133,7 +132,10 @@ var ResetPasswordForm = ({
|
|
|
133
132
|
] })
|
|
134
133
|
}
|
|
135
134
|
),
|
|
136
|
-
/* @__PURE__ */
|
|
135
|
+
/* @__PURE__ */ jsxs(Button, { type: "submit", className: "w-full", disabled: isLoading, children: [
|
|
136
|
+
isLoading && /* @__PURE__ */ jsx(Spinner, {}),
|
|
137
|
+
isLoading ? t("form.submitting") : t("form.submit")
|
|
138
|
+
] })
|
|
137
139
|
] }) });
|
|
138
140
|
};
|
|
139
141
|
export {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/auth/reset-password-form.tsx"],"sourcesContent":["'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Button } from '@mesob/ui/components/button';\nimport {\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n} from '@mesob/ui/components/form';\nimport { Input } from '@mesob/ui/components/input';\nimport {\n InputOTP,\n InputOTPGroup,\n InputOTPSlot,\n} from '@mesob/ui/components/input-otp';\nimport { Spinner } from '@mesob/ui/components/spinner';\nimport { IconEye, IconEyeOff } from '@tabler/icons-react';\nimport { useTranslations } from 'next-intl';\nimport { useMemo, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { z } from 'zod';\nimport type { AuthErrorContent } from '../../utils/handle-error';\n\ntype ResetPasswordFormValues = {\n code: string;\n password: string;\n confirmPassword: string;\n};\n\ntype ResetPasswordFormProps = {\n verificationId: string;\n onSubmit: (values: ResetPasswordFormValues) => Promise<void> | void;\n isLoading?: boolean;\n error?: AuthErrorContent | string | null;\n};\n\nexport const ResetPasswordForm = ({\n onSubmit,\n isLoading = false,\n}: ResetPasswordFormProps) => {\n const t = useTranslations('Auth.resetPassword');\n const [showPassword, setShowPassword] = useState(false);\n const resetPasswordSchema = useMemo(\n () =>\n z\n .object({\n code: z.string().length(6, t('errors.codeLength')),\n password: z.string().min(8, t('errors.passwordLength')),\n confirmPassword: z.string(),\n })\n .refine((data) => data.password === data.confirmPassword, {\n message: t('errors.passwordsMismatch'),\n path: ['confirmPassword'],\n }),\n [t],\n );\n\n const form = useForm<ResetPasswordFormValues>({\n resolver: zodResolver(resetPasswordSchema),\n defaultValues: {\n code: '',\n password: '',\n confirmPassword: '',\n },\n });\n\n const handleSubmit = form.handleSubmit(async (values) => {\n await onSubmit(values);\n });\n\n return (\n <Form {...form}>\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n <FormField\n control={form.control}\n name=\"code\"\n render={({ field }) => (\n <FormItem>\n <div className=\"flex justify-center\">\n <FormLabel>{t('form.codeLabel')}</FormLabel>\n </div>\n <FormControl>\n <div className=\"flex mt-2 justify-center\">\n <InputOTP maxLength={6} {...field} containerClassName=\"gap-4\">\n <InputOTPGroup className=\"gap-3 *:data-[slot=input-otp-slot]:h-12 *:data-[slot=input-otp-slot]:w-12 *:data-[slot=input-otp-slot]:rounded-md *:data-[slot=input-otp-slot]:border *:data-[slot=input-otp-slot]:text-xl\">\n <InputOTPSlot className=\"h-12\" index={0} />\n <InputOTPSlot className=\"h-12\" index={1} />\n <InputOTPSlot className=\"h-12\" index={2} />\n <InputOTPSlot className=\"h-12\" index={3} />\n <InputOTPSlot className=\"h-12\" index={4} />\n <InputOTPSlot className=\"h-12\" index={5} />\n </InputOTPGroup>\n </InputOTP>\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n <FormField\n control={form.control}\n name=\"password\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.passwordLabel')}</FormLabel>\n <FormControl>\n <div className=\"relative\">\n <Input\n type={showPassword ? 'text' : 'password'}\n placeholder={t('form.passwordPlaceholder')}\n {...field}\n />\n <button\n type=\"button\"\n onClick={() => setShowPassword(!showPassword)}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground\"\n >\n {showPassword ? (\n <IconEyeOff className=\"h-4 w-4\" />\n ) : (\n <IconEye className=\"h-4 w-4\" />\n )}\n </button>\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n <FormField\n control={form.control}\n name=\"confirmPassword\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.confirmPasswordLabel')}</FormLabel>\n <FormControl>\n <div className=\"relative\">\n <Input\n type={showPassword ? 'text' : 'password'}\n placeholder={t('form.passwordPlaceholder')}\n {...field}\n />\n <button\n type=\"button\"\n onClick={() => setShowPassword(!showPassword)}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground\"\n >\n {showPassword ? (\n <IconEyeOff className=\"h-4 w-4\" />\n ) : (\n <IconEye className=\"h-4 w-4\" />\n )}\n </button>\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n <Button type=\"submit\" className=\"w-full\" disabled={isLoading}>\n {isLoading && <Spinner />}\n {isLoading ? t('form.submitting') : t('form.submit')}\n </Button>\n </form>\n </Form>\n );\n};\n"],"mappings":"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","names":[]}
|