Skip to content

Commit dfe8a5f

Browse files
committed
chore: Extract common cloud sign-in hook
https://harperdb.atlassian.net/browse/STUDIO-588
1 parent fb8c874 commit dfe8a5f

File tree

7 files changed

+89
-88
lines changed

7 files changed

+89
-88
lines changed

src/features/auth/ClusterInstanceSignIn.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { getClusterInfoQueryOptions } from '@/features/cluster/queries/getCluste
1515
import { useInstanceLoginMutation } from '@/features/instance/operations/mutations/useInstanceLoginMutation';
1616
import { getInstanceHealthQueryOptions } from '@/features/instance/operations/queries/getInstanceHealth';
1717
import { getInstanceUserInfo } from '@/features/instance/operations/queries/getInstanceUserInfo';
18-
import { SignInSchema } from '@/features/instance/operations/schemas/signInSchema';
18+
import { UsernameSignInSchema } from '@/features/instance/operations/schemas/signInSchema';
1919
import { CrossLocalhostIssueType, detectCrossLocalhostUrls } from '@/lib/urls/detectCrossLocalhostUrls';
2020
import { getOperationsUrlForCluster } from '@/lib/urls/getOperationsUrlForCluster';
2121
import { getOperationsUrlForInstance } from '@/lib/urls/getOperationsUrlForInstance';
@@ -67,7 +67,7 @@ export function ClusterInstanceSignIn() {
6767
);
6868

