@questpie/admin 0.0.1 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +439 -424
- package/dist/auth-layout-M8K8_q5R.mjs +181 -0
- package/dist/auth-layout-M8K8_q5R.mjs.map +1 -0
- package/dist/bulk-upload-dialog-D7w7W1Hl.mjs +273 -0
- package/dist/bulk-upload-dialog-D7w7W1Hl.mjs.map +1 -0
- package/dist/{components/ui/card.mjs → card-BKHjBQfw.mjs} +8 -8
- package/dist/card-BKHjBQfw.mjs.map +1 -0
- package/dist/client/styles/index.css +434 -0
- package/dist/client-DbpZKSgH.d.mts +13585 -0
- package/dist/client-DbpZKSgH.d.mts.map +1 -0
- package/dist/client-njX1rZmi.mjs +22612 -0
- package/dist/client-njX1rZmi.mjs.map +1 -0
- package/dist/client.d.mts +3 -0
- package/dist/client.mjs +13 -0
- package/dist/content-locales-provider-BXvuIgfg.mjs +1650 -0
- package/dist/content-locales-provider-BXvuIgfg.mjs.map +1 -0
- package/dist/dashboard-page-B4PGEdc2.mjs +2500 -0
- package/dist/dashboard-page-B4PGEdc2.mjs.map +1 -0
- package/dist/dashboard-page-mCY0pgZv.mjs +3 -0
- package/dist/dropzone-Do3awXKd.mjs +634 -0
- package/dist/dropzone-Do3awXKd.mjs.map +1 -0
- package/dist/{views/auth/forgot-password-form.mjs → forgot-password-page-Bcp-An4Y.mjs} +87 -14
- package/dist/forgot-password-page-Bcp-An4Y.mjs.map +1 -0
- package/dist/forgot-password-page-CEwsdLwn.mjs +3 -0
- package/dist/index-B9Xwk4hi.d.mts +2753 -0
- package/dist/index-B9Xwk4hi.d.mts.map +1 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +13 -0
- package/dist/login-page-BUnpCbCa.mjs +3 -0
- package/dist/login-page-CP4gA-dl.mjs +298 -0
- package/dist/login-page-CP4gA-dl.mjs.map +1 -0
- package/dist/preview-utils-BKQ9-TMa.mjs +65 -0
- package/dist/preview-utils-BKQ9-TMa.mjs.map +1 -0
- package/dist/{views/auth/reset-password-form.mjs → reset-password-page-BqfDmLxA.mjs} +111 -14
- package/dist/reset-password-page-BqfDmLxA.mjs.map +1 -0
- package/dist/reset-password-page-CufHz3h3.mjs +3 -0
- package/dist/runtime-6VZM878K.mjs +69 -0
- package/dist/runtime-6VZM878K.mjs.map +1 -0
- package/dist/saved-views.types-BMsz5mCy.d.mts +42 -0
- package/dist/saved-views.types-BMsz5mCy.d.mts.map +1 -0
- package/dist/server.d.mts +250 -0
- package/dist/server.d.mts.map +1 -0
- package/dist/server.mjs +832 -0
- package/dist/server.mjs.map +1 -0
- package/dist/setup-page-BNNzt_Z6.mjs +3 -0
- package/dist/setup-page-YAP_fzqh.mjs +264 -0
- package/dist/setup-page-YAP_fzqh.mjs.map +1 -0
- package/dist/shared.d.mts +57 -0
- package/dist/shared.d.mts.map +1 -0
- package/dist/shared.mjs +3 -0
- package/dist/{hooks/use-auth.mjs → use-auth-BoLmWtmU.mjs} +42 -30
- package/dist/use-auth-BoLmWtmU.mjs.map +1 -0
- package/package.json +48 -198
- package/.turbo/turbo-build.log +0 -108
- package/CHANGELOG.md +0 -10
- package/STATUS.md +0 -917
- package/VALIDATION.md +0 -602
- package/components.json +0 -24
- package/dist/__tests__/setup.mjs +0 -38
- package/dist/__tests__/test-utils.mjs +0 -45
- package/dist/__tests__/vitest.d.mjs +0 -3
- package/dist/components/admin-app.mjs +0 -69
- package/dist/components/fields/array-field.mjs +0 -190
- package/dist/components/fields/checkbox-field.mjs +0 -34
- package/dist/components/fields/custom-field.mjs +0 -32
- package/dist/components/fields/date-field.mjs +0 -41
- package/dist/components/fields/datetime-field.mjs +0 -42
- package/dist/components/fields/email-field.mjs +0 -37
- package/dist/components/fields/embedded-collection.mjs +0 -253
- package/dist/components/fields/field-types.mjs +0 -1
- package/dist/components/fields/field-utils.mjs +0 -10
- package/dist/components/fields/field-wrapper.mjs +0 -34
- package/dist/components/fields/index.mjs +0 -23
- package/dist/components/fields/json-field.mjs +0 -243
- package/dist/components/fields/locale-badge.mjs +0 -16
- package/dist/components/fields/number-field.mjs +0 -39
- package/dist/components/fields/password-field.mjs +0 -37
- package/dist/components/fields/relation-field.mjs +0 -104
- package/dist/components/fields/relation-picker.mjs +0 -229
- package/dist/components/fields/relation-select.mjs +0 -188
- package/dist/components/fields/rich-text-editor/index.mjs +0 -897
- package/dist/components/fields/select-field.mjs +0 -41
- package/dist/components/fields/switch-field.mjs +0 -34
- package/dist/components/fields/text-field.mjs +0 -38
- package/dist/components/fields/textarea-field.mjs +0 -38
- package/dist/components/index.mjs +0 -59
- package/dist/components/primitives/checkbox-input.mjs +0 -127
- package/dist/components/primitives/date-input.mjs +0 -303
- package/dist/components/primitives/index.mjs +0 -12
- package/dist/components/primitives/number-input.mjs +0 -104
- package/dist/components/primitives/select-input.mjs +0 -177
- package/dist/components/primitives/tag-input.mjs +0 -135
- package/dist/components/primitives/text-input.mjs +0 -39
- package/dist/components/primitives/textarea-input.mjs +0 -37
- package/dist/components/primitives/toggle-input.mjs +0 -31
- package/dist/components/primitives/types.mjs +0 -12
- package/dist/components/ui/accordion.mjs +0 -55
- package/dist/components/ui/avatar.mjs +0 -54
- package/dist/components/ui/badge.mjs +0 -34
- package/dist/components/ui/button.mjs +0 -48
- package/dist/components/ui/checkbox.mjs +0 -21
- package/dist/components/ui/combobox.mjs +0 -163
- package/dist/components/ui/dialog.mjs +0 -95
- package/dist/components/ui/dropdown-menu.mjs +0 -138
- package/dist/components/ui/field.mjs +0 -113
- package/dist/components/ui/input-group.mjs +0 -82
- package/dist/components/ui/input.mjs +0 -17
- package/dist/components/ui/label.mjs +0 -15
- package/dist/components/ui/popover.mjs +0 -56
- package/dist/components/ui/scroll-area.mjs +0 -38
- package/dist/components/ui/select.mjs +0 -100
- package/dist/components/ui/separator.mjs +0 -16
- package/dist/components/ui/sheet.mjs +0 -90
- package/dist/components/ui/sidebar.mjs +0 -387
- package/dist/components/ui/skeleton.mjs +0 -14
- package/dist/components/ui/spinner.mjs +0 -16
- package/dist/components/ui/switch.mjs +0 -22
- package/dist/components/ui/table.mjs +0 -68
- package/dist/components/ui/tabs.mjs +0 -48
- package/dist/components/ui/textarea.mjs +0 -15
- package/dist/components/ui/tooltip.mjs +0 -44
- package/dist/config/component-registry.mjs +0 -38
- package/dist/config/index.mjs +0 -129
- package/dist/hooks/admin-provider.mjs +0 -70
- package/dist/hooks/index.mjs +0 -7
- package/dist/hooks/store.mjs +0 -178
- package/dist/hooks/use-collection-db.mjs +0 -146
- package/dist/hooks/use-collection.mjs +0 -112
- package/dist/hooks/use-global.mjs +0 -46
- package/dist/hooks/use-mobile.mjs +0 -20
- package/dist/lib/utils.mjs +0 -10
- package/dist/styles/index.css +0 -336
- package/dist/styles/index.mjs +0 -1
- package/dist/utils/index.mjs +0 -9
- package/dist/views/auth/auth-layout.mjs +0 -52
- package/dist/views/auth/index.mjs +0 -6
- package/dist/views/auth/login-form.mjs +0 -156
- package/dist/views/collection/auto-form-fields.mjs +0 -525
- package/dist/views/collection/collection-form.mjs +0 -91
- package/dist/views/collection/collection-list.mjs +0 -76
- package/dist/views/collection/form-field.mjs +0 -42
- package/dist/views/collection/index.mjs +0 -6
- package/dist/views/common/index.mjs +0 -4
- package/dist/views/common/locale-switcher.mjs +0 -39
- package/dist/views/common/version-history.mjs +0 -272
- package/dist/views/index.mjs +0 -9
- package/dist/views/layout/admin-layout.mjs +0 -40
- package/dist/views/layout/admin-router.mjs +0 -95
- package/dist/views/layout/admin-sidebar.mjs +0 -63
- package/dist/views/layout/index.mjs +0 -5
- package/src/__tests__/setup.ts +0 -44
- package/src/__tests__/test-utils.tsx +0 -49
- package/src/__tests__/vitest.d.ts +0 -9
- package/src/components/admin-app.tsx +0 -221
- package/src/components/fields/array-field.tsx +0 -237
- package/src/components/fields/checkbox-field.tsx +0 -47
- package/src/components/fields/custom-field.tsx +0 -50
- package/src/components/fields/date-field.tsx +0 -65
- package/src/components/fields/datetime-field.tsx +0 -67
- package/src/components/fields/email-field.tsx +0 -51
- package/src/components/fields/embedded-collection.tsx +0 -315
- package/src/components/fields/field-types.ts +0 -162
- package/src/components/fields/field-utils.ts +0 -6
- package/src/components/fields/field-wrapper.tsx +0 -52
- package/src/components/fields/index.ts +0 -66
- package/src/components/fields/json-field.tsx +0 -440
- package/src/components/fields/locale-badge.tsx +0 -15
- package/src/components/fields/number-field.tsx +0 -57
- package/src/components/fields/password-field.tsx +0 -51
- package/src/components/fields/relation-field.tsx +0 -243
- package/src/components/fields/relation-picker.tsx +0 -402
- package/src/components/fields/relation-select.tsx +0 -327
- package/src/components/fields/rich-text-editor/index.tsx +0 -1337
- package/src/components/fields/select-field.tsx +0 -61
- package/src/components/fields/switch-field.tsx +0 -47
- package/src/components/fields/text-field.tsx +0 -55
- package/src/components/fields/textarea-field.tsx +0 -55
- package/src/components/index.ts +0 -40
- package/src/components/primitives/checkbox-input.tsx +0 -193
- package/src/components/primitives/date-input.tsx +0 -401
- package/src/components/primitives/index.ts +0 -24
- package/src/components/primitives/number-input.tsx +0 -132
- package/src/components/primitives/select-input.tsx +0 -296
- package/src/components/primitives/tag-input.tsx +0 -200
- package/src/components/primitives/text-input.tsx +0 -49
- package/src/components/primitives/textarea-input.tsx +0 -46
- package/src/components/primitives/toggle-input.tsx +0 -36
- package/src/components/primitives/types.ts +0 -235
- package/src/components/ui/accordion.tsx +0 -72
- package/src/components/ui/avatar.tsx +0 -106
- package/src/components/ui/badge.tsx +0 -48
- package/src/components/ui/button.tsx +0 -53
- package/src/components/ui/card.tsx +0 -94
- package/src/components/ui/checkbox.tsx +0 -27
- package/src/components/ui/combobox.tsx +0 -290
- package/src/components/ui/dialog.tsx +0 -151
- package/src/components/ui/dropdown-menu.tsx +0 -254
- package/src/components/ui/field.tsx +0 -227
- package/src/components/ui/input-group.tsx +0 -149
- package/src/components/ui/input.tsx +0 -20
- package/src/components/ui/label.tsx +0 -18
- package/src/components/ui/popover.tsx +0 -88
- package/src/components/ui/scroll-area.tsx +0 -53
- package/src/components/ui/select.tsx +0 -192
- package/src/components/ui/separator.tsx +0 -23
- package/src/components/ui/sheet.tsx +0 -127
- package/src/components/ui/sidebar.tsx +0 -723
- package/src/components/ui/skeleton.tsx +0 -13
- package/src/components/ui/spinner.tsx +0 -10
- package/src/components/ui/switch.tsx +0 -32
- package/src/components/ui/table.tsx +0 -99
- package/src/components/ui/tabs.tsx +0 -82
- package/src/components/ui/textarea.tsx +0 -18
- package/src/components/ui/tooltip.tsx +0 -70
- package/src/config/component-registry.ts +0 -190
- package/src/config/index.ts +0 -1099
- package/src/hooks/README.md +0 -269
- package/src/hooks/admin-provider.tsx +0 -110
- package/src/hooks/index.ts +0 -41
- package/src/hooks/store.ts +0 -248
- package/src/hooks/use-auth.ts +0 -168
- package/src/hooks/use-collection-db.ts +0 -209
- package/src/hooks/use-collection.ts +0 -156
- package/src/hooks/use-global.ts +0 -69
- package/src/hooks/use-mobile.ts +0 -21
- package/src/lib/utils.ts +0 -6
- package/src/styles/index.css +0 -340
- package/src/utils/index.ts +0 -6
- package/src/views/auth/auth-layout.tsx +0 -77
- package/src/views/auth/forgot-password-form.tsx +0 -192
- package/src/views/auth/index.ts +0 -21
- package/src/views/auth/login-form.tsx +0 -229
- package/src/views/auth/reset-password-form.tsx +0 -232
- package/src/views/collection/auto-form-fields.tsx +0 -982
- package/src/views/collection/collection-form.tsx +0 -186
- package/src/views/collection/collection-list.tsx +0 -223
- package/src/views/collection/form-field.tsx +0 -52
- package/src/views/collection/index.ts +0 -15
- package/src/views/common/index.ts +0 -8
- package/src/views/common/locale-switcher.tsx +0 -45
- package/src/views/common/version-history.tsx +0 -406
- package/src/views/index.ts +0 -25
- package/src/views/layout/admin-layout.tsx +0 -117
- package/src/views/layout/admin-router.tsx +0 -206
- package/src/views/layout/admin-sidebar.tsx +0 -185
- package/src/views/layout/index.ts +0 -12
- package/tsconfig.json +0 -13
- package/tsconfig.tsbuildinfo +0 -1
- package/tsdown.config.ts +0 -13
- package/vitest.config.ts +0 -29
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Login Form - email/password authentication
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import * as React from "react";
|
|
6
|
-
import { useForm } from "react-hook-form";
|
|
7
|
-
import { Envelope, Lock, SpinnerGap } from "@phosphor-icons/react";
|
|
8
|
-
import { Button } from "../../components/ui/button";
|
|
9
|
-
import { Input } from "../../components/ui/input";
|
|
10
|
-
import {
|
|
11
|
-
Field,
|
|
12
|
-
FieldContent,
|
|
13
|
-
FieldDescription,
|
|
14
|
-
FieldError,
|
|
15
|
-
FieldGroup,
|
|
16
|
-
FieldLabel,
|
|
17
|
-
} from "../../components/ui/field";
|
|
18
|
-
import { cn } from "../../lib/utils";
|
|
19
|
-
|
|
20
|
-
export type LoginFormValues = {
|
|
21
|
-
email: string;
|
|
22
|
-
password: string;
|
|
23
|
-
rememberMe?: boolean;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export type LoginFormProps = {
|
|
27
|
-
/** Called when form is submitted with valid data */
|
|
28
|
-
onSubmit: (values: LoginFormValues) => Promise<void>;
|
|
29
|
-
/** Called when sign up link is clicked */
|
|
30
|
-
onSignUpClick?: () => void;
|
|
31
|
-
/** Called when forgot password link is clicked */
|
|
32
|
-
onForgotPasswordClick?: () => void;
|
|
33
|
-
/** Show remember me checkbox */
|
|
34
|
-
showRememberMe?: boolean;
|
|
35
|
-
/** Show sign up link */
|
|
36
|
-
showSignUp?: boolean;
|
|
37
|
-
/** Show forgot password link */
|
|
38
|
-
showForgotPassword?: boolean;
|
|
39
|
-
/** Default values */
|
|
40
|
-
defaultValues?: Partial<LoginFormValues>;
|
|
41
|
-
/** Additional class name */
|
|
42
|
-
className?: string;
|
|
43
|
-
/** Error message from auth */
|
|
44
|
-
error?: string | null;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Login form with email and password fields
|
|
49
|
-
*
|
|
50
|
-
* @example
|
|
51
|
-
* ```tsx
|
|
52
|
-
* const authClient = createAdminAuthClient<typeof cms>({ baseURL: '...' })
|
|
53
|
-
*
|
|
54
|
-
* function LoginPage() {
|
|
55
|
-
* const [error, setError] = useState<string | null>(null)
|
|
56
|
-
*
|
|
57
|
-
* const handleLogin = async (values: LoginFormValues) => {
|
|
58
|
-
* const result = await authClient.signIn.email({
|
|
59
|
-
* email: values.email,
|
|
60
|
-
* password: values.password,
|
|
61
|
-
* })
|
|
62
|
-
* if (result.error) {
|
|
63
|
-
* setError(result.error.message)
|
|
64
|
-
* }
|
|
65
|
-
* }
|
|
66
|
-
*
|
|
67
|
-
* return (
|
|
68
|
-
* <AuthLayout title="Sign in">
|
|
69
|
-
* <LoginForm onSubmit={handleLogin} error={error} />
|
|
70
|
-
* </AuthLayout>
|
|
71
|
-
* )
|
|
72
|
-
* }
|
|
73
|
-
* ```
|
|
74
|
-
*/
|
|
75
|
-
export function LoginForm({
|
|
76
|
-
onSubmit,
|
|
77
|
-
onSignUpClick,
|
|
78
|
-
onForgotPasswordClick,
|
|
79
|
-
showRememberMe = false,
|
|
80
|
-
showSignUp = true,
|
|
81
|
-
showForgotPassword = true,
|
|
82
|
-
defaultValues,
|
|
83
|
-
className,
|
|
84
|
-
error,
|
|
85
|
-
}: LoginFormProps) {
|
|
86
|
-
const {
|
|
87
|
-
register,
|
|
88
|
-
handleSubmit,
|
|
89
|
-
formState: { errors, isSubmitting },
|
|
90
|
-
} = useForm<LoginFormValues>({
|
|
91
|
-
defaultValues: {
|
|
92
|
-
email: "",
|
|
93
|
-
password: "",
|
|
94
|
-
rememberMe: false,
|
|
95
|
-
...defaultValues,
|
|
96
|
-
},
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
const handleFormSubmit = handleSubmit(async (values) => {
|
|
100
|
-
await onSubmit(values);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
return (
|
|
104
|
-
<form onSubmit={handleFormSubmit} className={cn("space-y-4", className)}>
|
|
105
|
-
<FieldGroup>
|
|
106
|
-
{/* Email Field */}
|
|
107
|
-
<Field data-invalid={!!errors.email}>
|
|
108
|
-
<FieldLabel htmlFor="email">Email</FieldLabel>
|
|
109
|
-
<FieldContent>
|
|
110
|
-
<div className="relative">
|
|
111
|
-
<Envelope
|
|
112
|
-
className="text-muted-foreground absolute left-2 top-1/2 size-4 -translate-y-1/2"
|
|
113
|
-
weight="duotone"
|
|
114
|
-
/>
|
|
115
|
-
<Input
|
|
116
|
-
id="email"
|
|
117
|
-
type="email"
|
|
118
|
-
placeholder="you@example.com"
|
|
119
|
-
className="pl-8"
|
|
120
|
-
autoComplete="email"
|
|
121
|
-
aria-invalid={!!errors.email}
|
|
122
|
-
{...register("email", {
|
|
123
|
-
required: "Email is required",
|
|
124
|
-
pattern: {
|
|
125
|
-
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
|
126
|
-
message: "Invalid email address",
|
|
127
|
-
},
|
|
128
|
-
})}
|
|
129
|
-
/>
|
|
130
|
-
</div>
|
|
131
|
-
<FieldError>{errors.email?.message}</FieldError>
|
|
132
|
-
</FieldContent>
|
|
133
|
-
</Field>
|
|
134
|
-
|
|
135
|
-
{/* Password Field */}
|
|
136
|
-
<Field data-invalid={!!errors.password}>
|
|
137
|
-
<FieldLabel htmlFor="password">Password</FieldLabel>
|
|
138
|
-
<FieldContent>
|
|
139
|
-
<div className="relative">
|
|
140
|
-
<Lock
|
|
141
|
-
className="text-muted-foreground absolute left-2 top-1/2 size-4 -translate-y-1/2"
|
|
142
|
-
weight="duotone"
|
|
143
|
-
/>
|
|
144
|
-
<Input
|
|
145
|
-
id="password"
|
|
146
|
-
type="password"
|
|
147
|
-
placeholder="Enter your password"
|
|
148
|
-
className="pl-8"
|
|
149
|
-
autoComplete="current-password"
|
|
150
|
-
aria-invalid={!!errors.password}
|
|
151
|
-
{...register("password", {
|
|
152
|
-
required: "Password is required",
|
|
153
|
-
minLength: {
|
|
154
|
-
value: 6,
|
|
155
|
-
message: "Password must be at least 6 characters",
|
|
156
|
-
},
|
|
157
|
-
})}
|
|
158
|
-
/>
|
|
159
|
-
</div>
|
|
160
|
-
<FieldError>{errors.password?.message}</FieldError>
|
|
161
|
-
</FieldContent>
|
|
162
|
-
</Field>
|
|
163
|
-
|
|
164
|
-
{/* Remember Me & Forgot Password */}
|
|
165
|
-
{(showRememberMe || showForgotPassword) && (
|
|
166
|
-
<div className="flex items-center justify-between">
|
|
167
|
-
{showRememberMe && (
|
|
168
|
-
<label className="text-muted-foreground flex items-center gap-2 text-xs">
|
|
169
|
-
<input
|
|
170
|
-
type="checkbox"
|
|
171
|
-
className="rounded border-gray-300"
|
|
172
|
-
{...register("rememberMe")}
|
|
173
|
-
/>
|
|
174
|
-
Remember me
|
|
175
|
-
</label>
|
|
176
|
-
)}
|
|
177
|
-
{showForgotPassword && (
|
|
178
|
-
<button
|
|
179
|
-
type="button"
|
|
180
|
-
onClick={onForgotPasswordClick}
|
|
181
|
-
className="text-primary text-xs hover:underline"
|
|
182
|
-
>
|
|
183
|
-
Forgot password?
|
|
184
|
-
</button>
|
|
185
|
-
)}
|
|
186
|
-
</div>
|
|
187
|
-
)}
|
|
188
|
-
</FieldGroup>
|
|
189
|
-
|
|
190
|
-
{/* Error Message */}
|
|
191
|
-
{error && (
|
|
192
|
-
<div className="bg-destructive/10 text-destructive rounded-md p-3 text-xs">
|
|
193
|
-
{error}
|
|
194
|
-
</div>
|
|
195
|
-
)}
|
|
196
|
-
|
|
197
|
-
{/* Submit Button */}
|
|
198
|
-
<Button
|
|
199
|
-
type="submit"
|
|
200
|
-
className="w-full"
|
|
201
|
-
size="lg"
|
|
202
|
-
disabled={isSubmitting}
|
|
203
|
-
>
|
|
204
|
-
{isSubmitting ? (
|
|
205
|
-
<>
|
|
206
|
-
<SpinnerGap className="animate-spin" weight="bold" />
|
|
207
|
-
Signing in...
|
|
208
|
-
</>
|
|
209
|
-
) : (
|
|
210
|
-
"Sign in"
|
|
211
|
-
)}
|
|
212
|
-
</Button>
|
|
213
|
-
|
|
214
|
-
{/* Sign Up Link */}
|
|
215
|
-
{showSignUp && (
|
|
216
|
-
<p className="text-muted-foreground text-center text-xs">
|
|
217
|
-
Don't have an account?{" "}
|
|
218
|
-
<button
|
|
219
|
-
type="button"
|
|
220
|
-
onClick={onSignUpClick}
|
|
221
|
-
className="text-primary hover:underline"
|
|
222
|
-
>
|
|
223
|
-
Sign up
|
|
224
|
-
</button>
|
|
225
|
-
</p>
|
|
226
|
-
)}
|
|
227
|
-
</form>
|
|
228
|
-
);
|
|
229
|
-
}
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reset Password Form - set new password with token
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import * as React from "react";
|
|
6
|
-
import { useForm } from "react-hook-form";
|
|
7
|
-
import { Lock, SpinnerGap, CheckCircle } from "@phosphor-icons/react";
|
|
8
|
-
import { Button } from "../../components/ui/button";
|
|
9
|
-
import { Input } from "../../components/ui/input";
|
|
10
|
-
import {
|
|
11
|
-
Field,
|
|
12
|
-
FieldContent,
|
|
13
|
-
FieldDescription,
|
|
14
|
-
FieldError,
|
|
15
|
-
FieldGroup,
|
|
16
|
-
FieldLabel,
|
|
17
|
-
} from "../../components/ui/field";
|
|
18
|
-
import { cn } from "../../lib/utils";
|
|
19
|
-
|
|
20
|
-
export type ResetPasswordFormValues = {
|
|
21
|
-
password: string;
|
|
22
|
-
confirmPassword: string;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export type ResetPasswordFormProps = {
|
|
26
|
-
/** Reset token from URL */
|
|
27
|
-
token: string;
|
|
28
|
-
/** Called when form is submitted with valid data */
|
|
29
|
-
onSubmit: (
|
|
30
|
-
values: ResetPasswordFormValues & { token: string },
|
|
31
|
-
) => Promise<void>;
|
|
32
|
-
/** Called when back to login link is clicked */
|
|
33
|
-
onBackToLoginClick?: () => void;
|
|
34
|
-
/** Minimum password length */
|
|
35
|
-
minPasswordLength?: number;
|
|
36
|
-
/** Additional class name */
|
|
37
|
-
className?: string;
|
|
38
|
-
/** Error message from auth */
|
|
39
|
-
error?: string | null;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Reset password form with password confirmation
|
|
44
|
-
*
|
|
45
|
-
* @example
|
|
46
|
-
* ```tsx
|
|
47
|
-
* const authClient = createAdminAuthClient<typeof cms>({ baseURL: '...' })
|
|
48
|
-
*
|
|
49
|
-
* function ResetPasswordPage() {
|
|
50
|
-
* const token = useSearchParams().get('token')
|
|
51
|
-
* const [error, setError] = useState<string | null>(null)
|
|
52
|
-
*
|
|
53
|
-
* const handleSubmit = async (values) => {
|
|
54
|
-
* const result = await authClient.resetPassword({
|
|
55
|
-
* token: values.token,
|
|
56
|
-
* newPassword: values.password,
|
|
57
|
-
* })
|
|
58
|
-
* if (result.error) {
|
|
59
|
-
* setError(result.error.message)
|
|
60
|
-
* }
|
|
61
|
-
* }
|
|
62
|
-
*
|
|
63
|
-
* return (
|
|
64
|
-
* <AuthLayout title="Reset password">
|
|
65
|
-
* <ResetPasswordForm token={token} onSubmit={handleSubmit} error={error} />
|
|
66
|
-
* </AuthLayout>
|
|
67
|
-
* )
|
|
68
|
-
* }
|
|
69
|
-
* ```
|
|
70
|
-
*/
|
|
71
|
-
export function ResetPasswordForm({
|
|
72
|
-
token,
|
|
73
|
-
onSubmit,
|
|
74
|
-
onBackToLoginClick,
|
|
75
|
-
minPasswordLength = 8,
|
|
76
|
-
className,
|
|
77
|
-
error,
|
|
78
|
-
}: ResetPasswordFormProps) {
|
|
79
|
-
const [isSuccess, setIsSuccess] = React.useState(false);
|
|
80
|
-
|
|
81
|
-
const {
|
|
82
|
-
register,
|
|
83
|
-
handleSubmit,
|
|
84
|
-
watch,
|
|
85
|
-
formState: { errors, isSubmitting },
|
|
86
|
-
} = useForm<ResetPasswordFormValues>({
|
|
87
|
-
defaultValues: {
|
|
88
|
-
password: "",
|
|
89
|
-
confirmPassword: "",
|
|
90
|
-
},
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
const password = watch("password");
|
|
94
|
-
|
|
95
|
-
const handleFormSubmit = handleSubmit(async (values) => {
|
|
96
|
-
await onSubmit({ ...values, token });
|
|
97
|
-
if (!error) {
|
|
98
|
-
setIsSuccess(true);
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
// Success state
|
|
103
|
-
if (isSuccess) {
|
|
104
|
-
return (
|
|
105
|
-
<div className={cn("space-y-4 text-center", className)}>
|
|
106
|
-
<div className="bg-primary/10 mx-auto flex size-12 items-center justify-center rounded-full">
|
|
107
|
-
<CheckCircle className="text-primary size-6" weight="duotone" />
|
|
108
|
-
</div>
|
|
109
|
-
<div className="space-y-2">
|
|
110
|
-
<h3 className="text-sm font-medium">Password reset successful</h3>
|
|
111
|
-
<p className="text-muted-foreground text-xs">
|
|
112
|
-
Your password has been reset successfully. You can now sign in with
|
|
113
|
-
your new password.
|
|
114
|
-
</p>
|
|
115
|
-
</div>
|
|
116
|
-
<Button
|
|
117
|
-
type="button"
|
|
118
|
-
className="w-full"
|
|
119
|
-
size="lg"
|
|
120
|
-
onClick={onBackToLoginClick}
|
|
121
|
-
>
|
|
122
|
-
Sign in
|
|
123
|
-
</Button>
|
|
124
|
-
</div>
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return (
|
|
129
|
-
<form onSubmit={handleFormSubmit} className={cn("space-y-4", className)}>
|
|
130
|
-
<p className="text-muted-foreground text-xs">
|
|
131
|
-
Enter your new password below.
|
|
132
|
-
</p>
|
|
133
|
-
|
|
134
|
-
<FieldGroup>
|
|
135
|
-
{/* Password Field */}
|
|
136
|
-
<Field data-invalid={!!errors.password}>
|
|
137
|
-
<FieldLabel htmlFor="password">New password</FieldLabel>
|
|
138
|
-
<FieldContent>
|
|
139
|
-
<div className="relative">
|
|
140
|
-
<Lock
|
|
141
|
-
className="text-muted-foreground absolute left-2 top-1/2 size-4 -translate-y-1/2"
|
|
142
|
-
weight="duotone"
|
|
143
|
-
/>
|
|
144
|
-
<Input
|
|
145
|
-
id="password"
|
|
146
|
-
type="password"
|
|
147
|
-
placeholder="Enter new password"
|
|
148
|
-
className="pl-8"
|
|
149
|
-
autoComplete="new-password"
|
|
150
|
-
aria-invalid={!!errors.password}
|
|
151
|
-
{...register("password", {
|
|
152
|
-
required: "Password is required",
|
|
153
|
-
minLength: {
|
|
154
|
-
value: minPasswordLength,
|
|
155
|
-
message: `Password must be at least ${minPasswordLength} characters`,
|
|
156
|
-
},
|
|
157
|
-
})}
|
|
158
|
-
/>
|
|
159
|
-
</div>
|
|
160
|
-
<FieldDescription>
|
|
161
|
-
Must be at least {minPasswordLength} characters
|
|
162
|
-
</FieldDescription>
|
|
163
|
-
<FieldError>{errors.password?.message}</FieldError>
|
|
164
|
-
</FieldContent>
|
|
165
|
-
</Field>
|
|
166
|
-
|
|
167
|
-
{/* Confirm Password Field */}
|
|
168
|
-
<Field data-invalid={!!errors.confirmPassword}>
|
|
169
|
-
<FieldLabel htmlFor="confirmPassword">Confirm password</FieldLabel>
|
|
170
|
-
<FieldContent>
|
|
171
|
-
<div className="relative">
|
|
172
|
-
<Lock
|
|
173
|
-
className="text-muted-foreground absolute left-2 top-1/2 size-4 -translate-y-1/2"
|
|
174
|
-
weight="duotone"
|
|
175
|
-
/>
|
|
176
|
-
<Input
|
|
177
|
-
id="confirmPassword"
|
|
178
|
-
type="password"
|
|
179
|
-
placeholder="Confirm new password"
|
|
180
|
-
className="pl-8"
|
|
181
|
-
autoComplete="new-password"
|
|
182
|
-
aria-invalid={!!errors.confirmPassword}
|
|
183
|
-
{...register("confirmPassword", {
|
|
184
|
-
required: "Please confirm your password",
|
|
185
|
-
validate: (value) =>
|
|
186
|
-
value === password || "Passwords do not match",
|
|
187
|
-
})}
|
|
188
|
-
/>
|
|
189
|
-
</div>
|
|
190
|
-
<FieldError>{errors.confirmPassword?.message}</FieldError>
|
|
191
|
-
</FieldContent>
|
|
192
|
-
</Field>
|
|
193
|
-
</FieldGroup>
|
|
194
|
-
|
|
195
|
-
{/* Error Message */}
|
|
196
|
-
{error && (
|
|
197
|
-
<div className="bg-destructive/10 text-destructive rounded-md p-3 text-xs">
|
|
198
|
-
{error}
|
|
199
|
-
</div>
|
|
200
|
-
)}
|
|
201
|
-
|
|
202
|
-
{/* Submit Button */}
|
|
203
|
-
<Button
|
|
204
|
-
type="submit"
|
|
205
|
-
className="w-full"
|
|
206
|
-
size="lg"
|
|
207
|
-
disabled={isSubmitting}
|
|
208
|
-
>
|
|
209
|
-
{isSubmitting ? (
|
|
210
|
-
<>
|
|
211
|
-
<SpinnerGap className="animate-spin" weight="bold" />
|
|
212
|
-
Resetting...
|
|
213
|
-
</>
|
|
214
|
-
) : (
|
|
215
|
-
"Reset password"
|
|
216
|
-
)}
|
|
217
|
-
</Button>
|
|
218
|
-
|
|
219
|
-
{/* Back to Login Link */}
|
|
220
|
-
<p className="text-muted-foreground text-center text-xs">
|
|
221
|
-
Remember your password?{" "}
|
|
222
|
-
<button
|
|
223
|
-
type="button"
|
|
224
|
-
onClick={onBackToLoginClick}
|
|
225
|
-
className="text-primary hover:underline"
|
|
226
|
-
>
|
|
227
|
-
Back to login
|
|
228
|
-
</button>
|
|
229
|
-
</p>
|
|
230
|
-
</form>
|
|
231
|
-
);
|
|
232
|
-
}
|