create-croissant 0.1.54 → 0.1.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/template/apps/desktop/src/renderer/src/components/app-sidebar.tsx +1 -5
- package/template/apps/desktop/src/renderer/src/components/login-form.tsx +11 -144
- package/template/apps/desktop/src/renderer/src/routeTree.gen.ts +0 -21
- package/template/apps/desktop/src/renderer/src/components/signup-form.tsx +0 -205
- package/template/apps/desktop/src/renderer/src/routes/_public/signup.tsx +0 -16
package/package.json
CHANGED
|
@@ -58,10 +58,6 @@ export const publicNavItems = [
|
|
|
58
58
|
title: "Login",
|
|
59
59
|
url: "/login",
|
|
60
60
|
},
|
|
61
|
-
{
|
|
62
|
-
title: "Sign Up",
|
|
63
|
-
url: "/signup",
|
|
64
|
-
},
|
|
65
61
|
],
|
|
66
62
|
},
|
|
67
63
|
{
|
|
@@ -157,7 +153,7 @@ export function AppSidebar({ items = authNavItems, ...props }: AppSidebarProps)
|
|
|
157
153
|
<Settings className="h-4 w-4" />
|
|
158
154
|
</SidebarMenuButton>
|
|
159
155
|
<SidebarMenuButton
|
|
160
|
-
onClick={async (e) => {
|
|
156
|
+
onClick={async (e: React.MouseEvent) => {
|
|
161
157
|
e.preventDefault();
|
|
162
158
|
e.stopPropagation();
|
|
163
159
|
await authClient.signOut();
|
|
@@ -7,29 +7,11 @@ import {
|
|
|
7
7
|
CardHeader,
|
|
8
8
|
CardTitle,
|
|
9
9
|
} from "@workspace/ui/components/card";
|
|
10
|
-
import {
|
|
11
|
-
Field,
|
|
12
|
-
FieldDescription,
|
|
13
|
-
FieldError,
|
|
14
|
-
FieldGroup,
|
|
15
|
-
FieldLabel,
|
|
16
|
-
} from "@workspace/ui/components/field";
|
|
17
|
-
import { Input } from "@workspace/ui/components/input";
|
|
18
10
|
import { useEffect, useState } from "react";
|
|
19
|
-
import {
|
|
20
|
-
import { useForm } from "@tanstack/react-form";
|
|
21
|
-
import { z } from "zod";
|
|
22
|
-
|
|
23
|
-
import { authClient } from "@renderer/lib/auth-client";
|
|
24
|
-
|
|
25
|
-
const loginSchema = z.object({
|
|
26
|
-
email: z.string().email("Invalid email address"),
|
|
27
|
-
password: z.string().min(8, "Password must be at least 8 characters"),
|
|
28
|
-
});
|
|
11
|
+
import { useNavigate } from "@tanstack/react-router";
|
|
29
12
|
|
|
30
13
|
export function LoginForm({ className, ...props }: React.ComponentProps<"div">) {
|
|
31
14
|
const [loading, setLoading] = useState(false);
|
|
32
|
-
const [error, setError] = useState<string | null>(null);
|
|
33
15
|
const navigate = useNavigate();
|
|
34
16
|
|
|
35
17
|
useEffect(() => {
|
|
@@ -53,136 +35,21 @@ export function LoginForm({ className, ...props }: React.ComponentProps<"div">)
|
|
|
53
35
|
window.api.openExternal(platformUrl);
|
|
54
36
|
};
|
|
55
37
|
|
|
56
|
-
const form = useForm({
|
|
57
|
-
defaultValues: {
|
|
58
|
-
email: "",
|
|
59
|
-
password: "",
|
|
60
|
-
},
|
|
61
|
-
validators: {
|
|
62
|
-
onChange: loginSchema,
|
|
63
|
-
},
|
|
64
|
-
onSubmit: async ({ value }) => {
|
|
65
|
-
setLoading(true);
|
|
66
|
-
setError(null);
|
|
67
|
-
const { error: signInError } = await authClient.signIn.email({
|
|
68
|
-
email: value.email,
|
|
69
|
-
password: value.password,
|
|
70
|
-
});
|
|
71
|
-
if (signInError) {
|
|
72
|
-
setError(signInError.message || "Failed to sign in");
|
|
73
|
-
} else {
|
|
74
|
-
navigate({ to: "/dashboard" });
|
|
75
|
-
}
|
|
76
|
-
setLoading(false);
|
|
77
|
-
},
|
|
78
|
-
});
|
|
79
|
-
|
|
80
38
|
return (
|
|
81
39
|
<div className={cn("flex flex-col gap-6", className)} {...props}>
|
|
82
40
|
<Card>
|
|
83
|
-
<CardHeader>
|
|
84
|
-
<CardTitle>Login to your account</CardTitle>
|
|
85
|
-
<CardDescription>
|
|
41
|
+
<CardHeader className="text-center">
|
|
42
|
+
<CardTitle className="text-xl">Login to your account</CardTitle>
|
|
43
|
+
<CardDescription>
|
|
44
|
+
Click the button below to login via your web browser.
|
|
45
|
+
</CardDescription>
|
|
86
46
|
</CardHeader>
|
|
87
47
|
<CardContent>
|
|
88
|
-
<
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}}
|
|
94
|
-
>
|
|
95
|
-
<FieldGroup>
|
|
96
|
-
{error && <div className="rounded bg-red-100 p-2 text-sm text-red-600">{error}</div>}
|
|
97
|
-
<form.Field
|
|
98
|
-
name="email"
|
|
99
|
-
children={(field) => {
|
|
100
|
-
const isInvalid =
|
|
101
|
-
field.state.meta.isTouched && field.state.meta.errors.length > 0;
|
|
102
|
-
return (
|
|
103
|
-
<Field data-invalid={isInvalid}>
|
|
104
|
-
<FieldLabel htmlFor={field.name}>Email</FieldLabel>
|
|
105
|
-
<Input
|
|
106
|
-
id={field.name}
|
|
107
|
-
name={field.name}
|
|
108
|
-
type="email"
|
|
109
|
-
placeholder="m@example.com"
|
|
110
|
-
value={field.state.value}
|
|
111
|
-
onBlur={field.handleBlur}
|
|
112
|
-
onChange={(e) => field.handleChange(e.target.value)}
|
|
113
|
-
required
|
|
114
|
-
/>
|
|
115
|
-
{isInvalid && <FieldError errors={field.state.meta.errors} />}
|
|
116
|
-
</Field>
|
|
117
|
-
);
|
|
118
|
-
}}
|
|
119
|
-
/>
|
|
120
|
-
<form.Field
|
|
121
|
-
name="password"
|
|
122
|
-
children={(field) => {
|
|
123
|
-
const isInvalid =
|
|
124
|
-
field.state.meta.isTouched && field.state.meta.errors.length > 0;
|
|
125
|
-
return (
|
|
126
|
-
<Field data-invalid={isInvalid}>
|
|
127
|
-
<div className="flex items-center">
|
|
128
|
-
<FieldLabel htmlFor={field.name}>Password</FieldLabel>
|
|
129
|
-
<a
|
|
130
|
-
href="#"
|
|
131
|
-
className="ml-auto inline-block text-sm underline-offset-4 hover:underline"
|
|
132
|
-
>
|
|
133
|
-
Forgot your password?
|
|
134
|
-
</a>
|
|
135
|
-
</div>
|
|
136
|
-
<Input
|
|
137
|
-
id={field.name}
|
|
138
|
-
name={field.name}
|
|
139
|
-
type="password"
|
|
140
|
-
value={field.state.value}
|
|
141
|
-
onBlur={field.handleBlur}
|
|
142
|
-
onChange={(e) => field.handleChange(e.target.value)}
|
|
143
|
-
required
|
|
144
|
-
/>
|
|
145
|
-
{isInvalid && <FieldError errors={field.state.meta.errors} />}
|
|
146
|
-
</Field>
|
|
147
|
-
);
|
|
148
|
-
}}
|
|
149
|
-
/>
|
|
150
|
-
<Field>
|
|
151
|
-
<form.Subscribe
|
|
152
|
-
selector={(state) => ({
|
|
153
|
-
canSubmit: state.canSubmit,
|
|
154
|
-
isSubmitting: state.isSubmitting,
|
|
155
|
-
})}
|
|
156
|
-
>
|
|
157
|
-
{(state: { canSubmit: boolean; isSubmitting: boolean }) => (
|
|
158
|
-
<Button type="submit" disabled={!state.canSubmit || state.isSubmitting || loading}>
|
|
159
|
-
{state.isSubmitting || loading ? "Logging in..." : "Login"}
|
|
160
|
-
</Button>
|
|
161
|
-
)}
|
|
162
|
-
</form.Subscribe>
|
|
163
|
-
<div className="relative">
|
|
164
|
-
<div className="absolute inset-0 flex items-center">
|
|
165
|
-
<span className="w-full border-t" />
|
|
166
|
-
</div>
|
|
167
|
-
<div className="relative flex justify-center text-xs uppercase">
|
|
168
|
-
<span className="bg-background px-2 text-muted-foreground">Or continue with</span>
|
|
169
|
-
</div>
|
|
170
|
-
</div>
|
|
171
|
-
<Button variant="outline" type="button" onClick={handleBrowserLogin} disabled={loading}>
|
|
172
|
-
Login with Browser
|
|
173
|
-
</Button>
|
|
174
|
-
<Button variant="outline" type="button" disabled={loading}>
|
|
175
|
-
Login with Google
|
|
176
|
-
</Button>
|
|
177
|
-
<FieldDescription className="text-center">
|
|
178
|
-
Don't have an account?{" "}
|
|
179
|
-
<Link to="/signup" className="underline">
|
|
180
|
-
Sign up
|
|
181
|
-
</Link>
|
|
182
|
-
</FieldDescription>
|
|
183
|
-
</Field>
|
|
184
|
-
</FieldGroup>
|
|
185
|
-
</form>
|
|
48
|
+
<div className="flex flex-col gap-4">
|
|
49
|
+
<Button size="lg" className="w-full" onClick={handleBrowserLogin} disabled={loading}>
|
|
50
|
+
{loading ? "Authenticating..." : "Login from the web"}
|
|
51
|
+
</Button>
|
|
52
|
+
</div>
|
|
186
53
|
</CardContent>
|
|
187
54
|
</Card>
|
|
188
55
|
</div>
|
|
@@ -12,7 +12,6 @@ import { Route as rootRouteImport } from './routes/__root'
|
|
|
12
12
|
import { Route as PublicRouteImport } from './routes/_public'
|
|
13
13
|
import { Route as AuthRouteImport } from './routes/_auth'
|
|
14
14
|
import { Route as PublicIndexRouteImport } from './routes/_public/index'
|
|
15
|
-
import { Route as PublicSignupRouteImport } from './routes/_public/signup'
|
|
16
15
|
import { Route as PublicLoginRouteImport } from './routes/_public/login'
|
|
17
16
|
import { Route as AuthDashboardRouteImport } from './routes/_auth/dashboard'
|
|
18
17
|
import { Route as AuthAccountRouteImport } from './routes/_auth/account'
|
|
@@ -32,11 +31,6 @@ const PublicIndexRoute = PublicIndexRouteImport.update({
|
|
|
32
31
|
path: '/',
|
|
33
32
|
getParentRoute: () => PublicRoute,
|
|
34
33
|
} as any)
|
|
35
|
-
const PublicSignupRoute = PublicSignupRouteImport.update({
|
|
36
|
-
id: '/signup',
|
|
37
|
-
path: '/signup',
|
|
38
|
-
getParentRoute: () => PublicRoute,
|
|
39
|
-
} as any)
|
|
40
34
|
const PublicLoginRoute = PublicLoginRouteImport.update({
|
|
41
35
|
id: '/login',
|
|
42
36
|
path: '/login',
|
|
@@ -70,7 +64,6 @@ export interface FileRoutesByFullPath {
|
|
|
70
64
|
'/account': typeof AuthAccountRoute
|
|
71
65
|
'/dashboard': typeof AuthDashboardRoute
|
|
72
66
|
'/login': typeof PublicLoginRoute
|
|
73
|
-
'/signup': typeof PublicSignupRoute
|
|
74
67
|
'/examples/client-orpc-auth': typeof AuthExamplesClientOrpcAuthRoute
|
|
75
68
|
'/examples/client-orpc': typeof PublicExamplesClientOrpcRoute
|
|
76
69
|
}
|
|
@@ -79,7 +72,6 @@ export interface FileRoutesByTo {
|
|
|
79
72
|
'/account': typeof AuthAccountRoute
|
|
80
73
|
'/dashboard': typeof AuthDashboardRoute
|
|
81
74
|
'/login': typeof PublicLoginRoute
|
|
82
|
-
'/signup': typeof PublicSignupRoute
|
|
83
75
|
'/examples/client-orpc-auth': typeof AuthExamplesClientOrpcAuthRoute
|
|
84
76
|
'/examples/client-orpc': typeof PublicExamplesClientOrpcRoute
|
|
85
77
|
}
|
|
@@ -90,7 +82,6 @@ export interface FileRoutesById {
|
|
|
90
82
|
'/_auth/account': typeof AuthAccountRoute
|
|
91
83
|
'/_auth/dashboard': typeof AuthDashboardRoute
|
|
92
84
|
'/_public/login': typeof PublicLoginRoute
|
|
93
|
-
'/_public/signup': typeof PublicSignupRoute
|
|
94
85
|
'/_public/': typeof PublicIndexRoute
|
|
95
86
|
'/_auth/examples/client-orpc-auth': typeof AuthExamplesClientOrpcAuthRoute
|
|
96
87
|
'/_public/examples/client-orpc': typeof PublicExamplesClientOrpcRoute
|
|
@@ -102,7 +93,6 @@ export interface FileRouteTypes {
|
|
|
102
93
|
| '/account'
|
|
103
94
|
| '/dashboard'
|
|
104
95
|
| '/login'
|
|
105
|
-
| '/signup'
|
|
106
96
|
| '/examples/client-orpc-auth'
|
|
107
97
|
| '/examples/client-orpc'
|
|
108
98
|
fileRoutesByTo: FileRoutesByTo
|
|
@@ -111,7 +101,6 @@ export interface FileRouteTypes {
|
|
|
111
101
|
| '/account'
|
|
112
102
|
| '/dashboard'
|
|
113
103
|
| '/login'
|
|
114
|
-
| '/signup'
|
|
115
104
|
| '/examples/client-orpc-auth'
|
|
116
105
|
| '/examples/client-orpc'
|
|
117
106
|
id:
|
|
@@ -121,7 +110,6 @@ export interface FileRouteTypes {
|
|
|
121
110
|
| '/_auth/account'
|
|
122
111
|
| '/_auth/dashboard'
|
|
123
112
|
| '/_public/login'
|
|
124
|
-
| '/_public/signup'
|
|
125
113
|
| '/_public/'
|
|
126
114
|
| '/_auth/examples/client-orpc-auth'
|
|
127
115
|
| '/_public/examples/client-orpc'
|
|
@@ -155,13 +143,6 @@ declare module '@tanstack/react-router' {
|
|
|
155
143
|
preLoaderRoute: typeof PublicIndexRouteImport
|
|
156
144
|
parentRoute: typeof PublicRoute
|
|
157
145
|
}
|
|
158
|
-
'/_public/signup': {
|
|
159
|
-
id: '/_public/signup'
|
|
160
|
-
path: '/signup'
|
|
161
|
-
fullPath: '/signup'
|
|
162
|
-
preLoaderRoute: typeof PublicSignupRouteImport
|
|
163
|
-
parentRoute: typeof PublicRoute
|
|
164
|
-
}
|
|
165
146
|
'/_public/login': {
|
|
166
147
|
id: '/_public/login'
|
|
167
148
|
path: '/login'
|
|
@@ -216,14 +197,12 @@ const AuthRouteWithChildren = AuthRoute._addFileChildren(AuthRouteChildren)
|
|
|
216
197
|
|
|
217
198
|
interface PublicRouteChildren {
|
|
218
199
|
PublicLoginRoute: typeof PublicLoginRoute
|
|
219
|
-
PublicSignupRoute: typeof PublicSignupRoute
|
|
220
200
|
PublicIndexRoute: typeof PublicIndexRoute
|
|
221
201
|
PublicExamplesClientOrpcRoute: typeof PublicExamplesClientOrpcRoute
|
|
222
202
|
}
|
|
223
203
|
|
|
224
204
|
const PublicRouteChildren: PublicRouteChildren = {
|
|
225
205
|
PublicLoginRoute: PublicLoginRoute,
|
|
226
|
-
PublicSignupRoute: PublicSignupRoute,
|
|
227
206
|
PublicIndexRoute: PublicIndexRoute,
|
|
228
207
|
PublicExamplesClientOrpcRoute: PublicExamplesClientOrpcRoute,
|
|
229
208
|
}
|
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
import { Button } from "@workspace/ui/components/button";
|
|
2
|
-
import {
|
|
3
|
-
Card,
|
|
4
|
-
CardContent,
|
|
5
|
-
CardDescription,
|
|
6
|
-
CardHeader,
|
|
7
|
-
CardTitle,
|
|
8
|
-
} from "@workspace/ui/components/card";
|
|
9
|
-
import {
|
|
10
|
-
Field,
|
|
11
|
-
FieldDescription,
|
|
12
|
-
FieldError,
|
|
13
|
-
FieldGroup,
|
|
14
|
-
FieldLabel,
|
|
15
|
-
} from "@workspace/ui/components/field";
|
|
16
|
-
import { Input } from "@workspace/ui/components/input";
|
|
17
|
-
import { useState } from "react";
|
|
18
|
-
import { Link, useNavigate } from "@tanstack/react-router";
|
|
19
|
-
import { useForm } from "@tanstack/react-form";
|
|
20
|
-
import { z } from "zod";
|
|
21
|
-
import { authClient } from "@renderer/lib/auth-client";
|
|
22
|
-
|
|
23
|
-
const signupSchema = z
|
|
24
|
-
.object({
|
|
25
|
-
name: z.string().min(1, "Name is required"),
|
|
26
|
-
email: z.string().email("Invalid email address"),
|
|
27
|
-
password: z.string().min(8, "Password must be at least 8 characters"),
|
|
28
|
-
confirmPassword: z.string().min(1, "Confirm password is required"),
|
|
29
|
-
})
|
|
30
|
-
.refine((data) => data.password === data.confirmPassword, {
|
|
31
|
-
message: "Passwords do not match",
|
|
32
|
-
path: ["confirmPassword"],
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
export function SignupForm({ ...props }: React.ComponentProps<typeof Card>) {
|
|
36
|
-
const [loading, setLoading] = useState(false);
|
|
37
|
-
const [error, setError] = useState<string | null>(null);
|
|
38
|
-
const navigate = useNavigate();
|
|
39
|
-
|
|
40
|
-
const form = useForm({
|
|
41
|
-
defaultValues: {
|
|
42
|
-
name: "",
|
|
43
|
-
email: "",
|
|
44
|
-
password: "",
|
|
45
|
-
confirmPassword: "",
|
|
46
|
-
},
|
|
47
|
-
validators: {
|
|
48
|
-
onChange: signupSchema,
|
|
49
|
-
},
|
|
50
|
-
onSubmit: async ({ value }) => {
|
|
51
|
-
setLoading(true);
|
|
52
|
-
setError(null);
|
|
53
|
-
const { error: signUpError } = await authClient.signUp.email({
|
|
54
|
-
email: value.email,
|
|
55
|
-
password: value.password,
|
|
56
|
-
name: value.name,
|
|
57
|
-
});
|
|
58
|
-
if (signUpError) {
|
|
59
|
-
setError(signUpError.message || "Failed to sign up");
|
|
60
|
-
} else {
|
|
61
|
-
navigate({ to: "/dashboard" });
|
|
62
|
-
}
|
|
63
|
-
setLoading(false);
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
return (
|
|
68
|
-
<Card {...props}>
|
|
69
|
-
<CardHeader>
|
|
70
|
-
<CardTitle>Create an account</CardTitle>
|
|
71
|
-
<CardDescription>Enter your information below to create your account</CardDescription>
|
|
72
|
-
</CardHeader>
|
|
73
|
-
<CardContent>
|
|
74
|
-
<form
|
|
75
|
-
onSubmit={(e) => {
|
|
76
|
-
e.preventDefault();
|
|
77
|
-
e.stopPropagation();
|
|
78
|
-
form.handleSubmit();
|
|
79
|
-
}}
|
|
80
|
-
>
|
|
81
|
-
<FieldGroup>
|
|
82
|
-
{error && <div className="rounded bg-red-100 p-2 text-sm text-red-600">{error}</div>}
|
|
83
|
-
<form.Field
|
|
84
|
-
name="name"
|
|
85
|
-
children={(field) => {
|
|
86
|
-
const isInvalid = field.state.meta.isTouched && field.state.meta.errors.length > 0;
|
|
87
|
-
return (
|
|
88
|
-
<Field data-invalid={isInvalid}>
|
|
89
|
-
<FieldLabel htmlFor={field.name}>Full Name</FieldLabel>
|
|
90
|
-
<Input
|
|
91
|
-
id={field.name}
|
|
92
|
-
name={field.name}
|
|
93
|
-
type="text"
|
|
94
|
-
placeholder="John Doe"
|
|
95
|
-
value={field.state.value}
|
|
96
|
-
onBlur={field.handleBlur}
|
|
97
|
-
onChange={(e) => field.handleChange(e.target.value)}
|
|
98
|
-
required
|
|
99
|
-
/>
|
|
100
|
-
{isInvalid && <FieldError errors={field.state.meta.errors} />}
|
|
101
|
-
</Field>
|
|
102
|
-
);
|
|
103
|
-
}}
|
|
104
|
-
/>
|
|
105
|
-
<form.Field
|
|
106
|
-
name="email"
|
|
107
|
-
children={(field) => {
|
|
108
|
-
const isInvalid = field.state.meta.isTouched && field.state.meta.errors.length > 0;
|
|
109
|
-
return (
|
|
110
|
-
<Field data-invalid={isInvalid}>
|
|
111
|
-
<FieldLabel htmlFor={field.name}>Email</FieldLabel>
|
|
112
|
-
<Input
|
|
113
|
-
id={field.name}
|
|
114
|
-
name={field.name}
|
|
115
|
-
type="email"
|
|
116
|
-
placeholder="m@example.com"
|
|
117
|
-
value={field.state.value}
|
|
118
|
-
onBlur={field.handleBlur}
|
|
119
|
-
onChange={(e) => field.handleChange(e.target.value)}
|
|
120
|
-
required
|
|
121
|
-
/>
|
|
122
|
-
<FieldDescription>
|
|
123
|
-
We'll use this to contact you. We will not share your email with anyone
|
|
124
|
-
else.
|
|
125
|
-
</FieldDescription>
|
|
126
|
-
{isInvalid && <FieldError errors={field.state.meta.errors} />}
|
|
127
|
-
</Field>
|
|
128
|
-
);
|
|
129
|
-
}}
|
|
130
|
-
/>
|
|
131
|
-
<form.Field
|
|
132
|
-
name="password"
|
|
133
|
-
children={(field) => {
|
|
134
|
-
const isInvalid = field.state.meta.isTouched && field.state.meta.errors.length > 0;
|
|
135
|
-
return (
|
|
136
|
-
<Field data-invalid={isInvalid}>
|
|
137
|
-
<FieldLabel htmlFor={field.name}>Password</FieldLabel>
|
|
138
|
-
<Input
|
|
139
|
-
id={field.name}
|
|
140
|
-
name={field.name}
|
|
141
|
-
type="password"
|
|
142
|
-
value={field.state.value}
|
|
143
|
-
onBlur={field.handleBlur}
|
|
144
|
-
onChange={(e) => field.handleChange(e.target.value)}
|
|
145
|
-
required
|
|
146
|
-
/>
|
|
147
|
-
<FieldDescription>Must be at least 8 characters long.</FieldDescription>
|
|
148
|
-
{isInvalid && <FieldError errors={field.state.meta.errors} />}
|
|
149
|
-
</Field>
|
|
150
|
-
);
|
|
151
|
-
}}
|
|
152
|
-
/>
|
|
153
|
-
<form.Field
|
|
154
|
-
name="confirmPassword"
|
|
155
|
-
children={(field) => {
|
|
156
|
-
const isInvalid = field.state.meta.isTouched && field.state.meta.errors.length > 0;
|
|
157
|
-
return (
|
|
158
|
-
<Field data-invalid={isInvalid}>
|
|
159
|
-
<FieldLabel htmlFor={field.name}>Confirm Password</FieldLabel>
|
|
160
|
-
<Input
|
|
161
|
-
id={field.name}
|
|
162
|
-
name={field.name}
|
|
163
|
-
type="password"
|
|
164
|
-
value={field.state.value}
|
|
165
|
-
onBlur={field.handleBlur}
|
|
166
|
-
onChange={(e) => field.handleChange(e.target.value)}
|
|
167
|
-
required
|
|
168
|
-
/>
|
|
169
|
-
<FieldDescription>Please confirm your password.</FieldDescription>
|
|
170
|
-
{isInvalid && <FieldError errors={field.state.meta.errors} />}
|
|
171
|
-
</Field>
|
|
172
|
-
);
|
|
173
|
-
}}
|
|
174
|
-
/>
|
|
175
|
-
<FieldGroup>
|
|
176
|
-
<Field>
|
|
177
|
-
<form.Subscribe
|
|
178
|
-
selector={(state) => ({
|
|
179
|
-
canSubmit: state.canSubmit,
|
|
180
|
-
isSubmitting: state.isSubmitting,
|
|
181
|
-
})}
|
|
182
|
-
>
|
|
183
|
-
{(state: { canSubmit: boolean; isSubmitting: boolean }) => (
|
|
184
|
-
<Button type="submit" disabled={!state.canSubmit || state.isSubmitting || loading}>
|
|
185
|
-
{state.isSubmitting || loading ? "Creating..." : "Create Account"}
|
|
186
|
-
</Button>
|
|
187
|
-
)}
|
|
188
|
-
</form.Subscribe>
|
|
189
|
-
<Button variant="outline" type="button" disabled={loading}>
|
|
190
|
-
Sign up with Google
|
|
191
|
-
</Button>
|
|
192
|
-
<FieldDescription className="px-6 text-center">
|
|
193
|
-
Already have an account?{" "}
|
|
194
|
-
<Link to="/login" className="underline">
|
|
195
|
-
Sign in
|
|
196
|
-
</Link>
|
|
197
|
-
</FieldDescription>
|
|
198
|
-
</Field>
|
|
199
|
-
</FieldGroup>
|
|
200
|
-
</FieldGroup>
|
|
201
|
-
</form>
|
|
202
|
-
</CardContent>
|
|
203
|
-
</Card>
|
|
204
|
-
);
|
|
205
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { createFileRoute } from "@tanstack/react-router";
|
|
2
|
-
import { SignupForm } from "@renderer/components/signup-form";
|
|
3
|
-
|
|
4
|
-
export const Route = createFileRoute("/_public/signup")({
|
|
5
|
-
component: Signup,
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
function Signup() {
|
|
9
|
-
return (
|
|
10
|
-
<div className="flex min-h-svh items-center justify-center p-6">
|
|
11
|
-
<div className="w-full max-w-sm">
|
|
12
|
-
<SignupForm />
|
|
13
|
-
</div>
|
|
14
|
-
</div>
|
|
15
|
-
);
|
|
16
|
-
}
|