6969
const methods = useForm({
70-
resolver: zodResolver(SignInSchema),
70+
resolver: zodResolver(UsernameSignInSchema),
7171
defaultValues: {
7272
username: '',
7373
password: '',
@@ -81,7 +81,7 @@ export function ClusterInstanceSignIn() {
8181

8282
const { mutate: submitInstanceLogin, isPending } = useInstanceLoginMutation();
8383

84-
const submitForm = useCallback(async (formData: z.infer<typeof SignInSchema>) => {
84+
const submitForm = useCallback(async (formData: z.infer<typeof UsernameSignInSchema>) => {
8585
submitInstanceLogin(
8686
{
8787
...formData,

src/features/auth/SignIn.tsx

Lines changed: 7 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,71 +6,26 @@ import { FormItem } from '@/components/ui/form/FormItem';
66
import { FormLabel } from '@/components/ui/form/FormLabel';
77
import { FormMessage } from '@/components/ui/form/FormMessage';
88
import { Input } from '@/components/ui/input';
9-
import { loginSuccessDatadogAction } from '@/integrations/datadog/datadog';
10-
import { reoClient } from '@/integrations/reo/reo';
11-
import { parseCompanyFromEmail } from '@/lib/string/parseCompanyFromEmail';
12-
import { getDefaultSignedInCloudRouteForUser } from '@/lib/urls/getDefaultSignedInCloudRouteForUser';
13-
import { zodRequireEmail } from '@/lib/zod/email';
14-
import { zodRequirePassword } from '@/lib/zod/password';
9+
import { EmailSignInSchema } from '@/features/instance/operations/schemas/signInSchema';
1510
import { zodResolver } from '@hookform/resolvers/zod';
16-
import { useQueryClient } from '@tanstack/react-query';
17-
import { Link, useNavigate, useRouter, useSearch } from '@tanstack/react-router';
18-
import { useEffect } from 'react';
11+
import { Link, useSearch } from '@tanstack/react-router';
1912
import { useForm } from 'react-hook-form';
20-
import { z } from 'zod';
21-
import { useLoginMutation } from './hooks/useSignIn';
22-
import { currentUserQueryKey } from './queries/getCurrentUser';
23-
import { authStore, OverallAppSignIn } from './store/authStore';
24-
25-
const SignInSchema = z.object({
26-
email: zodRequireEmail,
27-
password: zodRequirePassword,
28-
});
13+
import { useCloudSignIn } from './hooks/useCloudSignIn';
2914

3015
export function SignIn() {
31-
const navigate = useNavigate();
3216
const { me: formPersistenceEmail } = useSearch({ strict: false });
33-
const router = useRouter();
34-
const queryClient = useQueryClient();
35-
const { redirect } = useSearch({ strict: false });
3617

3718
const methods = useForm({
38-
resolver: zodResolver(SignInSchema),
19+
resolver: zodResolver(EmailSignInSchema),
3920
defaultValues: {
4021
email: formPersistenceEmail || '',
4122
password: '',
4223
},
4324
});
44-
25+
const { handleSubmit, control } = methods;
4526
const email = methods.watch('email');
46-
const { handleSubmit, control, setFocus } = methods;
47-
48-
useEffect(() => {
49-
setFocus('email');
50-
}, [setFocus]);
51-
52-
const { mutate: submitLoginData, isPending } = useLoginMutation();
53-
54-
const submitForm = (formData: z.infer<typeof SignInSchema>) => {
55-
submitLoginData(formData, {
56-
onSuccess: async (data) => {
57-
authStore.setUserForEntity(OverallAppSignIn, data);
58-
const defaultCloudRoute = getDefaultSignedInCloudRouteForUser(data);
59-
60-
loginSuccessDatadogAction(data);
6127

62-
const company = parseCompanyFromEmail(data.email);
63-
reoClient?.identify?.({
64-
username: data.email,
65-
type: 'email',
66-
...(company ? { company } : {}),
67-
});
68-
await queryClient.invalidateQueries({ queryKey: currentUserQueryKey, refetchType: 'none' });
69-
void router.invalidate();
70-
await navigate({ to: redirect?.startsWith('/') ? redirect : defaultCloudRoute });
71-
},
72-
});
73-
};
28+
const { submitForm, isPending } = useCloudSignIn();
7429

7530
return (
7631
<div className="text-white w-xs">
@@ -86,6 +41,7 @@ export function SignIn() {
8641
<FormControl>
8742
<Input
8843
type="email"
44+
autoFocus={true}
8945
className="bg-purple-400 border-purple-400 dark:bg-black dark:border-black"
9046
{...field}
9147
/>

src/features/auth/SignUp.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ import { zodRequireEmail } from '@/lib/zod/email';
1212
import { zodRequirePassword } from '@/lib/zod/password';
1313
import { zodResolver } from '@hookform/resolvers/zod';
1414
import { Link, useNavigate, useSearch } from '@tanstack/react-router';
15-
import { useEffect } from 'react';
15+
import { useCallback, useEffect } from 'react';
1616
import { useForm } from 'react-hook-form';
1717
import { z } from 'zod';
1818
import { useSignUpMutation } from './hooks/useSignUp';
1919

20-
const SignInSchema = z.object({
20+
const SignUpSchema = z.object({
2121
email: zodRequireEmail
2222
.max(80, { error: 'Email cannot be longer than 80 characters.' }),
2323
firstname: z
@@ -43,7 +43,7 @@ export function SignUp() {
4343
const navigate = useNavigate();
4444
const { email: searchEmail, me: formPersistenceEmail } = useSearch({ strict: false });
4545
const methods = useForm({
46-
resolver: zodResolver(SignInSchema),
46+
resolver: zodResolver(SignUpSchema),
4747
defaultValues: {
4848
firstname: '',
4949
lastname: '',
@@ -62,7 +62,7 @@ export function SignUp() {
6262

6363
const { mutate: submitSignUpData } = useSignUpMutation();
6464

65-
const submitForm = async (formData: z.infer<typeof SignInSchema>) => {
65+
const submitForm = useCallback(async (formData: z.infer<typeof SignUpSchema>) => {
6666
// eslint-disable-next-line @typescript-eslint/no-unused-vars
6767
const { confirmPassword, ...userData } = formData;
6868
submitSignUpData(userData, {
@@ -78,7 +78,7 @@ export function SignUp() {
7878
void navigate({ to: '/verifying?email=' + encodeURIComponent(userData.email) });
7979
},
8080
});
81-
};
81+
}, [navigate, submitSignUpData]);
8282

8383
return (
8484
<div className="text-white w-xs">
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { apiClient } from '@/config/apiClient';
2+
import { currentUserQueryKey } from '@/features/auth/queries/getCurrentUser';
3+
import { authStore, OverallAppSignIn } from '@/features/auth/store/authStore';
4+
import { EmailSignInSchema } from '@/features/instance/operations/schemas/signInSchema';
5+
import { loginSuccessDatadogAction } from '@/integrations/datadog/datadog';
6+
import { reoClient } from '@/integrations/reo/reo';
7+
import { User } from '@/lib/api.patch';
8+
import { parseCompanyFromEmail } from '@/lib/string/parseCompanyFromEmail';
9+
import { getDefaultSignedInCloudRouteForUser } from '@/lib/urls/getDefaultSignedInCloudRouteForUser';
10+
import { useMutation, useQueryClient } from '@tanstack/react-query';
11+
import { useNavigate, useRouter, useSearch } from '@tanstack/react-router';
12+
import { useCallback } from 'react';
13+
import { z } from 'zod';
14+
15+
export function useCloudSignIn() {
16+
const navigate = useNavigate();
17+
const queryClient = useQueryClient();
18+
const router = useRouter();
19+
const { mutate: submitLoginData, isPending } = useLoginMutation();
20+
const { redirect } = useSearch({ strict: false });
21+
22+
const submitForm = useCallback((formData: z.infer<typeof EmailSignInSchema>) => {
23+
submitLoginData(formData, {
24+
onSuccess: async (data) => {
25+
// TODO: Detect and fallback to session storage and basic auth if necessary.
26+
authStore.setUserForEntity(OverallAppSignIn, data);
27+
const defaultCloudRoute = getDefaultSignedInCloudRouteForUser(data);
28+
29+
loginSuccessDatadogAction(data);
30+
31+
const company = parseCompanyFromEmail(data.email);
32+
reoClient?.identify?.({
33+
username: data.email,
34+
type: 'email',
35+
...(company ? { company } : {}),
36+
});
37+
await queryClient.invalidateQueries({ queryKey: currentUserQueryKey, refetchType: 'none' });
38+
void router.invalidate();
39+
await navigate({ to: redirect?.startsWith('/') ? redirect : defaultCloudRoute });
40+
},
41+
});
42+
}, [navigate, queryClient, redirect, router, submitLoginData]);
43+
return {
44+
isPending,
45+
submitForm,
46+
};
47+
}
48+
49+
function useLoginMutation() {
50+
return useMutation<User, Error, z.infer<typeof EmailSignInSchema>>({
51+
mutationFn: (loginData) => onLoginSubmit(loginData),
52+
});
53+
}
54+
55+
async function onLoginSubmit({ email, password }: z.infer<typeof EmailSignInSchema>) {
56+
// TODO: The OpenAPI request body for this endpoint isn't defined.
57+
const { data } = await apiClient.post('/Login/', {
58+
email,
59+
password,
60+
});
61+
if (data) {
62+
// TODO: The OpenAPI response for this endpoint isn't defined.
63+
return data as unknown as User;
64+
} else {
65+
throw new Error('Something went wrong');
66+
}
67+
}

src/features/auth/hooks/useClusterInstanceSignIn.ts

Whitespace-only changes.

src/features/auth/hooks/useSignIn.ts

Lines changed: 0 additions & 28 deletions
This file was deleted.
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1+
import { zodRequireEmail } from '@/lib/zod/email';
12
import { zodRequirePassword } from '@/lib/zod/password';
23
import { zodRequireUsername } from '@/lib/zod/username';
34
import { z } from 'zod';
45

5-
export const SignInSchema = z.object({
6+
export const UsernameSignInSchema = z.object({
67
username: zodRequireUsername,
78
password: zodRequirePassword,
89
});
10+
11+
export const EmailSignInSchema = z.object({
12+
email: zodRequireEmail,
13+
password: zodRequirePassword,
14+
});

0 commit comments

Comments
 (0)