From 693c569fdfcb062c070a8323e483a7bd56c1eb74 Mon Sep 17 00:00:00 2001 From: Suejung Shin Date: Sun, 22 Dec 2024 16:32:39 -0800 Subject: [PATCH] chore: Migrate onboardUser to TS --- src/services/user/useOnboardUser.ts | 108 +++++++++++++++++++++++++--- 1 file changed, 99 insertions(+), 9 deletions(-) diff --git a/src/services/user/useOnboardUser.ts b/src/services/user/useOnboardUser.ts index 4dfb2c0fab..2a16406d00 100644 --- a/src/services/user/useOnboardUser.ts +++ b/src/services/user/useOnboardUser.ts @@ -2,6 +2,10 @@ import { useMutation, useQueryClient } from '@tanstack/react-query' import { useParams } from 'react-router-dom' import Api from 'shared/api' +import { NetworkErrorObject } from 'shared/api/helpers' +import { z } from 'zod' + +const TOAST_DURATION = 10000 const currentUserFragment = ` fragment CurrentUserFragment on Me { @@ -43,6 +47,59 @@ fragment CurrentUserFragment on Me { } ` +const CurrentUserFragmentSchema = z.object({ + email: z.string(), + privateAccess: z.boolean(), + onboardingCompleted: z.boolean(), + businessEmail: z.string(), + user: z.object({ + name: z.string(), + username: z.string(), + avatarUrl: z.string(), + avatar: z.string(), + student: z.boolean(), + studentCreatedAt: z.string(), + studentUpdatedAt: z.string(), + }), + trackingMetadata: z.object({ + service: z.string(), + ownerid: z.string(), + serviceId: z.string(), + plan: z.string(), + staff: z.boolean(), + hasYaml: z.boolean(), + bot: z.boolean(), + delinquent: z.boolean(), + didTrial: z.boolean(), + planProvider: z.string(), + planUserCount: z.number(), + createdAt: z.string(), + updatedAt: z.string(), + }), +}) + +const ResponseSchema = z.object({ + onboardUser: z + .object({ + error: z + .discriminatedUnion('__typename', [ + z.object({ + __typename: z.literal('UnauthorizedError'), + }), + z.object({ + __typename: z.literal('ValidationError'), + }), + z.object({ + __typename: z.literal('UnauthenticatedError'), + }), + ]) + .nullable(), + me: CurrentUserFragmentSchema.nullable(), + }) + .nullable(), +}) + + interface URLParams { provider: string } @@ -66,9 +123,7 @@ export function useOnboardUser(opts?: Record) { return useMutation({ mutationFn: (input: { formData?: unknown; selectedOrg?: string }) => { - const formData = input.formData - const selectedOrg = input.selectedOrg - + const { formData, selectedOrg } = input return Api.graphqlMutation({ provider, query: mutation, @@ -76,17 +131,52 @@ export function useOnboardUser(opts?: Record) { variables: { input: formData, }, - }).then((res) => ({ - user: res?.data?.onboardUser?.me, - selectedOrg: selectedOrg, + }).then(result => ({ + ...result, + selectedOrg })) }, - onSuccess: (data) => { - const user = data?.user + onSuccess: (data: { data: any; selectedOrg?: string }) => { + const parsedData = ResponseSchema.safeParse(data.data) + if (!parsedData.success) { + return Promise.reject({ + status: 404, + data: {}, + dev: 'useOnboardUser - 404 failed to parse', + } satisfies NetworkErrorObject) + } + + const error = parsedData.data.onboardUser?.error + if (error) { + if ( + error.__typename === 'ValidationError' || + error.__typename === 'UnauthorizedError' || + error.__typename === 'UnauthenticatedError' + ) { + addToast({ + type: 'error', + text: , + disappearAfter: TOAST_DURATION, + }) + } + } else { + addToast({ + type: 'success', + text: 'Okta configuration saved successfully!', + disappearAfter: TOAST_DURATION, + }) + } + + // .then((res) => ({ + // user: res?.data?.onboardUser?.me, + // selectedOrg: selectedOrg, + // })) + + const user = data.data?.user queryClient.setQueryData(['currentUser', provider], () => user) if (user && typeof opts?.onSuccess === 'function') { - opts.onSuccess(data, opts?.data) + opts.onSuccess(data.data, opts?.data) } }, })